diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-03-04 10:31:21 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-03-04 10:31:21 -0300 |
commit | a80cada9142f9e967c710e37934067a708224161 (patch) | |
tree | b6ecc44201408c9e9cf520f47f15413531c51161 | |
parent | a00013c8d0d268616e004715da499e88e03b534c (diff) | |
download | lua-a80cada9142f9e967c710e37934067a708224161.tar.gz lua-a80cada9142f9e967c710e37934067a708224161.tar.bz2 lua-a80cada9142f9e967c710e37934067a708224161.zip |
new cache for interning strings
-rw-r--r-- | lgc.c | 16 | ||||
-rw-r--r-- | llimits.h | 10 | ||||
-rw-r--r-- | lstate.c | 10 | ||||
-rw-r--r-- | lstate.h | 3 | ||||
-rw-r--r-- | lstring.c | 34 | ||||
-rw-r--r-- | lstring.h | 3 |
6 files changed, 61 insertions, 15 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.201 2014/12/20 13:58:15 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.202 2015/01/16 16:54:37 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -967,6 +967,19 @@ void luaC_freeallobjects (lua_State *L) { | |||
967 | } | 967 | } |
968 | 968 | ||
969 | 969 | ||
970 | /* | ||
971 | ** Clear API string cache. (Entries cannot be empty, so fill them with | ||
972 | ** a non-collectable string.) | ||
973 | */ | ||
974 | static void clearapihash (global_State *g) { | ||
975 | int i; | ||
976 | for (i = 0; i < STRCACHE_SIZE; i++) { | ||
977 | if (iswhite(g->strcache[i])) /* will entry be collected? */ | ||
978 | g->strcache[i] = g->memerrmsg; /* replace it with something fixed */ | ||
979 | } | ||
980 | } | ||
981 | |||
982 | |||
970 | static l_mem atomic (lua_State *L) { | 983 | static l_mem atomic (lua_State *L) { |
971 | global_State *g = G(L); | 984 | global_State *g = G(L); |
972 | l_mem work; | 985 | l_mem work; |
@@ -1007,6 +1020,7 @@ static l_mem atomic (lua_State *L) { | |||
1007 | /* clear values from resurrected weak tables */ | 1020 | /* clear values from resurrected weak tables */ |
1008 | clearvalues(g, g->weak, origweak); | 1021 | clearvalues(g, g->weak, origweak); |
1009 | clearvalues(g, g->allweak, origall); | 1022 | clearvalues(g, g->allweak, origall); |
1023 | clearapihash(g); | ||
1010 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ | 1024 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ |
1011 | work += g->GCmemtrav; /* complete counting */ | 1025 | work += g->GCmemtrav; /* complete counting */ |
1012 | return work; /* estimate of memory marked by 'atomic' */ | 1026 | return work; /* estimate of memory marked by 'atomic' */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llimits.h,v 1.131 2015/02/09 15:41:56 roberto Exp roberto $ | 2 | ** $Id: llimits.h,v 1.132 2015/03/03 19:53:13 roberto Exp roberto $ |
3 | ** Limits, basic types, and some other 'installation-dependent' definitions | 3 | ** Limits, basic types, and some other 'installation-dependent' definitions |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -187,6 +187,14 @@ typedef unsigned long Instruction; | |||
187 | #endif | 187 | #endif |
188 | 188 | ||
189 | 189 | ||
190 | /* | ||
191 | ** Size of cache for strings in the API (better be a prime) | ||
192 | */ | ||
193 | #if !defined(STRCACHE_SIZE) | ||
194 | #define STRCACHE_SIZE 127 | ||
195 | #endif | ||
196 | |||
197 | |||
190 | /* minimum size for string buffer */ | 198 | /* minimum size for string buffer */ |
191 | #if !defined(LUA_MINBUFFER) | 199 | #if !defined(LUA_MINBUFFER) |
192 | #define LUA_MINBUFFER 32 | 200 | #define LUA_MINBUFFER 32 |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.126 2014/11/02 19:19:04 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.127 2014/11/02 19:33:33 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -37,9 +37,6 @@ | |||
37 | #endif | 37 | #endif |
38 | 38 | ||
39 | 39 | ||
40 | #define MEMERRMSG "not enough memory" | ||
41 | |||
42 | |||
43 | /* | 40 | /* |
44 | ** a macro to help the creation of a unique random seed when a state is | 41 | ** a macro to help the creation of a unique random seed when a state is |
45 | ** created; the seed is used to randomize hashes. | 42 | ** created; the seed is used to randomize hashes. |
@@ -200,12 +197,9 @@ static void f_luaopen (lua_State *L, void *ud) { | |||
200 | UNUSED(ud); | 197 | UNUSED(ud); |
201 | stack_init(L, L); /* init stack */ | 198 | stack_init(L, L); /* init stack */ |
202 | init_registry(L, g); | 199 | init_registry(L, g); |
203 | luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ | 200 | luaS_init(L); |
204 | luaT_init(L); | 201 | luaT_init(L); |
205 | luaX_init(L); | 202 | luaX_init(L); |
206 | /* pre-create memory-error message */ | ||
207 | g->memerrmsg = luaS_newliteral(L, MEMERRMSG); | ||
208 | luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ | ||
209 | g->gcrunning = 1; /* allow gc */ | 203 | g->gcrunning = 1; /* allow gc */ |
210 | g->version = lua_version(NULL); | 204 | g->version = lua_version(NULL); |
211 | luai_userstateopen(L); | 205 | luai_userstateopen(L); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 2.118 2014/10/25 11:50:46 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.119 2014/10/30 18:53:28 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -140,6 +140,7 @@ typedef struct global_State { | |||
140 | TString *memerrmsg; /* memory-error message */ | 140 | TString *memerrmsg; /* memory-error message */ |
141 | TString *tmname[TM_N]; /* array with tag-method names */ | 141 | TString *tmname[TM_N]; /* array with tag-method names */ |
142 | struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ | 142 | struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ |
143 | TString *strcache[STRCACHE_SIZE]; /* cache for strings in API */ | ||
143 | } global_State; | 144 | } global_State; |
144 | 145 | ||
145 | 146 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.c,v 2.45 2014/11/02 19:19:04 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 2.46 2015/01/16 16:54:37 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 | */ |
@@ -22,6 +22,8 @@ | |||
22 | #include "lstring.h" | 22 | #include "lstring.h" |
23 | 23 | ||
24 | 24 | ||
25 | #define MEMERRMSG "not enough memory" | ||
26 | |||
25 | 27 | ||
26 | /* | 28 | /* |
27 | ** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to | 29 | ** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to |
@@ -85,6 +87,21 @@ void luaS_resize (lua_State *L, int newsize) { | |||
85 | } | 87 | } |
86 | 88 | ||
87 | 89 | ||
90 | /* | ||
91 | ** Initialize the string table and the string cache | ||
92 | */ | ||
93 | void luaS_init (lua_State *L) { | ||
94 | global_State *g = G(L); | ||
95 | int i; | ||
96 | luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ | ||
97 | /* pre-create memory-error message */ | ||
98 | g->memerrmsg = luaS_newliteral(L, MEMERRMSG); | ||
99 | luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ | ||
100 | for (i = 0; i < STRCACHE_SIZE; i++) | ||
101 | g->strcache[i] = g->memerrmsg; /* fill cache with valid strings */ | ||
102 | } | ||
103 | |||
104 | |||
88 | 105 | ||
89 | /* | 106 | /* |
90 | ** creates a new string object | 107 | ** creates a new string object |
@@ -163,10 +180,21 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { | |||
163 | 180 | ||
164 | 181 | ||
165 | /* | 182 | /* |
166 | ** new zero-terminated string | 183 | ** Create or reuse a zero-terminated string, first checking in the |
184 | ** cache (using the string address as a key). The cache can contain | ||
185 | ** only zero-terminated strings, so it is safe to use 'strcmp' to | ||
186 | ** check hits. | ||
167 | */ | 187 | */ |
168 | TString *luaS_new (lua_State *L, const char *str) { | 188 | TString *luaS_new (lua_State *L, const char *str) { |
169 | return luaS_newlstr(L, str, strlen(str)); | 189 | unsigned int i = point2uint(str) % STRCACHE_SIZE; /* hash */ |
190 | TString **p = &G(L)->strcache[i]; | ||
191 | if (strcmp(str, getstr(*p)) == 0) /* hit? */ | ||
192 | return *p; /* that it is */ | ||
193 | else { /* normal route */ | ||
194 | TString *s = luaS_newlstr(L, str, strlen(str)); | ||
195 | *p = s; | ||
196 | return s; | ||
197 | } | ||
170 | } | 198 | } |
171 | 199 | ||
172 | 200 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.h,v 1.56 2014/07/18 14:46:47 roberto Exp roberto $ | 2 | ** $Id: lstring.h,v 1.57 2015/01/16 16:54:37 roberto Exp roberto $ |
3 | ** String table (keep all strings handled by Lua) | 3 | ** String table (keep all strings handled by Lua) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -36,6 +36,7 @@ | |||
36 | LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); | 36 | LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); |
37 | LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); | 37 | LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); |
38 | LUAI_FUNC void luaS_resize (lua_State *L, int newsize); | 38 | LUAI_FUNC void luaS_resize (lua_State *L, int newsize); |
39 | LUAI_FUNC void luaS_init (lua_State *L); | ||
39 | LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); | 40 | LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); |
40 | LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); | 41 | LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); |
41 | LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); | 42 | LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); |