Bläddra i källkod

Missing GC barrier in 'luaV_finishset'

Roberto Ierusalimschy 4 månader sedan
förälder
incheckning
c2dc6e8e94
3 ändrade filer med 19 tillägg och 3 borttagningar
  1. 1 2
      lapi.c
  2. 3 1
      lvm.c
  3. 15 0
      testes/gc.lua

+ 1 - 2
lapi.c

@@ -888,9 +888,8 @@ LUA_API void lua_settable (lua_State *L, int idx) {
   api_checkpop(L, 2);
   t = index2value(L, idx);
   luaV_fastset(t, s2v(L->top.p - 2), s2v(L->top.p - 1), hres, luaH_pset);
-  if (hres == HOK) {
+  if (hres == HOK)
     luaV_finishfastset(L, t, s2v(L->top.p - 1));
-  }
   else
     luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), hres);
   L->top.p -= 2;  /* pop index and value */

+ 3 - 1
lvm.c

@@ -362,8 +362,10 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
     }
     t = tm;  /* else repeat assignment over 'tm' */
     luaV_fastset(t, key, val, hres, luaH_pset);
-    if (hres == HOK)
+    if (hres == HOK) {
+      luaV_finishfastset(L, t, val);
       return;  /* done */
+    }
     /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */
   }
   luaG_runerror(L, "'__newindex' chain too long; possible loop");

+ 15 - 0
testes/gc.lua

@@ -600,6 +600,21 @@ if T then
 end
 
 
+if T then
+  collectgarbage("stop")
+  T.gcstate("pause")
+  local sup = {x = 0}
+  local a = setmetatable({}, {__newindex = sup})
+  T.gcstate("enteratomic")
+  assert(T.gccolor(sup) == "black")
+  a.x = {}   -- should not break the invariant
+  assert(not (T.gccolor(sup) == "black" and T.gccolor(sup.x) == "white"))
+  T.gcstate("pause")  -- complete the GC cycle
+  sup.x.y = 10
+  collectgarbage("restart")
+end
+
+
 if T then
   print("emergency collections")
   collectgarbage()