new interface for weak modes

This commit is contained in:
Roberto Ierusalimschy 2002-01-09 19:50:35 -02:00
parent facfec0687
commit b3bb0f132b
6 changed files with 33 additions and 44 deletions

24
lapi.c
View File

@ -695,28 +695,7 @@ LUA_API void lua_newuserdatabox (lua_State *L, void *p) {
} }
LUA_API int lua_getweakmode (lua_State *L, int index) { LUA_API int lua_pushupvalues (lua_State *L) {
StkId t;
int mode;
lua_lock(L);
t = luaA_index(L, index);
api_check(L, ttype(t) == LUA_TTABLE);
mode = hvalue(t)->weakmode;
lua_unlock(L);
return mode;
}
LUA_API void lua_setweakmode (lua_State *L, int mode) {
lua_lock(L);
api_check(L, ttype(L->top-1) == LUA_TTABLE);
hvalue(L->top-1)->weakmode = cast(lu_byte, mode);
lua_unlock(L);
}
LUA_API void lua_pushupvalues (lua_State *L) {
TObject *func; TObject *func;
int n, i; int n, i;
lua_lock(L); lua_lock(L);
@ -730,6 +709,7 @@ LUA_API void lua_pushupvalues (lua_State *L) {
L->top++; L->top++;
} }
lua_unlock(L); lua_unlock(L);
return n;
} }

46
lgc.c
View File

