diff --git a/src/lj_str.c b/src/lj_str.c index 8e999223..d684b393 100644 --- a/src/lj_str.c +++ b/src/lj_str.c @@ -130,6 +130,27 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx) lj_err_msg(L, LJ_ERR_STROV); g = G(L); /* Compute string hash. Constants taken from lookup3 hash by Bob Jenkins. */ +#if LJ_ARCH_BITS == 64 && LJ_TARGET_UNALIGNED + if (LJ_UNLIKELY(len > 128)) { + MSize i = (len-1)/16; + const char *ss; + uint64_t h1 = *(uint64_t*)(str+len-8); + uint64_t h2 = *(uint64_t*)(str+len-16); + uint64_t h3 = len; + ss = str; + for (; i; i--, ss += 16) { + h3 = lj_rol(h3 ^ h1, 33) + (h2 ^ 0xdeadbeef); + h1 = lj_rol(h1, 23); h1 -= *(uint64_t*)ss; + h2 = lj_rol(h2, 21); h2 -= *(uint64_t*)(ss+8); + } + h1 -= lj_rol(h3, 19); + h2 -= lj_rol(h1, 19); + h3 -= lj_rol(h2, 19); + h = (uint32_t)h3 - (uint32_t)(h1 >> 32); + a = (uint32_t)h1 - (uint32_t)(h2 >> 32); + b = (uint32_t)h2 - (uint32_t)(h3 >> 32); + } else +#endif if (len >= 12) { /* Caveat: unaligned access! */ MSize i = (len-1)/8; const char *ss;