Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions src/coreclr/jit/helperexpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2822,6 +2822,7 @@ bool Compiler::fgExpandStackArrayAllocation(BasicBlock* block, Statement* stmt,

const CorInfoHelpFunc helper = eeGetHelperNum(call->gtCallMethHnd);
int lengthArgIndex = -1;
int typeArgIndex = -1;

switch (helper)
{
Expand All @@ -2830,10 +2831,7 @@ bool Compiler::fgExpandStackArrayAllocation(BasicBlock* block, Statement* stmt,
case CORINFO_HELP_NEWARR_1_OBJ:
case CORINFO_HELP_NEWARR_1_ALIGN8:
lengthArgIndex = 1;
break;

case CORINFO_HELP_READYTORUN_NEWARR_1:
lengthArgIndex = 0;
typeArgIndex = 0;
break;

default:
Expand Down Expand Up @@ -2871,9 +2869,7 @@ bool Compiler::fgExpandStackArrayAllocation(BasicBlock* block, Statement* stmt,

// Initialize the array method table pointer.
//
CORINFO_CLASS_HANDLE arrayHnd = (CORINFO_CLASS_HANDLE)call->compileTimeHelperArgumentHandle;

GenTree* const mt = gtNewIconEmbClsHndNode(arrayHnd);
GenTree* const mt = call->gtArgs.GetArgByIndex(typeArgIndex)->GetNode();
GenTree* const mtStore = gtNewStoreValueNode(TYP_I_IMPL, stackLocalAddress, mt);
Statement* const mtStmt = fgNewStmtFromTree(mtStore);

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,7 @@ ClassLayoutBuilder ClassLayoutBuilder::BuildArray(Compiler* compiler, CORINFO_CL

ClrSafeInt<unsigned> totalSize(elementSize);
totalSize *= static_cast<unsigned>(length);
totalSize.AlignUp(TARGET_POINTER_SIZE);
totalSize += static_cast<unsigned>(OFFSETOF__CORINFO_Array__data);
assert(!totalSize.IsOverflow());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,11 @@ public static int TestEntryPoint()
// Stack allocation of boxed structs is now enabled
CallTestAndVerifyAllocation(BoxSimpleStructAndAddFields, 12, expectedAllocationKind);

// Fixed-sized stack array cases
CallTestAndVerifyAllocation(AllocateArrayWithNonGCElements, 84, expectedAllocationKind);
CallTestAndVerifyAllocation(AllocateArrayWithGCElements, 84, expectedAllocationKind);
CallTestAndVerifyAllocation(AllocateArrayT<int>, 84, expectedAllocationKind);
CallTestAndVerifyAllocation(AllocateArrayT<string>, 84, expectedAllocationKind);

// The remaining tests currently never allocate on the stack
if (expectedAllocationKind == AllocationKind.Stack) {
Expand All @@ -170,6 +174,7 @@ public static int TestEntryPoint()
CallTestAndVerifyAllocation(AllocateSimpleClassAndCast, 7, expectedAllocationKind);

CallTestAndVerifyAllocation(AllocateArrayWithNonGCElementsEscape, 42, expectedAllocationKind);
CallTestAndVerifyAllocation(AllocateArrayWithGCElementsEscape, 42, expectedAllocationKind);

// This test calls CORINFO_HELP_OVERFLOW
CallTestAndVerifyAllocation(AllocateArrayWithNonGCElementsOutOfRangeLeft, 0, expectedAllocationKind, true);
Expand Down Expand Up @@ -375,6 +380,29 @@ static int AllocateArrayWithNonGCElements()
return array[24] + array.Length;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static int AllocateArrayWithGCElements()
{
string[] array = new string[42];
array[24] = "42";
GC.Collect();
return array[24].Length * 21 + array.Length;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static int AllocateArrayT<T>()
{
T[] array = new T[42];
T t = array[24];
GC.Collect();

// Todo -- validate array type (currently causes escape for shared)
// Todo -- store to array (currently causes escape for shared)

Consume(t);
return array.Length + 42;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static int AllocateArrayWithNonGCElementsEscape()
{
Expand All @@ -384,6 +412,15 @@ static int AllocateArrayWithNonGCElementsEscape()
return array[24];
}

[MethodImpl(MethodImplOptions.NoInlining)]
static int AllocateArrayWithGCElementsEscape()
{
string[] array = new string[42];
Use(ref array[24]);
GC.Collect();
return array[24].Length * 21;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static int AllocateArrayWithNonGCElementsOutOfRangeRight()
{
Expand Down Expand Up @@ -424,6 +461,12 @@ static void Use(ref int v)
v = 42;
}

[MethodImpl(MethodImplOptions.NoInlining)]
static void Use(ref string s)
{
s = "42";
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static void ZeroAllocTest()
{
Expand Down
Loading