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

Commit 939b8aa

Browse files
committed
use core.internal.hash for TypeInfo.getHash
1 parent b70774b commit 939b8aa

29 files changed

+161
-249
lines changed

mak/DOCS

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ DOCS=\
140140
$(DOCDIR)\rt_util_container_common.html \
141141
$(DOCDIR)\rt_util_container_hashtab.html \
142142
$(DOCDIR)\rt_util_container_treap.html \
143-
$(DOCDIR)\rt_util_hash.html \
144143
$(DOCDIR)\rt_util_random.html \
145144
$(DOCDIR)\rt_util_typeinfo.html \
146145
$(DOCDIR)\rt_util_utf.html \

mak/SRCS

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,6 @@ SRCS=\
347347
src\rt\backtrace\macho.d \
348348
\
349349
src\rt\util\array.d \
350-
src\rt\util\hash.d \
351350
src\rt\util\random.d \
352351
src\rt\util\typeinfo.d \
353352
src\rt\util\utf.d \

src/core/internal/hash.d

Lines changed: 112 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import core.internal.convert;
1313

1414
// If true ensure that positive zero and negative zero have the same hash.
1515
// typeid(float).getHash does this but historically hashOf(float) did not.
16-
private enum floatCoalesceZeroes = false;
16+
private enum floatCoalesceZeroes = true;
1717
// If true ensure that all NaNs of the same floating point type have the same hash.
1818
// typeid(float).getHash does not do this but historically hashOf(float) did.
1919
private enum floatCoalesceNaNs = true;
@@ -47,12 +47,7 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (is(T == enum))
4747
//CTFE ready (depends on base type). Can be merged with dynamic array hash
4848
size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && __traits(isStaticArray, T))
4949
{
50-
size_t cur_hash = seed;
51-
foreach (ref cur; val)
52-
{
53-
cur_hash = hashOf(cur, cur_hash);
54-
}
55-
return cur_hash;
50+
return hashOf(val[], seed);
5651
}
5752

5853
//dynamic array hash
@@ -64,14 +59,15 @@ if (!is(T == enum) && !is(T : typeof(null)) && is(T S: S[]) && !__traits(isStati
6459
static if (is(ElementType == interface) || is(ElementType == class) ||
6560
(is(ElementType == struct) && !isNonReference!ElementType) ||
6661
((is(ElementType == struct) || is(ElementType == union))
67-
&& is(typeof(val[0].toHash()) == size_t)))
62+
&& is(typeof(val[0].toHash()) == size_t)) ||
63+
((floatCoalesceZeroes || floatCoalesceNaNs) && __traits(isFloating, ElementType)))
6864
//class or interface array or struct array with toHash(); CTFE depend on toHash() method
6965
//also do this for arrays of structs whose hashes would be calculated in a memberwise fashion
7066
{
7167
size_t hash = seed;
7268
foreach (o; val)
7369
{
74-
hash = hashOf(o, hash);
70+
hash = hashOf(hashOf(o), hash); // double hashing because TypeInfo.getHash doesn't allow to pass seed value
7571
}
7672
return hash;
7773
}
@@ -109,9 +105,16 @@ size_t hashOf(T)(scope const T val, size_t seed = 0) if (!is(T == enum) && __tra
109105
{
110106
import core.internal.traits : Unqual;
111107
Unqual!T data = val;
112-
// Zero coalescing not supported for deprecated complex types.
108+
// +0.0 and -0.0 become the same.
113109
static if (floatCoalesceZeroes && is(typeof(data = 0)))
114-
if (data == 0) data = 0; // +0.0 and -0.0 become the same.
110+
if (data == 0) data = 0;
111+
static if (floatCoalesceZeroes && is(typeof(data = 0.0i)))
112+
if (data == 0.0i) data = 0.0i;
113+
static if (floatCoalesceZeroes && is(typeof(data = 0.0 + 0.0i)))
114+
{
115+
if (data.re == 0.0) data = 0.0 + (data.im * 1.0i);
116+
if (data.im == 0.0i) data = data.re + 0.0i;
117+
}
115118
static if (floatCoalesceNaNs)
116119
if (data != data) data = T.nan; // All NaN patterns become the same.
117120
}
@@ -313,6 +316,12 @@ unittest
313316
int* a = null;
314317
}
315318

