Skip to content

Commit 7288528

Browse files
committed
Short strings always use all bytes in the hash
Collisions in short strings occurr just by their existence, when internalizing them. (Collisions in long strings is caused/controlled by the program, when adding them as keys to the same table.)
1 parent 513559c commit 7288528

File tree

3 files changed

+10
-7
lines changed

3 files changed

+10
-7
lines changed

lstate.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ static unsigned int luai_makeseed (lua_State *L) {
7676
addbuff(buff, p, &h); /* local variable */
7777
addbuff(buff, p, &lua_newstate); /* public function */
7878
lua_assert(p == sizeof(buff));
79-
return luaS_hash(buff, p, h);
79+
return luaS_hash(buff, p, h, 1);
8080
}
8181

8282
#endif

lstring.c

+7-5
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424

2525
/*
26-
** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to
26+
** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a long string to
2727
** compute its hash
2828
*/
2929
#if !defined(LUAI_HASHLIMIT)
@@ -50,9 +50,9 @@ int luaS_eqlngstr (TString *a, TString *b) {
5050
}
5151

5252

53-
unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {
53+
unsigned int luaS_hash (const char *str, size_t l, unsigned int seed,
54+
size_t step) {
5455
unsigned int h = seed ^ cast_uint(l);
55-
size_t step = (l >> LUAI_HASHLIMIT) + 1;
5656
for (; l >= step; l -= step)
5757
h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1]));
5858
return h;
@@ -62,7 +62,9 @@ unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {
6262
unsigned int luaS_hashlongstr (TString *ts) {
6363
lua_assert(ts->tt == LUA_VLNGSTR);
6464
if (ts->extra == 0) { /* no hash? */
65-
ts->hash = luaS_hash(getstr(ts), ts->u.lnglen, ts->hash);
65+
size_t len = ts->u.lnglen;
66+
size_t step = (len >> LUAI_HASHLIMIT) + 1;
67+
ts->hash = luaS_hash(getstr(ts), len, ts->hash, step);
6668
ts->extra = 1; /* now it has its hash */
6769
}
6870
return ts->hash;
@@ -199,7 +201,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
199201
TString *ts;
200202
global_State *g = G(L);
201203
stringtable *tb = &g->strt;
202-
unsigned int h = luaS_hash(str, l, g->seed);
204+
unsigned int h = luaS_hash(str, l, g->seed, 1);
203205
TString **list = &tb->hash[lmod(h, tb->size)];
204206
lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */
205207
for (ts = *list; ts != NULL; ts = ts->u.hnext) {

lstring.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737
#define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b))
3838

3939

40-
LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed);
40+
LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l,
41+
unsigned int seed, size_t step);
4142
LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts);
4243
LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
4344
LUAI_FUNC void luaS_resize (lua_State *L, int newsize);

0 commit comments

Comments
 (0)