diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-06-09 13:48:44 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-06-09 13:48:44 -0300 |
commit | b6f87491afe32140563fe3c546b8812c28a63410 (patch) | |
tree | ac85dff5a850c5d488f1efa4ea95d0d7da99be16 /lgc.c | |
parent | 4bb30f461b146e1d189ee301472953e948699acf (diff) | |
download | lua-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.c | 42 |
1 files changed, 23 insertions, 19 deletions
@@ -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 | */ |
126 | static void removeentry (Node *n) { | 130 | static 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 | */ |
140 | static int iscleared (global_State *g, const TValue *o) { | 144 | static 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 | } |