From 9014d77ab028b70d80dd6e93ff60b9744bd1780c Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Thu, 30 Jan 2020 22:07:37 -0800 Subject: [PATCH] Fix Issue 20548 - Use bit vector instead of bool[] in RandomCover when choices cannot be packed in a single word --- std/random.d | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/std/random.d b/std/random.d index 84aaa3d17..58fe5c5a0 100644 --- a/std/random.d +++ b/std/random.d @@ -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 {