-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Remove invalid Unsafe.As from array helpers #99778
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
198de58
9d72f6c
e4b716e
097207a
41608a5
55aaf7d
ea23fe4
463678a
0f6104c
8b98907
e59ad83
ebf890a
0d69258
1bdb1f6
e4a3096
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,8 @@ namespace System.Runtime | |
// | ||
///////////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
[StackTraceHidden] | ||
[DebuggerStepThrough] | ||
[EagerStaticClassConstruction] | ||
internal static class TypeCast | ||
{ | ||
|
@@ -737,23 +739,69 @@ public static unsafe void CheckArrayStore(object array, object obj) | |
throw array.GetMethodTable()->GetClasslibException(ExceptionIDs.ArrayTypeMismatch); | ||
} | ||
|
||
internal struct ArrayElement | ||
private static unsafe void ThrowIndexOutOfRangeException(object?[] array) | ||
{ | ||
public object Value; | ||
// Throw the index out of range exception defined by the classlib, using the input array's MethodTable* | ||
// to find the correct classlib. | ||
throw array.GetMethodTable()->GetClasslibException(ExceptionIDs.IndexOutOfRange); | ||
} | ||
|
||
private static unsafe void ThrowArrayMismatchException(object?[] array) | ||
{ | ||
// Throw the array type mismatch exception defined by the classlib, using the input array's MethodTable* | ||
// to find the correct classlib. | ||
throw array.GetMethodTable()->GetClasslibException(ExceptionIDs.ArrayTypeMismatch); | ||
} | ||
|
||
// | ||
// Array stelem/ldelema helpers with RyuJIT conventions | ||
// | ||
|
||
[RuntimeExport("RhpLdelemaRef")] | ||
public static unsafe ref object? LdelemaRef(object?[] array, nint index, MethodTable* elementType) | ||
{ | ||
Debug.Assert(array is null || array.GetMethodTable()->IsArray, "first argument must be an array"); | ||
|
||
#if INPLACE_RUNTIME | ||
// This will throw NullReferenceException if obj is null. | ||
if ((nuint)index >= (uint)array.Length) | ||
ThrowIndexOutOfRangeException(array); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can just use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wanted to remove the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test.CoreLib is very minimal implementation of CoreLib for testing, debugging and various experiments. It is fine to add minimal implementations of MemoryMarshal or ThrowHelper to it to keep it working. |
||
|
||
Debug.Assert(index >= 0); | ||
ref object? element = ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), index); | ||
#else | ||
if (array is null) | ||
{ | ||
throw elementType->GetClasslibException(ExceptionIDs.NullReference); | ||
} | ||
if ((nuint)index >= (uint)array.Length) | ||
{ | ||
throw elementType->GetClasslibException(ExceptionIDs.IndexOutOfRange); | ||
} | ||
ref object rawData = ref Unsafe.As<byte, object>(ref Unsafe.As<RawArrayData>(array).Data); | ||
ref object element = ref Unsafe.Add(ref rawData, index); | ||
#endif | ||
MethodTable* arrayElemType = array.GetMethodTable()->RelatedParameterType; | ||
|
||
if (elementType != arrayElemType) | ||
ThrowArrayMismatchException(array); | ||
|
||
return ref element; | ||
} | ||
|
||
[RuntimeExport("RhpStelemRef")] | ||
public static unsafe void StelemRef(Array array, nint index, object obj) | ||
public static unsafe void StelemRef(object?[] array, nint index, object? obj) | ||
{ | ||
// This is supported only on arrays | ||
Debug.Assert(array.GetMethodTable()->IsArray, "first argument must be an array"); | ||
Debug.Assert(array is null || array.GetMethodTable()->IsArray, "first argument must be an array"); | ||
|
||
#if INPLACE_RUNTIME | ||
// this will throw appropriate exceptions if array is null or access is out of range. | ||
ref object element = ref Unsafe.As<ArrayElement[]>(array)[index].Value; | ||
// This will throw NullReferenceException if obj is null. | ||
if ((nuint)index >= (uint)array.Length) | ||
ThrowIndexOutOfRangeException(array); | ||
|
||
Debug.Assert(index >= 0); | ||
ref object? element = ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), index); | ||
#else | ||
if (array is null) | ||
{ | ||
|
@@ -796,7 +844,7 @@ public static unsafe void StelemRef(Array array, nint index, object obj) | |
} | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
private static unsafe void StelemRef_Helper(ref object element, MethodTable* elementType, object obj) | ||
private static unsafe void StelemRef_Helper(ref object? element, MethodTable* elementType, object obj) | ||
{ | ||
CastResult result = s_castCache.TryGet((nuint)obj.GetMethodTable() + (int)AssignmentVariation.BoxedSource, (nuint)elementType); | ||
if (result == CastResult.CanCast) | ||
|
@@ -808,58 +856,17 @@ private static unsafe void StelemRef_Helper(ref object element, MethodTable* ele | |
StelemRef_Helper_NoCacheLookup(ref element, elementType, obj); | ||
} | ||
|
||
private static unsafe void StelemRef_Helper_NoCacheLookup(ref object element, MethodTable* elementType, object obj) | ||
private static unsafe void StelemRef_Helper_NoCacheLookup(ref object? element, MethodTable* elementType, object obj) | ||
{ | ||
object? castedObj = IsInstanceOfAny_NoCacheLookup(elementType, obj); | ||
if (castedObj != null) | ||
if (castedObj == null) | ||
{ | ||
InternalCalls.RhpAssignRef(ref element, obj); | ||
return; | ||
// Throw the array type mismatch exception defined by the classlib, using the input array's | ||
// MethodTable* to find the correct classlib. | ||
throw elementType->GetClasslibException(ExceptionIDs.ArrayTypeMismatch); | ||
} | ||
|
||
// Throw the array type mismatch exception defined by the classlib, using the input array's | ||
// MethodTable* to find the correct classlib. | ||
throw elementType->GetClasslibException(ExceptionIDs.ArrayTypeMismatch); | ||
} | ||
|
||
[RuntimeExport("RhpLdelemaRef")] | ||
public static unsafe ref object LdelemaRef(Array array, nint index, IntPtr elementType) | ||
{ | ||
Debug.Assert(array is null || array.GetMethodTable()->IsArray, "first argument must be an array"); | ||
|
||
#if INPLACE_RUNTIME | ||
// this will throw appropriate exceptions if array is null or access is out of range. | ||
ref object element = ref Unsafe.As<ArrayElement[]>(array)[index].Value; | ||
#else | ||
if (array is null) | ||
{ | ||
throw ((MethodTable*)elementType)->GetClasslibException(ExceptionIDs.NullReference); | ||
} | ||
if ((uint)index >= (uint)array.Length) | ||
{ | ||
throw ((MethodTable*)elementType)->GetClasslibException(ExceptionIDs.IndexOutOfRange); | ||
} | ||
ref object rawData = ref Unsafe.As<byte, object>(ref Unsafe.As<RawArrayData>(array).Data); | ||
ref object element = ref Unsafe.Add(ref rawData, index); | ||
#endif | ||
|
||
MethodTable* elemType = (MethodTable*)elementType; | ||
MethodTable* arrayElemType = array.GetMethodTable()->RelatedParameterType; | ||
|
||
if (elemType == arrayElemType) | ||
{ | ||
return ref element; | ||
} | ||
|
||
return ref ThrowArrayMismatchException(array); | ||
} | ||
|
||
// This weird structure is for parity with CoreCLR - allows potentially to be tailcalled | ||
private static unsafe ref object ThrowArrayMismatchException(Array array) | ||
{ | ||
// Throw the array type mismatch exception defined by the classlib, using the input array's MethodTable* | ||
// to find the correct classlib. | ||
throw array.GetMethodTable()->GetClasslibException(ExceptionIDs.ArrayTypeMismatch); | ||
InternalCalls.RhpAssignRef(ref element, obj); | ||
} | ||
|
||
private static unsafe object IsInstanceOfArray(MethodTable* pTargetType, object obj) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
namespace System.Diagnostics | ||
{ | ||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false)] | ||
public sealed class DebuggerStepThroughAttribute : Attribute | ||
{ | ||
public DebuggerStepThroughAttribute() { } | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.