Fix Issue 20548 - Use bit vector instead of bool[] in RandomCover when choices cannot be packed in a single word

This commit is contained in:
Nathan Sashihara 2020-01-30 22:07:37 -08:00
parent 3502f0a0ae
commit 9014d77ab0

View file

@ -2950,9 +2950,10 @@ do
- bigger length means non-GC heap allocation(s) and dealloc. +/
private struct RandomCoverChoices
{
private void* buffer;
private size_t* buffer;
private immutable size_t _length;
private immutable bool hasPackedBits;
private enum BITS_PER_WORD = typeof(buffer[0]).sizeof * 8;
void opAssign(T)(T) @disable;
@ -2963,8 +2964,9 @@ private struct RandomCoverChoices
if (!hasPackedBits && buffer !is null)
{
void* nbuffer = enforceMalloc(_length);
buffer = memcpy(nbuffer, buffer, _length);
const nBytesToAlloc = 8 * (_length / BITS_PER_WORD + int(_length % BITS_PER_WORD != 0));
void* nbuffer = enforceMalloc(nBytesToAlloc);
buffer = cast(size_t*) memcpy(nbuffer, buffer, nBytesToAlloc);
}
}
@ -2976,7 +2978,8 @@ private struct RandomCoverChoices
hasPackedBits = _length <= size_t.sizeof * 8;
if (!hasPackedBits)
{
buffer = enforceCalloc(numChoices, 1);
const nWordsToAlloc = _length / BITS_PER_WORD + int(_length % BITS_PER_WORD != 0);
buffer = cast(size_t*) enforceCalloc(nWordsToAlloc, BITS_PER_WORD / 8);
}
}
@ -2993,8 +2996,9 @@ private struct RandomCoverChoices
bool opIndex(size_t index) const pure nothrow @nogc @trusted
{
assert(index < _length);
import core.bitop : bt;
if (!hasPackedBits)
return *((cast(bool*) buffer) + index);
return cast(bool) bt(buffer, index);
else
return ((cast(size_t) buffer) >> index) & size_t(1);
}
@ -3004,7 +3008,11 @@ private struct RandomCoverChoices
assert(index < _length);
if (!hasPackedBits)
{
*((cast(bool*) buffer) + index) = value;
import core.bitop : btr, bts;
if (value)
bts(buffer, index);
else
btr(buffer, index);
}
else
{