From 413fc7334bf8ceaea71417d73edef15c99d3a793 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Thu, 29 Nov 2001 18:22:22 -0200 Subject: new implementation for lua upvalues (sugested by E.T.): simpler and solves a bug for multi-stacks --- ldo.c | 1 - lfunc.c | 82 ++++++++++++++++++--------------------------------------------- lfunc.h | 2 +- lgc.c | 50 ++++++++++++++++---------------------- lobject.h | 20 ++++++++-------- lstate.c | 7 +++++- lstate.h | 8 +++---- lvm.c | 9 +++---- 8 files changed, 67 insertions(+), 112 deletions(-) diff --git a/ldo.c b/ldo.c index f28dca44..4e7722e3 100644 --- a/ldo.c +++ b/ldo.c @@ -215,7 +215,6 @@ static void f_parser (lua_State *L, void *ud) { Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z); Closure *cl = luaF_newLclosure(L, 0); cl->l.p = tf; - luaF_LConlist(L, cl); setclvalue(L->top, cl); incr_top; } diff --git a/lfunc.c b/lfunc.c index 8af857a8..25a8bb07 100644 --- a/lfunc.c +++ b/lfunc.c @@ -22,6 +22,7 @@ cast(int, sizeof(TObject *)*((n)-1))) + Closure *luaF_newCclosure (lua_State *L, int nelems) { Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); c->c.isC = 1; @@ -36,76 +37,39 @@ Closure *luaF_newCclosure (lua_State *L, int nelems) { Closure *luaF_newLclosure (lua_State *L, int nelems) { Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); c->l.isC = 0; + c->c.next = G(L)->rootcl; + G(L)->rootcl = c; c->l.marked = 0; c->l.nupvalues = nelems; return c; } -/* -** returns the open pointer in a closure that points higher into the stack -*/ -static StkId uppoint (LClosure *cl) { - StkId lp = NULL; - int i; - for (i=0; inupvalues; i++) { - if (!isclosed(cl->upvals[i]) && (lp == NULL || cl->upvals[i] > lp)) - lp = cl->upvals[i]; - } - return lp; -} - - -void luaF_LConlist (lua_State *L, Closure *cl) { - StkId cli = uppoint(&cl->l); - if (cli == NULL) { /* no more open entries? */ - cl->l.next = G(L)->rootcl; /* insert in final list */ - G(L)->rootcl = cl; - } - else { /* insert in list of open closures, ordered by decreasing uppoints */ - Closure **p = &L->opencl; - while (*p != NULL && uppoint(&(*p)->l) > cli) p = &(*p)->l.next; - cl->l.next = *p; - *p = cl; +UpVal *luaF_findupval (lua_State *L, StkId level) { + UpVal **pp = &L->openupval; + UpVal *p; + while ((p = *pp) != NULL && p->v >= level) { + if (p->v == level) return p; + pp = &p->next; } -} - - -static int closeCl (lua_State *L, LClosure *cl, StkId level) { - int got = 0; /* flag: 1 if some pointer in the closure was corrected */ - int i; - for (i=0; inupvalues; i++) { - StkId var; - if (!isclosed(cl->upvals[i]) && (var=cl->upvals[i]) >= level) { - if (ttype(var) != LUA_TUPVAL) { - TObject *v = luaM_newvector(L, 2, TObject); - v[1] = *var; - setupvalue(v, G(L)->rootupval, LUA_HEAPUPVAL); - G(L)->rootupval = v; - setupvalue(var, &v[1], LUA_TUPVAL); - } - cl->upvals[i] = vvalue(var); - got = 1; - } - } - return got; + p = luaM_new(L, UpVal); /* not found: create a new one */ + p->v = level; /* current value lives in the stack */ + p->mark = 1; /* won't participate in GC while open */ + p->next = *pp; /* chain it in the proper position */ + *pp = p; + return p; } void luaF_close (lua_State *L, StkId level) { - Closure *affected = NULL; /* closures with open pointers >= level */ - Closure *cl; - while ((cl=L->opencl) != NULL) { - if (!closeCl(L, cast(LClosure *, cl), level)) break; - /* some pointer in `cl' changed; will re-insert it in original list */ - L->opencl = cl->l.next; /* remove from original list */ - cl->l.next = affected; - affected = cl; /* insert in affected list */ - } - /* re-insert all affected closures in original list */ - while ((cl=affected) != NULL) { - affected = cl->l.next; - luaF_LConlist(L, cl); + UpVal *p; + while ((p = L->openupval) != NULL && p->v >= level) { + setobj(&p->value, p->v); /* save current value */ + p->v = &p->value; /* now current value lives here */ + L->openupval = p->next; /* remove from `open' list */ + p->next = G(L)->rootupval; /* chain in `closed' list */ + p->mark = 0; /* now it can be collected */ + G(L)->rootupval = p; } } diff --git a/lfunc.h b/lfunc.h index 111e554c..f57df4c2 100644 --- a/lfunc.h +++ b/lfunc.h @@ -14,7 +14,7 @@ Proto *luaF_newproto (lua_State *L); Closure *luaF_newCclosure (lua_State *L, int nelems); Closure *luaF_newLclosure (lua_State *L, int nelems); -void luaF_LConlist (lua_State *L, Closure *cl); +UpVal *luaF_findupval (lua_State *L, StkId level); void luaF_close (lua_State *L, StkId level); void luaF_freeproto (lua_State *L, Proto *f); void luaF_freeclosure (lua_State *L, Closure *c); diff --git a/lgc.c b/lgc.c index 418ccd6c..5ea01c77 100644 --- a/lgc.c +++ b/lgc.c @@ -65,10 +65,10 @@ static void markclosure (GCState *st, Closure *cl) { lua_assert(cl->l.nupvalues == cl->l.p->nupvalues); protomark(cl->l.p); for (i=0; il.nupvalues; i++) { /* mark its upvalues */ - TObject *u = cl->l.upvals[i]; - if (isclosed(u)) { - ttype(u-1) = LUA_TNIL; /* temporary value (to mark as visited) */ - markobject(st, u); + UpVal *u = cl->l.upvals[i]; + if (!u->mark) { + u->mark = 1; + markobject(st, u->v); } } } @@ -101,7 +101,7 @@ static void markobject (GCState *st, TObject *o) { break; } default: { - lua_assert(0 <= ttype(o) && ttype(o) <= LUA_TUPVAL); + lua_assert(ttype(o) == LUA_TNIL || ttype(o) == LUA_TNUMBER); break; } } @@ -241,7 +241,8 @@ static void collectproto (lua_State *L) { } -static void collectclosure (lua_State *L, Closure **p) { +static void collectclosures (lua_State *L) { + Closure **p = &G(L)->rootcl; Closure *curr; while ((curr = *p) != NULL) { if (curr->c.marked) { @@ -256,13 +257,19 @@ static void collectclosure (lua_State *L, Closure **p) { } -static void collectclosures (lua_State *L) { - lua_State *L1 = L; - do { /* for each thread */ - collectclosure(L1, &L1->opencl); - L1 = L1->next; - } while (L1 != L); - collectclosure(L, &G(L)->rootcl); +static void collectupval (lua_State *L) { + UpVal **v = &G(L)->rootupval; + UpVal *curr; + while ((curr = *v) != NULL) { + if (curr->mark) { + curr->mark = 0; + v = &curr->next; /* next */ + } + else { + *v = curr->next; /* next */ + luaM_freelem(L, curr); + } + } } @@ -282,23 +289,6 @@ static void collecttable (lua_State *L) { } -static void collectupval (lua_State *L) { - TObject **v = &G(L)->rootupval; - TObject *curr; - while ((curr = *v) != NULL) { - if (ttype(curr) == LUA_TNIL) { /* was marked? */ - ttype(curr) = LUA_HEAPUPVAL; /* unmark */ - v = &vvalue(curr); /* next */ - } - else { - lua_assert(ttype(curr) == LUA_HEAPUPVAL); - *v = vvalue(curr); /* next */ - luaM_freearray(L, curr, 2, TObject); - } - } -} - - static void collectudata (lua_State *L, int keep) { Udata **p = &G(L)->rootudata; Udata *curr; diff --git a/lobject.h b/lobject.h index 3e1e8b36..beb6574f 100644 --- a/lobject.h +++ b/lobject.h @@ -170,15 +170,15 @@ typedef struct LocVar { /* -** Upvalues in the heap. There is a small trick here: to allow a closure to -** diferentiate between upvalues in the heap and in the stack, upvalues in -** the heap always have another TObject before them (like those in the stack), -** but those `prefix' objects have a tag that cannot happen in the stack. -** Moreover, we use these extra `prexif' object to store GC-related -** information. +** Upvalues */ -#define isclosed(u) (ttype((u)-1) == LUA_HEAPUPVAL) +typedef struct UpVal { + TObject *v; /* points to stack or to its own value */ + int mark; + struct UpVal *next; + TObject value; /* the value (when closed) */ +} UpVal; /* @@ -201,7 +201,7 @@ typedef struct LClosure { lu_byte marked; union Closure *next; /* first four fields must be equal to CClosure!! */ struct Proto *p; - TObject *upvals[1]; + UpVal *upvals[1]; } LClosure; @@ -221,8 +221,8 @@ typedef union Closure { typedef struct Node { struct Node *next; /* for chaining */ - TObject key; - TObject val; + TObject _key; + TObject _val; } Node; diff --git a/lstate.c b/lstate.c index a9130455..6e2ba8f1 100644 --- a/lstate.c +++ b/lstate.c @@ -10,6 +10,7 @@ #include "lua.h" #include "ldo.h" +#include "lfunc.h" #include "lgc.h" #include "llex.h" #include "lmem.h" @@ -88,7 +89,7 @@ LUA_API lua_State *lua_newthread (lua_State *OL, int stacksize) { L->errorJmp = NULL; L->callhook = NULL; L->linehook = NULL; - L->opencl = NULL; + L->openupval = NULL; L->allowhooks = 1; L->next = L->previous = L; so.stacksize = stacksize; @@ -105,6 +106,8 @@ LUA_API lua_State *lua_newthread (lua_State *OL, int stacksize) { static void close_state (lua_State *L, lua_State *OL) { + luaF_close(L, L->stack); /* close all upvalues for this thread */ + lua_assert(L->openupval == NULL); if (OL != NULL) { /* are there other threads? */ lua_assert(L->previous != L); L->previous->next = L->next; @@ -116,6 +119,7 @@ static void close_state (lua_State *L, lua_State *OL) { lua_assert(G(L)->rootproto == NULL); lua_assert(G(L)->rootudata == NULL); lua_assert(G(L)->rootcl == NULL); + lua_assert(G(L)->rootupval == NULL); lua_assert(G(L)->roottable == NULL); luaS_freeall(L); luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM); @@ -126,6 +130,7 @@ static void close_state (lua_State *L, lua_State *OL) { luaM_freelem(OL, L); } + LUA_API void lua_close (lua_State *L) { lua_State *OL; lua_assert(L != lua_state || lua_gettop(L) == 0); diff --git a/lstate.h b/lstate.h index 9f7c7e5c..981e28fe 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 1.63 2001/10/31 19:58:11 roberto Exp $ +** $Id: lstate.h,v 1.64 2001/11/06 21:40:51 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -65,10 +65,10 @@ typedef struct global_State { lu_mem GCthreshold; lu_mem nblocks; /* number of `bytes' currently allocated */ Proto *rootproto; /* list of all prototypes */ - Closure *rootcl; /* list of all C closures and closed Lua closures */ + Closure *rootcl; /* list of all closures */ Table *roottable; /* list of all tables */ Udata *rootudata; /* list of all userdata */ - TObject *rootupval; /* list of all up values */ + UpVal *rootupval; /* list of closed up values */ } global_State; @@ -88,7 +88,7 @@ struct lua_State { lua_Hook linehook; int allowhooks; struct lua_longjmp *errorJmp; /* current error recover point */ - Closure *opencl; /* list of closures still pointing to this stack */ + UpVal *openupval; /* list of open upvalues in this stack */ lua_State *next; /* circular double linked list of states */ lua_State *previous; CallInfo basefunc; diff --git a/lvm.c b/lvm.c index 5c8eabdc..c4281e44 100644 --- a/lvm.c +++ b/lvm.c @@ -390,8 +390,7 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) { } case OP_GETUPVAL: { int b = GETARG_B(i); - lua_assert(isclosed(cl->upvals[b]) || cl->upvals[b] < base); - setobj(ra, cl->upvals[b]); + setobj(ra, cl->upvals[b]->v); break; } case OP_GETGLOBAL: { @@ -410,8 +409,7 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) { } case OP_SETUPVAL: { int b = GETARG_B(i); - lua_assert(isclosed(cl->upvals[b]) || cl->upvals[b] < base); - setobj(cl->upvals[b], ra); + setobj(cl->upvals[b]->v, ra); break; } case OP_SETTABLE: { @@ -648,10 +646,9 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) { ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)]; else { lua_assert(GET_OPCODE(*pc) == OP_MOVE); - ncl->l.upvals[j] = base + GETARG_B(*pc); + ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); } } - luaF_LConlist(L, ncl); setclvalue(ra, ncl); break; } -- cgit v1.2.3-55-g6feb