@@ -490,11 +490,8 @@ namespace detail {
490490// / recursive combining of arguments used in hash_combine. It is particularly
491491// / useful at minimizing the code in the recursive calls to ease the pain
492492// / caused by a lack of variadic functions.
493- struct hash_combine_helper {
493+ struct hash_combine_recursive_helper {
494494 char buffer[64 ] = {};
495- char *buffer_ptr;
496- char *const buffer_end;
497- size_t length = 0 ;
498495 hash_state state;
499496 const uint64_t seed;
500497
@@ -503,17 +500,17 @@ struct hash_combine_helper {
503500 // /
504501 // / This sets up the state for a recursive hash combine, including getting
505502 // / the seed and buffer setup.
506- hash_combine_helper ()
507- : buffer_ptr(buffer), buffer_end(buffer + 64 ),
508- seed (get_execution_seed()) {}
503+ hash_combine_recursive_helper ()
504+ : seed(get_execution_seed()) {}
509505
510506 // / Combine one chunk of data into the current in-flight hash.
511507 // /
512508 // / This merges one chunk of data into the hash. First it tries to buffer
513509 // / the data. If the buffer is full, it hashes the buffer into its
514510 // / hash_state, empties it, and then merges the new chunk in. This also
515511 // / handles cases where the data straddles the end of the buffer.
516- template <typename T> void combine_data (T data) {
512+ template <typename T>
513+ char *combine_data (size_t &length, char *buffer_ptr, char *buffer_end, T data) {
517514 if (!store_and_advance (buffer_ptr, buffer_end, data)) {
518515 // Check for skew which prevents the buffer from being packed, and do
519516 // a partial store into the buffer to fill it. This is only a concern
@@ -544,17 +541,28 @@ struct hash_combine_helper {
544541 partial_store_size))
545542 llvm_unreachable (" buffer smaller than stored type" );
546543 }
544+ return buffer_ptr;
547545 }
548546
549547 // / Recursive, variadic combining method.
550548 // /
551549 // / This function recurses through each argument, combining that argument
552550 // / into a single hash.
553- template <typename ... Ts> hash_code combine (const Ts &...args) {
554- (combine_data (get_hashable_data (args)), ...);
551+ template <typename T, typename ...Ts>
552+ hash_code combine (size_t length, char *buffer_ptr, char *buffer_end,
553+ const T &arg, const Ts &...args) {
554+ buffer_ptr = combine_data (length, buffer_ptr, buffer_end, get_hashable_data (arg));
555555
556- // Finalize the hash by flushing any remaining data in the buffer.
557- //
556+ // Recurse to the next argument.
557+ return combine (length, buffer_ptr, buffer_end, args...);
558+ }
559+
560+ // / Base case for recursive, variadic combining.
561+ // /
562+ // / The base case when combining arguments recursively is reached when all
563+ // / arguments have been handled. It flushes the remaining buffer and
564+ // / constructs a hash_code.
565+ hash_code combine (size_t length, char *buffer_ptr, char *buffer_end) {
558566 // Check whether the entire set of values fit in the buffer. If so, we'll
559567 // use the optimized short hashing routine and skip state entirely.
560568 if (length == 0 )
@@ -588,10 +596,10 @@ struct hash_combine_helper {
588596// / The result is suitable for returning from a user's hash_value
589597// / *implementation* for their user-defined type. Consumers of a type should
590598// / *not* call this routine, they should instead call 'hash_value'.
591- template <typename ... Ts> hash_code hash_combine (const Ts &...args) {
599+ template <typename ...Ts> hash_code hash_combine (const Ts &...args) {
592600 // Recursively hash each argument using a helper class.
593- ::llvm::hashing::detail::hash_combine_helper helper;
594- return helper.combine (args...);
601+ ::llvm::hashing::detail::hash_combine_recursive_helper helper;
602+ return helper.combine (0 , helper. buffer , helper. buffer + 64 , args...);
595603}
596604
597605// Implementation details for implementations of hash_value overloads provided
0 commit comments