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; |
