diff options
Diffstat (limited to 'src/lj_str.c')
-rw-r--r-- | src/lj_str.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/src/lj_str.c b/src/lj_str.c index 4a9477dd..5ba55bdd 100644 --- a/src/lj_str.c +++ b/src/lj_str.c | |||
@@ -76,15 +76,29 @@ GCstr *lj_str_new(lua_State *L, const char *str, size_t lenx) | |||
76 | GCstr *s; | 76 | GCstr *s; |
77 | GCobj *o; | 77 | GCobj *o; |
78 | MSize len = (MSize)lenx; | 78 | MSize len = (MSize)lenx; |
79 | MSize h = len; | 79 | MSize a, b, h = len; |
80 | MSize step = (len>>5)+1; /* Partial hash. */ | ||
81 | MSize l1; | ||
82 | if (lenx >= LJ_MAX_STR) | 80 | if (lenx >= LJ_MAX_STR) |
83 | lj_err_msg(L, LJ_ERR_STROV); | 81 | lj_err_msg(L, LJ_ERR_STROV); |
84 | for (l1 = len; l1 >= step; l1 -= step) /* Compute string hash. */ | ||
85 | h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); | ||
86 | /* Check if the string has already been interned. */ | ||
87 | g = G(L); | 82 | g = G(L); |
83 | /* Compute string hash. Constants taken from lookup3 hash by Bob Jenkins. */ | ||
84 | if (len >= 4) { /* Caveat: unaligned access! */ | ||
85 | a = *(const uint32_t *)str; | ||
86 | h ^= *(const uint32_t *)(str+len-4); | ||
87 | b = *(const uint32_t *)(str+(len>>1)-2); | ||
88 | h ^= b; h -= lj_rol(b, 14); | ||
89 | b += *(const uint32_t *)(str+(len>>2)-1); | ||
90 | } else if (len > 0) { | ||
91 | a = *(const uint8_t *)str; | ||
92 | h ^= *(const uint8_t *)(str+len-1); | ||
93 | b = *(const uint8_t *)(str+(len>>1)); | ||
94 | h ^= b; h -= lj_rol(b, 14); | ||
95 | } else { | ||
96 | return &g->strempty; | ||
97 | } | ||
98 | a ^= h; a -= lj_rol(h, 11); | ||
99 | b ^= a; b -= lj_rol(a, 25); | ||
100 | h ^= b; h -= lj_rol(b, 16); | ||
101 | /* Check if the string has already been interned. */ | ||
88 | for (o = gcref(g->strhash[h & g->strmask]); o != NULL; o = gcnext(o)) { | 102 | for (o = gcref(g->strhash[h & g->strmask]); o != NULL; o = gcnext(o)) { |
89 | GCstr *tso = gco2str(o); | 103 | GCstr *tso = gco2str(o); |
90 | if (tso->len == len && (memcmp(str, strdata(tso), len) == 0)) { | 104 | if (tso->len == len && (memcmp(str, strdata(tso), len) == 0)) { |