Skip to content

Commit 0be256e

Browse files
EgorBojakobbotsch
andauthored
Allocate Array.Empty<> on a frozen segment (NonGC heap) (#85559)
Co-authored-by: Jakob Botsch Nielsen <[email protected]>
1 parent 7afd85d commit 0be256e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+451
-354
lines changed

docs/design/coreclr/botr/readytorun-format.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,8 @@ enum ReadyToRunHelper
798798
READYTORUN_HELPER_GenericNonGcTlsBase = 0x67,
799799
READYTORUN_HELPER_VirtualFuncPtr = 0x68,
800800
READYTORUN_HELPER_IsInstanceOfException = 0x69,
801+
READYTORUN_HELPER_NewMaybeFrozenArray = 0x6A,
802+
READYTORUN_HELPER_NewMaybeFrozenObject = 0x6B,
801803

802804
// Long mul/div/shift ops
803805
READYTORUN_HELPER_LMul = 0xC0,

src/coreclr/inc/corinfo.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ enum CorInfoHelpFunc
404404
which is the right helper to use to allocate an object of a given type. */
405405

406406
CORINFO_HELP_NEWFAST,
407+
CORINFO_HELP_NEWFAST_MAYBEFROZEN, // allocator for objects that *might* allocate them on a frozen segment
407408
CORINFO_HELP_NEWSFAST, // allocator for small, non-finalizer, non-array object
408409
CORINFO_HELP_NEWSFAST_FINALIZE, // allocator for small, finalizable, non-array object
409410
CORINFO_HELP_NEWSFAST_ALIGN8, // allocator for small, non-finalizer, non-array object, 8 byte aligned
@@ -412,6 +413,7 @@ enum CorInfoHelpFunc
412413
CORINFO_HELP_NEW_MDARR,// multi-dim array helper for arrays Rank != 1 (with or without lower bounds - dimensions passed in as unmanaged array)
413414
CORINFO_HELP_NEW_MDARR_RARE,// rare multi-dim array helper (Rank == 1)
414415
CORINFO_HELP_NEWARR_1_DIRECT, // helper for any one dimensional array creation
416+
CORINFO_HELP_NEWARR_1_MAYBEFROZEN, // allocator for arrays that *might* allocate them on a frozen segment
415417
CORINFO_HELP_NEWARR_1_OBJ, // optimized 1-D object arrays
416418
CORINFO_HELP_NEWARR_1_VC, // optimized 1-D value class arrays
417419
CORINFO_HELP_NEWARR_1_ALIGN8, // like VC, but aligns the array start
@@ -583,8 +585,6 @@ enum CorInfoHelpFunc
583585
CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE, // Convert from a TypeHandle (native structure pointer) to RuntimeTypeHandle at run-time
584586
CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE_MAYBENULL, // Convert from a TypeHandle (native structure pointer) to RuntimeTypeHandle at run-time, handle might point to a null type
585587

586-
CORINFO_HELP_ARE_TYPES_EQUIVALENT, // Check whether two TypeHandles (native structure pointers) are equivalent
587-
588588
CORINFO_HELP_VIRTUAL_FUNC_PTR, // look up a virtual method at run-time
589589

590590
// Not a real helpers. Instead of taking handle arguments, these helpers point to a small stub that loads the handle argument and calls the static helper.
@@ -2619,12 +2619,6 @@ class ICorStaticInfo
26192619
CORINFO_CLASS_HANDLE parent // base type
26202620
) = 0;
26212621