319+
static struct Plain
320+
{
321+
int a = 1;
322+
int b = 2;
323+
}
324+
316325
interface IBoo
317326
{
318327
void boo();
@@ -362,7 +371,8 @@ unittest
362371
enum realexpr = 7.88;
363372
enum raexpr = [8.99L+86i, 3.12L+99i, 5.66L+12i];
364373
enum nullexpr = null;
365-
374+
enum plstr = Plain();
375+
enum plarrstr = [Plain(), Plain(), Plain()];
366376
//No CTFE:
367377
Boom rstructexpr = Boom();
368378
Boom[] rstrarrexpr = [Boom(), Boom(), Boom()];
@@ -406,6 +416,9 @@ unittest
406416
enum h28 = realexpr.hashOf();
407417
enum h29 = raexpr.hashOf();
408418
enum h30 = nullexpr.hashOf();
419+
enum h31 = plstr.hashOf();
420+
enum h32 = plarrstr.hashOf();
421+
enum h33 = hashOf(cast(Plain[3])plarrstr);
409422

410423
auto v1 = dexpr;
411424
auto v2 = fexpr;
@@ -431,14 +444,17 @@ unittest
431444
auto v22 = cast(IBoo[3])[cast(IBoo)new Boo, cast(IBoo)new Boo, cast(IBoo)new Boo];
432445
auto v23 = cast(Bar[3])vsaexpr;
433446
auto v30 = null;
447+
auto v31 = plstr;
448+
auto v32 = plarrstr;
449+
auto v33 = cast(Plain[3])plarrstr;
434450

435451
//NO CTFE:
436-
/*auto v24 = rstructexpr;
452+
auto v24 = rstructexpr;
437453
auto v25 = rstrarrexpr;
438454
auto v26 = dgexpr;
439455
auto v27 = ptrexpr;
440456
auto v28 = realexpr;
441-
auto v29 = raexpr;*/
457+
auto v29 = raexpr;
442458

443459
//runtime hashes
444460
auto rth1 = hashOf(v1);
@@ -465,13 +481,17 @@ unittest
465481
auto rth22 = hashOf(v22);
466482
auto rth23 = hashOf(v23);
467483
auto rth30 = hashOf(v30);
468-
/*//NO CTFE:
484+
//NO CTFE:
469485
auto rth24 = hashOf(v24);
470486
auto rth25 = hashOf(v25);
471487
auto rth26 = hashOf(v26);
472488
auto rth27 = hashOf(v27);
473489
auto rth28 = hashOf(v28);
474-
auto rth29 = hashOf(v29);*/
490+
auto rth29 = hashOf(v29);
491+
492+
auto rth31 = hashOf(v31);
493+
auto rth32 = hashOf(v32);
494+
auto rth33 = hashOf(v33);
475495

476496
assert(h1 == rth1);
477497
assert(h2 == rth2);
@@ -503,8 +523,84 @@ unittest
503523
assert(h28 == rth28);
504524
assert(h29 == rth29);*/
505525
assert(h30 == rth30);
526+
assert(h31 == rth31);
527+
assert(h32 == rth32);
528+
assert(h33 == rth33);
506529

507530
assert(hashOf(null, 0) != hashOf(null, 123456789)); // issue 18932
531+
532+
static size_t tiHashOf(T)(T var)
533+
{
534+
return typeid(T).getHash(&var);
535+
}
536+
537+
auto tih1 = tiHashOf(v1);
538+
auto tih2 = tiHashOf(v2);
539+
auto tih3 = tiHashOf(v3);
540+
auto tih4 = tiHashOf(v4);
541+
auto tih5 = tiHashOf(v5);
542+
auto tih6 = tiHashOf(v6);
543+
auto tih7 = tiHashOf(v7);
544+
auto tih8 = tiHashOf(v8);
545+
auto tih9 = tiHashOf(v9);
546+
auto tih10 = tiHashOf(v10);
547+
auto tih11 = tiHashOf(v11);
548+
auto tih12 = tiHashOf(v12);
549+
auto tih13 = tiHashOf(v13);
550+
auto tih14 = tiHashOf(v14);
551+
auto tih15 = tiHashOf(v15);
552+
auto tih16 = tiHashOf(v16);
553+
auto tih17 = tiHashOf(v17);
554+
auto tih18 = tiHashOf(v18);
555+
auto tih19 = tiHashOf(v19);
556+
auto tih20 = tiHashOf(v20);
557+
auto tih21 = tiHashOf(v21);
558+
auto tih22 = tiHashOf(v22);
559+
auto tih23 = tiHashOf(v23);
560+
auto tih24 = tiHashOf(v24);
561+
auto tih25 = tiHashOf(v25);
562+
auto tih26 = tiHashOf(v26);
563+
auto tih27 = tiHashOf(v27);
564+
auto tih28 = tiHashOf(v28);
565+
auto tih29 = tiHashOf(v29);
566+
auto tih30 = tiHashOf(v30);
567+
auto tih31 = tiHashOf(v31);
568+
auto tih32 = tiHashOf(v32);
569+
auto tih33 = tiHashOf(v33);
570+
571+
assert(tih1 == rth1);
572+
assert(tih2 == rth2);
573+
assert(tih3 == rth3);
574+
assert(tih4 == rth4);
575+
assert(tih5 == rth5);
576+
assert(tih6 == rth6);
577+
assert(tih7 == rth7);
578+
assert(tih8 == rth8);
579+
assert(tih9 == rth9);
580+
//assert(tih10 == rth10); // need compiler-generated __xtoHash changes
581+
assert(tih11 == rth11);
582+
assert(tih12 == rth12);
583+
assert(tih13 == rth13);
584+
assert(tih14 == rth14);
585+
assert(tih15 == rth15);
586+
assert(tih16 == rth16);
587+
assert(tih17 == rth17);
588+
assert(tih18 == rth18);
589+
//assert(tih19 == rth19); // need compiler-generated __xtoHash changes
590+
assert(tih20 == rth20);
591+
assert(tih21 == rth21);
592+
assert(tih22 == rth22);
593+
//assert(tih23 == rth23); // need compiler-generated __xtoHash changes
594+
//assert(tih24 == rth24);
595+
//assert(tih25 == rth25);
596+
assert(tih26 == rth26);
597+
assert(tih27 == rth27);
598+
assert(tih28 == rth28);
599+
assert(tih29 == rth29);
600+
assert(tih30 == rth30);
601+
assert(tih31 == rth31);
602+
assert(tih32 == rth32);
603+
assert(tih33 == rth33);
508604
}
509605

