aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-02-23 10:16:18 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-02-23 10:16:18 -0300
commit9243c414d92c253edd908f438caa31e2aa16f3f4 (patch)
treee8959a48f4672037aef061cc6eb82bba21d0766b /lgc.c
parent477ca2fe8ceaf79038972977915987adbef0e425 (diff)
downloadlua-9243c414d92c253edd908f438caa31e2aa16f3f4.tar.gz
lua-9243c414d92c253edd908f438caa31e2aa16f3f4.tar.bz2
lua-9243c414d92c253edd908f438caa31e2aa16f3f4.zip
first version of empty entries in tables
(so that, in the future, tables can contain regular nil entries)
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c58
1 files changed, 30 insertions, 28 deletions
diff --git a/lgc.c b/lgc.c
index 7cb3c18d..8245dc21 100644
--- a/lgc.c
+++ b/lgc.c
@@ -145,12 +145,13 @@ static GCObject **getgclist (GCObject *o) {
145** Clear keys for empty entries in tables. If entry is empty 145** Clear keys for empty entries in tables. If entry is empty
146** and its key is not marked, mark its entry as dead. This allows the 146** and its key is not marked, mark its entry as dead. This allows the
147** collection of the key, but keeps its entry in the table (its removal 147** collection of the key, but keeps its entry in the table (its removal
148** could break a chain). Other places never manipulate dead keys, 148** could break a chain). The main feature of a dead key is that it must
149** because its associated nil value is enough to signal that the entry 149** be different from any other value, to do not disturb searches.
150** is logically empty. 150** Other places never manipulate dead keys, because its associated empty
151** value is enough to signal that the entry is logically empty.
151*/ 152*/
152static void removeentry (Node *n) { 153static void clearkey (Node *n) {
153 lua_assert(ttisnil(gval(n))); 154 lua_assert(isempty(gval(n)));
154 if (keyiswhite(n)) 155 if (keyiswhite(n))
155 setdeadkey(n); /* unused and unmarked key; remove it */ 156 setdeadkey(n); /* unused and unmarked key; remove it */
156} 157}
@@ -386,8 +387,8 @@ static void traverseweakvalue (global_State *g, Table *h) {
386 worth traversing it now just to check) */ 387 worth traversing it now just to check) */
387 int hasclears = (h->sizearray > 0); 388 int hasclears = (h->sizearray > 0);
388 for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ 389 for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
389 if (ttisnil(gval(n))) /* entry is empty? */ 390 if (isempty(gval(n))) /* entry is empty? */
390 removeentry(n); /* remove it */ 391 clearkey(n); /* clear its key */
391 else { 392 else {
392 lua_assert(!keyisnil(n)); 393 lua_assert(!keyisnil(n));
393 markkey(g, n); 394 markkey(g, n);
@@ -428,8 +429,8 @@ static int traverseephemeron (global_State *g, Table *h) {
428 } 429 }
429 /* traverse hash part */ 430 /* traverse hash part */
430 for (n = gnode(h, 0); n < limit; n++) { 431 for (n = gnode(h, 0); n < limit; n++) {
431 if (ttisnil(gval(n))) /* entry is empty? */ 432 if (isempty(gval(n))) /* entry is empty? */
432 removeentry(n); /* remove it */ 433 clearkey(n); /* clear its key */
433 else if (iscleared(g, gckeyN(n))) { /* key is not marked (yet)? */ 434 else if (iscleared(g, gckeyN(n))) { /* key is not marked (yet)? */
434 hasclears = 1; /* table must be cleared */ 435 hasclears = 1; /* table must be cleared */
435 if (valiswhite(gval(n))) /* value not marked yet? */ 436 if (valiswhite(gval(n))) /* value not marked yet? */
@@ -461,8 +462,8 @@ static void traversestrongtable (global_State *g, Table *h) {
461 for (i = 0; i < h->sizearray; i++) /* traverse array part */ 462 for (i = 0; i < h->sizearray; i++) /* traverse array part */
462 markvalue(g, &h->array[i]); 463 markvalue(g, &h->array[i]);
463 for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ 464 for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
464 if (ttisnil(gval(n))) /* entry is empty? */ 465 if (isempty(gval(n))) /* entry is empty? */
465 removeentry(n); /* remove it */ 466 clearkey(n); /* clear its key */
466 else { 467 else {
467 lua_assert(!keyisnil(n)); 468 lua_assert(!keyisnil(n));
468 markkey(g, n); 469 markkey(g, n);
@@ -681,15 +682,16 @@ static void clearprotolist (global_State *g) {
681/* 682/*
682** clear entries with unmarked keys from all weaktables in list 'l' 683** clear entries with unmarked keys from all weaktables in list 'l'
683*/ 684*/
684static void clearkeys (global_State *g, GCObject *l) { 685static void clearbykeys (global_State *g, GCObject *l) {
685 for (; l; l = gco2t(l)->gclist) { 686 for (; l; l = gco2t(l)->gclist) {
686 Table *h = gco2t(l); 687 Table *h = gco2t(l);
687 Node *n, *limit = gnodelast(h); 688 Node *limit = gnodelast(h);
689 Node *n;
688 for (n = gnode(h, 0); n < limit; n++) { 690 for (n = gnode(h, 0); n < limit; n++) {
689 if (!ttisnil(gval(n)) && (iscleared(g, gckeyN(n)))) /* unmarked key? */ 691 if (isempty(gval(n))) /* is entry empty? */
690 setnilvalue(gval(n)); /* clear value */ 692 clearkey(n); /* clear its key */
691 if (ttisnil(gval(n))) /* is entry empty? */ 693 else if (iscleared(g, gckeyN(n))) /* unmarked key? */
692 removeentry(n); /* remove it from table */ 694 setempty(gval(n)); /* remove entry */
693 } 695 }
694 } 696 }
695} 697}
@@ -699,7 +701,7 @@ static void clearkeys (global_State *g, GCObject *l) {
699** clear entries with unmarked values from all weaktables in list 'l' up 701** clear entries with unmarked values from all weaktables in list 'l' up
700** to element 'f' 702** to element 'f'
701*/ 703*/
702static void clearvalues (global_State *g, GCObject *l, GCObject *f) { 704static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
703 for (; l != f; l = gco2t(l)->gclist) { 705 for (; l != f; l = gco2t(l)->gclist) {
704 Table *h = gco2t(l); 706 Table *h = gco2t(l);
705 Node *n, *limit = gnodelast(h); 707 Node *n, *limit = gnodelast(h);
@@ -707,13 +709,13 @@ static void clearvalues (global_State *g, GCObject *l, GCObject *f) {
707 for (i = 0; i < h->sizearray; i++) { 709 for (i = 0; i < h->sizearray; i++) {
708 TValue *o = &h->array[i]; 710 TValue *o = &h->array[i];
709 if (iscleared(g, gcvalueN(o))) /* value was collected? */ 711 if (iscleared(g, gcvalueN(o))) /* value was collected? */
710 setnilvalue(o); /* remove value */ 712 setempty(o); /* remove entry */
711 } 713 }
712 for (n = gnode(h, 0); n < limit; n++) { 714 for (n = gnode(h, 0); n < limit; n++) {
713 if (iscleared(g, gcvalueN(gval(n)))) /* unmarked value? */ 715 if (iscleared(g, gcvalueN(gval(n)))) /* unmarked value? */
714 setnilvalue(gval(n)); /* clear value */ 716 setempty(gval(n)); /* remove entry */
715 if (ttisnil(gval(n))) /* is entry empty? */ 717 if (isempty(gval(n))) /* is entry empty? */
716 removeentry(n); /* remove it from table */ 718 clearkey(n); /* clear its key */
717 } 719 }
718 } 720 }
719} 721}
@@ -1372,8 +1374,8 @@ static lu_mem atomic (lua_State *L) {
1372 convergeephemerons(g); 1374 convergeephemerons(g);
1373 /* at this point, all strongly accessible objects are marked. */ 1375 /* at this point, all strongly accessible objects are marked. */
1374 /* Clear values from weak tables, before checking finalizers */ 1376 /* Clear values from weak tables, before checking finalizers */
1375 clearvalues(g, g->weak, NULL); 1377 clearbyvalues(g, g->weak, NULL);
1376 clearvalues(g, g->allweak, NULL); 1378 clearbyvalues(g, g->allweak, NULL);
1377 origweak = g->weak; origall = g->allweak; 1379 origweak = g->weak; origall = g->allweak;
1378 separatetobefnz(g, 0); /* separate objects to be finalized */ 1380 separatetobefnz(g, 0); /* separate objects to be finalized */
1379 work += markbeingfnz(g); /* mark objects that will be finalized */ 1381 work += markbeingfnz(g); /* mark objects that will be finalized */
@@ -1381,11 +1383,11 @@ static lu_mem atomic (lua_State *L) {
1381 convergeephemerons(g); 1383 convergeephemerons(g);
1382 /* at this point, all resurrected objects are marked. */ 1384 /* at this point, all resurrected objects are marked. */
1383 /* remove dead objects from weak tables */ 1385 /* remove dead objects from weak tables */
1384 clearkeys(g, g->ephemeron); /* clear keys from all ephemeron tables */ 1386 clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron tables */
1385 clearkeys(g, g->allweak); /* clear keys from all 'allweak' tables */ 1387 clearbykeys(g, g->allweak); /* clear keys from all 'allweak' tables */
1386 /* clear values from resurrected weak tables */ 1388 /* clear values from resurrected weak tables */
1387 clearvalues(g, g->weak, origweak); 1389 clearbyvalues(g, g->weak, origweak);
1388 clearvalues(g, g->allweak, origall); 1390 clearbyvalues(g, g->allweak, origall);
1389 luaS_clearcache(g); 1391 luaS_clearcache(g);
1390 clearprotolist(g); 1392 clearprotolist(g);
1391 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ 1393 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */