Sfoglia il codice sorgente

Simpler code for 'traversetable'

Check the mode in a separate function (getmode), instead of using
comma expressions inside the 'if' condition.
Roberto Ierusalimschy 1 mese fa
parent
commit
8cd7ae7da0
2 ha cambiato i file con 31 aggiunte e 13 eliminazioni
  1. 26 13
      lgc.c
  2. 5 0
      testes/gc.lua

+ 26 - 13
lgc.c

@@ -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;
+  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);
-  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? */
+  switch (getmode(g, h)) {
+    case 0:  /* not weak */
+      traversestrongtable(g, h);
+      break;
+    case 1:  /* weak values */
       traverseweakvalue(g, h);
-    else if (!weakvalue)  /* strong values? */
+      break;
+    case 2:  /* weak keys */
       traverseephemeron(g, h, 0);
-    else  /* all weak */
+      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;
 }
 

+ 5 - 0
testes/gc.lua

@@ -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 = {}