new implementation for lua upvalues (sugested by E.T.): simpler and solves
a bug for multi-stacks
This commit is contained in:
1
ldo.c
1
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);
|
Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z);
|
||||||
Closure *cl = luaF_newLclosure(L, 0);
|
Closure *cl = luaF_newLclosure(L, 0);
|
||||||
cl->l.p = tf;
|
cl->l.p = tf;
|
||||||
luaF_LConlist(L, cl);
|
|
||||||
setclvalue(L->top, cl);
|
setclvalue(L->top, cl);
|
||||||
incr_top;
|
incr_top;
|
||||||
}
|
}
|
||||||
|
|||||||
82
lfunc.c
82
lfunc.c
@@ -22,6 +22,7 @@
|
|||||||
cast(int, sizeof(TObject *)*((n)-1)))
|
cast(int, sizeof(TObject *)*((n)-1)))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Closure *luaF_newCclosure (lua_State *L, int nelems) {
|
Closure *luaF_newCclosure (lua_State *L, int nelems) {
|
||||||
Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
|
Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
|
||||||
c->c.isC = 1;
|
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 *luaF_newLclosure (lua_State *L, int nelems) {
|
||||||
Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
|
Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
|
||||||
c->l.isC = 0;
|
c->l.isC = 0;
|
||||||
|
c->c.next = G(L)->rootcl;
|
||||||
|
G(L)->rootcl = c;
|
||||||
c->l.marked = 0;
|
c->l.marked = 0;
|
||||||
c->l.nupvalues = nelems;
|
c->l.nupvalues = nelems;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
UpVal *luaF_findupval (lua_State *L, StkId level) {
|
||||||
** returns the open pointer in a closure that points higher into the stack
|
UpVal **pp = &L->openupval;
|
||||||
*/
|
UpVal *p;
|
||||||
static StkId uppoint (LClosure *cl) {
|
while ((p = *pp) != NULL && p->v >= level) {
|
||||||
StkId lp = NULL;
|
if (p->v == level) return p;
|
||||||
int i;
|
pp = &p->next;
|
||||||
for (i=0; i<cl->nupvalues; i++) {
|
|
||||||
if (!isclosed(cl->upvals[i]) && (lp == NULL || cl->upvals[i] > lp))
|
|
||||||
lp = cl->upvals[i];
|
|
||||||
}
|
}
|
||||||
return lp;
|
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 */
|
||||||
void luaF_LConlist (lua_State *L, Closure *cl) {
|
*pp = p;
|
||||||
StkId cli = uppoint(&cl->l);
|
return p;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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; i<cl->nupvalues; 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void luaF_close (lua_State *L, StkId level) {
|
void luaF_close (lua_State *L, StkId level) {
|
||||||
Closure *affected = NULL; /* closures with open pointers >= level */
|
UpVal *p;
|
||||||
Closure *cl;
|
while ((p = L->openupval) != NULL && p->v >= level) {
|
||||||
while ((cl=L->opencl) != NULL) {
|
setobj(&p->value, p->v); /* save current value */
|
||||||
if (!closeCl(L, cast(LClosure *, cl), level)) break;
|
p->v = &p->value; /* now current value lives here */
|
||||||
/* some pointer in `cl' changed; will re-insert it in original list */
|
L->openupval = p->next; /* remove from `open' list */
|
||||||
L->opencl = cl->l.next; /* remove from original list */
|
p->next = G(L)->rootupval; /* chain in `closed' list */
|
||||||
cl->l.next = affected;
|
p->mark = 0; /* now it can be collected */
|
||||||
affected = cl; /* insert in affected list */
|
G(L)->rootupval = p;
|
||||||
}
|
|
||||||
/* re-insert all affected closures in original list */
|
|
||||||
while ((cl=affected) != NULL) {
|
|
||||||
affected = cl->l.next;
|
|
||||||
luaF_LConlist(L, cl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
lfunc.h
2
lfunc.h
@@ -14,7 +14,7 @@
|
|||||||
Proto *luaF_newproto (lua_State *L);
|
Proto *luaF_newproto (lua_State *L);
|
||||||
Closure *luaF_newCclosure (lua_State *L, int nelems);
|
Closure *luaF_newCclosure (lua_State *L, int nelems);
|
||||||
Closure *luaF_newLclosure (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_close (lua_State *L, StkId level);
|
||||||
void luaF_freeproto (lua_State *L, Proto *f);
|
void luaF_freeproto (lua_State *L, Proto *f);
|
||||||
void luaF_freeclosure (lua_State *L, Closure *c);
|
void luaF_freeclosure (lua_State *L, Closure *c);
|
||||||
|
|||||||
50
lgc.c
50
lgc.c
@@ -65,10 +65,10 @@ static void markclosure (GCState *st, Closure *cl) {
|
|||||||
lua_assert(cl->l.nupvalues == cl->l.p->nupvalues);
|
lua_assert(cl->l.nupvalues == cl->l.p->nupvalues);
|
||||||
protomark(cl->l.p);
|
protomark(cl->l.p);
|
||||||
for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
|
for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
|
||||||
TObject *u = cl->l.upvals[i];
|
UpVal *u = cl->l.upvals[i];
|
||||||
if (isclosed(u)) {
|
if (!u->mark) {
|
||||||
ttype(u-1) = LUA_TNIL; /* temporary value (to mark as visited) */
|
u->mark = 1;
|
||||||
markobject(st, u);
|
markobject(st, u->v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,7 @@ static void markobject (GCState *st, TObject *o) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
lua_assert(0 <= ttype(o) && ttype(o) <= LUA_TUPVAL);
|
lua_assert(ttype(o) == LUA_TNIL || ttype(o) == LUA_TNUMBER);
|
||||||
break;
|
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;
|
Closure *curr;
|
||||||
while ((curr = *p) != NULL) {
|
while ((curr = *p) != NULL) {
|
||||||
if (curr->c.marked) {
|
if (curr->c.marked) {
|
||||||
@@ -256,13 +257,19 @@ static void collectclosure (lua_State *L, Closure **p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void collectclosures (lua_State *L) {
|
static void collectupval (lua_State *L) {
|
||||||
lua_State *L1 = L;
|
UpVal **v = &G(L)->rootupval;
|
||||||
do { /* for each thread */
|
UpVal *curr;
|
||||||
collectclosure(L1, &L1->opencl);
|
while ((curr = *v) != NULL) {
|
||||||
L1 = L1->next;
|
if (curr->mark) {
|
||||||
} while (L1 != L);
|
curr->mark = 0;
|
||||||
collectclosure(L, &G(L)->rootcl);
|
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) {
|
static void collectudata (lua_State *L, int keep) {
|
||||||
Udata **p = &G(L)->rootudata;
|
Udata **p = &G(L)->rootudata;
|
||||||
Udata *curr;
|
Udata *curr;
|
||||||
|
|||||||
20
lobject.h
20
lobject.h
@@ -170,15 +170,15 @@ typedef struct LocVar {
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Upvalues in the heap. There is a small trick here: to allow a closure to
|
** Upvalues
|
||||||
** 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.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#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;
|
lu_byte marked;
|
||||||
union Closure *next; /* first four fields must be equal to CClosure!! */
|
union Closure *next; /* first four fields must be equal to CClosure!! */
|
||||||
struct Proto *p;
|
struct Proto *p;
|
||||||
TObject *upvals[1];
|
UpVal *upvals[1];
|
||||||
} LClosure;
|
} LClosure;
|
||||||
|
|
||||||
|
|
||||||
@@ -221,8 +221,8 @@ typedef union Closure {
|
|||||||
|
|
||||||
typedef struct Node {
|
typedef struct Node {
|
||||||
struct Node *next; /* for chaining */
|
struct Node *next; /* for chaining */
|
||||||
TObject key;
|
TObject _key;
|
||||||
TObject val;
|
TObject _val;
|
||||||
} Node;
|
} Node;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
7
lstate.c
7
lstate.c
@@ -10,6 +10,7 @@
|
|||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
#include "ldo.h"
|
#include "ldo.h"
|
||||||
|
#include "lfunc.h"
|
||||||
#include "lgc.h"
|
#include "lgc.h"
|
||||||
#include "llex.h"
|
#include "llex.h"
|
||||||
#include "lmem.h"
|
#include "lmem.h"
|
||||||
@@ -88,7 +89,7 @@ LUA_API lua_State *lua_newthread (lua_State *OL, int stacksize) {
|
|||||||
L->errorJmp = NULL;
|
L->errorJmp = NULL;
|
||||||
L->callhook = NULL;
|
L->callhook = NULL;
|
||||||
L->linehook = NULL;
|
L->linehook = NULL;
|
||||||
L->opencl = NULL;
|
L->openupval = NULL;
|
||||||
L->allowhooks = 1;
|
L->allowhooks = 1;
|
||||||
L->next = L->previous = L;
|
L->next = L->previous = L;
|
||||||
so.stacksize = stacksize;
|
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) {
|
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? */
|
if (OL != NULL) { /* are there other threads? */
|
||||||
lua_assert(L->previous != L);
|
lua_assert(L->previous != L);
|
||||||
L->previous->next = L->next;
|
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)->rootproto == NULL);
|
||||||
lua_assert(G(L)->rootudata == NULL);
|
lua_assert(G(L)->rootudata == NULL);
|
||||||
lua_assert(G(L)->rootcl == NULL);
|
lua_assert(G(L)->rootcl == NULL);
|
||||||
|
lua_assert(G(L)->rootupval == NULL);
|
||||||
lua_assert(G(L)->roottable == NULL);
|
lua_assert(G(L)->roottable == NULL);
|
||||||
luaS_freeall(L);
|
luaS_freeall(L);
|
||||||
luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM);
|
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);
|
luaM_freelem(OL, L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LUA_API void lua_close (lua_State *L) {
|
LUA_API void lua_close (lua_State *L) {
|
||||||
lua_State *OL;
|
lua_State *OL;
|
||||||
lua_assert(L != lua_state || lua_gettop(L) == 0);
|
lua_assert(L != lua_state || lua_gettop(L) == 0);
|
||||||
|
|||||||
8
lstate.h
8
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
|
** Global State
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
@@ -65,10 +65,10 @@ typedef struct global_State {
|
|||||||
lu_mem GCthreshold;
|
lu_mem GCthreshold;
|
||||||
lu_mem nblocks; /* number of `bytes' currently allocated */
|
lu_mem nblocks; /* number of `bytes' currently allocated */
|
||||||
Proto *rootproto; /* list of all prototypes */
|
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 */
|
Table *roottable; /* list of all tables */
|
||||||
Udata *rootudata; /* list of all userdata */
|
Udata *rootudata; /* list of all userdata */
|
||||||
TObject *rootupval; /* list of all up values */
|
UpVal *rootupval; /* list of closed up values */
|
||||||
} global_State;
|
} global_State;
|
||||||
|
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ struct lua_State {
|
|||||||
lua_Hook linehook;
|
lua_Hook linehook;
|
||||||
int allowhooks;
|
int allowhooks;
|
||||||
struct lua_longjmp *errorJmp; /* current error recover point */
|
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 *next; /* circular double linked list of states */
|
||||||
lua_State *previous;
|
lua_State *previous;
|
||||||
CallInfo basefunc;
|
CallInfo basefunc;
|
||||||
|
|||||||
9
lvm.c
9
lvm.c
@@ -390,8 +390,7 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) {
|
|||||||
}
|
}
|
||||||
case OP_GETUPVAL: {
|
case OP_GETUPVAL: {
|
||||||
int b = GETARG_B(i);
|
int b = GETARG_B(i);
|
||||||
lua_assert(isclosed(cl->upvals[b]) || cl->upvals[b] < base);
|
setobj(ra, cl->upvals[b]->v);
|
||||||
setobj(ra, cl->upvals[b]);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_GETGLOBAL: {
|
case OP_GETGLOBAL: {
|
||||||
@@ -410,8 +409,7 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) {
|
|||||||
}
|
}
|
||||||
case OP_SETUPVAL: {
|
case OP_SETUPVAL: {
|
||||||
int b = GETARG_B(i);
|
int b = GETARG_B(i);
|
||||||
lua_assert(isclosed(cl->upvals[b]) || cl->upvals[b] < base);
|
setobj(cl->upvals[b]->v, ra);
|
||||||
setobj(cl->upvals[b], ra);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_SETTABLE: {
|
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)];
|
ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];
|
||||||
else {
|
else {
|
||||||
lua_assert(GET_OPCODE(*pc) == OP_MOVE);
|
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);
|
setclvalue(ra, ncl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user