summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-08-07 17:21:34 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-08-07 17:21:34 -0300
commitd9e61e8ceafe8c3f6ad936979719ca7c446ce228 (patch)
tree0808ada3d7b7219022b9002503894c76c7253df6
parent397905ef8694ec716a51acebc993bb625340d388 (diff)
downloadlua-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.c37
-rw-r--r--lfunc.c4
-rw-r--r--lgc.c148
-rw-r--r--lobject.h24
-rw-r--r--lref.c12
-rw-r--r--ltable.c12
-rw-r--r--ltm.c15
-rw-r--r--ltm.h3
8 files changed, 143 insertions, 112 deletions
diff --git a/ldebug.c b/ldebug.c
index 00f8e94c..bfc3763f 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -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
175static int checkfunc (lua_State *L, TObject *o) { 175static 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
180static void lua_getobjname (lua_State *L, StkId f, lua_Debug *ar) { 187static 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
199static 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}
diff --git a/lfunc.c b/lfunc.c
index cabe717f..004b5d41 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -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;
diff --git a/lgc.c b/lgc.c
index 7bdc5790..d884d224 100644
--- a/lgc.c
+++ b/lgc.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
23typedef 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
25static int markobject (lua_State *L, TObject *o); 29
30static 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
33static void protomark (lua_State *L, Proto *f) { 38static 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
51static void closuremark (lua_State *L, Closure *f) { 56static 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
61static 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
78static 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
85static void travlock (lua_State *L) { 63static 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
72static 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
94static int markobject (lua_State *L, TObject *o) { 82static 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
118static 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
121static void collectproto (lua_State *L) { 153static 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
259static 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
267void luaC_collect (lua_State *L, int all) { 291void 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 */
diff --git a/lobject.h b/lobject.h
index 2185eac4..b432c84a 100644
--- a/lobject.h
+++ b/lobject.h
@@ -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*/
112typedef struct Proto { 112typedef 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*/
141typedef struct Closure { 141typedef 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
159typedef struct Hash { 159typedef 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*/
diff --git a/lref.c b/lref.c
index cf355d51..26889cfb 100644
--- a/lref.c
+++ b/lref.c
@@ -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
84static int ismarked (const TObject *o) { 84static 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)),
diff --git a/ltable.c b/ltable.c
index d91ed36c..fefd4043 100644
--- a/ltable.c
+++ b/ltable.c
@@ -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*/
129void luaH_remove (Hash *t, TObject *key) { 129void 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;
diff --git a/ltm.c b/ltm.c
index 27866c2c..a6f39155 100644
--- a/ltm.c
+++ b/ltm.c
@@ -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
151const 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
diff --git a/ltm.h b/ltm.h
index 48acd59f..2a4510a0 100644
--- a/ltm.h
+++ b/ltm.h
@@ -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);
52int luaT_effectivetag (lua_State *L, const TObject *o); 52int luaT_effectivetag (lua_State *L, const TObject *o);
53void luaT_settagmethod (lua_State *L, int t, const char *event, TObject *func); 53void luaT_settagmethod (lua_State *L, int t, const char *event, TObject *func);
54const TObject *luaT_gettagmethod (lua_State *L, int t, const char *event); 54const TObject *luaT_gettagmethod (lua_State *L, int t, const char *event);
55const char *luaT_travtagmethods (lua_State *L, int (*fn)(lua_State *, TObject *));
56int luaT_validevent (int t, int e); /* used by compatibility module */ 55int luaT_validevent (int t, int e); /* used by compatibility module */
57 56
58 57