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