@@ -483,11 +483,8 @@ namespace detail {
483483// / recursive combining of arguments used in hash_combine. It is particularly
484484// / useful at minimizing the code in the recursive calls to ease the pain
485485// / caused by a lack of variadic functions.
486- struct hash_combine_helper {
486+ struct hash_combine_recursive_helper {
487487 char buffer[64 ] = {};
488- char *buffer_ptr;
489- char *const buffer_end;
490- size_t length = 0 ;
491488 hash_state state;
492489 const uint64_t seed;
493490
@@ -496,17 +493,17 @@ struct hash_combine_helper {
496493 // /
497494 // / This sets up the state for a recursive hash combine, including getting
498495 // / 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()) {}
502498
503499 // / Combine one chunk of data into the current in-flight hash.
504500 // /
505501 // / This merges one chunk of data into the hash. First it tries to buffer
506502 // / the data. If the buffer is full, it hashes the buffer into its
507503 // / hash_state, empties it, and then merges the new chunk in. This also
508504 // / 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) {
510507 if (!store_and_advance (buffer_ptr, buffer_end, data)) {
511508 // Check for skew which prevents the buffer from being packed, and do
512509 // a partial store into the buffer to fill it. This is only a concern
@@ -537,17 +534,28 @@ struct hash_combine_helper {
537534 partial_store_size))
538535 llvm_unreachable (" buffer smaller than stored type" );
539536 }
537+ return buffer_ptr;
540538 }
541539
542540 // / Recursive, variadic combining method.
543541 // /
544542 // / This function recurses through each argument, combining that argument
545543 // / 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));
548548
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) {
551559 // Check whether the entire set of values fit in the buffer. If so, we'll
552560 // use the optimized short hashing routine and skip state entirely.
553561 if (length == 0 )
@@ -581,10 +589,10 @@ struct hash_combine_helper {
581589// / The result is suitable for returning from a user's hash_value
582590// / *implementation* for their user-defined type. Consumers of a type should
583591// / *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) {
585593 // 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...);
588596}
589597
590598// Implementation details for implementations of hash_value overloads provided
0 commit comments