rehashes string table always allocating a new array instead of

reallocating old one. (Avoids problems if reallocation to a small
size fails.)
This commit is contained in:
Roberto Ierusalimschy 2017-12-01 14:40:29 -02:00
parent e0bece77d6
commit 9d28b40152
1 changed files with 11 additions and 17 deletions

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lstring.c,v 2.56 2015/11/23 11:32:51 roberto Exp roberto $ ** $Id: lstring.c,v 2.57 2017/07/27 13:50:16 roberto Exp roberto $
** String table (keeps all strings handled by Lua) ** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -63,32 +63,26 @@ unsigned int luaS_hashlongstr (TString *ts) {
/* /*
** resizes the string table ** Resizes the string table.
*/ */
void luaS_resize (lua_State *L, int newsize) { void luaS_resize (lua_State *L, int newsize) {
int i; int i;
TString **newhash = luaM_newvector(L, newsize, TString *);
stringtable *tb = &G(L)->strt; stringtable *tb = &G(L)->strt;
if (newsize > tb->size) { /* grow table if needed */ for (i = 0; i < newsize; i++) /* initialize new hash array */
luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); newhash[i] = NULL;
for (i = tb->size; i < newsize; i++) for (i = 0; i < tb->size; i++) { /* rehash all elements into new array */
tb->hash[i] = NULL;
}
for (i = 0; i < tb->size; i++) { /* rehash */
TString *p = tb->hash[i]; TString *p = tb->hash[i];
tb->hash[i] = NULL; while (p) { /* for each string in the list */
while (p) { /* for each node in the list */
TString *hnext = p->u.hnext; /* save next */ TString *hnext = p->u.hnext; /* save next */
unsigned int h = lmod(p->hash, newsize); /* new position */ unsigned int h = lmod(p->hash, newsize); /* new position */
p->u.hnext = tb->hash[h]; /* chain it */ p->u.hnext = newhash[h]; /* chain it into new array */
tb->hash[h] = p; newhash[h] = p;
p = hnext; p = hnext;
} }
} }
if (newsize < tb->size) { /* shrink table if needed */ luaM_freearray(L, tb->hash, tb->size); /* free old array */
/* vanishing slice should be empty */ tb->hash = newhash;
lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL);
luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *);
}
tb->size = newsize; tb->size = newsize;
} }