Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit b70774b

Browse files
authored
Merge pull request #2247 from n8sh/object-hash-19072
Fix Issue 19072 - Object.toHash and typeid(void*).getHash(&ptr) should be more varied in their low bits merged-on-behalf-of: Petar Kirov <ZombineDev@users.noreply.github.com>
2 parents 006a44c + 710adf3 commit b70774b

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

src/object.d

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,15 @@ class Object
871871
size_t toHash() @trusted nothrow
872872
{
873873
// BUG: this prevents a compacting GC from working, needs to be fixed
874-
return cast(size_t)cast(void*)this;
874+
size_t addr = cast(size_t) cast(void*) this;
875+
// The bottom log2((void*).alignof) bits of the address will always
876+
// be 0. Moreover it is likely that each Object is allocated with a
877+
// separate call to malloc. The alignment of malloc differs from
878+
// platform to platform, but rather than having special cases for
879+
// each platform it is safe to use a shift of 4. To minimize
880+
// collisions in the low bits it is more important for the shift to
881+
// not be too small than for the shift to not be too big.
882+
return addr ^ (addr >>> 4);
875883
}
876884

877885
/**
@@ -1183,7 +1191,12 @@ class TypeInfo_Pointer : TypeInfo
11831191

11841192
override size_t getHash(scope const void* p) @trusted const
11851193
{
1186-
return cast(size_t)*cast(void**)p;
1194+
// If the target of `p` is n-byte aligned then the
1195+
// bottom log2(n) bits of `p` will always be 0.
1196+
// Performing a constant magnitude xor-shift is
1197+
// inexpensive and will generally pay off.
1198+
size_t addr = cast(size_t) *cast(const void**) p;
1199+
return addr ^ (addr >>> 4);
11871200
}
11881201

11891202
override bool equals(in void* p1, in void* p2) const

0 commit comments

Comments
 (0)