From 6cda73133fcb8785d0c2ab6cb296f956286f4034 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Tue, 27 Jun 2017 21:31:03 +0300 Subject: [PATCH 13/32] Implement JIT_NewArr1_R2R as R2R wrapper for JIT_NewArr1 to support both MethodTable-based and TypeDesc-based helpers. (#12475) Related issue: #12463 FIX: fix No.3, rebased --- src/inc/corinfo.h | 11 +-- src/inc/jithelpers.h | 1 + src/inc/readytorunhelpers.h | 2 +- src/jit/earlyprop.cpp | 2 + src/jit/importer.cpp | 5 +- src/jit/utils.cpp | 1 + src/jit/valuenum.cpp | 1 + src/vm/jithelpers.cpp | 15 ++++ src/vm/jitinterface.cpp | 6 +- src/vm/jitinterface.h | 1 + src/zap/zapinfo.cpp | 2 +- tests/src/readytorun/tests/newarray.cs | 126 +++++++++++++++++++++++++++++ tests/src/readytorun/tests/newarray.csproj | 32 ++++++++ 13 files changed, 195 insertions(+), 10 deletions(-) create mode 100644 tests/src/readytorun/tests/newarray.cs create mode 100644 tests/src/readytorun/tests/newarray.csproj diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h index f6a136c..a6acd71 100644 --- a/src/inc/corinfo.h +++ b/src/inc/corinfo.h @@ -213,11 +213,11 @@ TODO: Talk about initializing strutures before use #define SELECTANY extern __declspec(selectany) #endif -SELECTANY const GUID JITEEVersionIdentifier = { /* f00b3f49-ddd2-49be-ba43-6e49ffa66959 */ - 0xf00b3f49, - 0xddd2, - 0x49be, - { 0xba, 0x43, 0x6e, 0x49, 0xff, 0xa6, 0x69, 0x59 } +SELECTANY const GUID JITEEVersionIdentifier = { /* 28eb875f-b6a9-4a04-9ba7-69ba59deed46 */ + 0x28eb875f, + 0xb6a9, + 0x4a04, + { 0x9b, 0xa7, 0x69, 0xba, 0x59, 0xde, 0xed, 0x46 } }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -400,6 +400,7 @@ enum CorInfoHelpFunc 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 diff --git a/src/inc/jithelpers.h b/src/inc/jithelpers.h index 4e56250..b45948a 100644 --- a/src/inc/jithelpers.h +++ b/src/inc/jithelpers.h @@ -77,6 +77,7 @@ 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) diff --git a/src/inc/readytorunhelpers.h b/src/inc/readytorunhelpers.h index 9baf0e4..7a1245c 100644 --- a/src/inc/readytorunhelpers.h +++ b/src/inc/readytorunhelpers.h @@ -46,7 +46,7 @@ HELPER(READYTORUN_HELPER_NewMultiDimArr, CORINFO_HELP_NEW_MDARR, 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, ) diff --git a/src/jit/earlyprop.cpp b/src/jit/earlyprop.cpp index 51de631..ec460c6 100644 --- a/src/jit/earlyprop.cpp +++ b/src/jit/earlyprop.cpp @@ -79,6 +79,7 @@ GenTreePtr Compiler::getArrayLengthFromAllocation(GenTreePtr tree) 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)) @@ -116,6 +117,7 @@ GenTreePtr Compiler::getObjectHandleNodeFromAllocation(GenTreePtr tree) 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)) diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index 80c0b75..c5f2970 100644 --- a/src/jit/importer.cpp +++ b/src/jit/importer.cpp @@ -3004,9 +3004,10 @@ GenTreePtr Compiler::impInitializeArrayIntrinsic(CORINFO_SIG_INFO* sig) 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 ) { diff --git a/src/jit/utils.cpp b/src/jit/utils.cpp index 9fbe394..30ea30a 100644 --- a/src/jit/utils.cpp +++ b/src/jit/utils.cpp @@ -1315,6 +1315,7 @@ void HelperCallProperties::init() 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 diff --git a/src/jit/valuenum.cpp b/src/jit/valuenum.cpp index 5b40122..e4836d6 100644 --- a/src/jit/valuenum.cpp +++ b/src/jit/valuenum.cpp @@ -7610,6 +7610,7 @@ VNFunc Compiler::fgValueNumberHelperMethVNFunc(CorInfoHelpFunc helpFunc) vnf = VNF_JitNewArr; break; + case CORINFO_HELP_NEWARR_1_R2R_DIRECT: case CORINFO_HELP_READYTORUN_NEWARR_1: vnf = VNF_JitReadyToRunNewArr; break; diff --git a/src/vm/jithelpers.cpp b/src/vm/jithelpers.cpp index 2552b01..0b51339 100644 --- a/src/vm/jithelpers.cpp +++ b/src/vm/jithelpers.cpp @@ -3140,6 +3140,21 @@ HCIMPL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayMT, I } 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 /*************************************************************/ diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index f756c90..52db7c5 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -3412,7 +3412,11 @@ NoSpecialCase: { 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); } diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h index a3017ef..d67cfc5 100644 --- a/src/vm/jitinterface.h +++ b/src/vm/jitinterface.h @@ -217,6 +217,7 @@ extern FCDECL1(StringObject*, FramedAllocateString, DWORD stringLength); 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 diff --git a/src/zap/zapinfo.cpp b/src/zap/zapinfo.cpp index 60e03af..e94dea6 100644 --- a/src/zap/zapinfo.cpp +++ b/src/zap/zapinfo.cpp @@ -3384,7 +3384,7 @@ CorInfoHelpFunc ZapInfo::getCastingHelper(CORINFO_RESOLVED_TOKEN * pResolvedToke 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); } diff --git a/tests/src/readytorun/tests/newarray.cs b/tests/src/readytorun/tests/newarray.cs new file mode 100644 index 0000000..66917ab --- /dev/null +++ b/tests/src/readytorun/tests/newarray.cs @@ -0,0 +1,126 @@ +// 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(); + + Assert.AreEqual(arr.GetType().ToString(), "System.Int32[]"); + } + + static void RunTest4() + { + string [] arr = new_array_generic(); + + Assert.AreEqual(arr.GetType().ToString(), "System.String[]"); + } + + static void RunTest5() + { + object [] arr = new_array_generic(); + + Assert.AreEqual(arr.GetType().ToString(), "System.Object[]"); + } + + static void RunTest6() + { + GenericClass1 [] arr = new GenericClass1[ARRAY_SIZE]; + + Assert.AreEqual(arr.GetType().ToString(), "GenericClass1`1[System.Int32][]"); + } + + static void RunTest7() + { + GenericClass1 [] arr = new_array_generic>(); + + Assert.AreEqual(arr.GetType().ToString(), "GenericClass1`1[System.Object][]"); + } + + static void RunTest8() + { + genericclass1_object_array_field = new_array_generic>(); + + Assert.AreEqual(genericclass1_object_array_field.GetType().ToString(), "GenericClass2`1[System.Object][]"); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static T[] new_array_generic() + { + return new T[ARRAY_SIZE]; + } + + static volatile GenericClass1 [] genericclass1_object_array_field; +} + +class GenericClass1 +{ +} + +class GenericClass2 : GenericClass1 +{ +} + +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; + } + } +} diff --git a/tests/src/readytorun/tests/newarray.csproj b/tests/src/readytorun/tests/newarray.csproj new file mode 100644 index 0000000..21acf81 --- /dev/null +++ b/tests/src/readytorun/tests/newarray.csproj @@ -0,0 +1,32 @@ + + + + + newarray + Debug + AnyCPU + 2.0 + {8DDE6EB9-7CAE-4DD1-B2CC-8D756855EF78} + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + true + Exe + BuildAndRun + 0 + + + + + False + + + + + + + + + + + + + -- 2.7.4