diff options
author | Jan Kotas <jkotas@microsoft.com> | 2016-12-07 15:16:57 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-12-07 15:16:57 -0800 |
commit | 64c2ad17351ac5bc0bb042216bfcbf1c5136d7cf (patch) | |
tree | bbbec792192a88f2afe1e126f0ca4d0050348e32 | |
parent | bea2a8cf3d1ffe90683c47758f27f7cc83850982 (diff) | |
download | coreclr-64c2ad17351ac5bc0bb042216bfcbf1c5136d7cf.tar.gz coreclr-64c2ad17351ac5bc0bb042216bfcbf1c5136d7cf.tar.bz2 coreclr-64c2ad17351ac5bc0bb042216bfcbf1c5136d7cf.zip |
Refactor Span<T> to ease implementation of JIT intrinsics (#8497)
- Introduce internal ByReference<T> type for byref fields and change Span to use it
- Generalize handling of byref-like types in the type loader
- Make DangerousGetPinnableReference public while I was on it
-rw-r--r-- | src/inc/dacvars.h | 3 | ||||
-rw-r--r-- | src/mscorlib/model.xml | 2 | ||||
-rw-r--r-- | src/mscorlib/mscorlib.shared.sources.props | 1 | ||||
-rw-r--r-- | src/mscorlib/src/System/ByReference.cs | 31 | ||||
-rw-r--r-- | src/mscorlib/src/System/ReadOnlySpan.cs | 42 | ||||
-rw-r--r-- | src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs | 16 | ||||
-rw-r--r-- | src/mscorlib/src/System/Span.cs | 56 | ||||
-rw-r--r-- | src/vm/appdomain.cpp | 5 | ||||
-rw-r--r-- | src/vm/classnames.h | 3 | ||||
-rw-r--r-- | src/vm/jitinterface.cpp | 15 | ||||
-rw-r--r-- | src/vm/methodtablebuilder.cpp | 36 | ||||
-rw-r--r-- | src/vm/methodtablebuilder.h | 1 | ||||
-rw-r--r-- | src/vm/mscorlib.h | 2 | ||||
-rw-r--r-- | src/vm/vars.cpp | 3 | ||||
-rw-r--r-- | src/vm/vars.hpp | 3 |
15 files changed, 123 insertions, 96 deletions
diff --git a/src/inc/dacvars.h b/src/inc/dacvars.h index 4df214203a..0a60684ad1 100644 --- a/src/inc/dacvars.h +++ b/src/inc/dacvars.h @@ -219,8 +219,7 @@ DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pArrayClass, ::g_pArrayClass) 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) diff --git a/src/mscorlib/model.xml b/src/mscorlib/model.xml index 92ef0d932d..b4cd2bdbbf 100644 --- a/src/mscorlib/model.xml +++ b/src/mscorlib/model.xml @@ -12406,6 +12406,7 @@ <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" /> @@ -12425,6 +12426,7 @@ <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>" /> diff --git a/src/mscorlib/mscorlib.shared.sources.props b/src/mscorlib/mscorlib.shared.sources.props index 891f73c055..8d4142ea62 100644 --- a/src/mscorlib/mscorlib.shared.sources.props +++ b/src/mscorlib/mscorlib.shared.sources.props @@ -438,6 +438,7 @@ <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> diff --git a/src/mscorlib/src/System/ByReference.cs b/src/mscorlib/src/System/ByReference.cs new file mode 100644 index 0000000000..6f8bb2281e --- /dev/null +++ b/src/mscorlib/src/System/ByReference.cs @@ -0,0 +1,31 @@ +// 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); } + } + } + } +} diff --git a/src/mscorlib/src/System/ReadOnlySpan.cs b/src/mscorlib/src/System/ReadOnlySpan.cs index e94d3534fc..9235fcfa74 100644 --- a/src/mscorlib/src/System/ReadOnlySpan.cs +++ b/src/mscorlib/src/System/ReadOnlySpan.cs @@ -13,10 +13,10 @@ namespace System /// 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; @@ -31,8 +31,7 @@ namespace System 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; } @@ -54,8 +53,7 @@ namespace System 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; } @@ -78,8 +76,7 @@ namespace System 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; } @@ -105,7 +102,7 @@ namespace System if (length < 0) ThrowHelper.ThrowArgumentOutOfRangeException(); - _rawPointer = (IntPtr)pointer; + _pointer = new ByReference<T>(ref Unsafe.AsRef<T>(pointer)); _length = length; } @@ -114,18 +111,17 @@ namespace System /// </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> @@ -133,7 +129,7 @@ namespace System /// </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> @@ -189,7 +185,7 @@ namespace System if ((uint)index >= (uint)_length) ThrowHelper.ThrowIndexOutOfRangeException(); - return Unsafe.Add(ref GetRawPointer(), index); + return Unsafe.Add(ref DangerousGetPinnableReference(), index); } } @@ -204,7 +200,7 @@ namespace System 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; } @@ -221,7 +217,7 @@ namespace System 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> @@ -238,7 +234,7 @@ namespace System 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> @@ -248,7 +244,7 @@ namespace System 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> @@ -261,7 +257,7 @@ namespace System 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; } } diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs b/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs index 70d8ec079a..db3b2f28b7 100644 --- a/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs +++ b/src/mscorlib/src/System/Runtime/CompilerServices/Unsafe.cs @@ -23,7 +23,7 @@ namespace System.Runtime.CompilerServices [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(); } @@ -41,13 +41,25 @@ namespace System.Runtime.CompilerServices } /// <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(); } diff --git a/src/mscorlib/src/System/Span.cs b/src/mscorlib/src/System/Span.cs index 2eff6ae800..21785cd865 100644 --- a/src/mscorlib/src/System/Span.cs +++ b/src/mscorlib/src/System/Span.cs @@ -13,10 +13,10 @@ namespace System /// 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; @@ -36,8 +36,7 @@ namespace System 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; } @@ -64,8 +63,7 @@ namespace System 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; } @@ -93,8 +91,7 @@ namespace System 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; } @@ -120,7 +117,7 @@ namespace System if (length < 0) ThrowHelper.ThrowArgumentOutOfRangeException(); - _rawPointer = (IntPtr)pointer; + _pointer = new ByReference<T>(ref Unsafe.AsRef<T>(pointer)); _length = length; } @@ -129,18 +126,17 @@ namespace System /// </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> @@ -196,14 +192,14 @@ namespace System 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; } } @@ -218,7 +214,7 @@ namespace System 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; } @@ -235,7 +231,7 @@ namespace System 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> @@ -252,7 +248,7 @@ namespace System 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> @@ -262,7 +258,7 @@ namespace System 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> @@ -275,7 +271,7 @@ namespace System 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; } @@ -287,7 +283,7 @@ namespace System 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); } } @@ -308,7 +304,7 @@ namespace System 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>())); } @@ -327,7 +323,7 @@ namespace System 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>())); } @@ -342,7 +338,7 @@ namespace System /// <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 { @@ -352,7 +348,7 @@ namespace System 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>()))); } @@ -367,7 +363,7 @@ namespace System /// <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 { @@ -377,7 +373,7 @@ namespace System 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>()))); } } diff --git a/src/vm/appdomain.cpp b/src/vm/appdomain.cpp index 0ee260e3ef..b7fc67cd24 100644 --- a/src/vm/appdomain.cpp +++ b/src/vm/appdomain.cpp @@ -2871,9 +2871,8 @@ void SystemDomain::LoadBaseSystemClasses() 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 diff --git a/src/vm/classnames.h b/src/vm/classnames.h index ec5486ac7a..47f1fecdec 100644 --- a/src/vm/classnames.h +++ b/src/vm/classnames.h @@ -17,8 +17,7 @@ #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" diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index fac4cb44f2..cebd410347 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -2303,13 +2303,9 @@ unsigned CEEInfo::getClassGClayout (CORINFO_CLASS_HANDLE clsHnd, BYTE* gcPtrs) 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; @@ -2317,6 +2313,9 @@ unsigned CEEInfo::getClassGClayout (CORINFO_CLASS_HANDLE clsHnd, BYTE* gcPtrs) } else { + // TODO-SPAN: Proper GC reporting + memset(gcPtrs, TYPE_GC_NONE, + (VMClsHnd.GetSize() + sizeof(void*) -1)/ sizeof(void*)); result = 0; } } @@ -7034,7 +7033,9 @@ bool getILIntrinsicImplementationForUnsafe(MethodDesc * ftn, 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 }; diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp index ab55f11ced..682268eb39 100644 --- a/src/vm/methodtablebuilder.cpp +++ b/src/vm/methodtablebuilder.cpp @@ -1862,6 +1862,11 @@ MethodTableBuilder::BuildMethodTableThrowing( pMT->SetHasBoxedRegularStatics(); } + if (bmtFP->fIsByRefLikeType) + { + pMT->SetIsByRefLike(); + } + if (IsValueClass()) { if (bmtFP->NumInstanceFieldBytes != totalDeclaredFieldSize || HasOverLayedField()) @@ -4214,14 +4219,12 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList, 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 @@ -10207,19 +10210,10 @@ void MethodTableBuilder::CheckForSystemTypes() 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; @@ -10281,11 +10275,7 @@ void MethodTableBuilder::CheckForSystemTypes() 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(); } diff --git a/src/vm/methodtablebuilder.h b/src/vm/methodtablebuilder.h index 1e40ea996c..1cf71499e6 100644 --- a/src/vm/methodtablebuilder.h +++ b/src/vm/methodtablebuilder.h @@ -2081,6 +2081,7 @@ private: DWORD NumGCPointerSeries; DWORD NumInstanceFieldBytes; + bool fIsByRefLikeType; bool fHasFixedAddressValueTypes; bool fHasSelfReferencingStaticValueTypeField_WithRVA; diff --git a/src/vm/mscorlib.h b/src/vm/mscorlib.h index c145e4deff..7a0b1a04f1 100644 --- a/src/vm/mscorlib.h +++ b/src/vm/mscorlib.h @@ -1053,6 +1053,7 @@ DEFINE_FIELD(NULL, VALUE, Value) 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 @@ -1352,6 +1353,7 @@ DEFINE_METHOD(JIT_HELPERS, CONTAINSREFERENCES, ContainsReferences, 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) diff --git a/src/vm/vars.cpp b/src/vm/vars.cpp index 8d19a5c20e..626ca3c9d3 100644 --- a/src/vm/vars.cpp +++ b/src/vm/vars.cpp @@ -70,8 +70,7 @@ GPTR_IMPL(MethodTable, g_pArrayClass); 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); diff --git a/src/vm/vars.hpp b/src/vm/vars.hpp index 712543c2b1..62d6656eaf 100644 --- a/src/vm/vars.hpp +++ b/src/vm/vars.hpp @@ -403,8 +403,7 @@ GPTR_DECL(MethodTable, g_pArrayClass); 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); |