@@ -59,12 +59,12 @@ if (!is(T == enum) && !is(T : typeof(null)) && is(T S: S[]) && !__traits(isStati
59
59
else static if (is (typeof (toUbyte(val)) == const (ubyte )[]))
60
60
// ubyteble array (arithmetic types and structs without toHash) CTFE ready for arithmetic types and structs without reference fields
61
61
{
62
- return bytesHash (toUbyte(val), seed);
62
+ return bytesHashAlignedBy ! ElementType (toUbyte(val), seed);
63
63
}
64
64
else // Other types. CTFE unsupported
65
65
{
66
66
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);
68
68
}
69
69
}
70
70
@@ -87,11 +87,11 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && __traits
87
87
static if (__traits(isFloating, val))
88
88
{
89
89
T data = (val != val) ? T.nan : val;
90
- return bytesHash (toUbyte(data), seed);
90
+ return bytesHashAlignedBy ! T (toUbyte(data), seed);
91
91
}
92
92
else
93
93
{
94
- return bytesHash (toUbyte(val), seed);
94
+ return bytesHashAlignedBy ! T (toUbyte(val), seed);
95
95
}
96
96
}
97
97
@@ -147,13 +147,13 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && (is(T ==
147
147
}
148
148
else static if (is (typeof (toUbyte(val)) == const (ubyte )[]))// CTFE ready for structs without reference fields
149
149
{
150
- return bytesHash (toUbyte(val), seed);
150
+ return bytesHashAlignedBy ! T (toUbyte(val), seed);
151
151
}
152
152
else // CTFE unsupported
153
153
{
154
154
assert (! __ctfe, " unable to compute hash of " ~ T.stringof);
155
155
const (ubyte )[] bytes = (() @trusted => (cast (const (ubyte )* )&val)[0 .. T.sizeof])();
156
- return bytesHash (bytes, seed);
156
+ return bytesHashAlignedBy ! T (bytes, seed);
157
157
}
158
158
}
159
159
}
@@ -187,7 +187,7 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && is(T ==
187
187
{
188
188
assert (! __ctfe, " unable to compute hash of " ~ T.stringof);
189
189
const (ubyte )[] bytes = (cast (const (ubyte )* )&val)[0 .. T.sizeof];
190
- return bytesHash (bytes, seed);
190
+ return bytesHashAlignedBy ! T (bytes, seed);
191
191
}
192
192
193
193
// class or interface hash. CTFE depends on toHash
@@ -473,11 +473,20 @@ nothrow pure @system unittest // issue 18918
473
473
@system pure nothrow @nogc
474
474
size_t bytesHash (const (void )* buf, size_t len, size_t seed)
475
475
{
476
- return bytesHash ((cast (const (ubyte )* ) buf)[0 .. len], seed);
476
+ return bytesHashAlignedBy ! ubyte ((cast (const (ubyte )* ) buf)[0 .. len], seed);
477
477
}
478
478
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)
481
490
{
482
491
static uint rotl32 (uint n)(in uint x) pure nothrow @safe @nogc
483
492
{
@@ -490,6 +499,11 @@ size_t bytesHash(scope const(ubyte)[] bytes, size_t seed)
490
499
static uint get32bits (scope const (ubyte )* x) pure nothrow @nogc
491
500
{
492
501
// 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
+ }
493
507
version (BigEndian )
494
508
{
495
509
return ((cast (uint ) x[0 ]) << 24 ) | ((cast (uint ) x[1 ]) << 16 ) | ((cast (uint ) x[2 ]) << 8 ) | (cast (uint ) x[3 ]);
0 commit comments