510606

src/object.d

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,10 +1025,7 @@ class TypeInfo
10251025

10261026
override size_t toHash() @trusted const nothrow
10271027
{
1028-
import core.internal.traits : externDFunc;
1029-
alias hashOf = externDFunc!("rt.util.hash.hashOf",
1030-
size_t function(const(void)[], size_t) @trusted pure nothrow @nogc);
1031-
return hashOf(this.toString(), 0);
1028+
return hashOf(this.toString());
10321029
}
10331030

10341031
override int opCmp(Object o)
@@ -1064,7 +1061,10 @@ class TypeInfo
10641061
* Bugs:
10651062
* fix https://issues.dlang.org/show_bug.cgi?id=12516 e.g. by changing this to a truly safe interface.
10661063
*/
1067-
size_t getHash(scope const void* p) @trusted nothrow const { return cast(size_t)p; }
1064+
size_t getHash(scope const void* p) @trusted nothrow const
1065+
{
1066+
return hashOf(p);
1067+
}
10681068

10691069
/// Compares two instances for equality.
10701070
bool equals(in void* p1, in void* p2) const { return p1 == p2; }
@@ -1191,12 +1191,7 @@ class TypeInfo_Pointer : TypeInfo
11911191

11921192
override size_t getHash(scope const void* p) @trusted const
11931193
{
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);
1194+
return hashOf(*cast(void**)p);
12001195
}
12011196

