mirror of
https://github.com/lua/lua
synced 2025-01-23 17:42:05 +03:00
avoid traversing extra elements when cleaning weak tables
This commit is contained in:
parent
81e142fc14
commit
ac27b7a842
73
lgc.c
73
lgc.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** $Id: lgc.c,v 1.154 2002/10/25 20:05:28 roberto Exp roberto $
|
** $Id: lgc.c,v 1.155 2002/11/07 15:37:10 roberto Exp roberto $
|
||||||
** Garbage Collector
|
** Garbage Collector
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@ -22,7 +22,9 @@
|
|||||||
|
|
||||||
typedef struct GCState {
|
typedef struct GCState {
|
||||||
Table *tmark; /* list of marked tables to be visited */
|
Table *tmark; /* list of marked tables to be visited */
|
||||||
Table *toclear; /* list of visited weak tables (to be cleared after GC) */
|
Table *wk; /* list of visited key-weak tables (to be cleared after GC) */
|
||||||
|
Table *wv; /* list of visited value-weak tables */
|
||||||
|
Table *wkv; /* list of visited key-value weak tables */
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
} GCState;
|
} GCState;
|
||||||
|
|
||||||
@ -198,10 +200,14 @@ static void traversetable (GCState *st, Table *h) {
|
|||||||
marktable(st, h->metatable);
|
marktable(st, h->metatable);
|
||||||
lua_assert(h->lsizenode || h->node == G(st->L)->dummynode);
|
lua_assert(h->lsizenode || h->node == G(st->L)->dummynode);
|
||||||
if (h->mode & (WEAKKEY | WEAKVALUE)) { /* weak table? */
|
if (h->mode & (WEAKKEY | WEAKVALUE)) { /* weak table? */
|
||||||
|
Table **weaklist;
|
||||||
weakkey = h->mode & WEAKKEY;
|
weakkey = h->mode & WEAKKEY;
|
||||||
weakvalue = h->mode & WEAKVALUE;
|
weakvalue = h->mode & WEAKVALUE;
|
||||||
h->gclist = st->toclear; /* must be cleared after GC, ... */
|
weaklist = (weakkey && weakvalue) ? &st->wkv :
|
||||||
st->toclear = h; /* ... so put in the appropriate list */
|
(weakkey) ? &st->wk :
|
||||||
|
&st->wv;
|
||||||
|
h->gclist = *weaklist; /* must be cleared after GC, ... */
|
||||||
|
*weaklist = h; /* ... so put in the appropriate list */
|
||||||
}
|
}
|
||||||
if (!weakvalue) {
|
if (!weakvalue) {
|
||||||
i = sizearray(h);
|
i = sizearray(h);
|
||||||
@ -241,14 +247,12 @@ static int valismarked (const TObject *o) {
|
|||||||
*/
|
*/
|
||||||
static void cleartablekeys (Table *h) {
|
static void cleartablekeys (Table *h) {
|
||||||
for (; h; h = h->gclist) {
|
for (; h; h = h->gclist) {
|
||||||
lua_assert(h->mode & (WEAKKEY | WEAKVALUE));
|
int i = sizenode(h);
|
||||||
if ((h->mode & WEAKKEY)) { /* table may have collected keys? */
|
lua_assert(h->mode & WEAKKEY);
|
||||||
int i = sizenode(h);
|
while (i--) {
|
||||||
while (i--) {
|
Node *n = node(h, i);
|
||||||
Node *n = node(h, i);
|
if (!valismarked(key(n))) /* key was collected? */
|
||||||
if (!valismarked(key(n))) /* key was collected? */
|
removekey(n); /* remove entry from table */
|
||||||
removekey(n); /* remove entry from table */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -259,19 +263,18 @@ static void cleartablekeys (Table *h) {
|
|||||||
*/
|
*/
|
||||||
static void cleartablevalues (Table *h) {
|
static void cleartablevalues (Table *h) {
|
||||||
for (; h; h = h->gclist) {
|
for (; h; h = h->gclist) {
|
||||||
if ((h->mode & WEAKVALUE)) { /* table may have collected values? */
|
int i = sizearray(h);
|
||||||
int i = sizearray(h);
|
lua_assert(h->mode & WEAKVALUE);
|
||||||
while (i--) {
|
while (i--) {
|
||||||
TObject *o = &h->array[i];
|
TObject *o = &h->array[i];
|
||||||
if (!valismarked(o)) /* value was collected? */
|
if (!valismarked(o)) /* value was collected? */
|
||||||
setnilvalue(o); /* remove value */
|
setnilvalue(o); /* remove value */
|
||||||
}
|
}
|
||||||
i = sizenode(h);
|
i = sizenode(h);
|
||||||
while (i--) {
|
while (i--) {
|
||||||
Node *n = node(h, i);
|
Node *n = node(h, i);
|
||||||
if (!valismarked(val(n))) /* value was collected? */
|
if (!valismarked(val(n))) /* value was collected? */
|
||||||
removekey(n); /* remove entry from table */
|
removekey(n); /* remove entry from table */
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -398,22 +401,26 @@ static void markroot (GCState *st) {
|
|||||||
|
|
||||||
static void mark (lua_State *L) {
|
static void mark (lua_State *L) {
|
||||||
GCState st;
|
GCState st;
|
||||||
Table *toclear;
|
Table *wkv;
|
||||||
st.L = L;
|
st.L = L;
|
||||||
st.tmark = NULL;
|
st.tmark = NULL;
|
||||||
st.toclear = NULL;
|
st.wkv = st.wk = st.wv = NULL;
|
||||||
markroot(&st);
|
markroot(&st);
|
||||||
propagatemarks(&st); /* mark all reachable objects */
|
propagatemarks(&st); /* mark all reachable objects */
|
||||||
toclear = st.toclear; /* weak tables; to be cleared */
|
cleartablevalues(st.wkv);
|
||||||
st.toclear = NULL;
|
cleartablevalues(st.wv);
|
||||||
cleartablevalues(toclear);
|
wkv = st.wkv; /* keys must be cleared after preserving udata */
|
||||||
|
st.wkv = NULL;
|
||||||
|
st.wv = NULL;
|
||||||
separateudata(L); /* separate userdata to be preserved */
|
separateudata(L); /* separate userdata to be preserved */
|
||||||
marktmu(&st); /* mark `preserved' userdata */
|
marktmu(&st); /* mark `preserved' userdata */
|
||||||
propagatemarks(&st); /* remark, to propagate `preserveness' */
|
propagatemarks(&st); /* remark, to propagate `preserveness' */
|
||||||
cleartablekeys(toclear);
|
cleartablekeys(wkv);
|
||||||
/* `propagatemarks' may reborne some weak tables; clear them too */
|
/* `propagatemarks' may reborne some weak tables; clear them too */
|
||||||
cleartablekeys(st.toclear);
|
cleartablekeys(st.wk);
|
||||||
cleartablevalues(st.toclear);
|
cleartablevalues(st.wv);
|
||||||
|
cleartablekeys(st.wkv);
|
||||||
|
cleartablevalues(st.wkv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user