summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-11-06 19:41:53 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-11-06 19:41:53 -0200
commit26bf2adaceb18877d836174226d2bfdc3f1fc512 (patch)
treeb23ccd2e297e7c5e732ce65e88f35145271f7faa
parentfd48dcc7c8734091181d8d0e54b0ba3d1770f4c3 (diff)
downloadlua-26bf2adaceb18877d836174226d2bfdc3f1fc512.tar.gz
lua-26bf2adaceb18877d836174226d2bfdc3f1fc512.tar.bz2
lua-26bf2adaceb18877d836174226d2bfdc3f1fc512.zip
optimizations for space in LClosures and time cleanning weak tables
-rw-r--r--lfunc.c22
-rw-r--r--lgc.c100
-rw-r--r--lobject.h38
-rw-r--r--lvm.c13
4 files changed, 88 insertions, 85 deletions
diff --git a/lfunc.c b/lfunc.c
index bed67101..1e903a5b 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lfunc.c,v 1.47 2001/09/07 17:39:10 roberto Exp $ 2** $Id: lfunc.c,v 1.48 2001/10/02 16:45:03 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*/
@@ -20,7 +20,7 @@
20 cast(int, sizeof(TObject)*((n)-1))) 20 cast(int, sizeof(TObject)*((n)-1)))
21 21
22#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ 22#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \
23 cast(int, sizeof(LClosureEntry)*((n)-1))) 23 cast(int, sizeof(TObject *)*((n)-1)))
24 24
25 25
26Closure *luaF_newCclosure (lua_State *L, int nelems) { 26Closure *luaF_newCclosure (lua_State *L, int nelems) {
@@ -50,8 +50,8 @@ static StkId uppoint (LClosure *cl) {
50 StkId lp = NULL; 50 StkId lp = NULL;
51 int i; 51 int i;
52 for (i=0; i<cl->nupvalues; i++) { 52 for (i=0; i<cl->nupvalues; i++) {
53 if (cl->upvals[i].heap == NULL && (lp == NULL || cl->upvals[i].val > lp)) 53 if (!isclosed(cl->upvals[i]) && (lp == NULL || cl->upvals[i] > lp))
54 lp = cl->upvals[i].val; 54 lp = cl->upvals[i];
55 } 55 }
56 return lp; 56 return lp;
57} 57}
@@ -77,17 +77,15 @@ static int closeCl (lua_State *L, LClosure *cl, StkId level) {
77 int i; 77 int i;
78 for (i=0; i<cl->nupvalues; i++) { 78 for (i=0; i<cl->nupvalues; i++) {
79 StkId var; 79 StkId var;
80 if (cl->upvals[i].heap == NULL && (var=cl->upvals[i].val) >= level) { 80 if (!isclosed(cl->upvals[i]) && (var=cl->upvals[i]) >= level) {
81 if (ttype(var) != LUA_TUPVAL) { 81 if (ttype(var) != LUA_TUPVAL) {
82 UpVal *v = luaM_new(L, UpVal); 82 TObject *v = luaM_newvector(L, 2, TObject);
83 v->val = *var; 83 v[1] = *var;
84 v->marked = 0; 84 setupvalue(v, G(L)->rootupval, LUA_HEAPUPVAL);
85 v->next = G(L)->rootupval;
86 G(L)->rootupval = v; 85 G(L)->rootupval = v;
87 setupvalue(var, v); 86 setupvalue(var, &v[1], LUA_TUPVAL);
88 } 87 }
89 cl->upvals[i].heap = vvalue(var); 88 cl->upvals[i] = vvalue(var);
90 cl->upvals[i].val = &vvalue(var)->val;
91 got = 1; 89 got = 1;
92 } 90 }
93 } 91 }
diff --git a/lgc.c b/lgc.c
index abace987..d41b6d51 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.114 2001/10/25 19:14:14 roberto Exp roberto $ 2** $Id: lgc.c,v 1.115 2001/10/31 19:58:11 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,6 +22,7 @@
22 22
23typedef struct GCState { 23typedef struct GCState {
24 Table *tmark; /* list of marked tables to be visited */ 24 Table *tmark; /* list of marked tables to be visited */
25 Table *toclear; /* list of visited weak tables (to be cleared after GC) */
25} GCState; 26} GCState;
26 27
27 28
@@ -65,10 +66,10 @@ static void markclosure (GCState *st, Closure *cl) {
65 lua_assert(cl->l.nupvalues == cl->l.p->nupvalues); 66 lua_assert(cl->l.nupvalues == cl->l.p->nupvalues);
66 protomark(cl->l.p); 67 protomark(cl->l.p);
67 for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */ 68 for (i=0; i<cl->l.nupvalues; i++) { /* mark its upvalues */
68 UpVal *u = cl->l.upvals[i].heap; 69 TObject *u = cl->l.upvals[i];
69 if (u && !u->marked) { 70 if (isclosed(u)) {
70 u->marked = 1; 71 ttype(u-1) = LUA_TNIL; /* temporary value (to mark as visited) */
71 markobject(st, &u->val); 72 markobject(st, u);
72 } 73 }
73 } 74 }
74 } 75 }
@@ -148,6 +149,10 @@ static void removekey (Node *n) {
148static void traversetable (GCState *st, Table *h) { 149static void traversetable (GCState *st, Table *h) {
149 int i; 150 int i;
150 int mode = h->weakmode; 151 int mode = h->weakmode;
152 if (mode) { /* weak table? must be cleared after GC... */
153 h->mark = st->toclear; /* put in the appropriate list */
154 st->toclear = h;
155 }
151 if (!(mode & LUA_WEAK_VALUE)) { 156 if (!(mode & LUA_WEAK_VALUE)) {
152 i = sizearray(h); 157 i = sizearray(h);
153 while (i--) 158 while (i--)
@@ -167,17 +172,15 @@ static void traversetable (GCState *st, Table *h) {
167} 172}
168 173
169 174
170static void markall (lua_State *L) { 175static void markall (lua_State *L, GCState *st) {
171 GCState st; 176 marktagmethods(G(L), st); /* mark tag methods */
172 st.tmark = NULL; 177 markstacks(L, st); /* mark all stacks */
173 marktagmethods(G(L), &st); /* mark tag methods */ 178 marktable(st, G(L)->type2tag);
174 markstacks(L, &st); /* mark all stacks */ 179 markobject(st, &G(L)->registry);
175 marktable(&st, G(L)->type2tag); 180 while (st->tmark) { /* mark tables */
176 markobject(&st, &G(L)->registry); 181 Table *h = st->tmark; /* get first table from list */
177 while (st.tmark) { /* mark tables */ 182 st->tmark = h->mark; /* remove it from list */
178 Table *h = st.tmark; /* get first table from list */ 183 traversetable(st, h);
179 st.tmark = h->mark; /* remove it from list */
180 traversetable(&st, h);
181 } 184 }
182} 185}
183 186
@@ -198,30 +201,27 @@ static int hasmark (const TObject *o) {
198} 201}
199 202
200 203
201static void cleardeadnodes (Table *h) { 204/*
202 int i; 205** clear (set to nil) keys and values from weaktables that were collected
203 i = sizearray(h); 206*/
204 while (i--) { 207static void cleartables (Table *h) {
205 TObject *o = &h->array[i]; 208 for (; h; h = h->mark) {
206 if (!hasmark(o)) 209 int i;
207 setnilvalue(o); /* remove value */ 210 lua_assert(h->weakmode);
208 } 211 i = sizearray(h);
209 i = sizenode(h); 212 while (i--) {
210 while (i--) { 213 TObject *o = &h->array[i];
211 Node *n = node(h, i); 214 if (!hasmark(o))
212 if (!hasmark(val(n)) || !hasmark(key(n))) { 215 setnilvalue(o); /* remove value */
213 setnilvalue(val(n)); /* remove value ... */ 216 }
214 removekey(n); /* ... and key */ 217 i = sizenode(h);
218 while (i--) {
219 Node *n = node(h, i);
220 if (!hasmark(val(n)) || !hasmark(key(n))) {
221 setnilvalue(val(n)); /* remove value ... */
222 removekey(n); /* ... and key */
223 }
215 } 224 }
216 }
217}
218
219
220static void cleartables (global_State *G) {
221 Table *h;
222 for (h = G->roottable; h; h = h->next) {
223 if (h->weakmode && ismarked(h))
224 cleardeadnodes(h);
225 } 225 }
226} 226}
227 227
@@ -284,16 +284,17 @@ static void collecttable (lua_State *L) {
284 284
285 285
286static void collectupval (lua_State *L) { 286static void collectupval (lua_State *L) {
287 UpVal **v = &G(L)->rootupval; 287 TObject **v = &G(L)->rootupval;
288 UpVal *curr; 288 TObject *curr;
289 while ((curr = *v) != NULL) { 289 while ((curr = *v) != NULL) {
290 if (curr->marked) { 290 if (ttype(curr) == LUA_TNIL) { /* was marked? */
291 curr->marked = 0; 291 ttype(curr) = LUA_HEAPUPVAL; /* unmark */
292 v = &curr->next; 292 v = &vvalue(curr); /* next */
293 } 293 }
294 else { 294 else {
295 *v = curr->next; 295 lua_assert(ttype(curr) == LUA_HEAPUPVAL);
296 luaM_freelem(L, curr); 296 *v = vvalue(curr); /* next */
297 luaM_freearray(L, curr, 2, TObject);
297 } 298 }
298 } 299 }
299} 300}
@@ -411,8 +412,11 @@ void luaC_collect (lua_State *L, int all) {
411 412
412 413
413void luaC_collectgarbage (lua_State *L) { 414void luaC_collectgarbage (lua_State *L) {
414 markall(L); 415 GCState st;
415 cleartables(G(L)); 416 st.tmark = NULL;
417 st.toclear = NULL;
418 markall(L, &st);
419 cleartables(st.toclear);
416 luaC_collect(L, 0); 420 luaC_collect(L, 0);
417 checkMbuffer(L); 421 checkMbuffer(L);
418 G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */ 422 G(L)->GCthreshold = 2*G(L)->nblocks; /* new threshold */
diff --git a/lobject.h b/lobject.h
index dbabc638..d8e6057f 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.h,v 1.114 2001/10/02 16:45:03 roberto Exp $ 2** $Id: lobject.h,v 1.115 2001/10/25 19:14:14 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*/
@@ -31,8 +31,13 @@
31#define NUM_TAGS 6 31#define NUM_TAGS 6
32 32
33 33
34/* extra tag: used locally when moving an upvalue from the stack to the heap */ 34/*
35** extra tags:
36** first is used locally when moving an upvalue from the stack to the heap;
37** second prefixes upvalues in the heap
38*/
35#define LUA_TUPVAL 6 39#define LUA_TUPVAL 6
40#define LUA_HEAPUPVAL 7
36 41
37 42
38typedef union { 43typedef union {
@@ -40,7 +45,7 @@ typedef union {
40 union Udata *u; 45 union Udata *u;
41 union Closure *cl; 46 union Closure *cl;
42 struct Table *h; 47 struct Table *h;
43 struct UpVal *v; 48 struct lua_TObject *v;
44 lua_Number n; /* LUA_TNUMBER */ 49 lua_Number n; /* LUA_TNUMBER */
45} Value; 50} Value;
46 51
@@ -81,8 +86,8 @@ typedef struct lua_TObject {
81 86
82#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) 87#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)
83 88
84#define setupvalue(obj,x) \ 89#define setupvalue(obj,x,t) \
85 { TObject *_o=(obj); _o->tt=LUA_TUPVAL; _o->value.v=(x); } 90 { TObject *_o=(obj); _o->tt=(t); _o->value.v=(x); }
86 91
87#define setobj(obj1,obj2) \ 92#define setobj(obj1,obj2) \
88 { TObject *o1=(obj1); const TObject *o2=(obj2); \ 93 { TObject *o1=(obj1); const TObject *o2=(obj2); \
@@ -165,13 +170,15 @@ typedef struct LocVar {
165 170
166 171
167/* 172/*
168** Upvalues in the heap 173** Upvalues in the heap. There is a small trick here: to allow a closure to
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.
169*/ 179*/
170typedef struct UpVal { 180
171 TObject val; 181#define isclosed(u) (ttype((u)-1) == LUA_HEAPUPVAL)
172 struct UpVal *next;
173 int marked;
174} UpVal;
175 182
176 183
177/* 184/*
@@ -188,20 +195,16 @@ typedef struct CClosure {
188} CClosure; 195} CClosure;
189 196
190 197
191typedef struct LClosureEntry {
192 TObject *val;
193 UpVal *heap; /* NULL when upvalue is still in the stack */
194} LClosureEntry;
195
196typedef struct LClosure { 198typedef struct LClosure {
197 lu_byte isC; 199 lu_byte isC;
198 lu_byte nupvalues; 200 lu_byte nupvalues;
199 lu_byte marked; 201 lu_byte marked;
200 union Closure *next; /* first four fields must be equal to CClosure!! */ 202 union Closure *next; /* first four fields must be equal to CClosure!! */
201 struct Proto *p; 203 struct Proto *p;
202 LClosureEntry upvals[1]; 204 TObject *upvals[1];
203} LClosure; 205} LClosure;
204 206
207
205typedef union Closure { 208typedef union Closure {
206 CClosure c; 209 CClosure c;
207 LClosure l; 210 LClosure l;
@@ -212,7 +215,6 @@ typedef union Closure {
212 215
213 216
214 217
215
216/* 218/*
217** Tables 219** Tables
218*/ 220*/
diff --git a/lvm.c b/lvm.c
index 6f0d9ab7..cc94b836 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 1.196 2001/10/25 19:14:14 roberto Exp roberto $ 2** $Id: lvm.c,v 1.197 2001/10/31 19:58:11 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*/
@@ -391,8 +391,8 @@ StkId luaV_execute (lua_State *L, const LClosure *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(cl->upvals[b].heap || cl->upvals[b].val < base); 394 lua_assert(isclosed(cl->upvals[b]) || cl->upvals[b] < base);
395 setobj(ra, cl->upvals[b].val); 395 setobj(ra, cl->upvals[b]);
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 LClosure *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(cl->upvals[b].heap || cl->upvals[b].val < base); 414 lua_assert(isclosed(cl->upvals[b]) || cl->upvals[b] < base);
415 setobj(cl->upvals[b].val, ra); 415 setobj(cl->upvals[b], ra);
416 break; 416 break;
417 } 417 }
418 case OP_SETTABLE: { 418 case OP_SETTABLE: {
@@ -649,8 +649,7 @@ StkId luaV_execute (lua_State *L, const LClosure *cl, StkId base) {
649 ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)]; 649 ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];
650 else { 650 else {
651 lua_assert(GET_OPCODE(*pc) == OP_MOVE); 651 lua_assert(GET_OPCODE(*pc) == OP_MOVE);
652 ncl->l.upvals[j].heap = NULL; 652 ncl->l.upvals[j] = base + GETARG_B(*pc);
653 ncl->l.upvals[j].val = base + GETARG_B(*pc);
654 } 653 }
655 } 654 }
656 luaF_LConlist(L, ncl); 655 luaF_LConlist(L, ncl);