Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Fix BitArray.CopyTo to byte[] regression - update offset for extra bits. #40441

Merged
merged 1 commit into from
Aug 20, 2019

Conversation

ahsonkhan
Copy link
Member

@ahsonkhan ahsonkhan added this to the 5.0 milestone Aug 20, 2019
@ahsonkhan ahsonkhan self-assigned this Aug 20, 2019
@@ -657,7 +657,7 @@ public void CopyTo(Array array, int index)
Debug.Assert(span.Length > 0);
Debug.Assert(m_array.Length > quotient);
// mask the final byte
span[span.Length - 1] = (byte)((m_array[quotient] >> (remainder * 8)) & ((1 << (int)extraBits) - 1));
span[remainder] = (byte)((m_array[quotient] >> (remainder * 8)) & ((1 << (int)extraBits) - 1));
Copy link
Member Author

@ahsonkhan ahsonkhan Aug 20, 2019

Choose a reason for hiding this comment

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

Before the change from #33367, this used to be as follows:

// copy all the perfectly-aligned bytes
for (int i = 0; i < arrayLength; i++)
b[index + i] = (byte)((m_array[i / 4] >> ((i % 4) * 8)) & 0x000000FF); // Shift to bring the required byte to LSB, then mask
if (extraBits > 0)
{
// mask the final byte
int i = arrayLength;
b[index + i] = (byte)((m_array[i / 4] >> ((i % 4) * 8)) & ((1 << extraBits) - 1));
}

Before, we were writing one byte at a time, and then if the bit array contained extra bits to be copied over, we used the next index to write those bits. Now, we are writing 4 bytes at a time, and if we have 1-3 bytes left to write, we have the switch on remainder below. Beyond that, any extra bits left to copy (i.e. < 1 byte) should go at offset remainder.

I believe using remainder as the offset to write the last bits to is correct (and the test pass). Please review/verify.

Copy link
Member

@EgorBo EgorBo Aug 20, 2019

Choose a reason for hiding this comment

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

By the way

(byte)((m_array[quotient] >> (remainder * 8)) & ((1 << (int)extraBits) - 1));

can be optimized in JIT: https://godbolt.org/z/XQ9Mpe (or at least with Bmi2.ZeroHighBits)
current codegen: sharplab.io

Copy link
Member Author

Choose a reason for hiding this comment

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

@ahsonkhan
Copy link
Member Author

/azp run corefx-ci

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

}
}

// https://github.com/dotnet/corefx/issues/39929
Copy link
Member

Choose a reason for hiding this comment

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

Are these comments necessary?

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 the test name speaks for itself 😄

Copy link
Member

@safern safern left a comment

Choose a reason for hiding this comment

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

LGTM, thanks @ahsonkhan

picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BitArray.CopyTo(array, index) doesn't respect index - .NET Core 3.0 Preview 8
3 participants