aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-11-29 18:22:22 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-11-29 18:22:22 -0200
commit413fc7334bf8ceaea71417d73edef15c99d3a793 (patch)
tree50e762d979ad8e80681902cdeb8aa42b041ae323
parentfca0a12e23f964006ce43d35ab86b27c6bbb0a48 (diff)
downloadlua-413fc7334bf8ceaea71417d73edef15c99d3a793.tar.gz
lua-413fc7334bf8ceaea71417d73edef15c99d3a793.tar.bz2
lua-413fc7334bf8ceaea71417d73edef15c99d3a793.zip
new implementation for lua upvalues (sugested by E.T.): simpler and solves
a bug for multi-stacks
-rw-r--r--ldo.c1
-rw-r--r--lfunc.c82
-rw-r--r--lfunc.h2
-rw-r--r--lgc.c50
-rw-r--r--lobject.h20
-rw-r--r--lstate.c7
-rw-r--r--lstate.h8
-rw-r--r--lvm.c9
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) {
215 Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z); 215 Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z);
216 Closure *cl = luaF_newLclosure(L, 0); 216 Closure *cl = luaF_newLclosure(L, 0);
217 cl->l.p = tf; 217 cl->l.p = tf;
218 luaF_LConlist(L, cl);
219 setclvalue(L->top, cl); 218 setclvalue(L->top, cl);
220 incr_top; 219 incr_top;
221} 220}
diff --git a/lfunc.c b/lfunc.c
index 8af857a8..25a8bb07 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -22,6 +22,7 @@
22 cast(int, sizeof(TObject *)*((n)-1))) 22 cast(int, sizeof(TObject *)*((n)-1)))
23 23
24 24
25
25Closure *luaF_newCclosure (lua_State *L, int nelems) { 26Closure *luaF_newCclosure (lua_State *L, int nelems) {
26 Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); 27 Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
27 c->c.isC = 1; 28 c->c.isC = 1;
@@ -36,76 +37,39 @@ Closure *luaF_newCclosure (lua_State *L, int nelems) {
36Closure *luaF_newLclosure (lua_State *L, int nelems) { 37Closure *luaF_newLclosure (lua_State *L, int nelems) {
37 Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); 38 Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
38 c->l.isC = 0; 39 c->l.isC = 0;
40 c->c.next = G(L)->rootcl;
41 G(L)->rootcl = c;
39 c->l.marked = 0; 42 c->l.marked = 0;
40 c->l.nupvalues = nelems; 43 c->l.nupvalues = nelems;
41 return c; 44 return c;
42} 45}
43 46
44 47
45/* 48UpVal *luaF_findupval (lua_State *L, StkId level) {
46** returns the open pointer in a closure that points higher into the stack 49 UpVal **pp = &L->openupval;
47*/ 50 UpVal *p;
48static StkId uppoint (LClosure *cl) { 51 while ((p = *pp) != NULL && p->v >= level) {
49 StkId lp = NULL; 52 if (p->v == level) return p;
50 int i; 53 pp = &p->next;
51 for (i=0; i<cl->nupvalues; i++) {
52 if (!isclosed(cl->upvals[i]) && (lp == NULL || cl->upvals[i] > lp))
53 lp = cl->upvals[i];
54 }
55 return lp;
56}
57
58
59void luaF_LConlist (lua_State *L, Closure *cl) {
60 StkId cli = uppoint(&cl->l);
61 if (cli == NULL) { /* no more open entries? */
62 cl->l.next = G(L)->rootcl; /* insert in final list */
63 G(L)->rootcl = cl;
64 }
65 else { /* insert in list of open closures, ordered by decreasing uppoints */
66 Closure **p = &L->opencl;
67 while (*p != NULL && uppoint(&(*p)->l) > cli) p = &(*p)->l.next;
68 cl->l.next = *p;
69 *p = cl;
70 } 54 }
71} 55 p = luaM_new(L, UpVal); /* not found: create a new one */
72 56 p->v = level; /* current value lives in the stack */
73 57 p->mark = 1; /* won't participate in GC while open */
74static int closeCl (lua_State *L, LClosure *cl, StkId level) { 58 p->next = *pp; /* chain it in the proper position */
75 int got = 0; /* flag: 1 if some pointer in the closure was corrected */ 59 *pp = p;
76 int i; 60 return p;
77 for (i=0; i<cl->nupvalues; i++) {
78 StkId var;
79 if (!isclosed(cl->upvals[i]) && (var=cl->upvals[i]) >= level) {
80 if (ttype(var) != LUA_TUPVAL) {
81 TObject *v = luaM_newvector(L, 2, TObject);
82 v[1] = *var;
83 setupvalue(v, G(L)->rootupval, LUA_HEAPUPVAL);
84 G(L)->rootupval = v;
85 setupvalue(var, &v[1], LUA_TUPVAL);
86 }
87 cl->upvals[i] = vvalue(var);
88 got = 1;
89 }
90 }
91 return got;
92} 61}
93 62
94 63
95void luaF_close (lua_State *L, StkId level) { 64void luaF_close (lua_State *L, StkId level) {
96 Closure *affected = NULL; /* closures with open pointers >= level */ 65 UpVal *p;
97 Closure *cl; 66 while ((p = L->openupval) != NULL && p->v >= level) {
98 while ((cl=L->opencl) != NULL) { 67 setobj(&p->value, p->v); /* save current value */
99 if (!closeCl(L, cast(LClosure *, cl), level)) break; 68 p->v = &p->value; /* now current value lives here */
100 /* some pointer in `cl' changed; will re-insert it in original list */ 69 L->openupval = p->next; /* remove from `open' list */
101 L->opencl = cl->l.next; /* remove from original list */ 70 p->next = G(L)->rootupval; /* chain in `closed' list */
102 cl->l.next = affected; 71 p->mark = 0; /* now it can be collected */
103 affected = cl; /* insert in affected list */ 72 G(L)->rootupval = p;
104 }
105 /* re-insert all affected closures in original list */
106 while ((cl=affected) != NULL) {
107 affected = cl->l.next;
108 luaF_LConlist(L, cl);
109 } 73 }
110} 74}
111 75
diff --git a/lfunc.h b/lfunc.h
index 111e554c..f57df4c2 100644
--- a/lfunc.h
+++ b/lfunc.h
@@ -14,7 +14,7 @@
14Proto *luaF_newproto (lua_State *L); 14Proto *luaF_newproto (lua_State *L);
15Closure *luaF_newCclosure (lua_State *L, int nelems); 15Closure *luaF_newCclosure (lua_State *L, int nelems);
16Closure *luaF_newLclosure (lua_State *L, int nelems); 16Closure *luaF_newLclosure (lua_State *L, int nelems);
17void luaF_LConlist (lua_State *L, Closure *cl); 17UpVal *luaF_findupval (lua_State *L, StkId level);
18void luaF_close (lua_State *L, StkId level); 18void luaF_close (lua_State *L, StkId level);
19void luaF_freeproto (lua_State *L, Proto *f); 19void luaF_freeproto (lua_State *L, Proto *f);
20void luaF_freeclosure (lua_State *L, Closure *c); 20void 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) {
65 lua_assert(cl->l.nupvalues == cl->l.p->nupvalues); 65 lua_assert(cl->l.nupvalues == cl->l.p->nupvalues);
66 protomark(cl->l.p); 66 protomark(cl->l.p);
67 for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ 67 for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
68 TObject *u = cl->l.upvals[i]; 68 UpVal *u = cl->l.upvals[i];
69 if (isclosed(u)) { 69 if (!u->mark) {
70 ttype(u-1) = LUA_TNIL; /* temporary value (to mark as visited) */ 70 u->mark = 1;
71 markobject(st, u); 71 markobject(st, u->v);
72 } 72 }
73 } 73 }
74 } 74 }
@@ -101,7 +101,7 @@ static void markobject (GCState *st, TObject *o) {
101 break; 101 break;
102 } 102 }
103 default: { 103 default: {
104 lua_assert(0 <= ttype(o) && ttype(o) <= LUA_TUPVAL); 104 lua_assert(ttype(o) == LUA_TNIL || ttype(o) == LUA_TNUMBER);
105 break; 105 break;
106 } 106 }
107 } 107 }
@@ -241,7 +241,8 @@ static void collectproto (lua_State *L) {
241} 241}
242 242
243 243
244static void collectclosure (lua_State *L, Closure **p) { 244static void collectclosures (lua_State *L) {
245 Closure **p = &G(L)->rootcl;
245 Closure *curr; 246 Closure *curr;
246 while ((curr = *p) != NULL) { 247 while ((curr = *p) != NULL) {
247 if (curr->c.marked) { 248 if (curr->c.marked) {
@@ -256,13 +257,19 @@ static void collectclosure (lua_State *L, Closure **p) {
256} 257}
257 258
258 259
259static void collectclosures (lua_State *L) { 260static void collectupval (lua_State *L) {
260 lua_State *L1 = L; 261 UpVal **v = &G(L)->rootupval;
261 do { /* for each thread */ 262 UpVal *curr;
262 collectclosure(L1, &L1->opencl); 263 while ((curr = *v) != NULL) {
263 L1 = L1->next; 264 if (curr->mark) {
264 } while (L1 != L); 265 curr->mark = 0;
265 collectclosure(L, &G(L)->rootcl); 266 v = &curr->next; /* next */
267 }
268 else {
269 *v = curr->next; /* next */
270 luaM_freelem(L, curr);
271 }
272 }
266} 273}
267 274
268 275
@@ -282,23 +289,6 @@ static void collecttable (lua_State *L) {
282} 289}
283 290
284 291
285static void collectupval (lua_State *L) {
286 TObject **v = &G(L)->rootupval;
287 TObject *curr;
288 while ((curr = *v) != NULL) {
289 if (ttype(curr) == LUA_TNIL) { /* was marked? */
290 ttype(curr) = LUA_HEAPUPVAL; /* unmark */
291 v = &vvalue(curr); /* next */
292 }
293 else {
294 lua_assert(ttype(curr) == LUA_HEAPUPVAL);
295 *v = vvalue(curr); /* next */
296 luaM_freearray(L, curr, 2, TObject);
297 }
298 }
299}
300
301
302static void collectudata (lua_State *L, int keep) { 292static void collectudata (lua_State *L, int keep) {
303 Udata **p = &G(L)->rootudata; 293 Udata **p = &G(L)->rootudata;
304 Udata *curr; 294 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 {
170 170
171 171
172/* 172/*
173** Upvalues in the heap. There is a small trick here: to allow a closure to 173** Upvalues
174** diferentiate between upvalues in the heap and in the stack, upvalues in
175** the heap always have another TObject before them (like those in the stack),
176** but those `prefix' objects have a tag that cannot happen in the stack.
177** Moreover, we use these extra `prexif' object to store GC-related
178** information.
179*/ 174*/
180 175
181#define isclosed(u) (ttype((u)-1) == LUA_HEAPUPVAL) 176typedef struct UpVal {
177 TObject *v; /* points to stack or to its own value */
178 int mark;
179 struct UpVal *next;
180 TObject value; /* the value (when closed) */
181} UpVal;
182 182
183 183
184/* 184/*
@@ -201,7 +201,7 @@ typedef struct LClosure {
201 lu_byte marked; 201 lu_byte marked;
202 union Closure *next; /* first four fields must be equal to CClosure!! */ 202 union Closure *next; /* first four fields must be equal to CClosure!! */
203 struct Proto *p; 203 struct Proto *p;
204 TObject *upvals[1]; 204 UpVal *upvals[1];
205} LClosure; 205} LClosure;
206 206
207 207
@@ -221,8 +221,8 @@ typedef union Closure {
221 221
222typedef struct Node { 222typedef struct Node {
223 struct Node *next; /* for chaining */ 223 struct Node *next; /* for chaining */
224 TObject key; 224 TObject _key;
225 TObject val; 225 TObject _val;
226} Node; 226} Node;
227 227
228 228
diff --git a/lstate.c b/lstate.c
index a9130455..6e2ba8f1 100644
--- a/lstate.c
+++ b/lstate.c
@@ -10,6 +10,7 @@
10#include "lua.h" 10#include "lua.h"
11 11
12#include "ldo.h" 12#include "ldo.h"
13#include "lfunc.h"
13#include "lgc.h" 14#include "lgc.h"
14#include "llex.h" 15#include "llex.h"
15#include "lmem.h" 16#include "lmem.h"
@@ -88,7 +89,7 @@ LUA_API lua_State *lua_newthread (lua_State *OL, int stacksize) {
88 L->errorJmp = NULL; 89 L->errorJmp = NULL;
89 L->callhook = NULL; 90 L->callhook = NULL;
90 L->linehook = NULL; 91 L->linehook = NULL;
91 L->opencl = NULL; 92 L->openupval = NULL;
92 L->allowhooks = 1; 93 L->allowhooks = 1;
93 L->next = L->previous = L; 94 L->next = L->previous = L;
94 so.stacksize = stacksize; 95 so.stacksize = stacksize;
@@ -105,6 +106,8 @@ LUA_API lua_State *lua_newthread (lua_State *OL, int stacksize) {
105 106
106 107
107static void close_state (lua_State *L, lua_State *OL) { 108static void close_state (lua_State *L, lua_State *OL) {
109 luaF_close(L, L->stack); /* close all upvalues for this thread */
110 lua_assert(L->openupval == NULL);
108 if (OL != NULL) { /* are there other threads? */ 111 if (OL != NULL) { /* are there other threads? */
109 lua_assert(L->previous != L); 112 lua_assert(L->previous != L);
110 L->previous->next = L->next; 113 L->previous->next = L->next;
@@ -116,6 +119,7 @@ static void close_state (lua_State *L, lua_State *OL) {
116 lua_assert(G(L)->rootproto == NULL); 119 lua_assert(G(L)->rootproto == NULL);
117 lua_assert(G(L)->rootudata == NULL); 120 lua_assert(G(L)->rootudata == NULL);
118 lua_assert(G(L)->rootcl == NULL); 121 lua_assert(G(L)->rootcl == NULL);
122 lua_assert(G(L)->rootupval == NULL);
119 lua_assert(G(L)->roottable == NULL); 123 lua_assert(G(L)->roottable == NULL);
120 luaS_freeall(L); 124 luaS_freeall(L);
121 luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM); 125 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) {
126 luaM_freelem(OL, L); 130 luaM_freelem(OL, L);
127} 131}
128 132
133
129LUA_API void lua_close (lua_State *L) { 134LUA_API void lua_close (lua_State *L) {
130 lua_State *OL; 135 lua_State *OL;
131 lua_assert(L != lua_state || lua_gettop(L) == 0); 136 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 @@
1/* 1/*
2** $Id: lstate.h,v 1.63 2001/10/31 19:58:11 roberto Exp $ 2** $Id: lstate.h,v 1.64 2001/11/06 21:40:51 roberto Exp $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -65,10 +65,10 @@ typedef struct global_State {
65 lu_mem GCthreshold; 65 lu_mem GCthreshold;
66 lu_mem nblocks; /* number of `bytes' currently allocated */ 66 lu_mem nblocks; /* number of `bytes' currently allocated */
67 Proto *rootproto; /* list of all prototypes */ 67 Proto *rootproto; /* list of all prototypes */
68 Closure *rootcl; /* list of all C closures and closed Lua closures */ 68 Closure *rootcl; /* list of all closures */
69 Table *roottable; /* list of all tables */ 69 Table *roottable; /* list of all tables */
70 Udata *rootudata; /* list of all userdata */ 70 Udata *rootudata; /* list of all userdata */
71 TObject *rootupval; /* list of all up values */ 71 UpVal *rootupval; /* list of closed up values */
72} global_State; 72} global_State;
73 73
74 74
@@ -88,7 +88,7 @@ struct lua_State {
88 lua_Hook linehook; 88 lua_Hook linehook;
89 int allowhooks; 89 int allowhooks;
90 struct lua_longjmp *errorJmp; /* current error recover point */ 90 struct lua_longjmp *errorJmp; /* current error recover point */
91 Closure *opencl; /* list of closures still pointing to this stack */ 91 UpVal *openupval; /* list of open upvalues in this stack */
92 lua_State *next; /* circular double linked list of states */ 92 lua_State *next; /* circular double linked list of states */
93 lua_State *previous; 93 lua_State *previous;
94 CallInfo basefunc; 94 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) {
390 } 390 }
391 case OP_GETUPVAL: { 391 case OP_GETUPVAL: {
392 int b = GETARG_B(i); 392 int b = GETARG_B(i);
393 lua_assert(isclosed(cl->upvals[b]) || cl->upvals[b] < base); 393 setobj(ra, cl->upvals[b]->v);
394 setobj(ra, cl->upvals[b]);
395 break; 394 break;
396 } 395 }
397 case OP_GETGLOBAL: { 396 case OP_GETGLOBAL: {
@@ -410,8 +409,7 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) {
410 } 409 }
411 case OP_SETUPVAL: { 410 case OP_SETUPVAL: {
412 int b = GETARG_B(i); 411 int b = GETARG_B(i);
413 lua_assert(isclosed(cl->upvals[b]) || cl->upvals[b] < base); 412 setobj(cl->upvals[b]->v, ra);
414 setobj(cl->upvals[b], ra);
415 break; 413 break;
416 } 414 }
417 case OP_SETTABLE: { 415 case OP_SETTABLE: {
@@ -648,10 +646,9 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) {
648 ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)]; 646 ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];
649 else { 647 else {
650 lua_assert(GET_OPCODE(*pc) == OP_MOVE); 648 lua_assert(GET_OPCODE(*pc) == OP_MOVE);
651 ncl->l.upvals[j] = base + GETARG_B(*pc); 649 ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));
652 } 650 }
653 } 651 }
654 luaF_LConlist(L, ncl);
655 setclvalue(ra, ncl); 652 setclvalue(ra, ncl);
656 break; 653 break;
657 } 654 }