Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT: array allocation fixes #112676

Merged
merged 1 commit into from
Feb 19, 2025
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