diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-10-25 17:05:28 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-10-25 17:05:28 -0300 |
commit | 96e15b8501e5d8fc40c475cbac573f910ab5853b (patch) | |
tree | 2c8efededa6849704f0db3075d0cbe0efaa40b2d /lgc.c | |
parent | 0fd91b1b087b478fffa36f96bc0f608d86627a4b (diff) | |
download | lua-96e15b8501e5d8fc40c475cbac573f910ab5853b.tar.gz lua-96e15b8501e5d8fc40c475cbac573f910ab5853b.tar.bz2 lua-96e15b8501e5d8fc40c475cbac573f910ab5853b.zip |
threads now are real Lua objects, subject to garbage collection
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 89 |
1 files changed, 48 insertions, 41 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.152 2002/10/08 18:46:08 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.153 2002/10/22 17:58:14 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -99,6 +99,32 @@ static void markclosure (GCState *st, Closure *cl) { | |||
99 | } | 99 | } |
100 | 100 | ||
101 | 101 | ||
102 | static void checkstacksizes (lua_State *L, StkId max) { | ||
103 | int used = L->ci - L->base_ci; /* number of `ci' in use */ | ||
104 | if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) | ||
105 | luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ | ||
106 | used = max - L->stack; /* part of stack in use */ | ||
107 | if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) | ||
108 | luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ | ||
109 | } | ||
110 | |||
111 | |||
112 | static void markstack (GCState *st, lua_State *L1) { | ||
113 | StkId o, lim; | ||
114 | CallInfo *ci; | ||
115 | markobject(st, gt(L1)); | ||
116 | for (o=L1->stack; o<L1->top; o++) | ||
117 | markobject(st, o); | ||
118 | lim = o; | ||
119 | for (ci = L1->base_ci; ci <= L1->ci; ci++) { | ||
120 | lua_assert(ci->top <= L1->stack_last); | ||
121 | if (lim < ci->top) lim = ci->top; | ||
122 | } | ||
123 | for (; o<=lim; o++) setnilvalue(o); | ||
124 | checkstacksizes(L1, lim); | ||
125 | } | ||
126 | |||
127 | |||
102 | static void reallymarkobject (GCState *st, GCObject *o) { | 128 | static void reallymarkobject (GCState *st, GCObject *o) { |
103 | setbit(o->gch.marked, 0); /* mark object */ | 129 | setbit(o->gch.marked, 0); /* mark object */ |
104 | switch (o->gch.tt) { | 130 | switch (o->gch.tt) { |
@@ -115,46 +141,11 @@ static void reallymarkobject (GCState *st, GCObject *o) { | |||
115 | st->tmark = &o->h; | 141 | st->tmark = &o->h; |
116 | break; | 142 | break; |
117 | } | 143 | } |
118 | } | 144 | case LUA_TTHREAD: { |
119 | } | 145 | markstack(st, &o->th); |
120 | 146 | break; | |
121 | |||
122 | static void checkstacksizes (lua_State *L, StkId max) { | ||
123 | int used = L->ci - L->base_ci; /* number of `ci' in use */ | ||
124 | if (4*used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) | ||
125 | luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ | ||
126 | used = max - L->stack; /* part of stack in use */ | ||
127 | if (4*used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) | ||
128 | luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ | ||
129 | } | ||
130 | |||
131 | |||
132 | static void traversestacks (GCState *st) { | ||
133 | lua_State *L1 = st->L; | ||
134 | do { /* for each thread */ | ||
135 | StkId o, lim; | ||
136 | CallInfo *ci; | ||
137 | if (ttisnil(gt(L1))) { /* incomplete state? */ | ||
138 | lua_assert(L1 != st->L); | ||
139 | L1 = L1->next; | ||
140 | luaE_closethread(st->L, L1->previous); /* collect it */ | ||
141 | continue; | ||
142 | } | ||
143 | markobject(st, gt(L1)); | ||
144 | for (o=L1->stack; o<L1->top; o++) | ||
145 | markobject(st, o); | ||
146 | lim = o; | ||
147 | for (ci = L1->base_ci; ci <= L1->ci; ci++) { | ||
148 | lua_assert(ci->top <= L1->stack_last); | ||
149 | if (lim < ci->top) lim = ci->top; | ||
150 | } | 147 | } |
151 | for (; o<=lim; o++) setnilvalue(o); | 148 | } |
152 | checkstacksizes(L1, lim); | ||
153 | lua_assert(L1->previous->next == L1 && L1->next->previous == L1); | ||
154 | L1 = L1->next; | ||
155 | } while (L1 != st->L); | ||
156 | markobject(st, defaultmeta(L1)); | ||
157 | markobject(st, registry(L1)); | ||
158 | } | 149 | } |
159 | 150 | ||
160 | 151 | ||
@@ -292,6 +283,11 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
292 | case LUA_TFUNCTION: luaF_freeclosure(L, &o->cl); break; | 283 | case LUA_TFUNCTION: luaF_freeclosure(L, &o->cl); break; |
293 | case LUA_TUPVAL: luaM_freelem(L, &o->uv); break; | 284 | case LUA_TUPVAL: luaM_freelem(L, &o->uv); break; |
294 | case LUA_TTABLE: luaH_free(L, &o->h); break; | 285 | case LUA_TTABLE: luaH_free(L, &o->h); break; |
286 | case LUA_TTHREAD: { | ||
287 | lua_assert(&o->th != L && &o->th != G(L)->mainthread); | ||
288 | luaE_freethread(L, &o->th); | ||
289 | break; | ||
290 | } | ||
295 | case LUA_TSTRING: { | 291 | case LUA_TSTRING: { |
296 | luaM_free(L, o, sizestring((&o->ts)->tsv.len)); | 292 | luaM_free(L, o, sizestring((&o->ts)->tsv.len)); |
297 | break; | 293 | break; |
@@ -389,13 +385,24 @@ void luaC_sweep (lua_State *L, int all) { | |||
389 | } | 385 | } |
390 | 386 | ||
391 | 387 | ||
388 | /* mark root set */ | ||
389 | static void markroot (GCState *st) { | ||
390 | lua_State *L = st->L; | ||
391 | markobject(st, defaultmeta(L)); | ||
392 | markobject(st, registry(L)); | ||
393 | markstack(st, G(L)->mainthread); | ||
394 | if (L != G(L)->mainthread) /* another thread is running? */ | ||
395 | reallymarkobject(st, cast(GCObject *, L)); /* cannot collect it */ | ||
396 | } | ||
397 | |||
398 | |||
392 | static void mark (lua_State *L) { | 399 | static void mark (lua_State *L) { |
393 | GCState st; | 400 | GCState st; |
394 | Table *toclear; | 401 | Table *toclear; |
395 | st.L = L; | 402 | st.L = L; |
396 | st.tmark = NULL; | 403 | st.tmark = NULL; |
397 | st.toclear = NULL; | 404 | st.toclear = NULL; |
398 | traversestacks(&st); /* mark all stacks */ | 405 | markroot(&st); |
399 | propagatemarks(&st); /* mark all reachable objects */ | 406 | propagatemarks(&st); /* mark all reachable objects */ |
400 | toclear = st.toclear; /* weak tables; to be cleared */ | 407 | toclear = st.toclear; /* weak tables; to be cleared */ |
401 | st.toclear = NULL; | 408 | st.toclear = NULL; |