Skip to content

Commit 84692a5

Browse files
committed
Run unit tests in 64 and 32 bit mode. Fix #41 and should prevent 32-bit bugs in the future
1 parent e5c21fc commit 84692a5

File tree

5 files changed

+73
-33
lines changed

5 files changed

+73
-33
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@
33
*.lst
44
*.s
55
test/tests
6+
test/tests_32
67
test/looptest
78
perf.data
89
doc/
910
.dub/
1011
dub.selections.json
1112
test/compile_test
13+
test/compile_test_32
1214
test/external_allocator_test
15+
test/external_allocator_test_32
16+
.gdb_history
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
module containers.internal.backwards;
2+
3+
static if (__VERSION__ < 2071)
4+
{
5+
/// 64-bit popcnt
6+
int popcnt(ulong v) pure nothrow @nogc @safe
7+
{
8+
import core.bitop : popcnt;
9+
10+
return popcnt(cast(uint) v) + popcnt(cast(uint)(v >>> 32));
11+
}
12+
13+
version (X86_64)
14+
public import core.bitop : bsf;
15+
else
16+
{
17+
/// Allow 64-bit bsf on old compilers
18+
int bsf(ulong v) pure nothrow @nogc @safe
19+
{
20+
import core.bitop : bsf;
21+
22+
immutable uint lower = cast(uint) v;
23+
immutable uint upper = cast(uint)(v >>> 32);
24+
return lower == 0 ? bsf(upper) + 32 : bsf(lower);
25+
}
26+
}
27+
}
28+
else
29+
public import core.bitop : bsf, popcnt;

src/containers/ttree.d

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,8 @@ private:
389389
alias N = FatNodeInfo!(T.sizeof, 3, cacheLineSize, ulong.sizeof);
390390
enum size_t nodeCapacity = N[0];
391391
alias BookkeepingType = N[1];
392-
static assert (nodeCapacity <= (uint.sizeof * 8), "cannot fit height info and registry in ulong");
392+
enum HEIGHT_BIT_OFFSET = 48UL;
393+
static assert (nodeCapacity <= HEIGHT_BIT_OFFSET, "cannot fit height info and registry in ulong");
393394
enum fullBitPattern = fullBits!(ulong, nodeCapacity);
394395

395396
enum RangeType : ubyte { all, lower, equal, upper }
@@ -454,7 +455,8 @@ private:
454455
{
455456
private size_t nextAvailableIndex() const nothrow pure @nogc @safe
456457
{
457-
import core.bitop : bsf;
458+
import containers.internal.backwards : bsf;
459+
458460
return bsf(~(registry & fullBitPattern));
459461
}
460462

@@ -501,14 +503,15 @@ private:
501503
immutable ulong l = left !is null ? left.height() : 0;
502504
immutable ulong r = right !is null ? right.height() : 0;
503505
immutable ulong h = 1 + (l > r ? l : r);
506+
assert (h < ushort.max);
504507
registry &= fullBitPattern;
505-
registry |= (h << 32UL);
508+
registry |= (h << HEIGHT_BIT_OFFSET);
506509
return h;
507510
}
508511

509512
ulong height() const nothrow pure @nogc @safe
510513
{
511-
return registry >>> 32UL;
514+
return registry >>> HEIGHT_BIT_OFFSET;
512515
}
513516

