summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lfunc.c34
-rw-r--r--lfunc.h3
-rw-r--r--lgc.c25
-rw-r--r--lobject.h10
-rw-r--r--lstate.c8
-rw-r--r--lstate.h20
-rw-r--r--ltests.c19
7 files changed, 47 insertions, 72 deletions
diff --git a/lfunc.c b/lfunc.c
index a0264fed..82d05656 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lfunc.c,v 2.30 2012/10/03 12:36:46 roberto Exp roberto $ 2** $Id: lfunc.c,v 2.31 2013/08/05 16:58:28 roberto Exp roberto $
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*/
@@ -38,7 +38,7 @@ Closure *luaF_newLclosure (lua_State *L, int n) {
38 38
39UpVal *luaF_newupval (lua_State *L) { 39UpVal *luaF_newupval (lua_State *L) {
40 UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), NULL, 0)->uv; 40 UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), NULL, 0)->uv;
41 uv->v = &uv->u.value; 41 uv->v = &uv->value;
42 setnilvalue(uv->v); 42 setnilvalue(uv->v);
43 return uv; 43 return uv;
44} 44}
@@ -51,7 +51,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
51 UpVal *uv; 51 UpVal *uv;
52 while (*pp != NULL && (p = gco2uv(*pp))->v >= level) { 52 while (*pp != NULL && (p = gco2uv(*pp))->v >= level) {
53 GCObject *o = obj2gco(p); 53 GCObject *o = obj2gco(p);
54 lua_assert(p->v != &p->u.value); 54 lua_assert(p->v != &p->value);
55 if (p->v == level) { /* found a corresponding upvalue? */ 55 if (p->v == level) { /* found a corresponding upvalue? */
56 if (isdead(g, o)) /* is it dead? */ 56 if (isdead(g, o)) /* is it dead? */
57 changewhite(o); /* resurrect it */ 57 changewhite(o); /* resurrect it */
@@ -62,42 +62,22 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
62 /* not found: create a new one */ 62 /* not found: create a new one */
63 uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv; 63 uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv;
64 uv->v = level; /* current value lives in the stack */ 64 uv->v = level; /* current value lives in the stack */
65 uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */
66 uv->u.l.next = g->uvhead.u.l.next;
67 uv->u.l.next->u.l.prev = uv;
68 g->uvhead.u.l.next = uv;
69 lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
70 return uv; 65 return uv;
71} 66}
72 67
73 68
74static void unlinkupval (UpVal *uv) {
75 lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
76 uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */
77 uv->u.l.prev->u.l.next = uv->u.l.next;
78}
79
80
81void luaF_freeupval (lua_State *L, UpVal *uv) {
82 if (uv->v != &uv->u.value) /* is it open? */
83 unlinkupval(uv); /* remove from open list */
84 luaM_free(L, uv); /* free upvalue */
85}
86
87
88void luaF_close (lua_State *L, StkId level) { 69void luaF_close (lua_State *L, StkId level) {
89 UpVal *uv; 70 UpVal *uv;
90 global_State *g = G(L); 71 global_State *g = G(L);
91 while (L->openupval != NULL && (uv = gco2uv(L->openupval))->v >= level) { 72 while (L->openupval != NULL && (uv = gco2uv(L->openupval))->v >= level) {
92 GCObject *o = obj2gco(uv); 73 GCObject *o = obj2gco(uv);
93 lua_assert(!isblack(o) && uv->v != &uv->u.value); 74 lua_assert(!isblack(o) && uv->v != &uv->value);
94 L->openupval = uv->next; /* remove from `open' list */ 75 L->openupval = uv->next; /* remove from `open' list */
95 if (isdead(g, o)) 76 if (isdead(g, o))
96 luaF_freeupval(L, uv); /* free upvalue */ 77 luaM_free(L, uv); /* free upvalue */
97 else { 78 else {
98 unlinkupval(uv); /* remove upvalue from 'uvhead' list */ 79 setobj(L, &uv->value, uv->v); /* move value to upvalue slot */
99 setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ 80 uv->v = &uv->value; /* now current value lives here */
100 uv->v = &uv->u.value; /* now current value lives here */
101 gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */ 81 gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */
102 g->allgc = o; 82 g->allgc = o;
103 luaC_checkupvalcolor(g, uv); 83 luaC_checkupvalcolor(g, uv);
diff --git a/lfunc.h b/lfunc.h
index 27d041ce..c5e8b89c 100644
--- a/lfunc.h
+++ b/lfunc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lfunc.h,v 2.7 2012/01/20 22:05:50 roberto Exp roberto $ 2** $Id: lfunc.h,v 2.8 2012/05/08 13:53:33 roberto Exp roberto $
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*/
@@ -25,7 +25,6 @@ LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
25LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); 25LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
26LUAI_FUNC void luaF_close (lua_State *L, StkId level); 26LUAI_FUNC void luaF_close (lua_State *L, StkId level);
27LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); 27LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
28LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv);
29LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, 28LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
30 int pc); 29 int pc);
31 30
diff --git a/lgc.c b/lgc.c
index 8e73ff21..993af884 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.141 2013/04/26 18:26:49 roberto Exp roberto $ 2** $Id: lgc.c,v 2.142 2013/08/05 16:58:28 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -258,7 +258,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
258 case LUA_TUPVAL: { 258 case LUA_TUPVAL: {
259 UpVal *uv = gco2uv(o); 259 UpVal *uv = gco2uv(o);
260 markvalue(g, uv->v); 260 markvalue(g, uv->v);
261 if (uv->v != &uv->u.value) /* open? */ 261 if (uv->v != &uv->value) /* open? */
262 return; /* open upvalues remain gray */ 262 return; /* open upvalues remain gray */
263 size = sizeof(UpVal); 263 size = sizeof(UpVal);
264 break; 264 break;
@@ -317,14 +317,21 @@ static void markbeingfnz (global_State *g) {
317 317
318 318
319/* 319/*
320** mark all values stored in marked open upvalues. (See comment in 320** Mark all values stored in marked open upvalues from non-marked threads.
321** 'lstate.h'.) 321** (Values from marked threads were already marked when traversing the
322** thread.)
322*/ 323*/
323static void remarkupvals (global_State *g) { 324static void remarkupvals (global_State *g) {
324 UpVal *uv; 325 GCObject *thread = hvalue(&g->l_registry)->next;
325 for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { 326 for (; thread != NULL; thread = gch(thread)->next) {
326 if (isgray(obj2gco(uv))) 327 lua_assert(!isblack(thread)); /* threads are never black */
327 markvalue(g, uv->v); 328 if (!isgray(thread)) { /* dead thread? */
329 GCObject *uv = gco2th(thread)->openupval;
330 for (; uv != NULL; uv = gch(uv)->next) {
331 if (isgray(uv)) /* marked? */
332 markvalue(g, gco2uv(uv)->v); /* remark upvalue's value */
333 }
334 }
328 } 335 }
329} 336}
330 337
@@ -669,7 +676,7 @@ static void freeobj (lua_State *L, GCObject *o) {
669 luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); 676 luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues));
670 break; 677 break;
671 } 678 }
672 case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; 679 case LUA_TUPVAL: luaM_free(L, gco2uv(o)); break;
673 case LUA_TTABLE: luaH_free(L, gco2t(o)); break; 680 case LUA_TTABLE: luaH_free(L, gco2t(o)); break;
674 case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; 681 case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break;
675 case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; 682 case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break;
diff --git a/lobject.h b/lobject.h
index 769e96db..ba425fed 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.h,v 2.77 2013/05/06 17:17:09 roberto Exp roberto $ 2** $Id: lobject.h,v 2.78 2013/05/14 15:59:04 roberto Exp roberto $
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*/
@@ -395,13 +395,7 @@ typedef struct Proto {
395typedef struct UpVal { 395typedef struct UpVal {
396 CommonHeader; 396 CommonHeader;
397 TValue *v; /* points to stack or to its own value */ 397 TValue *v; /* points to stack or to its own value */
398 union { 398 TValue value; /* the value (when closed) */
399 TValue value; /* the value (when closed) */
400 struct { /* double linked list (when open) */
401 struct UpVal *prev;
402 struct UpVal *next;
403 } l;
404 } u;
405} UpVal; 399} UpVal;
406 400
407 401
diff --git a/lstate.c b/lstate.c
index c9a397fd..9c4130a8 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 2.99 2012/10/02 17:40:53 roberto Exp roberto $ 2** $Id: lstate.c,v 2.100 2013/08/05 16:58:28 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -230,7 +230,9 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
230 lua_State *L1; 230 lua_State *L1;
231 lua_lock(L); 231 lua_lock(L);
232 luaC_checkGC(L); 232 luaC_checkGC(L);
233 L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX), NULL, offsetof(LX, l))->th; 233 /* create new thread, linked after 'l_registry' */
234 L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX),
235 &hvalue(&G(L)->l_registry)->next, offsetof(LX, l))->th;
234 setthvalue(L, L->top, L1); 236 setthvalue(L, L->top, L1);
235 api_incr_top(L); 237 api_incr_top(L);
236 preinit_state(L1, G(L)); 238 preinit_state(L1, G(L));
@@ -273,8 +275,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
273 g->ud = ud; 275 g->ud = ud;
274 g->mainthread = L; 276 g->mainthread = L;
275 g->seed = makeseed(L); 277 g->seed = makeseed(L);
276 g->uvhead.u.l.prev = &g->uvhead;
277 g->uvhead.u.l.next = &g->uvhead;
278 g->gcrunning = 0; /* no GC while building state */ 278 g->gcrunning = 0; /* no GC while building state */
279 g->GCestimate = 0; 279 g->GCestimate = 0;
280 g->strt.size = 0; 280 g->strt.size = 0;
diff --git a/lstate.h b/lstate.h
index ae8c5500..4eda35fd 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 2.82 2012/07/02 13:37:04 roberto Exp roberto $ 2** $Id: lstate.h,v 2.83 2013/08/05 16:58:28 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -20,17 +20,18 @@
20** be kept somehow accessible until being freed. 20** be kept somehow accessible until being freed.
21** 21**
22** Lua keeps most objects linked in list g->allgc. The link uses field 22** Lua keeps most objects linked in list g->allgc. The link uses field
23** 'next' of the CommonHeader. 23** 'next' of the CommonHeader. Threads (except the main one) ar kept
24** at the end of the 'allgc' list, after the 'l_registry' (which is
25** the first object to be added to the list).
24** 26**
25** Strings are kept in several lists headed by the array g->strt.hash. 27** Short strings are kept in several lists headed by the array g->strt.hash.
26** 28**
27** Open upvalues are not subject to independent garbage collection. They 29** Open upvalues are not subject to independent garbage collection. They
28** are collected together with their respective threads. Lua keeps a 30** are collected together with their respective threads. (They are
29** double-linked list with all open upvalues (g->uvhead) so that it can 31** always gray, so they must be remarked in the atomic step. Usually
30** mark objects referred by them. (They are always gray, so they must 32** their contents would be marked when traversing the respective
31** be remarked in the atomic step. Usually their contents would be marked 33** threads, but the thread may already be dead, while the upvalue is
32** when traversing the respective threads, but the thread may already be 34** still accessible through closures.)
33** dead, while the upvalue is still accessible through closures.)
34** 35**
35** Objects with finalizers are kept in the list g->finobj. 36** Objects with finalizers are kept in the list g->finobj.
36** 37**
@@ -133,7 +134,6 @@ typedef struct global_State {
133 GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ 134 GCObject *ephemeron; /* list of ephemeron tables (weak keys) */
134 GCObject *allweak; /* list of all-weak tables */ 135 GCObject *allweak; /* list of all-weak tables */
135 GCObject *tobefnz; /* list of userdata to be GC */ 136 GCObject *tobefnz; /* list of userdata to be GC */
136 UpVal uvhead; /* head of double-linked list of all open upvalues */
137 Mbuffer buff; /* temporary buffer for string concatenation */ 137 Mbuffer buff; /* temporary buffer for string concatenation */
138 int gcpause; /* size of pause between successive GCs */ 138 int gcpause; /* size of pause between successive GCs */
139 int gcstepmul; /* GC `granularity' */ 139 int gcstepmul; /* GC `granularity' */
diff --git a/ltests.c b/ltests.c
index 4378d0ef..e45a82cf 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 2.139 2013/06/20 21:59:13 roberto Exp roberto $ 2** $Id: ltests.c,v 2.140 2013/08/05 16:58:28 roberto Exp roberto $
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*/
@@ -310,7 +310,7 @@ static void checkstack (global_State *g, lua_State *L1) {
310 lua_assert(!isdead(g, obj2gco(L1))); 310 lua_assert(!isdead(g, obj2gco(L1)));
311 for (uvo = L1->openupval; uvo != NULL; uvo = gch(uvo)->next) { 311 for (uvo = L1->openupval; uvo != NULL; uvo = gch(uvo)->next) {
312 UpVal *uv = gco2uv(uvo); 312 UpVal *uv = gco2uv(uvo);
313 lua_assert(uv->v != &uv->u.value); /* must be open */ 313 lua_assert(uv->v != &uv->value); /* must be open */
314 lua_assert(!isblack(uvo)); /* open upvalues cannot be black */ 314 lua_assert(!isblack(uvo)); /* open upvalues cannot be black */
315 } 315 }
316 for (ci = L1->ci; ci != NULL; ci = ci->previous) { 316 for (ci = L1->ci; ci != NULL; ci = ci->previous) {
@@ -334,7 +334,7 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) {
334 switch (gch(o)->tt) { 334 switch (gch(o)->tt) {
335 case LUA_TUPVAL: { 335 case LUA_TUPVAL: {
336 UpVal *uv = gco2uv(o); 336 UpVal *uv = gco2uv(o);
337 lua_assert(uv->v == &uv->u.value); /* must be closed */ 337 lua_assert(uv->v == &uv->value); /* must be closed */
338 lua_assert(!isgray(o)); /* closed upvalues are never gray */ 338 lua_assert(!isgray(o)); /* closed upvalues are never gray */
339 checkvalref(g, o, uv->v); 339 checkvalref(g, o, uv->v);
340 break; 340 break;
@@ -419,8 +419,8 @@ static void checkgray (global_State *g, GCObject *o) {
419int lua_checkmemory (lua_State *L) { 419int lua_checkmemory (lua_State *L) {
420 global_State *g = G(L); 420 global_State *g = G(L);
421 GCObject *o; 421 GCObject *o;
422 UpVal *uv;
423 int maybedead; 422 int maybedead;
423 int isthread;
424 if (keepinvariant(g)) { 424 if (keepinvariant(g)) {
425 lua_assert(!iswhite(obj2gco(g->mainthread))); 425 lua_assert(!iswhite(obj2gco(g->mainthread)));
426 lua_assert(!iswhite(gcvalue(&g->l_registry))); 426 lua_assert(!iswhite(gcvalue(&g->l_registry)));
@@ -433,9 +433,12 @@ int lua_checkmemory (lua_State *L) {
433 checkgray(g, g->allgc); 433 checkgray(g, g->allgc);
434 lua_assert(g->sweepgc == NULL || issweepphase(g)); 434 lua_assert(g->sweepgc == NULL || issweepphase(g));
435 maybedead = 0; 435 maybedead = 0;
436 isthread = 0; /* not traversing threads (yet) */
436 for (o = g->allgc; o != NULL; o = gch(o)->next) { 437 for (o = g->allgc; o != NULL; o = gch(o)->next) {
437 if (g->sweepgc && o == *g->sweepgc) 438 if (g->sweepgc && o == *g->sweepgc)
438 maybedead = 1; /* part of the list not yet swept */ 439 maybedead = 1; /* part of the list not yet swept */
440 if (gch(o)->tt == LUA_TTHREAD) isthread = 1; /* now travesing threads... */
441 else lua_assert(!isthread); /* ... and only threads */
439 checkobject(g, o, maybedead); 442 checkobject(g, o, maybedead);
440 lua_assert(!testbit(o->gch.marked, SEPARATED)); 443 lua_assert(!testbit(o->gch.marked, SEPARATED));
441 } 444 }
@@ -455,14 +458,6 @@ int lua_checkmemory (lua_State *L) {
455 lua_assert(gch(o)->tt == LUA_TUSERDATA || 458 lua_assert(gch(o)->tt == LUA_TUSERDATA ||
456 gch(o)->tt == LUA_TTABLE); 459 gch(o)->tt == LUA_TTABLE);
457 } 460 }
458 /* check 'uvhead' list */
459 for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {
460 lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);
461 lua_assert(uv->v != &uv->u.value); /* must be open */
462 lua_assert(!isblack(obj2gco(uv))); /* open upvalues are never black */
463 if (!isdead(g, obj2gco(uv)))
464 checkvalref(g, obj2gco(uv), uv->v);
465 }
466 return 0; 461 return 0;
467} 462}
468 463