summaryrefslogtreecommitdiff
path: root/ltests.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2004-02-16 16:09:52 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2004-02-16 16:09:52 -0300
commit2aaf7394ad17180565423ce360d5faffb60f4e4f (patch)
tree32caa2d7b0079b4bc9b0ac392d216c5094a6433d /ltests.c
parentb3ce4505296253e6da1fa780c23e7ed012efc88e (diff)
downloadlua-2aaf7394ad17180565423ce360d5faffb60f4e4f.tar.gz
lua-2aaf7394ad17180565423ce360d5faffb60f4e4f.tar.bz2
lua-2aaf7394ad17180565423ce360d5faffb60f4e4f.zip
more and better tools (assertions & inspectors) to check incremental GC
Diffstat (limited to 'ltests.c')
-rw-r--r--ltests.c184
1 files changed, 183 insertions, 1 deletions
diff --git a/ltests.c b/ltests.c
index 05093162..581b47ff 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 1.169 2003/11/19 12:21:57 roberto Exp roberto $ 2** $Id: ltests.c,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -143,6 +143,188 @@ void *debug_realloc (void *ud, void *block, size_t oldsize, size_t size) {
143 143
144/* 144/*
145** {====================================================== 145** {======================================================
146** Functions to check memory consistency
147** =======================================================
148*/
149
150static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
151 if (isdead(g,t)) return 0;
152 if (g->gcstate == GCSpropagate)
153 return !isblack(f) || !iswhite(t);
154 else if (g->gcstate == GCSfinalize)
155 return iswhite(f);
156 else
157 return 1;
158}
159
160
161static void printobj (global_State *g, GCObject *o) {
162int i = 0;
163GCObject *p;
164for (p = g->rootgc; p != o && p != NULL; p = p->gch.next) i++;
165if (p == NULL) i = -1;
166printf("%d:%s(%p)-%c",
167i, luaT_typenames[o->gch.tt], (void *)o,
168isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g');
169}
170
171
172static int testobjref (global_State *g, GCObject *f, GCObject *t) {
173 int r = testobjref1(g,f,t);
174if (!r) {
175printf("%d - ", g->gcstate);
176printobj(g, f);
177printf("\t-> ");
178printobj(g, t);
179printf("\n");
180}
181 return r;
182}
183
184#define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t)))
185
186#define checkvalref(g,f,t) lua_assert(!iscollectable(t) || \
187 ((ttype(t) == (t)->value.gc->gch.tt) && testobjref(g,f,gcvalue(t))))
188
189
190
191static void checktable (global_State *g, Table *h) {
192 int i;
193 int weakkey = 0;
194 int weakvalue = 0;
195 const TValue *mode;
196 GCObject *hgc = obj2gco(h);
197 if (h->metatable)
198 checkobjref(g, hgc, h->metatable);
199 lua_assert(h->lsizenode || h->node == g->dummynode);
200 mode = gfasttm(g, h->metatable, TM_MODE);
201 if (mode && ttisstring(mode)) { /* is there a weak mode? */
202 weakkey = (strchr(svalue(mode), 'k') != NULL);
203 weakvalue = (strchr(svalue(mode), 'v') != NULL);
204 }
205 i = h->sizearray;
206 while (i--)
207 checkvalref(g, hgc, &h->array[i]);
208 i = sizenode(h);
209 while (i--) {
210 Node *n = gnode(h, i);
211 if (!ttisnil(gval(n))) {
212 lua_assert(!ttisnil(gkey(n)));
213 checkvalref(g, hgc, gkey(n));
214 checkvalref(g, hgc, gval(n));
215 }
216 }
217}
218
219
220/*
221** All marks are conditional because a GC may happen while the
222** prototype is still being created
223*/
224static void checkproto (global_State *g, Proto *f) {
225 int i;
226 GCObject *fgc = obj2gco(f);
227 if (f->source) checkobjref(g, fgc, f->source);
228 for (i=0; i<f->sizek; i++) {
229 if (ttisstring(f->k+i))
230 checkobjref(g, fgc, rawtsvalue(f->k+i));
231 }
232 for (i=0; i<f->sizeupvalues; i++) {
233 if (f->upvalues[i])
234 checkobjref(g, fgc, f->upvalues[i]);
235 }
236 for (i=0; i<f->sizep; i++) {
237 if (f->p[i])
238 checkobjref(g, fgc, f->p[i]);
239 }
240 for (i=0; i<f->sizelocvars; i++) {
241 if (f->locvars[i].varname)
242 checkobjref(g, fgc, f->locvars[i].varname);
243 }
244}
245
246
247
248static void checkclosure (global_State *g, Closure *cl) {
249 GCObject *clgc = obj2gco(cl);
250 if (cl->c.isC) {
251 int i;
252 for (i=0; i<cl->c.nupvalues; i++)
253 checkvalref(g, clgc, &cl->c.upvalue[i]);
254 }
255 else {
256 int i;
257 lua_assert(cl->l.nupvalues == cl->l.p->nups);
258 checkobjref(g, clgc, hvalue(&cl->l.g));
259 checkobjref(g, clgc, cl->l.p);
260 for (i=0; i<cl->l.nupvalues; i++) {
261 lua_assert(cl->l.upvals[i]->tt == LUA_TUPVAL);
262 checkobjref(g, clgc, cl->l.upvals[i]);
263 }
264 }
265}
266
267
268static void checkstack (global_State *g, lua_State *L1) {
269 StkId o;
270 CallInfo *ci;
271 lua_assert(!isdead(g, obj2gco(L1)));
272 checkliveness(g, gt(L1));
273 for (ci = L1->base_ci; ci <= L1->ci; ci++)
274 lua_assert(ci->top <= L1->stack_last);
275 for (o = L1->stack; o < L1->top; o++)
276 checkliveness(g, o);
277}
278
279
280void luaC_checkall (lua_State *L) {
281 global_State *g = G(L);
282 GCObject *o;
283 checkstack(g, g->mainthread);
284 for (o = g->rootgc; o; o = o->gch.next) {
285 if (isdead(g, o))
286 lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
287 else {
288 switch (o->gch.tt) {
289 case LUA_TUPVAL: {
290 UpVal *uv = gco2uv(o);
291 lua_assert(uv->v == &uv->value); /* must be closed */
292 checkvalref(g, o, uv->v);
293 break;
294 }
295 case LUA_TUSERDATA: {
296 Table *mt = gco2u(o)->metatable;
297 if (mt) checkobjref(g, o, mt);
298 break;
299 }
300 case LUA_TTABLE: {
301 checktable(g, gco2h(o));
302 break;
303 }
304 case LUA_TTHREAD: {
305 checkstack(g, gco2th(o));
306 break;
307 }
308 case LUA_TFUNCTION: {
309 checkclosure(g, gco2cl(o));
310 break;
311 }
312 case LUA_TPROTO: {
313 checkproto(g, gco2p(o));
314 break;
315 }
316 default: lua_assert(0);
317 }
318 }
319 }
320}
321
322/* }====================================================== */
323
324
325
326/*
327** {======================================================
146** Disassembler 328** Disassembler
147** ======================================================= 329** =======================================================
148*/ 330*/