diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-08-22 12:21:48 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-08-22 12:21:48 -0300 |
| commit | 33c49f7fa03cf7e3bf7bb3aa697dc567d910c661 (patch) | |
| tree | 15af62f7b744bcb0e5abfc6fd935af592cbb5da2 /lstring.c | |
| parent | 0df6635711230ab306710056f621b6da59fac5ea (diff) | |
| download | lua-33c49f7fa03cf7e3bf7bb3aa697dc567d910c661.tar.gz lua-33c49f7fa03cf7e3bf7bb3aa697dc567d910c661.tar.bz2 lua-33c49f7fa03cf7e3bf7bb3aa697dc567d910c661.zip | |
some details over new implementation of string table
Diffstat (limited to 'lstring.c')
| -rw-r--r-- | lstring.c | 34 |
1 files changed, 18 insertions, 16 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstring.c,v 2.28 2013/08/05 16:58:28 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 2.29 2013/08/21 19:21:16 roberto Exp roberto $ |
| 3 | ** String table (keeps all strings handled by Lua) | 3 | ** String table (keeps all strings handled by Lua) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -13,6 +13,7 @@ | |||
| 13 | #include "lua.h" | 13 | #include "lua.h" |
| 14 | 14 | ||
| 15 | #include "ldebug.h" | 15 | #include "ldebug.h" |
| 16 | #include "ldo.h" | ||
| 16 | #include "lmem.h" | 17 | #include "lmem.h" |
| 17 | #include "lobject.h" | 18 | #include "lobject.h" |
| 18 | #include "lstate.h" | 19 | #include "lstate.h" |
| @@ -24,7 +25,7 @@ | |||
| 24 | 25 | ||
| 25 | 26 | ||
| 26 | /* second hash (for double hash) */ | 27 | /* second hash (for double hash) */ |
| 27 | #define h2(h1,hash,size) lmod(h1 + ((hash % 31) | 1), size) | 28 | #define h2(h1,hash,size) lmod(h1 + ((hash % 61) | 1), size) |
| 28 | 29 | ||
| 29 | 30 | ||
| 30 | /* | 31 | /* |
| @@ -116,19 +117,18 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l, | |||
| 116 | 117 | ||
| 117 | 118 | ||
| 118 | static void rehash (lua_State *L, stringtable *tb) { | 119 | static void rehash (lua_State *L, stringtable *tb) { |
| 119 | int newsize; | 120 | int size = tb->size; |
| 120 | if (tb->nuse < tb->size / 2) { /* using less than half the size? */ | 121 | if (tb->nuse < size / 2) { /* using less than half the size? */ |
| 121 | if (tb->nuse < tb->size / 4) /* using less than half of that? */ | 122 | if (tb->nuse < size / 4) /* using less than half of that? */ |
| 122 | newsize = tb->size / 2; /* shrink table */ | 123 | size /= 2; /* shrink table */ |
| 123 | else | 124 | /* else keep size (but reorganize table) */ |
| 124 | newsize = tb->size; /* keep size (but reorganize table) */ | ||
| 125 | } | 125 | } |
| 126 | else { /* table must grow */ | 126 | else { /* table must grow */ |
| 127 | if (tb->size >= MAX_INT/2) | 127 | if (size >= MAX_INT/2) /* avoid arith. overflow */ |
| 128 | luaG_runerror(L, "string-table overflow: too many strings"); | 128 | luaD_throw(L, LUA_ERRMEM); /* regular errors need new strings... */ |
| 129 | newsize = tb->size * 2; | 129 | size *= 2; |
| 130 | } | 130 | } |
| 131 | luaS_resize(L, newsize); | 131 | luaS_resize(L, size); |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | 134 | ||
| @@ -154,12 +154,10 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { | |||
| 154 | stringtable *tb = &G(L)->strt; | 154 | stringtable *tb = &G(L)->strt; |
| 155 | int vacant = -1; | 155 | int vacant = -1; |
| 156 | int h1; | 156 | int h1; |
| 157 | if (tb->empty <= 0) | ||
| 158 | rehash(L, tb); | ||
| 159 | h1 = lmod(hash, tb->size); /* previous call can changed 'size' */ | 157 | h1 = lmod(hash, tb->size); /* previous call can changed 'size' */ |
| 160 | while ((ts = tb->hash[h1]) != NULL) { /* search the string in hash table */ | 158 | while ((ts = tb->hash[h1]) != NULL) { /* search the string in hash table */ |
| 161 | if (ts == VACANTK) { | 159 | if (ts == VACANTK) { |
| 162 | if (vacant < 0) vacant = h1; /* keep track of a vacant place */ | 160 | if (vacant < 0) vacant = h1; /* keep track of first vacant place */ |
| 163 | } | 161 | } |
| 164 | else if (l == ts->tsv.len && | 162 | else if (l == ts->tsv.len && |
| 165 | (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { | 163 | (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { |
| @@ -174,12 +172,16 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { | |||
| 174 | } | 172 | } |
| 175 | h1 = h2(h1, hash, tb->size); | 173 | h1 = h2(h1, hash, tb->size); |
| 176 | } | 174 | } |
| 175 | if (tb->empty <= 0) { /* no more empty spaces? */ | ||
| 176 | rehash(L, tb); | ||
| 177 | return internshrstr(L, str, l); /* recompute insertion with new size */ | ||
| 178 | } | ||
| 177 | ts = createstrobj(L, str, l, LUA_TSHRSTR, hash); | 179 | ts = createstrobj(L, str, l, LUA_TSHRSTR, hash); |
| 178 | tb->nuse++; | 180 | tb->nuse++; |
| 179 | if (vacant < 0) /* found no vacant place? */ | 181 | if (vacant < 0) /* found no vacant place? */ |
| 180 | tb->empty--; /* will have to use the empty place */ | 182 | tb->empty--; /* will have to use the empty place */ |
| 181 | else | 183 | else |
| 182 | h1 = vacant; /* insert string into vacant place */ | 184 | h1 = vacant; /* use vacant place */ |
| 183 | tb->hash[h1] = ts; | 185 | tb->hash[h1] = ts; |
| 184 | return ts; | 186 | return ts; |
| 185 | } | 187 | } |
