@@ -57,12 +57,12 @@ if (!is(T == enum) && !is(T : typeof(null)) && is(T S: S[]) && !__traits(isStati
57
57
else static if (is (typeof (toUbyte(val)) == const (ubyte )[]))
58
58
// ubyteble array (arithmetic types and structs without toHash) CTFE ready for arithmetic types and structs without reference fields
59
59
{
60
- return bytesHash (toUbyte(val), seed);
60
+ return bytesHashAlignedBy ! ElementType (toUbyte(val), seed);
61
61
}
62
62
else // Other types. CTFE unsupported
63
63
{
64
64
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);
66
66
}
67
67
}
68
68
@@ -85,11 +85,11 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && __traits
85
85
static if (__traits(isFloating, val))
86
86
{
87
87
T data = (val != val) ? T.nan : val;
88
- return bytesHash (toUbyte(data), seed);
88
+ return bytesHashAlignedBy ! T (toUbyte(data), seed);
89
89
}
90
90
else
91
91
{
92
- return bytesHash (toUbyte(val), seed);
92
+ return bytesHashAlignedBy ! T (toUbyte(val), seed);
93
93
}
94
94
}
95
95
@@ -137,13 +137,13 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && (is(T ==
137
137
138
138
static if (is (typeof (toUbyte(val)) == const (ubyte )[]))// CTFE ready for structs without reference fields
139
139
{
140
- return bytesHash (toUbyte(val), seed);
140
+ return bytesHashAlignedBy ! T (toUbyte(val), seed);
141
141
}
142
142
else // CTFE unsupported
143
143
{
144
144
assert (! __ctfe, " unable to compute hash of " ~ T.stringof);
145
145
const (ubyte )[] bytes = (() @trusted => (cast (const (ubyte )* )&val)[0 .. T.sizeof])();
146
- return bytesHash (bytes, seed);
146
+ return bytesHashAlignedBy ! T (bytes, seed);
147
147
}
148
148
}
149
149
}
@@ -177,7 +177,7 @@ size_t hashOf(T)(auto ref T val, size_t seed = 0) if (!is(T == enum) && is(T ==
177
177
{
178
178
assert (! __ctfe, " unable to compute hash of " ~ T.stringof);
179
179
const (ubyte )[] bytes = (cast (const (ubyte )* )&val)[0 .. T.sizeof];
180
- return bytesHash (bytes, seed);
180
+ return bytesHashAlignedBy ! T (bytes, seed);
181
181
}
182
182
183
183
// class or interface hash. CTFE depends on toHash
@@ -453,11 +453,20 @@ unittest // issue 15111
453
453
@system pure nothrow @nogc
454
454
size_t bytesHash (const (void )* buf, size_t len, size_t seed)
455
455
{
456
- return bytesHash ((cast (const (ubyte )* ) buf)[0 .. len], seed);
456
+ return bytesHashAlignedBy ! ubyte ((cast (const (ubyte )* ) buf)[0 .. len], seed);
457
457
}
458
458
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)
461
470
{
462
471
static uint rotl32 (uint n)(in uint x) pure nothrow @safe @nogc
463
472
{
@@ -470,6 +479,11 @@ size_t bytesHash(scope const(ubyte)[] bytes, size_t seed)
470
479
static uint get32bits (scope const (ubyte )* x) pure nothrow @nogc
471
480
{
472
481
// 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
+ }
473
487
version (BigEndian )
474
488
{
475
489
return ((cast (uint ) x[0 ]) << 24 ) | ((cast (uint ) x[1 ]) << 16 ) | ((cast (uint ) x[2 ]) << 8 ) | (cast (uint ) x[3 ]);
0 commit comments