@@ -70,19 +70,55 @@ pm_constant_id_list_includes(pm_constant_id_list_t *list, pm_constant_id_t id) {
7070}
7171
7272/**
73- * A relatively simple hash function (djb2) that is used to hash strings. We are
74- * optimizing here for simplicity and speed.
73+ * A multiply-xorshift hash that processes input a word at a time. This is
74+ * significantly faster than the byte-at-a-time djb2 hash for the short strings
75+ * typical in Ruby source (~15 bytes average). Each word is mixed into the hash
76+ * by XOR followed by multiplication by a large odd constant, which spreads
77+ * entropy across all bits. A final xorshift fold produces the 32-bit result.
7578 */
7679static inline uint32_t
7780pm_constant_pool_hash (const uint8_t * start , size_t length ) {
78- // This is a prime number used as the initial value for the hash function.
79- uint32_t value = 5381 ;
81+ // This constant is borrowed from wyhash. It is a 64-bit odd integer with
82+ // roughly equal 0/1 bits, chosen for good avalanche behavior when used in
83+ // multiply-xorshift sequences.
84+ static const uint64_t secret = 0x517cc1b727220a95ULL ;
85+ uint64_t hash = (uint64_t ) length ;
86+
87+ const uint8_t * ptr = start ;
88+ size_t remaining = length ;
89+
90+ while (remaining >= 8 ) {
91+ uint64_t word ;
92+ memcpy (& word , ptr , 8 );
93+ hash ^= word ;
94+ hash *= secret ;
95+ ptr += 8 ;
96+ remaining -= 8 ;
97+ }
98+
99+ if (remaining >= 4 ) {
100+ uint32_t word ;
101+ memcpy (& word , ptr , 4 );
102+ hash ^= (uint64_t ) word ;
103+ hash *= secret ;
104+ ptr += 4 ;
105+ remaining -= 4 ;
106+ }
107+
108+ if (remaining >= 2 ) {
109+ hash ^= (uint64_t ) ptr [0 ] | ((uint64_t ) ptr [1 ] << 8 );
110+ hash *= secret ;
111+ ptr += 2 ;
112+ remaining -= 2 ;
113+ }
80114
81- for (size_t index = 0 ; index < length ; index ++ ) {
82- value = ((value << 5 ) + value ) + start [index ];
115+ if (remaining >= 1 ) {
116+ hash ^= (uint64_t ) ptr [0 ];
117+ hash *= secret ;
83118 }
84119
85- return value ;
120+ hash ^= hash >> 32 ;
121+ return (uint32_t ) hash ;
86122}
87123
88124/**
0 commit comments