static int traversetable (global_State *g, Table *h) { const TValue *mode = gfasttm(g, h->metatable, TM_MODE); markobject(g, h->metatable); if (mode && ttisstring(mode)) { /* is there a weak mode? */ int weakkey = (strchr(svalue(mode), 'k') != NULL); int weakvalue = (strchr(svalue(mode), 'v') != NULL); if (weakkey || weakvalue) { /* is really weak? */ black2gray(obj2gco(h)); /* keep table gray */ if (!weakkey) { /* strong keys? */ traverseweakvalue(g, h); return TRAVCOST + sizenode(h); } else if (!weakvalue) { /* strong values? */ traverseephemeron(g, h); return TRAVCOST + h->sizearray + sizenode(h); } else { linktable(h, &g->allweak); /* nothing to traverse now */ return TRAVCOST; } } /* else go through */ } traversestrongtable(g, h); return TRAVCOST + h->sizearray + (2 * sizenode(h)); }
static void convergeephemerons (global_State *g) { int changed; do { GCObject *w; GCObject *next = g->ephemeron; /* get ephemeron list */ g->ephemeron = NULL; /* tables may return to this list when traversed */ changed = 0; while ((w = next) != NULL) { next = gco2t(w)->gclist; if (traverseephemeron(g, gco2t(w))) { /* traverse marked some value? */ propagateall(g); /* propagate changes */ changed = 1; /* will have to revisit all ephemeron tables */ } } } while (changed); }
static lu_mem traversetable (global_State *g, Table *h) { const char *weakkey, *weakvalue; const TValue *mode = gfasttm(g, h->metatable, TM_MODE); markobjectN(g, h->metatable); if (mode && ttisstring(mode) && /* is there a weak mode? */ ((weakkey = strchr(svalue(mode), 'k')), (weakvalue = strchr(svalue(mode), 'v')), (weakkey || weakvalue))) { /* is really weak? */ black2gray(h); /* keep table gray */ if (!weakkey) /* strong keys? */ traverseweakvalue(g, h); else if (!weakvalue) /* strong values? */ traverseephemeron(g, h); else /* all weak */ linkgclist(h, g->allweak); /* nothing to traverse now */ } else /* not weak */ traversestrongtable(g, h); return sizeof(Table) + sizeof(TValue) * h->sizearray + sizeof(Node) * cast(size_t, sizenode(h)); }