2622-
// TRUE if cls1 and cls2 are considered equivalent types.
2623-
virtual bool areTypesEquivalent(
2624-
CORINFO_CLASS_HANDLE cls1,
2625-
CORINFO_CLASS_HANDLE cls2
2626-
) = 0;
2627-
26282622
// See if a cast from fromClass to toClass will succeed, fail, or needs
26292623
// to be resolved at runtime.
26302624
virtual TypeCompareState compareTypesForCast(

src/coreclr/inc/corjitflags.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class CORJIT_FLAGS
5555
CORJIT_FLAG_OSR = 13, // Generate alternate method for On Stack Replacement
5656

5757
CORJIT_FLAG_ALT_JIT = 14, // JIT should consider itself an ALT_JIT
58-
CORJIT_FLAG_UNUSED8 = 15,
58+
CORJIT_FLAG_FROZEN_ALLOC_ALLOWED = 15, // JIT is allowed to use *_MAYBEFROZEN allocators
5959
CORJIT_FLAG_UNUSED9 = 16,
6060
CORJIT_FLAG_UNUSED10 = 17,
6161

src/coreclr/inc/icorjitinfoimpl_generated.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -339,10 +339,6 @@ bool canCast(
339339
CORINFO_CLASS_HANDLE child,
340340
CORINFO_CLASS_HANDLE parent) override;
341341

342-
bool areTypesEquivalent(
343-
CORINFO_CLASS_HANDLE cls1,
344-
CORINFO_CLASS_HANDLE cls2) override;
345-
346342
TypeCompareState compareTypesForCast(
347343
CORINFO_CLASS_HANDLE fromClass,
348344
CORINFO_CLASS_HANDLE toClass) override;

src/coreclr/inc/jiteeversionguid.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
4343
#define GUID_DEFINED
4444
#endif // !GUID_DEFINED
4545

46-
constexpr GUID JITEEVersionIdentifier = { /* 387bcec3-9a71-4422-a11c-e7ce3b73c592 */
47-
0x387bcec3,
48-
0x9a71,
49-
0x4422,
50-
{0xa1, 0x1c, 0xe7, 0xce, 0x3b, 0x73, 0xc5, 0x92}
46+
constexpr GUID JITEEVersionIdentifier = { /* 4e6355a0-3844-45e2-8cef-082c18217e14 */
47+
0x4e6355a0,
48+
0x3844,
49+
0x45e2,
50+
{0x8c, 0xef, 0x8, 0x2c, 0x18, 0x21, 0x7e, 0x14}
5151
};
5252

5353
//////////////////////////////////////////////////////////////////////////////////////////////////////////

src/coreclr/inc/jithelpers.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070

7171
// Allocating a new object
7272
JITHELPER(CORINFO_HELP_NEWFAST, JIT_New, CORINFO_HELP_SIG_REG_ONLY)
73+
JITHELPER(CORINFO_HELP_NEWFAST_MAYBEFROZEN, JIT_NewMaybeFrozen,CORINFO_HELP_SIG_REG_ONLY)
7374
DYNAMICJITHELPER(CORINFO_HELP_NEWSFAST, JIT_New, CORINFO_HELP_SIG_REG_ONLY)
7475
JITHELPER(CORINFO_HELP_NEWSFAST_FINALIZE, NULL, CORINFO_HELP_SIG_REG_ONLY)
7576
DYNAMICJITHELPER(CORINFO_HELP_NEWSFAST_ALIGN8, JIT_New, CORINFO_HELP_SIG_REG_ONLY)
@@ -78,6 +79,7 @@
7879
JITHELPER(CORINFO_HELP_NEW_MDARR, JIT_NewMDArr,CORINFO_HELP_SIG_4_STACK)
7980
JITHELPER(CORINFO_HELP_NEW_MDARR_RARE, JIT_NewMDArr,CORINFO_HELP_SIG_4_STACK)
8081
JITHELPER(CORINFO_HELP_NEWARR_1_DIRECT, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY)
82+
JITHELPER(CORINFO_HELP_NEWARR_1_MAYBEFROZEN, JIT_NewArr1MaybeFrozen,CORINFO_HELP_SIG_REG_ONLY)
8183
DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_OBJ, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY)
8284
DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_VC, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY)
8385
DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_ALIGN8, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY)
@@ -252,8 +254,6 @@
252254
JITHELPER(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE, JIT_GetRuntimeType, CORINFO_HELP_SIG_REG_ONLY)
253255
JITHELPER(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE_MAYBENULL, JIT_GetRuntimeType_MaybeNull, CORINFO_HELP_SIG_REG_ONLY)
254256

255-
JITHELPER(CORINFO_HELP_ARE_TYPES_EQUIVALENT, NULL, CORINFO_HELP_SIG_REG_ONLY)
256-
257257
JITHELPER(CORINFO_HELP_VIRTUAL_FUNC_PTR, JIT_VirtualFunctionPointer, CORINFO_HELP_SIG_4_STACK)
258258

259259
JITHELPER(CORINFO_HELP_READYTORUN_NEW, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB)

