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

Commit 892c792

Browse files
authored
Merge pull request #2209 from n8sh/core-hash-18942
Fix Issue 18942 - core.internal.hash can take advantage of alignment info on non-x86 merged-on-behalf-of: Sebastian Wilzbach <sebi.wilzbach@gmail.com>
2 parents 63efdef + ff171a8 commit 892c792

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

src/core/internal/hash.d

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ if (!is(T == enum) && !is(T : typeof(null)) && is(T S: S[]) && !__traits(isStati
5959
else static if (is(typeof(toUbyte(val)) == const(ubyte)[]))
6060
//ubyteble array (arithmetic types and structs without toHash) CTFE ready for arithmetic types and structs without reference fields
6161
{
62-
return bytesHash(toUbyte(val), seed);
62+
return bytesHashAlignedBy!ElementType(toUbyte(val), seed);
6363
}
6464
else //Other types. CTFE unsupported
6565
{
6666
assert(!__ctfe, "unable to compute hash of "~T.stringof);
67-
return bytesHash(val.ptr, ElementType.sizeof*val.length, seed);
67+
return bytesHashAlignedBy!ElementType((cast(const(ubyte)*) val.ptr)[0 .. ElementType.sizeof*val.length], seed);
6868
}
6969
}
7070

@@ -87,11 +87,11 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && __traits
8787
static if(__traits(isFloating, val))
8888
{
8989
T data = (val != val) ? T.nan : val;
90-
return bytesHash(toUbyte(data), seed);
90+
return bytesHashAlignedBy!T(toUbyte(data), seed);
9191
}
9292
else
9393
{
94-
return bytesHash(toUbyte(val), seed);
94+
return bytesHashAlignedBy!T(toUbyte(val), seed);
9595
}
9696
}
9797

@@ -147,13 +147,13 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && (is(T ==
147147
}
148148
else static if (is(typeof(toUbyte(val)) == const(ubyte)[]))//CTFE ready for structs without reference fields
149149
{
150-
return bytesHash(toUbyte(val), seed);
150+
return bytesHashAlignedBy!T(toUbyte(val), seed);
151151
}
152152
else // CTFE unsupported
153153
{
154154
assert(!__ctfe, "unable to compute hash of "~T.stringof);
155155
const(ubyte)[] bytes = (() @trusted => (cast(const(ubyte)*)&val)[0 .. T.sizeof])();
156-
return bytesHash(bytes, seed);
156+
return bytesHashAlignedBy!T(bytes, seed);
157157
}
158158
}
159159
}
@@ -187,7 +187,7 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && is(T ==
187187
{
188188
assert(!__ctfe, "unable to compute hash of "~T.stringof);
189189
const(ubyte)[] bytes = (cast(const(ubyte)*)&val)[0 .. T.sizeof];
190-
return bytesHash(bytes, seed);
190+
return bytesHashAlignedBy!T(bytes, seed);
191191
}
192192

193193
//class or interface hash. CTFE depends on toHash
@@ -473,11 +473,20 @@ nothrow pure @system unittest // issue 18918
473473
@system pure nothrow @nogc
474474
size_t bytesHash(const(void)* buf, size_t len, size_t seed)
475475
{
476-
return bytesHash((cast(const(ubyte)*) buf)[0 .. len], seed);
476+
return bytesHashAlignedBy!ubyte((cast(const(ubyte)*) buf)[0 .. len], seed);
477477
}
478478

479-
private @nogc nothrow pure @trusted
480-
size_t bytesHash(scope const(ubyte)[] bytes, size_t seed)
479+
private template bytesHashAlignedBy(AlignType)
480+
{
481+
alias bytesHashAlignedBy = bytesHash!(AlignType.alignof >= uint.alignof);
482+
}
483+
484+
/+
485+
Params:
486+
dataKnownToBeAligned = whether the data is known at compile time to be uint-aligned.
487+
+/
488+
@nogc nothrow pure @trusted
489+
private size_t bytesHash(bool dataKnownToBeAligned)(scope const(ubyte)[] bytes, size_t seed)
481490
{
482491
static uint rotl32(uint n)(in uint x) pure nothrow @safe @nogc
483492
{
@@ -490,6 +499,11 @@ size_t bytesHash(scope const(ubyte)[] bytes, size_t seed)
490499
static uint get32bits(scope const (ubyte)* x) pure nothrow @nogc
491500
{
492501
//Compiler can optimize this code to simple *cast(uint*)x if it possible.
502+
static if (dataKnownToBeAligned)
503+
{
504+
if (!__ctfe)
505+
return *cast(uint*)x;
506+
}
493507
version(BigEndian)
494508
{
495509
return ((cast(uint) x[0]) << 24) | ((cast(uint) x[1]) << 16) | ((cast(uint) x[2]) << 8) | (cast(uint) x[3]);

0 commit comments

Comments
 (0)