summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jit/compiler.h3
-rwxr-xr-xsrc/jit/ee_il_dll.cpp30
-rw-r--r--[-rwxr-xr-x]src/jit/importer.cpp267
-rw-r--r--src/jit/instr.cpp3
-rwxr-xr-xsrc/jit/lower.cpp3
-rw-r--r--tests/src/JIT/Methodical/Arrays/misc/_il_dbginitializearray.ilproj23
-rw-r--r--tests/src/JIT/Methodical/Arrays/misc/_il_relinitializearray.ilproj22
-rw-r--r--tests/src/JIT/Methodical/Arrays/misc/initializearray.il640
8 files changed, 934 insertions, 57 deletions
diff --git a/src/jit/compiler.h b/src/jit/compiler.h
index 2a0d4eed72..81a2bd00cd 100644
--- a/src/jit/compiler.h
+++ b/src/jit/compiler.h
@@ -6397,7 +6397,10 @@ public :
CORINFO_EE_INFO * eeGetEEInfo();
+ // Gets the offset of a SDArray's first element
unsigned eeGetArrayDataOffset(var_types type);
+ // Gets the offset of a MDArray's first element
+ unsigned eeGetMDArrayDataOffset(var_types type, unsigned rank);
GenTreePtr eeGetPInvokeCookie(CORINFO_SIG_INFO *szMetaSig);
diff --git a/src/jit/ee_il_dll.cpp b/src/jit/ee_il_dll.cpp
index 787c311368..f51e4521e3 100755
--- a/src/jit/ee_il_dll.cpp
+++ b/src/jit/ee_il_dll.cpp
@@ -494,7 +494,14 @@ GenTreePtr Compiler::eeGetPInvokeCookie(CORINFO_SIG_INFO *szMetaSig)
return gtNewIconEmbHndNode(cookie, pCookie, GTF_ICON_PINVKI_HDL);
}
-/*****************************************************************************/
+//------------------------------------------------------------------------
+// eeGetArrayDataOffset: Gets the offset of a SDArray's first element
+//
+// Arguments:
+// type - The array element type
+//
+// Return Value:
+// The offset to the first array element.
unsigned Compiler::eeGetArrayDataOffset(var_types type)
{
@@ -502,6 +509,27 @@ unsigned Compiler::eeGetArrayDataOffset(var_types type)
: offsetof(CORINFO_Array, u1Elems);
}
+//------------------------------------------------------------------------
+// eeGetMDArrayDataOffset: Gets the offset of a MDArray's first element
+//
+// Arguments:
+// type - The array element type
+// rank - The array rank
+//
+// Return Value:
+// The offset to the first array element.
+//
+// Assumptions:
+// The rank should be greater than 0.
+
+unsigned Compiler::eeGetMDArrayDataOffset(var_types type, unsigned rank)
+{
+ assert(rank > 0);
+ // Note that below we're specifically using genTypeSize(TYP_INT) because array
+ // indices are not native int.
+ return eeGetArrayDataOffset(type) + 2 * genTypeSize(TYP_INT) * rank;
+}
+
/*****************************************************************************/
void Compiler::eeGetStmtOffsets()
diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp
index 5a3bcf852b..4ca25255b5 100755..100644
--- a/src/jit/importer.cpp
+++ b/src/jit/importer.cpp
@@ -2666,23 +2666,30 @@ BOOL Compiler::impLocAllocOnStack()
return(FALSE);
}
-/*****************************************************************************/
+//------------------------------------------------------------------------
+// impInitializeArrayIntrinsic: Attempts to replace a call to InitializeArray
+// with a GT_COPYBLK node.
+//
+// Arguments:
+// sig - The InitializeArray signature.
+//
+// Return Value:
+// A pointer to the newly created GT_COPYBLK node if the replacement succeeds or
+// nullptr otherwise.
+//
+// Notes:
+// The function recognizes the following IL pattern:
+// ldc <length> or a list of ldc <lower bound>/<length>
+// newarr or newobj
+// dup
+// ldtoken <field handle>
+// call InitializeArray
+// The lower bounds need not be constant except when the array rank is 1.
+// The function recognizes all kinds of arrays thus enabling a small runtime
+// such as CoreRT to skip providing an implementation for InitializeArray.
GenTreePtr Compiler::impInitializeArrayIntrinsic(CORINFO_SIG_INFO * sig)
{
- //
- // The IL for array initialization looks like the following:
- //
- // ldc <number of elements>
- // newarr
- // dup
- // ldtoken <field handle>
- // call InitializeArray
- //
- // We will try to implement it using a GT_COPYBLK node to avoid the
- // runtime call to the helper.
- //
-
assert(sig->numArgs == 2);
GenTreePtr fieldTokenNode = impStackTop(0).val;
@@ -2767,6 +2774,9 @@ GenTreePtr Compiler::impInitializeArrayIntrinsic(CORINFO_SIG_INFO * sig)
//
// Verify that it is one of the new array helpers.
//
+
+ bool isMDArray = false;
+
if (newArrayCall->gtCall.gtCallMethHnd != eeFindHelper(CORINFO_HELP_NEWARR_1_DIRECT) &&
newArrayCall->gtCall.gtCallMethHnd != eeFindHelper(CORINFO_HELP_NEWARR_1_OBJ) &&
newArrayCall->gtCall.gtCallMethHnd != eeFindHelper(CORINFO_HELP_NEWARR_1_VC) &&
@@ -2776,57 +2786,195 @@ GenTreePtr Compiler::impInitializeArrayIntrinsic(CORINFO_SIG_INFO * sig)
#endif
)
{
- //
- // In order to simplify the code, we won't support the multi-dim
- // case. Instead we simply return NULL, and the caller will insert
- // a run-time call to the helper. Note that we can't assert
- // failure here, because this is a valid case.
- //
+ if (newArrayCall->gtCall.gtCallMethHnd != eeFindHelper(CORINFO_HELP_NEW_MDARR_NONVARARG))
+ return nullptr;
- return NULL;
+ isMDArray = true;
}
+ CORINFO_CLASS_HANDLE arrayClsHnd = (CORINFO_CLASS_HANDLE) newArrayCall->gtCall.compileTimeHelperArgumentHandle;
//
- // Make sure there are exactly two arguments: the array class and
- // the number of elements.
+ // Make sure we found a compile time handle to the array
//
- GenTreePtr arrayLengthNode;
+ if (!arrayClsHnd)
+ return nullptr;
+
+ unsigned rank;
+ S_UINT32 numElements;
- GenTreeArgList* args = newArrayCall->gtCall.gtCallArgs;
-#ifdef FEATURE_READYTORUN_COMPILER
- if (newArrayCall->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_READYTORUN_NEWARR_1))
+ if (isMDArray)
{
- // Array length is 1st argument for readytorun helper
- arrayLengthNode = args->Current();
+ rank = info.compCompHnd->getArrayRank(arrayClsHnd);
+
+ if (rank == 0)
+ return nullptr;
+
+ GenTreeArgList* tokenArg = newArrayCall->gtCall.gtCallArgs;
+ assert(tokenArg != nullptr);
+ GenTreeArgList* numArgsArg = tokenArg->Rest();
+ assert(numArgsArg != nullptr);
+ GenTreeArgList* argsArg = numArgsArg->Rest();
+ assert(argsArg != nullptr);
+
+ //
+ // The number of arguments should be a constant between 1 and 64. The rank can't be 0
+ // so at least one length must be present and the rank can't exceed 32 so there can
+ // be at most 64 arguments - 32 lengths and 32 lower bounds.
+ //
+
+ if ((!numArgsArg->Current()->IsCnsIntOrI()) ||
+ (numArgsArg->Current()->AsIntCon()->IconValue() < 1) ||
+ (numArgsArg->Current()->AsIntCon()->IconValue() > 64))
+ {
+ return nullptr;
+ }
+
+ unsigned numArgs = static_cast<unsigned>(numArgsArg->Current()->AsIntCon()->IconValue());
+ bool lowerBoundsSpecified;
+
+ if (numArgs == rank * 2)
+ {
+ lowerBoundsSpecified = true;
+ }
+ else if (numArgs == rank)
+ {
+ lowerBoundsSpecified = false;
+
+ //
+ // If the rank is 1 and a lower bound isn't specified then the runtime creates
+ // a SDArray. Note that even if a lower bound is specified it can be 0 and then
+ // we get a SDArray as well, see the for loop below.
+ //
+
+ if (rank == 1)
+ isMDArray = false;
+ }
+ else
+ {
+ return nullptr;
+ }
+
+ //
+ // The rank is known to be at least 1 so we can start with numElements being 1
+ // to avoid the need to special case the first dimension.
+ //
+
+ numElements = S_UINT32(1);
+
+ struct Match
+ {
+ static bool IsArgsFieldInit(GenTree* tree, unsigned index, unsigned lvaNewObjArrayArgs)
+ {
+ return (tree->OperGet() == GT_ASG) &&
+ IsArgsFieldIndir(tree->gtGetOp1(), index, lvaNewObjArrayArgs) &&
+ IsArgsAddr(tree->gtGetOp1()->gtGetOp1()->gtGetOp1(), lvaNewObjArrayArgs);
+ }
+
+ static bool IsArgsFieldIndir(GenTree* tree, unsigned index, unsigned lvaNewObjArrayArgs)
+ {
+ return (tree->OperGet() == GT_IND) &&
+ (tree->gtGetOp1()->OperGet() == GT_ADD) &&
+ (tree->gtGetOp1()->gtGetOp2()->IsIntegralConst(sizeof(INT32) * index)) &&
+ IsArgsAddr(tree->gtGetOp1()->gtGetOp1(), lvaNewObjArrayArgs);
+ }
+
+ static bool IsArgsAddr(GenTree* tree, unsigned lvaNewObjArrayArgs)
+ {
+ return (tree->OperGet() == GT_ADDR) &&
+ (tree->gtGetOp1()->OperGet() == GT_LCL_VAR) &&
+ (tree->gtGetOp1()->AsLclVar()->GetLclNum() == lvaNewObjArrayArgs);
+ }
+
+ static bool IsComma(GenTree* tree)
+ {
+ return (tree != nullptr) &&
+ (tree->OperGet() == GT_COMMA);
+ }
+ };
+
+ int argIndex = 0;
+ GenTree* comma;
+
+ for (comma = argsArg->Current(); Match::IsComma(comma); comma = comma->gtGetOp2())
+ {
+ if (lowerBoundsSpecified)
+ {
+ //
+ // In general lower bounds can be ignored because they're not needed to
+ // calculate the total number of elements. But for single dimensional arrays
+ // we need to know if the lower bound is 0 because in this case the runtime
+ // creates a SDArray and this affects the way the array data offset is calculated.
+ //
+
+ if (rank == 1)
+ {
+ GenTree* lowerBoundAssign = comma->gtGetOp1();
+ assert(Match::IsArgsFieldInit(lowerBoundAssign, argIndex, lvaNewObjArrayArgs));
+ GenTree* lowerBoundNode = lowerBoundAssign->gtGetOp2();
+
+ if (lowerBoundNode->IsIntegralConst(0))
+ isMDArray = false;
+ }
+
+ comma = comma->gtGetOp2();
+ argIndex++;
+ }
+
+ GenTree* lengthNodeAssign = comma->gtGetOp1();
+ assert(Match::IsArgsFieldInit(lengthNodeAssign, argIndex, lvaNewObjArrayArgs));
+ GenTree* lengthNode = lengthNodeAssign->gtGetOp2();
+
+ if (!lengthNode->IsCnsIntOrI())
+ return nullptr;
+
+ numElements *= S_SIZE_T(lengthNode->AsIntCon()->IconValue());
+ argIndex++;
+ }
+
+ assert((comma != nullptr) && Match::IsArgsAddr(comma, lvaNewObjArrayArgs));
+
+ if (argIndex != numArgs)
+ return nullptr;
}
else
-#endif
{
- // Array length is 2nd argument for regular helper
- arrayLengthNode = args->Rest()->Current();
- }
+ //
+ // Make sure there are exactly two arguments: the array class and
+ // the number of elements.
+ //
- //
- // Make sure that the number of elements look valid.
- //
- if (arrayLengthNode->gtOper != GT_CNS_INT)
- {
- return NULL;
- }
+ GenTreePtr arrayLengthNode;
- S_UINT32 numElements = S_SIZE_T(arrayLengthNode->gtIntCon.gtIconVal);
- CORINFO_CLASS_HANDLE arrayClsHnd = (CORINFO_CLASS_HANDLE) newArrayCall->gtCall.compileTimeHelperArgumentHandle;
+ GenTreeArgList* args = newArrayCall->gtCall.gtCallArgs;
+#ifdef FEATURE_READYTORUN_COMPILER
+ if (newArrayCall->gtCall.gtCallMethHnd == eeFindHelper(CORINFO_HELP_READYTORUN_NEWARR_1))
+ {
+ // Array length is 1st argument for readytorun helper
+ arrayLengthNode = args->Current();
+ }
+ else
+#endif
+ {
+ // Array length is 2nd argument for regular helper
+ arrayLengthNode = args->Rest()->Current();
+ }
- //
- // Make sure we found a compile time handle to the array
- //
+ //
+ // Make sure that the number of elements look valid.
+ //
+ if (arrayLengthNode->gtOper != GT_CNS_INT)
+ {
+ return NULL;
+ }
- if (!arrayClsHnd ||
- !info.compCompHnd->isSDArray(arrayClsHnd))
- {
- return NULL;
+ numElements = S_SIZE_T(arrayLengthNode->gtIntCon.gtIconVal);
+
+ if (!info.compCompHnd->isSDArray(arrayClsHnd))
+ {
+ return NULL;
+ }
}
CORINFO_CLASS_HANDLE elemClsHnd;
@@ -2868,10 +3016,24 @@ GenTreePtr Compiler::impInitializeArrayIntrinsic(CORINFO_SIG_INFO * sig)
impPopStack();
impPopStack();
- GenTreePtr dst = gtNewOperNode(GT_ADDR,
- TYP_BYREF,
- gtNewIndexRef(elementType, arrayLocalNode, gtNewIconNode(0)));
+ GenTreePtr dst;
+ if (isMDArray)
+ {
+ unsigned dataOffset = eeGetMDArrayDataOffset(elementType, rank);
+
+ dst = gtNewOperNode(GT_ADD,
+ TYP_BYREF,
+ arrayLocalNode,
+ gtNewIconNode(dataOffset, TYP_I_IMPL));
+ }
+ else
+ {
+ dst = gtNewOperNode(GT_ADDR,
+ TYP_BYREF,
+ gtNewIndexRef(elementType, arrayLocalNode, gtNewIconNode(0)));
+ }
+
return gtNewBlkOpNode(GT_COPYBLK,
dst, // dst
gtNewIconHandleNode((size_t) initData, GTF_ICON_STATIC_HDL), // src
@@ -4828,6 +4990,7 @@ void Compiler::impImportNewObjArray(CORINFO_RESOLVED_TOKEN* pResolvedToken,
}
node->gtFlags |= args->gtFlags & GTF_GLOB_EFFECT;
+ node->gtCall.compileTimeHelperArgumentHandle = (CORINFO_GENERIC_HANDLE)pResolvedToken->hClass;
// Remember that this basic block contains 'new' of a md array
compCurBB->bbFlags |= BBF_HAS_NEWARRAY;
diff --git a/src/jit/instr.cpp b/src/jit/instr.cpp
index 3dd10f2d2d..4fb23f662e 100644
--- a/src/jit/instr.cpp
+++ b/src/jit/instr.cpp
@@ -580,8 +580,7 @@ void CodeGen::instGetAddrMode(GenTreePtr addr,
else
*indScale = 0;
- *cns = compiler->eeGetArrayDataOffset(addr->gtArrElem.gtArrElemType)
- + 2 * sizeof(int) * addr->gtArrElem.gtArrRank;
+ *cns = compiler->eeGetMDArrayDataOffset(addr->gtArrElem.gtArrElemType, addr->gtArrElem.gtArrRank);
}
else if (addr->gtOper == GT_LEA)
{
diff --git a/src/jit/lower.cpp b/src/jit/lower.cpp
index d76ce8cd92..da34404fbd 100755
--- a/src/jit/lower.cpp
+++ b/src/jit/lower.cpp
@@ -3689,8 +3689,7 @@ Lowering::LowerArrElem(GenTree **ppTree, Compiler::fgWalkData* data)
// Generate the LEA and make it reverse evaluation, because we want to evaluate the index expression before the base.
GenTreePtr leaBase = comp->gtClone(arrObjNode);
unsigned scale = arrElem->gtArrElem.gtArrElemSize;
- // Note that below we're specifically using genTypeSize(TYP_INT) because array indices are not native int.
- unsigned offset = comp->eeGetArrayDataOffset(arrElem->gtArrElem.gtArrElemType) + 2 * genTypeSize(TYP_INT) * arrElem->gtArrElem.gtArrRank;
+ unsigned offset = comp->eeGetMDArrayDataOffset(arrElem->gtArrElem.gtArrElemType, arrElem->gtArrElem.gtArrRank);
GenTreePtr leaIndexNode = prevArrOffs;
if (!jitIsScaleIndexMul(scale))
{
diff --git a/tests/src/JIT/Methodical/Arrays/misc/_il_dbginitializearray.ilproj b/tests/src/JIT/Methodical/Arrays/misc/_il_dbginitializearray.ilproj
new file mode 100644
index 0000000000..466865d22a
--- /dev/null
+++ b/tests/src/JIT/Methodical/Arrays/misc/_il_dbginitializearray.ilproj
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+ <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+ <DebugType>Full</DebugType>
+ <Optimize>false</Optimize>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="initializearray.il" />
+ <None Include="app.config" />
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/tests/src/JIT/Methodical/Arrays/misc/_il_relinitializearray.ilproj b/tests/src/JIT/Methodical/Arrays/misc/_il_relinitializearray.ilproj
new file mode 100644
index 0000000000..689b3e00fd
--- /dev/null
+++ b/tests/src/JIT/Methodical/Arrays/misc/_il_relinitializearray.ilproj
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+ <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+ <Optimize>true</Optimize>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="initializearray.il" />
+ <None Include="app.config" />
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/tests/src/JIT/Methodical/Arrays/misc/initializearray.il b/tests/src/JIT/Methodical/Arrays/misc/initializearray.il
new file mode 100644
index 0000000000..256c2bece9
--- /dev/null
+++ b/tests/src/JIT/Methodical/Arrays/misc/initializearray.il
@@ -0,0 +1,640 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+.assembly extern mscorlib
+{
+ .publickeytoken = (B7 7A 5C 56 19 34 E0 89)
+ .ver 4:0:0:0
+}
+.assembly initializearray
+{
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+.module initializearray.exe
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003 // WINDOWS_CUI
+.corflags 0x00000001 // ILONLY
+
+.class private auto ansi beforefieldinit InitializeArray extends [mscorlib]System.Object
+{
+ .method private hidebysig static int32 Main() cil managed
+ {
+ .entrypoint
+ .maxstack 8
+
+ call bool InitializeArray::SZArray_Int64_5_ValidInitializationTest()
+ brfalse.s fail
+
+ call bool InitializeArray::SZArray_Int64_6_InvalidInitializationTest()
+ brfalse.s fail
+
+ call bool InitializeArray::MDArray_Int16_10_ValidInitializationTest()
+ brfalse.s fail
+
+ call bool InitializeArray::MDArray_Int16_0_10_ValidInitializationTest()
+ brfalse.s fail
+
+ call bool InitializeArray::MDArray_Int16_11_InvalidInitializationTest()
+ brfalse.s fail
+
+ call bool InitializeArray::MDArray_Int8_8x10_ValidInitializationTest()
+ brfalse.s fail
+
+ call bool InitializeArray::MDArray_Int8_10x10_InvalidInitializationTest()
+ brfalse.s fail
+
+ call bool InitializeArray::MDArray_Float32_4x5_ValidInitializationTest()
+ brfalse.s fail
+
+ call bool InitializeArray::MDArray_Float32_5x5_InvalidInitializationTest()
+ brfalse.s fail
+
+ call bool InitializeArray::MDArray_Int8_2_4x3_5_ValidInitializationTest()
+ brfalse.s fail
+
+ call bool InitializeArray::MDArray_Int8_2_5x3_5_InvalidInitializationTest()
+ brfalse.s fail
+
+ ldc.i4.s 100
+ ret
+
+ fail:
+ ldc.i4.s 0
+ ret
+ }
+
+ .method private hidebysig static bool SZArray_Int64_5_ValidInitializationTest() cil managed noinlining
+ {
+ .maxstack 8
+ call int64[] InitializeArray::SZArray_Initialize_Int64_5()
+ call int64[] InitializeArray::SZArray_Initialize_Int64_5_Optimized()
+ call bool InitializeArray::ArrayEquals(class [mscorlib]System.Array, class [mscorlib]System.Array)
+ ret
+ }
+
+ .method private hidebysig static int64[] SZArray_Initialize_Int64_5() cil managed noinlining nooptimization
+ {
+ .maxstack 8
+ ldc.i4 5
+ newarr int64
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize40' 'ArrayInitializers'::'InitializerField40'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ ret
+ }
+
+ .method private hidebysig static int64[] SZArray_Initialize_Int64_5_Optimized() cil managed noinlining
+ {
+ .maxstack 8
+ ldc.i4 5
+ newarr int64
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize40' 'ArrayInitializers'::'InitializerField40'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ ret
+ }
+
+ .method private hidebysig static bool SZArray_Int64_6_InvalidInitializationTest() cil managed noinlining
+ {
+ .maxstack 8
+ .locals init (int32 exitCode)
+ .try
+ {
+ ldc.i4 11
+ newarr int64
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize20' 'ArrayInitializers'::'InitializerField20'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ pop
+ ldc.i4 0
+ stloc.0
+ leave exit
+ }
+ catch [mscorlib]System.ArgumentException
+ {
+ pop
+ ldc.i4 1
+ stloc.0
+ leave exit
+ }
+
+ exit:
+ ldloc.0
+ ret
+ }
+
+ .method private hidebysig static bool MDArray_Int16_10_ValidInitializationTest() cil managed noinlining
+ {
+ .maxstack 8
+ call int16[0...] InitializeArray::MDArray_Initialize_Int16_10()
+ call int16[0...] InitializeArray::MDArray_Initialize_Int16_10_Optimized()
+ call bool InitializeArray::ArrayEquals(class [mscorlib]System.Array, class [mscorlib]System.Array)
+ ret
+ }
+
+ .method private hidebysig static int16[0...] MDArray_Initialize_Int16_10() cil managed noinlining nooptimization
+ {
+ .maxstack 8
+ ldc.i4 10
+ newobj instance void int16[0...]::.ctor(int32)
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize20' 'ArrayInitializers'::'InitializerField20'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ ret
+ }
+
+ .method private hidebysig static int16[0...] MDArray_Initialize_Int16_10_Optimized() cil managed noinlining
+ {
+ .maxstack 8
+ ldc.i4 10
+ newobj instance void int16[0...]::.ctor(int32)
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize20' 'ArrayInitializers'::'InitializerField20'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ ret
+ }
+
+ .method private hidebysig static bool MDArray_Int16_11_InvalidInitializationTest() cil managed noinlining
+ {
+ .maxstack 8
+ .locals init (int32 exitCode)
+ .try
+ {
+ ldc.i4 11
+ newobj instance void int16[0...]::.ctor(int32)
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize20' 'ArrayInitializers'::'InitializerField20'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ pop
+ ldc.i4 0
+ stloc.0
+ leave exit
+ }
+ catch [mscorlib]System.ArgumentException
+ {
+ pop
+ ldc.i4 1
+ stloc.0
+ leave exit
+ }
+
+ exit:
+ ldloc.0
+ ret
+ }
+
+ .method private hidebysig static bool MDArray_Int16_0_10_ValidInitializationTest() cil managed noinlining
+ {
+ .maxstack 8
+ call int16[...] InitializeArray::MDArray_Initialize_Int16_0_10()
+ call int16[...] InitializeArray::MDArray_Initialize_Int16_0_10_Optimized()
+ call bool InitializeArray::ArrayEquals(class [mscorlib]System.Array, class [mscorlib]System.Array)
+ ret
+ }
+
+ .method private hidebysig static int16[...] MDArray_Initialize_Int16_0_10() cil managed noinlining nooptimization
+ {
+ .maxstack 8
+ ldc.i4 0
+ ldc.i4 10
+ newobj instance void int16[...]::.ctor(int32, int32)
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize20' 'ArrayInitializers'::'InitializerField20'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ ret
+ }
+
+ .method private hidebysig static int16[...] MDArray_Initialize_Int16_0_10_Optimized() cil managed noinlining
+ {
+ .maxstack 8
+ ldc.i4 0
+ ldc.i4 10
+ newobj instance void int16[...]::.ctor(int32, int32)
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize20' 'ArrayInitializers'::'InitializerField20'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ ret
+ }
+
+
+ .method private hidebysig static bool MDArray_Int8_8x10_ValidInitializationTest() cil managed noinlining
+ {
+ .maxstack 8
+ call int8[0..., 0...] InitializeArray::MDArray_Initialize_Int8_8x10()
+ call int8[0..., 0...] InitializeArray::MDArray_Initialize_Int8_8x10_Optimized()
+ call bool InitializeArray::ArrayEquals(class [mscorlib]System.Array, class [mscorlib]System.Array)
+ ret
+ }
+
+ .method private hidebysig static int8[0..., 0...] MDArray_Initialize_Int8_8x10() cil managed noinlining nooptimization
+ {
+ .maxstack 8
+ ldc.i4 8
+ ldc.i4 10
+ newobj instance void int8 [0..., 0...]::.ctor(int32, int32)
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize80' 'ArrayInitializers'::'InitializerField80'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ ret
+ }
+
+ .method private hidebysig static int8[0..., 0...] MDArray_Initialize_Int8_8x10_Optimized() cil managed noinlining
+ {
+ .maxstack 8
+ ldc.i4 8
+ ldc.i4 10
+ newobj instance void int8[0..., 0...]::.ctor(int32, int32)
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize80' 'ArrayInitializers'::'InitializerField80'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ ret
+ }
+
+ .method private hidebysig static bool MDArray_Int8_10x10_InvalidInitializationTest() cil managed noinlining
+ {
+ .maxstack 8
+ .locals init (int32 exitCode)
+ .try
+ {
+ ldc.i4 10
+ ldc.i4 10
+ newobj instance void int8[0..., 0...]::.ctor(int32, int32)
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize80' 'ArrayInitializers'::'InitializerField80'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ pop
+ ldc.i4 0
+ stloc.0
+ leave exit
+ }
+ catch [mscorlib]System.ArgumentException
+ {
+ pop
+ ldc.i4 1
+ stloc.0
+ leave exit
+ }
+
+ exit:
+ ldloc.0
+ ret
+ }
+
+ .method private hidebysig static bool MDArray_Float32_4x5_ValidInitializationTest() cil managed noinlining
+ {
+ .maxstack 8
+ call float32[0..., 0...] InitializeArray::MDArray_Initialize_Float32_4x5()
+ call float32[0..., 0...] InitializeArray::MDArray_Initialize_Float32_4x5_Optimized()
+ call bool InitializeArray::ArrayEquals(class [mscorlib]System.Array, class [mscorlib]System.Array)
+ ret
+ }
+
+ .method private hidebysig static float32[0..., 0...] MDArray_Initialize_Float32_4x5_Optimized() cil managed noinlining
+ {
+ .maxstack 8
+ ldc.i4.4
+ ldc.i4.5
+ newobj instance void float32[0..., 0...]::.ctor(int32, int32)
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize80' 'ArrayInitializers'::'InitializerField80'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ ret
+ }
+
+ .method private hidebysig static float32[0..., 0...] MDArray_Initialize_Float32_4x5() cil managed noinlining nooptimization
+ {
+ .maxstack 8
+ ldc.i4 4
+ ldc.i4 5
+ newobj instance void float32[0..., 0...]::.ctor(int32, int32)
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize80' 'ArrayInitializers'::'InitializerField80'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ ret
+ }
+
+ .method private hidebysig static bool MDArray_Float32_5x5_InvalidInitializationTest() cil managed noinlining
+ {
+ .maxstack 8
+ .locals init (int32 exitCode)
+ .try
+ {
+ ldc.i4 5
+ ldc.i4 5
+ newobj instance void float32[0..., 0...]::.ctor(int32, int32)
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize80' 'ArrayInitializers'::'InitializerField80'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ pop
+ ldc.i4 0
+ stloc.0
+ leave exit
+ }
+ catch [mscorlib]System.ArgumentException
+ {
+ pop
+ ldc.i4 1
+ stloc.0
+ leave exit
+ }
+
+ exit:
+ ldloc.0
+ ret
+ }
+
+ .method private hidebysig static bool MDArray_Int8_2_4x3_5_ValidInitializationTest() cil managed noinlining
+ {
+ .maxstack 8
+ call int8[..., ...] InitializeArray::MDArray_Initialize_Int8_2_4x3_5()
+ call int8[..., ...] InitializeArray::MDArray_Initialize_Int8_2_4x3_5_Optimized()
+ call bool InitializeArray::ArrayEquals(class [mscorlib]System.Array, class [mscorlib]System.Array)
+ ret
+ }
+
+ .method private hidebysig static int8[..., ...] MDArray_Initialize_Int8_2_4x3_5() cil managed noinlining nooptimization
+ {
+ .maxstack 8
+ ldc.i4.2
+ ldc.i4.4
+ ldc.i4.3
+ ldc.i4.5
+ newobj instance void int8 [..., ...]::.ctor(int32, int32, int32, int32)
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize20' 'ArrayInitializers'::'InitializerField20'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ ret
+ }
+
+ .method private hidebysig static int8[..., ...] MDArray_Initialize_Int8_2_4x3_5_Optimized() cil managed noinlining
+ {
+ .maxstack 8
+ ldc.i4.2
+ ldc.i4.4
+ ldc.i4.3
+ ldc.i4.5
+ newobj instance void int8[..., ...]::.ctor(int32, int32, int32, int32)
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize20' 'ArrayInitializers'::'InitializerField20'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ ret
+ }
+
+ .method private hidebysig static bool MDArray_Int8_2_5x3_5_InvalidInitializationTest() cil managed noinlining
+ {
+ .maxstack 8
+ .locals init (int32 exitCode)
+ .try
+ {
+ ldc.i4.2
+ ldc.i4.5
+ ldc.i4.3
+ ldc.i4.5
+ newobj instance void int8[..., ...]::.ctor(int32, int32, int32, int32)
+ dup
+ ldtoken field valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize20' 'ArrayInitializers'::'InitializerField20'
+ call void[mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype[mscorlib] System.RuntimeFieldHandle)
+ pop
+ ldc.i4 0
+ stloc.0
+ leave exit
+ }
+ catch [mscorlib]System.ArgumentException
+ {
+ pop
+ ldc.i4 1
+ stloc.0
+ leave exit
+ }
+
+ exit:
+ ldloc.0
+ ret
+ }
+
+//
+// ArrayEquals was generated from the following C# code:
+//
+//static bool ArrayEquals(Array x, Array y)
+//{
+// if (x.Rank != y.Rank)
+// return false;
+
+// var lower = new int[x.Rank];
+// var indices = new int[x.Rank];
+// var upper = new int[x.Rank];
+
+// for (int i = 0; i < indices.Length; i++)
+// {
+// if (x.GetLowerBound(i) != y.GetLowerBound(i))
+// return false;
+// if (x.GetLength(i) != y.GetLength(i))
+// return false;
+// lower[i] = x.GetLowerBound(i);
+// indices[i] = lower[i];
+// upper[i] = lower[i] + x.GetLength(i);
+// }
+
+// while (true)
+// {
+// if (!object.Equals(x.GetValue(indices), y.GetValue(indices)))
+// return false;
+
+// int i = 0;
+// indices[i]++;
+
+// while (indices[i] >= upper[i])
+// {
+// indices[i] = lower[i];
+// i++;
+
+// if (i >= indices.Length)
+// return true;
+
+// indices[i]++;
+// }
+// }
+//}
+
+ .method private hidebysig static bool ArrayEquals(class [mscorlib]System.Array x, class [mscorlib]System.Array y) cil managed
+ {
+ .maxstack 5
+ .locals init (
+ [0] int32[] lower,
+ [1] int32[] indices,
+ [2] int32[] upper,
+ [3] int32 i,
+ [4] int32 V_4)
+ L_0000: ldarg.0
+ L_0001: callvirt instance int32 [mscorlib]System.Array::get_Rank()
+ L_0006: ldarg.1
+ L_0007: callvirt instance int32 [mscorlib]System.Array::get_Rank()
+ L_000c: beq.s L_0010
+ L_000e: ldc.i4.0
+ L_000f: ret
+ L_0010: ldarg.0
+ L_0011: callvirt instance int32 [mscorlib]System.Array::get_Rank()
+ L_0016: newarr int32
+ L_001b: stloc.0
+ L_001c: ldarg.0
+ L_001d: callvirt instance int32 [mscorlib]System.Array::get_Rank()
+ L_0022: newarr int32
+ L_0027: stloc.1
+ L_0028: ldarg.0
+ L_0029: callvirt instance int32 [mscorlib]System.Array::get_Rank()
+ L_002e: newarr int32
+ L_0033: stloc.2
+ L_0034: ldc.i4.0
+ L_0035: stloc.3
+ L_0036: br.s L_007e
+ L_0038: ldarg.0
+ L_0039: ldloc.3
+ L_003a: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
+ L_003f: ldarg.1
+ L_0040: ldloc.3
+ L_0041: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
+ L_0046: beq.s L_004a
+ L_0048: ldc.i4.0
+ L_0049: ret
+ L_004a: ldarg.0
+ L_004b: ldloc.3
+ L_004c: callvirt instance int32 [mscorlib]System.Array::GetLength(int32)
+ L_0051: ldarg.1
+ L_0052: ldloc.3
+ L_0053: callvirt instance int32 [mscorlib]System.Array::GetLength(int32)
+ L_0058: beq.s L_005c
+ L_005a: ldc.i4.0
+ L_005b: ret
+ L_005c: ldloc.0
+ L_005d: ldloc.3
+ L_005e: ldarg.0
+ L_005f: ldloc.3
+ L_0060: callvirt instance int32 [mscorlib]System.Array::GetLowerBound(int32)
+ L_0065: stelem.i4
+ L_0066: ldloc.1
+ L_0067: ldloc.3
+ L_0068: ldloc.0
+ L_0069: ldloc.3
+ L_006a: ldelem.i4
+ L_006b: stelem.i4
+ L_006c: ldloc.2
+ L_006d: ldloc.3
+ L_006e: ldloc.0
+ L_006f: ldloc.3
+ L_0070: ldelem.i4
+ L_0071: ldarg.0
+ L_0072: ldloc.3
+ L_0073: callvirt instance int32 [mscorlib]System.Array::GetLength(int32)
+ L_0078: add
+ L_0079: stelem.i4
+ L_007a: ldloc.3
+ L_007b: ldc.i4.1
+ L_007c: add
+ L_007d: stloc.3
+ L_007e: ldloc.3
+ L_007f: ldloc.1
+ L_0080: ldlen
+ L_0081: conv.i4
+ L_0082: blt.s L_0038
+ L_0084: ldarg.0
+ L_0085: ldloc.1
+ L_0086: callvirt instance object [mscorlib]System.Array::GetValue(int32[])
+ L_008b: ldarg.1
+ L_008c: ldloc.1
+ L_008d: callvirt instance object [mscorlib]System.Array::GetValue(int32[])
+ L_0092: call bool [mscorlib]System.Object::Equals(object, object)
+ L_0097: brtrue.s L_009b
+ L_0099: ldc.i4.0
+ L_009a: ret
+ L_009b: ldc.i4.0
+ L_009c: stloc.s V_4
+ L_009e: ldloc.1
+ L_009f: ldloc.s V_4
+ L_00a1: ldelema int32
+ L_00a6: dup
+ L_00a7: ldind.i4
+ L_00a8: ldc.i4.1
+ L_00a9: add
+ L_00aa: stind.i4
+ L_00ab: br.s L_00d1
+ L_00ad: ldloc.1
+ L_00ae: ldloc.s V_4
+ L_00b0: ldloc.0
+ L_00b1: ldloc.s V_4
+ L_00b3: ldelem.i4
+ L_00b4: stelem.i4
+ L_00b5: ldloc.s V_4
+ L_00b7: ldc.i4.1
+ L_00b8: add
+ L_00b9: stloc.s V_4
+ L_00bb: ldloc.s V_4
+ L_00bd: ldloc.1
+ L_00be: ldlen
+ L_00bf: conv.i4
+ L_00c0: blt.s L_00c4
+ L_00c2: ldc.i4.1
+ L_00c3: ret
+ L_00c4: ldloc.1
+ L_00c5: ldloc.s V_4
+ L_00c7: ldelema int32
+ L_00cc: dup
+ L_00cd: ldind.i4
+ L_00ce: ldc.i4.1
+ L_00cf: add
+ L_00d0: stind.i4
+ L_00d1: ldloc.1
+ L_00d2: ldloc.s V_4
+ L_00d4: ldelem.i4
+ L_00d5: ldloc.2
+ L_00d6: ldloc.s V_4
+ L_00d8: ldelem.i4
+ L_00d9: bge.s L_00ad
+ L_00db: br.s L_0084
+ }
+
+ .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
+ {
+ .maxstack 8
+ ldarg.0
+ call instance void [mscorlib]System.Object::.ctor()
+ ret
+ }
+}
+
+.class private auto ansi 'ArrayInitializers' extends [mscorlib]System.Object
+{
+ .class explicit ansi sealed nested private 'StaticArrayInitTypeSize20' extends [mscorlib]System.ValueType
+ {
+ .pack 1
+ .size 20
+ }
+
+ .class explicit ansi sealed nested private 'StaticArrayInitTypeSize40' extends [mscorlib]System.ValueType
+ {
+ .pack 1
+ .size 40
+ }
+
+ .class explicit ansi sealed nested private 'StaticArrayInitTypeSize80' extends [mscorlib]System.ValueType
+ {
+ .pack 1
+ .size 80
+ }
+
+ .field static assembly valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize20' 'InitializerField20' at InitializerField20Data
+ .field static assembly valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize40' 'InitializerField40' at InitializerField40Data
+ .field static assembly valuetype 'ArrayInitializers'/'StaticArrayInitTypeSize80' 'InitializerField80' at InitializerField80Data
+}
+
+.data cil InitializerField20Data = bytearray (01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14)
+
+.data cil InitializerField40Data = bytearray (01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14
+ 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28)
+
+.data cil InitializerField80Data = bytearray (01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14
+ 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28
+ 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C
+ 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50)