@@ -48,27 +48,60 @@ public static long Decrement(ref long location) =>
48
48
/// <returns>The original value of <paramref name="location1"/>.</returns>
49
49
/// <exception cref="NullReferenceException">The address of location1 is a null pointer.</exception>
50
50
[ Intrinsic ]
51
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
52
+ public static int Exchange ( ref int location1 , int value )
53
+ {
54
+ #if TARGET_X86 || TARGET_AMD64 || TARGET_ARM64 || TARGET_RISCV64
55
+ return Exchange ( ref location1 , value ) ; // Must expand intrinsic
56
+ #else
57
+ if ( Unsafe . IsNullRef ( ref location1 ) )
58
+ ThrowHelper . ThrowNullReferenceException ( ) ;
59
+ return Exchange32 ( ref location1 , value ) ;
60
+ #endif
61
+ }
62
+
51
63
[ MethodImpl ( MethodImplOptions . InternalCall ) ]
52
- public static extern int Exchange ( ref int location1 , int value ) ;
64
+ private static extern int Exchange32 ( ref int location1 , int value ) ;
53
65
54
66
/// <summary>Sets a 64-bit signed integer to a specified value and returns the original value, as an atomic operation.</summary>
55
67
/// <param name="location1">The variable to set to the specified value.</param>
56
68
/// <param name="value">The value to which the <paramref name="location1"/> parameter is set.</param>
57
69
/// <returns>The original value of <paramref name="location1"/>.</returns>
58
70
/// <exception cref="NullReferenceException">The address of location1 is a null pointer.</exception>
59
71
[ Intrinsic ]
72
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
73
+ public static long Exchange ( ref long location1 , long value )
74
+ {
75
+ #if TARGET_AMD64 || TARGET_ARM64 || TARGET_RISCV64
76
+ return Exchange ( ref location1 , value ) ; // Must expand intrinsic
77
+ #else
78
+ if ( Unsafe . IsNullRef ( ref location1 ) )
79
+ ThrowHelper . ThrowNullReferenceException ( ) ;
80
+ return Exchange64 ( ref location1 , value ) ;
81
+ #endif
82
+ }
83
+
60
84
[ MethodImpl ( MethodImplOptions . InternalCall ) ]
61
- public static extern long Exchange ( ref long location1 , long value ) ;
85
+ private static extern long Exchange64 ( ref long location1 , long value ) ;
62
86
63
87
/// <summary>Sets an object to the specified value and returns a reference to the original object, as an atomic operation.</summary>
64
88
/// <param name="location1">The variable to set to the specified value.</param>
65
89
/// <param name="value">The value to which the <paramref name="location1"/> parameter is set.</param>
66
90
/// <returns>The original value of <paramref name="location1"/>.</returns>
67
91
/// <exception cref="NullReferenceException">The address of location1 is a null pointer.</exception>
68
92
[ Intrinsic ]
69
- [ MethodImpl ( MethodImplOptions . InternalCall ) ]
93
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
70
94
[ return : NotNullIfNotNull ( nameof ( location1 ) ) ]
71
- public static extern object ? Exchange ( [ NotNullIfNotNull ( nameof ( value ) ) ] ref object ? location1 , object ? value ) ;
95
+ public static object ? Exchange ( [ NotNullIfNotNull ( nameof ( value ) ) ] ref object ? location1 , object ? value )
96
+ {
97
+ if ( Unsafe . IsNullRef ( ref location1 ) )
98
+ ThrowHelper . ThrowNullReferenceException ( ) ;
99
+ return ExchangeObject ( ref location1 , value ) ;
100
+ }
101
+
102
+ [ return : NotNullIfNotNull ( nameof ( location1 ) ) ]
103
+ [ MethodImpl ( MethodImplOptions . InternalCall ) ]
104
+ private static extern object ? ExchangeObject ( [ NotNullIfNotNull ( nameof ( value ) ) ] ref object ? location1 , object ? value ) ;
72
105
73
106
// The below whole method reduces to a single call to Exchange(ref object, object) but
74
107
// the JIT thinks that it will generate more native code than it actually does.
@@ -84,7 +117,7 @@ public static long Decrement(ref long location) =>
84
117
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
85
118
public static T Exchange < T > ( [ NotNullIfNotNull ( nameof ( value ) ) ] ref T location1 , T value ) where T : class ? =>
86
119
Unsafe . As < T > ( Exchange ( ref Unsafe . As < T , object ? > ( ref location1 ) , value ) ) ;
87
- #endregion
120
+ #endregion
88
121
89
122
#region CompareExchange
90
123
/// <summary>Compares two 32-bit signed integers for equality and, if they are equal, replaces the first value.</summary>
@@ -94,8 +127,20 @@ public static T Exchange<T>([NotNullIfNotNull(nameof(value))] ref T location1, T
94
127
/// <returns>The original value in <paramref name="location1"/>.</returns>
95
128
/// <exception cref="NullReferenceException">The address of <paramref name="location1"/> is a null pointer.</exception>
96
129
[ Intrinsic ]
130
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
131
+ public static int CompareExchange ( ref int location1 , int value , int comparand )
132
+ {
133
+ #if TARGET_X86 || TARGET_AMD64 || TARGET_ARM64 || TARGET_RISCV64
134
+ return CompareExchange ( ref location1 , value , comparand ) ; // Must expand intrinsic
135
+ #else
136
+ if ( Unsafe . IsNullRef ( ref location1 ) )
137
+ ThrowHelper . ThrowNullReferenceException ( ) ;
138
+ return CompareExchange32 ( ref location1 , value , comparand ) ;
139
+ #endif
140
+ }
141
+
97
142
[ MethodImpl ( MethodImplOptions . InternalCall ) ]
98
- public static extern int CompareExchange ( ref int location1 , int value , int comparand ) ;
143
+ private static extern int CompareExchange32 ( ref int location1 , int value , int comparand ) ;
99
144
100
145
/// <summary>Compares two 64-bit signed integers for equality and, if they are equal, replaces the first value.</summary>
101
146
/// <param name="location1">The destination, whose value is compared with <paramref name="comparand"/> and possibly replaced.</param>
@@ -104,8 +149,20 @@ public static T Exchange<T>([NotNullIfNotNull(nameof(value))] ref T location1, T
104
149
/// <returns>The original value in <paramref name="location1"/>.</returns>
105
150
/// <exception cref="NullReferenceException">The address of <paramref name="location1"/> is a null pointer.</exception>
106
151
[ Intrinsic ]
152
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
153
+ public static long CompareExchange ( ref long location1 , long value , long comparand )
154
+ {
155
+ #if TARGET_AMD64 || TARGET_ARM64 || TARGET_RISCV64
156
+ return CompareExchange ( ref location1 , value , comparand ) ; // Must expand intrinsic
157
+ #else
158
+ if ( Unsafe . IsNullRef ( ref location1 ) )
159
+ ThrowHelper . ThrowNullReferenceException ( ) ;
160
+ return CompareExchange64 ( ref location1 , value , comparand ) ;
161
+ #endif
162
+ }
163
+
107
164
[ MethodImpl ( MethodImplOptions . InternalCall ) ]
108
- public static extern long CompareExchange ( ref long location1 , long value , long comparand ) ;
165
+ private static extern long CompareExchange64 ( ref long location1 , long value , long comparand ) ;
109
166
110
167
/// <summary>Compares two objects for reference equality and, if they are equal, replaces the first object.</summary>
111
168
/// <param name="location1">The destination object that is compared by reference with <paramref name="comparand"/> and possibly replaced.</param>
@@ -114,9 +171,18 @@ public static T Exchange<T>([NotNullIfNotNull(nameof(value))] ref T location1, T
114
171
/// <returns>The original value in <paramref name="location1"/>.</returns>
115
172
/// <exception cref="NullReferenceException">The address of <paramref name="location1"/> is a null pointer.</exception>
116
173
[ Intrinsic ]
174
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
175
+ [ return : NotNullIfNotNull ( nameof ( location1 ) ) ]
176
+ public static object ? CompareExchange ( ref object ? location1 , object ? value , object ? comparand )
177
+ {
178
+ if ( Unsafe . IsNullRef ( ref location1 ) )
179
+ ThrowHelper . ThrowNullReferenceException ( ) ;
180
+ return CompareExchangeObject ( ref location1 , value , comparand ) ;
181
+ }
182
+
117
183
[ MethodImpl ( MethodImplOptions . InternalCall ) ]
118
184
[ return : NotNullIfNotNull ( nameof ( location1 ) ) ]
119
- public static extern object ? CompareExchange ( ref object ? location1 , object ? value , object ? comparand ) ;
185
+ private static extern object ? CompareExchangeObject ( ref object ? location1 , object ? value , object ? comparand ) ;
120
186
121
187
// Note that getILIntrinsicImplementationForInterlocked() in vm\jitinterface.cpp replaces
122
188
// the body of the following method with the following IL:
@@ -136,8 +202,8 @@ public static T Exchange<T>([NotNullIfNotNull(nameof(value))] ref T location1, T
136
202
/// <exception cref="NullReferenceException">The address of <paramref name="location1"/> is a null pointer.</exception>
137
203
/// <typeparam name="T">The type to be used for <paramref name="location1"/>, <paramref name="value"/>, and <paramref name="comparand"/>. This type must be a reference type.</typeparam>
138
204
[ Intrinsic ]
139
- [ return : NotNullIfNotNull ( nameof ( location1 ) ) ]
140
205
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
206
+ [ return : NotNullIfNotNull ( nameof ( location1 ) ) ]
141
207
public static T CompareExchange < T > ( ref T location1 , T value , T comparand ) where T : class ? =>
142
208
Unsafe . As < T > ( CompareExchange ( ref Unsafe . As < T , object ? > ( ref location1 ) , value , comparand ) ) ;
143
209
#endregion
@@ -160,12 +226,36 @@ public static long Add(ref long location1, long value) =>
160
226
ExchangeAdd ( ref location1 , value ) + value ;
161
227
162
228
[ Intrinsic ]
229
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
230
+ private static int ExchangeAdd ( ref int location1 , int value )
231
+ {
232
+ #if TARGET_X86 || TARGET_AMD64 || TARGET_ARM64 || TARGET_RISCV64
233
+ return ExchangeAdd ( ref location1 , value ) ; // Must expand intrinsic
234
+ #else
235
+ if ( Unsafe . IsNullRef ( ref location1 ) )
236
+ ThrowHelper . ThrowNullReferenceException ( ) ;
237
+ return ExchangeAdd32 ( ref location1 , value ) ;
238
+ #endif
239
+ }
240
+
163
241
[ MethodImpl ( MethodImplOptions . InternalCall ) ]
164
- private static extern int ExchangeAdd ( ref int location1 , int value ) ;
242
+ private static extern int ExchangeAdd32 ( ref int location1 , int value ) ;
165
243
166
244
[ Intrinsic ]
245
+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
246
+ private static long ExchangeAdd ( ref long location1 , long value )
247
+ {
248
+ #if TARGET_AMD64 || TARGET_ARM64 || TARGET_RISCV64
249
+ return ExchangeAdd ( ref location1 , value ) ; // Must expand intrinsic
250
+ #else
251
+ if ( Unsafe . IsNullRef ( ref location1 ) )
252
+ ThrowHelper . ThrowNullReferenceException ( ) ;
253
+ return ExchangeAdd64 ( ref location1 , value ) ;
254
+ #endif
255
+ }
256
+
167
257
[ MethodImpl ( MethodImplOptions . InternalCall ) ]
168
- private static extern long ExchangeAdd ( ref long location1 , long value ) ;
258
+ private static extern long ExchangeAdd64 ( ref long location1 , long value ) ;
169
259
#endregion
170
260
171
261
#region Read
0 commit comments