diff options
-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, |