diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-08-07 17:21:34 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-08-07 17:21:34 -0300 |
commit | d9e61e8ceafe8c3f6ad936979719ca7c446ce228 (patch) | |
tree | 0808ada3d7b7219022b9002503894c76c7253df6 | |
parent | 397905ef8694ec716a51acebc993bb625340d388 (diff) | |
download | lua-d9e61e8ceafe8c3f6ad936979719ca7c446ce228.tar.gz lua-d9e61e8ceafe8c3f6ad936979719ca7c446ce228.tar.bz2 lua-d9e61e8ceafe8c3f6ad936979719ca7c446ce228.zip |
new algorithm for traversing in GC to avoid deep recursion calls
-rw-r--r-- | ldebug.c | 37 | ||||
-rw-r--r-- | lfunc.c | 4 | ||||
-rw-r--r-- | lgc.c | 148 | ||||
-rw-r--r-- | lobject.h | 24 | ||||
-rw-r--r-- | lref.c | 12 | ||||
-rw-r--r-- | ltable.c | 12 | ||||
-rw-r--r-- | ltm.c | 15 | ||||
-rw-r--r-- | ltm.h | 3 |
8 files changed, 143 insertions, 112 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.c,v 1.26 2000/06/30 14:29:35 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 1.27 2000/06/30 14:35:17 roberto Exp roberto $ |
3 | ** Debug Interface | 3 | ** Debug Interface |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -172,25 +172,38 @@ static void lua_funcinfo (lua_Debug *ar, StkId func) { | |||
172 | } | 172 | } |
173 | 173 | ||
174 | 174 | ||
175 | static int checkfunc (lua_State *L, TObject *o) { | 175 | static const char *travtagmethods (lua_State *L, const TObject *o) { |
176 | return luaO_equalObj(o, L->top); | 176 | int e; |
177 | for (e=0; e<IM_N; e++) { | ||
178 | int t; | ||
179 | for (t=0; t<=L->last_tag; t++) | ||
180 | if (luaO_equalObj(o, luaT_getim(L, t,e))) | ||
181 | return luaT_eventname[e]; | ||
182 | } | ||
183 | return NULL; | ||
177 | } | 184 | } |
178 | 185 | ||
179 | 186 | ||
180 | static void lua_getobjname (lua_State *L, StkId f, lua_Debug *ar) { | 187 | static const char *travglobals (lua_State *L, const TObject *o) { |
181 | Hash *g = L->gt; | 188 | Hash *g = L->gt; |
182 | int i; | 189 | int i; |
183 | /* try to find a name for given function */ | ||
184 | setnormalized(L->top, f); /* to be used by `checkfunc' */ | ||
185 | for (i=0; i<=g->size; i++) { | 190 | for (i=0; i<=g->size; i++) { |
186 | if (ttype(key(node(g,i))) == TAG_STRING && checkfunc(L, val(node(g,i)))) { | 191 | if (luaO_equalObj(o, val(node(g, i))) && |
187 | ar->name = tsvalue(key(node(g,i)))->str; | 192 | ttype(key(node(g, i))) == TAG_STRING) |
188 | ar->namewhat = "global"; | 193 | return tsvalue(key(node(g, i)))->str; |
189 | return; | ||
190 | } | ||
191 | } | 194 | } |
195 | return NULL; | ||
196 | } | ||
197 | |||
198 | |||
199 | static void lua_getobjname (lua_State *L, StkId f, lua_Debug *ar) { | ||
200 | TObject o; | ||
201 | setnormalized(&o, f); | ||
202 | /* try to find a name for given function */ | ||
203 | if ((ar->name = travglobals(L, &o)) != NULL) | ||
204 | ar->namewhat = "global"; | ||
192 | /* not found: try tag methods */ | 205 | /* not found: try tag methods */ |
193 | if ((ar->name = luaT_travtagmethods(L, checkfunc)) != NULL) | 206 | else if ((ar->name = travtagmethods(L, &o)) != NULL) |
194 | ar->namewhat = "tag-method"; | 207 | ar->namewhat = "tag-method"; |
195 | else ar->namewhat = ""; /* not found at all */ | 208 | else ar->namewhat = ""; /* not found at all */ |
196 | } | 209 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lfunc.c,v 1.24 2000/06/12 13:52:05 roberto Exp roberto $ | 2 | ** $Id: lfunc.c,v 1.25 2000/06/26 19:28:31 roberto Exp roberto $ |
3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -25,7 +25,7 @@ Closure *luaF_newclosure (lua_State *L, int nelems) { | |||
25 | (lint32)sizeof(TObject)*(nelems-1)); | 25 | (lint32)sizeof(TObject)*(nelems-1)); |
26 | c->next = L->rootcl; | 26 | c->next = L->rootcl; |
27 | L->rootcl = c; | 27 | L->rootcl = c; |
28 | c->marked = 0; | 28 | c->mark = c; |
29 | c->nupvalues = nelems; | 29 | c->nupvalues = nelems; |
30 | L->nblocks += gcsizeclosure(L, c); | 30 | L->nblocks += gcsizeclosure(L, c); |
31 | return c; | 31 | return c; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.58 2000/06/26 19:28:31 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.59 2000/06/30 14:35:17 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 | */ |
@@ -20,97 +20,94 @@ | |||
20 | #include "ltm.h" | 20 | #include "ltm.h" |
21 | 21 | ||
22 | 22 | ||
23 | typedef struct GCState { | ||
24 | Hash *tmark; /* list of marked tables to be visited */ | ||
25 | Closure *cmark; /* list of marked closures to be visited */ | ||
26 | } GCState; | ||
23 | 27 | ||
24 | 28 | ||
25 | static int markobject (lua_State *L, TObject *o); | 29 | |
30 | static int markobject (GCState *st, TObject *o); | ||
26 | 31 | ||
27 | 32 | ||
28 | /* mark a string; marks larger than 1 cannot be changed */ | 33 | /* mark a string; marks larger than 1 cannot be changed */ |
29 | #define strmark(L, s) {if ((s)->marked == 0) (s)->marked = 1;} | 34 | #define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;} |
30 | 35 | ||
31 | 36 | ||
32 | 37 | ||
33 | static void protomark (lua_State *L, Proto *f) { | 38 | static void protomark (Proto *f) { |
34 | if (!f->marked) { | 39 | if (!f->marked) { |
35 | int i; | 40 | int i; |
36 | f->marked = 1; | 41 | f->marked = 1; |
37 | strmark(L, f->source); | 42 | strmark(f->source); |
38 | for (i=0; i<f->nkstr; i++) | 43 | for (i=0; i<f->nkstr; i++) |
39 | strmark(L, f->kstr[i]); | 44 | strmark(f->kstr[i]); |
40 | for (i=0; i<f->nkproto; i++) | 45 | for (i=0; i<f->nkproto; i++) |
41 | protomark(L, f->kproto[i]); | 46 | protomark(f->kproto[i]); |
42 | if (f->locvars) { /* is there debug information? */ | 47 | if (f->locvars) { /* is there debug information? */ |
43 | LocVar *lv; | 48 | LocVar *lv; |
44 | for (lv=f->locvars; lv->pc != -1; lv++) /* mark local-variable names */ | 49 | for (lv=f->locvars; lv->pc != -1; lv++) /* mark local-variable names */ |
45 | if (lv->varname) strmark(L, lv->varname); | 50 | if (lv->varname) strmark(lv->varname); |
46 | } | 51 | } |
47 | } | 52 | } |
48 | } | 53 | } |
49 | 54 | ||
50 | 55 | ||
51 | static void closuremark (lua_State *L, Closure *f) { | 56 | static void markstack (lua_State *L, GCState *st) { |
52 | if (!f->marked) { | ||
53 | int i = f->nupvalues; | ||
54 | f->marked = 1; | ||
55 | while (i--) | ||
56 | markobject(L, &f->upvalue[i]); | ||
57 | } | ||
58 | } | ||
59 | |||
60 | |||
61 | static void tablemark (lua_State *L, Hash *h) { | ||
62 | if (!h->marked) { | ||
63 | int i; | ||
64 | h->marked = 1; | ||
65 | for (i=h->size-1; i>=0; i--) { | ||
66 | Node *n = node(h,i); | ||
67 | if (ttype(key(n)) != TAG_NIL) { | ||
68 | if (ttype(val(n)) == TAG_NIL) | ||
69 | luaH_remove(h, key(n)); /* dead element; try to remove it */ | ||
70 | markobject(L, &n->key); | ||
71 | markobject(L, &n->val); | ||
72 | } | ||
73 | } | ||
74 | } | ||
75 | } | ||
76 | |||
77 | |||
78 | static void travstack (lua_State *L) { | ||
79 | StkId o; | 57 | StkId o; |
80 | for (o=L->stack; o<L->top; o++) | 58 | for (o=L->stack; o<L->top; o++) |
81 | markobject(L, o); | 59 | markobject(st, o); |
82 | } | 60 | } |
83 | 61 | ||
84 | 62 | ||
85 | static void travlock (lua_State *L) { | 63 | static void marklock (lua_State *L, GCState *st) { |
86 | int i; | 64 | int i; |
87 | for (i=0; i<L->refSize; i++) { | 65 | for (i=0; i<L->refSize; i++) { |
88 | if (L->refArray[i].st == LOCK) | 66 | if (L->refArray[i].st == LOCK) |
89 | markobject(L, &L->refArray[i].o); | 67 | markobject(st, &L->refArray[i].o); |
68 | } | ||
69 | } | ||
70 | |||
71 | |||
72 | static void marktagmethods (lua_State *L, GCState *st) { | ||
73 | int e; | ||
74 | for (e=0; e<IM_N; e++) { | ||
75 | int t; | ||
76 | for (t=0; t<=L->last_tag; t++) | ||
77 | markobject(st, luaT_getim(L, t,e)); | ||
90 | } | 78 | } |
91 | } | 79 | } |
92 | 80 | ||
93 | 81 | ||
94 | static int markobject (lua_State *L, TObject *o) { | 82 | static int markobject (GCState *st, TObject *o) { |
95 | switch (ttype(o)) { | 83 | switch (ttype(o)) { |
96 | case TAG_USERDATA: case TAG_STRING: | 84 | case TAG_USERDATA: case TAG_STRING: |
97 | strmark(L, tsvalue(o)); | 85 | strmark(tsvalue(o)); |
98 | break; | ||
99 | case TAG_TABLE: | ||
100 | tablemark(L, hvalue(o)); | ||
101 | break; | 86 | break; |
102 | case TAG_LCLOSURE: | 87 | case TAG_TABLE: { |
103 | protomark(L, clvalue(o)->f.l); | 88 | if (!ismarked(hvalue(o))) { |
104 | closuremark(L, clvalue(o)); | 89 | hvalue(o)->mark = st->tmark; /* chain it in list of marked */ |
90 | st->tmark = hvalue(o); | ||
91 | } | ||
105 | break; | 92 | break; |
93 | } | ||
106 | case TAG_LMARK: { | 94 | case TAG_LMARK: { |
107 | Closure *cl = infovalue(o)->func; | 95 | Closure *cl = infovalue(o)->func; |
108 | protomark(L, cl->f.l); | 96 | if (!ismarked(cl)) { |
109 | closuremark(L, cl); | 97 | protomark(cl->f.l); |
98 | cl->mark = st->cmark; /* chain it for later traversal */ | ||
99 | st->cmark = cl; | ||
100 | } | ||
110 | break; | 101 | break; |
111 | } | 102 | } |
103 | case TAG_LCLOSURE: | ||
104 | protomark(clvalue(o)->f.l); | ||
105 | /* go through */ | ||
112 | case TAG_CCLOSURE: case TAG_CMARK: | 106 | case TAG_CCLOSURE: case TAG_CMARK: |
113 | closuremark(L, clvalue(o)); | 107 | if (!ismarked(clvalue(o))) { |
108 | clvalue(o)->mark = st->cmark; /* chain it for later traversal */ | ||
109 | st->cmark = clvalue(o); | ||
110 | } | ||
114 | break; | 111 | break; |
115 | default: break; /* numbers, etc */ | 112 | default: break; /* numbers, etc */ |
116 | } | 113 | } |
@@ -118,6 +115,41 @@ static int markobject (lua_State *L, TObject *o) { | |||
118 | } | 115 | } |
119 | 116 | ||
120 | 117 | ||
118 | static void markall (lua_State *L) { | ||
119 | GCState st; | ||
120 | st.cmark = NULL; | ||
121 | st.tmark = L->gt; /* put table of globals in mark list */ | ||
122 | L->gt->mark = NULL; | ||
123 | marktagmethods(L, &st); /* mark tag methods */ | ||
124 | markstack(L, &st); /* mark stack objects */ | ||
125 | marklock(L, &st); /* mark locked objects */ | ||
126 | for (;;) { /* mark tables and closures */ | ||
127 | if (st.cmark) { | ||
128 | int i; | ||
129 | Closure *f = st.cmark; /* get first closure from list */ | ||
130 | st.cmark = f->mark; /* remove it from list */ | ||
131 | for (i=0; i<f->nupvalues; i++) /* mark its upvalues */ | ||
132 | markobject(&st, &f->upvalue[i]); | ||
133 | } | ||
134 | else if (st.tmark) { | ||
135 | int i; | ||
136 | Hash *h = st.tmark; /* get first table from list */ | ||
137 | st.tmark = h->mark; /* remove it from list */ | ||
138 | for (i=0; i<h->size; i++) { | ||
139 | Node *n = node(h, i); | ||
140 | if (ttype(key(n)) != TAG_NIL) { | ||
141 | if (ttype(val(n)) == TAG_NIL) | ||
142 | luaH_remove(h, key(n)); /* dead element; try to remove it */ | ||
143 | markobject(&st, &n->key); | ||
144 | markobject(&st, &n->val); | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | else break; /* nothing else to mark */ | ||
149 | } | ||
150 | } | ||
151 | |||
152 | |||
121 | static void collectproto (lua_State *L) { | 153 | static void collectproto (lua_State *L) { |
122 | Proto **p = &L->rootproto; | 154 | Proto **p = &L->rootproto; |
123 | Proto *next; | 155 | Proto *next; |
@@ -138,8 +170,8 @@ static void collectclosure (lua_State *L) { | |||
138 | Closure **p = &L->rootcl; | 170 | Closure **p = &L->rootcl; |
139 | Closure *next; | 171 | Closure *next; |
140 | while ((next = *p) != NULL) { | 172 | while ((next = *p) != NULL) { |
141 | if (next->marked) { | 173 | if (ismarked(next)) { |
142 | next->marked = 0; | 174 | next->mark = next; /* unmark */ |
143 | p = &next->next; | 175 | p = &next->next; |
144 | } | 176 | } |
145 | else { | 177 | else { |
@@ -154,8 +186,8 @@ static void collecttable (lua_State *L) { | |||
154 | Hash **p = &L->roottable; | 186 | Hash **p = &L->roottable; |
155 | Hash *next; | 187 | Hash *next; |
156 | while ((next = *p) != NULL) { | 188 | while ((next = *p) != NULL) { |
157 | if (next->marked) { | 189 | if (ismarked(next)) { |
158 | next->marked = 0; | 190 | next->mark = next; /* unmark */ |
159 | p = &next->next; | 191 | p = &next->next; |
160 | } | 192 | } |
161 | else { | 193 | else { |
@@ -256,14 +288,6 @@ static void callgcTMudata (lua_State *L) { | |||
256 | } | 288 | } |
257 | 289 | ||
258 | 290 | ||
259 | static void markall (lua_State *L) { | ||
260 | luaT_travtagmethods(L, markobject); /* mark tag methods */ | ||
261 | travstack(L); /* mark stack objects */ | ||
262 | tablemark(L, L->gt); /* mark global variables */ | ||
263 | travlock(L); /* mark locked objects */ | ||
264 | } | ||
265 | |||
266 | |||
267 | void luaC_collect (lua_State *L, int all) { | 291 | void luaC_collect (lua_State *L, int all) { |
268 | int oldah = L->allowhooks; | 292 | int oldah = L->allowhooks; |
269 | L->allowhooks = 0; /* stop debug hooks during GC */ | 293 | L->allowhooks = 0; /* stop debug hooks during GC */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.h,v 1.69 2000/06/28 20:20:36 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 1.70 2000/06/30 14:35:17 roberto Exp roberto $ |
3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -110,15 +110,15 @@ typedef struct TString { | |||
110 | ** Function Prototypes | 110 | ** Function Prototypes |
111 | */ | 111 | */ |
112 | typedef struct Proto { | 112 | typedef struct Proto { |
113 | struct Proto *next; | ||
114 | int marked; | ||
115 | struct TString **kstr; /* strings used by the function */ | ||
116 | int nkstr; /* size of `kstr' */ | ||
117 | Number *knum; /* Number numbers used by the function */ | 113 | Number *knum; /* Number numbers used by the function */ |
118 | int nknum; /* size of `knum' */ | 114 | int nknum; /* size of `knum' */ |
115 | struct TString **kstr; /* strings used by the function */ | ||
116 | int nkstr; /* size of `kstr' */ | ||
119 | struct Proto **kproto; /* functions defined inside the function */ | 117 | struct Proto **kproto; /* functions defined inside the function */ |
120 | int nkproto; /* size of `kproto' */ | 118 | int nkproto; /* size of `kproto' */ |
121 | Instruction *code; /* ends with opcode ENDCODE */ | 119 | Instruction *code; /* ends with opcode ENDCODE */ |
120 | struct Proto *next; | ||
121 | int marked; | ||
122 | int *lines; /* source line that generated each opcode */ | 122 | int *lines; /* source line that generated each opcode */ |
123 | int lineDefined; | 123 | int lineDefined; |
124 | TString *source; | 124 | TString *source; |
@@ -139,12 +139,12 @@ typedef struct LocVar { | |||
139 | ** Closures | 139 | ** Closures |
140 | */ | 140 | */ |
141 | typedef struct Closure { | 141 | typedef struct Closure { |
142 | struct Closure *next; | ||
143 | int marked; | ||
144 | union { | 142 | union { |
145 | lua_CFunction c; /* C functions */ | 143 | lua_CFunction c; /* C functions */ |
146 | struct Proto *l; /* Lua functions */ | 144 | struct Proto *l; /* Lua functions */ |
147 | } f; | 145 | } f; |
146 | struct Closure *next; | ||
147 | struct Closure *mark; /* marked closures (point to itself when not marked) */ | ||
148 | int nupvalues; | 148 | int nupvalues; |
149 | TObject upvalue[1]; | 149 | TObject upvalue[1]; |
150 | } Closure; | 150 | } Closure; |
@@ -157,15 +157,21 @@ typedef struct Node { | |||
157 | } Node; | 157 | } Node; |
158 | 158 | ||
159 | typedef struct Hash { | 159 | typedef struct Hash { |
160 | int htag; | ||
161 | Node *node; | 160 | Node *node; |
161 | int htag; | ||
162 | int size; | 162 | int size; |
163 | Node *firstfree; /* this position is free; all positions after it are full */ | 163 | Node *firstfree; /* this position is free; all positions after it are full */ |
164 | struct Hash *next; | 164 | struct Hash *next; |
165 | int marked; | 165 | struct Hash *mark; /* marked tables (point to itself when not marked) */ |
166 | } Hash; | 166 | } Hash; |
167 | 167 | ||
168 | 168 | ||
169 | /* unmarked tables and closures are represented by pointing `mark' to | ||
170 | ** themselves | ||
171 | */ | ||
172 | #define ismarked(x) ((x)->mark != (x)) | ||
173 | |||
174 | |||
169 | /* | 175 | /* |
170 | ** informations about a call (for debugging) | 176 | ** informations about a call (for debugging) |
171 | */ | 177 | */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lref.c,v 1.14 2000/06/12 13:52:05 roberto Exp roberto $ | 2 | ** $Id: lref.c,v 1.15 2000/06/30 14:35:17 roberto Exp roberto $ |
3 | ** reference mechanism | 3 | ** reference mechanism |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -81,15 +81,15 @@ void lua_endblock (lua_State *L) { | |||
81 | 81 | ||
82 | 82 | ||
83 | 83 | ||
84 | static int ismarked (const TObject *o) { | 84 | static int hasmark (const TObject *o) { |
85 | /* valid only for locked objects */ | 85 | /* valid only for locked objects */ |
86 | switch (o->ttype) { | 86 | switch (o->ttype) { |
87 | case TAG_STRING: case TAG_USERDATA: | 87 | case TAG_STRING: case TAG_USERDATA: |
88 | return tsvalue(o)->marked; | 88 | return tsvalue(o)->marked; |
89 | case TAG_TABLE: | 89 | case TAG_TABLE: |
90 | return hvalue(o)->marked; | 90 | return ismarked(hvalue(o)); |
91 | case TAG_LCLOSURE: case TAG_CCLOSURE: | 91 | case TAG_LCLOSURE: case TAG_CCLOSURE: |
92 | return clvalue(o)->marked; | 92 | return ismarked(clvalue(o)->mark); |
93 | default: /* number */ | 93 | default: /* number */ |
94 | return 1; | 94 | return 1; |
95 | } | 95 | } |
@@ -104,9 +104,9 @@ void luaR_invalidaterefs (lua_State *L) { | |||
104 | int i; | 104 | int i; |
105 | for (i=0; i<n; i++) { | 105 | for (i=0; i<n; i++) { |
106 | struct Ref *r = &L->refArray[i]; | 106 | struct Ref *r = &L->refArray[i]; |
107 | if (r->st == HOLD && !ismarked(&r->o)) | 107 | if (r->st == HOLD && !hasmark(&r->o)) |
108 | r->st = COLLECTED; | 108 | r->st = COLLECTED; |
109 | LUA_ASSERT((r->st == LOCK && ismarked(&r->o)) || | 109 | LUA_ASSERT((r->st == LOCK && hasmark(&r->o)) || |
110 | r->st == COLLECTED || | 110 | r->st == COLLECTED || |
111 | r->st == NONEXT || | 111 | r->st == NONEXT || |
112 | (r->st < n && VALIDLINK(L, L->refArray[r->st].st, n)), | 112 | (r->st < n && VALIDLINK(L, L->refArray[r->st].st, n)), |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltable.c,v 1.50 2000/06/30 14:35:17 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 1.51 2000/08/04 19:38:35 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 | */ |
@@ -127,14 +127,16 @@ int luaH_pos (lua_State *L, const Hash *t, const TObject *key) { | |||
127 | ** hash, change `key' for a number with the same hash. | 127 | ** hash, change `key' for a number with the same hash. |
128 | */ | 128 | */ |
129 | void luaH_remove (Hash *t, TObject *key) { | 129 | void luaH_remove (Hash *t, TObject *key) { |
130 | /* do not remove numbers */ | 130 | if (ttype(key) == TAG_NUMBER || |
131 | if (ttype(key) != TAG_NUMBER) { | 131 | (ttype(key) == TAG_STRING && tsvalue(key)->u.s.len <= 30)) |
132 | return; /* do not remove numbers nor small strings */ | ||
133 | else { | ||
132 | /* try to find a number `n' with the same hash as `key' */ | 134 | /* try to find a number `n' with the same hash as `key' */ |
133 | Node *mp = luaH_mainposition(t, key); | 135 | Node *mp = luaH_mainposition(t, key); |
134 | int n = mp - &t->node[0]; | 136 | int n = mp - &t->node[0]; |
135 | /* make sure `n' is not in `t' */ | 137 | /* make sure `n' is not in `t' */ |
136 | while (luaH_getnum(t, n) != &luaO_nilobject) { | 138 | while (luaH_getnum(t, n) != &luaO_nilobject) { |
137 | if (t->size >= MAX_INT-n) | 139 | if (n >= MAX_INT - t->size) |
138 | return; /* give up; (to avoid overflow) */ | 140 | return; /* give up; (to avoid overflow) */ |
139 | n += t->size; | 141 | n += t->size; |
140 | } | 142 | } |
@@ -165,7 +167,7 @@ Hash *luaH_new (lua_State *L, int size) { | |||
165 | t->htag = TagDefault; | 167 | t->htag = TagDefault; |
166 | t->next = L->roottable; | 168 | t->next = L->roottable; |
167 | L->roottable = t; | 169 | L->roottable = t; |
168 | t->marked = 0; | 170 | t->mark = t; |
169 | t->size = 0; | 171 | t->size = 0; |
170 | L->nblocks += gcsize(L, 0); | 172 | L->nblocks += gcsize(L, 0); |
171 | t->node = NULL; | 173 | t->node = NULL; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.c,v 1.43 2000/06/12 13:52:05 roberto Exp roberto $ | 2 | ** $Id: ltm.c,v 1.44 2000/08/04 19:38:35 roberto Exp roberto $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -147,16 +147,3 @@ void luaT_settagmethod (lua_State *L, int t, const char *event, TObject *func) { | |||
147 | *luaT_getim(L, t, e) = temp; | 147 | *luaT_getim(L, t, e) = temp; |
148 | } | 148 | } |
149 | 149 | ||
150 | |||
151 | const char *luaT_travtagmethods (lua_State *L, | ||
152 | int (*fn)(lua_State *, TObject *)) { /* ORDER IM */ | ||
153 | int e; | ||
154 | for (e=IM_GETTABLE; e<=IM_FUNCTION; e++) { | ||
155 | int t; | ||
156 | for (t=0; t<=L->last_tag; t++) | ||
157 | if (fn(L, luaT_getim(L, t,e))) | ||
158 | return luaT_eventname[e]; | ||
159 | } | ||
160 | return NULL; | ||
161 | } | ||
162 | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.h,v 1.12 2000/03/30 16:41:51 roberto Exp roberto $ | 2 | ** $Id: ltm.h,v 1.13 2000/05/30 18:54:49 roberto Exp roberto $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -52,7 +52,6 @@ void luaT_realtag (lua_State *L, int tag); | |||
52 | int luaT_effectivetag (lua_State *L, const TObject *o); | 52 | int luaT_effectivetag (lua_State *L, const TObject *o); |
53 | void luaT_settagmethod (lua_State *L, int t, const char *event, TObject *func); | 53 | void luaT_settagmethod (lua_State *L, int t, const char *event, TObject *func); |
54 | const TObject *luaT_gettagmethod (lua_State *L, int t, const char *event); | 54 | const TObject *luaT_gettagmethod (lua_State *L, int t, const char *event); |
55 | const char *luaT_travtagmethods (lua_State *L, int (*fn)(lua_State *, TObject *)); | ||
56 | int luaT_validevent (int t, int e); /* used by compatibility module */ | 55 | int luaT_validevent (int t, int e); /* used by compatibility module */ |
57 | 56 | ||
58 | 57 | ||