src/coreclr/inc/readytorun.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
// src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs
1919
// src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h
2020
#define READYTORUN_MAJOR_VERSION 0x0009
21-
#define READYTORUN_MINOR_VERSION 0x0000
21+
#define READYTORUN_MINOR_VERSION 0x0001
2222

2323
#define MINIMUM_READYTORUN_MAJOR_VERSION 0x009
2424

@@ -30,6 +30,7 @@
3030
// R2R 6.0 is not backward compatible with 5.x or earlier.
3131
// R2R Version 8.0 Changes the alignment of the Int128 type
3232
// R2R Version 9.0 adds support for the Vector512 type
33+
// R2R Version 9.1 adds new helpers to allocate objects on frozen segments
3334

3435
struct READYTORUN_CORE_HEADER
3536
{
@@ -335,6 +336,8 @@ enum ReadyToRunHelper
335336
READYTORUN_HELPER_GenericNonGcTlsBase = 0x67,
336337
READYTORUN_HELPER_VirtualFuncPtr = 0x68,
337338
READYTORUN_HELPER_IsInstanceOfException = 0x69,
339+
READYTORUN_HELPER_NewMaybeFrozenArray = 0x6A,
340+
READYTORUN_HELPER_NewMaybeFrozenObject = 0x6B,
338341

339342
// Long mul/div/shift ops
340343
READYTORUN_HELPER_LMul = 0xC0,

src/coreclr/inc/readytorunhelpers.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ HELPER(READYTORUN_HELPER_GenericNonGcTlsBase, CORINFO_HELP_GETGENERICS_NON
5555

5656
HELPER(READYTORUN_HELPER_VirtualFuncPtr, CORINFO_HELP_VIRTUAL_FUNC_PTR, )
5757
HELPER(READYTORUN_HELPER_IsInstanceOfException, CORINFO_HELP_ISINSTANCEOF_EXCEPTION, )
58+
HELPER(READYTORUN_HELPER_NewMaybeFrozenArray, CORINFO_HELP_NEWARR_1_MAYBEFROZEN, )
59+
HELPER(READYTORUN_HELPER_NewMaybeFrozenObject, CORINFO_HELP_NEWFAST_MAYBEFROZEN, )
5860

5961
HELPER(READYTORUN_HELPER_LMul, CORINFO_HELP_LMUL, )
6062
HELPER(READYTORUN_HELPER_LMulOfv, CORINFO_HELP_LMUL_OVF, )

src/coreclr/jit/ICorJitInfo_names_generated.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ DEF_CLR_API(getBuiltinClass)
8484
DEF_CLR_API(getTypeForPrimitiveValueClass)
8585
DEF_CLR_API(getTypeForPrimitiveNumericClass)
8686
DEF_CLR_API(canCast)
87-
DEF_CLR_API(areTypesEquivalent)
8887
DEF_CLR_API(compareTypesForCast)
8988
DEF_CLR_API(compareTypesForEquality)
9089
DEF_CLR_API(mergeClasses)

src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -793,16 +793,6 @@ bool WrapICorJitInfo::canCast(
793793
return temp;
794794
}
795795

796-
bool WrapICorJitInfo::areTypesEquivalent(
797-
CORINFO_CLASS_HANDLE cls1,
798-
CORINFO_CLASS_HANDLE cls2)
799-
{
800-
API_ENTER(areTypesEquivalent);
801-
bool temp = wrapHnd->areTypesEquivalent(cls1, cls2);
802-
API_LEAVE(areTypesEquivalent);
803-
return temp;
804-
}
805-
806796
TypeCompareState WrapICorJitInfo::compareTypesForCast(
807797
CORINFO_CLASS_HANDLE fromClass,
808798
CORINFO_CLASS_HANDLE toClass)

src/coreclr/jit/compiler.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3038,10 +3038,6 @@ class Compiler
30383038
GenTree* gtFoldBoxNullable(GenTree* tree);
30393039
GenTree* gtFoldExprCompare(GenTree* tree);
30403040
GenTree* gtFoldExprConditional(GenTree* tree);
3041-
GenTree* gtCreateHandleCompare(genTreeOps oper,
3042-
GenTree* op1,
3043-
GenTree* op2,
3044-
CorInfoInlineTypeCheck typeCheckInliningResult);
30453041
GenTree* gtFoldExprCall(GenTreeCall* call);
30463042
GenTree* gtFoldTypeCompare(GenTree* tree);
30473043
GenTree* gtFoldTypeEqualityCall(bool isEq, GenTree* op1, GenTree* op2);

src/coreclr/jit/gentree.cpp

Lines changed: 12 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,30 +2158,17 @@ GenTree* Compiler::getArrayLengthFromAllocation(GenTree* tree DEBUGARG(BasicBloc
21582158

21592159
if (call->gtCallType == CT_HELPER)
21602160
{
2161-
switch (eeGetHelperNum(call->gtCallMethHnd))
2161+
CorInfoHelpFunc helper = eeGetHelperNum(call->gtCallMethHnd);
2162+
switch (helper)
21622163
{
2164+
case CORINFO_HELP_NEWARR_1_MAYBEFROZEN:
21632165
case CORINFO_HELP_NEWARR_1_DIRECT:
21642166
case CORINFO_HELP_NEWARR_1_OBJ:
21652167
case CORINFO_HELP_NEWARR_1_VC:
21662168
case CORINFO_HELP_NEWARR_1_ALIGN8:
21672169
{
21682170
// This is an array allocation site. Grab the array length node.
2169-
arrayLength = call->gtArgs.GetArgByIndex(1)->GetNode();
2170-
break;
2171-
}
2172-
2173-
case CORINFO_HELP_READYTORUN_NEWARR_1:
2174-
{
2175-
// On arm when compiling on certain platforms for ready to
2176-
// run, a handle will be inserted before the length. To
2177-
// handle this case, we will grab the last argument as
2178-
// that's always the length. See
2179-
// CallArgs::AddFinalArgsAndDetermineABIInfo for where the
2180-
// handle is inserted.
2181-
for (CallArg& arg : call->gtArgs.Args())
2182-
{
2183-
arrayLength = arg.GetNode();
2184-
}
2171+
arrayLength = call->gtArgs.GetUserArgByIndex(1)->GetNode();
21852172
break;
21862173
}
21872174

@@ -13614,47 +13601,6 @@ GenTree* Compiler::gtFoldExprConditional(GenTree* tree)
1361413601
return replacement;
1361513602
}
1361613603

13617-
//------------------------------------------------------------------------
13618-
// gtCreateHandleCompare: generate a type handle comparison
13619-
//
13620-
// Arguments:
13621-
// oper -- comparison operation (equal/not equal)
13622-
// op1 -- first operand
13623-
// op2 -- second operand
13624-
// typeCheckInliningResult -- indicates how the comparison should happen
13625-
//
13626-
// Returns:
13627-
// Type comparison tree
13628-
//
13629-
13630-
GenTree* Compiler::gtCreateHandleCompare(genTreeOps oper,
13631-
GenTree* op1,
13632-
GenTree* op2,
13633-
CorInfoInlineTypeCheck typeCheckInliningResult)
13634-
{
13635-
// If we can compare pointers directly, just emit the binary operation
13636-
if (typeCheckInliningResult == CORINFO_INLINE_TYPECHECK_PASS)
13637-
{
13638-
return gtNewOperNode(oper, TYP_INT, op1, op2);
13639-
}
13640-
13641-
assert(typeCheckInliningResult == CORINFO_INLINE_TYPECHECK_USE_HELPER);
13642-
13643-
// Emit a call to a runtime helper
13644-
GenTree* ret = gtNewHelperCallNode(CORINFO_HELP_ARE_TYPES_EQUIVALENT, TYP_INT, op1, op2);
13645-
if (oper == GT_EQ)
13646-
{
13647-
ret = gtNewOperNode(GT_NE, TYP_INT, ret, gtNewIconNode(0, TYP_INT));
13648-
}
13649-
else
13650-
{
13651-
assert(oper == GT_NE);
13652-
ret = gtNewOperNode(GT_EQ, TYP_INT, ret, gtNewIconNode(0, TYP_INT));
13653-
}
13654-
13655-
return ret;
13656-
}
13657-
1365813604
//------------------------------------------------------------------------
1365913605
// gtFoldTypeCompare: see if a type comparison can be further simplified
1366013606
//
@@ -13767,9 +13713,9 @@ GenTree* Compiler::gtFoldTypeCompare(GenTree* tree)
1376713713
inliningKind = info.compCompHnd->canInlineTypeCheck(cls2Hnd, CORINFO_INLINE_TYPECHECK_SOURCE_TOKEN);
1376813714
}
1376913715

13770-
assert(inliningKind == CORINFO_INLINE_TYPECHECK_PASS || inliningKind == CORINFO_INLINE_TYPECHECK_USE_HELPER);
13716+
assert(inliningKind == CORINFO_INLINE_TYPECHECK_PASS);
1377113717

13772-
GenTree* compare = gtCreateHandleCompare(oper, op1ClassFromHandle, op2ClassFromHandle, inliningKind);
13718+
GenTree* compare = gtNewOperNode(oper, TYP_INT, op1ClassFromHandle, op2ClassFromHandle);
1377313719

1377413720
// Drop any now-irrelevant flags
1377513721
compare->gtFlags |= tree->gtFlags & (GTF_RELOP_JMP_USED | GTF_DONT_CSE);
@@ -13805,11 +13751,10 @@ GenTree* Compiler::gtFoldTypeCompare(GenTree* tree)
1380513751

1380613752
arg2 = gtNewMethodTableLookup(arg2);
1380713753

13808-
CorInfoInlineTypeCheck inliningKind =
13809-
info.compCompHnd->canInlineTypeCheck(nullptr, CORINFO_INLINE_TYPECHECK_SOURCE_VTABLE);
13810-
assert(inliningKind == CORINFO_INLINE_TYPECHECK_PASS || inliningKind == CORINFO_INLINE_TYPECHECK_USE_HELPER);
13754+
assert(info.compCompHnd->canInlineTypeCheck(nullptr, CORINFO_INLINE_TYPECHECK_SOURCE_VTABLE) ==
13755+
CORINFO_INLINE_TYPECHECK_PASS);
1381113756

13812-
GenTree* compare = gtCreateHandleCompare(oper, arg1, arg2, inliningKind);
13757+
GenTree* compare = gtNewOperNode(oper, TYP_INT, arg1, arg2);
1381313758

1381413759
// Drop any now-irrelevant flags
1381513760
compare->gtFlags |= tree->gtFlags & (GTF_RELOP_JMP_USED | GTF_DONT_CSE);
@@ -13907,7 +13852,8 @@ GenTree* Compiler::gtFoldTypeCompare(GenTree* tree)
1390713852
GenTree* const objMT = gtNewMethodTableLookup(objOp);
1390813853

1390913854
// Compare the two method tables
13910-
GenTree* const compare = gtCreateHandleCompare(oper, objMT, knownMT, typeCheckInliningResult);
13855+
assert(typeCheckInliningResult == CORINFO_INLINE_TYPECHECK_PASS);
13856+
GenTree* const compare = gtNewOperNode(oper, TYP_INT, objMT, knownMT);
1391113857

1391213858
// Drop any now irrelevant flags
1391313859
compare->gtFlags |= tree->gtFlags & (GTF_RELOP_JMP_USED | GTF_DONT_CSE);
@@ -18576,6 +18522,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetHelperCallClassHandle(GenTreeCall* call, boo
1857618522
}
1857718523

1857818524
case CORINFO_HELP_NEWARR_1_DIRECT:
18525+
case CORINFO_HELP_NEWARR_1_MAYBEFROZEN:
1857918526
case CORINFO_HELP_NEWARR_1_OBJ:
1858018527
case CORINFO_HELP_NEWARR_1_VC:
1858118528
case CORINFO_HELP_NEWARR_1_ALIGN8:

src/coreclr/jit/importer.cpp

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9734,11 +9734,57 @@ void Compiler::impImportBlockCode(BasicBlock* block)
97349734
// So if we have an int, explicitly extend it to be a native int.
97359735
op2 = impImplicitIorI4Cast(op2, TYP_I_IMPL);
97369736

9737+
bool isFrozenAllocator = false;
9738+
// If we're jitting a static constructor and detect the following code pattern:
9739+
//
9740+
// newarr
9741+
// stsfld
9742+
// ret
9743+
//
9744+
// we emit a "frozen" allocator for newarr to, hopefully, allocate that array on a frozen segment.
9745+
// This is a very simple and conservative implementation targeting Array.Empty<T>()'s shape
9746+
// Ideally, we want to be able to use frozen allocators more broadly, but such an analysis is
9747+
// not trivial.
9748+
//
9749+
if (((info.compFlags & FLG_CCTOR) == FLG_CCTOR) &&
9750+
// Does VM allow us to use frozen allocators?
9751+
opts.jitFlags->IsSet(JitFlags::JIT_FLAG_FROZEN_ALLOC_ALLOWED))
9752+
{
9753+
// Check next two opcodes (have to be STSFLD and RET)
9754+
const BYTE* nextOpcode1 = codeAddr + sizeof(mdToken);
9755+
const BYTE* nextOpcode2 = nextOpcode1 + sizeof(mdToken) + 1;
9756+
if ((nextOpcode2 < codeEndp) && (getU1LittleEndian(nextOpcode1) == CEE_STSFLD))
9757+
{
9758+
if (getU1LittleEndian(nextOpcode2) == CEE_RET)
9759+
{
9760+
// Check that the field is "static readonly", we don't want to waste memory
9761+
// for potentially mutable fields.
9762+
CORINFO_RESOLVED_TOKEN fldToken;
9763+
impResolveToken(nextOpcode1 + 1, &fldToken, CORINFO_TOKENKIND_Field);
9764+
CORINFO_FIELD_INFO fi;
9765+
eeGetFieldInfo(&fldToken, CORINFO_ACCESS_SET, &fi);
9766+
unsigned flagsToCheck = CORINFO_FLG_FIELD_STATIC | CORINFO_FLG_FIELD_FINAL;
9767+
if ((fi.fieldFlags & flagsToCheck) == flagsToCheck)
9768+
{
97379769
#ifdef FEATURE_READYTORUN
9738-
if (opts.IsReadyToRun())
9770+
if (opts.IsReadyToRun())
9771+
{
9772+
// Need to restore array classes before creating array objects on the heap
9773+
op1 = impTokenToHandle(&resolvedToken, nullptr, true /*mustRestoreHandle*/);
9774+
}
9775+
#endif
9776+
op1 = gtNewHelperCallNode(CORINFO_HELP_NEWARR_1_MAYBEFROZEN, TYP_REF, op1, op2);
9777+
isFrozenAllocator = true;
9778+
}
9779+
}
9780+
}
9781+
}
9782+
9783+
#ifdef FEATURE_READYTORUN
9784+
if (opts.IsReadyToRun() && !isFrozenAllocator)
97399785
{
9740-
op1 = impReadyToRunHelperToTree(&resolvedToken, CORINFO_HELP_READYTORUN_NEWARR_1, TYP_REF, nullptr,
9741-
op2);
9786+
helper = CORINFO_HELP_READYTORUN_NEWARR_1;
9787+
op1 = impReadyToRunHelperToTree(&resolvedToken, helper, TYP_REF, nullptr, op2);
97429788
usingReadyToRunHelper = (op1 != nullptr);
97439789

97449790
if (!usingReadyToRunHelper)
@@ -9750,7 +9796,6 @@ void Compiler::impImportBlockCode(BasicBlock* block)
97509796
// 3) Allocate the new array
97519797
// Reason: performance (today, we'll always use the slow helper for the R2R generics case)
97529798

9753-
// Need to restore array classes before creating array objects on the heap
97549799
op1 = impTokenToHandle(&resolvedToken, nullptr, true /*mustRestoreHandle*/);
97559800
if (op1 == nullptr)
97569801
{ // compDonotInline()
@@ -9759,15 +9804,15 @@ void Compiler::impImportBlockCode(BasicBlock* block)
97599804
}
97609805
}
97619806

9762-
if (!usingReadyToRunHelper)
9807+
if (!usingReadyToRunHelper && !isFrozenAllocator)
97639808
#endif
97649809
{
97659810
/* Create a call to 'new' */
9811+
helper = info.compCompHnd->getNewArrHelper(resolvedToken.hClass);
97669812

97679813
// Note that this only works for shared generic code because the same helper is used for all
97689814
// reference array types
9769-
op1 =
9770-
gtNewHelperCallNode(info.compCompHnd->getNewArrHelper(resolvedToken.hClass), TYP_REF, op1, op2);
9815+
op1 = gtNewHelperCallNode(helper, TYP_REF, op1, op2);
97719816
}
97729817

97739818
op1->AsCall()->compileTimeHelperArgumentHandle = (CORINFO_GENERIC_HANDLE)resolvedToken.hClass;

0 commit comments

Comments
 (0)