@ -4,6 +4,8 @@
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
#include <string.h>
#include "lua.h" #include "lua.h"
#include "ldebug.h" #include "ldebug.h"
@ -22,6 +24,7 @@
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 *toclear; /* list of visited weak tables (to be cleared after GC) */
lua_State *L;
} GCState; } GCState;
@ -119,8 +122,8 @@ static void markobject (GCState *st, TObject *o) {
} }
static void markstacks (lua_State *L, GCState *st) { static void markstacks (GCState *st) {
lua_State *L1 = L; lua_State *L1 = st->L;
do { /* for each thread */ do { /* for each thread */
StkId o, lim; StkId o, lim;
for (o=L1->stack; o<L1->top; o++) for (o=L1->stack; o<L1->top; o++)
@ -130,15 +133,15 @@ static void markstacks (lua_State *L, GCState *st) {
for (; o<=lim; o++) setnilvalue(o); for (; o<=lim; o++) setnilvalue(o);
lua_assert(L1->previous->next == L1 && L1->next->previous == L1); lua_assert(L1->previous->next == L1 && L1->next->previous == L1);
L1 = L1->next; L1 = L1->next;
} while (L1 != L); } while (L1 != st->L);
} }
static void markudet (lua_State *L, GCState *st) { static void markudet (GCState *st) {
Udata *u; Udata *u;
for (u = G(L)->rootudata; u; u = u->uv.next) for (u = G(st->L)->rootudata; u; u = u->uv.next)
marktable(st, u->uv.eventtable); marktable(st, u->uv.eventtable);
for (u = G(L)->tmudata; u; u = u->uv.next) for (u = G(st->L)->tmudata; u; u = u->uv.next)
marktable(st, u->uv.eventtable); marktable(st, u->uv.eventtable);
} }
@ -152,13 +155,20 @@ static void removekey (Node *n) {
static void traversetable (GCState *st, Table *h) { static void traversetable (GCState *st, Table *h) {
int i; int i;
int mode = h->weakmode; const TObject *mode;
int weakkey = 0;
int weakvalue = 0;
marktable(st, h->eventtable);
mode = fasttm(st->L, h->eventtable, TM_WEAKMODE);
if (mode) { /* weak table? must be cleared after GC... */ if (mode) { /* weak table? must be cleared after GC... */
h->mark = st->toclear; /* put in the appropriate list */ h->mark = st->toclear; /* put in the appropriate list */
st->toclear = h; st->toclear = h;
if (ttype(mode) == LUA_TSTRING) {
weakkey = (strchr(svalue(mode), 'k') != NULL);
weakvalue = (strchr(svalue(mode), 'v') != NULL);
}
} }
marktable(st, h->eventtable); if (!weakvalue) {
if (!(mode & LUA_WEAK_VALUE)) {
i = sizearray(h); i = sizearray(h);
while (i--) while (i--)
markobject(st, &h->array[i]); markobject(st, &h->array[i]);
@ -168,18 +178,18 @@ static void traversetable (GCState *st, Table *h) {
Node *n = node(h, i); Node *n = node(h, i);
if (ttype(val(n)) != LUA_TNIL) { if (ttype(val(n)) != LUA_TNIL) {
lua_assert(ttype(key(n)) != LUA_TNIL); lua_assert(ttype(key(n)) != LUA_TNIL);
if (!(mode & LUA_WEAK_KEY)) if (!weakkey) markobject(st, key(n));
markobject(st, key(n)); if (!weakvalue) markobject(st, val(n));
if (!(mode & LUA_WEAK_VALUE))
markobject(st, val(n));
} }
} }
} }
static void markall (lua_State *L, GCState *st) { static void markall (GCState *st) {
markstacks(L, st); /* mark all stacks */ lua_assert(hvalue(defaultet(st->L))->flags == cast(unsigned short, ~0));
markudet(L, st); /* mark userdata's event tables */ /* table is unchanged */
markstacks(st); /* mark all stacks */
markudet(st); /* mark userdata's event tables */
while (st->tmark) { /* traverse marked tables */ while (st->tmark) { /* traverse marked tables */
Table *h = st->tmark; /* get first table from list */ Table *h = st->tmark; /* get first table from list */
st->tmark = h->mark; /* remove it from list */ st->tmark = h->mark; /* remove it from list */
@ -210,7 +220,6 @@ static int hasmark (const TObject *o) {
static void cleartables (Table *h) { static void cleartables (Table *h) {
for (; h; h = h->mark) { for (; h; h = h->mark) {
int i; int i;
lua_assert(h->weakmode);
i = sizearray(h); i = sizearray(h);
while (i--) { while (i--) {
TObject *o = &h->array[i]; TObject *o = &h->array[i];
@ -421,9 +430,10 @@ void luaC_collect (lua_State *L, int all) {
void luaC_collectgarbage (lua_State *L) { void luaC_collectgarbage (lua_State *L) {
GCState st; GCState st;
st.L = L;
st.tmark = NULL; st.tmark = NULL;
st.toclear = NULL; st.toclear = NULL;
markall(L, &st); markall(&st);
cleartables(st.toclear); cleartables(st.toclear);
luaC_collect(L, 0); luaC_collect(L, 0);
checkMbuffer(L); checkMbuffer(L);

View File

@ -214,9 +214,9 @@ typedef union Closure {
*/ */
typedef struct Node { typedef struct Node {
struct Node *next; /* for chaining */
TObject _key; TObject _key;
TObject _val; TObject _val;
struct Node *next; /* for chaining */
} Node; } Node;
@ -226,7 +226,6 @@ typedef struct Table {
Node *node; Node *node;
int sizearray; /* size of `array' array */ int sizearray; /* size of `array' array */
lu_byte lsizenode; /* log2 of size of `node' array */ lu_byte lsizenode; /* log2 of size of `node' array */
lu_byte weakmode;
unsigned short flags; /* 1<<p means tagmethod(p) is not present */ unsigned short flags; /* 1<<p means tagmethod(p) is not present */
Node *firstfree; /* this position is free; all positions after it are full */ Node *firstfree; /* this position is free; all positions after it are full */
struct Table *next; struct Table *next;

View File

@ -274,7 +274,6 @@ Table *luaH_new (lua_State *L, int narray, int lnhash) {
t->next = G(L)->roottable; t->next = G(L)->roottable;
G(L)->roottable = t; G(L)->roottable = t;
t->mark = t; t->mark = t;
t->weakmode = 0;
t->flags = cast(unsigned short, ~0); t->flags = cast(unsigned short, ~0);
/* temporary values (kept only if some malloc fails) */ /* temporary values (kept only if some malloc fails) */
t->array = NULL; t->array = NULL;

2
ltm.c
View File

@ -26,7 +26,7 @@ const char *const luaT_typenames[] = {
void luaT_init (lua_State *L) { void luaT_init (lua_State *L) {
static const char *const luaT_eventname[] = { /* ORDER TM */ static const char *const luaT_eventname[] = { /* ORDER TM */
"gettable", "settable", "index", "gettable", "settable", "index",
"gc", "gc", "weakmode",
"add", "sub", "mul", "div", "add", "sub", "mul", "div",
"pow", "unm", "lt", "concat", "pow", "unm", "lt", "concat",
"call" "call"

1
ltm.h
View File

@ -19,6 +19,7 @@ typedef enum {
TM_SETTABLE, TM_SETTABLE,
TM_INDEX, TM_INDEX,
TM_GC, TM_GC,
TM_WEAKMODE,
TM_ADD, TM_ADD,
TM_SUB, TM_SUB,
TM_MUL, TM_MUL,