diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index ef226f6eca5d255453b953a1c05b25b966f406f9..69fb562d2d72f7b1058f9e1d873393e8361c47f2 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -268,7 +268,7 @@ public override bool IsCollectible char c = Type.Delimiter; string resourceName = nameSpace != null && name != null ? - string.Concat(nameSpace, new ReadOnlySpan(ref c, 1), name) : + string.Concat(nameSpace, new ReadOnlySpan(in c), name) : string.Concat(nameSpace, name); return GetManifestResourceStream(resourceName); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs index 2b26b90cb7770fd9777e9268ade39b6d804ad5c6..a78691e1e6552d1a7ccd0a81b388a8849a8b8c3b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs @@ -338,7 +338,7 @@ public override MethodImplAttributes GetMethodImplementationFlags() } StackAllocedArguments stackArgs = default; - Span arguments = CheckArguments(ref stackArgs, new ReadOnlySpan(ref parameter, 1), binder, invokeAttr, culture, sig.Arguments); + Span arguments = CheckArguments(ref stackArgs, new ReadOnlySpan(in parameter), binder, invokeAttr, culture, sig.Arguments); bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0; return RuntimeMethodHandle.InvokeMethod(obj, arguments, Signature, constructor: false, wrapExceptions); diff --git a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs index bf1ac24679664d5f651aa63730100ae839677656..1f67966a7353a2fdfd394a5d6eaa5852a139f713 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs @@ -35,7 +35,7 @@ internal static unsafe byte ConvertToNative(char managedChar, bool fBestFit, boo internal static char ConvertToManaged(byte nativeChar) { - var bytes = new ReadOnlySpan(ref nativeChar, 1); + var bytes = new ReadOnlySpan(in nativeChar); string str = Encoding.Default.GetString(bytes); return str[0]; } diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index b462f6807c6e52af3cf9ac944a0baeb50f3454a4..54cedb357958ba60f8af7da3572cc4462cc77c9f 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -4080,7 +4080,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, // For Span // Comma // BoundsCheck(index, s->_length) - // s->_pointer + index * sizeof(T) + // s->_reference + index * sizeof(T) // // For ReadOnlySpan -- same expansion, as it now returns a readonly ref // diff --git a/src/coreclr/jit/morphblock.cpp b/src/coreclr/jit/morphblock.cpp index 5b28585d5a70dee5dae839d470abbd26e5e1fd3e..3ee695e8658daebb3acf0b98f40f0eae23895efc 100644 --- a/src/coreclr/jit/morphblock.cpp +++ b/src/coreclr/jit/morphblock.cpp @@ -895,7 +895,7 @@ void MorphCopyBlockHelper::MorphStructCases() } else if (m_srcDoFldAsg && srcFldIsProfitable) { - // Check for the symmetric case (which happens for the _pointer field of promoted spans): + // Check for the symmetric case (which happens for the _reference field of promoted spans): // // [000240] -----+------ /--* lclVar struct(P) V18 tmp9 // /--* byref V18._value (offs=0x00) -> V30 diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index 0f4033f45b507b07ca70b727f9ca1f4ff5474216..bf3f9c0bc17bc9ae8cd4a384dd97570b97a881e2 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -748,7 +748,7 @@ class Span { private: /* Keep fields below in sync with managed Span / ReadOnlySpan layout. */ - KIND* _pointer; + KIND* _reference; unsigned int _length; public: @@ -762,7 +762,7 @@ public: LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; _ASSERTE(index < GetLength()); - return _pointer[index]; + return _reference[index]; } // Gets the length (in elements) of this span. diff --git a/src/libraries/System.Private.CoreLib/src/System/Array.cs b/src/libraries/System.Private.CoreLib/src/System/Array.cs index 663d5f9ba4d7fa1a60d9d1d8dec116d559975a9e..f564e0c5bec523853d96f8bbc3ed338449e09ac1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Array.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Array.cs @@ -239,12 +239,12 @@ public static void Copy(Array sourceArray, long sourceIndex, Array destinationAr return InternalGetValue(GetFlattenedIndex(new ReadOnlySpan(indices))); } - public unsafe object? GetValue(int index) + public object? GetValue(int index) { if (Rank != 1) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need1DArray); - return InternalGetValue(GetFlattenedIndex(new ReadOnlySpan(&index, 1))); + return InternalGetValue(GetFlattenedIndex(new ReadOnlySpan(in index))); } public object? GetValue(int index1, int index2) @@ -263,12 +263,12 @@ public static void Copy(Array sourceArray, long sourceIndex, Array destinationAr return InternalGetValue(GetFlattenedIndex(stackalloc int[] { index1, index2, index3 })); } - public unsafe void SetValue(object? value, int index) + public void SetValue(object? value, int index) { if (Rank != 1) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need1DArray); - InternalSetValue(value, GetFlattenedIndex(new ReadOnlySpan(&index, 1))); + InternalSetValue(value, GetFlattenedIndex(new ReadOnlySpan(in index))); } public void SetValue(object? value, int index1, int index2) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs index cfda28a9ed2fd734e82b11181d194e7486a7abb8..b4eb5a06b1986616fac84aca359a4caeac6e7e58 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs @@ -110,7 +110,7 @@ public static CompareInfo GetCompareInfo(string name!!) public static bool IsSortable(char ch) { - return IsSortable(MemoryMarshal.CreateReadOnlySpan(ref ch, 1)); + return IsSortable(new ReadOnlySpan(in ch)); } public static bool IsSortable(string text!!) @@ -785,7 +785,7 @@ public int IndexOf(string source, char value, CompareOptions options) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - return IndexOf(source, MemoryMarshal.CreateReadOnlySpan(ref value, 1), options); + return IndexOf(source, new ReadOnlySpan(in value), options); } public int IndexOf(string source, string value, CompareOptions options) @@ -865,7 +865,7 @@ public unsafe int IndexOf(string source, char value, int startIndex, int count, } } - int result = IndexOf(sourceSpan, MemoryMarshal.CreateReadOnlySpan(ref value, 1), options); + int result = IndexOf(sourceSpan, new ReadOnlySpan(in value), options); if (result >= 0) { result += startIndex; @@ -1118,7 +1118,7 @@ public int LastIndexOf(string source, char value, CompareOptions options) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); } - return LastIndexOf(source, MemoryMarshal.CreateReadOnlySpan(ref value, 1), options); + return LastIndexOf(source, new ReadOnlySpan(in value), options); } public int LastIndexOf(string source, string value, CompareOptions options) @@ -1213,7 +1213,7 @@ public int LastIndexOf(string source, char value, int startIndex, int count, Com ThrowHelper.ThrowCountArgumentOutOfRange_ArgumentOutOfRange_Count(); } - int retVal = LastIndexOf(sourceSpan, MemoryMarshal.CreateReadOnlySpan(ref value, 1), options); + int retVal = LastIndexOf(sourceSpan, new ReadOnlySpan(in value), options); if (retVal >= 0) { retVal += startIndex; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs index f8c1745c1e4994d9a0f63f73cecf7ef3a122eee3..a8bd75c4f647efeb2230f0ac656bbc695d73e3e3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs @@ -715,7 +715,7 @@ private static bool IsUseGenitiveForm(ReadOnlySpan format, int index, int if (nextChar >= 0 && nextChar != '%') { char nextCharChar = (char)nextChar; - StringBuilder origStringBuilder = FormatCustomized(dateTime, MemoryMarshal.CreateReadOnlySpan(ref nextCharChar, 1), dtfi, offset, result); + StringBuilder origStringBuilder = FormatCustomized(dateTime, new ReadOnlySpan(in nextCharChar), dtfi, offset, result); Debug.Assert(ReferenceEquals(origStringBuilder, result)); tokenLen = 2; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanFormat.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanFormat.cs index 429f55d5db17462a86749ba94063cb44129ef932..5e9d6feb25b3461c7ff9b53ddea5aaf1e453ea56 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanFormat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanFormat.cs @@ -437,7 +437,7 @@ private static StringBuilder FormatCustomized(TimeSpan value, ReadOnlySpan if (nextChar >= 0 && nextChar != (int)'%') { char nextCharChar = (char)nextChar; - StringBuilder origStringBuilder = FormatCustomized(value, MemoryMarshal.CreateReadOnlySpan(ref nextCharChar, 1), dtfi, result); + StringBuilder origStringBuilder = FormatCustomized(value, new ReadOnlySpan(in nextCharChar), dtfi, result); Debug.Assert(ReferenceEquals(origStringBuilder, result)); tokenLen = 2; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Guid.cs b/src/libraries/System.Private.CoreLib/src/System/Guid.cs index 150e0f94da9f631f9367a3ce509baba431ce87b7..26579512ce71bcb6cbf72295117ac056fc2252d8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Guid.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Guid.cs @@ -385,7 +385,7 @@ private static bool TryParseExactD(ReadOnlySpan guidString, ref GuidResult return false; } - Span bytes = MemoryMarshal.AsBytes(new Span(ref result, 1)); + Span bytes = MemoryMarshal.AsBytes(new Span(ref result)); int invalidIfNegative = 0; bytes[0] = DecodeByte(guidString[6], guidString[7], ref invalidIfNegative); bytes[1] = DecodeByte(guidString[4], guidString[5], ref invalidIfNegative); @@ -471,7 +471,7 @@ private static bool TryParseExactN(ReadOnlySpan guidString, ref GuidResult return false; } - Span bytes = MemoryMarshal.AsBytes(new Span(ref result, 1)); + Span bytes = MemoryMarshal.AsBytes(new Span(ref result)); int invalidIfNegative = 0; bytes[0] = DecodeByte(guidString[6], guidString[7], ref invalidIfNegative); bytes[1] = DecodeByte(guidString[4], guidString[5], ref invalidIfNegative); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/BinaryWriter.cs b/src/libraries/System.Private.CoreLib/src/System/IO/BinaryWriter.cs index f81b64c4dd2160a631887f676e53a204ca953d06..5ed90b7582d6750e980a8fe9d3b7b5192dde8cb6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/BinaryWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/BinaryWriter.cs @@ -194,7 +194,7 @@ public virtual void Write(char ch) buffer = rented; } - int actualByteCount = _encoding.GetBytes(MemoryMarshal.CreateReadOnlySpan(ref ch, 1), buffer); + int actualByteCount = _encoding.GetBytes(new ReadOnlySpan(in ch), buffer); OutStream.Write(buffer.Slice(0, actualByteCount)); if (rented != null) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs index 2d949e7d532c4a244ffc4d76474bbe63be52bff1..d50abdb9ac85b311c85da0d29ab766b92d0ac409 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs @@ -202,10 +202,10 @@ protected unsafe void SetLengthCore(long value) } } - public sealed override unsafe int ReadByte() + public sealed override int ReadByte() { - byte b; - return Read(new Span(&b, 1)) != 0 ? b : -1; + byte b = 0; + return Read(new Span(ref b)) != 0 ? b : -1; } public sealed override int Read(byte[] buffer, int offset, int count) => @@ -229,8 +229,8 @@ public sealed override int Read(Span buffer) return r; } - public sealed override unsafe void WriteByte(byte value) => - Write(new ReadOnlySpan(&value, 1)); + public sealed override void WriteByte(byte value) => + Write(new ReadOnlySpan(in value)); public override void Write(byte[] buffer, int offset, int count) => Write(new ReadOnlySpan(buffer, offset, count)); diff --git a/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs b/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs index 6a57690d05d111f8c45cb09bab92c890d2c6de56..68b2cbc0c2c25c629ceb675efa5addf91313434f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs @@ -23,7 +23,7 @@ namespace System public readonly ref struct ReadOnlySpan { /// A byref or a native ptr. - internal readonly ByReference _pointer; + internal readonly ByReference _reference; /// The number of elements this ReadOnlySpan contains. private readonly int _length; @@ -41,7 +41,7 @@ public ReadOnlySpan(T[]? array) return; // returns default } - _pointer = new ByReference(ref MemoryMarshal.GetArrayDataReference(array)); + _reference = new ByReference(ref MemoryMarshal.GetArrayDataReference(array)); _length = array.Length; } @@ -75,7 +75,7 @@ public ReadOnlySpan(T[]? array, int start, int length) ThrowHelper.ThrowArgumentOutOfRangeException(); #endif - _pointer = new ByReference(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start /* force zero-extension */)); + _reference = new ByReference(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start /* force zero-extension */)); _length = length; } @@ -102,17 +102,27 @@ public unsafe ReadOnlySpan(void* pointer, int length) if (length < 0) ThrowHelper.ThrowArgumentOutOfRangeException(); - _pointer = new ByReference(ref Unsafe.As(ref *(byte*)pointer)); + _reference = new ByReference(ref Unsafe.As(ref *(byte*)pointer)); _length = length; } + // TODO https://github.com/dotnet/runtime/issues/67445: Make this public. + /// Creates a new of length 1 around the specified reference. + /// A reference to data. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal ReadOnlySpan(in T reference) + { + _reference = new ByReference(ref Unsafe.AsRef(in reference)); + _length = 1; + } + // Constructor for internal use only. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal ReadOnlySpan(ref T ptr, int length) + internal ReadOnlySpan(ref T reference, int length) { Debug.Assert(length >= 0); - _pointer = new ByReference(ref ptr); + _reference = new ByReference(ref reference); _length = length; } @@ -133,7 +143,7 @@ internal ReadOnlySpan(ref T ptr, int length) { if ((uint)index >= (uint)_length) ThrowHelper.ThrowIndexOutOfRangeException(); - return ref Unsafe.Add(ref _pointer.Value, (nint)(uint)index /* force zero-extension */); + return ref Unsafe.Add(ref _reference.Value, (nint)(uint)index /* force zero-extension */); } } @@ -251,7 +261,7 @@ public bool MoveNext() { // Ensure that the native code has just one forward branch that is predicted-not-taken. ref T ret = ref Unsafe.NullRef(); - if (_length != 0) ret = ref _pointer.Value; + if (_length != 0) ret = ref _reference.Value; return ref ret; } @@ -274,7 +284,7 @@ public void CopyTo(Span destination) if ((uint)_length <= (uint)destination.Length) { - Buffer.Memmove(ref destination._pointer.Value, ref _pointer.Value, (uint)_length); + Buffer.Memmove(ref destination._reference.Value, ref _reference.Value, (uint)_length); } else { @@ -295,7 +305,7 @@ public bool TryCopyTo(Span destination) bool retVal = false; if ((uint)_length <= (uint)destination.Length) { - Buffer.Memmove(ref destination._pointer.Value, ref _pointer.Value, (uint)_length); + Buffer.Memmove(ref destination._reference.Value, ref _reference.Value, (uint)_length); retVal = true; } return retVal; @@ -307,7 +317,7 @@ public bool TryCopyTo(Span destination) /// public static bool operator ==(ReadOnlySpan left, ReadOnlySpan right) => left._length == right._length && - Unsafe.AreSame(ref left._pointer.Value, ref right._pointer.Value); + Unsafe.AreSame(ref left._reference.Value, ref right._reference.Value); /// /// For , returns a new instance of string that represents the characters pointed to by the span. @@ -317,7 +327,7 @@ public override string ToString() { if (typeof(T) == typeof(char)) { - return new string(new ReadOnlySpan(ref Unsafe.As(ref _pointer.Value), _length)); + return new string(new ReadOnlySpan(ref Unsafe.As(ref _reference.Value), _length)); } return $"System.ReadOnlySpan<{typeof(T).Name}>[{_length}]"; } @@ -335,7 +345,7 @@ public ReadOnlySpan Slice(int start) if ((uint)start > (uint)_length) ThrowHelper.ThrowArgumentOutOfRangeException(); - return new ReadOnlySpan(ref Unsafe.Add(ref _pointer.Value, (nint)(uint)start /* force zero-extension */), _length - start); + return new ReadOnlySpan(ref Unsafe.Add(ref _reference.Value, (nint)(uint)start /* force zero-extension */), _length - start); } /// @@ -358,7 +368,7 @@ public ReadOnlySpan Slice(int start, int length) ThrowHelper.ThrowArgumentOutOfRangeException(); #endif - return new ReadOnlySpan(ref Unsafe.Add(ref _pointer.Value, (nint)(uint)start /* force zero-extension */), length); + return new ReadOnlySpan(ref Unsafe.Add(ref _reference.Value, (nint)(uint)start /* force zero-extension */), length); } /// @@ -372,7 +382,7 @@ public T[] ToArray() return Array.Empty(); var destination = new T[_length]; - Buffer.Memmove(ref MemoryMarshal.GetArrayDataReference(destination), ref _pointer.Value, (uint)_length); + Buffer.Memmove(ref MemoryMarshal.GetArrayDataReference(destination), ref _reference.Value, (uint)_length); return destination; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs b/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs index 85ed45ae4e5ad9d337bc1473cc29359a0d10516b..fa7bfb44b4bfcecad8868c77f0562c486e9ee31b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs @@ -343,7 +343,7 @@ private static ResourceSet InternalGetResourceSetFromSerializedData(Stream store char c = Type.Delimiter; string resourceName = nameSpace != null && name != null ? - string.Concat(nameSpace, new ReadOnlySpan(ref c, 1), name) : + string.Concat(nameSpace, new ReadOnlySpan(in c), name) : string.Concat(nameSpace, name); string? canonicalName = null; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs index f024762bba352b1134b92700e30119304a4536dd..431a8b8c67910d9d9ee4a342f74727dc79d9094a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs @@ -77,27 +77,27 @@ public static ReadOnlySpan AsBytes(ReadOnlySpan span) /// 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 may or may not be null. It can be used for pinning but must never be dereferenced. /// - public static ref T GetReference(Span span) => ref span._pointer.Value; + public static ref T GetReference(Span span) => ref span._reference.Value; /// /// Returns a reference to the 0th element of the ReadOnlySpan. If the ReadOnlySpan is empty, returns a reference to the location where the 0th element /// would have been stored. Such a reference may or may not be null. It can be used for pinning but must never be dereferenced. /// - public static ref T GetReference(ReadOnlySpan span) => ref span._pointer.Value; + public static ref T GetReference(ReadOnlySpan span) => ref span._reference.Value; /// /// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to fake non-null pointer. Such a reference can be used /// for pinning but must never be dereferenced. This is useful for interop with methods that do not accept null pointers for zero-sized buffers. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static unsafe ref T GetNonNullPinnableReference(Span span) => ref (span.Length != 0) ? ref span._pointer.Value : ref Unsafe.AsRef((void*)1); + internal static unsafe ref T GetNonNullPinnableReference(Span span) => ref (span.Length != 0) ? ref span._reference.Value : ref Unsafe.AsRef((void*)1); /// /// Returns a reference to the 0th element of the ReadOnlySpan. If the ReadOnlySpan is empty, returns a reference to fake non-null pointer. Such a reference /// can be used for pinning but must never be dereferenced. This is useful for interop with methods that do not accept null pointers for zero-sized buffers. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static unsafe ref T GetNonNullPinnableReference(ReadOnlySpan span) => ref (span.Length != 0) ? ref span._pointer.Value : ref Unsafe.AsRef((void*)1); + internal static unsafe ref T GetNonNullPinnableReference(ReadOnlySpan span) => ref (span.Length != 0) ? ref span._reference.Value : ref Unsafe.AsRef((void*)1); /// /// Casts a Span of one primitive type to another primitive type . @@ -150,7 +150,7 @@ public static ReadOnlySpan AsBytes(ReadOnlySpan span) } return new Span( - ref Unsafe.As(ref span._pointer.Value), + ref Unsafe.As(ref span._reference.Value), toLength); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Span.cs b/src/libraries/System.Private.CoreLib/src/System/Span.cs index dafd17730e95f95f295a960489f768497e18f4f5..74c80a8d00132105df0e91677d3940afd2d6b4dd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Span.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Span.cs @@ -22,7 +22,7 @@ namespace System public readonly ref struct Span { /// A byref or a native ptr. - internal readonly ByReference _pointer; + internal readonly ByReference _reference; /// The number of elements this Span contains. private readonly int _length; @@ -43,7 +43,7 @@ public Span(T[]? array) if (!typeof(T).IsValueType && array.GetType() != typeof(T[])) ThrowHelper.ThrowArrayTypeMismatchException(); - _pointer = new ByReference(ref MemoryMarshal.GetArrayDataReference(array)); + _reference = new ByReference(ref MemoryMarshal.GetArrayDataReference(array)); _length = array.Length; } @@ -80,7 +80,7 @@ public Span(T[]? array, int start, int length) ThrowHelper.ThrowArgumentOutOfRangeException(); #endif - _pointer = new ByReference(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start /* force zero-extension */)); + _reference = new ByReference(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start /* force zero-extension */)); _length = length; } @@ -107,17 +107,27 @@ public unsafe Span(void* pointer, int length) if (length < 0) ThrowHelper.ThrowArgumentOutOfRangeException(); - _pointer = new ByReference(ref Unsafe.As(ref *(byte*)pointer)); + _reference = new ByReference(ref Unsafe.As(ref *(byte*)pointer)); _length = length; } + // TODO https://github.com/dotnet/runtime/issues/67445: Make this public. + /// Creates a new of length 1 around the specified reference. + /// A reference to data. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal Span(ref T reference) + { + _reference = new ByReference(ref reference); + _length = 1; + } + // Constructor for internal use only. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal Span(ref T ptr, int length) + internal Span(ref T reference, int length) { Debug.Assert(length >= 0); - _pointer = new ByReference(ref ptr); + _reference = new ByReference(ref reference); _length = length; } @@ -138,7 +148,7 @@ internal Span(ref T ptr, int length) { if ((uint)index >= (uint)_length) ThrowHelper.ThrowIndexOutOfRangeException(); - return ref Unsafe.Add(ref _pointer.Value, (nint)(uint)index /* force zero-extension */); + return ref Unsafe.Add(ref _reference.Value, (nint)(uint)index /* force zero-extension */); } } @@ -256,7 +266,7 @@ public bool MoveNext() { // Ensure that the native code has just one forward branch that is predicted-not-taken. ref T ret = ref Unsafe.NullRef(); - if (_length != 0) ret = ref _pointer.Value; + if (_length != 0) ret = ref _reference.Value; return ref ret; } @@ -268,11 +278,11 @@ public unsafe void Clear() { if (RuntimeHelpers.IsReferenceOrContainsReferences()) { - SpanHelpers.ClearWithReferences(ref Unsafe.As(ref _pointer.Value), (uint)_length * (nuint)(Unsafe.SizeOf() / sizeof(nuint))); + SpanHelpers.ClearWithReferences(ref Unsafe.As(ref _reference.Value), (uint)_length * (nuint)(Unsafe.SizeOf() / sizeof(nuint))); } else { - SpanHelpers.ClearWithoutReferences(ref Unsafe.As(ref _pointer.Value), (uint)_length * (nuint)Unsafe.SizeOf()); + SpanHelpers.ClearWithoutReferences(ref Unsafe.As(ref _reference.Value), (uint)_length * (nuint)Unsafe.SizeOf()); } } @@ -288,12 +298,12 @@ public void Fill(T value) // The runtime eventually calls memset, which can efficiently support large buffers. // We don't need to check IsReferenceOrContainsReferences because no references // can ever be stored in types this small. - Unsafe.InitBlockUnaligned(ref Unsafe.As(ref _pointer.Value), Unsafe.As(ref value), (uint)_length); + Unsafe.InitBlockUnaligned(ref Unsafe.As(ref _reference.Value), Unsafe.As(ref value), (uint)_length); } else { // Call our optimized workhorse method for all other types. - SpanHelpers.Fill(ref _pointer.Value, (uint)_length, value); + SpanHelpers.Fill(ref _reference.Value, (uint)_length, value); } } @@ -315,7 +325,7 @@ public void CopyTo(Span destination) if ((uint)_length <= (uint)destination.Length) { - Buffer.Memmove(ref destination._pointer.Value, ref _pointer.Value, (uint)_length); + Buffer.Memmove(ref destination._reference.Value, ref _reference.Value, (uint)_length); } else { @@ -336,7 +346,7 @@ public bool TryCopyTo(Span destination) bool retVal = false; if ((uint)_length <= (uint)destination.Length) { - Buffer.Memmove(ref destination._pointer.Value, ref _pointer.Value, (uint)_length); + Buffer.Memmove(ref destination._reference.Value, ref _reference.Value, (uint)_length); retVal = true; } return retVal; @@ -348,13 +358,13 @@ public bool TryCopyTo(Span destination) /// public static bool operator ==(Span left, Span right) => left._length == right._length && - Unsafe.AreSame(ref left._pointer.Value, ref right._pointer.Value); + Unsafe.AreSame(ref left._reference.Value, ref right._reference.Value); /// /// Defines an implicit conversion of a to a /// public static implicit operator ReadOnlySpan(Span span) => - new ReadOnlySpan(ref span._pointer.Value, span._length); + new ReadOnlySpan(ref span._reference.Value, span._length); /// /// For , returns a new instance of string that represents the characters pointed to by the span. @@ -364,7 +374,7 @@ public override string ToString() { if (typeof(T) == typeof(char)) { - return new string(new ReadOnlySpan(ref Unsafe.As(ref _pointer.Value), _length)); + return new string(new ReadOnlySpan(ref Unsafe.As(ref _reference.Value), _length)); } return $"System.Span<{typeof(T).Name}>[{_length}]"; } @@ -382,7 +392,7 @@ public Span Slice(int start) if ((uint)start > (uint)_length) ThrowHelper.ThrowArgumentOutOfRangeException(); - return new Span(ref Unsafe.Add(ref _pointer.Value, (nint)(uint)start /* force zero-extension */), _length - start); + return new Span(ref Unsafe.Add(ref _reference.Value, (nint)(uint)start /* force zero-extension */), _length - start); } /// @@ -410,7 +420,7 @@ public Span Slice(int start, int length) ThrowHelper.ThrowArgumentOutOfRangeException(); #endif - return new Span(ref Unsafe.Add(ref _pointer.Value, (nint)(uint)start /* force zero-extension */), length); + return new Span(ref Unsafe.Add(ref _reference.Value, (nint)(uint)start /* force zero-extension */), length); } /// @@ -425,7 +435,7 @@ public T[] ToArray() return Array.Empty(); var destination = new T[_length]; - Buffer.Memmove(ref MemoryMarshal.GetArrayDataReference(destination), ref _pointer.Value, (uint)_length); + Buffer.Memmove(ref MemoryMarshal.GetArrayDataReference(destination), ref _reference.Value, (uint)_length); return destination; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs index d883782dbe5a3bde930a9af5a34dd1fdc432ad13..b81e614c47f0193ee3b93a36f1751ff324af8d69 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs @@ -518,7 +518,7 @@ public static string Join(char separator, params string?[] value) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value); } - return JoinCore(MemoryMarshal.CreateReadOnlySpan(ref separator, 1), new ReadOnlySpan(value)); + return JoinCore(new ReadOnlySpan(in separator), new ReadOnlySpan(value)); } public static string Join(string? separator, params string?[] value) @@ -532,7 +532,7 @@ public static string Join(string? separator, params string?[] value) } public static string Join(char separator, string?[] value, int startIndex, int count) => - JoinCore(MemoryMarshal.CreateReadOnlySpan(ref separator, 1), value, startIndex, count); + JoinCore(new ReadOnlySpan(in separator), value, startIndex, count); public static string Join(string? separator, string?[] value, int startIndex, int count) => JoinCore(separator.AsSpan(), value, startIndex, count); @@ -604,7 +604,7 @@ public static string Join(string? separator, IEnumerable values) } public static string Join(char separator, params object?[] values) => - JoinCore(MemoryMarshal.CreateReadOnlySpan(ref separator, 1), values); + JoinCore(new ReadOnlySpan(in separator), values); public static string Join(string? separator, params object?[] values) => JoinCore(separator.AsSpan(), values); @@ -646,7 +646,7 @@ private static string JoinCore(ReadOnlySpan separator, object?[] values) } public static string Join(char separator, IEnumerable values) => - JoinCore(MemoryMarshal.CreateReadOnlySpan(ref separator, 1), values); + JoinCore(new ReadOnlySpan(in separator), values); public static string Join(string? separator, IEnumerable values) => JoinCore(separator.AsSpan(), values); @@ -1257,12 +1257,12 @@ internal static int IndexOfNewlineChar(ReadOnlySpan text, out int stride) public string[] Split(char separator, StringSplitOptions options = StringSplitOptions.None) { - return SplitInternal(new ReadOnlySpan(ref separator, 1), int.MaxValue, options); + return SplitInternal(new ReadOnlySpan(in separator), int.MaxValue, options); } public string[] Split(char separator, int count, StringSplitOptions options = StringSplitOptions.None) { - return SplitInternal(new ReadOnlySpan(ref separator, 1), count, options); + return SplitInternal(new ReadOnlySpan(in separator), count, options); } // Creates an array of strings by splitting this string at each diff --git a/src/libraries/System.Private.CoreLib/src/System/String.cs b/src/libraries/System.Private.CoreLib/src/System/String.cs index edd0e1a0932e9e1afa2232f75e7019341223e95a..39f346ddde33ce25a4bdc15979fa8957318e49cf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.cs @@ -410,7 +410,7 @@ public void CopyTo(Span destination) { if ((uint)Length <= (uint)destination.Length) { - Buffer.Memmove(ref destination._pointer.Value, ref _firstChar, (uint)Length); + Buffer.Memmove(ref destination._reference.Value, ref _firstChar, (uint)Length); } else { @@ -427,7 +427,7 @@ public bool TryCopyTo(Span destination) bool retVal = false; if ((uint)Length <= (uint)destination.Length) { - Buffer.Memmove(ref destination._pointer.Value, ref _firstChar, (uint)Length); + Buffer.Memmove(ref destination._reference.Value, ref _firstChar, (uint)Length); retVal = true; } return retVal; diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/DecoderNLS.cs b/src/libraries/System.Private.CoreLib/src/System/Text/DecoderNLS.cs index b93c99ebfe57347644347d153fe27494b12f4fa5..e1bf717d9b6e672571136176af9dc3ce1eb8f5e6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/DecoderNLS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/DecoderNLS.cs @@ -205,11 +205,11 @@ internal void ClearMustFlush() } internal ReadOnlySpan GetLeftoverData() => - MemoryMarshal.AsBytes(new ReadOnlySpan(ref _leftoverBytes, 1)).Slice(0, _leftoverByteCount); + MemoryMarshal.AsBytes(new ReadOnlySpan(in _leftoverBytes)).Slice(0, _leftoverByteCount); internal void SetLeftoverData(ReadOnlySpan bytes) { - bytes.CopyTo(MemoryMarshal.AsBytes(new Span(ref _leftoverBytes, 1))); + bytes.CopyTo(MemoryMarshal.AsBytes(new Span(ref _leftoverBytes))); _leftoverByteCount = bytes.Length; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/TranscodingStream.cs b/src/libraries/System.Private.CoreLib/src/System/Text/TranscodingStream.cs index 4dbc443535b361ca8a68a7f09855011fb26ed1c5..65be587e192d1c2677de1c320951c39da681b689 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/TranscodingStream.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/TranscodingStream.cs @@ -439,8 +439,8 @@ async ValueTask ReadAsyncCore(Memory buffer, CancellationToken cancel public override unsafe int ReadByte() { - byte b; - return Read(new Span(&b, 1)) != 0 ? b : -1; + byte b = 0; + return Read(new Span(ref b)) != 0 ? b : -1; } public override long Seek(long offset, SeekOrigin origin) @@ -606,7 +606,7 @@ async ValueTask WriteAsyncCore(ReadOnlyMemory remainingOuterEncodedBytes, } } - public override unsafe void WriteByte(byte value) - => Write(new ReadOnlySpan(&value, 1)); + public override void WriteByte(byte value) + => Write(new ReadOnlySpan(in value)); } } diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index b36a8cf08c353ebd1726fddb11d2ba334a43d918..329f9c4b7d954d60195381367279b48029fd1b43 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -171,7 +171,7 @@ struct _MonoArray { /* match the layout of the managed definition of Span */ #define MONO_DEFINE_SPAN_OF_T(name, type) \ typedef struct { \ - type* _pointer; \ + type* _reference; \ uint32_t _length; \ } name; @@ -280,9 +280,9 @@ mono_handle_array_get_bounds_dim (MonoArrayHandle arr, gint32 dim, MonoArrayBoun #define mono_span_length(span) (span->_length) -#define mono_span_get(span,type,idx) (type)(!span->_pointer ? (type)0 : span->_pointer[idx]) +#define mono_span_get(span,type,idx) (type)(!span->_reference ? (type)0 : span->_reference[idx]) -#define mono_span_addr(span,type,idx) (type*)(span->_pointer + idx) +#define mono_span_addr(span,type,idx) (type*)(span->_reference + idx) #define mono_span_setref(span,index,value) \ do { \ @@ -296,10 +296,10 @@ mono_span_create_from_object_array (MonoArray *arr) { MonoSpanOfObjects span; if (arr != NULL) { span._length = (int32_t)mono_array_length_internal (arr); - span._pointer = mono_array_addr_fast (arr, MonoObject*, 0); + span._reference = mono_array_addr_fast (arr, MonoObject*, 0); } else { span._length = 0; - span._pointer = NULL; + span._reference = NULL; } return span; } diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 6ba370ba518239be93685f9916991e31b2068ea9..5c46d63880c8c203d557169c27cabc2f806b5e0a 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -2012,7 +2012,7 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas g_assert (length_field); int offset_length = m_field_get_offset (length_field) - sizeof (MonoObject); - MonoClassField *ptr_field = mono_class_get_field_from_name_full (target_method->klass, "_pointer", NULL); + MonoClassField *ptr_field = mono_class_get_field_from_name_full (target_method->klass, "_reference", NULL); g_assert (ptr_field); int offset_pointer = m_field_get_offset (ptr_field) - sizeof (MonoObject); diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index 35f1ff19a243415f3d69f0f4505f3788972033f2..8c36c07d80db1e5089c5850b69a8d1d7fc8399ca 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -327,7 +327,7 @@ emit_span_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature { MonoInst *ins; - MonoClassField *ptr_field = mono_class_get_field_from_name_full (cmethod->klass, "_pointer", NULL); + MonoClassField *ptr_field = mono_class_get_field_from_name_full (cmethod->klass, "_reference", NULL); if (!ptr_field) /* Portable Span */ return NULL; @@ -344,7 +344,7 @@ emit_span_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature return NULL; int span_reg = args [0]->dreg; - /* Load _pointer.Value */ + /* Load _reference.Value */ int base_reg = alloc_preg (cfg); EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, base_reg, span_reg, ptr_field->offset - MONO_ABI_SIZEOF (MonoObject)); /* Similar to mini_emit_ldelema_1_ins () */