#define SELECTANY extern __declspec(selectany)
#endif
-SELECTANY const GUID JITEEVersionIdentifier = { /* e5708e9e-dd18-4287-8745-5d10ff2697cf */
- 0xe5708e9e,
- 0xdd18,
- 0x4287,
- { 0x87, 0x45, 0x5d, 0x10, 0xff, 0x26, 0x97, 0xcf }
+SELECTANY const GUID JITEEVersionIdentifier = { /* 28eb875f-b6a9-4a04-9ba7-69ba59deed46 */
+ 0x28eb875f,
+ 0xb6a9,
+ 0x4a04,
+ { 0x9b, 0xa7, 0x69, 0xba, 0x59, 0xde, 0xed, 0x46 }
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
CORINFO_HELP_NEW_MDARR, // multi-dim array helper (with or without lower bounds - dimensions passed in as vararg)
CORINFO_HELP_NEW_MDARR_NONVARARG,// multi-dim array helper (with or without lower bounds - dimensions passed in as unmanaged array)
CORINFO_HELP_NEWARR_1_DIRECT, // helper for any one dimensional array creation
+ CORINFO_HELP_NEWARR_1_R2R_DIRECT, // wrapper for R2R direct call, which extracts method table from ArrayTypeDesc
CORINFO_HELP_NEWARR_1_OBJ, // optimized 1-D object arrays
CORINFO_HELP_NEWARR_1_VC, // optimized 1-D value class arrays
CORINFO_HELP_NEWARR_1_ALIGN8, // like VC, but aligns the array start
JITHELPER(CORINFO_HELP_NEW_MDARR, JIT_NewMDArr,CORINFO_HELP_SIG_8_VA)
JITHELPER(CORINFO_HELP_NEW_MDARR_NONVARARG, JIT_NewMDArrNonVarArg,CORINFO_HELP_SIG_4_STACK)
JITHELPER(CORINFO_HELP_NEWARR_1_DIRECT, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY)
+ JITHELPER(CORINFO_HELP_NEWARR_1_R2R_DIRECT, JIT_NewArr1_R2R,CORINFO_HELP_SIG_REG_ONLY)
DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_OBJ, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY)
DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_VC, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY)
DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_ALIGN8, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY)
HELPER(READYTORUN_HELPER_NewMultiDimArr_NonVarArg, CORINFO_HELP_NEW_MDARR_NONVARARG, )
HELPER(READYTORUN_HELPER_NewObject, CORINFO_HELP_NEWFAST, )
-HELPER(READYTORUN_HELPER_NewArray, CORINFO_HELP_NEWARR_1_DIRECT, )
+HELPER(READYTORUN_HELPER_NewArray, CORINFO_HELP_NEWARR_1_R2R_DIRECT, )
HELPER(READYTORUN_HELPER_CheckCastAny, CORINFO_HELP_CHKCASTANY, )
HELPER(READYTORUN_HELPER_CheckInstanceAny, CORINFO_HELP_ISINSTANCEOFANY, )
if (call->gtCallType == CT_HELPER)
{
if (call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_NEWARR_1_DIRECT) ||
+ call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_NEWARR_1_R2R_DIRECT) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_NEWARR_1_OBJ) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_NEWARR_1_VC) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_NEWARR_1_ALIGN8))
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_NEWSFAST) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_NEWSFAST_ALIGN8) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_NEWARR_1_DIRECT) ||
+ call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_NEWARR_1_R2R_DIRECT) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_NEWARR_1_OBJ) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_NEWARR_1_VC) ||
call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_NEWARR_1_ALIGN8))
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) &&
- newArrayCall->gtCall.gtCallMethHnd != eeFindHelper(CORINFO_HELP_NEWARR_1_ALIGN8)
+ newArrayCall->gtCall.gtCallMethHnd != eeFindHelper(CORINFO_HELP_NEWARR_1_ALIGN8) &&
#ifdef FEATURE_READYTORUN_COMPILER
- && newArrayCall->gtCall.gtCallMethHnd != eeFindHelper(CORINFO_HELP_READYTORUN_NEWARR_1)
+ newArrayCall->gtCall.gtCallMethHnd != eeFindHelper(CORINFO_HELP_NEWARR_1_R2R_DIRECT) &&
+ newArrayCall->gtCall.gtCallMethHnd != eeFindHelper(CORINFO_HELP_READYTORUN_NEWARR_1)
#endif
)
{
case CORINFO_HELP_NEW_MDARR:
case CORINFO_HELP_NEWARR_1_DIRECT:
case CORINFO_HELP_NEWARR_1_OBJ:
+ case CORINFO_HELP_NEWARR_1_R2R_DIRECT:
case CORINFO_HELP_READYTORUN_NEWARR_1:
mayFinalize = true; // These may run a finalizer
vnf = VNF_JitNewArr;
break;
+ case CORINFO_HELP_NEWARR_1_R2R_DIRECT:
case CORINFO_HELP_READYTORUN_NEWARR_1:
vnf = VNF_JitReadyToRunNewArr;
break;
}
HCIMPLEND
+//*************************************************************
+// R2R-specific array allocation wrapper that extracts array method table from ArrayTypeDesc
+//
+HCIMPL2(Object*, JIT_NewArr1_R2R, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size)
+{
+ FCALL_CONTRACT;
+
+ TypeHandle arrayTypeHandle(arrayTypeHnd_);
+ ArrayTypeDesc *pArrayTypeDesc = arrayTypeHandle.AsArray();
+ MethodTable *pArrayMT = pArrayTypeDesc->GetTemplateMethodTable();
+
+ return HCCALL2(JIT_NewArr1, (CORINFO_CLASS_HANDLE)pArrayMT, size);
+}
+HCIMPLEND
+
#include <optdefault.h>
/*************************************************************/
{
if (pResolvedToken->tokenType == CORINFO_TOKENKIND_Newarr)
{
- sigBuilder.AppendElementType((CorElementType)ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG);
+ if (!IsReadyToRunCompilation())
+ {
+ sigBuilder.AppendElementType((CorElementType)ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG);
+ }
+
sigBuilder.AppendElementType(ELEMENT_TYPE_SZARRAY);
}
extern FCDECL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size);
extern FCDECL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size);
+extern FCDECL2(Object*, JIT_NewArr1_R2R, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size);
extern FCDECL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size);
#ifndef JIT_Stelem_Ref
CorInfoHelpFunc ZapInfo::getNewArrHelper(CORINFO_CLASS_HANDLE arrayCls)
{
if (IsReadyToRunCompilation())
- return CORINFO_HELP_NEWARR_1_DIRECT;
+ return CORINFO_HELP_NEWARR_1_R2R_DIRECT;
return m_pEEJitInfo->getNewArrHelper(arrayCls);
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading;
+
+class Program
+{
+ const int ARRAY_SIZE = 1024;
+
+ static int Main()
+ {
+ // Run all tests 3x times to exercise both slow and fast paths work
+ for (int i = 0; i < 3; i++)
+ RunAllTests();
+
+ Console.WriteLine(Assert.HasAssertFired ? "FAILED" : "PASSED");
+ return Assert.HasAssertFired ? 1 : 100;
+ }
+
+ static void RunAllTests()
+ {
+ RunTest1();
+ RunTest2();
+ RunTest3();
+ RunTest4();
+ RunTest5();
+ RunTest6();
+ RunTest7();
+ RunTest8();
+ }
+
+ static void RunTest1()
+ {
+ int [] arr = new int[ARRAY_SIZE];
+
+ Assert.AreEqual(arr.GetType().ToString(), "System.Int32[]");
+ }
+
+ static void RunTest2()
+ {
+ object [] arr = new object[ARRAY_SIZE];
+
+ Assert.AreEqual(arr.GetType().ToString(), "System.Object[]");
+ }
+
+ static void RunTest3()
+ {
+ int [] arr = new_array_generic<int>();
+
+ Assert.AreEqual(arr.GetType().ToString(), "System.Int32[]");
+ }
+
+ static void RunTest4()
+ {
+ string [] arr = new_array_generic<string>();
+
+ Assert.AreEqual(arr.GetType().ToString(), "System.String[]");
+ }
+
+ static void RunTest5()
+ {
+ object [] arr = new_array_generic<object>();
+
+ Assert.AreEqual(arr.GetType().ToString(), "System.Object[]");
+ }
+
+ static void RunTest6()
+ {
+ GenericClass1<int> [] arr = new GenericClass1<int>[ARRAY_SIZE];
+
+ Assert.AreEqual(arr.GetType().ToString(), "GenericClass1`1[System.Int32][]");
+ }
+
+ static void RunTest7()
+ {
+ GenericClass1<object> [] arr = new_array_generic<GenericClass1<object>>();
+
+ Assert.AreEqual(arr.GetType().ToString(), "GenericClass1`1[System.Object][]");
+ }
+
+ static void RunTest8()
+ {
+ genericclass1_object_array_field = new_array_generic<GenericClass2<object>>();
+
+ Assert.AreEqual(genericclass1_object_array_field.GetType().ToString(), "GenericClass2`1[System.Object][]");
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static T[] new_array_generic<T>()
+ {
+ return new T[ARRAY_SIZE];
+ }
+
+ static volatile GenericClass1<object> [] genericclass1_object_array_field;
+}
+
+class GenericClass1<T>
+{
+}
+
+class GenericClass2<T> : GenericClass1<T>
+{
+}
+
+public static class Assert
+{
+ public static bool HasAssertFired;
+
+ public static void AreEqual(Object actual, Object expected)
+ {
+ if (!(actual == null && expected == null) && !actual.Equals(expected))
+ {
+ Console.WriteLine("Not equal!");
+ Console.WriteLine("actual = " + actual.ToString());
+ Console.WriteLine("expected = " + expected.ToString());
+ HasAssertFired = true;
+ }
+ }
+}
--- /dev/null
+<?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>
+ <AssemblyName>newarray</AssemblyName>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{8DDE6EB9-7CAE-4DD1-B2CC-8D756855EF78}</ProjectGuid>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <OutputType>Exe</OutputType>
+ <CLRTestKind>BuildAndRun</CLRTestKind>
+ <CLRTestPriority>0</CLRTestPriority>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="newarray.cs" />
+ </ItemGroup>
+
+
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>