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 /lgc.c | |
parent | facfec0687ff20351d3c7520344a722b9149c9ea (diff) | |
download | lua-b3bb0f132b2a3dba88385f8d71ba3f34252d94e4.tar.gz lua-b3bb0f132b2a3dba88385f8d71ba3f34252d94e4.tar.bz2 lua-b3bb0f132b2a3dba88385f8d71ba3f34252d94e4.zip |
new interface for weak modes
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 46 |
1 files changed, 28 insertions, 18 deletions
@@ -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); |