@@ -483,11 +483,8 @@ namespace detail {
483
483
// / recursive combining of arguments used in hash_combine. It is particularly
484
484
// / useful at minimizing the code in the recursive calls to ease the pain
485
485
// / caused by a lack of variadic functions.
486
- struct hash_combine_helper {
486
+ struct hash_combine_recursive_helper {
487
487
char buffer[64 ] = {};
488
- char *buffer_ptr;
489
- char *const buffer_end;
490
- size_t length = 0 ;
491
488
hash_state state;
492
489
const uint64_t seed;
493
490
@@ -496,17 +493,17 @@ struct hash_combine_helper {
496
493
// /
497
494
// / This sets up the state for a recursive hash combine, including getting
498
495
// / the seed and buffer setup.
499
- hash_combine_helper ()
500
- : buffer_ptr(buffer), buffer_end(buffer + 64 ),
501
- seed (get_execution_seed()) {}
496
+ hash_combine_recursive_helper ()
497
+ : seed(get_execution_seed()) {}
502
498
503
499
// / Combine one chunk of data into the current in-flight hash.
504
500
// /
505
501
// / This merges one chunk of data into the hash. First it tries to buffer
506
502
// / the data. If the buffer is full, it hashes the buffer into its
507
503
// / hash_state, empties it, and then merges the new chunk in. This also
508
504
// / handles cases where the data straddles the end of the buffer.
509
- template <typename T> void combine_data (T data) {
505
+ template <typename T>
506
+ char *combine_data (size_t &length, char *buffer_ptr, char *buffer_end, T data) {
510
507
if (!store_and_advance (buffer_ptr, buffer_end, data)) {
511
508
// Check for skew which prevents the buffer from being packed, and do
512
509
// a partial store into the buffer to fill it. This is only a concern
@@ -537,17 +534,28 @@ struct hash_combine_helper {
537
534
partial_store_size))
538
535
llvm_unreachable (" buffer smaller than stored type" );
539
536
}
537
+ return buffer_ptr;
540
538
}
541
539
542
540
// / Recursive, variadic combining method.
543
541
// /
544
542
// / This function recurses through each argument, combining that argument
545
543
// / into a single hash.
546
- template <typename ... Ts> hash_code combine (const Ts &...args) {
547
- (combine_data (get_hashable_data (args)), ...);
544
+ template <typename T, typename ...Ts>
545
+ hash_code combine (size_t length, char *buffer_ptr, char *buffer_end,
546
+ const T &arg, const Ts &...args) {
547
+ buffer_ptr = combine_data (length, buffer_ptr, buffer_end, get_hashable_data (arg));
548
548
549
- // Finalize the hash by flushing any remaining data in the buffer.
550
- //
549
+ // Recurse to the next argument.
550
+ return combine (length, buffer_ptr, buffer_end, args...);
551
+ }
552
+
553
+ // / Base case for recursive, variadic combining.
554
+ // /
555
+ // / The base case when combining arguments recursively is reached when all
556
+ // / arguments have been handled. It flushes the remaining buffer and
557
+ // / constructs a hash_code.
558
+ hash_code combine (size_t length, char *buffer_ptr, char *buffer_end) {
551
559
// Check whether the entire set of values fit in the buffer. If so, we'll
552
560
// use the optimized short hashing routine and skip state entirely.
553
561
if (length == 0 )
@@ -581,10 +589,10 @@ struct hash_combine_helper {
581
589
// / The result is suitable for returning from a user's hash_value
582
590
// / *implementation* for their user-defined type. Consumers of a type should
583
591
// / *not* call this routine, they should instead call 'hash_value'.
584
- template <typename ... Ts> hash_code hash_combine (const Ts &...args) {
592
+ template <typename ...Ts> hash_code hash_combine (const Ts &...args) {
585
593
// Recursively hash each argument using a helper class.
586
- ::llvm::hashing::detail::hash_combine_helper helper;
587
- return helper.combine (args...);
594
+ ::llvm::hashing::detail::hash_combine_recursive_helper helper;
595
+ return helper.combine (0 , helper. buffer , helper. buffer + 64 , args...);
588
596
}
589
597
590
598
// Implementation details for implementations of hash_value overloads provided
0 commit comments