]> granicus.if.org Git - re2c/commitdiff
Hash in 4-byte chunks to speedup determinization on large automata.
authorUlya Trofimovich <skvadrik@gmail.com>
Wed, 8 May 2019 08:57:59 +0000 (09:57 +0100)
committerUlya Trofimovich <skvadrik@gmail.com>
Wed, 8 May 2019 08:57:59 +0000 (09:57 +0100)
src/util/hash32.h

index 9a031415845cd956f18c781132768a90d494e388..2d57c8c0ad80beff9981fab0699bb72880d27ca5 100644 (file)
@@ -7,12 +7,36 @@
 namespace re2c
 {
 
+static inline uint32_t hash4(uint32_t h, uint32_t k)
+{
+    return h ^ ((h << 5) + (h >> 2) + k);
+}
+
+// hash in 4-byte chunks for speed
 inline uint32_t hash32(uint32_t h, const void *data, size_t size)
 {
-    const uint8_t *bytes = static_cast<const uint8_t*>(data);
-    for (size_t i = 0; i < size; ++i) {
-        h = h ^ ((h << 5) + (h >> 2) + bytes[i]);
+    static const uintptr_t ALIGN = sizeof(uint32_t);
+    static const uintptr_t MASK = ~(ALIGN - 1);
+
+    uintptr_t p = reinterpret_cast<uintptr_t>(data);
+    const uintptr_t e = p + size;
+
+    // first aligned address in range
+    const uintptr_t p1 = (p + ALIGN - 1) & MASK;
+
+    // last aligned address in range
+    const uintptr_t p2 = e & MASK;
+
+    for (; p < p1; ++p) {
+        h = hash4(h, *reinterpret_cast<uint8_t*>(p));
+    }
+    for (; p < p2; p += 4) {
+        h = hash4(h, *reinterpret_cast<uint32_t*>(p));
     }
+    for (; p < e; ++p) {
+        h = hash4(h, *reinterpret_cast<uint8_t*>(p));
+    }
+
     return h;
 }