diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-03-14 12:37:19 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-03-14 12:37:19 -0300 |
| commit | c2dc6e8e947ed0c7b18d452592f722f56ee1f96a (patch) | |
| tree | 2d39698d94992e158199db58d53693496250d2b6 | |
| parent | 22974326ca0d4f893849ce722cc1d65b3e228f42 (diff) | |
| download | lua-c2dc6e8e947ed0c7b18d452592f722f56ee1f96a.tar.gz lua-c2dc6e8e947ed0c7b18d452592f722f56ee1f96a.tar.bz2 lua-c2dc6e8e947ed0c7b18d452592f722f56ee1f96a.zip | |
Missing GC barrier in 'luaV_finishset'
| -rw-r--r-- | lapi.c | 3 | ||||
| -rw-r--r-- | lvm.c | 4 | ||||
| -rw-r--r-- | testes/gc.lua | 15 |
3 files changed, 19 insertions, 3 deletions
| @@ -888,9 +888,8 @@ LUA_API void lua_settable (lua_State *L, int idx) { | |||
| 888 | api_checkpop(L, 2); | 888 | api_checkpop(L, 2); |
| 889 | t = index2value(L, idx); | 889 | t = index2value(L, idx); |
| 890 | luaV_fastset(t, s2v(L->top.p - 2), s2v(L->top.p - 1), hres, luaH_pset); | 890 | luaV_fastset(t, s2v(L->top.p - 2), s2v(L->top.p - 1), hres, luaH_pset); |
| 891 | if (hres == HOK) { | 891 | if (hres == HOK) |
| 892 | luaV_finishfastset(L, t, s2v(L->top.p - 1)); | 892 | luaV_finishfastset(L, t, s2v(L->top.p - 1)); |
| 893 | } | ||
| 894 | else | 893 | else |
| 895 | luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), hres); | 894 | luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), hres); |
| 896 | L->top.p -= 2; /* pop index and value */ | 895 | L->top.p -= 2; /* pop index and value */ |
| @@ -362,8 +362,10 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, | |||
| 362 | } | 362 | } |
| 363 | t = tm; /* else repeat assignment over 'tm' */ | 363 | t = tm; /* else repeat assignment over 'tm' */ |
| 364 | luaV_fastset(t, key, val, hres, luaH_pset); | 364 | luaV_fastset(t, key, val, hres, luaH_pset); |
| 365 | if (hres == HOK) | 365 | if (hres == HOK) { |
| 366 | luaV_finishfastset(L, t, val); | ||
| 366 | return; /* done */ | 367 | return; /* done */ |
| 368 | } | ||
| 367 | /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */ | 369 | /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */ |
| 368 | } | 370 | } |
| 369 | luaG_runerror(L, "'__newindex' chain too long; possible loop"); | 371 | luaG_runerror(L, "'__newindex' chain too long; possible loop"); |
diff --git a/testes/gc.lua b/testes/gc.lua index 96eadad8..0693837c 100644 --- a/testes/gc.lua +++ b/testes/gc.lua | |||
| @@ -601,6 +601,21 @@ end | |||
| 601 | 601 | ||
| 602 | 602 | ||
| 603 | if T then | 603 | if T then |
| 604 | collectgarbage("stop") | ||
| 605 | T.gcstate("pause") | ||
| 606 | local sup = {x = 0} | ||
| 607 | local a = setmetatable({}, {__newindex = sup}) | ||
| 608 | T.gcstate("enteratomic") | ||
| 609 | assert(T.gccolor(sup) == "black") | ||
| 610 | a.x = {} -- should not break the invariant | ||
| 611 | assert(not (T.gccolor(sup) == "black" and T.gccolor(sup.x) == "white")) | ||
| 612 | T.gcstate("pause") -- complete the GC cycle | ||
| 613 | sup.x.y = 10 | ||
| 614 | collectgarbage("restart") | ||
| 615 | end | ||
| 616 | |||
| 617 | |||
| 618 | if T then | ||
| 604 | print("emergency collections") | 619 | print("emergency collections") |
| 605 | collectgarbage() | 620 | collectgarbage() |
| 606 | collectgarbage() | 621 | collectgarbage() |
