aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-06-09 13:48:44 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-06-09 13:48:44 -0300
commitb6f87491afe32140563fe3c546b8812c28a63410 (patch)
treeac85dff5a850c5d488f1efa4ea95d0d7da99be16 /lgc.c
parent4bb30f461b146e1d189ee301472953e948699acf (diff)
downloadlua-b6f87491afe32140563fe3c546b8812c28a63410.tar.gz
lua-b6f87491afe32140563fe3c546b8812c28a63410.tar.bz2
lua-b6f87491afe32140563fe3c546b8812c28a63410.zip
in hash nodes, keys are stored in separate pieces to avoid wasting
space with alignments
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c42
1 files changed, 23 insertions, 19 deletions
diff --git a/lgc.c b/lgc.c
index fa6cf799..36e34368 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.229 2017/05/26 19:14:29 roberto Exp roberto $ 2** $Id: lgc.c,v 2.230 2017/06/01 19:16:34 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*/
@@ -73,7 +73,9 @@
73 73
74#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) 74#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))
75 75
76#define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) 76#define keyiswhite(n) (keyiscollectable(n) && iswhite(gckey(n)))
77
78#define checkdeadkey(n) lua_assert(!keyisdead(n) || ttisnil(gval(n)))
77 79
78 80
79#define checkconsistency(obj) \ 81#define checkconsistency(obj) \
@@ -83,6 +85,8 @@
83#define markvalue(g,o) { checkconsistency(o); \ 85#define markvalue(g,o) { checkconsistency(o); \
84 if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } 86 if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
85 87
88#define markkey(g, n) { if keyiswhite(n) reallymarkobject(g,gckey(n)); }
89
86#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); } 90#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); }
87 91
88/* 92/*
@@ -125,8 +129,8 @@ static lu_mem atomic (lua_State *L);
125*/ 129*/
126static void removeentry (Node *n) { 130static void removeentry (Node *n) {
127 lua_assert(ttisnil(gval(n))); 131 lua_assert(ttisnil(gval(n)));
128 if (valiswhite(gkey(n))) 132 if (keyiswhite(n))
129 setdeadvalue(wgkey(n)); /* unused and unmarked key; remove it */ 133 setdeadkey(n); /* unused and unmarked key; remove it */
130} 134}
131 135
132 136
@@ -137,13 +141,13 @@ static void removeentry (Node *n) {
137** other objects: if really collected, cannot keep them; for objects 141** other objects: if really collected, cannot keep them; for objects
138** being finalized, keep them in keys, but not in values 142** being finalized, keep them in keys, but not in values
139*/ 143*/
140static int iscleared (global_State *g, const TValue *o) { 144static int iscleared (global_State *g, const GCObject *o) {
141 if (!iscollectable(o)) return 0; 145 if (o == NULL) return 0; /* non-collectable value */
142 else if (ttisstring(o)) { 146 else if (novariant(o->tt) == LUA_TSTRING) {
143 markobject(g, tsvalue(o)); /* strings are 'values', so are never weak */ 147 markobject(g, o); /* strings are 'values', so are never weak */
144 return 0; 148 return 0;
145 } 149 }
146 else return iswhite(gcvalue(o)); 150 else return iswhite(o);
147} 151}
148 152
149 153
@@ -391,9 +395,9 @@ static void traverseweakvalue (global_State *g, Table *h) {
391 if (ttisnil(gval(n))) /* entry is empty? */ 395 if (ttisnil(gval(n))) /* entry is empty? */
392 removeentry(n); /* remove it */ 396 removeentry(n); /* remove it */
393 else { 397 else {
394 lua_assert(!ttisnil(gkey(n))); 398 lua_assert(!keyisnil(n));
395 markvalue(g, gkey(n)); /* mark key */ 399 markkey(g, n);
396 if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */ 400 if (!hasclears && iscleared(g, gcvalueN(gval(n)))) /* a white value? */
397 hasclears = 1; /* table will have to be cleared */ 401 hasclears = 1; /* table will have to be cleared */
398 } 402 }
399 } 403 }
@@ -433,7 +437,7 @@ static int traverseephemeron (global_State *g, Table *h) {
433 checkdeadkey(n); 437 checkdeadkey(n);
434 if (ttisnil(gval(n))) /* entry is empty? */ 438 if (ttisnil(gval(n))) /* entry is empty? */
435 removeentry(n); /* remove it */ 439 removeentry(n); /* remove it */
436 else if (iscleared(g, gkey(n))) { /* key is not marked (yet)? */ 440 else if (iscleared(g, gckeyN(n))) { /* key is not marked (yet)? */
437 hasclears = 1; /* table must be cleared */ 441 hasclears = 1; /* table must be cleared */
438 if (valiswhite(gval(n))) /* value not marked yet? */ 442 if (valiswhite(gval(n))) /* value not marked yet? */
439 hasww = 1; /* white-white entry */ 443 hasww = 1; /* white-white entry */
@@ -468,9 +472,9 @@ static void traversestrongtable (global_State *g, Table *h) {
468 if (ttisnil(gval(n))) /* entry is empty? */ 472 if (ttisnil(gval(n))) /* entry is empty? */
469 removeentry(n); /* remove it */ 473 removeentry(n); /* remove it */
470 else { 474 else {
471 lua_assert(!ttisnil(gkey(n))); 475 lua_assert(!keyisnil(n));
472 markvalue(g, gkey(n)); /* mark key */ 476 markkey(g, n);
473 markvalue(g, gval(n)); /* mark value */ 477 markvalue(g, gval(n));
474 } 478 }
475 } 479 }
476 if (g->gckind == KGC_GEN) { 480 if (g->gckind == KGC_GEN) {
@@ -691,7 +695,7 @@ static void clearkeys (global_State *g, GCObject *l) {
691 Table *h = gco2t(l); 695 Table *h = gco2t(l);
692 Node *n, *limit = gnodelast(h); 696 Node *n, *limit = gnodelast(h);
693 for (n = gnode(h, 0); n < limit; n++) { 697 for (n = gnode(h, 0); n < limit; n++) {
694 if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { 698 if (!ttisnil(gval(n)) && (iscleared(g, gckeyN(n)))) {
695 setnilvalue(gval(n)); /* remove value ... */ 699 setnilvalue(gval(n)); /* remove value ... */
696 removeentry(n); /* and remove entry from table */ 700 removeentry(n); /* and remove entry from table */
697 } 701 }
@@ -711,11 +715,11 @@ static void clearvalues (global_State *g, GCObject *l, GCObject *f) {
711 unsigned int i; 715 unsigned int i;
712 for (i = 0; i < h->sizearray; i++) { 716 for (i = 0; i < h->sizearray; i++) {
713 TValue *o = &h->array[i]; 717 TValue *o = &h->array[i];
714 if (iscleared(g, o)) /* value was collected? */ 718 if (iscleared(g, gcvalueN(o))) /* value was collected? */
715 setnilvalue(o); /* remove value */ 719 setnilvalue(o); /* remove value */
716 } 720 }
717 for (n = gnode(h, 0); n < limit; n++) { 721 for (n = gnode(h, 0); n < limit; n++) {
718 if (iscleared(g, gval(n))) { 722 if (iscleared(g, gcvalueN(gval(n)))) {
719 setnilvalue(gval(n)); /* remove value ... */ 723 setnilvalue(gval(n)); /* remove value ... */
720 removeentry(n); /* and remove entry from table */ 724 removeentry(n); /* and remove entry from table */
721 } 725 }