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
16 changes: 11 additions & 5 deletions src/coreclr/jit/importercalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,12 @@ var_types Compiler::impImportCall(OPCODE opcode,
}
}

if (callInfo->thisTransform != CORINFO_NO_THIS_TRANSFORM)
{
impSpillSideEffects(false, CHECK_SPILL_ALL DEBUGARG(
"LDVIRTFTN constrained call requires transforming 'this'"));
}

impPopCallArgs(sig, call->AsCall());

if (call->AsCall()->IsAsync())
Expand Down Expand Up @@ -1034,17 +1040,17 @@ var_types Compiler::impImportCall(OPCODE opcode,
// The main group of arguments, and the this pointer.

// 'this' is pushed on the IL stack before all call args, but if this is a
// constrained call 'this' is a byref that may need to be dereferenced.
// That dereference should happen _after_ all args, so we need to spill
// them if they can interfere.
// constrained call 'this' is a byref that may need to be dereferenced or
// boxed. That transformation should happen _after_ all args, so we need
// to spill them if they can interfere.
bool hasThis;
hasThis = ((mflags & CORINFO_FLG_STATIC) == 0) && ((sig->callConv & CORINFO_CALLCONV_EXPLICITTHIS) == 0) &&
((opcode != CEE_NEWOBJ) || (newobjThis != nullptr));

if (hasThis && (constraintCallThisTransform == CORINFO_DEREF_THIS))
if (hasThis && (constraintCallThisTransform != CORINFO_NO_THIS_TRANSFORM))
Comment thread
Copilot marked this conversation as resolved.
{
impSpillSideEffects(false, CHECK_SPILL_ALL DEBUGARG(
"constrained call requires dereference for 'this' right before call"));
"constrained call requires transforming 'this' right before call"));
}

impPopCallArgs(sig, call->AsCall());
Expand Down
54 changes: 54 additions & 0 deletions src/tests/JIT/Regression_ro_2/Runtime_133716.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.CompilerServices;
using Xunit;

public class Runtime_133716
{
private static S s_value;

[Fact]
public static void TestEntryPoint()
{
s_value.X = 1;
Assert.True(TestBoxThis(), nameof(TestBoxThis));

s_value.X = 1;
Assert.True(TestLdvirtftn(ref s_value), nameof(TestLdvirtftn));
}

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
private static bool TestBoxThis()
{
return s_value.Equals(Mutate());
}

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
private static bool TestLdvirtftn<T>(ref T value)
where T : I
{
return value.Equals<int>(Mutate());
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static object Mutate()
{
s_value.X = 7;
return new S { X = 7 };
}

private interface I
{
bool Equals<T>(object other)
{
return Equals(other);
}
}

private struct S : I
{
public int X;
}
}
Loading