Skip to content

Commit f7fad34

Browse files
MichalStrehovskyhez2010
authored andcommitted
Remove some RuntimeExport/RuntimeImport indirections (dotnet#110437)
We had indirections set up where we'd `RuntimeExport` a method under a symbolic name and then `RuntimeImport` it elsewhere (or call the export from JIT-generated code). Most of this was motivated by the old Redhawk layering where things like casting and interface dispatch were part of Runtime.Base and not part of CoreLib. Since we decided if we ever reintroduce a Runtime.Base, we wouldn't have casting in it, this indirection will no longer be needed. Motivated by dotnet#110267 (and also the reason why I'm only doing it for `RuntimeExport`s used from the JIT right now). Once that PR gets in, calling methods through `RuntimeExport`s would actually become a bigger deoptimization than it is now.
1 parent 8e63d8d commit f7fad34

File tree

20 files changed

+130
-72
lines changed

20 files changed

+130
-72
lines changed

src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CompilerServices/Unsafe.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,21 @@ namespace System.Runtime.CompilerServices
1616
/// </summary>
1717
public static unsafe class Unsafe
1818
{
19+
/// <summary>
20+
/// Determines the byte offset from origin to target from the given references.
21+
/// </summary>
22+
[Intrinsic]
23+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
24+
public static IntPtr ByteOffset<T>(ref readonly T origin, ref readonly T target)
25+
{
26+
throw new PlatformNotSupportedException();
27+
28+
// ldarg .1
29+
// ldarg .0
30+
// sub
31+
// ret
32+
}
33+
1934
/// <summary>
2035
/// Returns a pointer to the given by-ref parameter.
2136
/// </summary>

src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ public static unsafe object RhNewArray(MethodTable* pEEType, int length)
7373
}
7474
}
7575

