Skip to content

Commit 6f7a322

Browse files
committed
Fixed aligned memory allocation
1 parent 6231f78 commit 6f7a322

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

src/DotNext.Tests/SpanTests.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,14 @@ public static void SwapElements()
469469
Equal(expected.Slice(0, midpoint), actual.Slice(midpoint));
470470
}
471471

472+
[Fact]
473+
public static void AlignedAllocation()
474+
{
475+
using var owner = new SpanOwner<UInt128>(64);
476+
owner.Span[0] = UInt128.One;
477+
Equal(UInt128.One, owner.Span[0]);
478+
}
479+
472480
[Fact]
473481
public static void TransformElements()
474482
{

src/DotNext/Buffers/SpanOwner.cs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,26 @@ public SpanOwner(int minBufferSize, bool exactSize = true)
118118

119119
static unsafe Span<T> Allocate(int length)
120120
{
121-
var sizeInBytes = (nuint)length * (nuint)Unsafe.SizeOf<T>();
122-
return new(NativeMemory.AlignedAlloc(sizeInBytes, (uint)Intrinsics.AlignOf<T>()), length);
121+
void* ptr;
122+
123+
if (IsNaturalAlignment)
124+
{
125+
ptr = NativeMemory.Alloc((uint)length, (uint)Unsafe.SizeOf<T>());
126+
}
127+
else
128+
{
129+
var byteCount = checked((uint)Unsafe.SizeOf<T>() * (nuint)(uint)length);
130+
ptr = NativeMemory.AlignedAlloc(byteCount, (uint)Intrinsics.AlignOf<T>());
131+
}
132+
133+
return new(ptr, length);
123134
}
124135
}
125136

137+
private static bool IsNaturalAlignment => Intrinsics.AlignOf<T>() <= nuint.Size;
138+
126139
private static bool UseNativeAllocation
127-
=> !LibrarySettings.DisableNativeAllocation && !RuntimeHelpers.IsReferenceOrContainsReferences<T>() && Intrinsics.AlignOf<T>() <= nuint.Size;
140+
=> !LibrarySettings.DisableNativeAllocation && !RuntimeHelpers.IsReferenceOrContainsReferences<T>();
128141

129142
/// <summary>
130143
/// Gets the rented memory.
@@ -181,11 +194,19 @@ public void Dispose()
181194
{
182195
ArrayPool<T>.Shared.Return(array, RuntimeHelpers.IsReferenceOrContainsReferences<T>());
183196
}
184-
else if (ReferenceEquals(owner, Sentinel.Instance))
197+
else if (UseNativeAllocation && ReferenceEquals(owner, Sentinel.Instance))
185198
{
186199
unsafe
187200
{
188-
NativeMemory.AlignedFree(Unsafe.AsPointer(ref MemoryMarshal.GetReference(memory)));
201+
var ptr = Unsafe.AsPointer(ref MemoryMarshal.GetReference(memory));
202+
if (IsNaturalAlignment)
203+
{
204+
NativeMemory.Free(ptr);
205+
}
206+
else
207+
{
208+
NativeMemory.AlignedFree(ptr);
209+
}
189210
}
190211
}
191212
else

0 commit comments

Comments
 (0)