diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs
index dbc3d064acc7a0..c2333f3854eedb 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs
@@ -463,7 +463,6 @@ private static void StelemRef_Helper_NoCacheLookup(ref object? element, void* el
WriteBarrier(ref element, obj);
}
-#if FEATURE_ARRAYSTUB_AS_IL
[DebuggerHidden]
private static unsafe void ArrayTypeCheck(object obj, Array array)
{
@@ -493,6 +492,5 @@ private static unsafe void ArrayTypeCheck_Helper(object obj, void* elementType)
ThrowArrayMismatchException();
}
}
-#endif
}
}
diff --git a/src/coreclr/clr.featuredefines.props b/src/coreclr/clr.featuredefines.props
index 7905f8a573d738..82dded497b6f9c 100644
--- a/src/coreclr/clr.featuredefines.props
+++ b/src/coreclr/clr.featuredefines.props
@@ -10,13 +10,11 @@
true
- true
true
true
- true
true
true
true
@@ -32,7 +30,6 @@
- $(DefineConstants);FEATURE_ARRAYSTUB_AS_IL
$(DefineConstants);FEATURE_MULTICASTSTUB_AS_IL
$(DefineConstants);FEATURE_COMWRAPPERS
$(DefineConstants);FEATURE_COMINTEROP
diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake
index 73de2d5bce2579..e376c63f758470 100644
--- a/src/coreclr/clrdefinitions.cmake
+++ b/src/coreclr/clrdefinitions.cmake
@@ -70,11 +70,9 @@ endif(CLR_CMAKE_TARGET_WIN32 AND CLR_CMAKE_TARGET_ARCH_AMD64)
# Features - please keep them alphabetically sorted
if(CLR_CMAKE_TARGET_WIN32)
if(NOT CLR_CMAKE_TARGET_ARCH_I386)
- add_definitions(-DFEATURE_ARRAYSTUB_AS_IL)
add_definitions(-DFEATURE_MULTICASTSTUB_AS_IL)
endif()
else(CLR_CMAKE_TARGET_WIN32)
- add_definitions(-DFEATURE_ARRAYSTUB_AS_IL)
add_definitions(-DFEATURE_MULTICASTSTUB_AS_IL)
endif(CLR_CMAKE_TARGET_WIN32)
diff --git a/src/coreclr/vm/.vscode/c_cpp_properties.json b/src/coreclr/vm/.vscode/c_cpp_properties.json
index ae1a019f9c05f7..30f8ba3e8f5c44 100644
--- a/src/coreclr/vm/.vscode/c_cpp_properties.json
+++ b/src/coreclr/vm/.vscode/c_cpp_properties.json
@@ -41,7 +41,6 @@
"TARGET_64BIT=1",
"DEBUGGING_SUPPORTED",
"FEATURE_METADATA_UPDATER",
- "FEATURE_ARRAYSTUB_AS_IL",
"FEATURE_BASICFREEZE",
"FEATURE_CODE_VERSIONING",
"FEATURE_COLLECTIBLE_TYPES",
diff --git a/src/coreclr/vm/amd64/AsmHelpers.asm b/src/coreclr/vm/amd64/AsmHelpers.asm
index 3fb2ca02e15a8f..39bee849fa19e2 100644
--- a/src/coreclr/vm/amd64/AsmHelpers.asm
+++ b/src/coreclr/vm/amd64/AsmHelpers.asm
@@ -18,74 +18,6 @@ extern DebugCheckStubUnwindInfoWorker:proc
endif
-GenerateArrayOpStubExceptionCase macro ErrorCaseName, ExceptionName
-
-NESTED_ENTRY ErrorCaseName&_RSIRDI_ScratchArea, _TEXT
-
- ; account for scratch area, rsi, rdi already on the stack
- .allocstack 38h
- END_PROLOGUE
-
- mov rcx, CORINFO_&ExceptionName&_ASM
-
- ; begin epilogue
-
- add rsp, 28h ; pop callee scratch area
- pop rdi
- pop rsi
- jmp JIT_InternalThrow
-
-NESTED_END ErrorCaseName&_RSIRDI_ScratchArea, _TEXT
-
-NESTED_ENTRY ErrorCaseName&_ScratchArea, _TEXT
-
- ; account for scratch area already on the stack
- .allocstack 28h
- END_PROLOGUE
-
- mov rcx, CORINFO_&ExceptionName&_ASM
-
- ; begin epilogue
-
- add rsp, 28h ; pop callee scratch area
- jmp JIT_InternalThrow
-
-NESTED_END ErrorCaseName&_ScratchArea, _TEXT
-
-NESTED_ENTRY ErrorCaseName&_RSIRDI, _TEXT
-
- ; account for rsi, rdi already on the stack
- .allocstack 10h
- END_PROLOGUE
-
- mov rcx, CORINFO_&ExceptionName&_ASM
-
- ; begin epilogue
-
- pop rdi
- pop rsi
- jmp JIT_InternalThrow
-
-NESTED_END ErrorCaseName&_RSIRDI, _TEXT
-
-LEAF_ENTRY ErrorCaseName, _TEXT
-
- mov rcx, CORINFO_&ExceptionName&_ASM
-
- ; begin epilogue
-
- jmp JIT_InternalThrow
-
-LEAF_END ErrorCaseName, _TEXT
-
- endm
-
-
-GenerateArrayOpStubExceptionCase ArrayOpStubNullException, NullReferenceException
-GenerateArrayOpStubExceptionCase ArrayOpStubRangeException, IndexOutOfRangeException
-GenerateArrayOpStubExceptionCase ArrayOpStubTypeMismatchException, ArrayTypeMismatchException
-
-
; EXTERN_C int __fastcall HelperMethodFrameRestoreState(
; INDEBUG_COMMA(HelperMethodFrame *pFrame)
; MachState *pState
diff --git a/src/coreclr/vm/amd64/asmconstants.h b/src/coreclr/vm/amd64/asmconstants.h
index 89e2039888d0ce..1f44fca2719f9e 100644
--- a/src/coreclr/vm/amd64/asmconstants.h
+++ b/src/coreclr/vm/amd64/asmconstants.h
@@ -208,22 +208,10 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__DynamicStaticsInfo__m_pGCStatics
ASMCONSTANTS_C_ASSERT( CORINFO_NullReferenceException_ASM
== CORINFO_NullReferenceException);
-#define CORINFO_InvalidCastException_ASM 2
-ASMCONSTANTS_C_ASSERT( CORINFO_InvalidCastException_ASM
- == CORINFO_InvalidCastException);
-
#define CORINFO_IndexOutOfRangeException_ASM 3
ASMCONSTANTS_C_ASSERT( CORINFO_IndexOutOfRangeException_ASM
== CORINFO_IndexOutOfRangeException);
-#define CORINFO_ArrayTypeMismatchException_ASM 6
-ASMCONSTANTS_C_ASSERT( CORINFO_ArrayTypeMismatchException_ASM
- == CORINFO_ArrayTypeMismatchException);
-
-#define CORINFO_ArgumentNullException_ASM 8
-ASMCONSTANTS_C_ASSERT( CORINFO_ArgumentNullException_ASM
- == CORINFO_ArgumentNullException);
-
#define CORINFO_ArgumentException_ASM 9
ASMCONSTANTS_C_ASSERT( CORINFO_ArgumentException_ASM
== CORINFO_ArgumentException);
diff --git a/src/coreclr/vm/arm/cgencpu.h b/src/coreclr/vm/arm/cgencpu.h
index 1f25c1b9f1876e..7c2e3b8160bc67 100644
--- a/src/coreclr/vm/arm/cgencpu.h
+++ b/src/coreclr/vm/arm/cgencpu.h
@@ -363,7 +363,6 @@ inline PCODE decodeBackToBackJump(PCODE pBuffer)
//----------------------------------------------------------------------
#include "stublink.h"
-struct ArrayOpScript;
inline BOOL IsThumbCode(PCODE pCode)
{
diff --git a/src/coreclr/vm/array.cpp b/src/coreclr/vm/array.cpp
index 806db9309f0fb3..3b2b778f4c50f0 100644
--- a/src/coreclr/vm/array.cpp
+++ b/src/coreclr/vm/array.cpp
@@ -72,10 +72,8 @@ VOID ArrayClass::GenerateArrayAccessorCallSig(
PCCOR_SIGNATURE *ppSig,// Generated signature
DWORD * pcSig, // Generated signature size
LoaderAllocator *pLoaderAllocator,
- AllocMemTracker *pamTracker
-#ifdef FEATURE_ARRAYSTUB_AS_IL
- ,BOOL fForStubAsIL
-#endif
+ AllocMemTracker *pamTracker,
+ BOOL fForStubAsIL
)
{
CONTRACTL {
@@ -109,9 +107,7 @@ VOID ArrayClass::GenerateArrayAccessorCallSig(
// BYREF VAR 0 I4 , ... , I4
case ArrayMethodDesc::ARRAY_FUNC_ADDRESS:
dwCallSigSize += 5;
-#ifdef FEATURE_ARRAYSTUB_AS_IL
if(fForStubAsIL) {dwArgCount++; dwCallSigSize++;}
-#endif
break;
}
@@ -124,11 +120,7 @@ VOID ArrayClass::GenerateArrayAccessorCallSig(
pSig = pSigMemory;
BYTE callConv = IMAGE_CEE_CS_CALLCONV_DEFAULT + IMAGE_CEE_CS_CALLCONV_HASTHIS;
- if (dwFuncType == ArrayMethodDesc::ARRAY_FUNC_ADDRESS
-#ifdef FEATURE_ARRAYSTUB_AS_IL
- && !fForStubAsIL
-#endif
- )
+ if (dwFuncType == ArrayMethodDesc::ARRAY_FUNC_ADDRESS && !fForStubAsIL)
{
callConv |= CORINFO_CALLCONV_PARAMTYPE; // Address routine needs special hidden arg
}
@@ -154,7 +146,7 @@ VOID ArrayClass::GenerateArrayAccessorCallSig(
break;
}
-#if defined(FEATURE_ARRAYSTUB_AS_IL ) && !defined(TARGET_X86)
+#ifndef TARGET_X86
if(dwFuncType == ArrayMethodDesc::ARRAY_FUNC_ADDRESS && fForStubAsIL)
{
*pSig++ = ELEMENT_TYPE_I;
@@ -169,7 +161,7 @@ VOID ArrayClass::GenerateArrayAccessorCallSig(
*pSig++ = ELEMENT_TYPE_VAR;
*pSig++ = 0; // variable 0
}
-#if defined(FEATURE_ARRAYSTUB_AS_IL ) && defined(TARGET_X86)
+#ifdef TARGET_X86
else if(dwFuncType == ArrayMethodDesc::ARRAY_FUNC_ADDRESS && fForStubAsIL)
{
*pSig++ = ELEMENT_TYPE_I;
@@ -515,11 +507,7 @@ MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementTy
PCCOR_SIGNATURE pSig;
DWORD cSig;
- pClass->GenerateArrayAccessorCallSig(dwFuncRank, dwFuncType, &pSig, &cSig, pAllocator, pamTracker
- #ifdef FEATURE_ARRAYSTUB_AS_IL
- ,0
- #endif
- );
+ pClass->GenerateArrayAccessorCallSig(dwFuncRank, dwFuncType, &pSig, &cSig, pAllocator, pamTracker, FALSE);
pClass->InitArrayMethodDesc(pNewMD, pSig, cSig, numVirtuals + dwMethodIndex, pAllocator, pamTracker);
@@ -628,8 +616,6 @@ MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementTy
} // Module::CreateArrayMethodTable
-#ifdef FEATURE_ARRAYSTUB_AS_IL
-
class ArrayOpLinker : public ILStubLinker
{
ILCodeStream * m_pCode;
@@ -930,237 +916,6 @@ Stub *GenerateArrayOpStub(ArrayMethodDesc* pMD)
return Stub::NewStub(JitILStub(pStubMD));
}
-#else // FEATURE_ARRAYSTUB_AS_IL
-//========================================================================
-// Generates the platform-independent arrayop stub.
-//========================================================================
-void GenerateArrayOpScript(ArrayMethodDesc *pMD, ArrayOpScript *paos)
-{
- STANDARD_VM_CONTRACT;
-
- ArrayOpIndexSpec *pai = NULL;
- MethodTable *pMT = pMD->GetMethodTable();
- ArrayClass *pcls = (ArrayClass*)(pMT->GetClass());
-
- // The ArrayOpScript and ArrayOpIndexSpec structs double as hash keys
- // for the ArrayStubCache. Thus, it's imperative that there be no
- // unused "pad" fields that contain unstable values.
- // pMT->GetRank() is bounded so the arithmetics here is safe.
- memset(paos, 0, sizeof(ArrayOpScript) + sizeof(ArrayOpIndexSpec) * pMT->GetRank());
-
- paos->m_rank = (BYTE)(pMT->GetRank());
- paos->m_fHasLowerBounds = (pMT->GetInternalCorElementType() == ELEMENT_TYPE_ARRAY);
-
- paos->m_ofsoffirst = ArrayBase::GetDataPtrOffset(pMT);
-
- switch (pMD->GetArrayFuncIndex())
- {
- case ArrayMethodDesc::ARRAY_FUNC_GET:
- paos->m_op = ArrayOpScript::LOAD;
- break;
- case ArrayMethodDesc::ARRAY_FUNC_SET:
- paos->m_op = ArrayOpScript::STORE;
- break;
- case ArrayMethodDesc::ARRAY_FUNC_ADDRESS:
- paos->m_op = ArrayOpScript::LOADADDR;
- break;
- default:
- _ASSERTE(!"Unknown array func!");
- }
-
- MetaSig msig(pMD);
- _ASSERTE(!msig.IsVarArg()); // No array signature is varargs, code below does not expect it.
-
- switch (pMT->GetArrayElementTypeHandle().GetInternalCorElementType())
- {
- // These are all different because of sign extension
-
- case ELEMENT_TYPE_I1:
- paos->m_elemsize = 1;
- paos->m_signed = TRUE;
- break;
-
- case ELEMENT_TYPE_BOOLEAN:
- case ELEMENT_TYPE_U1:
- paos->m_elemsize = 1;
- break;
-
- case ELEMENT_TYPE_I2:
- paos->m_elemsize = 2;
- paos->m_signed = TRUE;
- break;
-
- case ELEMENT_TYPE_CHAR:
- case ELEMENT_TYPE_U2:
- paos->m_elemsize = 2;
- break;
-
- case ELEMENT_TYPE_I4:
- IN_TARGET_32BIT(case ELEMENT_TYPE_I:)
- paos->m_elemsize = 4;
- paos->m_signed = TRUE;
- break;
-
- case ELEMENT_TYPE_U4:
- IN_TARGET_32BIT(case ELEMENT_TYPE_U:)
- IN_TARGET_32BIT(case ELEMENT_TYPE_PTR:)
- paos->m_elemsize = 4;
- break;
-
- case ELEMENT_TYPE_I8:
- IN_TARGET_64BIT(case ELEMENT_TYPE_I:)
- paos->m_elemsize = 8;
- paos->m_signed = TRUE;
- break;
-
- case ELEMENT_TYPE_U8:
- IN_TARGET_64BIT(case ELEMENT_TYPE_U:)
- IN_TARGET_64BIT(case ELEMENT_TYPE_PTR:)
- paos->m_elemsize = 8;
- break;
-
- case ELEMENT_TYPE_R4:
- paos->m_elemsize = 4;
- paos->m_flags |= paos->ISFPUTYPE;
- break;
-
- case ELEMENT_TYPE_R8:
- paos->m_elemsize = 8;
- paos->m_flags |= paos->ISFPUTYPE;
- break;
-
- case ELEMENT_TYPE_SZARRAY:
- case ELEMENT_TYPE_ARRAY:
- case ELEMENT_TYPE_CLASS:
- case ELEMENT_TYPE_STRING:
- case ELEMENT_TYPE_OBJECT:
- paos->m_elemsize = sizeof(LPVOID);
- paos->m_flags |= paos->NEEDSWRITEBARRIER;
- if (paos->m_op != ArrayOpScript::LOAD)
- {
- paos->m_flags |= paos->NEEDSTYPECHECK;
- }
-
- break;
-
- case ELEMENT_TYPE_VALUETYPE:
- paos->m_elemsize = pMT->GetComponentSize();
- if (pMT->ContainsPointers())
- {
- paos->m_gcDesc = CGCDesc::GetCGCDescFromMT(pMT);
- paos->m_flags |= paos->NEEDSWRITEBARRIER;
- }
- break;
-
- default:
- _ASSERTE(!"Unsupported Array Type!");
- }
-
- ArgIterator argit(&msig);
-
-#ifdef TARGET_X86
- UINT stackPop = argit.CbStackPop();
- _ASSERTE(stackPop <= USHRT_MAX);
- paos->m_cbretpop = (UINT16)stackPop;
-#endif
-
- if (argit.HasRetBuffArg())
- {
- paos->m_flags |= ArrayOpScript::HASRETVALBUFFER;
- UINT refBuffOffset = argit.GetRetBuffArgOffset();
- _ASSERTE(refBuffOffset <= USHRT_MAX);
- paos->m_fRetBufLoc = (UINT16)refBuffOffset;
- }
-
- if (paos->m_op == ArrayOpScript::LOADADDR)
- {
- paos->m_typeParamOffs = argit.GetParamTypeArgOffset();
- }
-
- for (UINT idx = 0; idx < paos->m_rank; idx++)
- {
- pai = (ArrayOpIndexSpec*)(paos->GetArrayOpIndexSpecs() + idx);
-
- pai->m_idxloc = argit.GetNextOffset();
- pai->m_lboundofs = paos->m_fHasLowerBounds ? (UINT32) (ArrayBase::GetLowerBoundsOffset(pMT) + idx*sizeof(DWORD)) : 0;
- pai->m_lengthofs = ArrayBase::GetBoundsOffset(pMT) + idx*sizeof(DWORD);
- }
-
- if (paos->m_op == paos->STORE)
- {
- UINT offset = argit.GetNextOffset();
- _ASSERTE(offset <= USHRT_MAX);
- paos->m_fValLoc = (UINT16)offset;
- }
-}
-
-//---------------------------------------------------------
-// Cache for array stubs
-//---------------------------------------------------------
-class ArrayStubCache : public StubCacheBase
-{
- virtual DWORD CompileStub(const BYTE *pRawStub,
- StubLinker *psl);
- virtual UINT Length(const BYTE *pRawStub);
-
-public:
-public:
- ArrayStubCache(LoaderHeap* heap) : StubCacheBase(heap)
- {
- }
-
- static ArrayStubCache * GetArrayStubCache()
- {
- STANDARD_VM_CONTRACT;
-
- static ArrayStubCache * s_pArrayStubCache = NULL;
-
- if (s_pArrayStubCache == NULL)
- {
- ArrayStubCache * pArrayStubCache = new ArrayStubCache(SystemDomain::GetGlobalLoaderAllocator()->GetStubHeap());
- if (InterlockedCompareExchangeT(&s_pArrayStubCache, pArrayStubCache, NULL) != NULL)
- delete pArrayStubCache;
- }
-
- return s_pArrayStubCache;
- }
-};
-
-Stub *GenerateArrayOpStub(ArrayMethodDesc* pMD)
-{
- STANDARD_VM_CONTRACT;
-
- MethodTable *pMT = pMD->GetMethodTable();
-
- ArrayOpScript *paos = (ArrayOpScript*)_alloca(sizeof(ArrayOpScript) + sizeof(ArrayOpIndexSpec) * pMT->GetRank());
-
- GenerateArrayOpScript(pMD, paos);
-
- Stub *pArrayOpStub;
- pArrayOpStub = ArrayStubCache::GetArrayStubCache()->Canonicalize((const BYTE *)paos);
- if (pArrayOpStub == NULL)
- COMPlusThrowOM();
-
- return pArrayOpStub;
-}
-
-DWORD ArrayStubCache::CompileStub(const BYTE *pRawStub,
- StubLinker *psl)
-{
- STANDARD_VM_CONTRACT;
-
- ((CPUSTUBLINKER*)psl)->EmitArrayOpStub((ArrayOpScript*)pRawStub);
- return NEWSTUB_FL_NONE;
-}
-
-UINT ArrayStubCache::Length(const BYTE *pRawStub)
-{
- LIMITED_METHOD_CONTRACT;
- return ((ArrayOpScript*)pRawStub)->Length();
-}
-
-#endif // FEATURE_ARRAYSTUB_AS_IL
-
//---------------------------------------------------------------------
// This method returns TRUE if pInterfaceMT could be one of the interfaces
diff --git a/src/coreclr/vm/array.h b/src/coreclr/vm/array.h
index 51a7c988c4afd1..1f687f140eef3b 100644
--- a/src/coreclr/vm/array.h
+++ b/src/coreclr/vm/array.h
@@ -14,90 +14,6 @@
class MethodTable;
-#ifndef FEATURE_ARRAYSTUB_AS_IL
-
-//======================================================================
-// The following structures double as hash keys for the ArrayStubCache.
-// Thus, it's imperative that there be no
-// unused "pad" fields that contain unstable values.
-#include
-
-
-// Specifies one index spec. This is used mostly to get the argument
-// location done early when we still have a signature to work with.
-struct ArrayOpIndexSpec
-{
- UINT32 m_idxloc; //if (m_fref) offset in ArgumentReg else base-frame offset into stack.
- UINT32 m_lboundofs; //offset within array of lowerbound
- UINT32 m_lengthofs; //offset within array of lengths
-};
-
-
-struct ArrayOpScript
-{
- enum
- {
- LOAD = 0,
- STORE = 1,
- LOADADDR = 2,
- };
-
-
- // FLAGS
- enum
- {
- ISFPUTYPE = 0x01,
- NEEDSWRITEBARRIER = 0x02,
- HASRETVALBUFFER = 0x04,
- NEEDSTYPECHECK = 0x10,
- };
-
- //
- // these args have been reordered for better packing..
- //
-
- BYTE m_rank; // # of ArrayOpIndexSpec's
- BYTE m_fHasLowerBounds; // if FALSE, all lowerbounds are 0
- BYTE m_flags;
- BYTE m_signed; // whether to sign-extend or zero-extend (for short types)
-
- BYTE m_op; // STORE/LOAD/LOADADDR
- BYTE m_pad1;
-
- UINT16 m_fRetBufLoc; // if HASRETVALBUFFER, stack offset or argreg offset of retbuf ptr
- UINT16 m_fValLoc; // for STORES, stack offset or argreg offset of value
-
- UINT16 m_cbretpop; // how much to pop
-
- UINT32 m_elemsize; // size in bytes of element.
- UINT m_ofsoffirst; // offset of first element
- INT m_typeParamOffs; // offset of type param
- CGCDesc* m_gcDesc; // layout of GC stuff (0 if not needed)
-
- // Array of ArrayOpIndexSpec's follow (one for each dimension).
-
- const ArrayOpIndexSpec *GetArrayOpIndexSpecs() const
- {
- LIMITED_METHOD_CONTRACT;
-
- return (const ArrayOpIndexSpec *)(1+ this);
- }
-
- UINT Length() const
- {
- LIMITED_METHOD_CONTRACT;
-
- return sizeof(*this) + m_rank * sizeof(ArrayOpIndexSpec);
- }
-
-};
-
-#include
-//======================================================================
-
-#endif // FEATURE_ARRAYSTUB_AS_IL
-
-
Stub *GenerateArrayOpStub(ArrayMethodDesc* pMD);
diff --git a/src/coreclr/vm/class.h b/src/coreclr/vm/class.h
index 77535d9ef4b239..e20b29b9e5f122 100644
--- a/src/coreclr/vm/class.h
+++ b/src/coreclr/vm/class.h
@@ -1984,10 +1984,8 @@ class ArrayClass : public EEClass
PCCOR_SIGNATURE *ppSig, // Generated signature
DWORD * pcSig, // Generated signature size
LoaderAllocator *pLoaderAllocator,
- AllocMemTracker *pamTracker
-#ifdef FEATURE_ARRAYSTUB_AS_IL
- ,BOOL fForStubAsIL
-#endif
+ AllocMemTracker *pamTracker,
+ BOOL fForStubAsIL
);
diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h
index 3974434e5c93a5..2e1a7e970563f7 100644
--- a/src/coreclr/vm/corelib.h
+++ b/src/coreclr/vm/corelib.h
@@ -1164,9 +1164,7 @@ DEFINE_METHOD(CASTHELPERS, CHKCASTCLASSSPECIAL, ChkCastClassSpecial, SM_Ptr
DEFINE_METHOD(CASTHELPERS, UNBOX, Unbox, SM_PtrVoid_Obj_RetRefByte)
DEFINE_METHOD(CASTHELPERS, STELEMREF, StelemRef, SM_ArrObject_IntPtr_Obj_RetVoid)
DEFINE_METHOD(CASTHELPERS, LDELEMAREF, LdelemaRef, SM_ArrObject_IntPtr_PtrVoid_RetRefObj)
-#ifdef FEATURE_ARRAYSTUB_AS_IL
DEFINE_METHOD(CASTHELPERS, ARRAYTYPECHECK, ArrayTypeCheck, SM_Obj_Array_RetVoid)
-#endif
#ifdef FEATURE_EH_FUNCLETS
DEFINE_CLASS(EH, Runtime, EH)
diff --git a/src/coreclr/vm/dllimport.h b/src/coreclr/vm/dllimport.h
index 9a7b1575bff06e..891221cff6b846 100644
--- a/src/coreclr/vm/dllimport.h
+++ b/src/coreclr/vm/dllimport.h
@@ -191,11 +191,9 @@ enum NDirectStubFlags
enum ILStubTypes
{
ILSTUB_INVALID = 0x80000000,
-#ifdef FEATURE_ARRAYSTUB_AS_IL
ILSTUB_ARRAYOP_GET = 0x80000001,
ILSTUB_ARRAYOP_SET = 0x80000002,
ILSTUB_ARRAYOP_ADDRESS = 0x80000003,
-#endif
#ifdef FEATURE_MULTICASTSTUB_AS_IL
ILSTUB_MULTICASTDELEGATE_INVOKE = 0x80000004,
#endif
@@ -229,11 +227,9 @@ inline bool SF_IsCheckPendingException (DWORD dwStubFlags) { LIMITED_METHOD_CONT
inline bool SF_IsVirtualStaticMethodDispatchStub(DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return dwStubFlags == ILSTUB_STATIC_VIRTUAL_DISPATCH_STUB; }
-#ifdef FEATURE_ARRAYSTUB_AS_IL
inline bool SF_IsArrayOpStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return ((dwStubFlags == ILSTUB_ARRAYOP_GET) ||
(dwStubFlags == ILSTUB_ARRAYOP_SET) ||
(dwStubFlags == ILSTUB_ARRAYOP_ADDRESS)); }
-#endif
#ifdef FEATURE_MULTICASTSTUB_AS_IL
inline bool SF_IsMulticastDelegateStub (DWORD dwStubFlags) { LIMITED_METHOD_CONTRACT; return (dwStubFlags == ILSTUB_MULTICASTDELEGATE_INVOKE); }
diff --git a/src/coreclr/vm/i386/asmconstants.h b/src/coreclr/vm/i386/asmconstants.h
index 392c04ac92b98c..8c8fec685e0f82 100644
--- a/src/coreclr/vm/i386/asmconstants.h
+++ b/src/coreclr/vm/i386/asmconstants.h
@@ -163,12 +163,6 @@ ASMCONSTANTS_C_ASSERT(CORINFO_IndexOutOfRangeException_ASM == CORINFO_IndexOutOf
#define CORINFO_OverflowException_ASM 4
ASMCONSTANTS_C_ASSERT(CORINFO_OverflowException_ASM == CORINFO_OverflowException)
-#define CORINFO_ArrayTypeMismatchException_ASM 6
-ASMCONSTANTS_C_ASSERT(CORINFO_ArrayTypeMismatchException_ASM == CORINFO_ArrayTypeMismatchException)
-
-#define CORINFO_ArgumentNullException_ASM 8
-ASMCONSTANTS_C_ASSERT(CORINFO_ArgumentNullException_ASM == CORINFO_ArgumentNullException)
-
#define CORINFO_ArgumentException_ASM 9
ASMCONSTANTS_C_ASSERT(CORINFO_ArgumentException_ASM == CORINFO_ArgumentException)
diff --git a/src/coreclr/vm/i386/asmhelpers.asm b/src/coreclr/vm/i386/asmhelpers.asm
index 6a12bc9870b1cb..07f6e8b955d038 100644
--- a/src/coreclr/vm/i386/asmhelpers.asm
+++ b/src/coreclr/vm/i386/asmhelpers.asm
@@ -425,39 +425,6 @@ InternalExceptionWorker proc public
jmp @JIT_InternalThrow@4
InternalExceptionWorker endp
-; EAX -> number of caller arg bytes on the stack that we must remove before going
-; to the throw helper, which assumes the stack is clean.
-_ArrayOpStubNullException proc public
- ; kFactorReg and kTotalReg could not have been modified, but let's pop
- ; them anyway for consistency and to avoid future bugs.
- pop esi
- pop edi
- mov ecx, CORINFO_NullReferenceException_ASM
- jmp InternalExceptionWorker
-_ArrayOpStubNullException endp
-
-; EAX -> number of caller arg bytes on the stack that we must remove before going
-; to the throw helper, which assumes the stack is clean.
-_ArrayOpStubRangeException proc public
- ; kFactorReg and kTotalReg could not have been modified, but let's pop
- ; them anyway for consistency and to avoid future bugs.
- pop esi
- pop edi
- mov ecx, CORINFO_IndexOutOfRangeException_ASM
- jmp InternalExceptionWorker
-_ArrayOpStubRangeException endp
-
-; EAX -> number of caller arg bytes on the stack that we must remove before going
-; to the throw helper, which assumes the stack is clean.
-_ArrayOpStubTypeMismatchException proc public
- ; kFactorReg and kTotalReg could not have been modified, but let's pop
- ; them anyway for consistency and to avoid future bugs.
- pop esi
- pop edi
- mov ecx, CORINFO_ArrayTypeMismatchException_ASM
- jmp InternalExceptionWorker
-_ArrayOpStubTypeMismatchException endp
-
;------------------------------------------------------------------------------
; This helper routine enregisters the appropriate arguments and makes the
; actual call.
diff --git a/src/coreclr/vm/i386/cgenx86.cpp b/src/coreclr/vm/i386/cgenx86.cpp
index d9dc22d148193b..69e2fe9e5360b0 100644
--- a/src/coreclr/vm/i386/cgenx86.cpp
+++ b/src/coreclr/vm/i386/cgenx86.cpp
@@ -45,8 +45,6 @@
// if someone changes the frame size. You are expected to keep this hard coded constant
// up to date so that changes in the frame size trigger errors at compile time if the code is not altered
-void generate_noref_copy (unsigned nbytes, StubLinkerCPU* sl);
-
#ifdef FEATURE_EH_FUNCLETS
void UpdateRegDisplayFromCalleeSavedRegisters(REGDISPLAY * pRD, CalleeSavedRegisters * regs)
{
diff --git a/src/coreclr/vm/i386/stublinkerx86.cpp b/src/coreclr/vm/i386/stublinkerx86.cpp
index aa4214bd42e834..7261dd0c67b9a6 100644
--- a/src/coreclr/vm/i386/stublinkerx86.cpp
+++ b/src/coreclr/vm/i386/stublinkerx86.cpp
@@ -50,24 +50,6 @@ extern "C" HRESULT __cdecl StubRareDisableHR(Thread *pThread);
#endif // FEATURE_COMINTEROP
extern "C" VOID __cdecl StubRareDisableTHROW(Thread *pThread, Frame *pFrame);
-#ifndef FEATURE_ARRAYSTUB_AS_IL
-extern "C" VOID __cdecl ArrayOpStubNullException(void);
-extern "C" VOID __cdecl ArrayOpStubRangeException(void);
-extern "C" VOID __cdecl ArrayOpStubTypeMismatchException(void);
-
-#if defined(TARGET_AMD64)
-#define EXCEPTION_HELPERS(base) \
- extern "C" VOID __cdecl base##_RSIRDI_ScratchArea(void); \
- extern "C" VOID __cdecl base##_ScratchArea(void); \
- extern "C" VOID __cdecl base##_RSIRDI(void); \
- extern "C" VOID __cdecl base(void)
-EXCEPTION_HELPERS(ArrayOpStubNullException);
-EXCEPTION_HELPERS(ArrayOpStubRangeException);
-EXCEPTION_HELPERS(ArrayOpStubTypeMismatchException);
-#undef EXCEPTION_HELPERS
-#endif // !TARGET_AMD64
-#endif // !FEATURE_ARRAYSTUB_AS_IL
-
#if defined(TARGET_AMD64)
#if defined(_DEBUG)
extern "C" VOID __cdecl DebugCheckStubUnwindInfo();
@@ -3863,959 +3845,6 @@ VOID StubLinkerCPU::EmitMulticastInvoke(UINT_PTR hash)
#endif // !FEATURE_STUBS_AS_IL
-#if !defined(FEATURE_ARRAYSTUB_AS_IL)
-
-// Little helper to generate code to move nbytes bytes of non Ref memory
-
-void generate_noref_copy (unsigned nbytes, StubLinkerCPU* sl)
-{
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- INJECT_FAULT(COMPlusThrowOM(););
- }
- CONTRACTL_END;
-
- // If the size is pointer-aligned, we'll use movsd
- if (IS_ALIGNED(nbytes, sizeof(void*)))
- {
- // If there are less than 4 pointers to copy, "unroll" the "rep movsd"
- if (nbytes <= 3*sizeof(void*))
- {
- while (nbytes > 0)
- {
- // movsd
- sl->X86_64BitOperands();
- sl->Emit8(0xa5);
-
- nbytes -= sizeof(void*);
- }
- }
- else
- {
- // mov ECX, size / 4
- sl->Emit8(0xb8+kECX);
- sl->Emit32(nbytes / sizeof(void*));
-
- // repe movsd
- sl->Emit8(0xf3);
- sl->X86_64BitOperands();
- sl->Emit8(0xa5);
- }
- }
- else
- {
- // mov ECX, size
- sl->Emit8(0xb8+kECX);
- sl->Emit32(nbytes);
-
- // repe movsb
- sl->Emit16(0xa4f3);
- }
-}
-
-
-X86Reg LoadArrayOpArg (
- UINT32 idxloc,
- StubLinkerCPU *psl,
- X86Reg kRegIfFromMem,
- UINT ofsadjust
- AMD64_ARG(StubLinkerCPU::X86OperandSize OperandSize = StubLinkerCPU::k64BitOp)
- )
-{
- STANDARD_VM_CONTRACT;
-
- if (!TransitionBlock::IsStackArgumentOffset(idxloc))
- return GetX86ArgumentRegisterFromOffset(idxloc - TransitionBlock::GetOffsetOfArgumentRegisters());
-
- psl->X86EmitEspOffset(0x8b, kRegIfFromMem, idxloc + ofsadjust AMD64_ARG(OperandSize));
- return kRegIfFromMem;
-}
-
-VOID StubLinkerCPU::EmitArrayOpStubThrow(unsigned exConst, unsigned cbRetArg)
-{
- STANDARD_VM_CONTRACT;
-
- //ArrayOpStub*Exception
- X86EmitPopReg(kESI);
- X86EmitPopReg(kEDI);
-
- //mov CORINFO_NullReferenceException_ASM, %ecx
- Emit8(0xb8 | kECX);
- Emit32(exConst);
- //InternalExceptionWorker
-
- X86EmitPopReg(kEDX);
- // add pArrayOpScript->m_cbretpop, %esp (was add %eax, %esp)
- Emit8(0x81);
- Emit8(0xc0 | 0x4);
- Emit32(cbRetArg);
- X86EmitPushReg(kEDX);
- X86EmitNearJump(NewExternalCodeLabel((PVOID)JIT_InternalThrow));
-}
-
-//===========================================================================
-// Emits code to do an array operation.
-#ifdef _PREFAST_
-#pragma warning(push)
-#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
-#endif
-VOID StubLinkerCPU::EmitArrayOpStub(const ArrayOpScript* pArrayOpScript)
-{
- STANDARD_VM_CONTRACT;
-
- // This is the offset to the parameters/what's already pushed on the stack:
- // return address.
- const INT locsize = sizeof(void*);
-
- // ArrayOpScript's stack offsets are built using ArgIterator, which
- // assumes a TransitionBlock has been pushed, which is not the case
- // here. rsp + ofsadjust should point at the first argument. Any further
- // stack modifications below need to adjust ofsadjust appropriately.
- // baseofsadjust needs to be the stack adjustment at the entry point -
- // this is used further below to compute how much stack space was used.
-
- INT ofsadjust = locsize - (INT)sizeof(TransitionBlock);
-
- // Register usage
- //
- // x86 AMD64
- // Inputs:
- // managed array THIS_kREG (ecx) THIS_kREG (rcx)
- // index 0 edx rdx
- // index 1/value r8
- // index 2/value r9
- // expected element type for LOADADDR eax rax rdx
- // Working registers:
- // total (accumulates unscaled offset) edi r10
- // factor (accumulates the slice factor) esi r11
- X86Reg kArrayRefReg = THIS_kREG;
-#ifdef TARGET_AMD64
- const X86Reg kArrayMTReg = kR10;
- const X86Reg kTotalReg = kR10;
- const X86Reg kFactorReg = kR11;
-#else
- const X86Reg kArrayMTReg = kESI;
- const X86Reg kTotalReg = kEDI;
- const X86Reg kFactorReg = kESI;
-#endif
-
-#ifdef TARGET_AMD64
- // Simplifying assumption for fNeedPrologue.
- _ASSERTE(!pArrayOpScript->m_gcDesc || (pArrayOpScript->m_flags & ArrayOpScript::NEEDSWRITEBARRIER));
- // Simplifying assumption for saving rsi and rdi.
- _ASSERTE(!(pArrayOpScript->m_flags & ArrayOpScript::HASRETVALBUFFER) || ArgIterator::IsArgPassedByRef(pArrayOpScript->m_elemsize));
-
- // Cases where we need to make calls
- BOOL fNeedScratchArea = ( (pArrayOpScript->m_flags & (ArrayOpScript::NEEDSTYPECHECK | ArrayOpScript::NEEDSWRITEBARRIER))
- && ( pArrayOpScript->m_op == ArrayOpScript::STORE
- || ( pArrayOpScript->m_op == ArrayOpScript::LOAD
- && (pArrayOpScript->m_flags & ArrayOpScript::HASRETVALBUFFER))));
-
- // Cases where we need to copy large values
- BOOL fNeedRSIRDI = ( ArgIterator::IsArgPassedByRef(pArrayOpScript->m_elemsize)
- && ArrayOpScript::LOADADDR != pArrayOpScript->m_op);
-
- BOOL fNeedPrologue = ( fNeedScratchArea
- || fNeedRSIRDI);
-#endif
-
- X86Reg kValueReg;
-
- CodeLabel *Epilog = NewCodeLabel();
- CodeLabel *Inner_nullexception = NewCodeLabel();
- CodeLabel *Inner_rangeexception = NewCodeLabel();
- CodeLabel *Inner_typeMismatchexception = NULL;
-
- //
- // Set up the stack frame.
- //
- //
- // x86:
- // value
- //
- // ...
- //
- // return address
- // saved edi
- // esp -> saved esi
- //
- //
- // AMD64:
- // value, if rank > 2
- // ...
- // + 0x48 more indices
- // + 0x40 r9 home
- // + 0x38 r8 home
- // + 0x30 rdx home
- // + 0x28 rcx home
- // + 0x20 return address
- // + 0x18 scratch area (callee's r9)
- // + 0x10 scratch area (callee's r8)
- // + 8 scratch area (callee's rdx)
- // rsp -> scratch area (callee's rcx)
- //
- // If the element type is a value class w/ object references, then rsi
- // and rdi will also be saved above the scratch area:
- //
- // ...
- // + 0x28 saved rsi
- // + 0x20 saved rdi
- // + 0x18 scratch area (callee's r9)
- // + 0x10 scratch area (callee's r8)
- // + 8 scratch area (callee's rdx)
- // rsp -> scratch area (callee's rcx)
- //
- // And if no call or movsb is necessary, then the scratch area sits
- // directly under the MethodDesc*.
-
- BOOL fSavedESI = FALSE;
- BOOL fSavedEDI = FALSE;
-
-#ifdef TARGET_AMD64
- if (fNeedPrologue)
- {
- // Save argument registers if we'll be making a call before using
- // them. Note that in this case the element value will always be an
- // object type, and never be in an xmm register.
-
- if ( (pArrayOpScript->m_flags & ArrayOpScript::NEEDSTYPECHECK)
- && ArrayOpScript::STORE == pArrayOpScript->m_op)
- {
- // mov [rsp+0x08], rcx
- X86EmitEspOffset(0x89, kRCX, 0x08);
- X86EmitEspOffset(0x89, kRDX, 0x10);
- X86EmitEspOffset(0x89, kR8, 0x18);
-
- if (pArrayOpScript->m_rank >= 2)
- X86EmitEspOffset(0x89, kR9, 0x20);
- }
-
- if (fNeedRSIRDI)
- {
- X86EmitPushReg(kRSI);
- X86EmitPushReg(kRDI);
-
- fSavedESI = fSavedEDI = TRUE;
-
- ofsadjust += 0x10;
- }
-
- if (fNeedScratchArea)
- {
- // Callee scratch area (0x8 for aligned esp)
- X86EmitSubEsp(sizeof(ArgumentRegisters) + 0x8);
- ofsadjust += sizeof(ArgumentRegisters) + 0x8;
- }
- }
-#else
- // Preserve the callee-saved registers
- // NOTE: if you change the sequence of these pushes, you must also update:
- // ArrayOpStubNullException
- // ArrayOpStubRangeException
- // ArrayOpStubTypeMismatchException
- _ASSERTE( kTotalReg == kEDI);
- X86EmitPushReg(kTotalReg);
- _ASSERTE( kFactorReg == kESI);
- X86EmitPushReg(kFactorReg);
-
- fSavedESI = fSavedEDI = TRUE;
-
- ofsadjust += 2*sizeof(void*);
-#endif
-
- // Check for null.
- X86EmitR2ROp(0x85, kArrayRefReg, kArrayRefReg); // TEST ECX, ECX
- X86EmitCondJump(Inner_nullexception, X86CondCode::kJZ); // jz Inner_nullexception
-
- // Do Type Check if needed
- if (pArrayOpScript->m_flags & ArrayOpScript::NEEDSTYPECHECK)
- {
- if (pArrayOpScript->m_op == ArrayOpScript::STORE)
- {
- // Get the value to be stored.
- kValueReg = LoadArrayOpArg(pArrayOpScript->m_fValLoc, this, kEAX, ofsadjust);
-
- X86EmitR2ROp(0x85, kValueReg, kValueReg); // TEST kValueReg, kValueReg
- CodeLabel *CheckPassed = NewCodeLabel();
- X86EmitCondJump(CheckPassed, X86CondCode::kJZ); // storing NULL is OK
-
- // mov EAX, element type ; possibly trashes kValueReg
- X86EmitOp(0x8b, kArrayMTReg, kArrayRefReg, 0 AMD64_ARG(k64BitOp)); // mov ESI/R10, [kArrayRefReg]
-
- X86EmitOp(0x8b, kEAX, kValueReg, 0 AMD64_ARG(k64BitOp)); // mov EAX, [kValueReg] ; possibly trashes kValueReg
- // cmp EAX, [ESI/R10+m_ElementType]
-
- X86EmitOp(0x3b, kEAX, kArrayMTReg, MethodTable::GetOffsetOfArrayElementTypeHandle() AMD64_ARG(k64BitOp));
- X86EmitCondJump(CheckPassed, X86CondCode::kJZ); // Exact match is OK
-
- X86EmitRegLoad(kEAX, (UINT_PTR)g_pObjectClass); // mov EAX, g_pObjectMethodTable
- // cmp EAX, [ESI/R10+m_ElementType]
-
- X86EmitOp(0x3b, kEAX, kArrayMTReg, MethodTable::GetOffsetOfArrayElementTypeHandle() AMD64_ARG(k64BitOp));
- X86EmitCondJump(CheckPassed, X86CondCode::kJZ); // Assigning to array of object is OK
-
- // Try to call the fast helper first ( ObjIsInstanceOfCached ).
- // If that fails we will fall back to calling the slow helper ( ArrayStoreCheck ) that erects a frame.
-
-#ifdef TARGET_AMD64
- // RCX contains pointer to object to check (Object*)
- // RDX contains array type handle
-
- // mov RCX, [rsp+offsetToObject] ; RCX = Object*
- X86EmitEspOffset(0x8b, kRCX, ofsadjust + pArrayOpScript->m_fValLoc);
-
- // get Array TypeHandle
- // mov RDX, [RSP+offsetOfTypeHandle]
-
- X86EmitEspOffset(0x8b, kRDX, ofsadjust
- + TransitionBlock::GetOffsetOfArgumentRegisters()
- + offsetof(ArgumentRegisters, THIS_REG));
-
- // mov RDX, [kArrayMTReg+offsetof(MethodTable, m_ElementType)]
- X86EmitIndexRegLoad(kRDX, kArrayMTReg, MethodTable::GetOffsetOfArrayElementTypeHandle());
-
-#else
- X86EmitPushReg(kEDX); // Save EDX
- X86EmitPushReg(kECX); // Pass array object
-
- X86EmitIndexPush(kArrayMTReg, MethodTable::GetOffsetOfArrayElementTypeHandle()); // push [kArrayMTReg + m_ElementType] ; Array element type handle
-
- // get address of value to store
- _ASSERTE(TransitionBlock::IsStackArgumentOffset(pArrayOpScript->m_fValLoc)); // on x86, value will never get a register
- X86EmitSPIndexPush(pArrayOpScript->m_fValLoc + ofsadjust + 3*sizeof(void*)); // push [ESP+offset] ; the object pointer
-
-#endif //_AMD64
-
-
- // emit a call to the fast helper
- // One side effect of this is that we are going to generate a "jnz Epilog" and we DON'T need it
- // in the fast path, however there are no side effects in emitting
- // it in the fast path anyway. the reason for that is that it makes
- // the cleanup code much easier ( we have only 1 place to cleanup the stack and
- // restore it to the original state )
- X86EmitCall(NewExternalCodeLabel((LPVOID)ObjIsInstanceOfCached), 0);
- X86EmitCmpRegImm32( kEAX, TypeHandle::CanCast); // CMP EAX, CanCast ; if ObjIsInstanceOfCached returns CanCast, we will go the fast path
- CodeLabel * Cleanup = NewCodeLabel();
- X86EmitCondJump(Cleanup, X86CondCode::kJZ);
-
-#ifdef TARGET_AMD64
- // get address of value to store
- // lea rcx, [rsp+offs]
- X86EmitEspOffset(0x8d, kRCX, ofsadjust + pArrayOpScript->m_fValLoc);
-
- // get address of 'this'/rcx
- // lea rdx, [rsp+offs]
- X86EmitEspOffset(0x8d, kRDX, ofsadjust
- + TransitionBlock::GetOffsetOfArgumentRegisters()
- + offsetof(ArgumentRegisters, THIS_REG));
-
-#else
- // The stack is already setup correctly for the slow helper.
- _ASSERTE(TransitionBlock::IsStackArgumentOffset(pArrayOpScript->m_fValLoc)); // on x86, value will never get a register
- X86EmitEspOffset(0x8d, kECX, pArrayOpScript->m_fValLoc + ofsadjust + 2*sizeof(void*)); // lea ECX, [ESP+offset]
-
- // get address of 'this'
- X86EmitEspOffset(0x8d, kEDX, 0); // lea EDX, [ESP] ; (address of ECX)
-
-
-#endif
- AMD64_ONLY(_ASSERTE(fNeedScratchArea));
- X86EmitCall(NewExternalCodeLabel((LPVOID)ArrayStoreCheck), 0);
-
- EmitLabel(Cleanup);
-#ifdef TARGET_AMD64
- X86EmitEspOffset(0x8b, kRCX, 0x00 + ofsadjust + TransitionBlock::GetOffsetOfArgumentRegisters());
- X86EmitEspOffset(0x8b, kRDX, 0x08 + ofsadjust + TransitionBlock::GetOffsetOfArgumentRegisters());
- X86EmitEspOffset(0x8b, kR8, 0x10 + ofsadjust + TransitionBlock::GetOffsetOfArgumentRegisters());
-
- if (pArrayOpScript->m_rank >= 2)
- X86EmitEspOffset(0x8b, kR9, 0x18 + ofsadjust + TransitionBlock::GetOffsetOfArgumentRegisters());
-#else
- X86EmitPopReg(kECX); // restore regs
- X86EmitPopReg(kEDX);
-
-
- X86EmitR2ROp(0x3B, kEAX, kEAX); // CMP EAX, EAX
- X86EmitCondJump(Epilog, X86CondCode::kJNZ); // This branch never taken, but epilog walker uses it
-#endif
-
- EmitLabel(CheckPassed);
- }
- else
- {
- _ASSERTE(pArrayOpScript->m_op == ArrayOpScript::LOADADDR);
-
- // Load up the hidden type parameter into 'typeReg'
- X86Reg typeReg = LoadArrayOpArg(pArrayOpScript->m_typeParamOffs, this, kEAX, ofsadjust);
-
- // 'typeReg' holds the typeHandle/MethodTable for the ARRAY.
- // If 'typeReg' is NULL then we're executing the readonly ::Address and no type check is
- // needed.
- CodeLabel *Inner_passedTypeCheck = NewCodeLabel();
-
- // test typeReg, typeReg
- X86EmitR2ROp(0x85, typeReg, typeReg);
- X86EmitCondJump(Inner_passedTypeCheck, X86CondCode::kJZ);
-
- // Compare MT against the MT of the array.
- // cmp typeReg, [kArrayRefReg]
- X86EmitOp(0x3b, typeReg, kArrayRefReg, 0 AMD64_ARG(k64BitOp));
-
- // Throw error if not equal
- Inner_typeMismatchexception = NewCodeLabel();
- X86EmitCondJump(Inner_typeMismatchexception, X86CondCode::kJNZ);
- EmitLabel(Inner_passedTypeCheck);
- }
- }
-
- CodeLabel* DoneCheckLabel = 0;
- if (pArrayOpScript->m_rank == 1 && pArrayOpScript->m_fHasLowerBounds)
- {
- DoneCheckLabel = NewCodeLabel();
- CodeLabel* NotSZArrayLabel = NewCodeLabel();
-
- // for rank1 arrays, we might actually have two different layouts depending on
- // if we are ELEMENT_TYPE_ARRAY or ELEMENT_TYPE_SZARRAY.
-
- // mov EAX, [ARRAY] // EAX holds the method table
- X86_64BitOperands();
- X86EmitOp(0x8b, kEAX, kArrayRefReg);
-
- // test [EAX + m_dwFlags], enum_flag_Category_IfArrayThenSzArray
- X86_64BitOperands();
- X86EmitOffsetModRM(0xf7, (X86Reg)0, kEAX, MethodTable::GetOffsetOfFlags());
- Emit32(MethodTable::GetIfArrayThenSzArrayFlag());
-
- // jz NotSZArrayLabel
- X86EmitCondJump(NotSZArrayLabel, X86CondCode::kJZ);
-
- //Load the passed-in index into the scratch register.
- const ArrayOpIndexSpec *pai = pArrayOpScript->GetArrayOpIndexSpecs();
- X86Reg idxReg = LoadArrayOpArg(pai->m_idxloc, this, SCRATCH_REGISTER_X86REG, ofsadjust);
-
- // cmp idxReg, [kArrayRefReg + LENGTH]
- X86EmitOp(0x3b, idxReg, kArrayRefReg, ArrayBase::GetOffsetOfNumComponents());
-
- // jae Inner_rangeexception
- X86EmitCondJump(Inner_rangeexception, X86CondCode::kJAE);
-
- // if we cared efficiency of this, this move can be optimized
- X86EmitR2ROp(0x8b, kTotalReg, idxReg AMD64_ARG(k32BitOp));
-
- // sub ARRAY. 8 // 8 is accounts for the Lower bound and Dim count in the ARRAY
- X86EmitSubReg(kArrayRefReg, 8); // adjust this pointer so that indexing works out for SZARRAY
-
- X86EmitNearJump(DoneCheckLabel);
- EmitLabel(NotSZArrayLabel);
- }
-
- // For each index, range-check and mix into accumulated total.
- UINT idx = pArrayOpScript->m_rank;
- BOOL firstTime = TRUE;
- while (idx--)
- {
- const ArrayOpIndexSpec *pai = pArrayOpScript->GetArrayOpIndexSpecs() + idx;
-
- //Load the passed-in index into the scratch register.
- X86Reg srcreg = LoadArrayOpArg(pai->m_idxloc, this, SCRATCH_REGISTER_X86REG, ofsadjust AMD64_ARG(k32BitOp));
- if (SCRATCH_REGISTER_X86REG != srcreg)
- X86EmitR2ROp(0x8b, SCRATCH_REGISTER_X86REG, srcreg AMD64_ARG(k32BitOp));
-
- // sub SCRATCH, dword ptr [kArrayRefReg + LOWERBOUND]
- if (pArrayOpScript->m_fHasLowerBounds)
- {
- X86EmitOp(0x2b, SCRATCH_REGISTER_X86REG, kArrayRefReg, pai->m_lboundofs);
- }
-
- // cmp SCRATCH, dword ptr [kArrayRefReg + LENGTH]
- X86EmitOp(0x3b, SCRATCH_REGISTER_X86REG, kArrayRefReg, pai->m_lengthofs);
-
- // jae Inner_rangeexception
- X86EmitCondJump(Inner_rangeexception, X86CondCode::kJAE);
-
-
- // SCRATCH == idx - LOWERBOUND
- //
- // imul SCRATCH, FACTOR
- if (!firstTime)
- {
- //Can skip the first time since FACTOR==1
- X86EmitR2ROp(0xaf0f, SCRATCH_REGISTER_X86REG, kFactorReg AMD64_ARG(k32BitOp));
- }
-
- // TOTAL += SCRATCH
- if (firstTime)
- {
- // First time, we must zero-init TOTAL. Since
- // zero-initing and then adding is just equivalent to a
- // "mov", emit a "mov"
- // mov TOTAL, SCRATCH
- X86EmitR2ROp(0x8b, kTotalReg, SCRATCH_REGISTER_X86REG AMD64_ARG(k32BitOp));
- }
- else
- {
- // add TOTAL, SCRATCH
- X86EmitR2ROp(0x03, kTotalReg, SCRATCH_REGISTER_X86REG AMD64_ARG(k32BitOp));
- }
-
- // FACTOR *= [kArrayRefReg + LENGTH]
- if (idx != 0)
- {
- // No need to update FACTOR on the last iteration
- // since we won't use it again
-
- if (firstTime)
- {
- // must init FACTOR to 1 first: hence,
- // the "imul" becomes a "mov"
- // mov FACTOR, [kArrayRefReg + LENGTH]
- X86EmitOp(0x8b, kFactorReg, kArrayRefReg, pai->m_lengthofs);
- }
- else
- {
- // imul FACTOR, [kArrayRefReg + LENGTH]
- X86EmitOp(0xaf0f, kFactorReg, kArrayRefReg, pai->m_lengthofs);
- }
- }
-
- firstTime = FALSE;
- }
-
- if (DoneCheckLabel != 0)
- EmitLabel(DoneCheckLabel);
-
- // Pass these values to X86EmitArrayOp() to generate the element address.
- X86Reg elemBaseReg = kArrayRefReg;
- X86Reg elemScaledReg = kTotalReg;
- UINT32 elemSize = pArrayOpScript->m_elemsize;
- UINT32 elemOfs = pArrayOpScript->m_ofsoffirst;
-
- if (!(elemSize == 1 || elemSize == 2 || elemSize == 4 || elemSize == 8))
- {
- switch (elemSize)
- {
- // No way to express this as a SIB byte. Fold the scale
- // into TOTAL.
-
- case 16:
- // shl TOTAL,4
- X86EmitR2ROp(0xc1, (X86Reg)4, kTotalReg AMD64_ARG(k32BitOp));
- Emit8(4);
- break;
-
- case 32:
- // shl TOTAL,5
- X86EmitR2ROp(0xc1, (X86Reg)4, kTotalReg AMD64_ARG(k32BitOp));
- Emit8(5);
- break;
-
- case 64:
- // shl TOTAL,6
- X86EmitR2ROp(0xc1, (X86Reg)4, kTotalReg AMD64_ARG(k32BitOp));
- Emit8(6);
- break;
-
- default:
- // imul TOTAL, elemScale
- X86EmitR2ROp(0x69, kTotalReg, kTotalReg AMD64_ARG(k32BitOp));
- Emit32(elemSize);
- break;
- }
- elemSize = 1;
- }
-
- _ASSERTE(FitsInU1(elemSize));
- BYTE elemScale = static_cast(elemSize);
-
- // Now, do the operation:
-
- switch (pArrayOpScript->m_op)
- {
- case ArrayOpScript::LOADADDR:
- // lea eax, ELEMADDR
- X86EmitOp(0x8d, kEAX, elemBaseReg, elemOfs, elemScaledReg, elemScale AMD64_ARG(k64BitOp));
- break;
-
- case ArrayOpScript::LOAD:
- if (pArrayOpScript->m_flags & ArrayOpScript::HASRETVALBUFFER)
- {
- // Ensure that these registers have been saved!
- _ASSERTE(fSavedESI && fSavedEDI);
-
- //lea esi, ELEMADDR
- X86EmitOp(0x8d, kESI, elemBaseReg, elemOfs, elemScaledReg, elemScale AMD64_ARG(k64BitOp));
-
- _ASSERTE(!TransitionBlock::IsStackArgumentOffset(pArrayOpScript->m_fRetBufLoc));
- // mov edi, retbufptr
- X86EmitR2ROp(0x8b, kEDI, GetX86ArgumentRegisterFromOffset(pArrayOpScript->m_fRetBufLoc - TransitionBlock::GetOffsetOfArgumentRegisters()));
-
-COPY_VALUE_CLASS:
- {
- size_t size = pArrayOpScript->m_elemsize;
- size_t total = 0;
- if(pArrayOpScript->m_gcDesc)
- {
- CGCDescSeries* cur = pArrayOpScript->m_gcDesc->GetHighestSeries();
- if ((cur->startoffset-elemOfs) > 0)
- generate_noref_copy ((unsigned) (cur->startoffset - elemOfs), this);
- total += cur->startoffset - elemOfs;
-
- SSIZE_T cnt = (SSIZE_T) pArrayOpScript->m_gcDesc->GetNumSeries();
-
- if (cnt == 1)
- {
- // all pointers
- for (size_t i = 0; i < size; i += sizeof(Object*))
- {
- X86EmitCall(NewExternalCodeLabel((LPVOID)JIT_ByRefWriteBarrier), 0);
- total += sizeof(Object*);
- }
- }
- else
- {
- // special array encoding
- _ASSERTE(cnt < 0);
-
- for (SSIZE_T __i = 0; __i > cnt; __i--)
- {
- HALF_SIZE_T skip = (cur->val_serie + __i)->skip;
- HALF_SIZE_T nptrs = (cur->val_serie + __i)->nptrs;
- total += nptrs*sizeof (Object*);
- do
- {
- AMD64_ONLY(_ASSERTE(fNeedScratchArea));
-
- X86EmitCall(NewExternalCodeLabel((LPVOID) JIT_ByRefWriteBarrier), 0);
- } while (--nptrs);
- if (skip > 0)
- {
- //check if we are at the end of the series
- if (__i == (cnt + 1))
- skip = skip - (HALF_SIZE_T)(cur->startoffset - elemOfs);
- if (skip > 0)
- generate_noref_copy (skip, this);
- }
- total += skip;
- }
- }
-
- _ASSERTE (size == total);
- }
- else
- {
- // no ref anywhere, just copy the bytes.
- _ASSERTE (size);
- generate_noref_copy ((unsigned)size, this);
- }
- }
- }
- else
- {
- switch (pArrayOpScript->m_elemsize)
- {
- case 1:
- // mov[zs]x eax, byte ptr ELEMADDR
- X86EmitOp(pArrayOpScript->m_signed ? 0xbe0f : 0xb60f, kEAX, elemBaseReg, elemOfs, elemScaledReg, elemScale);
- break;
-
- case 2:
- // mov[zs]x eax, word ptr ELEMADDR
- X86EmitOp(pArrayOpScript->m_signed ? 0xbf0f : 0xb70f, kEAX, elemBaseReg, elemOfs, elemScaledReg, elemScale);
- break;
-
- case 4:
- if (pArrayOpScript->m_flags & ArrayOpScript::ISFPUTYPE)
- {
-#ifdef TARGET_AMD64
- // movss xmm0, dword ptr ELEMADDR
- Emit8(0xf3);
- X86EmitOp(0x100f, (X86Reg)0, elemBaseReg, elemOfs, elemScaledReg, elemScale);
-#else // !TARGET_AMD64
- // fld dword ptr ELEMADDR
- X86EmitOp(0xd9, (X86Reg)0, elemBaseReg, elemOfs, elemScaledReg, elemScale);
-#endif // !TARGET_AMD64
- }
- else
- {
- // mov eax, ELEMADDR
- X86EmitOp(0x8b, kEAX, elemBaseReg, elemOfs, elemScaledReg, elemScale);
- }
- break;
-
- case 8:
- if (pArrayOpScript->m_flags & ArrayOpScript::ISFPUTYPE)
- {
-#ifdef TARGET_AMD64
- // movsd xmm0, qword ptr ELEMADDR
- Emit8(0xf2);
- X86EmitOp(0x100f, (X86Reg)0, elemBaseReg, elemOfs, elemScaledReg, elemScale);
-#else // !TARGET_AMD64
- // fld qword ptr ELEMADDR
- X86EmitOp(0xdd, (X86Reg)0, elemBaseReg, elemOfs, elemScaledReg, elemScale);
-#endif // !TARGET_AMD64
- }
- else
- {
- // mov eax, ELEMADDR
- X86EmitOp(0x8b, kEAX, elemBaseReg, elemOfs, elemScaledReg, elemScale AMD64_ARG(k64BitOp));
-#ifdef TARGET_X86
- // mov edx, ELEMADDR + 4
- X86EmitOp(0x8b, kEDX, elemBaseReg, elemOfs + 4, elemScaledReg, elemScale);
-#endif
- }
- break;
-
- default:
- _ASSERTE(0);
- }
- }
-
- break;
-
- case ArrayOpScript::STORE:
-
- switch (pArrayOpScript->m_elemsize)
- {
- case 1:
- // mov SCRATCH, [esp + valoffset]
- kValueReg = LoadArrayOpArg(pArrayOpScript->m_fValLoc, this, SCRATCH_REGISTER_X86REG, ofsadjust);
- // mov byte ptr ELEMADDR, SCRATCH.b
- X86EmitOp(0x88, kValueReg, elemBaseReg, elemOfs, elemScaledReg, elemScale);
- break;
- case 2:
- // mov SCRATCH, [esp + valoffset]
- kValueReg = LoadArrayOpArg(pArrayOpScript->m_fValLoc, this, SCRATCH_REGISTER_X86REG, ofsadjust);
- // mov word ptr ELEMADDR, SCRATCH.w
- Emit8(0x66);
- X86EmitOp(0x89, kValueReg, elemBaseReg, elemOfs, elemScaledReg, elemScale);
- break;
- case 4:
-#ifndef TARGET_AMD64
- if (pArrayOpScript->m_flags & ArrayOpScript::NEEDSWRITEBARRIER)
- {
- // mov SCRATCH, [esp + valoffset]
- kValueReg = LoadArrayOpArg(pArrayOpScript->m_fValLoc, this, SCRATCH_REGISTER_X86REG, ofsadjust);
-
- _ASSERTE(SCRATCH_REGISTER_X86REG == kEAX); // value to store is already in EAX where we want it.
- // lea edx, ELEMADDR
- X86EmitOp(0x8d, kEDX, elemBaseReg, elemOfs, elemScaledReg, elemScale);
-
- // call JIT_Writeable_Thunks_Buf.WriteBarrierReg[0] (== EAX)
- X86EmitCall(NewExternalCodeLabel((LPVOID) GetWriteBarrierCodeLocation(&JIT_WriteBarrierEAX)), 0);
- }
- else
-#else // TARGET_AMD64
- if (pArrayOpScript->m_flags & ArrayOpScript::ISFPUTYPE)
- {
- if (!TransitionBlock::IsStackArgumentOffset(pArrayOpScript->m_fValLoc))
- {
- kValueReg = (X86Reg)TransitionBlock::GetArgumentIndexFromOffset(pArrayOpScript->m_fValLoc);
- }
- else
- {
- kValueReg = (X86Reg)0; // xmm0
-
- // movss xmm0, dword ptr [rsp+??]
- Emit8(0xf3);
- X86EmitOp(0x100f, kValueReg, (X86Reg)4 /*rsp*/, ofsadjust + pArrayOpScript->m_fValLoc);
- }
-
- // movss dword ptr ELEMADDR, xmm?
- Emit8(0xf3);
- X86EmitOp(0x110f, kValueReg, elemBaseReg, elemOfs, elemScaledReg, elemScale);
- }
- else
-#endif // TARGET_AMD64
- {
- // mov SCRATCH, [esp + valoffset]
- kValueReg = LoadArrayOpArg(pArrayOpScript->m_fValLoc, this, SCRATCH_REGISTER_X86REG, ofsadjust AMD64_ARG(k32BitOp));
-
- // mov ELEMADDR, SCRATCH
- X86EmitOp(0x89, kValueReg, elemBaseReg, elemOfs, elemScaledReg, elemScale);
- }
- break;
-
- case 8:
-
- if (!(pArrayOpScript->m_flags & ArrayOpScript::NEEDSWRITEBARRIER))
- {
-#ifdef TARGET_AMD64
- if (pArrayOpScript->m_flags & ArrayOpScript::ISFPUTYPE)
- {
- if (!TransitionBlock::IsStackArgumentOffset(pArrayOpScript->m_fValLoc))
- {
- kValueReg = (X86Reg)TransitionBlock::GetArgumentIndexFromOffset(pArrayOpScript->m_fValLoc);
- }
- else
- {
- kValueReg = (X86Reg)0; // xmm0
-
- // movsd xmm0, qword ptr [rsp+??]
- Emit8(0xf2);
- X86EmitOp(0x100f, kValueReg, (X86Reg)4 /*rsp*/, ofsadjust + pArrayOpScript->m_fValLoc);
- }
-
- // movsd qword ptr ELEMADDR, xmm?
- Emit8(0xf2);
- X86EmitOp(0x110f, kValueReg, elemBaseReg, elemOfs, elemScaledReg, elemScale);
- }
- else
- {
- // mov SCRATCH, [esp + valoffset]
- kValueReg = LoadArrayOpArg(pArrayOpScript->m_fValLoc, this, SCRATCH_REGISTER_X86REG, ofsadjust);
-
- // mov ELEMADDR, SCRATCH
- X86EmitOp(0x89, kValueReg, elemBaseReg, elemOfs, elemScaledReg, elemScale, k64BitOp);
- }
-#else // !TARGET_AMD64
- _ASSERTE(TransitionBlock::IsStackArgumentOffset(pArrayOpScript->m_fValLoc)); // on x86, value will never get a register: so too lazy to implement that case
- // mov SCRATCH, [esp + valoffset]
- X86EmitEspOffset(0x8b, SCRATCH_REGISTER_X86REG, pArrayOpScript->m_fValLoc + ofsadjust);
- // mov ELEMADDR, SCRATCH
- X86EmitOp(0x89, SCRATCH_REGISTER_X86REG, elemBaseReg, elemOfs, elemScaledReg, elemScale);
-
- _ASSERTE(TransitionBlock::IsStackArgumentOffset(pArrayOpScript->m_fValLoc)); // on x86, value will never get a register: so too lazy to implement that case
- // mov SCRATCH, [esp + valoffset + 4]
- X86EmitEspOffset(0x8b, SCRATCH_REGISTER_X86REG, pArrayOpScript->m_fValLoc + ofsadjust + 4);
- // mov ELEMADDR+4, SCRATCH
- X86EmitOp(0x89, SCRATCH_REGISTER_X86REG, elemBaseReg, elemOfs+4, elemScaledReg, elemScale);
-#endif // !TARGET_AMD64
- break;
- }
-#ifdef TARGET_AMD64
- else
- {
- _ASSERTE(SCRATCH_REGISTER_X86REG == kEAX); // value to store is already in EAX where we want it.
- // lea rcx, ELEMADDR
- X86EmitOp(0x8d, kRCX, elemBaseReg, elemOfs, elemScaledReg, elemScale, k64BitOp);
-
- // mov rdx, [rsp + valoffset]
- kValueReg = LoadArrayOpArg(pArrayOpScript->m_fValLoc, this, kRDX, ofsadjust);
- _ASSERT(kRCX != kValueReg);
- if (kRDX != kValueReg)
- X86EmitR2ROp(0x8b, kRDX, kValueReg);
-
- _ASSERTE(fNeedScratchArea);
- X86EmitCall(NewExternalCodeLabel((PVOID)JIT_WriteBarrier), 0);
- break;
- }
-#endif // TARGET_AMD64
- // FALL THROUGH (on x86)
- default:
- // Ensure that these registers have been saved!
- _ASSERTE(fSavedESI && fSavedEDI);
-
-#ifdef TARGET_AMD64
- // mov rsi, [rsp + valoffset]
- kValueReg = LoadArrayOpArg(pArrayOpScript->m_fValLoc, this, kRSI, ofsadjust);
- if (kRSI != kValueReg)
- X86EmitR2ROp(0x8b, kRSI, kValueReg);
-#else // !TARGET_AMD64
- _ASSERTE(TransitionBlock::IsStackArgumentOffset(pArrayOpScript->m_fValLoc));
- // lea esi, [esp + valoffset]
- X86EmitEspOffset(0x8d, kESI, pArrayOpScript->m_fValLoc + ofsadjust);
-#endif // !TARGET_AMD64
-
- // lea edi, ELEMADDR
- X86EmitOp(0x8d, kEDI, elemBaseReg, elemOfs, elemScaledReg, elemScale AMD64_ARG(k64BitOp));
- goto COPY_VALUE_CLASS;
- }
- break;
-
- default:
- _ASSERTE(0);
- }
-
- EmitLabel(Epilog);
-
-#ifdef TARGET_AMD64
- if (fNeedPrologue)
- {
- if (fNeedScratchArea)
- {
- // Throw away scratch area
- X86EmitAddEsp(sizeof(ArgumentRegisters) + 0x8);
- }
-
- if (fSavedEDI)
- X86EmitPopReg(kRDI);
-
- if (fSavedESI)
- X86EmitPopReg(kRSI);
- }
-
- X86EmitReturn(0);
-#else // !TARGET_AMD64
- // Restore the callee-saved registers
- X86EmitPopReg(kFactorReg);
- X86EmitPopReg(kTotalReg);
-
-#ifndef UNIX_X86_ABI
- // ret N
- X86EmitReturn(pArrayOpScript->m_cbretpop);
-#else
- X86EmitReturn(0);
-#endif
-#endif // !TARGET_AMD64
-
- // Exception points must clean up the stack for all those extra args.
- // kFactorReg and kTotalReg will be popped by the jump targets.
-
- void *pvExceptionThrowFn;
-
-#if defined(TARGET_AMD64)
-#define ARRAYOP_EXCEPTION_HELPERS(base) { (PVOID)base, (PVOID)base##_RSIRDI, (PVOID)base##_ScratchArea, (PVOID)base##_RSIRDI_ScratchArea }
- static void *rgNullExceptionHelpers[] = ARRAYOP_EXCEPTION_HELPERS(ArrayOpStubNullException);
- static void *rgRangeExceptionHelpers[] = ARRAYOP_EXCEPTION_HELPERS(ArrayOpStubRangeException);
- static void *rgTypeMismatchExceptionHelpers[] = ARRAYOP_EXCEPTION_HELPERS(ArrayOpStubTypeMismatchException);
-#undef ARRAYOP_EXCEPTION_HELPERS
-
- UINT iExceptionHelper = (fNeedRSIRDI ? 1 : 0) + (fNeedScratchArea ? 2 : 0);
-#endif // defined(TARGET_AMD64)
-
- EmitLabel(Inner_nullexception);
-
-#ifndef TARGET_AMD64
- pvExceptionThrowFn = (LPVOID)ArrayOpStubNullException;
-
- Emit8(0xb8); // mov EAX,
- Emit32(pArrayOpScript->m_cbretpop);
-#else //TARGET_AMD64
- pvExceptionThrowFn = rgNullExceptionHelpers[iExceptionHelper];
-#endif //!TARGET_AMD64
- X86EmitNearJump(NewExternalCodeLabel(pvExceptionThrowFn));
-
- EmitLabel(Inner_rangeexception);
-#ifndef TARGET_AMD64
- pvExceptionThrowFn = (LPVOID)ArrayOpStubRangeException;
- Emit8(0xb8); // mov EAX,
- Emit32(pArrayOpScript->m_cbretpop);
-#else //TARGET_AMD64
- pvExceptionThrowFn = rgRangeExceptionHelpers[iExceptionHelper];
-#endif //!TARGET_AMD64
- X86EmitNearJump(NewExternalCodeLabel(pvExceptionThrowFn));
-
- if (Inner_typeMismatchexception != NULL)
- {
- EmitLabel(Inner_typeMismatchexception);
-#ifndef TARGET_AMD64
- pvExceptionThrowFn = (LPVOID)ArrayOpStubTypeMismatchException;
- Emit8(0xb8); // mov EAX,
- Emit32(pArrayOpScript->m_cbretpop);
-#else //TARGET_AMD64
- pvExceptionThrowFn = rgTypeMismatchExceptionHelpers[iExceptionHelper];
-#endif //!TARGET_AMD64
- X86EmitNearJump(NewExternalCodeLabel(pvExceptionThrowFn));
- }
-}
-#ifdef _PREFAST_
-#pragma warning(pop)
-#endif
-
-#endif // !FEATURE_ARRAYSTUB_AS_IL
-
#if !defined(FEATURE_STUBS_AS_IL)
//===========================================================================
// Emits code to break into debugger
diff --git a/src/coreclr/vm/i386/stublinkerx86.h b/src/coreclr/vm/i386/stublinkerx86.h
index 35aec1598fd559..38cde92fc9ffd0 100644
--- a/src/coreclr/vm/i386/stublinkerx86.h
+++ b/src/coreclr/vm/i386/stublinkerx86.h
@@ -6,7 +6,6 @@
#include "stublink.h"
-struct ArrayOpScript;
class MetaSig;
extern PCODE GetPreStubEntryPoint();
@@ -399,15 +398,6 @@ class StubLinkerCPU : public StubLinker
VOID EmitShuffleThunk(struct ShuffleEntry *pShuffleEntryArray);
-#ifndef FEATURE_ARRAYSTUB_AS_IL
- //===========================================================================
- // Emits code to do an array operation.
- VOID EmitArrayOpStub(const ArrayOpScript*);
-
- //Worker function to emit throw helpers for array ops.
- VOID EmitArrayOpStubThrow(unsigned exConst, unsigned cbRetArg);
-#endif
-
#ifndef FEATURE_STUBS_AS_IL
//===========================================================================
// Emits code to break into debugger
diff --git a/src/coreclr/vm/ilstubcache.cpp b/src/coreclr/vm/ilstubcache.cpp
index 1d8d14456a1f0b..8d3c4fe20b27f1 100644
--- a/src/coreclr/vm/ilstubcache.cpp
+++ b/src/coreclr/vm/ilstubcache.cpp
@@ -146,9 +146,7 @@ namespace
case DynamicMethodDesc::StubNativeToCLRInterop: return "IL_STUB_ReversePInvoke";
case DynamicMethodDesc::StubCOMToCLRInterop: return "IL_STUB_COMtoCLR";
case DynamicMethodDesc::StubStructMarshalInterop: return "IL_STUB_StructMarshal";
-#ifdef FEATURE_ARRAYSTUB_AS_IL
case DynamicMethodDesc::StubArrayOp: return "IL_STUB_Array";
-#endif
#ifdef FEATURE_MULTICASTSTUB_AS_IL
case DynamicMethodDesc::StubMulticastDelegate: return "IL_STUB_MulticastDelegate_Invoke";
#endif
@@ -236,13 +234,11 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa
#endif // _DEBUG
pMD->m_pResolver = new (pMD->m_pResolver) ILStubResolver();
-#ifdef FEATURE_ARRAYSTUB_AS_IL
if (SF_IsArrayOpStub(dwStubFlags))
{
pMD->SetILStubType(DynamicMethodDesc::StubArrayOp);
}
else
-#endif
#ifdef FEATURE_MULTICASTSTUB_AS_IL
if (SF_IsMulticastDelegateStub(dwStubFlags))
{
@@ -300,6 +296,11 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa
pMD->SetILStubType(DynamicMethodDesc::StubStructMarshalInterop);
}
else
+ if (SF_IsVirtualStaticMethodDispatchStub(dwStubFlags))
+ {
+ pMD->SetILStubType(DynamicMethodDesc::StubVirtualStaticMethodDispatch);
+ }
+ else
{
// mark certain types of stub MDs with random flags so ILStubManager recognizes them
if (SF_IsReverseStub(dwStubFlags))
@@ -320,13 +321,7 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa
}
}
- if (SF_IsVirtualStaticMethodDispatchStub(dwStubFlags))
- {
- pMD->SetILStubType(DynamicMethodDesc::StubVirtualStaticMethodDispatch);
- }
-
// if we made it this far, we can set a more descriptive stub name
-#ifdef FEATURE_ARRAYSTUB_AS_IL
if (SF_IsArrayOpStub(dwStubFlags))
{
switch(dwStubFlags)
@@ -341,7 +336,6 @@ MethodDesc* ILStubCache::CreateNewMethodDesc(LoaderHeap* pCreationHeap, MethodTa
}
}
else
-#endif
{
pMD->m_pszMethodName = GetStubMethodName(pMD->GetILStubType());
}
diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp
index 95b242b55fc0aa..66d46b10c0c9e3 100644
--- a/src/coreclr/vm/jithelpers.cpp
+++ b/src/coreclr/vm/jithelpers.cpp
@@ -2143,29 +2143,6 @@ HCIMPLEND
#include
-//===========================================================================
-// This routine is called if the Array store needs a frame constructed
-// in order to do the array check. It should only be called from
-// the array store check helpers.
-
-HCIMPL2(LPVOID, ArrayStoreCheck, Object** pElement, PtrArray** pArray)
-{
- FCALL_CONTRACT;
-
- HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_2(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, *pElement, *pArray);
-
- GCStress::MaybeTrigger();
-
- // call "Core" version directly since all the callers do the "NoGC" call first and that checks the cache
- if (!ObjIsInstanceOfCore(*pElement, (*pArray)->GetArrayElementTypeHandle()))
- COMPlusThrow(kArrayTypeMismatchException);
-
- HELPER_METHOD_FRAME_END();
-
- return (LPVOID)0; // Used to aid epilog walker
-}
-HCIMPLEND
-
//========================================================================
//
// VALUETYPE/BYREF HELPERS
diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h
index 488015c37d2d86..ee84883a9a584a 100644
--- a/src/coreclr/vm/jitinterface.h
+++ b/src/coreclr/vm/jitinterface.h
@@ -1069,8 +1069,6 @@ BOOL OnGcCoverageInterrupt(PT_CONTEXT regs);
void DoGcStress (PT_CONTEXT regs, NativeCodeVersion nativeCodeVersion);
#endif //HAVE_GCCOVER
-EXTERN_C FCDECL2(LPVOID, ArrayStoreCheck, Object** pElement, PtrArray** pArray);
-
// ppPinnedString: If the string is pinned (e.g. allocated in frozen heap),
// the pointer to the pinned string is returned in *ppPinnedPointer. ppPinnedPointer == nullptr
// means that the caller does not care whether the string is pinned or not.
diff --git a/src/coreclr/vm/method.hpp b/src/coreclr/vm/method.hpp
index 4642d8d8769da7..488520f2ec3446 100644
--- a/src/coreclr/vm/method.hpp
+++ b/src/coreclr/vm/method.hpp
@@ -2432,9 +2432,7 @@ class DynamicMethodDesc : public StoredSigMethodDesc
StubNativeToCLRInterop,
StubCOMToCLRInterop,
StubStructMarshalInterop,
-#ifdef FEATURE_ARRAYSTUB_AS_IL
StubArrayOp,
-#endif
#ifdef FEATURE_MULTICASTSTUB_AS_IL
StubMulticastDelegate,
#endif
@@ -2500,6 +2498,7 @@ class DynamicMethodDesc : public StoredSigMethodDesc
void SetILStubType(ILStubType type)
{
_ASSERTE(HasFlags(FlagIsILStub));
+ m_dwExtendedFlags &= ~ILStubTypeMask;
m_dwExtendedFlags |= type;
}
diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h
index 412711f8a33bc8..59c3e300b73058 100644
--- a/src/coreclr/vm/object.h
+++ b/src/coreclr/vm/object.h
@@ -732,9 +732,7 @@ class PtrArray : public ArrayBase
}
friend class StubLinkerCPU;
-#ifdef FEATURE_ARRAYSTUB_AS_IL
friend class ArrayOpLinker;
-#endif
public:
OBJECTREF m_Array[1];
};
diff --git a/src/coreclr/vm/typedesc.h b/src/coreclr/vm/typedesc.h
index 94f7e99517cc3c..e8d7526bd0b16c 100644
--- a/src/coreclr/vm/typedesc.h
+++ b/src/coreclr/vm/typedesc.h
@@ -256,9 +256,7 @@ class ParamTypeDesc : public TypeDesc {
friend class StubLinkerCPU;
-#ifdef FEATURE_ARRAYSTUB_AS_IL
friend class ArrayOpLinker;
-#endif
protected:
// the m_typeAndFlags field in TypeDesc tell what kind of parameterized type we have