diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1998-01-28 14:50:33 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1998-01-28 14:50:33 -0200 |
commit | 6cdf0d8768afb16faaf6c020d6798a4588be2f74 (patch) | |
tree | 44103165d9a04254c9970ad4ede4659c03e84c13 | |
parent | 07ff251a176f341467f66a853221da81f573b5a1 (diff) | |
download | lua-6cdf0d8768afb16faaf6c020d6798a4588be2f74.tar.gz lua-6cdf0d8768afb16faaf6c020d6798a4588be2f74.tar.bz2 lua-6cdf0d8768afb16faaf6c020d6798a4588be2f74.zip |
tables can become full of "emptys" slots, and keep growing without limits.
-rw-r--r-- | bugs | 6 | ||||
-rw-r--r-- | lstring.c | 33 | ||||
-rw-r--r-- | ltable.c | 34 |
3 files changed, 47 insertions, 26 deletions
@@ -21,7 +21,7 @@ Mon Jan 19 18:17:18 EDT 1998 | |||
21 | 21 | ||
22 | ** lstrlib.c | 22 | ** lstrlib.c |
23 | Tue Jan 27 15:27:49 EDT 1998 | 23 | Tue Jan 27 15:27:49 EDT 1998 |
24 | >> formats like "%020d" were considered too big (3 algarithms); moreover, | 24 | >> formats like "%020d" were considered too big (3 digits); moreover, |
25 | >> some sistems limit printf to at most 500 chars, so we can limit sizes | 25 | >> some sistems limit printf to at most 500 chars, so we can limit sizes |
26 | >> to 2 digits (99). | 26 | >> to 2 digits (99). |
27 | 27 | ||
@@ -29,3 +29,7 @@ Tue Jan 27 15:27:49 EDT 1998 | |||
29 | Tue Jan 27 17:12:36 EDT 1998 | 29 | Tue Jan 27 17:12:36 EDT 1998 |
30 | >> "lua_getstring" may create a new string, so should check GC | 30 | >> "lua_getstring" may create a new string, so should check GC |
31 | 31 | ||
32 | ** lstring.c / ltable.c | ||
33 | Wed Jan 28 14:48:12 EDT 1998 | ||
34 | >> tables can become full of "emptys" slots, and keep growing without limits. | ||
35 | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.c,v 1.9 1997/12/30 19:15:52 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 1.10 1998/01/13 18:06:27 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 | */ |
@@ -50,26 +50,43 @@ static unsigned long hash (char *s, int tag) | |||
50 | } | 50 | } |
51 | 51 | ||
52 | 52 | ||
53 | static int newsize (stringtable *tb) | ||
54 | { | ||
55 | int size = tb->size; | ||
56 | int realuse = 0; | ||
57 | int i; | ||
58 | /* count how many entries are really in use */ | ||
59 | for (i=0; i<size; i++) | ||
60 | if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) | ||
61 | realuse++; | ||
62 | if (2*(realuse+1) <= size) /* +1 is the new element */ | ||
63 | return size; /* don't need to grow, just rehash to clear EMPTYs */ | ||
64 | else | ||
65 | return luaO_redimension(size); | ||
66 | } | ||
67 | |||
68 | |||
53 | static void grow (stringtable *tb) | 69 | static void grow (stringtable *tb) |
54 | { | 70 | { |
55 | int newsize = luaO_redimension(tb->size); | 71 | |
56 | TaggedString **newhash = luaM_newvector(newsize, TaggedString *); | 72 | int ns = newsize(tb); |
73 | TaggedString **newhash = luaM_newvector(ns, TaggedString *); | ||
57 | int i; | 74 | int i; |
58 | for (i=0; i<newsize; i++) | 75 | for (i=0; i<ns; i++) |
59 | newhash[i] = NULL; | 76 | newhash[i] = NULL; |
60 | /* rehash */ | 77 | /* rehash */ |
61 | tb->nuse = 0; | 78 | tb->nuse = 0; |
62 | for (i=0; i<tb->size; i++) { | 79 | for (i=0; i<tb->size; i++) { |
63 | if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) { | 80 | if (tb->hash[i] != NULL && tb->hash[i] != &EMPTY) { |
64 | int h = tb->hash[i]->hash%newsize; | 81 | int h = tb->hash[i]->hash%ns; |
65 | while (newhash[h]) | 82 | while (newhash[h]) |
66 | h = (h+1)%newsize; | 83 | h = (h+1)%ns; |
67 | newhash[h] = tb->hash[i]; | 84 | newhash[h] = tb->hash[i]; |
68 | tb->nuse++; | 85 | tb->nuse++; |
69 | } | 86 | } |
70 | } | 87 | } |
71 | luaM_free(tb->hash); | 88 | luaM_free(tb->hash); |
72 | tb->size = newsize; | 89 | tb->size = ns; |
73 | tb->hash = newhash; | 90 | tb->hash = newhash; |
74 | } | 91 | } |
75 | 92 | ||
@@ -86,7 +103,7 @@ static TaggedString *newone (char *buff, int tag, unsigned long h) | |||
86 | L->nblocks += gcsizestring(l); | 103 | L->nblocks += gcsizestring(l); |
87 | } | 104 | } |
88 | else { | 105 | else { |
89 | ts = (TaggedString *)luaM_malloc(sizeof(TaggedString)); | 106 | ts = luaM_new(TaggedString); |
90 | ts->u.d.v = buff; | 107 | ts->u.d.v = buff; |
91 | ts->u.d.tag = tag == LUA_ANYTAG ? 0 : tag; | 108 | ts->u.d.tag = tag == LUA_ANYTAG ? 0 : tag; |
92 | ts->constindex = -1; /* tag -> this is a userdata */ | 109 | ts->constindex = -1; /* tag -> this is a userdata */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 1.10 1998/01/09 14:44:55 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 1.11 1998/01/13 18:06:27 roberto Exp roberto $ |
3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -121,36 +121,36 @@ Hash *luaH_new (int nhash) | |||
121 | } | 121 | } |
122 | 122 | ||
123 | 123 | ||
124 | /* | 124 | static int newsize (Hash *t) |
125 | ** Rehash: | ||
126 | ** Check if table has deleted slots. It it has, it does not need to | ||
127 | ** grow, since rehash will reuse them. | ||
128 | */ | ||
129 | static int emptyslots (Hash *t) | ||
130 | { | 125 | { |
126 | Node *v = t->node; | ||
127 | int size = nhash(t); | ||
128 | int realuse = 0; | ||
131 | int i; | 129 | int i; |
132 | for (i=nhash(t)-1; i>=0; i--) { | 130 | for (i=0; i<size; i++) { |
133 | Node *n = node(t, i); | 131 | if (ttype(ref(v+i)) != LUA_T_NIL && ttype(val(v+i)) != LUA_T_NIL) |
134 | if (ttype(ref(n)) != LUA_T_NIL && ttype(val(n)) == LUA_T_NIL) | 132 | realuse++; |
135 | return 1; | ||
136 | } | 133 | } |
137 | return 0; | 134 | if (2*(realuse+1) <= size) /* +1 is the new element */ |
135 | return size; /* don't need to grow, just rehash */ | ||
136 | else | ||
137 | return luaO_redimension(size); | ||
138 | } | 138 | } |
139 | 139 | ||
140 | static void rehash (Hash *t) | 140 | static void rehash (Hash *t) |
141 | { | 141 | { |
142 | int nold = nhash(t); | 142 | int nold = nhash(t); |
143 | Node *vold = nodevector(t); | 143 | Node *vold = nodevector(t); |
144 | int nnew = newsize(t); | ||
144 | int i; | 145 | int i; |
145 | if (!emptyslots(t)) | 146 | nodevector(t) = hashnodecreate(nnew); |
146 | nhash(t) = luaO_redimension(nhash(t)); | 147 | nhash(t) = nnew; |
147 | nodevector(t) = hashnodecreate(nhash(t)); | ||
148 | for (i=0; i<nold; i++) { | 148 | for (i=0; i<nold; i++) { |
149 | Node *n = vold+i; | 149 | Node *n = vold+i; |
150 | if (ttype(ref(n)) != LUA_T_NIL && ttype(val(n)) != LUA_T_NIL) | 150 | if (ttype(ref(n)) != LUA_T_NIL && ttype(val(n)) != LUA_T_NIL) |
151 | *node(t, present(t, ref(n))) = *n; /* copy old node to luaM_new hash */ | 151 | *node(t, present(t, ref(n))) = *n; /* copy old node to luaM_new hash */ |
152 | } | 152 | } |
153 | L->nblocks += gcsize(t->nhash)-gcsize(nold); | 153 | L->nblocks += gcsize(nnew)-gcsize(nold); |
154 | luaM_free(vold); | 154 | luaM_free(vold); |
155 | } | 155 | } |
156 | 156 | ||