Skip to content

Replace Unsafe.As with Unsafe.Read{Write}Unaligned #113293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

xtqqczze
Copy link
Contributor

@xtqqczze xtqqczze commented Mar 8, 2025

Doesn't depend upon implementation specific behaviour, i.e. that data is properly aligned.

For System.Private.CoreLib

Doesn't depend upon implementation specific behaviour, i.e. that the array data is properly aligned.
@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Mar 8, 2025
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Mar 8, 2025
@@ -600,7 +600,7 @@ internal static void Unbox_Nullable(ref byte destPtr, MethodTable* typeMT, objec
}
else
{
Unsafe.As<byte, bool>(ref destPtr) = true;
Unsafe.WriteUnaligned(ref destPtr, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bools are one byte long so this is not needed; accessing them is always aligned.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and below, can you replace these byte <-> bool with ternary ops and run MihuBot?

@xtqqczze xtqqczze changed the title Replace Unsafe.As with Unsafe.ReadUnaligned for loads Replace Unsafe.As with Unsafe.Read{Write}Unaligned Mar 8, 2025
@@ -69,7 +69,7 @@ private BoxCache(RuntimeType rt)
{
// If the allocator is null, then we shouldn't allocate and make a copy,
// we should return the data as the object it currently is.
return Unsafe.As<byte, object>(ref data);
return Unsafe.ReadUnaligned<object>(ref data);
Copy link
Member

@EgorBo EgorBo Mar 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GC references are not expected to be not-aligned. We can probably do Unsafe.Read here with a debug assert checking the alignment.

Same in other places

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can introduce an internal helper in Unsafe: ReadAligned that checks alignment in Debug.Assert

return true;

case EETypeElementType.Byte:
result = (ulong)(long)Unsafe.As<byte, byte>(ref pValue);
result = (ulong)(long)Unsafe.ReadUnaligned<byte>(ref pValue);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pValue is already byte, it doesn't need Unsafe. Same for SByte

@@ -1166,21 +1166,21 @@ internal object GetValue()
ref byte data = ref this.GetRawData();
return InternalGetCorElementType() switch
{
CorElementType.ELEMENT_TYPE_I1 => Unsafe.As<byte, sbyte>(ref data),
CorElementType.ELEMENT_TYPE_I1 => Unsafe.ReadUnaligned<sbyte>(ref data),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here: sbyte is read from byte with unsafe

@@ -1256,21 +1256,21 @@ public override int GetHashCode()
ref byte data = ref this.GetRawData();
return InternalGetCorElementType() switch
{
CorElementType.ELEMENT_TYPE_I1 => Unsafe.As<byte, sbyte>(ref data).GetHashCode(),
CorElementType.ELEMENT_TYPE_I1 => Unsafe.ReadUnaligned<sbyte>(ref data).GetHashCode(),
Copy link
Member

@EgorBo EgorBo Mar 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@@ -1294,35 +1294,35 @@ public int CompareTo(object? target)
switch (InternalGetCorElementType())
{
case CorElementType.ELEMENT_TYPE_I1:
return Unsafe.As<byte, sbyte>(ref pThisValue).CompareTo(Unsafe.As<byte, sbyte>(ref pTargetValue));
return Unsafe.ReadUnaligned<sbyte>(ref pThisValue).CompareTo(Unsafe.ReadUnaligned<sbyte>(ref pTargetValue));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

@@ -101,39 +101,39 @@ internal static unsafe bool TryGetUnboxedValueOfEnumOrInteger(object value, out
switch (elementType)
{
case EETypeElementType.Char:
result = (ulong)(long)Unsafe.As<byte, char>(ref pValue);
result = (ulong)(long)Unsafe.ReadUnaligned<char>(ref pValue);
Copy link
Member

@jkotas jkotas Mar 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pValue is expected to be aligned properly. Changes in this method are unnecessary deoptimization.

@@ -161,23 +161,23 @@ internal static void PrimitiveWiden(EETypeElementType dstType, EETypeElementType
switch (dstType)
{
case EETypeElementType.Single:
Unsafe.As<byte, float>(ref dstValue) = srcValue;
Unsafe.WriteUnaligned(ref dstValue, (float)srcValue);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. All changes in this method are unnecessary deoptimizations.

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many of the changes are unnecessary deoptimizations (I have not commented on all of them). You need to check what the surrounding code does and only fix this in places where unaligned access is actually possible.

@EgorBo
Copy link
Member

EgorBo commented Mar 9, 2025

@MihuBot

Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-runtime
See info in area-owners.md if you want to be subscribed.

@jkotas jkotas marked this pull request as draft March 31, 2025 19:30
@am11 am11 removed the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Apr 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Runtime community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants