aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lgc.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/lgc.c b/lgc.c
index cada07d9..bbaa5ff7 100644
--- a/lgc.c
+++ b/lgc.c
@@ -126,7 +126,6 @@ static l_mem objsize (GCObject *o) {
126 CClosure *cl = gco2ccl(o); 126 CClosure *cl = gco2ccl(o);
127 res = sizeCclosure(cl->nupvalues); 127 res = sizeCclosure(cl->nupvalues);
128 break; 128 break;
129 break;
130 } 129 }
131 case LUA_VUSERDATA: { 130 case LUA_VUSERDATA: {
132 Udata *u = gco2u(o); 131 Udata *u = gco2u(o);
@@ -465,6 +464,8 @@ static void restartcollection (global_State *g) {
465** TOUCHED1 objects need to be in the list. TOUCHED2 doesn't need to go 464** TOUCHED1 objects need to be in the list. TOUCHED2 doesn't need to go
466** back to a gray list, but then it must become OLD. (That is what 465** back to a gray list, but then it must become OLD. (That is what
467** 'correctgraylist' does when it finds a TOUCHED2 object.) 466** 'correctgraylist' does when it finds a TOUCHED2 object.)
467** This function is a no-op in incremental mode, as objects cannot be
468** marked as touched in that mode.
468*/ 469*/
469static void genlink (global_State *g, GCObject *o) { 470static void genlink (global_State *g, GCObject *o) {
470 lua_assert(isblack(o)); 471 lua_assert(isblack(o));
@@ -480,7 +481,8 @@ static void genlink (global_State *g, GCObject *o) {
480** Traverse a table with weak values and link it to proper list. During 481** Traverse a table with weak values and link it to proper list. During
481** propagate phase, keep it in 'grayagain' list, to be revisited in the 482** propagate phase, keep it in 'grayagain' list, to be revisited in the
482** atomic phase. In the atomic phase, if table has any white value, 483** atomic phase. In the atomic phase, if table has any white value,
483** put it in 'weak' list, to be cleared. 484** put it in 'weak' list, to be cleared; otherwise, call 'genlink'
485** to check table age in generational mode.
484*/ 486*/
485static void traverseweakvalue (global_State *g, Table *h) { 487static void traverseweakvalue (global_State *g, Table *h) {
486 Node *n, *limit = gnodelast(h); 488 Node *n, *limit = gnodelast(h);
@@ -501,6 +503,8 @@ static void traverseweakvalue (global_State *g, Table *h) {
501 linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ 503 linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */
502 else if (hasclears) 504 else if (hasclears)
503 linkgclist(h, g->weak); /* has to be cleared later */ 505 linkgclist(h, g->weak); /* has to be cleared later */
506 else
507 genlink(g, obj2gco(h));
504} 508}
505 509
506 510
@@ -585,25 +589,41 @@ static void traversestrongtable (global_State *g, Table *h) {
585} 589}
586 590
587 591
588static l_mem traversetable (global_State *g, Table *h) { 592/*
589 const char *weakkey, *weakvalue; 593** (result & 1) iff weak values; (result & 2) iff weak keys.
594*/
595static int getmode (global_State *g, Table *h) {
590 const TValue *mode = gfasttm(g, h->metatable, TM_MODE); 596 const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
591 TString *smode; 597 if (mode == NULL || !ttisshrstring(mode))
598 return 0; /* ignore non-(short)string modes */
599 else {
600 const char *smode = getshrstr(tsvalue(mode));
601 const char *weakkey = strchr(smode, 'k');
602 const char *weakvalue = strchr(smode, 'v');
603 return ((weakkey != NULL) << 1) | (weakvalue != NULL);
604 }
605}
606
607
608static l_mem traversetable (global_State *g, Table *h) {
592 markobjectN(g, h->metatable); 609 markobjectN(g, h->metatable);
593 if (mode && ttisshrstring(mode) && /* is there a weak mode? */ 610 switch (getmode(g, h)) {
594 (cast_void(smode = tsvalue(mode)), 611 case 0: /* not weak */
595 cast_void(weakkey = strchr(getshrstr(smode), 'k')), 612 traversestrongtable(g, h);
596 cast_void(weakvalue = strchr(getshrstr(smode), 'v')), 613 break;
597 (weakkey || weakvalue))) { /* is really weak? */ 614 case 1: /* weak values */
598 if (!weakkey) /* strong keys? */
599 traverseweakvalue(g, h); 615 traverseweakvalue(g, h);
600 else if (!weakvalue) /* strong values? */ 616 break;
617 case 2: /* weak keys */
601 traverseephemeron(g, h, 0); 618 traverseephemeron(g, h, 0);
602 else /* all weak */ 619 break;
603 linkgclist(h, g->allweak); /* nothing to traverse now */ 620 case 3: /* all weak; nothing to traverse */
621 if (g->gcstate == GCSpropagate)
622 linkgclist(h, g->grayagain); /* must visit again its metatable */
623 else
624 linkgclist(h, g->allweak); /* must clear collected entries */
625 break;
604 } 626 }
605 else /* not weak */
606 traversestrongtable(g, h);
607 return 1 + 2*sizenode(h) + h->asize; 627 return 1 + 2*sizenode(h) + h->asize;
608} 628}
609 629