simplification in the handling of finalizers: no more 'tmudata' list +
no more GCSsweeptmu collector's state
This commit is contained in:
106
lgc.c
106
lgc.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lgc.c,v 2.45 2008/06/23 16:51:28 roberto Exp roberto $
|
** $Id: lgc.c,v 2.46 2008/06/23 22:07:44 roberto Exp roberto $
|
||||||
** Garbage Collector
|
** Garbage Collector
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -79,7 +79,7 @@ static void removeentry (Node *n) {
|
|||||||
** The next function tells whether a key or value can be cleared from
|
** The next function tells whether a key or value can be cleared from
|
||||||
** a weak table. Non-collectable objects are never removed from weak
|
** a weak table. Non-collectable objects are never removed from weak
|
||||||
** tables. Strings behave as `values', so are never removed too. for
|
** tables. Strings behave as `values', so are never removed too. for
|
||||||
** other objects: if really collected, cannot keep them; for userdata
|
** other objects: if really collected, cannot keep them; for objects
|
||||||
** being finalized, keep them in keys, but not in values
|
** being finalized, keep them in keys, but not in values
|
||||||
*/
|
*/
|
||||||
static int iscleared (const TValue *o, int iskey) {
|
static int iscleared (const TValue *o, int iskey) {
|
||||||
@@ -205,14 +205,11 @@ static void markmt (global_State *g) {
|
|||||||
|
|
||||||
|
|
||||||
static void markbeingfnz (global_State *g) {
|
static void markbeingfnz (global_State *g) {
|
||||||
GCObject *u = g->tobefnz;
|
GCObject *o;
|
||||||
if (u) {
|
for (o = g->tobefnz; o != NULL; o = gch(o)->next) {
|
||||||
do {
|
lua_assert(testbit(gch(o)->marked, SEPARATED));
|
||||||
u = gch(u)->next;
|
makewhite(g, o);
|
||||||
lua_assert(testbit(gch(u)->marked, SEPARATED));
|
reallymarkobject(g, o);
|
||||||
makewhite(g, u);
|
|
||||||
reallymarkobject(g, u);
|
|
||||||
} while (u != g->tobefnz);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +225,7 @@ static void markroot (lua_State *L) {
|
|||||||
markvalue(g, gt(g->mainthread));
|
markvalue(g, gt(g->mainthread));
|
||||||
markvalue(g, registry(L));
|
markvalue(g, registry(L));
|
||||||
markmt(g);
|
markmt(g);
|
||||||
markbeingfnz(g); /* mark any finalizing userdata left from previous cycle */
|
markbeingfnz(g); /* mark any finalizing object left from previous cycle */
|
||||||
g->gcstate = GCSpropagate;
|
g->gcstate = GCSpropagate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,17 +570,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* sweep list where all objects are alive (dead udata were removed
|
|
||||||
when separated from this list) */
|
|
||||||
static GCObject **unmarklist (global_State *g, GCObject **p, lu_mem count) {
|
|
||||||
for (; *p != NULL && count-- > 0; p = &gch(*p)->next) {
|
|
||||||
lua_assert(ttisuserdata(gch(*p)) && !isdead(g, *p));
|
|
||||||
makewhite(g, *p);
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* }====================================================== */
|
/* }====================================================== */
|
||||||
|
|
||||||
|
|
||||||
@@ -602,18 +588,14 @@ static void checkSizes (lua_State *L) {
|
|||||||
|
|
||||||
|
|
||||||
static Udata *udata2finalize (global_State *g) {
|
static Udata *udata2finalize (global_State *g) {
|
||||||
GCObject *o = gch(g->tobefnz)->next; /* get first element */
|
GCObject *o = g->tobefnz; /* get first element */
|
||||||
Udata *udata = rawgco2u(o);
|
g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */
|
||||||
/* remove udata from `tobefnz' */
|
gch(o)->next = g->rootgc; /* return it to `root' list */
|
||||||
if (o == g->tobefnz) /* last element? */
|
g->rootgc = o;
|
||||||
g->tobefnz = NULL;
|
lua_assert(isfinalized(gch(o)));
|
||||||
else
|
resetbit(gch(o)->marked, SEPARATED); /* mark it as such */
|
||||||
gch(g->tobefnz)->next = udata->uv.next;
|
|
||||||
udata->uv.next = g->mainthread->next; /* return it to `root' list */
|
|
||||||
g->mainthread->next = o;
|
|
||||||
resetbit(udata->uv.marked, SEPARATED); /* mark it as such */
|
|
||||||
makewhite(g, o);
|
makewhite(g, o);
|
||||||
return udata;
|
return rawgco2u(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -639,28 +621,21 @@ static void GCTM (lua_State *L) {
|
|||||||
/*
|
/*
|
||||||
** Call all GC tag methods
|
** Call all GC tag methods
|
||||||
*/
|
*/
|
||||||
void luaC_callGCTM (lua_State *L) {
|
void luaC_callAllGCTM (lua_State *L) {
|
||||||
global_State *g = G(L);
|
while (G(L)->tobefnz) GCTM(L);
|
||||||
GCObject *last = g->tobefnz;
|
|
||||||
GCObject *curr;
|
|
||||||
if (last == NULL) return; /* empty list? */
|
|
||||||
do {
|
|
||||||
curr = gch(g->tobefnz)->next; /* element to be collected */
|
|
||||||
GCTM(L);
|
|
||||||
} while (curr != last); /* go only until original last */
|
|
||||||
/* do not finalize new udata created during previous finalizations */
|
|
||||||
while (g->tobefnz)
|
|
||||||
udata2finalize(g); /* simply remove them from list */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* move 'dead' udata that need finalization to list 'tobefnz' */
|
/* move 'dead' udata that need finalization to list 'tobefnz' */
|
||||||
size_t luaC_separateudata (lua_State *L, int all) {
|
size_t luaC_separateudata (lua_State *L, int all) {
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
size_t deadmem = 0;
|
size_t deadmem = 0; /* total size of all objects to be finalized */
|
||||||
GCObject **p = &g->tmudata;
|
GCObject **p = &g->mainthread->next;
|
||||||
GCObject *curr;
|
GCObject *curr;
|
||||||
while ((curr = *p) != NULL) {
|
GCObject **lastnext = &g->tobefnz;
|
||||||
|
/* find last 'next' field in 'tobefnz' list (to insert elements in its end) */
|
||||||
|
while (*lastnext != NULL) lastnext = &gch(*lastnext)->next;
|
||||||
|
while ((curr = *p) != NULL) { /* traverse all finalizable objects */
|
||||||
lua_assert(ttisuserdata(gch(curr)) && !isfinalized(gco2u(curr)));
|
lua_assert(ttisuserdata(gch(curr)) && !isfinalized(gco2u(curr)));
|
||||||
lua_assert(testbit(gch(curr)->marked, SEPARATED));
|
lua_assert(testbit(gch(curr)->marked, SEPARATED));
|
||||||
if (!(all || iswhite(curr))) /* not being collected? */
|
if (!(all || iswhite(curr))) /* not being collected? */
|
||||||
@@ -668,15 +643,11 @@ size_t luaC_separateudata (lua_State *L, int all) {
|
|||||||
else {
|
else {
|
||||||
l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */
|
l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */
|
||||||
deadmem += sizeudata(gco2u(curr));
|
deadmem += sizeudata(gco2u(curr));
|
||||||
*p = gch(curr)->next; /* remove 'curr' from 'tmudata' list */
|
*p = gch(curr)->next; /* remove 'curr' from 'rootgc' list */
|
||||||
/* link 'curr' at the end of 'tobefnz' list */
|
/* link 'curr' at the end of 'tobefnz' list */
|
||||||
if (g->tobefnz == NULL) /* list is empty? */
|
gch(curr)->next = *lastnext;
|
||||||
g->tobefnz = gch(curr)->next = curr; /* creates a circular list */
|
*lastnext = curr;
|
||||||
else {
|
lastnext = &gch(curr)->next;
|
||||||
gch(curr)->next = gch(g->tobefnz)->next;
|
|
||||||
gch(g->tobefnz)->next = curr;
|
|
||||||
g->tobefnz = curr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return deadmem;
|
return deadmem;
|
||||||
@@ -689,13 +660,13 @@ void luaC_checkfinalizer (lua_State *L, Udata *u) {
|
|||||||
isfinalized(&u->uv) || /* ... or is finalized... */
|
isfinalized(&u->uv) || /* ... or is finalized... */
|
||||||
gfasttm(g, u->uv.metatable, TM_GC) == NULL) /* or has no finalization? */
|
gfasttm(g, u->uv.metatable, TM_GC) == NULL) /* or has no finalization? */
|
||||||
return; /* nothing to be done */
|
return; /* nothing to be done */
|
||||||
else { /* move 'u' from root list to 'tmudata' list */
|
else { /* move 'u' to 2nd part of root list */
|
||||||
GCObject **p;
|
GCObject **p;
|
||||||
for (p = &g->rootgc; *p != obj2gco(u); p = &gch(*p)->next)
|
for (p = &g->rootgc; *p != obj2gco(u); p = &gch(*p)->next)
|
||||||
lua_assert(*p != NULL); /* 'u' must be in this list */
|
lua_assert(*p != obj2gco(g->mainthread)); /* 'u' must be in this list */
|
||||||
*p = u->uv.next; /* remove 'u' from root list */
|
*p = u->uv.next; /* remove 'u' from root list */
|
||||||
u->uv.next = g->tmudata; /* link it in 'tmudata' list */
|
u->uv.next = g->mainthread->next; /* re-link it in list */
|
||||||
g->tmudata = obj2gco(u);
|
g->mainthread->next = obj2gco(u);
|
||||||
l_setbit(u->uv.marked, SEPARATED); /* mark it as such */
|
l_setbit(u->uv.marked, SEPARATED); /* mark it as such */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -716,9 +687,8 @@ void luaC_freeall (lua_State *L) {
|
|||||||
/* mask to collect all elements */
|
/* mask to collect all elements */
|
||||||
g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT);
|
g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT);
|
||||||
sweepwholelist(L, &g->rootgc);
|
sweepwholelist(L, &g->rootgc);
|
||||||
lua_assert(g->rootgc == obj2gco(L));
|
lua_assert(g->rootgc == obj2gco(g->mainthread));
|
||||||
sweepwholelist(L, &g->tmudata);
|
lua_assert(g->mainthread->next == NULL);
|
||||||
lua_assert(g->tmudata == NULL);
|
|
||||||
for (i = 0; i < g->strt.size; i++) /* free all string lists */
|
for (i = 0; i < g->strt.size; i++) /* free all string lists */
|
||||||
sweepwholelist(L, &g->strt.hash[i]);
|
sweepwholelist(L, &g->strt.hash[i]);
|
||||||
lua_assert(g->strt.nuse == 0);
|
lua_assert(g->strt.nuse == 0);
|
||||||
@@ -781,18 +751,10 @@ static l_mem singlestep (lua_State *L) {
|
|||||||
case GCSsweepstring: {
|
case GCSsweepstring: {
|
||||||
correctestimate(g, sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]));
|
correctestimate(g, sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]));
|
||||||
if (g->sweepstrgc >= g->strt.size) { /* nothing more to sweep? */
|
if (g->sweepstrgc >= g->strt.size) { /* nothing more to sweep? */
|
||||||
g->sweepgc = &g->tmudata;
|
|
||||||
g->gcstate = GCSsweeptmu; /* end sweep-string phase */
|
|
||||||
}
|
|
||||||
return GCSWEEPCOST;
|
|
||||||
}
|
|
||||||
case GCSsweeptmu: {
|
|
||||||
g->sweepgc = unmarklist(g, g->sweepgc, GCSWEEPMAX);
|
|
||||||
if (*g->sweepgc == NULL) { /* nothing more to sweep? */
|
|
||||||
g->sweepgc = &g->rootgc;
|
g->sweepgc = &g->rootgc;
|
||||||
g->gcstate = GCSsweep; /* sweep all other objects */
|
g->gcstate = GCSsweep; /* sweep all other objects */
|
||||||
}
|
}
|
||||||
return GCSWEEPMAX*GCSWEEPCOST;
|
return GCSWEEPCOST;
|
||||||
}
|
}
|
||||||
case GCSsweep: {
|
case GCSsweep: {
|
||||||
correctestimate(g, g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX));
|
correctestimate(g, g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX));
|
||||||
|
|||||||
30
lgc.h
30
lgc.h
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lgc.h,v 2.17 2007/10/29 16:51:20 roberto Exp roberto $
|
** $Id: lgc.h,v 2.18 2008/02/19 18:55:09 roberto Exp roberto $
|
||||||
** Garbage Collector
|
** Garbage Collector
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -17,26 +17,24 @@
|
|||||||
#define GCSpause 0
|
#define GCSpause 0
|
||||||
#define GCSpropagate 1
|
#define GCSpropagate 1
|
||||||
#define GCSsweepstring 2
|
#define GCSsweepstring 2
|
||||||
#define GCSsweeptmu 3
|
#define GCSsweep 3
|
||||||
#define GCSsweep 4
|
#define GCSfinalize 4
|
||||||
#define GCSfinalize 5
|
|
||||||
|
|
||||||
|
|
||||||
#define issweep(g) \
|
#define issweep(g) (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep)
|
||||||
(GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** some userful bit tricks
|
** some userful bit tricks
|
||||||
*/
|
*/
|
||||||
#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m)))
|
#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m)))
|
||||||
#define setbits(x,m) ((x) |= (m))
|
#define setbits(x,m) ((x) |= (m))
|
||||||
#define testbits(x,m) ((x) & (m))
|
#define testbits(x,m) ((x) & (m))
|
||||||
#define bitmask(b) (1<<(b))
|
#define bitmask(b) (1<<(b))
|
||||||
#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2))
|
#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2))
|
||||||
#define l_setbit(x,b) setbits(x, bitmask(b))
|
#define l_setbit(x,b) setbits(x, bitmask(b))
|
||||||
#define resetbit(x,b) resetbits(x, bitmask(b))
|
#define resetbit(x,b) resetbits(x, bitmask(b))
|
||||||
#define testbit(x,b) testbits(x, bitmask(b))
|
#define testbit(x,b) testbits(x, bitmask(b))
|
||||||
#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2)))
|
#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2)))
|
||||||
#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2)))
|
#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2)))
|
||||||
|
|
||||||
@@ -48,7 +46,7 @@
|
|||||||
** bit 1 - object is white (type 1)
|
** bit 1 - object is white (type 1)
|
||||||
** bit 2 - object is black
|
** bit 2 - object is black
|
||||||
** bit 3 - for userdata: has been finalized
|
** bit 3 - for userdata: has been finalized
|
||||||
** bit 4 - for userdata: it's not in rootgc list (it's in tmudata or tobefnz)
|
** bit 4 - for userdata: it's in 2nd part of rootgc list or in tobefnz
|
||||||
** bit 5 - object is fixed (should not be collected)
|
** bit 5 - object is fixed (should not be collected)
|
||||||
** bit 6 - object is "super" fixed (only the main thread)
|
** bit 6 - object is "super" fixed (only the main thread)
|
||||||
*/
|
*/
|
||||||
@@ -99,7 +97,7 @@
|
|||||||
{ if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); }
|
{ if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); }
|
||||||
|
|
||||||
LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all);
|
LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all);
|
||||||
LUAI_FUNC void luaC_callGCTM (lua_State *L);
|
LUAI_FUNC void luaC_callAllGCTM (lua_State *L);
|
||||||
LUAI_FUNC void luaC_freeall (lua_State *L);
|
LUAI_FUNC void luaC_freeall (lua_State *L);
|
||||||
LUAI_FUNC void luaC_step (lua_State *L);
|
LUAI_FUNC void luaC_step (lua_State *L);
|
||||||
LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
|
LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency);
|
||||||
|
|||||||
8
lstate.c
8
lstate.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lstate.c,v 2.43 2008/02/11 15:45:30 roberto Exp roberto $
|
** $Id: lstate.c,v 2.44 2008/02/19 18:55:09 roberto Exp roberto $
|
||||||
** Global State
|
** Global State
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -181,7 +181,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
|
|||||||
g->gray = NULL;
|
g->gray = NULL;
|
||||||
g->grayagain = NULL;
|
g->grayagain = NULL;
|
||||||
g->weak = g->ephemeron = g->allweak = NULL;
|
g->weak = g->ephemeron = g->allweak = NULL;
|
||||||
g->tmudata = g->tobefnz = NULL;
|
g->tobefnz = NULL;
|
||||||
g->totalbytes = sizeof(LG);
|
g->totalbytes = sizeof(LG);
|
||||||
g->gcpause = LUAI_GCPAUSE;
|
g->gcpause = LUAI_GCPAUSE;
|
||||||
g->gcstepmul = LUAI_GCMUL;
|
g->gcstepmul = LUAI_GCMUL;
|
||||||
@@ -200,7 +200,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
|
|||||||
|
|
||||||
static void callallgcTM (lua_State *L, void *ud) {
|
static void callallgcTM (lua_State *L, void *ud) {
|
||||||
UNUSED(ud);
|
UNUSED(ud);
|
||||||
luaC_callGCTM(L); /* call GC metamethods for all udata */
|
luaC_callAllGCTM(L); /* call GC metamethods for all udata */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ LUA_API void lua_close (lua_State *L) {
|
|||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
luaF_close(L, L->stack); /* close all upvalues for this thread */
|
luaF_close(L, L->stack); /* close all upvalues for this thread */
|
||||||
luaC_separateudata(L, 1); /* separate all udata with GC metamethods */
|
luaC_separateudata(L, 1); /* separate all udata with GC metamethods */
|
||||||
lua_assert(G(L)->tmudata == NULL);
|
lua_assert(L->next == NULL);
|
||||||
L->errfunc = 0; /* no error function during GC metamethods */
|
L->errfunc = 0; /* no error function during GC metamethods */
|
||||||
do { /* repeat until no more errors */
|
do { /* repeat until no more errors */
|
||||||
L->ci = L->base_ci;
|
L->ci = L->base_ci;
|
||||||
|
|||||||
31
lstate.h
31
lstate.h
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lstate.h,v 2.32 2008/02/19 18:55:09 roberto Exp roberto $
|
** $Id: lstate.h,v 2.33 2008/06/23 16:51:08 roberto Exp roberto $
|
||||||
** Global State
|
** Global State
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -14,6 +14,32 @@
|
|||||||
#include "lzio.h"
|
#include "lzio.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
** Some notes about garbage-collected objects: All objects in Lua must
|
||||||
|
** be kept somehow accessible until being freed.
|
||||||
|
**
|
||||||
|
** Lua keeps most objects linked in list g->rootgc. The link uses field
|
||||||
|
** 'next' of the CommonHeader.
|
||||||
|
**
|
||||||
|
** Strings are kept in several lists headed by the array g->strt.hash.
|
||||||
|
**
|
||||||
|
** Open upvalues are not subject to independent garbage collection. They
|
||||||
|
** are collected together with their respective threads. Lua keeps a
|
||||||
|
** double-linked list with all open upvalues (g->uvhead) so that it can
|
||||||
|
** mark objects referred by them. (They are always gray, so they must
|
||||||
|
** be remarked in the atomic step. Usually their contents would be marked
|
||||||
|
** when traversing the respective threads, but the thread may already be
|
||||||
|
** dead, while the upvalue is still accessible through closures.)
|
||||||
|
**
|
||||||
|
** Userdata with finalizers are kept in the list g->rootgc, but after
|
||||||
|
** the mainthread, which should be otherwise the last element in the
|
||||||
|
** list, as it was the first one inserted there.
|
||||||
|
**
|
||||||
|
** The list g->tobefnz links all userdata being finalized.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
struct lua_longjmp; /* defined in ldo.c */
|
struct lua_longjmp; /* defined in ldo.c */
|
||||||
|
|
||||||
@@ -86,8 +112,7 @@ typedef struct global_State {
|
|||||||
GCObject *weak; /* list of tables with weak values */
|
GCObject *weak; /* list of tables with weak values */
|
||||||
GCObject *ephemeron; /* list of ephemeron tables (weak keys) */
|
GCObject *ephemeron; /* list of ephemeron tables (weak keys) */
|
||||||
GCObject *allweak; /* list of all-weak tables */
|
GCObject *allweak; /* list of all-weak tables */
|
||||||
GCObject *tmudata; /* list of userdata with finalizers */
|
GCObject *tobefnz; /* list of userdata to be GC */
|
||||||
GCObject *tobefnz; /* last element of list of userdata to be GC */
|
|
||||||
Mbuffer buff; /* temporary buffer for string concatentation */
|
Mbuffer buff; /* temporary buffer for string concatentation */
|
||||||
lu_mem GCthreshold;
|
lu_mem GCthreshold;
|
||||||
lu_mem totalbytes; /* number of bytes currently allocated */
|
lu_mem totalbytes; /* number of bytes currently allocated */
|
||||||
|
|||||||
14
ltests.c
14
ltests.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: ltests.c,v 2.51 2008/06/13 17:07:10 roberto Exp roberto $
|
** $Id: ltests.c,v 2.52 2008/06/23 16:50:34 roberto Exp roberto $
|
||||||
** Internal Module for Debugging of the Lua Implementation
|
** Internal Module for Debugging of the Lua Implementation
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -365,10 +365,15 @@ int lua_checkmemory (lua_State *L) {
|
|||||||
GCObject *o;
|
GCObject *o;
|
||||||
UpVal *uv;
|
UpVal *uv;
|
||||||
checkstack(g, g->mainthread);
|
checkstack(g, g->mainthread);
|
||||||
for (o = g->rootgc; o != NULL; o = gch(o)->next)
|
for (o = g->rootgc; o != obj2gco(g->mainthread); o = gch(o)->next) {
|
||||||
|
lua_assert(!testbits(o->gch.marked, bit2mask(SEPARATED, SFIXEDBIT)));
|
||||||
checkobject(g, o);
|
checkobject(g, o);
|
||||||
for (o = g->tmudata; o != NULL; o = gch(o)->next) {
|
}
|
||||||
lua_assert(!isdead(g, o));
|
lua_assert(testbit(o->gch.marked, SFIXEDBIT));
|
||||||
|
for (o = gch(o)->next; o != NULL; o = gch(o)->next) {
|
||||||
|
lua_assert(gch(o)->tt == LUA_TUSERDATA &&
|
||||||
|
!isdead(g, o) &&
|
||||||
|
testbit(o->gch.marked, SEPARATED));
|
||||||
checkobject(g, o);
|
checkobject(g, o);
|
||||||
}
|
}
|
||||||
for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
|
for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
|
||||||
@@ -535,7 +540,6 @@ static int gcstate (lua_State *L) {
|
|||||||
switch(G(L)->gcstate) {
|
switch(G(L)->gcstate) {
|
||||||
case GCSpropagate: lua_pushstring(L, "propagate"); break;
|
case GCSpropagate: lua_pushstring(L, "propagate"); break;
|
||||||
case GCSsweepstring: lua_pushstring(L, "sweep strings"); break;
|
case GCSsweepstring: lua_pushstring(L, "sweep strings"); break;
|
||||||
case GCSsweeptmu: lua_pushstring(L, "sweep udata with __gc"); break;
|
|
||||||
case GCSsweep: lua_pushstring(L, "sweep"); break;
|
case GCSsweep: lua_pushstring(L, "sweep"); break;
|
||||||
case GCSfinalize: lua_pushstring(L, "finalize"); break;
|
case GCSfinalize: lua_pushstring(L, "finalize"); break;
|
||||||
default: lua_assert(0);
|
default: lua_assert(0);
|
||||||
|
|||||||
Reference in New Issue
Block a user