76-
[RuntimeExport("RhBox")]
7776
public static unsafe object RhBox(MethodTable* pEEType, ref byte data)
7877
{
7978
// A null can be passed for boxing of a null ref.
@@ -207,7 +206,6 @@ public static unsafe void RhUnboxAny(object? o, ref byte data, MethodTable* pUnb
207206
//
208207
// Unbox helpers with RyuJIT conventions
209208
//
210-
[RuntimeExport("RhUnbox2")]
211209
public static unsafe ref byte RhUnbox2(MethodTable* pUnboxToEEType, object obj)
212210
{
213211
if ((obj == null) || !UnboxAnyTypeCompare(obj.GetMethodTable(), pUnboxToEEType))
@@ -218,7 +216,6 @@ public static unsafe ref byte RhUnbox2(MethodTable* pUnboxToEEType, object obj)
218216
return ref obj.GetRawData();
219217
}
220218

221-
[RuntimeExport("RhUnboxNullable")]
222219
public static unsafe void RhUnboxNullable(ref byte data, MethodTable* pUnboxToEEType, object obj)
223220
{
224221
if (obj != null && obj.GetMethodTable() != pUnboxToEEType->NullableType)
@@ -228,7 +225,6 @@ public static unsafe void RhUnboxNullable(ref byte data, MethodTable* pUnboxToEE
228225
RhUnbox(obj, ref data, pUnboxToEEType);
229226
}
230227

231-
[RuntimeExport("RhUnboxTypeTest")]
232228
public static unsafe void RhUnboxTypeTest(MethodTable* pType, MethodTable* pBoxType)
233229
{
234230
Debug.Assert(pType->IsValueType);

src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ internal enum AssignmentVariation
6363
// IsInstanceOf test used for unusual cases (naked type parameters, variant generic types)
6464
// Unlike the IsInstanceOfInterface and IsInstanceOfClass functions,
6565
// this test must deal with all kinds of type tests
66-
[RuntimeExport("RhTypeCast_IsInstanceOfAny")]
6766
public static unsafe object? IsInstanceOfAny(MethodTable* pTargetType, object? obj)
6867
{
6968
if (obj != null)
@@ -94,7 +93,6 @@ internal enum AssignmentVariation
9493
return IsInstanceOfAny_NoCacheLookup(pTargetType, obj);
9594
}
9695

97-
[RuntimeExport("RhTypeCast_IsInstanceOfInterface")]
9896
public static unsafe object? IsInstanceOfInterface(MethodTable* pTargetType, object? obj)
9997
{
10098
Debug.Assert(pTargetType->IsInterface);
@@ -184,7 +182,6 @@ internal enum AssignmentVariation
184182
return obj;
185183
}
186184

187-
[RuntimeExport("RhTypeCast_IsInstanceOfClass")]
188185
public static unsafe object? IsInstanceOfClass(MethodTable* pTargetType, object? obj)
189186
{
190187
Debug.Assert(!pTargetType->IsParameterizedType, "IsInstanceOfClass called with parameterized MethodTable");
@@ -248,7 +245,6 @@ internal enum AssignmentVariation
248245
return obj;
249246
}
250247

251-
[RuntimeExport("RhTypeCast_IsInstanceOfException")]
252248
public static unsafe bool IsInstanceOfException(MethodTable* pTargetType, object? obj)
253249
{
254250
// Based on IsInstanceOfClass
@@ -279,7 +275,6 @@ public static unsafe bool IsInstanceOfException(MethodTable* pTargetType, object
279275
// ChkCast test used for unusual cases (naked type parameters, variant generic types)
280276
// Unlike the ChkCastInterface and ChkCastClass functions,
281277
// this test must deal with all kinds of type tests
282-
[RuntimeExport("RhTypeCast_CheckCastAny")]
283278
public static unsafe object CheckCastAny(MethodTable* pTargetType, object obj)
284279
{
285280
CastResult result;
@@ -307,7 +302,6 @@ public static unsafe object CheckCastAny(MethodTable* pTargetType, object obj)
307302
return objRet;
308303
}
309304

310-
[RuntimeExport("RhTypeCast_CheckCastInterface")]
311305
public static unsafe object CheckCastInterface(MethodTable* pTargetType, object obj)
312306
{
313307
Debug.Assert(pTargetType->IsInterface);
@@ -393,7 +387,6 @@ private static unsafe object CheckCastInterface_Helper(MethodTable* pTargetType,
393387
return ThrowInvalidCastException(pTargetType);
394388
}
395389

396-
[RuntimeExport("RhTypeCast_CheckCastClass")]
397390
public static unsafe object CheckCastClass(MethodTable* pTargetType, object obj)
398391
{
399392
Debug.Assert(!pTargetType->IsParameterizedType, "CheckCastClass called with parameterized MethodTable");
@@ -411,7 +404,6 @@ public static unsafe object CheckCastClass(MethodTable* pTargetType, object obj)
411404

412405
// Optimized helper for classes. Assumes that the trivial cases
413406
// has been taken care of by the inlined check
414-
[RuntimeExport("RhTypeCast_CheckCastClassSpecial")]
415407
private static unsafe object CheckCastClassSpecial(MethodTable* pTargetType, object obj)
416408
{
417409
Debug.Assert(!pTargetType->IsParameterizedType, "CheckCastClassSpecial called with parameterized MethodTable");
@@ -761,8 +753,6 @@ private static unsafe void ThrowArrayMismatchException(object?[] array)
761753
//
762754
// Array stelem/ldelema helpers with RyuJIT conventions
763755
//
764-
765-
[RuntimeExport("RhpLdelemaRef")]
766756
public static unsafe ref object? LdelemaRef(object?[] array, nint index, MethodTable* elementType)
767757
{
768758
Debug.Assert(array is null || array.GetMethodTable()->IsArray, "first argument must be an array");
@@ -794,7 +784,6 @@ private static unsafe void ThrowArrayMismatchException(object?[] array)
794784
return ref element;
795785
}
796786

797-
[RuntimeExport("RhpStelemRef")]
798787
public static unsafe void StelemRef(object?[] array, nint index, object? obj)
799788
{
800789
// This is supported only on arrays

src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ public static unsafe void StoreValueTypeField(IntPtr address, object fieldValue,
216216

217217
public static unsafe object LoadValueTypeField(IntPtr address, RuntimeTypeHandle fieldType)
218218
{
219-
return RuntimeImports.RhBox(fieldType.ToMethodTable(), ref *(byte*)address);
219+
return RuntimeExports.RhBox(fieldType.ToMethodTable(), ref *(byte*)address);
220220
}
221221

222222
public static unsafe object LoadPointerTypeField(IntPtr address, RuntimeTypeHandle fieldType)
@@ -236,15 +236,15 @@ public static unsafe void StoreValueTypeField(object obj, int fieldOffset, objec
236236
public static unsafe object LoadValueTypeField(object obj, int fieldOffset, RuntimeTypeHandle fieldType)
237237
{
238238
ref byte address = ref Unsafe.AddByteOffset(ref obj.GetRawData(), new IntPtr(fieldOffset - ObjectHeaderSize));
239-
return RuntimeImports.RhBox(fieldType.ToMethodTable(), ref address);
239+
return RuntimeExports.RhBox(fieldType.ToMethodTable(), ref address);
240240
}
241241

242242
public static unsafe object LoadPointerTypeField(object obj, int fieldOffset, RuntimeTypeHandle fieldType)
243243
{
244244
ref byte address = ref Unsafe.AddByteOffset(ref obj.GetRawData(), new IntPtr(fieldOffset - ObjectHeaderSize));
245245

246246
if (fieldType.ToMethodTable()->IsFunctionPointer)
247-
return RuntimeImports.RhBox(MethodTable.Of<IntPtr>(), ref address);
247+
return RuntimeExports.RhBox(MethodTable.Of<IntPtr>(), ref address);
248248

249249
return ReflectionPointer.Box((void*)Unsafe.As<byte, IntPtr>(ref address), Type.GetTypeFromHandle(fieldType));
250250
}
@@ -285,7 +285,7 @@ public static object LoadValueTypeFieldValueFromValueType(TypedReference typedRe
285285
Debug.Assert(TypedReference.TargetTypeToken(typedReference).ToMethodTable()->IsValueType);
286286
Debug.Assert(fieldTypeHandle.ToMethodTable()->IsValueType);
287287

288-
return RuntimeImports.RhBox(fieldTypeHandle.ToMethodTable(), ref Unsafe.Add<byte>(ref typedReference.Value, fieldOffset));
288+
return RuntimeExports.RhBox(fieldTypeHandle.ToMethodTable(), ref Unsafe.Add<byte>(ref typedReference.Value, fieldOffset));
289289
}
290290

291291
[CLSCompliant(false)]
@@ -391,7 +391,7 @@ public static bool IsInterface(RuntimeTypeHandle type)
391391

392392
public static unsafe object Box(RuntimeTypeHandle type, IntPtr address)
393393
{
394-
return RuntimeImports.RhBox(type.ToMethodTable(), ref *(byte*)address);
394+
return RuntimeExports.RhBox(type.ToMethodTable(), ref *(byte*)address);
395395
}
396396

397397
//==============================================================================================

src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ private static unsafe void CopyImplGcRefArray(Array sourceArray, int sourceIndex
330330
for (int i = 0; i < length; i++)
331331
{
332332
object? value = Unsafe.Add(ref refSourceArray, sourceIndex - i);
333-
if (mustCastCheckEachElement && value != null && RuntimeImports.IsInstanceOf(destinationElementEEType, value) == null)
333+
if (mustCastCheckEachElement && value != null && TypeCast.IsInstanceOfAny(destinationElementEEType, value) == null)
334334
throw new InvalidCastException(SR.InvalidCast_DownCastArrayElement);
335335
Unsafe.Add(ref refDestinationArray, destinationIndex - i) = value;
336336
}
@@ -340,7 +340,7 @@ private static unsafe void CopyImplGcRefArray(Array sourceArray, int sourceIndex
340340
for (int i = 0; i < length; i++)
341341
{
342342
object? value = Unsafe.Add(ref refSourceArray, sourceIndex + i);
343-
if (mustCastCheckEachElement && value != null && RuntimeImports.IsInstanceOf(destinationElementEEType, value) == null)
343+
if (mustCastCheckEachElement && value != null && TypeCast.IsInstanceOfAny(destinationElementEEType, value) == null)
344344
throw new InvalidCastException(SR.InvalidCast_DownCastArrayElement);
345345
Unsafe.Add(ref refDestinationArray, destinationIndex + i) = value;
346346
}
@@ -370,7 +370,7 @@ private static unsafe void CopyImplValueTypeArrayToReferenceArray(Array sourceAr
370370
ref object refDestinationArray = ref Unsafe.As<byte, object>(ref MemoryMarshal.GetArrayDataReference(destinationArray));
371371
for (int i = 0; i < length; i++)
372372
{
373-
object boxedValue = RuntimeImports.RhBox(sourceElementEEType, ref *pElement);
373+
object boxedValue = RuntimeExports.RhBox(sourceElementEEType, ref *pElement);
374374
Unsafe.Add(ref refDestinationArray, destinationIndex + i) = boxedValue;
375375
pElement += sourceElementSize;
376376
}
@@ -457,7 +457,7 @@ private static unsafe void CopyImplValueTypeArrayWithInnerGcRefs(Array sourceArr
457457
pDestinationElement -= cbElementSize;
458458
}
459459

460-
object boxedValue = RuntimeImports.RhBox(sourceElementEEType, ref *pSourceElement);
460+
object boxedValue = RuntimeExports.RhBox(sourceElementEEType, ref *pSourceElement);
461461
if (boxedElements != null)
462462
boxedElements[i] = boxedValue;
463463
else
@@ -768,7 +768,7 @@ internal unsafe nint GetFlattenedIndex(ReadOnlySpan<int> indices)
768768
MethodTable* pElementEEType = ElementMethodTable;
769769
if (pElementEEType->IsValueType)
770770
{
771-
return RuntimeImports.RhBox(pElementEEType, ref element);
771+
return RuntimeExports.RhBox(pElementEEType, ref element);
772772
}
773773
else
774774
{

src/coreclr/nativeaot/System.Private.CoreLib/src/System/InvokeUtils.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ private static Exception ConvertOrWidenPrimitivesEnumsAndPointersIfPossible(obje
133133
if (dstElementType == srcElementType)
134134
{
135135
// Rebox the value if the EETypeElementTypes match
136-
dstObject = RuntimeImports.RhBox(dstEEType, ref srcObject.GetRawData());
136+
dstObject = RuntimeExports.RhBox(dstEEType, ref srcObject.GetRawData());
137137
}
138138
else
139139
{

src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ private unsafe void CopyBackToArray(ref object? src, object?[] dest)
783783
}
784784
else
785785
{
786-
obj = RuntimeImports.RhBox(
786+
obj = RuntimeExports.RhBox(
787787
(transform & Transform.FunctionPointer) != 0 ? MethodTable.Of<IntPtr>() : argumentInfo.Type,
788788
ref obj.GetRawData());
789789
}
@@ -818,7 +818,7 @@ private unsafe void CopyBackToSpan(Span<object?> src, Span<object?> dest)
818818
}
819819
else
820820
{
821-
obj = RuntimeImports.RhBox(
821+
obj = RuntimeExports.RhBox(
822822
(transform & Transform.FunctionPointer) != 0 ? MethodTable.Of<IntPtr>() : argumentInfo.Type,
823823
ref obj.GetRawData());
824824
}
@@ -849,7 +849,7 @@ private unsafe object ReturnTransform(ref byte byref, bool wrapInTargetInvocatio
849849
else if ((_returnTransform & Transform.FunctionPointer) != 0)
850850
{
851851
Debug.Assert(Type.GetTypeFromMethodTable(_returnType).IsFunctionPointer);
852-
obj = RuntimeImports.RhBox(MethodTable.Of<IntPtr>(), ref byref);
852+
obj = RuntimeExports.RhBox(MethodTable.Of<IntPtr>(), ref byref);
853853
}
854854
else if ((_returnTransform & Transform.Reference) != 0)
855855
{
@@ -859,7 +859,7 @@ private unsafe object ReturnTransform(ref byte byref, bool wrapInTargetInvocatio
859859
else
860860
{
861861
Debug.Assert((_returnTransform & (Transform.ByRef | Transform.Nullable)) != 0);
862-
obj = RuntimeImports.RhBox(_returnType, ref byref);
862+
obj = RuntimeExports.RhBox(_returnType, ref byref);
863863
}
864864
return obj;
865865
}

src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ public static unsafe object GetUninitializedObject(
380380
if (mt->IsByRefLike)
381381
throw new NotSupportedException(SR.NotSupported_ByRefLike);
382382

383-
return RuntimeImports.RhBox(mt, ref target);
383+
return RuntimeExports.RhBox(mt, ref target);
384384
}
385385

386386
/// <summary>

src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -379,10 +379,6 @@ internal static IntPtr RhHandleAllocDependent(object primary, object secondary)
379379
[RuntimeImport(RuntimeLibrary, "RhTypeCast_CheckArrayStore")]
380380
internal static extern void RhCheckArrayStore(object array, object? obj);
381381

382-
[MethodImpl(MethodImplOptions.InternalCall)]
383-
[RuntimeImport(RuntimeLibrary, "RhTypeCast_IsInstanceOfAny")]
384-
internal static extern unsafe object IsInstanceOf(MethodTable* pTargetType, object obj);
385-
386382
//
387383
// calls to runtime for allocation
388384
// These calls are needed in types which cannot use "new" to allocate and need to do it manually
@@ -405,10 +401,6 @@ internal static IntPtr RhHandleAllocDependent(object primary, object secondary)
405401
[RuntimeImport(RuntimeLibrary, "RhNewString")]
406402
internal static extern unsafe string RhNewString(MethodTable* pEEType, int length);
407403

408-
[MethodImpl(MethodImplOptions.InternalCall)]
409-
[RuntimeImport(RuntimeLibrary, "RhBox")]
410-
internal static extern unsafe object RhBox(MethodTable* pEEType, ref byte data);
411-
412404
[MethodImpl(MethodImplOptions.InternalCall)]
413405
[RuntimeImport(RuntimeLibrary, "RhUnbox")]
414406
internal static extern unsafe void RhUnbox(object? obj, ref byte data, MethodTable* pUnboxToEEType);

src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeType.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ public override bool IsInstanceOfType([NotNullWhen(true)] object? o)
630630
return false;
631631
if (pEEType->IsNullable)
632632
pEEType = pEEType->NullableType;
633-
return RuntimeImports.IsInstanceOf(pEEType, o) != null;
633+
return TypeCast.IsInstanceOfAny(pEEType, o) != null;
634634
}
635635

636636
//

0 commit comments

Comments
 (0)