12021197
override bool equals(in void* p1, in void* p2) const
@@ -1716,7 +1711,7 @@ class TypeInfo_Class : TypeInfo
17161711
override size_t getHash(scope const void* p) @trusted const
17171712
{
17181713
auto o = *cast(Object*)p;
1719-
return o ? o.toHash() : 0;
1714+
return hashOf(o ? o.toHash() : 0);
17201715
}
17211716

17221717
override bool equals(in void* p1, in void* p2) const
@@ -1870,10 +1865,14 @@ class TypeInfo_Interface : TypeInfo
18701865

18711866
override size_t getHash(scope const void* p) @trusted const
18721867
{
1868+
if (!*cast(void**)p)
1869+
{
1870+
return hashOf(null);
1871+
}
18731872
Interface* pi = **cast(Interface ***)*cast(void**)p;
18741873
Object o = cast(Object)(*cast(void**)p - pi.offset);
18751874
assert(o);
1876-
return o.toHash();
1875+
return hashOf(o.toHash());
18771876
}
18781877

18791878
override bool equals(in void* p1, in void* p2) const
@@ -1943,14 +1942,11 @@ class TypeInfo_Struct : TypeInfo
19431942
assert(p);
19441943
if (xtoHash)
19451944
{
1946-
return (*xtoHash)(p);
1945+
return hashOf((*xtoHash)(p));
19471946
}
19481947
else
19491948
{
1950-
import core.internal.traits : externDFunc;
1951-
alias hashOf = externDFunc!("rt.util.hash.hashOf",
1952-
size_t function(const(void)[], size_t) @trusted pure nothrow @nogc);
1953-
return hashOf(p[0 .. initializer().length], 0);
1949+
return hashOf(p[0 .. initializer().length]);
19541950
}
19551951
}
19561952

@@ -4546,14 +4542,12 @@ private size_t getArrayHash(in TypeInfo element, in void* ptr, in size_t count)
45464542
}
45474543

45484544
import core.internal.traits : externDFunc;
4549-
alias hashOf = externDFunc!("rt.util.hash.hashOf",
4550-
size_t function(const(void)[], size_t) @trusted pure nothrow @nogc);
45514545
if(!hasCustomToHash(element))
4552-
return hashOf(ptr[0 .. elementSize * count], 0);
4546+
return hashOf(ptr[0 .. elementSize * count]);
45534547

45544548
size_t hash = 0;
45554549
foreach(size_t i; 0 .. count)
4556-
hash = hash * 33 + element.getHash(ptr + i * elementSize);
4550+
hash = hashOf(element.getHash(ptr + i * elementSize), hash);
45574551
return hash;
45584552
}
45594553

src/rt/aaA.d

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -672,25 +672,28 @@ extern (C) int _aaEqual(in TypeInfo tiRaw, in AA aa1, in AA aa2)
672672
extern (C) hash_t _aaGetHash(in AA* aa, in TypeInfo tiRaw) nothrow
673673
{
674674
if (aa.empty)
675-
return 0;
675+
return hashOf(0);
676676

677677
import rt.lifetime : unqualify;
678678

679679
auto uti = unqualify(tiRaw);
680680
auto ti = *cast(TypeInfo_AssociativeArray*)&uti;
681681
immutable off = aa.valoff;
682+
auto keyHash = &ti.key.getHash;
682683
auto valHash = &ti.value.getHash;
683684

684685
size_t h;
686+
import core.stdc.stdio;
685687
foreach (b; aa.buckets)
686688
{
687689
if (!b.filled)
688690
continue;
689-
size_t[2] h2 = [b.hash, valHash(b.entry + off)];
691+
size_t[2] h2 = [keyHash(b.entry), valHash(b.entry + off)];
690692
// use addition here, so that hash is independent of element order
691693
h += hashOf(h2);
692694
}
693-
return h;
695+
696+
return hashOf(h);
694697
}
695698

696699
/**

0 commit comments

Comments
 (0)