summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-10-02 13:45:03 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-10-02 13:45:03 -0300
commit15462edb0ff86bf1904011b29635420451cab2c5 (patch)
tree9a626d34736b830f83fda3f1b2f3342990a05b1f
parent6f936bc7931662d0460d47ad73eca308ba5fab2f (diff)
downloadlua-15462edb0ff86bf1904011b29635420451cab2c5.tar.gz
lua-15462edb0ff86bf1904011b29635420451cab2c5.tar.bz2
lua-15462edb0ff86bf1904011b29635420451cab2c5.zip
new definitions for closure structures
-rw-r--r--lapi.c8
-rw-r--r--ldebug.c18
-rw-r--r--ldo.c15
-rw-r--r--lfunc.c62
-rw-r--r--lfunc.h7
-rw-r--r--lgc.c78
-rw-r--r--llimits.h9
-rw-r--r--lobject.h54
-rw-r--r--ltests.c8
-rw-r--r--lvm.c30
-rw-r--r--lvm.h4
11 files changed, 137 insertions, 156 deletions
diff --git a/lapi.c b/lapi.c
index 5c54c60c..8c093685 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.c,v 1.149 2001/07/22 00:59:36 roberto Exp roberto $ 2** $Id: lapi.c,v 1.152 2001/09/07 17:39:10 roberto Exp $
3** Lua API 3** Lua API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -248,7 +248,7 @@ LUA_API size_t lua_strlen (lua_State *L, int index) {
248 248
249LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index) { 249LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index) {
250 StkId o = luaA_indexAcceptable(L, index); 250 StkId o = luaA_indexAcceptable(L, index);
251 return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->u.c.f; 251 return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->c.f;
252} 252}
253 253
254 254
@@ -314,10 +314,10 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
314 lua_lock(L); 314 lua_lock(L);
315 api_checknelems(L, n); 315 api_checknelems(L, n);
316 cl = luaF_newCclosure(L, n); 316 cl = luaF_newCclosure(L, n);
317 cl->u.c.f = fn; 317 cl->c.f = fn;
318 L->top -= n; 318 L->top -= n;
319 while (n--) 319 while (n--)
320 setobj(&cl->u.c.upvalue[n], L->top+n); 320 setobj(&cl->c.upvalue[n], L->top+n);
321 setclvalue(L->top, cl); 321 setclvalue(L->top, cl);
322 incr_top; 322 incr_top;
323 lua_unlock(L); 323 lua_unlock(L);
diff --git a/ldebug.c b/ldebug.c
index cf397bd2..5ddf3d0a 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -33,7 +33,7 @@ static const l_char *getfuncname (lua_State *L, CallInfo *ci,
33 33
34static int isLmark (CallInfo *ci) { 34static int isLmark (CallInfo *ci) {
35 lua_assert(ci == NULL || ttype(ci->base - 1) == LUA_TFUNCTION); 35 lua_assert(ci == NULL || ttype(ci->base - 1) == LUA_TFUNCTION);
36 return (ci && ci->prev && !ci_func(ci)->isC); 36 return (ci && ci->prev && !ci_func(ci)->c.isC);
37} 37}
38 38
39 39
@@ -117,7 +117,7 @@ int luaG_getline (int *lineinfo, int pc, int refline, int *prefi) {
117static int currentpc (CallInfo *ci) { 117static int currentpc (CallInfo *ci) {
118 lua_assert(isLmark(ci)); 118 lua_assert(isLmark(ci));
119 if (ci->pc) 119 if (ci->pc)
120 return (*ci->pc - ci_func(ci)->u.l.p->code) - 1; 120 return (*ci->pc - ci_func(ci)->l.p->code) - 1;
121 else 121 else
122 return -1; /* function is not active */ 122 return -1; /* function is not active */
123} 123}
@@ -127,7 +127,7 @@ static int currentline (CallInfo *ci) {
127 if (!isLmark(ci)) 127 if (!isLmark(ci))
128 return -1; /* only active lua functions have current-line information */ 128 return -1; /* only active lua functions have current-line information */
129 else { 129 else {
130 int *lineinfo = ci_func(ci)->u.l.p->lineinfo; 130 int *lineinfo = ci_func(ci)->l.p->lineinfo;
131 return luaG_getline(lineinfo, currentpc(ci), 1, NULL); 131 return luaG_getline(lineinfo, currentpc(ci), 1, NULL);
132 } 132 }
133} 133}
@@ -135,7 +135,7 @@ static int currentline (CallInfo *ci) {
135 135
136 136
137static Proto *getluaproto (CallInfo *ci) { 137static Proto *getluaproto (CallInfo *ci) {
138 return (isLmark(ci) ? ci_func(ci)->u.l.p : NULL); 138 return (isLmark(ci) ? ci_func(ci)->l.p : NULL);
139} 139}
140 140
141 141
@@ -193,13 +193,13 @@ static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) {
193 luaD_error(L, l_s("value for `lua_getinfo' is not a function")); 193 luaD_error(L, l_s("value for `lua_getinfo' is not a function"));
194 cl = NULL; /* to avoid warnings */ 194 cl = NULL; /* to avoid warnings */
195 } 195 }
196 if (cl->isC) { 196 if (cl->c.isC) {
197 ar->source = l_s("=C"); 197 ar->source = l_s("=C");
198 ar->linedefined = -1; 198 ar->linedefined = -1;
199 ar->what = l_s("C"); 199 ar->what = l_s("C");
200 } 200 }
201 else 201 else
202 infoLproto(ar, cl->u.l.p); 202 infoLproto(ar, cl->l.p);
203 luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); 203 luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
204 if (ar->linedefined == 0) 204 if (ar->linedefined == 0)
205 ar->what = l_s("main"); 205 ar->what = l_s("main");
@@ -268,7 +268,7 @@ LUA_API int lua_getinfo (lua_State *L, const l_char *what, lua_Debug *ar) {
268 break; 268 break;
269 } 269 }
270 case l_c('u'): { 270 case l_c('u'): {
271 ar->nups = (ttype(f) == LUA_TFUNCTION) ? clvalue(f)->nupvalues : 0; 271 ar->nups = (ttype(f) == LUA_TFUNCTION) ? clvalue(f)->c.nupvalues : 0;
272 break; 272 break;
273 } 273 }
274 case l_c('n'): { 274 case l_c('n'): {
@@ -473,7 +473,7 @@ int luaG_checkcode (const Proto *pt) {
473static const l_char *getobjname (lua_State *L, StkId obj, const l_char **name) { 473static const l_char *getobjname (lua_State *L, StkId obj, const l_char **name) {
474 CallInfo *ci = ci_stack(L, obj); 474 CallInfo *ci = ci_stack(L, obj);
475 if (isLmark(ci)) { /* an active Lua function? */ 475 if (isLmark(ci)) { /* an active Lua function? */
476 Proto *p = ci_func(ci)->u.l.p; 476 Proto *p = ci_func(ci)->l.p;
477 int pc = currentpc(ci); 477 int pc = currentpc(ci);
478 int stackpos = obj - ci->base; 478 int stackpos = obj - ci->base;
479 Instruction i; 479 Instruction i;
@@ -517,7 +517,7 @@ static const l_char *getfuncname (lua_State *L, CallInfo *ci,
517 if (ci == &L->basefunc || !isLmark(ci)) 517 if (ci == &L->basefunc || !isLmark(ci))
518 return NULL; /* not an active Lua function */ 518 return NULL; /* not an active Lua function */
519 else { 519 else {
520 Proto *p = ci_func(ci)->u.l.p; 520 Proto *p = ci_func(ci)->l.p;
521 int pc = currentpc(ci); 521 int pc = currentpc(ci);
522 Instruction i; 522 Instruction i;
523 if (pc == -1) return NULL; /* function is not activated */ 523 if (pc == -1) return NULL; /* function is not activated */
diff --git a/ldo.c b/ldo.c
index ee055a8f..60e5dc2e 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 1.140 2001/09/07 17:39:10 roberto Exp $ 2** $Id: ldo.c,v 1.141 2001/09/25 17:05:49 roberto Exp $
3** Stack and Call structure of Lua 3** Stack and Call structure of Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -118,14 +118,14 @@ static void luaD_callHook (lua_State *L, lua_Hook callhook,
118} 118}
119 119
120 120
121static StkId callCclosure (lua_State *L, const struct Closure *cl) { 121static StkId callCclosure (lua_State *L, const struct CClosure *cl) {
122 int nup = cl->nupvalues; /* number of upvalues */ 122 int nup = cl->nupvalues; /* number of upvalues */
123 int n; 123 int n;
124 luaD_checkstack(L, nup+LUA_MINSTACK); /* ensure minimum stack size */ 124 luaD_checkstack(L, nup+LUA_MINSTACK); /* ensure minimum stack size */
125 for (n=0; n<nup; n++) /* copy upvalues as extra arguments */ 125 for (n=0; n<nup; n++) /* copy upvalues as extra arguments */
126 setobj(L->top++, &cl->u.c.upvalue[n]); 126 setobj(L->top++, &cl->upvalue[n]);
127 lua_unlock(L); 127 lua_unlock(L);
128 n = (*cl->u.c.f)(L); /* do the actual call */ 128 n = (*cl->f)(L); /* do the actual call */
129 lua_lock(L); 129 lua_lock(L);
130 return L->top - n; /* return index of first result */ 130 return L->top - n; /* return index of first result */
131} 131}
@@ -155,8 +155,9 @@ void luaD_call (lua_State *L, StkId func) {
155 callhook = L->callhook; 155 callhook = L->callhook;
156 if (callhook) 156 if (callhook)
157 luaD_callHook(L, callhook, l_s("call")); 157 luaD_callHook(L, callhook, l_s("call"));
158 firstResult = (clvalue(func)->isC ? callCclosure(L, clvalue(func)) : 158 firstResult = (clvalue(func)->c.isC ?
159 luaV_execute(L, clvalue(func), func+1)); 159 callCclosure(L, &clvalue(func)->c) :
160 luaV_execute(L, &clvalue(func)->l, func+1));
160 if (callhook) /* same hook that was active at entry */ 161 if (callhook) /* same hook that was active at entry */
161 luaD_callHook(L, callhook, l_s("return")); 162 luaD_callHook(L, callhook, l_s("return"));
162 L->ci = ci.prev; /* unchain callinfo */ 163 L->ci = ci.prev; /* unchain callinfo */
@@ -213,7 +214,7 @@ static void f_parser (lua_State *L, void *ud) {
213 struct SParser *p = cast(struct SParser *, ud); 214 struct SParser *p = cast(struct SParser *, ud);
214 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);
215 Closure *cl = luaF_newLclosure(L, 0); 216 Closure *cl = luaF_newLclosure(L, 0);
216 cl->u.l.p = tf; 217 cl->l.p = tf;
217 luaF_LConlist(L, cl); 218 luaF_LConlist(L, cl);
218 setclvalue(L->top, cl); 219 setclvalue(L->top, cl);
219 incr_top; 220 incr_top;
diff --git a/lfunc.c b/lfunc.c
index 8c197499..bed67101 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lfunc.c,v 1.45 2001/06/28 14:57:17 roberto Exp $ 2** $Id: lfunc.c,v 1.47 2001/09/07 17:39:10 roberto Exp $
3** Auxiliary functions to manipulate prototypes and closures 3** Auxiliary functions to manipulate prototypes and closures
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -16,30 +16,29 @@
16#include "lstate.h" 16#include "lstate.h"
17 17
18 18
19#define sizeCclosure(n) (cast(int, sizeof(Closure)) + \ 19#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \
20 cast(int, sizeof(TObject)*((n)-1))) 20 cast(int, sizeof(TObject)*((n)-1)))
21 21
22#define sizeLclosure(n) (cast(int, sizeof(Closure)) + \ 22#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
23 cast(int, sizeof(TObject *)*((n)-1))) 23 cast(int, sizeof(LClosureEntry)*((n)-1)))
24 24
25 25
26Closure *luaF_newCclosure (lua_State *L, int nelems) { 26Closure *luaF_newCclosure (lua_State *L, int nelems) {
27 Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); 27 Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));
28 c->isC = 1; 28 c->c.isC = 1;
29 c->next = G(L)->rootcl; 29 c->c.next = G(L)->rootcl;
30 G(L)->rootcl = c; 30 G(L)->rootcl = c;
31 c->mark = c; 31 c->c.marked = 0;
32 c->nupvalues = nelems; 32 c->c.nupvalues = nelems;
33 return c; 33 return c;
34} 34}
35 35
36 36
37Closure *luaF_newLclosure (lua_State *L, int nelems) { 37Closure *luaF_newLclosure (lua_State *L, int nelems) {
38 Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); 38 Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));
39 c->isC = 0; 39 c->l.isC = 0;
40 c->mark = c; 40 c->l.marked = 0;
41 c->u.l.isopen = 0; 41 c->l.nupvalues = nelems;
42 c->nupvalues = nelems;
43 return c; 42 return c;
44} 43}
45 44
@@ -47,42 +46,38 @@ Closure *luaF_newLclosure (lua_State *L, int nelems) {
47/* 46/*
48** returns the open pointer in a closure that points higher into the stack 47** returns the open pointer in a closure that points higher into the stack
49*/ 48*/
50static StkId uppoint (Closure *cl) { 49static StkId uppoint (LClosure *cl) {
51 StkId lp = NULL; 50 StkId lp = NULL;
52 int i; 51 int i;
53 lua_assert(cl->u.l.isopen);
54 for (i=0; i<cl->nupvalues; i++) { 52 for (i=0; i<cl->nupvalues; i++) {
55 if (!luaF_isclosed(cl, i)) 53 if (cl->upvals[i].heap == NULL && (lp == NULL || cl->upvals[i].val > lp))
56 if (lp == NULL || cl->u.l.upvals[i] > lp) 54 lp = cl->upvals[i].val;
57 lp = cl->u.l.upvals[i];
58 } 55 }
59 lua_assert(lp != NULL);
60 return lp; 56 return lp;
61} 57}
62 58
63 59
64void luaF_LConlist (lua_State *L, Closure *cl) { 60void luaF_LConlist (lua_State *L, Closure *cl) {
65 lua_assert(!cl->isC); 61 StkId cli = uppoint(&cl->l);
66 if (cl->u.l.isopen == 0) { /* no more open entries? */ 62 if (cli == NULL) { /* no more open entries? */
67 cl->next = G(L)->rootcl; /* insert in final list */ 63 cl->l.next = G(L)->rootcl; /* insert in final list */
68 G(L)->rootcl = cl; 64 G(L)->rootcl = cl;
69 } 65 }
70 else { /* insert in list of open closures, ordered by decreasing uppoints */ 66 else { /* insert in list of open closures, ordered by decreasing uppoints */
71 StkId cli = uppoint(cl);
72 Closure **p = &L->opencl; 67 Closure **p = &L->opencl;
73 while (*p != NULL && uppoint(*p) > cli) p = &(*p)->next; 68 while (*p != NULL && uppoint(&(*p)->l) > cli) p = &(*p)->l.next;
74 cl->next = *p; 69 cl->l.next = *p;
75 *p = cl; 70 *p = cl;
76 } 71 }
77} 72}
78 73
79 74
80static int closeCl (lua_State *L, Closure *cl, StkId level) { 75static int closeCl (lua_State *L, LClosure *cl, StkId level) {
81 int got = 0; /* flag: 1 if some pointer in the closure was corrected */ 76 int got = 0; /* flag: 1 if some pointer in the closure was corrected */
82 int i; 77 int i;
83 for (i=0; i<cl->nupvalues; i++) { 78 for (i=0; i<cl->nupvalues; i++) {
84 StkId var; 79 StkId var;
85 if (!luaF_isclosed(cl, i) && (var=cl->u.l.upvals[i]) >= level) { 80 if (cl->upvals[i].heap == NULL && (var=cl->upvals[i].val) >= level) {
86 if (ttype(var) != LUA_TUPVAL) { 81 if (ttype(var) != LUA_TUPVAL) {
87 UpVal *v = luaM_new(L, UpVal); 82 UpVal *v = luaM_new(L, UpVal);
88 v->val = *var; 83 v->val = *var;
@@ -91,8 +86,8 @@ static int closeCl (lua_State *L, Closure *cl, StkId level) {
91 G(L)->rootupval = v; 86 G(L)->rootupval = v;
92 setupvalue(var, v); 87 setupvalue(var, v);
93 } 88 }
94 cl->u.l.upvals[i] = cast(TObject *, vvalue(var)); 89 cl->upvals[i].heap = vvalue(var);
95 luaF_closeentry(cl, i); 90 cl->upvals[i].val = &vvalue(var)->val;
96 got = 1; 91 got = 1;
97 } 92 }
98 } 93 }
@@ -104,15 +99,15 @@ void luaF_close (lua_State *L, StkId level) {
104 Closure *affected = NULL; /* closures with open pointers >= level */ 99 Closure *affected = NULL; /* closures with open pointers >= level */
105 Closure *cl; 100 Closure *cl;
106 while ((cl=L->opencl) != NULL) { 101 while ((cl=L->opencl) != NULL) {
107 if (!closeCl(L, cl, level)) break; 102 if (!closeCl(L, cast(LClosure *, cl), level)) break;
108 /* some pointer in `cl' changed; will re-insert it in original list */ 103 /* some pointer in `cl' changed; will re-insert it in original list */
109 L->opencl = cl->next; /* remove from original list */ 104 L->opencl = cl->l.next; /* remove from original list */
110 cl->next = affected; 105 cl->l.next = affected;
111 affected = cl; /* insert in affected list */ 106 affected = cl; /* insert in affected list */
112 } 107 }
113 /* re-insert all affected closures in original list */ 108 /* re-insert all affected closures in original list */
114 while ((cl=affected) != NULL) { 109 while ((cl=affected) != NULL) {
115 affected = cl->next; 110 affected = cl->l.next;
116 luaF_LConlist(L, cl); 111 luaF_LConlist(L, cl);
117 } 112 }
118} 113}
@@ -154,7 +149,8 @@ void luaF_freeproto (lua_State *L, Proto *f) {
154 149
155 150
156void luaF_freeclosure (lua_State *L, Closure *c) { 151void luaF_freeclosure (lua_State *L, Closure *c) {
157 int size = (c->isC) ? sizeCclosure(c->nupvalues) : sizeLclosure(c->nupvalues); 152 int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :
153 sizeLclosure(c->l.nupvalues);
158 luaM_free(L, c, size); 154 luaM_free(L, c, size);
159} 155}
160 156
diff --git a/lfunc.h b/lfunc.h
index 385767a2..d7506f84 100644
--- a/lfunc.h
+++ b/lfunc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lfunc.h,v 1.15 2001/02/23 17:17:25 roberto Exp $ 2** $Id: lfunc.h,v 1.16 2001/09/07 17:39:10 roberto Exp $
3** Auxiliary functions to manipulate prototypes and closures 3** Auxiliary functions to manipulate prototypes and closures
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -11,11 +11,6 @@
11#include "lobject.h" 11#include "lobject.h"
12 12
13 13
14#define luaF_isclosed(c, i) (!((c)->u.l.isopen & (1 << (i))))
15#define luaF_openentry(c, i) ((c)->u.l.isopen |= (1 << (i)))
16#define luaF_closeentry(c, i) ((c)->u.l.isopen &= ~(1 << (i)))
17
18
19Proto *luaF_newproto (lua_State *L); 14Proto *luaF_newproto (lua_State *L);
20Closure *luaF_newCclosure (lua_State *L, int nelems); 15Closure *luaF_newCclosure (lua_State *L, int nelems);
21Closure *luaF_newLclosure (lua_State *L, int nelems); 16Closure *luaF_newLclosure (lua_State *L, int nelems);
diff --git a/lgc.c b/lgc.c
index 20d97cf2..cb08df35 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.109 2001/06/28 14:57:17 roberto Exp $ 2** $Id: lgc.c,v 1.111 2001/09/07 17:39:10 roberto Exp $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -22,7 +22,6 @@
22 22
23typedef struct GCState { 23typedef struct GCState {
24 Hash *tmark; /* list of marked tables to be visited */ 24 Hash *tmark; /* list of marked tables to be visited */
25 Closure *cmark; /* list of marked closures to be visited */
26} GCState; 25} GCState;
27 26
28 27
@@ -32,6 +31,9 @@ typedef struct GCState {
32 31
33 32
34 33
34static void markobject (GCState *st, TObject *o);
35
36
35static void protomark (Proto *f) { 37static void protomark (Proto *f) {
36 if (!f->marked) { 38 if (!f->marked) {
37 int i; 39 int i;
@@ -51,9 +53,25 @@ static void protomark (Proto *f) {
51 53
52 54
53static void markclosure (GCState *st, Closure *cl) { 55static void markclosure (GCState *st, Closure *cl) {
54 if (!ismarked(cl)) { 56 if (!cl->c.marked) {
55 cl->mark = st->cmark; /* chain it for later traversal */ 57 cl->c.marked = 1;
56 st->cmark = cl; 58 if (cl->c.isC) {
59 int i;
60 for (i=0; i<cl->c.nupvalues; i++) /* mark its upvalues */
61 markobject(st, &cl->c.upvalue[i]);
62 }
63 else {
64 int i;
65 lua_assert(cl->l.nupvalues == cl->l.p->nupvalues);
66 protomark(cl->l.p);
67 for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
68 UpVal *u = cl->l.upvals[i].heap;
69 if (u && !u->marked) {
70 u->marked = 1;
71 markobject(st, &u->val);
72 }
73 }
74 }
57 } 75 }
58} 76}
59 77
@@ -120,29 +138,6 @@ static void marktagmethods (global_State *G, GCState *st) {
120} 138}
121 139
122 140
123static void traverseclosure (GCState *st, Closure *cl) {
124 if (cl->isC) {
125 int i;
126 for (i=0; i<cl->nupvalues; i++) /* mark its upvalues */
127 markobject(st, &cl->u.c.upvalue[i]);
128 }
129 else {
130 int i;
131 lua_assert(cl->nupvalues == cl->u.l.p->nupvalues);
132 protomark(cl->u.l.p);
133 for (i=0; i<cl->nupvalues; i++) { /* mark its upvalues */
134 if (luaF_isclosed(cl, i)) {
135 UpVal *u = cast(UpVal *, cl->u.l.upvals[i]);
136 if (!u->marked) {
137 u->marked = 1;
138 markobject(st, &u->val);
139 }
140 }
141 }
142 }
143}
144
145
146static void removekey (Node *n) { 141static void removekey (Node *n) {
147 lua_assert(ttype(val(n)) == LUA_TNIL); 142 lua_assert(ttype(val(n)) == LUA_TNIL);
148 if (ttype(key(n)) != LUA_TNIL && ttype(key(n)) != LUA_TNUMBER) 143 if (ttype(key(n)) != LUA_TNIL && ttype(key(n)) != LUA_TNUMBER)
@@ -172,25 +167,16 @@ static void traversetable (GCState *st, Hash *h) {
172 167
173static void markall (lua_State *L) { 168static void markall (lua_State *L) {
174 GCState st; 169 GCState st;
175 st.cmark = NULL;
176 st.tmark = NULL; 170 st.tmark = NULL;
177 marktagmethods(G(L), &st); /* mark tag methods */ 171 marktagmethods(G(L), &st); /* mark tag methods */
178 markstacks(L, &st); /* mark all stacks */ 172 markstacks(L, &st); /* mark all stacks */
179 marktable(&st, G(L)->type2tag); 173 marktable(&st, G(L)->type2tag);
180 marktable(&st, G(L)->registry); 174 marktable(&st, G(L)->registry);
181 marktable(&st, G(L)->weakregistry); 175 marktable(&st, G(L)->weakregistry);
182 for (;;) { /* mark tables and closures */ 176 while (st.tmark) { /* mark tables */
183 if (st.cmark) { 177 Hash *h = st.tmark; /* get first table from list */
184 Closure *cl = st.cmark; /* get first closure from list */ 178 st.tmark = h->mark; /* remove it from list */
185 st.cmark = cl->mark; /* remove it from list */ 179 traversetable(&st, h);
186 traverseclosure(&st, cl);
187 }
188 else if (st.tmark) {
189 Hash *h = st.tmark; /* get first table from list */
190 st.tmark = h->mark; /* remove it from list */
191 traversetable(&st, h);
192 }
193 else break; /* nothing else to mark */
194 } 180 }
195} 181}
196 182
@@ -204,7 +190,7 @@ static int hasmark (const TObject *o) {
204 case LUA_TTABLE: 190 case LUA_TTABLE:
205 return ismarked(hvalue(o)); 191 return ismarked(hvalue(o));
206 case LUA_TFUNCTION: 192 case LUA_TFUNCTION:
207 return ismarked(clvalue(o)); 193 return clvalue(o)->c.marked;
208 default: /* number, nil */ 194 default: /* number, nil */
209 return 1; 195 return 1;
210 } 196 }
@@ -252,12 +238,12 @@ static void collectproto (lua_State *L) {
252static void collectclosure (lua_State *L, Closure **p) { 238static void collectclosure (lua_State *L, Closure **p) {
253 Closure *curr; 239 Closure *curr;
254 while ((curr = *p) != NULL) { 240 while ((curr = *p) != NULL) {
255 if (ismarked(curr)) { 241 if (curr->c.marked) {
256 curr->mark = curr; /* unmark */ 242 curr->c.marked = 0;
257 p = &curr->next; 243 p = &curr->c.next;
258 } 244 }
259 else { 245 else {
260 *p = curr->next; 246 *p = curr->c.next;
261 luaF_freeclosure(L, curr); 247 luaF_freeclosure(L, curr);
262 } 248 }
263 } 249 }
diff --git a/llimits.h b/llimits.h
index 40815404..5b5b0203 100644
--- a/llimits.h
+++ b/llimits.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: llimits.h,v 1.31 2001/08/27 15:16:28 roberto Exp $ 2** $Id: llimits.h,v 1.32 2001/09/07 17:39:10 roberto Exp $
3** Limits, basic types, and some other `installation-dependent' definitions 3** Limits, basic types, and some other `installation-dependent' definitions
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -51,9 +51,6 @@ typedef unsigned long lu_mem;
51/* an integer big enough to count the number of strings in use */ 51/* an integer big enough to count the number of strings in use */
52typedef long ls_nstr; 52typedef long ls_nstr;
53 53
54/* a bitmap with one bit for each upvalue used by a function */
55typedef unsigned long ls_bitup;
56
57 54
58/* chars used as small naturals (so that `char' is reserved for characteres) */ 55/* chars used as small naturals (so that `char' is reserved for characteres) */
59typedef unsigned char lu_byte; 56typedef unsigned char lu_byte;
@@ -109,9 +106,9 @@ typedef unsigned long Instruction;
109#endif 106#endif
110 107
111 108
112/* maximum number of upvalues */ 109/* maximum number of upvalues per function */
113#ifndef MAXUPVALUES 110#ifndef MAXUPVALUES
114#define MAXUPVALUES (sizeof(ls_bitup)*CHAR_BIT) 111#define MAXUPVALUES 32
115#endif 112#endif
116 113
117 114
diff --git a/lobject.h b/lobject.h
index 234b78b1..359055f3 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.h,v 1.112 2001/09/07 17:39:10 roberto Exp $ 2** $Id: lobject.h,v 1.113 2001/09/25 17:08:46 roberto Exp $
3** Type definitions for Lua objects 3** Type definitions for Lua objects
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -38,7 +38,7 @@
38typedef union { 38typedef union {
39 union TString *ts; 39 union TString *ts;
40 union Udata *u; 40 union Udata *u;
41 struct Closure *cl; 41 union Closure *cl;
42 struct Hash *h; 42 struct Hash *h;
43 struct UpVal *v; 43 struct UpVal *v;
44 lua_Number n; /* LUA_TNUMBER */ 44 lua_Number n; /* LUA_TNUMBER */
@@ -177,26 +177,38 @@ typedef struct UpVal {
177/* 177/*
178** Closures 178** Closures
179*/ 179*/
180typedef struct Closure { 180
181 short isC; /* 0 for Lua functions, 1 for C functions */ 181typedef struct CClosure {
182 short nupvalues; 182 lu_byte isC; /* 0 for Lua functions, 1 for C functions */
183 struct Closure *next; 183 lu_byte nupvalues;
184 struct Closure *mark; /* marked closures (point to itself when not marked) */ 184 lu_byte marked;
185 union { 185 union Closure *next;
186 struct { /* C functions */ 186 lua_CFunction f;
187 lua_CFunction f; 187 TObject upvalue[1];
188 TObject upvalue[1]; 188} CClosure;
189 } c; 189
190 struct { /* Lua functions */ 190
191 struct Proto *p; 191typedef struct LClosureEntry {
192 ls_bitup isopen; /* bitmap: bit==1 when upvals point to the stack */ 192 TObject *val;
193 TObject *upvals[1]; /* may point to the stack or to an UpVal */ 193 UpVal *heap; /* NULL when upvalue is still in the stack */
194 } l; 194} LClosureEntry;
195 } u; 195
196typedef struct LClosure {
197 lu_byte isC;
198 lu_byte nupvalues;
199 lu_byte marked;
200 union Closure *next; /* first four fields must be equal to CClosure!! */
201 struct Proto *p;
202 LClosureEntry upvals[1];
203} LClosure;
204
205typedef union Closure {
206 CClosure c;
207 LClosure l;
196} Closure; 208} Closure;
197 209
198 210
199#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->isC) 211#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)
200 212
201 213
202 214
@@ -223,9 +235,7 @@ typedef struct Hash {
223} Hash; 235} Hash;
224 236
225 237
226/* unmarked tables and closures are represented by pointing `mark' to 238/* unmarked tables are represented by pointing `mark' to themselves */
227** themselves
228*/
229#define ismarked(x) ((x)->mark != (x)) 239#define ismarked(x) ((x)->mark != (x))
230 240
231 241
diff --git a/ltests.c b/ltests.c
index a33a9638..03d65657 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 1.88 2001/07/12 18:11:58 roberto Exp $ 2** $Id: ltests.c,v 1.91 2001/09/07 17:39:10 roberto Exp $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -165,7 +165,7 @@ static int listcode (lua_State *L) {
165 Proto *p; 165 Proto *p;
166 luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 166 luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
167 1, l_s("Lua function expected")); 167 1, l_s("Lua function expected"));
168 p = clvalue(luaA_index(L, 1))->u.l.p; 168 p = clvalue(luaA_index(L, 1))->l.p;
169 lua_newtable(L); 169 lua_newtable(L);
170 setnameval(L, l_s("maxstack"), p->maxstacksize); 170 setnameval(L, l_s("maxstack"), p->maxstacksize);
171 setnameval(L, l_s("numparams"), p->numparams); 171 setnameval(L, l_s("numparams"), p->numparams);
@@ -184,7 +184,7 @@ static int listk (lua_State *L) {
184 int i; 184 int i;
185 luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 185 luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
186 1, l_s("Lua function expected")); 186 1, l_s("Lua function expected"));
187 p = clvalue(luaA_index(L, 1))->u.l.p; 187 p = clvalue(luaA_index(L, 1))->l.p;
188 lua_newtable(L); 188 lua_newtable(L);
189 for (i=0; i<p->sizek; i++) { 189 for (i=0; i<p->sizek; i++) {
190 lua_pushnumber(L, i+1); 190 lua_pushnumber(L, i+1);
@@ -202,7 +202,7 @@ static int listlocals (lua_State *L) {
202 const l_char *name; 202 const l_char *name;
203 luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 203 luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1),
204 1, l_s("Lua function expected")); 204 1, l_s("Lua function expected"));
205 p = clvalue(luaA_index(L, 1))->u.l.p; 205 p = clvalue(luaA_index(L, 1))->l.p;
206 while ((name = luaF_getlocalname(p, ++i, pc)) != NULL) 206 while ((name = luaF_getlocalname(p, ++i, pc)) != NULL)
207 lua_pushstring(L, name); 207 lua_pushstring(L, name);
208 return i-1; 208 return i-1;
diff --git a/lvm.c b/lvm.c
index 1fe4aad5..980ed113 100644
--- a/lvm.c
+++ b/lvm.c
@@ -64,8 +64,8 @@ int luaV_tostring (lua_State *L, TObject *obj) {
64 64
65static void traceexec (lua_State *L, lua_Hook linehook) { 65static void traceexec (lua_State *L, lua_Hook linehook) {
66 CallInfo *ci = L->ci; 66 CallInfo *ci = L->ci;
67 int *lineinfo = ci_func(ci)->u.l.p->lineinfo; 67 int *lineinfo = ci_func(ci)->l.p->lineinfo;
68 int pc = (*ci->pc - ci_func(ci)->u.l.p->code) - 1; 68 int pc = (*ci->pc - ci_func(ci)->l.p->code) - 1;
69 int newline; 69 int newline;
70 if (pc == 0) { /* may be first time? */ 70 if (pc == 0) { /* may be first time? */
71 ci->line = 1; 71 ci->line = 1;
@@ -351,8 +351,8 @@ static void adjust_varargs (lua_State *L, StkId base, int nfixargs) {
351** Executes the given Lua function. Parameters are between [base,top). 351** Executes the given Lua function. Parameters are between [base,top).
352** Returns n such that the the results are between [n,top). 352** Returns n such that the the results are between [n,top).
353*/ 353*/
354StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { 354StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) {
355 const Proto *const tf = cl->u.l.p; 355 const Proto *const tf = cl->p;
356 const Instruction *pc; 356 const Instruction *pc;
357 lua_Hook linehook; 357 lua_Hook linehook;
358 if (tf->is_vararg) /* varargs? */ 358 if (tf->is_vararg) /* varargs? */
@@ -391,8 +391,8 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
391 } 391 }
392 case OP_GETUPVAL: { 392 case OP_GETUPVAL: {
393 int b = GETARG_B(i); 393 int b = GETARG_B(i);
394 lua_assert(luaF_isclosed(cl, b) || cl->u.l.upvals[b] < base); 394 lua_assert(cl->upvals[b].heap || cl->upvals[b].val < base);
395 setobj(ra, cl->u.l.upvals[b]); 395 setobj(ra, cl->upvals[b].val);
396 break; 396 break;
397 } 397 }
398 case OP_GETGLOBAL: { 398 case OP_GETGLOBAL: {
@@ -411,8 +411,8 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
411 } 411 }
412 case OP_SETUPVAL: { 412 case OP_SETUPVAL: {
413 int b = GETARG_B(i); 413 int b = GETARG_B(i);
414 lua_assert(luaF_isclosed(cl, b) || cl->u.l.upvals[b] < base); 414 lua_assert(cl->upvals[b].heap || cl->upvals[b].val < base);
415 setobj(cl->u.l.upvals[b], ra); 415 setobj(cl->upvals[b].val, ra);
416 break; 416 break;
417 } 417 }
418 case OP_SETTABLE: { 418 case OP_SETTABLE: {
@@ -644,18 +644,14 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
644 p = tf->p[GETARG_Bc(i)]; 644 p = tf->p[GETARG_Bc(i)];
645 nup = p->nupvalues; 645 nup = p->nupvalues;
646 ncl = luaF_newLclosure(L, nup); 646 ncl = luaF_newLclosure(L, nup);
647 ncl->u.l.p = p; 647 ncl->l.p = p;
648 for (j=0; j<nup; j++, pc++) { 648 for (j=0; j<nup; j++, pc++) {
649 if (GET_OPCODE(*pc) == OP_GETUPVAL) { 649 if (GET_OPCODE(*pc) == OP_GETUPVAL)
650 int n = GETARG_B(*pc); 650 ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];
651 if (!luaF_isclosed(cl, n))
652 luaF_openentry(ncl, j);
653 ncl->u.l.upvals[j] = cl->u.l.upvals[n];
654 }
655 else { 651 else {
656 lua_assert(GET_OPCODE(*pc) == OP_MOVE); 652 lua_assert(GET_OPCODE(*pc) == OP_MOVE);
657 luaF_openentry(ncl, j); 653 ncl->l.upvals[j].heap = NULL;
658 ncl->u.l.upvals[j] = base + GETARG_B(*pc); 654 ncl->l.upvals[j].val = base + GETARG_B(*pc);
659 } 655 }
660 } 656 }
661 luaF_LConlist(L, ncl); 657 luaF_LConlist(L, ncl);
diff --git a/lvm.h b/lvm.h
index de3fd45c..a9378de1 100644
--- a/lvm.h
+++ b/lvm.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.h,v 1.30 2001/06/05 18:17:01 roberto Exp $ 2** $Id: lvm.h,v 1.31 2001/09/07 17:39:10 roberto Exp $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -22,7 +22,7 @@ void luaV_gettable (lua_State *L, StkId t, TObject *key, StkId res);
22void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val); 22void luaV_settable (lua_State *L, StkId t, TObject *key, StkId val);
23void luaV_getglobal (lua_State *L, TString *s, StkId res); 23void luaV_getglobal (lua_State *L, TString *s, StkId res);
24void luaV_setglobal (lua_State *L, TString *s, StkId val); 24void luaV_setglobal (lua_State *L, TString *s, StkId val);
25StkId luaV_execute (lua_State *L, const Closure *cl, StkId base); 25StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base);
26int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r); 26int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r);
27void luaV_strconc (lua_State *L, int total, StkId top); 27void luaV_strconc (lua_State *L, int total, StkId top);
28 28