Simpler code for 'traversetable'

Check the mode in a separate function (getmode), instead of using
comma expressions inside the 'if' condition.
This commit is contained in:
Roberto Ierusalimschy 2025-06-16 15:50:12 -03:00
parent 0cecf1ab6d
commit 8cd7ae7da0
2 changed files with 35 additions and 17 deletions

47
lgc.c
View File

@ -589,25 +589,38 @@ static void traversestrongtable (global_State *g, Table *h) {
}
static l_mem traversetable (global_State *g, Table *h) {
const char *weakkey, *weakvalue;
/*
** (result & 1) iff weak values; (result & 2) iff weak keys.
*/
static int getmode (global_State *g, Table *h) {
const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
TString *smode;
markobjectN(g, h->metatable);
if (mode && ttisshrstring(mode) && /* is there a weak mode? */
(cast_void(smode = tsvalue(mode)),
cast_void(weakkey = strchr(getshrstr(smode), 'k')),
cast_void(weakvalue = strchr(getshrstr(smode), 'v')),
(weakkey || weakvalue))) { /* is really weak? */
if (!weakkey) /* strong keys? */
traverseweakvalue(g, h);
else if (!weakvalue) /* strong values? */
traverseephemeron(g, h, 0);
else /* all weak */
linkgclist(h, g->allweak); /* nothing to traverse now */
if (mode == NULL || !ttisshrstring(mode))
return 0; /* ignore non-(short)string modes */
else {
const char *smode = getshrstr(tsvalue(mode));
const char *weakkey = strchr(smode, 'k');
const char *weakvalue = strchr(smode, 'v');
return ((weakkey != NULL) << 1) | (weakvalue != NULL);
}
}
static l_mem traversetable (global_State *g, Table *h) {
markobjectN(g, h->metatable);
switch (getmode(g, h)) {
case 0: /* not weak */
traversestrongtable(g, h);
break;
case 1: /* weak values */
traverseweakvalue(g, h);
break;
case 2: /* weak keys */
traverseephemeron(g, h, 0);
break;
case 3: /* all weak */
linkgclist(h, g->allweak); /* nothing to traverse now */
break;
}
else /* not weak */
traversestrongtable(g, h);
return 1 + 2*sizenode(h) + h->asize;
}

View File

@ -288,6 +288,11 @@ x,y,z=nil
collectgarbage()
assert(next(a) == string.rep('$', 11))
do -- invalid mode
local a = setmetatable({}, {__mode = 34})
collectgarbage()
end
-- 'bug' in 5.1
a = {}