Skip to content

Commit

Permalink
Optimize Interlocked.Exchange and Interlocked.CompareExchange for IntPtr
Browse files Browse the repository at this point in the history
  • Loading branch information
EgorBo committed Jan 21, 2021
1 parent c4421ac commit 34fdd14
Showing 1 changed file with 18 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,15 @@ 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>
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern IntPtr Exchange(ref IntPtr location1, IntPtr value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]

This comment has been minimized.

Copy link
@jkotas

jkotas Jan 21, 2021

Also delete the unmanaged FCall.

This comment has been minimized.

Copy link
@jkotas

jkotas Jan 21, 2021

Also, can these methods be moved to shared CoreLib partition now?

public static IntPtr Exchange(ref IntPtr location1, IntPtr value)
{
if (IntPtr.Size == 4)

This comment has been minimized.

Copy link
@jkotas

jkotas Jan 21, 2021

Make this #if TARGET_64BIT so that it is as straightforward as possible for JIT to inline?

This comment has been minimized.

Copy link
@EgorBo

EgorBo Jan 21, 2021

Author Owner

Good point! Will address your feedback in a PR a bit later, thanks!

{
return (IntPtr)Interlocked.Exchange(ref Unsafe.As<IntPtr, int>(ref location1), (int)value);
}
return (IntPtr)Interlocked.Exchange(ref Unsafe.As<IntPtr, long>(ref location1), (long)value);
}

This comment has been minimized.

Copy link
@stephentoub

stephentoub Jan 21, 2021

Nevermind, I see Jan already suggested that.


// The below whole method reduces to a single call to Exchange(ref object, object) but
// the JIT thinks that it will generate more native code than it actually does.
Expand Down Expand Up @@ -162,8 +169,15 @@ public static partial class Interlocked
/// <param name="comparand">The <see cref="IntPtr"/> that is compared to the value 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>
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr comparand);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr comparand)
{
if (IntPtr.Size == 4)
{
return (IntPtr)Interlocked.CompareExchange(ref Unsafe.As<IntPtr, int>(ref location1), (int)value, (int)comparand);
}
return (IntPtr)Interlocked.CompareExchange(ref Unsafe.As<IntPtr, long>(ref location1), (long)value, (long)comparand);
}

// Note that getILIntrinsicImplementationForInterlocked() in vm\jitinterface.cpp replaces
// the body of the following method with the the following IL:
Expand Down

0 comments on commit 34fdd14

Please sign in to comment.