// See getILIntrinsicImplementationForUnsafe for how this happens.
throw new InvalidOperationException();
}
+
+ /// <summary>
+ /// Initializes a block of memory at the given location with a given initial value
+ /// without assuming architecture dependent alignment of the address.
+ /// </summary>
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void InitBlockUnaligned(ref byte startAddress, byte value, uint byteCount)
+ {
+ // The body of this function will be replaced by the EE with unsafe code!!!
+ // See getILIntrinsicImplementationForUnsafe for how this happens.
+ throw new InvalidOperationException();
+ }
}
}
/// <summary>
/// Clears the contents of this span.
/// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clear()
{
// TODO: Optimize - https://github.com/dotnet/coreclr/issues/9161
/// </summary>
public void Fill(T value)
{
- // TODO: Optimize - https://github.com/dotnet/coreclr/issues/9161
- for (int i = 0; i < _length; i++)
+ int length = _length;
+
+ if (length == 0)
+ return;
+
+ if (Unsafe.SizeOf<T>() == 1)
+ {
+ byte fill = Unsafe.As<T, byte>(ref value);
+ ref byte r = ref Unsafe.As<T, byte>(ref _pointer.Value);
+ Unsafe.InitBlockUnaligned(ref r, fill, (uint)length);
+ }
+ else
{
- this[i] = value;
+ ref T r = ref DangerousGetPinnableReference();
+
+ // TODO: Create block fill for value types of power of two sizes e.g. 2,4,8,16
+
+ // Simple loop unrolling
+ int i = 0;
+ for (; i < (length & ~7); i += 8)
+ {
+ Unsafe.Add<T>(ref r, i + 0) = value;
+ Unsafe.Add<T>(ref r, i + 1) = value;
+ Unsafe.Add<T>(ref r, i + 2) = value;
+ Unsafe.Add<T>(ref r, i + 3) = value;
+ Unsafe.Add<T>(ref r, i + 4) = value;
+ Unsafe.Add<T>(ref r, i + 5) = value;
+ Unsafe.Add<T>(ref r, i + 6) = value;
+ Unsafe.Add<T>(ref r, i + 7) = value;
+ }
+ if (i < (length & ~3))
+ {
+ Unsafe.Add<T>(ref r, i + 0) = value;
+ Unsafe.Add<T>(ref r, i + 1) = value;
+ Unsafe.Add<T>(ref r, i + 2) = value;
+ Unsafe.Add<T>(ref r, i + 3) = value;
+ i += 4;
+ }
+ for (; i < length; i++)
+ {
+ Unsafe.Add<T>(ref r, i) = value;
+ }
}
}
methInfo->options = (CorInfoOptions)0;
return true;
}
+ else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_INIT_BLOCK_UNALIGNED)->GetMemberDef())
+ {
+ static const BYTE ilcode[] = { CEE_LDARG_0, CEE_LDARG_1, CEE_LDARG_2, CEE_PREFIX1, (CEE_UNALIGNED & 0xFF), 0x01, CEE_PREFIX1, (CEE_INITBLK & 0xFF), CEE_RET };
+ methInfo->ILCode = const_cast<BYTE*>(ilcode);
+ methInfo->ILCodeSize = sizeof(ilcode);
+ methInfo->maxStack = 3;
+ methInfo->EHcount = 0;
+ methInfo->options = (CorInfoOptions)0;
+ return true;
+ }
return false;
}
DEFINE_METHOD(UNSAFE, BYREF_AS, As, NoSig)
DEFINE_METHOD(UNSAFE, BYREF_ADD, Add, NoSig)
DEFINE_METHOD(UNSAFE, BYREF_ARE_SAME, AreSame, NoSig)
+DEFINE_METHOD(UNSAFE, BYREF_INIT_BLOCK_UNALIGNED, InitBlockUnaligned, NoSig)
#endif
DEFINE_CLASS(INTERLOCKED, Threading, Interlocked)