@@ -249,7 +249,7 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
249
249
return 1 ;
250
250
}
251
251
252
- static unsigned long xdl_hash_record_with_whitespace (char const * * data ,
252
+ unsigned long xdl_hash_record_with_whitespace (char const * * data ,
253
253
char const * top , long flags ) {
254
254
unsigned long ha = 5381 ;
255
255
char const * ptr = * data ;
@@ -294,19 +294,67 @@ static unsigned long xdl_hash_record_with_whitespace(char const **data,
294
294
return ha ;
295
295
}
296
296
297
- unsigned long xdl_hash_record (char const * * data , char const * top , long flags ) {
298
- unsigned long ha = 5381 ;
297
+ /*
298
+ * Compiler reassociation barrier: pretend to modify X and Y to disallow
299
+ * changing evaluation order with respect to following uses of X and Y.
300
+ */
301
+ #ifdef __GNUC__
302
+ #define REASSOC_FENCE (x , y ) __asm__("" : "+r"(x), "+r"(y))
303
+ #else
304
+ #define REASSOC_FENCE (x , y )
305
+ #endif
306
+
307
+ unsigned long xdl_hash_record_verbatim (char const * * data , char const * top ) {
308
+ unsigned long ha = 5381 , c0 , c1 ;
299
309
char const * ptr = * data ;
300
-
301
- if (flags & XDF_WHITESPACE_FLAGS )
302
- return xdl_hash_record_with_whitespace (data , top , flags );
303
-
310
+ #if 0
311
+ /*
312
+ * The baseline form of the optimized loop below. This is the djb2
313
+ * hash (the above function uses a variant with XOR instead of ADD).
314
+ */
304
315
for (; ptr < top && * ptr != '\n' ; ptr ++ ) {
305
316
ha += (ha << 5 );
306
- ha ^ = (unsigned long ) * ptr ;
317
+ ha + = (unsigned long ) * ptr ;
307
318
}
308
319
* data = ptr < top ? ptr + 1 : ptr ;
309
-
320
+ #else
321
+ /* Process two characters per iteration. */
322
+ if (top - ptr >= 2 ) do {
323
+ if ((c0 = ptr [0 ]) == '\n' ) {
324
+ * data = ptr + 1 ;
325
+ return ha ;
326
+ }
327
+ if ((c1 = ptr [1 ]) == '\n' ) {
328
+ * data = ptr + 2 ;
329
+ c0 += ha ;
330
+ REASSOC_FENCE (c0 , ha );
331
+ ha = ha * 32 + c0 ;
332
+ return ha ;
333
+ }
334
+ /*
335
+ * Combine characters C0 and C1 into the hash HA. We have
336
+ * HA = (HA * 33 + C0) * 33 + C1, and we want to ensure
337
+ * that dependency chain over HA is just one multiplication
338
+ * and one addition, i.e. we want to evaluate this as
339
+ * HA = HA * 33 * 33 + (C0 * 33 + C1), and likewise prefer
340
+ * (C0 * 32 + (C0 + C1)) for the expression in parenthesis.
341
+ */
342
+ ha *= 33 * 33 ;
343
+ c1 += c0 ;
344
+ REASSOC_FENCE (c1 , c0 );
345
+ c1 += c0 * 32 ;
346
+ REASSOC_FENCE (c1 , ha );
347
+ ha += c1 ;
348
+
349
+ ptr += 2 ;
350
+ } while (ptr < top - 1 );
351
+ * data = top ;
352
+ if (ptr < top && (c0 = ptr [0 ]) != '\n' ) {
353
+ c0 += ha ;
354
+ REASSOC_FENCE (c0 , ha );
355
+ ha = ha * 32 + c0 ;
356
+ }
357
+ #endif
310
358
return ha ;
311
359
}
312
360
0 commit comments