Skip to content

Commit

Permalink
Intrinsify Interlocked.CompareExchange and Interlocked.Exchange for n…
Browse files Browse the repository at this point in the history
…ull (#79181)
  • Loading branch information
EgorBo committed Dec 5, 2022
1 parent 440d362 commit 60d00c4
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 4 deletions.
Expand Up @@ -81,6 +81,7 @@ public static partial class Interlocked
/// <param name="value">The value to which the <paramref name="location1"/> parameter is set.</param>
/// <returns>The original value of <paramref name="location1"/>.</returns>
/// <exception cref="NullReferenceException">The address of location1 is a null pointer.</exception>
[Intrinsic]
[MethodImpl(MethodImplOptions.InternalCall)]
[return: NotNullIfNotNull(nameof(location1))]
public static extern object? Exchange([NotNullIfNotNull(nameof(value))] ref object? location1, object? value);
Expand Down Expand Up @@ -145,6 +146,7 @@ public static partial class Interlocked
/// <param name="comparand">The object that is compared by reference to the object at <paramref name="location1"/>.</param>
/// <returns>The original value in <paramref name="location1"/>.</returns>
/// <exception cref="NullReferenceException">The address of <paramref name="location1"/> is a null pointer.</exception>
[Intrinsic]
[MethodImpl(MethodImplOptions.InternalCall)]
[return: NotNullIfNotNull(nameof(location1))]
public static extern object? CompareExchange(ref object? location1, object? value, object? comparand);
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/codegenxarch.cpp
Expand Up @@ -4064,7 +4064,7 @@ void CodeGen::genLockedInstructions(GenTreeOp* node)

assert(addr->isUsedFromReg());
assert(data->isUsedFromReg());
assert((size == EA_4BYTE) || (size == EA_PTRSIZE));
assert((size == EA_4BYTE) || (size == EA_PTRSIZE) || (size == EA_GCREF));

genConsumeOperands(node);

Expand Down
9 changes: 8 additions & 1 deletion src/coreclr/jit/emitxarch.cpp
Expand Up @@ -12193,7 +12193,14 @@ BYTE* emitter::emitOutputAM(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc)

case IF_ARW_RRD:
case IF_ARW_CNS:
assert(id->idGCref() == GCT_BYREF && (ins == INS_add || ins == INS_sub || ins == INS_sub_hide));
if (id->idGCref() == GCT_BYREF)
{
assert(ins == INS_add || ins == INS_sub || ins == INS_sub_hide);
}
else
{
assert((id->idGCref() == GCT_GCREF) && (ins == INS_cmpxchg || ins == INS_xchg));
}
break;

default:
Expand Down
15 changes: 13 additions & 2 deletions src/coreclr/jit/importercalls.cpp
Expand Up @@ -2967,7 +2967,12 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
{
break;
}
if ((retType != TYP_INT) && (retType != TYP_LONG))
if ((retType == TYP_REF) && impStackTop(1).val->IsIntegralConst(0))
{
// Intrinsify "object" overload in case of null assignment
// since we don't need the write barrier.
}
else if ((retType != TYP_INT) && (retType != TYP_LONG))
{
break;
}
Expand Down Expand Up @@ -2997,7 +3002,13 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
{
break;
}
if ((retType != TYP_INT) && (retType != TYP_LONG))
if ((retType == TYP_REF) && impStackTop().val->IsIntegralConst(0))
{
// Intrinsify "object" overload in case of null assignment
// since we don't need the write barrier.
assert(ni == NI_System_Threading_Interlocked_Exchange);
}
else if ((retType != TYP_INT) && (retType != TYP_LONG))
{
break;
}
Expand Down

0 comments on commit 60d00c4

Please sign in to comment.