514517
int imbalanced() const nothrow pure @nogc @safe
@@ -720,7 +723,7 @@ private:
720723
{
721724
if (left is null && right is null)
722725
{
723-
size_t i = nextAvailableIndex() - 1;
726+
immutable size_t i = nextAvailableIndex() - 1;
724727
Value r = values[i];
725728
markUnused(i);
726729
return r;
@@ -871,7 +874,7 @@ private:
871874
Node* parent;
872875

873876
Value[nodeCapacity] values;
874-
ulong registry = 1UL << 32UL;
877+
ulong registry = 1UL << HEIGHT_BIT_OFFSET;
875878
}
876879

877880
AllocatorType allocator;

src/containers/unrolledlist.d

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ struct UnrolledList(T, Allocator = Mallocator,
176176
*/
177177
bool remove(T item)
178178
{
179-
import core.bitop : popcnt;
179+
import containers.internal.backwards : popcnt;
180180
if (_front is null)
181181
return false;
182182
bool retVal = false;
@@ -218,7 +218,7 @@ struct UnrolledList(T, Allocator = Mallocator,
218218
}
219219
body
220220
{
221-
import core.bitop : bsf, popcnt;
221+
import containers.internal.backwards : bsf;
222222
size_t index = bsf(_front.registry);
223223
T r = _front.items[index];
224224
_front.markUnused(index);
@@ -268,7 +268,7 @@ struct UnrolledList(T, Allocator = Mallocator,
268268
}
269269
body
270270
{
271-
import core.bitop: bsf;
271+
import containers.internal.backwards : bsf;
272272
import std.string: format;
273273
size_t index = bsf(_front.registry);
274274
assert (index < nodeCapacity, format("%d", index));
@@ -308,7 +308,7 @@ struct UnrolledList(T, Allocator = Mallocator,
308308
}
309309
body
310310
{
311-
import core.bitop : popcnt;
311+
import containers.internal.backwards : popcnt;
312312
size_t i = nodeCapacity - 1;
313313
while (_back.isFree(i))
314314
{
@@ -346,13 +346,15 @@ struct UnrolledList(T, Allocator = Mallocator,
346346

347347
this(inout(Node)* current, size_t l)
348348
{
349-
import core.bitop: bsf;
349+
import containers.internal.backwards : bsf;
350+
version(assert) import std.format:format;
351+
350352
this.current = current;
351353
this.length = l;
352354
if (current !is null)
353355
{
354356
index = bsf(current.registry);
355-
assert (index < nodeCapacity);
357+
assert (index < nodeCapacity, "index = %d, nodeCapacity = %d".format(index, nodeCapacity));
356358
}
357359
}
358360

@@ -456,22 +458,12 @@ private:
456458

457459
static bool shouldMerge(const Node* first, const Node* second)
458460
{
459-
import core.bitop : popcnt;
461+
import containers.internal.backwards : popcnt;
460462

461463
if (first is null || second is null)
462464
return false;
463-
static if (first.registry.sizeof > uint.sizeof)
464-
{
465-
immutable f = popcnt(cast(uint) first.registry)
466-
+ popcnt(cast(uint) (first.registry >>> 32));
467-
immutable s = popcnt(cast(uint) second.registry)
468-
+ popcnt(cast(uint) (second.registry >>> 32));
469-
}
470-
else
471-
{
472-
immutable f = popcnt(first.registry);
473-
immutable s = popcnt(second.registry);
474-
}
465+
immutable f = popcnt(first.registry);
466+
immutable s = popcnt(second.registry);
475467
return f + s <= nodeCapacity;
476468
}
477469

@@ -484,7 +476,7 @@ private:
484476
}
485477
body
486478
{
487-
import core.bitop: bsf;
479+
import containers.internal.backwards : bsf;
488480
size_t i;
489481
ContainerStorageType!T[nodeCapacity] temp;
490482
foreach (j; 0 .. nodeCapacity)
@@ -505,7 +497,7 @@ private:
505497
{
506498
size_t nextAvailableIndex() const nothrow pure @safe @nogc
507499
{
508-
import core.bitop: bsf;
500+
import containers.internal.backwards : bsf;
509501
return bsf(~registry);
510502
}
511503

test/makefile

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
11
.PHONY: test graphs clean
22

3-
SRC=$(shell find ../src/ -name "*.d") $(shell find ../experimental_allocator -name "*.d")
4-
FLAGS=-unittest -main -g -cov -I../src/ -debug -wi
3+
SRC:=$(shell find ../src/ -name "*.d") $(shell find ../experimental_allocator -name "*.d")
4+
FLAGS:=-unittest -main -g -cov -I../src/ -debug -wi
5+
FLAGS32:=$(FLAGS) -m32
56

6-
test: compile_test external_allocator_test
7-
dmd $(FLAGS) $(SRC) -oftests
7+
all: test test_32 compile_test compile_test_32 external_allocator_test external_allocator_test_32
88
./tests
9+
./tests_32
910
./compile_test
11+
./compile_test_32
1012
./external_allocator_test
13+
./external_allocator_test_32
14+
15+
test: $(SRC)
16+
dmd $(FLAGS) $(SRC) -oftests
17+
test_32: $(SRC)
18+
dmd $(FLAGS32) $(SRC) -oftests_32
1119

12-
compile_test: compile_test.d
20+
compile_test: compile_test.d $(SRC)
1321
dmd $(FLAGS) compile_test.d $(SRC) -ofcompile_test
22+
compile_test_32: compile_test.d $(SRC)
23+
dmd $(FLAGS32) compile_test.d $(SRC) -ofcompile_test_32
1424

15-
external_allocator_test: external_allocator_test.d
25+
external_allocator_test: external_allocator_test.d $(SRC)
1626
dmd $(FLAGS) external_allocator_test.d $(SRC) -ofexternal_allocator_test
27+
external_allocator_test_32: external_allocator_test.d $(SRC)
28+
dmd $(FLAGS32) external_allocator_test.d $(SRC) -ofexternal_allocator_test_32
1729

1830
looptest: looptest.d
1931
dmd looptest.d -inline -O -release \

0 commit comments

Comments
 (0)