未验证 提交 041933fd 编写于 作者: S Stephen Toub 提交者: GitHub

Add {ReadOnly}Span ctor (internal for now) that takes a ref and no length (#67447)

* Add {ReadOnly}Span ctor (internal for now) that takes an in and no length

* Address PR feedback

* Fix native references to _pointer
上级 135053ea
......@@ -268,7 +268,7 @@ public override bool IsCollectible
char c = Type.Delimiter;
string resourceName = nameSpace != null && name != null ?
string.Concat(nameSpace, new ReadOnlySpan<char>(ref c, 1), name) :
string.Concat(nameSpace, new ReadOnlySpan<char>(in c), name) :
string.Concat(nameSpace, name);
return GetManifestResourceStream(resourceName);
......
......@@ -338,7 +338,7 @@ public override MethodImplAttributes GetMethodImplementationFlags()
}
StackAllocedArguments stackArgs = default;
Span<object?> arguments = CheckArguments(ref stackArgs, new ReadOnlySpan<object?>(ref parameter, 1), binder, invokeAttr, culture, sig.Arguments);
Span<object?> arguments = CheckArguments(ref stackArgs, new ReadOnlySpan<object?>(in parameter), binder, invokeAttr, culture, sig.Arguments);
bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0;
return RuntimeMethodHandle.InvokeMethod(obj, arguments, Signature, constructor: false, wrapExceptions);
......
......@@ -35,7 +35,7 @@ internal static unsafe byte ConvertToNative(char managedChar, bool fBestFit, boo
internal static char ConvertToManaged(byte nativeChar)
{
var bytes = new ReadOnlySpan<byte>(ref nativeChar, 1);
var bytes = new ReadOnlySpan<byte>(in nativeChar);
string str = Encoding.Default.GetString(bytes);
return str[0];
}
......
......@@ -4080,7 +4080,7 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
// For Span<T>
// Comma
// BoundsCheck(index, s->_length)
// s->_pointer + index * sizeof(T)
// s->_reference + index * sizeof(T)
//
// For ReadOnlySpan<T> -- same expansion, as it now returns a readonly ref
//
......
......@@ -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
......
......@@ -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.
......
......@@ -239,12 +239,12 @@ public static void Copy(Array sourceArray, long sourceIndex, Array destinationAr
return InternalGetValue(GetFlattenedIndex(new ReadOnlySpan<int>(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<int>(&index, 1)));
return InternalGetValue(GetFlattenedIndex(new ReadOnlySpan<int>(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<int>(&index, 1)));
InternalSetValue(value, GetFlattenedIndex(new ReadOnlySpan<int>(in index)));
}
public void SetValue(object? value, int index1, int index2)
......
......@@ -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<char>(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<char>(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<char>(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<char>(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<char>(in value), options);
if (retVal >= 0)
{
retVal += startIndex;
......
......@@ -715,7 +715,7 @@ private static bool IsUseGenitiveForm(ReadOnlySpan<char> format, int index, int
if (nextChar >= 0 && nextChar != '%')
{
char nextCharChar = (char)nextChar;
StringBuilder origStringBuilder = FormatCustomized(dateTime, MemoryMarshal.CreateReadOnlySpan<char>(ref nextCharChar, 1), dtfi, offset, result);
StringBuilder origStringBuilder = FormatCustomized(dateTime, new ReadOnlySpan<char>(in nextCharChar), dtfi, offset, result);
Debug.Assert(ReferenceEquals(origStringBuilder, result));
tokenLen = 2;
}
......
......@@ -437,7 +437,7 @@ private static StringBuilder FormatCustomized(TimeSpan value, ReadOnlySpan<char>
if (nextChar >= 0 && nextChar != (int)'%')
{
char nextCharChar = (char)nextChar;
StringBuilder origStringBuilder = FormatCustomized(value, MemoryMarshal.CreateReadOnlySpan<char>(ref nextCharChar, 1), dtfi, result);
StringBuilder origStringBuilder = FormatCustomized(value, new ReadOnlySpan<char>(in nextCharChar), dtfi, result);
Debug.Assert(ReferenceEquals(origStringBuilder, result));
tokenLen = 2;
}
......
......@@ -385,7 +385,7 @@ private static bool TryParseExactD(ReadOnlySpan<char> guidString, ref GuidResult
return false;
}
Span<byte> bytes = MemoryMarshal.AsBytes(new Span<GuidResult>(ref result, 1));
Span<byte> bytes = MemoryMarshal.AsBytes(new Span<GuidResult>(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<char> guidString, ref GuidResult
return false;
}
Span<byte> bytes = MemoryMarshal.AsBytes(new Span<GuidResult>(ref result, 1));
Span<byte> bytes = MemoryMarshal.AsBytes(new Span<GuidResult>(ref result));
int invalidIfNegative = 0;
bytes[0] = DecodeByte(guidString[6], guidString[7], ref invalidIfNegative);
bytes[1] = DecodeByte(guidString[4], guidString[5], ref invalidIfNegative);
......
......@@ -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<char>(in ch), buffer);
OutStream.Write(buffer.Slice(0, actualByteCount));
if (rented != null)
......
......@@ -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<byte>(&b, 1)) != 0 ? b : -1;
byte b = 0;
return Read(new Span<byte>(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<byte> buffer)
return r;
}
public sealed override unsafe void WriteByte(byte value) =>
Write(new ReadOnlySpan<byte>(&value, 1));
public sealed override void WriteByte(byte value) =>
Write(new ReadOnlySpan<byte>(in value));
public override void Write(byte[] buffer, int offset, int count) =>
Write(new ReadOnlySpan<byte>(buffer, offset, count));
......
......@@ -23,7 +23,7 @@ namespace System
public readonly ref struct ReadOnlySpan<T>
{
/// <summary>A byref or a native ptr.</summary>
internal readonly ByReference<T> _pointer;
internal readonly ByReference<T> _reference;
/// <summary>The number of elements this ReadOnlySpan contains.</summary>
private readonly int _length;
......@@ -41,7 +41,7 @@ public ReadOnlySpan(T[]? array)
return; // returns default
}
_pointer = new ByReference<T>(ref MemoryMarshal.GetArrayDataReference(array));
_reference = new ByReference<T>(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<T>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start /* force zero-extension */));
_reference = new ByReference<T>(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<T>(ref Unsafe.As<byte, T>(ref *(byte*)pointer));
_reference = new ByReference<T>(ref Unsafe.As<byte, T>(ref *(byte*)pointer));
_length = length;
}
// TODO https://github.com/dotnet/runtime/issues/67445: Make this public.
/// <summary>Creates a new <see cref="ReadOnlySpan{T}"/> of length 1 around the specified reference.</summary>
/// <param name="reference">A reference to data.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal ReadOnlySpan(in T reference)
{
_reference = new ByReference<T>(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<T>(ref ptr);
_reference = new ByReference<T>(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<T>();
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<T> 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<T> 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<T> destination)
/// </summary>
public static bool operator ==(ReadOnlySpan<T> left, ReadOnlySpan<T> right) =>
left._length == right._length &&
Unsafe.AreSame<T>(ref left._pointer.Value, ref right._pointer.Value);
Unsafe.AreSame<T>(ref left._reference.Value, ref right._reference.Value);
/// <summary>
/// For <see cref="ReadOnlySpan{Char}"/>, 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<char>(ref Unsafe.As<T, char>(ref _pointer.Value), _length));
return new string(new ReadOnlySpan<char>(ref Unsafe.As<T, char>(ref _reference.Value), _length));
}
return $"System.ReadOnlySpan<{typeof(T).Name}>[{_length}]";
}
......@@ -335,7 +345,7 @@ public ReadOnlySpan<T> Slice(int start)
if ((uint)start > (uint)_length)
ThrowHelper.ThrowArgumentOutOfRangeException();
return new ReadOnlySpan<T>(ref Unsafe.Add(ref _pointer.Value, (nint)(uint)start /* force zero-extension */), _length - start);
return new ReadOnlySpan<T>(ref Unsafe.Add(ref _reference.Value, (nint)(uint)start /* force zero-extension */), _length - start);
}
/// <summary>
......@@ -358,7 +368,7 @@ public ReadOnlySpan<T> Slice(int start, int length)
ThrowHelper.ThrowArgumentOutOfRangeException();
#endif
return new ReadOnlySpan<T>(ref Unsafe.Add(ref _pointer.Value, (nint)(uint)start /* force zero-extension */), length);
return new ReadOnlySpan<T>(ref Unsafe.Add(ref _reference.Value, (nint)(uint)start /* force zero-extension */), length);
}
/// <summary>
......@@ -372,7 +382,7 @@ public T[] ToArray()
return Array.Empty<T>();
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;
}
}
......
......@@ -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<char>(ref c, 1), name) :
string.Concat(nameSpace, new ReadOnlySpan<char>(in c), name) :
string.Concat(nameSpace, name);
string? canonicalName = null;
......
......@@ -77,27 +77,27 @@ public static ReadOnlySpan<byte> AsBytes<T>(ReadOnlySpan<T> 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.
/// </summary>
public static ref T GetReference<T>(Span<T> span) => ref span._pointer.Value;
public static ref T GetReference<T>(Span<T> span) => ref span._reference.Value;
/// <summary>
/// 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.
/// </summary>
public static ref T GetReference<T>(ReadOnlySpan<T> span) => ref span._pointer.Value;
public static ref T GetReference<T>(ReadOnlySpan<T> span) => ref span._reference.Value;
/// <summary>
/// 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.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe ref T GetNonNullPinnableReference<T>(Span<T> span) => ref (span.Length != 0) ? ref span._pointer.Value : ref Unsafe.AsRef<T>((void*)1);
internal static unsafe ref T GetNonNullPinnableReference<T>(Span<T> span) => ref (span.Length != 0) ? ref span._reference.Value : ref Unsafe.AsRef<T>((void*)1);
/// <summary>
/// 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.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe ref T GetNonNullPinnableReference<T>(ReadOnlySpan<T> span) => ref (span.Length != 0) ? ref span._pointer.Value : ref Unsafe.AsRef<T>((void*)1);
internal static unsafe ref T GetNonNullPinnableReference<T>(ReadOnlySpan<T> span) => ref (span.Length != 0) ? ref span._reference.Value : ref Unsafe.AsRef<T>((void*)1);
/// <summary>
/// Casts a Span of one primitive type <typeparamref name="TFrom"/> to another primitive type <typeparamref name="TTo"/>.
......@@ -150,7 +150,7 @@ public static ReadOnlySpan<byte> AsBytes<T>(ReadOnlySpan<T> span)
}
return new Span<TTo>(
ref Unsafe.As<TFrom, TTo>(ref span._pointer.Value),
ref Unsafe.As<TFrom, TTo>(ref span._reference.Value),
toLength);
}
......
......@@ -22,7 +22,7 @@ namespace System
public readonly ref struct Span<T>
{
/// <summary>A byref or a native ptr.</summary>
internal readonly ByReference<T> _pointer;
internal readonly ByReference<T> _reference;
/// <summary>The number of elements this Span contains.</summary>
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<T>(ref MemoryMarshal.GetArrayDataReference(array));
_reference = new ByReference<T>(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<T>(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start /* force zero-extension */));
_reference = new ByReference<T>(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<T>(ref Unsafe.As<byte, T>(ref *(byte*)pointer));
_reference = new ByReference<T>(ref Unsafe.As<byte, T>(ref *(byte*)pointer));
_length = length;
}
// TODO https://github.com/dotnet/runtime/issues/67445: Make this public.
/// <summary>Creates a new <see cref="Span{T}"/> of length 1 around the specified reference.</summary>
/// <param name="reference">A reference to data.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal Span(ref T reference)
{
_reference = new ByReference<T>(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<T>(ref ptr);
_reference = new ByReference<T>(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<T>();
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<T>())
{
SpanHelpers.ClearWithReferences(ref Unsafe.As<T, IntPtr>(ref _pointer.Value), (uint)_length * (nuint)(Unsafe.SizeOf<T>() / sizeof(nuint)));
SpanHelpers.ClearWithReferences(ref Unsafe.As<T, IntPtr>(ref _reference.Value), (uint)_length * (nuint)(Unsafe.SizeOf<T>() / sizeof(nuint)));
}
else
{
SpanHelpers.ClearWithoutReferences(ref Unsafe.As<T, byte>(ref _pointer.Value), (uint)_length * (nuint)Unsafe.SizeOf<T>());
SpanHelpers.ClearWithoutReferences(ref Unsafe.As<T, byte>(ref _reference.Value), (uint)_length * (nuint)Unsafe.SizeOf<T>());
}
}
......@@ -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<T, byte>(ref _pointer.Value), Unsafe.As<T, byte>(ref value), (uint)_length);
Unsafe.InitBlockUnaligned(ref Unsafe.As<T, byte>(ref _reference.Value), Unsafe.As<T, byte>(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<T> 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<T> 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<T> destination)
/// </summary>
public static bool operator ==(Span<T> left, Span<T> right) =>
left._length == right._length &&
Unsafe.AreSame<T>(ref left._pointer.Value, ref right._pointer.Value);
Unsafe.AreSame<T>(ref left._reference.Value, ref right._reference.Value);
/// <summary>
/// Defines an implicit conversion of a <see cref="Span{T}"/> to a <see cref="ReadOnlySpan{T}"/>
/// </summary>
public static implicit operator ReadOnlySpan<T>(Span<T> span) =>
new ReadOnlySpan<T>(ref span._pointer.Value, span._length);
new ReadOnlySpan<T>(ref span._reference.Value, span._length);
/// <summary>
/// For <see cref="Span{Char}"/>, 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<char>(ref Unsafe.As<T, char>(ref _pointer.Value), _length));
return new string(new ReadOnlySpan<char>(ref Unsafe.As<T, char>(ref _reference.Value), _length));
}
return $"System.Span<{typeof(T).Name}>[{_length}]";
}
......@@ -382,7 +392,7 @@ public Span<T> Slice(int start)
if ((uint)start > (uint)_length)
ThrowHelper.ThrowArgumentOutOfRangeException();
return new Span<T>(ref Unsafe.Add(ref _pointer.Value, (nint)(uint)start /* force zero-extension */), _length - start);
return new Span<T>(ref Unsafe.Add(ref _reference.Value, (nint)(uint)start /* force zero-extension */), _length - start);
}
/// <summary>
......@@ -410,7 +420,7 @@ public Span<T> Slice(int start, int length)
ThrowHelper.ThrowArgumentOutOfRangeException();
#endif
return new Span<T>(ref Unsafe.Add(ref _pointer.Value, (nint)(uint)start /* force zero-extension */), length);
return new Span<T>(ref Unsafe.Add(ref _reference.Value, (nint)(uint)start /* force zero-extension */), length);
}
/// <summary>
......@@ -425,7 +435,7 @@ public T[] ToArray()
return Array.Empty<T>();
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;
}
}
......
......@@ -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<string?>(value));
return JoinCore(new ReadOnlySpan<char>(in separator), new ReadOnlySpan<string?>(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<char>(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<string?> values)
}
public static string Join(char separator, params object?[] values) =>
JoinCore(MemoryMarshal.CreateReadOnlySpan(ref separator, 1), values);
JoinCore(new ReadOnlySpan<char>(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<char> separator, object?[] values)
}
public static string Join<T>(char separator, IEnumerable<T> values) =>
JoinCore(MemoryMarshal.CreateReadOnlySpan(ref separator, 1), values);
JoinCore(new ReadOnlySpan<char>(in separator), values);
public static string Join<T>(string? separator, IEnumerable<T> values) =>
JoinCore(separator.AsSpan(), values);
......@@ -1257,12 +1257,12 @@ internal static int IndexOfNewlineChar(ReadOnlySpan<char> text, out int stride)
public string[] Split(char separator, StringSplitOptions options = StringSplitOptions.None)
{
return SplitInternal(new ReadOnlySpan<char>(ref separator, 1), int.MaxValue, options);
return SplitInternal(new ReadOnlySpan<char>(in separator), int.MaxValue, options);
}
public string[] Split(char separator, int count, StringSplitOptions options = StringSplitOptions.None)
{
return SplitInternal(new ReadOnlySpan<char>(ref separator, 1), count, options);
return SplitInternal(new ReadOnlySpan<char>(in separator), count, options);
}
// Creates an array of strings by splitting this string at each
......
......@@ -410,7 +410,7 @@ public void CopyTo(Span<char> 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<char> 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;
......
......@@ -205,11 +205,11 @@ internal void ClearMustFlush()
}
internal ReadOnlySpan<byte> GetLeftoverData() =>
MemoryMarshal.AsBytes(new ReadOnlySpan<int>(ref _leftoverBytes, 1)).Slice(0, _leftoverByteCount);
MemoryMarshal.AsBytes(new ReadOnlySpan<int>(in _leftoverBytes)).Slice(0, _leftoverByteCount);
internal void SetLeftoverData(ReadOnlySpan<byte> bytes)
{
bytes.CopyTo(MemoryMarshal.AsBytes(new Span<int>(ref _leftoverBytes, 1)));
bytes.CopyTo(MemoryMarshal.AsBytes(new Span<int>(ref _leftoverBytes)));
_leftoverByteCount = bytes.Length;
}
......
......@@ -439,8 +439,8 @@ async ValueTask<int> ReadAsyncCore(Memory<byte> buffer, CancellationToken cancel
public override unsafe int ReadByte()
{
byte b;
return Read(new Span<byte>(&b, 1)) != 0 ? b : -1;
byte b = 0;
return Read(new Span<byte>(ref b)) != 0 ? b : -1;
}
public override long Seek(long offset, SeekOrigin origin)
......@@ -606,7 +606,7 @@ async ValueTask WriteAsyncCore(ReadOnlyMemory<byte> remainingOuterEncodedBytes,
}
}
public override unsafe void WriteByte(byte value)
=> Write(new ReadOnlySpan<byte>(&value, 1));
public override void WriteByte(byte value)
=> Write(new ReadOnlySpan<byte>(in value));
}
}
......@@ -171,7 +171,7 @@ struct _MonoArray {
/* match the layout of the managed definition of Span<T> */
#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;
}
......
......@@ -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);
......
......@@ -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<T> */
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 () */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册