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

Commit ff171a8

Browse files
n8shwilzbach
authored andcommitted
Fix Issue 18942 - core.internal.hash can take advantage of alignment info on non-x86
1 parent 8fd5201 commit ff171a8

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
@@ -57,12 +57,12 @@ if (!is(T == enum) && !is(T : typeof(null)) && is(T S: S[]) && !__traits(isStati
5757
else static if (is(typeof(toUbyte(val)) == const(ubyte)[]))
5858
//ubyteble array (arithmetic types and structs without toHash) CTFE ready for arithmetic types and structs without reference fields
5959
{
60-
return bytesHash(toUbyte(val), seed);
60+
return bytesHashAlignedBy!ElementType(toUbyte(val), seed);
6161
}
6262
else //Other types. CTFE unsupported
6363
{
6464
assert(!__ctfe, "unable to compute hash of "~T.stringof);
65-
return bytesHash(val.ptr, ElementType.sizeof*val.length, seed);
65+
return bytesHashAlignedBy!ElementType((cast(const(ubyte)*) val.ptr)[0 .. ElementType.sizeof*val.length], seed);
6666
}
6767
}
6868

@@ -85,11 +85,11 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && __traits
8585
static if(__traits(isFloating, val))
8686
{
8787
T data = (val != val) ? T.nan : val;
88-
return bytesHash(toUbyte(data), seed);
88+
return bytesHashAlignedBy!T(toUbyte(data), seed);
8989
}
9090
else
9191
{
92-
return bytesHash(toUbyte(val), seed);
92+
return bytesHashAlignedBy!T(toUbyte(val), seed);
9393
}
9494
}
9595

@@ -137,13 +137,13 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && (is(T ==
137137

138138
static if (is(typeof(toUbyte(val)) == const(ubyte)[]))//CTFE ready for structs without reference fields
139139
{
140-
return bytesHash(toUbyte(val), seed);
140+
return bytesHashAlignedBy!T(toUbyte(val), seed);
141141
}
142142
else // CTFE unsupported
143143
{
144144
assert(!__ctfe, "unable to compute hash of "~T.stringof);
145145
const(ubyte)[] bytes = (() @trusted => (cast(const(ubyte)*)&val)[0 .. T.sizeof])();
146-
return bytesHash(bytes, seed);
146+
return bytesHashAlignedBy!T(bytes, seed);
147147
}
148148
}
149149
}
@@ -177,7 +177,7 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && is(T ==
177177
{
178178
assert(!__ctfe, "unable to compute hash of "~T.stringof);
179179
const(ubyte)[] bytes = (cast(const(ubyte)*)&val)[0 .. T.sizeof];
180-
return bytesHash(bytes, seed);
180+
return bytesHashAlignedBy!T(bytes, seed);
181181
}
182182

183183
//class or interface hash. CTFE depends on toHash
@@ -453,11 +453,20 @@ unittest // issue 15111
453453
@system pure nothrow @nogc
454454
size_t bytesHash(const(void)* buf, size_t len, size_t seed)
455455
{
456-
return bytesHash((cast(const(ubyte)*) buf)[0 .. len], seed);
456+
return bytesHashAlignedBy!ubyte((cast(const(ubyte)*) buf)[0 .. len], seed);
457457
}
458458

459-
private @nogc nothrow pure @trusted
460-
size_t bytesHash(scope const(ubyte)[] bytes, size_t seed)
459+
private template bytesHashAlignedBy(AlignType)
460+
{
461+
alias bytesHashAlignedBy = bytesHash!(AlignType.alignof >= uint.alignof);
462+
}
463+
464+
/+
465+
Params:
466+
dataKnownToBeAligned = whether the data is known at compile time to be uint-aligned.
467+
+/
468+
@nogc nothrow pure @trusted
469+
private size_t bytesHash(bool dataKnownToBeAligned)(scope const(ubyte)[] bytes, size_t seed)
461470
{
462471
static uint rotl32(uint n)(in uint x) pure nothrow @safe @nogc
463472
{
@@ -470,6 +479,11 @@ size_t bytesHash(scope const(ubyte)[] bytes, size_t seed)
470479
static uint get32bits(scope const (ubyte)* x) pure nothrow @nogc
471480
{
472481
//Compiler can optimize this code to simple *cast(uint*)x if it possible.
482+
static if (dataKnownToBeAligned)
483+
{
484+
if (!__ctfe)
485+
return *cast(uint*)x;
486+
}
473487
version(BigEndian)
474488
{
475489
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)