DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pSZArrayHelperClass, ::g_pSZArrayHelperClass)
DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pNullableClass, ::g_pNullableClass)
#ifdef FEATURE_SPAN_OF_T
-DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pSpanClass, ::g_pSpanClass)
-DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pReadOnlySpanClass, ::g_pReadOnlySpanClass)
+DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pByReferenceClass, ::g_pByReferenceClass)
#endif
DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pExceptionClass, ::g_pExceptionClass)
DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pThreadAbortExceptionClass, ::g_pThreadAbortExceptionClass)
<Member Name="#ctor(T[],System.Int32)" />
<Member Name="#ctor(T[],System.Int32,System.Int32)" />
<Member Name="#ctor(System.Void*,System.Int32)" />
+ <Member Name="DangerousGetPinnableReference" />
<Member Name="op_Implicit(T[])" ReturnType="System.Span<T>" />
<Member Name="op_Implicit(System.ArraySegment<T>)" ReturnType="System.Span<T>" />
<Member Name="get_Length" />
<Member Name="#ctor(T[],System.Int32)" />
<Member Name="#ctor(T[],System.Int32,System.Int32)" />
<Member Name="#ctor(System.Void*,System.Int32)" />
+ <Member Name="DangerousGetPinnableReference" />
<Member Name="op_Implicit(System.Span<T>)" ReturnType="System.ReadOnlySpan<T>" />
<Member Name="op_Implicit(T[])" ReturnType="System.ReadOnlySpan<T>" />
<Member Name="op_Implicit(System.ArraySegment<T>)" ReturnType="System.ReadOnlySpan<T>" />
<SystemSources Condition="'$(FeatureCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\__ComObject.cs" />
<SystemSources Condition="'$(FeatureCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\Variant.cs" />
<SystemSources Condition="'$(FeatureClassicCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\OleAutBinder.cs" />
+ <SystemSources Condition="'$(FeatureSpanOfT)' == 'true'" Include="$(BclSourcesRoot)\System\ByReference.cs" />
<SystemSources Condition="'$(FeatureSpanOfT)' == 'true'" Include="$(BclSourcesRoot)\System\Span.cs" />
<SystemSources Condition="'$(FeatureSpanOfT)' == 'true'" Include="$(BclSourcesRoot)\System\ReadOnlySpan.cs" />
</ItemGroup>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.CompilerServices;
+
+namespace System
+{
+ // ByReference<T> is meant to be used to represent "ref T" fields. It is working
+ // around lack of first class support for byref fields in C# and IL. The JIT and
+ // type loader has special handling for it that turns it into a thin wrapper around ref T.
+ internal struct ByReference<T>
+ {
+ private IntPtr _value;
+
+ public ByReference(ref T value)
+ {
+ // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead
+ unsafe { _value = (IntPtr)Unsafe.AsPointer(ref value); }
+ }
+
+ public ref T Value
+ {
+ get
+ {
+ // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead
+ unsafe { return ref Unsafe.As<IntPtr, T>(ref *(IntPtr*)_value); }
+ }
+ }
+ }
+}
/// characteristics on par with T[]. Unlike arrays, it can point to either managed
/// or native memory, or to memory allocated on the stack. It is type- and memory-safe.
/// </summary>
- public unsafe struct ReadOnlySpan<T>
+ public struct ReadOnlySpan<T>
{
- /// <summary>A byref or a native ptr. Do not access directly</summary>
- private readonly IntPtr _rawPointer;
+ /// <summary>A byref or a native ptr.</summary>
+ private readonly ByReference<T> _pointer;
/// <summary>The number of elements this ReadOnlySpan contains.</summary>
private readonly int _length;
if (array == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
- // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead
- _rawPointer = (IntPtr)Unsafe.AsPointer(ref JitHelpers.GetArrayData(array));
+ _pointer = new ByReference<T>(ref JitHelpers.GetArrayData(array));
_length = array.Length;
}
if ((uint)start > (uint)array.Length)
ThrowHelper.ThrowArgumentOutOfRangeException();
- // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead
- _rawPointer = (IntPtr)Unsafe.AsPointer(ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start));
+ _pointer = new ByReference<T>(ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start));
_length = array.Length - start;
}
if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start))
ThrowHelper.ThrowArgumentOutOfRangeException();
- // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead
- _rawPointer = (IntPtr)Unsafe.AsPointer(ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start));
+ _pointer = new ByReference<T>(ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start));
_length = length;
}
if (length < 0)
ThrowHelper.ThrowArgumentOutOfRangeException();
- _rawPointer = (IntPtr)pointer;
+ _pointer = new ByReference<T>(ref Unsafe.AsRef<T>(pointer));
_length = length;
}
/// </summary>
internal ReadOnlySpan(ref T ptr, int length)
{
- // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead
- _rawPointer = (IntPtr)Unsafe.AsPointer(ref ptr);
+ _pointer = new ByReference<T>(ref ptr);
_length = length;
}
/// <summary>
- /// An internal helper for accessing spans.
+ /// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element
+ /// would have been stored. Such a reference can be used for pinning but must never be dereferenced.
/// </summary>
- internal unsafe ref T GetRawPointer()
+ public ref T DangerousGetPinnableReference()
{
- // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead
- return ref Unsafe.As<IntPtr, T>(ref *(IntPtr *)_rawPointer);
+ return ref _pointer.Value;
}
/// <summary>
/// </summary>
public static implicit operator ReadOnlySpan<T>(Span<T> slice)
{
- return new ReadOnlySpan<T>(ref slice.GetRawPointer(), slice.Length);
+ return new ReadOnlySpan<T>(ref slice.DangerousGetPinnableReference(), slice.Length);
}
/// <summary>
if ((uint)index >= (uint)_length)
ThrowHelper.ThrowIndexOutOfRangeException();
- return Unsafe.Add(ref GetRawPointer(), index);
+ return Unsafe.Add(ref DangerousGetPinnableReference(), index);
}
}
return Array.Empty<T>();
var destination = new T[_length];
- SpanHelper.CopyTo<T>(ref JitHelpers.GetArrayData(destination), ref GetRawPointer(), _length);
+ SpanHelper.CopyTo<T>(ref JitHelpers.GetArrayData(destination), ref DangerousGetPinnableReference(), _length);
return destination;
}
if ((uint)start > (uint)_length)
ThrowHelper.ThrowArgumentOutOfRangeException();
- return new ReadOnlySpan<T>(ref Unsafe.Add(ref GetRawPointer(), start), _length - start);
+ return new ReadOnlySpan<T>(ref Unsafe.Add(ref DangerousGetPinnableReference(), start), _length - start);
}
/// <summary>
if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start))
ThrowHelper.ThrowArgumentOutOfRangeException();
- return new ReadOnlySpan<T>(ref Unsafe.Add(ref GetRawPointer(), start), length);
+ return new ReadOnlySpan<T>(ref Unsafe.Add(ref DangerousGetPinnableReference(), start), length);
}
/// <summary>
public bool Equals(ReadOnlySpan<T> other)
{
return (_length == other.Length) &&
- (_length == 0 || Unsafe.AreSame(ref GetRawPointer(), ref other.GetRawPointer()));
+ (_length == 0 || Unsafe.AreSame(ref DangerousGetPinnableReference(), ref other.DangerousGetPinnableReference()));
}
/// <summary>
if ((uint)_length > (uint)destination.Length)
return false;
- SpanHelper.CopyTo<T>(ref destination.GetRawPointer(), ref GetRawPointer(), _length);
+ SpanHelper.CopyTo<T>(ref destination.DangerousGetPinnableReference(), ref DangerousGetPinnableReference(), _length);
return true;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void* AsPointer<T>(ref T value)
{
- // The body of this function will be replaced by the EE with unsafe code that just returns sizeof !!T
+ // The body of this function will be replaced by the EE with unsafe code!!!
// See getILIntrinsicImplementationForUnsafe for how this happens.
throw new InvalidOperationException();
}
}
/// <summary>
+ /// Reinterprets the given location as a reference to a value of type<typeparamref name="T"/>.
+ /// </summary>
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ref T AsRef<T>(void * source)
+ {
+ // The body of this function will be replaced by the EE with unsafe code!!!
+ // See getILIntrinsicImplementationForUnsafe for how this happens.
+ throw new InvalidOperationException();
+ }
+
+ /// <summary>
/// Reinterprets the given reference as a reference to a value of type <typeparamref name="TTo"/>.
/// </summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref TTo As<TFrom, TTo>(ref TFrom source)
{
- // The body of this function will be replaced by the EE with unsafe code that just returns sizeof !!T
+ // The body of this function will be replaced by the EE with unsafe code!!!
// See getILIntrinsicImplementationForUnsafe for how this happens.
throw new InvalidOperationException();
}
/// characteristics on par with T[]. Unlike arrays, it can point to either managed
/// or native memory, or to memory allocated on the stack. It is type- and memory-safe.
/// </summary>
- public unsafe struct Span<T>
+ public struct Span<T>
{
- /// <summary>A byref or a native ptr. Do not access directly</summary>
- private readonly IntPtr _rawPointer;
+ /// <summary>A byref or a native ptr.</summary>
+ private readonly ByReference<T> _pointer;
/// <summary>The number of elements this Span contains.</summary>
private readonly int _length;
ThrowHelper.ThrowArrayTypeMismatchException();
}
- // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead
- _rawPointer = (IntPtr)Unsafe.AsPointer(ref JitHelpers.GetArrayData(array));
+ _pointer = new ByReference<T>(ref JitHelpers.GetArrayData(array));
_length = array.Length;
}
if ((uint)start > (uint)array.Length)
ThrowHelper.ThrowArgumentOutOfRangeException();
- // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead
- _rawPointer = (IntPtr)Unsafe.AsPointer(ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start));
+ _pointer = new ByReference<T>(ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start));
_length = array.Length - start;
}
if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start))
ThrowHelper.ThrowArgumentOutOfRangeException();
- // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead
- _rawPointer = (IntPtr)Unsafe.AsPointer(ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start));
+ _pointer = new ByReference<T>(ref Unsafe.Add(ref JitHelpers.GetArrayData(array), start));
_length = length;
}
if (length < 0)
ThrowHelper.ThrowArgumentOutOfRangeException();
- _rawPointer = (IntPtr)pointer;
+ _pointer = new ByReference<T>(ref Unsafe.AsRef<T>(pointer));
_length = length;
}
/// </summary>
internal Span(ref T ptr, int length)
{
- // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead
- _rawPointer = (IntPtr)Unsafe.AsPointer(ref ptr);
+ _pointer = new ByReference<T>(ref ptr);
_length = length;
}
/// <summary>
- /// An internal helper for accessing spans.
+ /// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element
+ /// would have been stored. Such a reference can be used for pinning but must never be dereferenced.
/// </summary>
- internal unsafe ref T GetRawPointer()
+ public ref T DangerousGetPinnableReference()
{
- // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead
- return ref Unsafe.As<IntPtr, T>(ref *(IntPtr*)_rawPointer);
+ return ref _pointer.Value;
}
/// <summary>
if ((uint)index >= (uint)_length)
ThrowHelper.ThrowIndexOutOfRangeException();
- return Unsafe.Add(ref GetRawPointer(), index);
+ return Unsafe.Add(ref DangerousGetPinnableReference(), index);
}
set
{
if ((uint)index >= (uint)_length)
ThrowHelper.ThrowIndexOutOfRangeException();
- Unsafe.Add(ref GetRawPointer(), index) = value;
+ Unsafe.Add(ref DangerousGetPinnableReference(), index) = value;
}
}
return Array.Empty<T>();
var destination = new T[_length];
- SpanHelper.CopyTo<T>(ref JitHelpers.GetArrayData(destination), ref GetRawPointer(), _length);
+ SpanHelper.CopyTo<T>(ref JitHelpers.GetArrayData(destination), ref DangerousGetPinnableReference(), _length);
return destination;
}
if ((uint)start > (uint)_length)
ThrowHelper.ThrowArgumentOutOfRangeException();
- return new Span<T>(ref Unsafe.Add(ref GetRawPointer(), start), _length - start);
+ return new Span<T>(ref Unsafe.Add(ref DangerousGetPinnableReference(), start), _length - start);
}
/// <summary>
if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start))
ThrowHelper.ThrowArgumentOutOfRangeException();
- return new Span<T>(ref Unsafe.Add(ref GetRawPointer(), start), length);
+ return new Span<T>(ref Unsafe.Add(ref DangerousGetPinnableReference(), start), length);
}
/// <summary>
public bool Equals(Span<T> other)
{
return (_length == other.Length) &&
- (_length == 0 || Unsafe.AreSame(ref GetRawPointer(), ref other.GetRawPointer()));
+ (_length == 0 || Unsafe.AreSame(ref DangerousGetPinnableReference(), ref other.DangerousGetPinnableReference()));
}
/// <summary>
if ((uint)_length > (uint)destination.Length)
return false;
- SpanHelper.CopyTo<T>(ref destination.GetRawPointer(), ref GetRawPointer(), _length);
+ SpanHelper.CopyTo<T>(ref destination.DangerousGetPinnableReference(), ref DangerousGetPinnableReference(), _length);
return true;
}
if ((uint)values.Length > (uint)_length)
ThrowHelper.ThrowArgumentOutOfRangeException();
- SpanHelper.CopyTo<T>(ref GetRawPointer(), ref values.GetRawPointer(), values.Length);
+ SpanHelper.CopyTo<T>(ref DangerousGetPinnableReference(), ref values.DangerousGetPinnableReference(), values.Length);
}
}
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
return new Span<byte>(
- ref Unsafe.As<T, byte>(ref source.GetRawPointer()),
+ ref Unsafe.As<T, byte>(ref source.DangerousGetPinnableReference()),
checked(source.Length * Unsafe.SizeOf<T>()));
}
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
return new ReadOnlySpan<byte>(
- ref Unsafe.As<T, byte>(ref source.GetRawPointer()),
+ ref Unsafe.As<T, byte>(ref source.DangerousGetPinnableReference()),
checked(source.Length * Unsafe.SizeOf<T>()));
}
/// <exception cref="System.ArgumentException">
/// Thrown when <typeparamref name="TFrom"/> or <typeparamref name="TTo"/> contains pointers.
/// </exception>
- public static unsafe Span<TTo> NonPortableCast<TFrom, TTo>(this Span<TFrom> source)
+ public static Span<TTo> NonPortableCast<TFrom, TTo>(this Span<TFrom> source)
where TFrom : struct
where TTo : struct
{
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TTo));
return new Span<TTo>(
- ref Unsafe.As<TFrom, TTo>(ref source.GetRawPointer()),
+ ref Unsafe.As<TFrom, TTo>(ref source.DangerousGetPinnableReference()),
checked((int)((long)source.Length * Unsafe.SizeOf<TFrom>() / Unsafe.SizeOf<TTo>())));
}
/// <exception cref="System.ArgumentException">
/// Thrown when <typeparamref name="TFrom"/> or <typeparamref name="TTo"/> contains pointers.
/// </exception>
- public static unsafe ReadOnlySpan<TTo> NonPortableCast<TFrom, TTo>(this ReadOnlySpan<TFrom> source)
+ public static ReadOnlySpan<TTo> NonPortableCast<TFrom, TTo>(this ReadOnlySpan<TFrom> source)
where TFrom : struct
where TTo : struct
{
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TTo));
return new ReadOnlySpan<TTo>(
- ref Unsafe.As<TFrom, TTo>(ref source.GetRawPointer()),
+ ref Unsafe.As<TFrom, TTo>(ref source.DangerousGetPinnableReference()),
checked((int)((long)source.Length * Unsafe.SizeOf<TFrom>() / Unsafe.SizeOf<TTo>())));
}
}
g_pSZArrayHelperClass = MscorlibBinder::GetClass(CLASS__SZARRAYHELPER);
#ifdef FEATURE_SPAN_OF_T
- // Load Span class
- g_pSpanClass = MscorlibBinder::GetClass(CLASS__SPAN);
- g_pReadOnlySpanClass = MscorlibBinder::GetClass(CLASS__READONLY_SPAN);
+ // Load ByReference class
+ g_pByReferenceClass = MscorlibBinder::GetClass(CLASS__BYREFERENCE);
#endif
// Load Nullable class
#define g_NullableName "Nullable`1"
#ifdef FEATURE_SPAN_OF_T
-#define g_SpanName "Span`1"
-#define g_ReadOnlySpanName "ReadOnlySpan`1"
+#define g_ByReferenceName "ByReference`1"
#endif
#define g_CollectionsEnumerableItfName "System.Collections.IEnumerable"
MethodTable* pMT = VMClsHnd.GetMethodTable();
- if (pMT == g_TypedReferenceMT) // if (pMT->IsByRefLike()) // TODO-SPAN: Proper GC reporting
+ if (pMT->IsByRefLike())
{
- if (pMT == g_TypedReferenceMT
-#ifdef FEATURE_SPAN_OF_T
- || pMT->HasSameTypeDefAs(g_pSpanClass) || pMT->HasSameTypeDefAs(g_pReadOnlySpanClass)
-#endif
- )
+ if (pMT == g_TypedReferenceMT)
{
gcPtrs[0] = TYPE_GC_BYREF;
gcPtrs[1] = TYPE_GC_NONE;
}
else
{
+ // TODO-SPAN: Proper GC reporting
+ memset(gcPtrs, TYPE_GC_NONE,
+ (VMClsHnd.GetSize() + sizeof(void*) -1)/ sizeof(void*));
result = 0;
}
}
methInfo->options = (CorInfoOptions)0;
return true;
}
- else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_AS)->GetMemberDef())
+ else if ((tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__AS_REF)->GetMemberDef()) ||
+ (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_AS)->GetMemberDef()))
+
{
// Return the argument that was passed in.
static const BYTE ilcode[] = { CEE_LDARG_0, CEE_RET };
pMT->SetHasBoxedRegularStatics();
}
+ if (bmtFP->fIsByRefLikeType)
+ {
+ pMT->SetIsByRefLike();
+ }
+
if (IsValueClass())
{
if (bmtFP->NumInstanceFieldBytes != totalDeclaredFieldSize || HasOverLayedField())
goto GOT_ELEMENT_TYPE;
}
- // There are just few types with code:IsByRefLike set - see code:CheckForSystemTypes.
- // Note: None of them will ever have self-referencing static ValueType field (we cannot assert it now because the IsByRefLike
- // status for this type has not been initialized yet).
+ // Inherit IsByRefLike characteristic from fields
if (!IsSelfRef(pByValueClass) && pByValueClass->IsByRefLike())
- { // Cannot have embedded valuetypes that contain a field that require stack allocation.
- BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, IDS_CLASSLOAD_BAD_FIELD, mdTokenNil);
+ {
+ bmtFP->fIsByRefLikeType = true;
}
-
+
if (!IsSelfRef(pByValueClass) && pByValueClass->GetClass()->HasNonPublicFields())
{ // If a class has a field of type ValueType with non-public fields in it,
// the class must "inherit" this characteristic
if (bmtGenerics->HasInstantiation() && g_pNullableClass != NULL)
{
#ifdef FEATURE_SPAN_OF_T
- _ASSERTE(g_pSpanClass != NULL);
- _ASSERTE(g_pReadOnlySpanClass != NULL);
-
- _ASSERTE(g_pSpanClass->IsByRefLike());
- _ASSERTE(g_pReadOnlySpanClass->IsByRefLike());
+ _ASSERTE(g_pByReferenceClass != NULL);
+ _ASSERTE(g_pByReferenceClass->IsByRefLike());
- if (GetCl() == g_pSpanClass->GetCl())
- {
- pMT->SetIsByRefLike();
- return;
- }
-
- if (GetCl() == g_pReadOnlySpanClass->GetCl())
+ if (GetCl() == g_pByReferenceClass->GetCl())
{
pMT->SetIsByRefLike();
return;
pMT->SetIsNullable();
}
#ifdef FEATURE_SPAN_OF_T
- else if (strcmp(name, g_SpanName) == 0)
- {
- pMT->SetIsByRefLike();
- }
- else if (strcmp(name, g_ReadOnlySpanName) == 0)
+ else if (strcmp(name, g_ByReferenceName) == 0)
{
pMT->SetIsByRefLike();
}
DWORD NumGCPointerSeries;
DWORD NumInstanceFieldBytes;
+ bool fIsByRefLikeType;
bool fHasFixedAddressValueTypes;
bool fHasSelfReferencingStaticValueTypeField_WithRVA;
DEFINE_CLASS(NULLABLE, System, Nullable`1)
#ifdef FEATURE_SPAN_OF_T
+DEFINE_CLASS(BYREFERENCE, System, ByReference`1)
DEFINE_CLASS(SPAN, System, Span`1)
DEFINE_CLASS(READONLY_SPAN, System, ReadOnlySpan`1)
#endif
DEFINE_CLASS(UNSAFE, CompilerServices, Unsafe)
DEFINE_METHOD(UNSAFE, AS_POINTER, AsPointer, NoSig)
DEFINE_METHOD(UNSAFE, SIZEOF, SizeOf, NoSig)
+DEFINE_METHOD(UNSAFE, AS_REF, AsRef, NoSig)
DEFINE_METHOD(UNSAFE, BYREF_AS, As, NoSig)
DEFINE_METHOD(UNSAFE, BYREF_ADD, Add, NoSig)
DEFINE_METHOD(UNSAFE, BYREF_ARE_SAME, AreSame, NoSig)
GPTR_IMPL(MethodTable, g_pSZArrayHelperClass);
GPTR_IMPL(MethodTable, g_pNullableClass);
#ifdef FEATURE_SPAN_OF_T
-GPTR_IMPL(MethodTable, g_pSpanClass);
-GPTR_IMPL(MethodTable, g_pReadOnlySpanClass);
+GPTR_IMPL(MethodTable, g_pByReferenceClass);
#endif
GPTR_IMPL(MethodTable, g_pExceptionClass);
GPTR_IMPL(MethodTable, g_pThreadAbortExceptionClass);
GPTR_DECL(MethodTable, g_pSZArrayHelperClass);
GPTR_DECL(MethodTable, g_pNullableClass);
#ifdef FEATURE_SPAN_OF_T
-GPTR_DECL(MethodTable, g_pSpanClass);
-GPTR_DECL(MethodTable, g_pReadOnlySpanClass);
+GPTR_DECL(MethodTable, g_pByReferenceClass);
#endif
GPTR_DECL(MethodTable, g_pExceptionClass);
GPTR_DECL(MethodTable, g_pThreadAbortExceptionClass);