Skip to content

Remove unsafe code from System.Collections.BitArray#127846

Draft
EgorBo wants to merge 1 commit intodotnet:mainfrom
EgorBo:reduce-unsafe-bitarray
Draft

Remove unsafe code from System.Collections.BitArray#127846
EgorBo wants to merge 1 commit intodotnet:mainfrom
EgorBo:reduce-unsafe-bitarray

Conversation

@EgorBo
Copy link
Copy Markdown
Member

@EgorBo EgorBo commented May 6, 2026

Note

This PR is AI-generated.

No diffs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

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

@EgorBo
Copy link
Copy Markdown
Member Author

EgorBo commented May 6, 2026

@MihuBot

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the BitArray(bool[] values) constructor in System.Private.CoreLib to avoid reinterpreting the bool[] backing storage via Unsafe.As<bool, byte> by instead operating over a ReadOnlySpan<byte> obtained from MemoryMarshal.AsBytes.

Changes:

  • Convert the input bool[] to ReadOnlySpan<byte> and use it as the SIMD input source.
  • Replace Vector*.LoadUnsafe(ref, offset) loops with Vector*.Create(ReadOnlySpan<byte>) plus span slicing to advance through the input.
  • Adjust loop structure from indexed for loops to while (valuesAsBytes.Length >= ...) loops.

@EgorBo
Copy link
Copy Markdown
Member Author

EgorBo commented May 6, 2026

Note

AI-generated benchmark.

@EgorBot -arm -amd

using System;
using System.Collections;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

BenchmarkSwitcher.FromAssembly(typeof(Bench).Assembly).Run(args);

public class Bench
{
    private bool[] _values = default!;

    [Params(64, 256, 1024, 16384)]
    public int Length { get; set; }

    [GlobalSetup]
    public void Setup()
    {
        var rng = new Random(42);
        _values = new bool[Length];
        for (int i = 0; i < Length; i++)
            _values[i] = rng.Next(2) == 0;
    }

    [Benchmark]
    public BitArray Construct() => new BitArray(_values);
}


ref byte arrayRef = ref MemoryMarshal.GetArrayDataReference(_array);
ref byte value = ref Unsafe.As<bool, byte>(ref MemoryMarshal.GetArrayDataReference<bool>(values));
ReadOnlySpan<byte> valuesAsBytes = MemoryMarshal.AsBytes(values.AsSpan());
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It's fully safe to bitcast Span<bool> to Span<byte>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants