diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-01-09 19:50:35 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-01-09 19:50:35 -0200 |
| commit | b3bb0f132b2a3dba88385f8d71ba3f34252d94e4 (patch) | |
| tree | 111d09e92f36a4525ee9a62596925ac6cc9567b0 | |
| parent | facfec0687ff20351d3c7520344a722b9149c9ea (diff) | |
| download | lua-b3bb0f132b2a3dba88385f8d71ba3f34252d94e4.tar.gz lua-b3bb0f132b2a3dba88385f8d71ba3f34252d94e4.tar.bz2 lua-b3bb0f132b2a3dba88385f8d71ba3f34252d94e4.zip | |
new interface for weak modes
| -rw-r--r-- | lapi.c | 24 | ||||
| -rw-r--r-- | lgc.c | 46 | ||||
| -rw-r--r-- | lobject.h | 3 | ||||
| -rw-r--r-- | ltable.c | 1 | ||||
| -rw-r--r-- | ltm.c | 2 | ||||
| -rw-r--r-- | ltm.h | 1 |
6 files changed, 33 insertions, 44 deletions
| @@ -695,28 +695,7 @@ LUA_API void lua_newuserdatabox (lua_State *L, void *p) { | |||
| 695 | } | 695 | } |
| 696 | 696 | ||
| 697 | 697 | ||
| 698 | LUA_API int lua_getweakmode (lua_State *L, int index) { | 698 | LUA_API int lua_pushupvalues (lua_State *L) { |
| 699 | StkId t; | ||
| 700 | int mode; | ||
| 701 | lua_lock(L); | ||
| 702 | t = luaA_index(L, index); | ||
| 703 | api_check(L, ttype(t) == LUA_TTABLE); | ||
| 704 | mode = hvalue(t)->weakmode; | ||
| 705 | lua_unlock(L); | ||
| 706 | return mode; | ||
| 707 | } | ||
| 708 | |||
| 709 | |||
| 710 | LUA_API void lua_setweakmode (lua_State *L, int mode) { | ||
| 711 | lua_lock(L); | ||
| 712 | api_check(L, ttype(L->top-1) == LUA_TTABLE); | ||
| 713 | hvalue(L->top-1)->weakmode = cast(lu_byte, mode); | ||
| 714 | lua_unlock(L); | ||
| 715 | } | ||
| 716 | |||
| 717 | |||
| 718 | |||
| 719 | LUA_API void lua_pushupvalues (lua_State *L) { | ||
| 720 | TObject *func; | 699 | TObject *func; |
| 721 | int n, i; | 700 | int n, i; |
| 722 | lua_lock(L); | 701 | lua_lock(L); |
| @@ -730,6 +709,7 @@ LUA_API void lua_pushupvalues (lua_State *L) { | |||
| 730 | L->top++; | 709 | L->top++; |
| 731 | } | 710 | } |
| 732 | lua_unlock(L); | 711 | lua_unlock(L); |
| 712 | return n; | ||
| 733 | } | 713 | } |
| 734 | 714 | ||
| 735 | 715 | ||
| @@ -4,6 +4,8 @@ | |||
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <string.h> | ||
| 8 | |||
| 7 | #include "lua.h" | 9 | #include "lua.h" |
| 8 | 10 | ||
| 9 | #include "ldebug.h" | 11 | #include "ldebug.h" |
| @@ -22,6 +24,7 @@ | |||
| 22 | typedef struct GCState { | 24 | typedef struct GCState { |
| 23 | Table *tmark; /* list of marked tables to be visited */ | 25 | Table *tmark; /* list of marked tables to be visited */ |
| 24 | Table *toclear; /* list of visited weak tables (to be cleared after GC) */ | 26 | Table *toclear; /* list of visited weak tables (to be cleared after GC) */ |
| 27 | lua_State *L; | ||
| 25 | } GCState; | 28 | } GCState; |
| 26 | 29 | ||
| 27 | 30 | ||
| @@ -119,8 +122,8 @@ static void markobject (GCState *st, TObject *o) { | |||
| 119 | } | 122 | } |
| 120 | 123 | ||
| 121 | 124 | ||
| 122 | static void markstacks (lua_State *L, GCState *st) { | 125 | static void markstacks (GCState *st) { |
| 123 | lua_State *L1 = L; | 126 | lua_State *L1 = st->L; |
| 124 | do { /* for each thread */ | 127 | do { /* for each thread */ |
| 125 | StkId o, lim; | 128 | StkId o, lim; |
| 126 | for (o=L1->stack; o<L1->top; o++) | 129 | for (o=L1->stack; o<L1->top; o++) |
| @@ -130,15 +133,15 @@ static void markstacks (lua_State *L, GCState *st) { | |||
| 130 | for (; o<=lim; o++) setnilvalue(o); | 133 | for (; o<=lim; o++) setnilvalue(o); |
| 131 | lua_assert(L1->previous->next == L1 && L1->next->previous == L1); | 134 | lua_assert(L1->previous->next == L1 && L1->next->previous == L1); |
| 132 | L1 = L1->next; | 135 | L1 = L1->next; |
| 133 | } while (L1 != L); | 136 | } while (L1 != st->L); |
| 134 | } | 137 | } |
| 135 | 138 | ||
| 136 | 139 | ||
| 137 | static void markudet (lua_State *L, GCState *st) { | 140 | static void markudet (GCState *st) { |
| 138 | Udata *u; | 141 | Udata *u; |
| 139 | for (u = G(L)->rootudata; u; u = u->uv.next) | 142 | for (u = G(st->L)->rootudata; u; u = u->uv.next) |
| 140 | marktable(st, u->uv.eventtable); | 143 | marktable(st, u->uv.eventtable); |
| 141 | for (u = G(L)->tmudata; u; u = u->uv.next) | 144 | for (u = G(st->L)->tmudata; u; u = u->uv.next) |
| 142 | marktable(st, u->uv.eventtable); | 145 | marktable(st, u->uv.eventtable); |
| 143 | } | 146 | } |
| 144 | 147 | ||
| @@ -152,13 +155,20 @@ static void removekey (Node *n) { | |||
| 152 | 155 | ||
| 153 | static void traversetable (GCState *st, Table *h) { | 156 | static void traversetable (GCState *st, Table *h) { |
| 154 | int i; | 157 | int i; |
| 155 | int mode = h->weakmode; | 158 | const TObject *mode; |
| 159 | int weakkey = 0; | ||
| 160 | int weakvalue = 0; | ||
| 161 | marktable(st, h->eventtable); | ||
| 162 | mode = fasttm(st->L, h->eventtable, TM_WEAKMODE); | ||
| 156 | if (mode) { /* weak table? must be cleared after GC... */ | 163 | if (mode) { /* weak table? must be cleared after GC... */ |
| 157 | h->mark = st->toclear; /* put in the appropriate list */ | 164 | h->mark = st->toclear; /* put in the appropriate list */ |
| 158 | st->toclear = h; | 165 | st->toclear = h; |
| 166 | if (ttype(mode) == LUA_TSTRING) { | ||
| 167 | weakkey = (strchr(svalue(mode), 'k') != NULL); | ||
| 168 | weakvalue = (strchr(svalue(mode), 'v') != NULL); | ||
| 169 | } | ||
| 159 | } | 170 | } |
| 160 | marktable(st, h->eventtable); | 171 | if (!weakvalue) { |
| 161 | if (!(mode & LUA_WEAK_VALUE)) { | ||
| 162 | i = sizearray(h); | 172 | i = sizearray(h); |
| 163 | while (i--) | 173 | while (i--) |
| 164 | markobject(st, &h->array[i]); | 174 | markobject(st, &h->array[i]); |
| @@ -168,18 +178,18 @@ static void traversetable (GCState *st, Table *h) { | |||
| 168 | Node *n = node(h, i); | 178 | Node *n = node(h, i); |
| 169 | if (ttype(val(n)) != LUA_TNIL) { | 179 | if (ttype(val(n)) != LUA_TNIL) { |
| 170 | lua_assert(ttype(key(n)) != LUA_TNIL); | 180 | lua_assert(ttype(key(n)) != LUA_TNIL); |
| 171 | if (!(mode & LUA_WEAK_KEY)) | 181 | if (!weakkey) markobject(st, key(n)); |
| 172 | markobject(st, key(n)); | 182 | if (!weakvalue) markobject(st, val(n)); |
| 173 | if (!(mode & LUA_WEAK_VALUE)) | ||
| 174 | markobject(st, val(n)); | ||
| 175 | } | 183 | } |
| 176 | } | 184 | } |
| 177 | } | 185 | } |
| 178 | 186 | ||
| 179 | 187 | ||
| 180 | static void markall (lua_State *L, GCState *st) { | 188 | static void markall (GCState *st) { |
| 181 | markstacks(L, st); /* mark all stacks */ | 189 | lua_assert(hvalue(defaultet(st->L))->flags == cast(unsigned short, ~0)); |
| 182 | markudet(L, st); /* mark userdata's event tables */ | 190 | /* table is unchanged */ |
| 191 | markstacks(st); /* mark all stacks */ | ||
| 192 | markudet(st); /* mark userdata's event tables */ | ||
| 183 | while (st->tmark) { /* traverse marked tables */ | 193 | while (st->tmark) { /* traverse marked tables */ |
| 184 | Table *h = st->tmark; /* get first table from list */ | 194 | Table *h = st->tmark; /* get first table from list */ |
| 185 | st->tmark = h->mark; /* remove it from list */ | 195 | st->tmark = h->mark; /* remove it from list */ |
| @@ -210,7 +220,6 @@ static int hasmark (const TObject *o) { | |||
| 210 | static void cleartables (Table *h) { | 220 | static void cleartables (Table *h) { |
| 211 | for (; h; h = h->mark) { | 221 | for (; h; h = h->mark) { |
| 212 | int i; | 222 | int i; |
| 213 | lua_assert(h->weakmode); | ||
| 214 | i = sizearray(h); | 223 | i = sizearray(h); |
| 215 | while (i--) { | 224 | while (i--) { |
| 216 | TObject *o = &h->array[i]; | 225 | TObject *o = &h->array[i]; |
| @@ -421,9 +430,10 @@ void luaC_collect (lua_State *L, int all) { | |||
| 421 | 430 | ||
| 422 | void luaC_collectgarbage (lua_State *L) { | 431 | void luaC_collectgarbage (lua_State *L) { |
| 423 | GCState st; | 432 | GCState st; |
| 433 | st.L = L; | ||
| 424 | st.tmark = NULL; | 434 | st.tmark = NULL; |
| 425 | st.toclear = NULL; | 435 | st.toclear = NULL; |
| 426 | markall(L, &st); | 436 | markall(&st); |
| 427 | cleartables(st.toclear); | 437 | cleartables(st.toclear); |
| 428 | luaC_collect(L, 0); | 438 | luaC_collect(L, 0); |
| 429 | checkMbuffer(L); | 439 | checkMbuffer(L); |
| @@ -214,9 +214,9 @@ typedef union Closure { | |||
| 214 | */ | 214 | */ |
| 215 | 215 | ||
| 216 | typedef struct Node { | 216 | typedef struct Node { |
| 217 | struct Node *next; /* for chaining */ | ||
| 218 | TObject _key; | 217 | TObject _key; |
| 219 | TObject _val; | 218 | TObject _val; |
| 219 | struct Node *next; /* for chaining */ | ||
| 220 | } Node; | 220 | } Node; |
| 221 | 221 | ||
| 222 | 222 | ||
| @@ -226,7 +226,6 @@ typedef struct Table { | |||
| 226 | Node *node; | 226 | Node *node; |
| 227 | int sizearray; /* size of `array' array */ | 227 | int sizearray; /* size of `array' array */ |
| 228 | lu_byte lsizenode; /* log2 of size of `node' array */ | 228 | lu_byte lsizenode; /* log2 of size of `node' array */ |
| 229 | lu_byte weakmode; | ||
| 230 | unsigned short flags; /* 1<<p means tagmethod(p) is not present */ | 229 | unsigned short flags; /* 1<<p means tagmethod(p) is not present */ |
| 231 | Node *firstfree; /* this position is free; all positions after it are full */ | 230 | Node *firstfree; /* this position is free; all positions after it are full */ |
| 232 | struct Table *next; | 231 | struct Table *next; |
| @@ -274,7 +274,6 @@ Table *luaH_new (lua_State *L, int narray, int lnhash) { | |||
| 274 | t->next = G(L)->roottable; | 274 | t->next = G(L)->roottable; |
| 275 | G(L)->roottable = t; | 275 | G(L)->roottable = t; |
| 276 | t->mark = t; | 276 | t->mark = t; |
| 277 | t->weakmode = 0; | ||
| 278 | t->flags = cast(unsigned short, ~0); | 277 | t->flags = cast(unsigned short, ~0); |
| 279 | /* temporary values (kept only if some malloc fails) */ | 278 | /* temporary values (kept only if some malloc fails) */ |
| 280 | t->array = NULL; | 279 | t->array = NULL; |
| @@ -26,7 +26,7 @@ const char *const luaT_typenames[] = { | |||
| 26 | void luaT_init (lua_State *L) { | 26 | void luaT_init (lua_State *L) { |
| 27 | static const char *const luaT_eventname[] = { /* ORDER TM */ | 27 | static const char *const luaT_eventname[] = { /* ORDER TM */ |
| 28 | "gettable", "settable", "index", | 28 | "gettable", "settable", "index", |
| 29 | "gc", | 29 | "gc", "weakmode", |
| 30 | "add", "sub", "mul", "div", | 30 | "add", "sub", "mul", "div", |
| 31 | "pow", "unm", "lt", "concat", | 31 | "pow", "unm", "lt", "concat", |
| 32 | "call" | 32 | "call" |
| @@ -19,6 +19,7 @@ typedef enum { | |||
| 19 | TM_SETTABLE, | 19 | TM_SETTABLE, |
| 20 | TM_INDEX, | 20 | TM_INDEX, |
| 21 | TM_GC, | 21 | TM_GC, |
| 22 | TM_WEAKMODE, | ||
| 22 | TM_ADD, | 23 | TM_ADD, |
| 23 | TM_SUB, | 24 | TM_SUB, |
| 24 | TM_MUL, | 25 | TM_MUL, |
