aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-10-07 11:45:23 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-10-12 12:29:09 -0300
commitc23cc86c542449db47bdb21e9550203309bef045 (patch)
tree1b7876f7ad26feef4a3ab18f29d3b0b03deabfb2
parent171dcd7d745566e69c61845599705707500a104e (diff)
downloadlua-c23cc86c542449db47bdb21e9550203309bef045.tar.gz
lua-c23cc86c542449db47bdb21e9550203309bef045.tar.bz2
lua-c23cc86c542449db47bdb21e9550203309bef045.zip
Details
- After converting a generic GCObject to a specific type ('gco2*'), avoid using the original GCObject (to reduce aliasing). - Small corrections in comments in 'lopcodes.h' - Added tests about who calls __close metamethods
-rw-r--r--lfunc.c2
-rw-r--r--lgc.c30
-rw-r--r--lopcodes.h4
-rw-r--r--testes/locals.lua23
4 files changed, 45 insertions, 14 deletions
diff --git a/lfunc.c b/lfunc.c
index 88d45328..c4360f09 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -53,7 +53,7 @@ void luaF_initupvals (lua_State *L, LClosure *cl) {
53 uv->v = &uv->u.value; /* make it closed */ 53 uv->v = &uv->u.value; /* make it closed */
54 setnilvalue(uv->v); 54 setnilvalue(uv->v);
55 cl->upvals[i] = uv; 55 cl->upvals[i] = uv;
56 luaC_objbarrier(L, cl, o); 56 luaC_objbarrier(L, cl, uv);
57 } 57 }
58} 58}
59 59
diff --git a/lgc.c b/lgc.c
index 3b8d0ed6..03326df3 100644
--- a/lgc.c
+++ b/lgc.c
@@ -301,7 +301,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
301 if (upisopen(uv)) 301 if (upisopen(uv))
302 set2gray(uv); /* open upvalues are kept gray */ 302 set2gray(uv); /* open upvalues are kept gray */
303 else 303 else
304 set2black(o); /* closed upvalues are visited here */ 304 set2black(uv); /* closed upvalues are visited here */
305 markvalue(g, uv->v); /* mark its content */ 305 markvalue(g, uv->v); /* mark its content */
306 break; 306 break;
307 } 307 }
@@ -309,7 +309,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
309 Udata *u = gco2u(o); 309 Udata *u = gco2u(o);
310 if (u->nuvalue == 0) { /* no user values? */ 310 if (u->nuvalue == 0) { /* no user values? */
311 markobjectN(g, u->metatable); /* mark its metatable */ 311 markobjectN(g, u->metatable); /* mark its metatable */
312 set2black(o); /* nothing else to mark */ 312 set2black(u); /* nothing else to mark */
313 break; 313 break;
314 } 314 }
315 /* else... */ 315 /* else... */
@@ -770,12 +770,16 @@ static void freeobj (lua_State *L, GCObject *o) {
770 case LUA_VUPVAL: 770 case LUA_VUPVAL:
771 freeupval(L, gco2upv(o)); 771 freeupval(L, gco2upv(o));
772 break; 772 break;
773 case LUA_VLCL: 773 case LUA_VLCL: {
774 luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); 774 LClosure *cl = gco2lcl(o);
775 luaM_freemem(L, cl, sizeLclosure(cl->nupvalues));
775 break; 776 break;
776 case LUA_VCCL: 777 }
777 luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); 778 case LUA_VCCL: {
779 CClosure *cl = gco2ccl(o);
780 luaM_freemem(L, cl, sizeCclosure(cl->nupvalues));
778 break; 781 break;
782 }
779 case LUA_VTABLE: 783 case LUA_VTABLE:
780 luaH_free(L, gco2t(o)); 784 luaH_free(L, gco2t(o));
781 break; 785 break;
@@ -787,13 +791,17 @@ static void freeobj (lua_State *L, GCObject *o) {
787 luaM_freemem(L, o, sizeudata(u->nuvalue, u->len)); 791 luaM_freemem(L, o, sizeudata(u->nuvalue, u->len));
788 break; 792 break;
789 } 793 }
790 case LUA_VSHRSTR: 794 case LUA_VSHRSTR: {
791 luaS_remove(L, gco2ts(o)); /* remove it from hash table */ 795 TString *ts = gco2ts(o);
792 luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); 796 luaS_remove(L, ts); /* remove it from hash table */
797 luaM_freemem(L, ts, sizelstring(ts->shrlen));
793 break; 798 break;
794 case LUA_VLNGSTR: 799 }
795 luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); 800 case LUA_VLNGSTR: {
801 TString *ts = gco2ts(o);
802 luaM_freemem(L, ts, sizelstring(ts->u.lnglen));
796 break; 803 break;
804 }
797 default: lua_assert(0); 805 default: lua_assert(0);
798 } 806 }
799} 807}
diff --git a/lopcodes.h b/lopcodes.h
index 122e5d21..120cdd94 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -261,7 +261,7 @@ OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */
261OP_UNM,/* A B R[A] := -R[B] */ 261OP_UNM,/* A B R[A] := -R[B] */
262OP_BNOT,/* A B R[A] := ~R[B] */ 262OP_BNOT,/* A B R[A] := ~R[B] */
263OP_NOT,/* A B R[A] := not R[B] */ 263OP_NOT,/* A B R[A] := not R[B] */
264OP_LEN,/* A B R[A] := length of R[B] */ 264OP_LEN,/* A B R[A] := #R[B] (length operator) */
265 265
266OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */ 266OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */
267 267
@@ -297,7 +297,7 @@ OP_TFORPREP,/* A Bx create upvalue for R[A + 3]; pc+=Bx */
297OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */ 297OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */
298OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */ 298OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */
299 299
300OP_SETLIST,/* A B C k R[A][(C-1)*FPF+i] := R[A+i], 1 <= i <= B */ 300OP_SETLIST,/* A B C k R[A][C+i] := R[A+i], 1 <= i <= B */
301 301
302OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */ 302OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */
303 303
diff --git a/testes/locals.lua b/testes/locals.lua
index f5e96244..df44b86f 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -246,6 +246,11 @@ do
246 246
247 X = false 247 X = false
248 foo = function (x) 248 foo = function (x)
249 local _<close> = func2close(function ()
250 -- without errors, enclosing function should be still active when
251 -- __close is called
252 assert(debug.getinfo(2).name == "foo")
253 end)
249 local _<close> = closescope 254 local _<close> = closescope
250 local y = 15 255 local y = 15
251 return y 256 return y
@@ -343,6 +348,18 @@ local function endwarn ()
343end 348end
344 349
345 350
351-- errors inside __close can generate a warning instead of an
352-- error. This new 'assert' force them to appear.
353local function assert(cond, msg)
354 if not cond then
355 local line = debug.getinfo(2).currentline or "?"
356 msg = string.format("assertion failed! line %d (%s)\n", line, msg or "")
357 io.stderr:write(msg)
358 os.exit(1)
359 end
360end
361
362
346local function checkwarn (msg) 363local function checkwarn (msg)
347 if T then 364 if T then
348 assert(string.find(_WARN, msg)) 365 assert(string.find(_WARN, msg))
@@ -406,11 +423,15 @@ do print("testing errors in __close")
406 423
407 local x <close> = 424 local x <close> =
408 func2close(function (self, msg) 425 func2close(function (self, msg)
426 -- after error, 'foo' was discarded, so caller now
427 -- must be 'pcall'
428 assert(debug.getinfo(2).name == "pcall")
409 assert(msg == 4) 429 assert(msg == 4)
410 end) 430 end)
411 431
412 local x1 <close> = 432 local x1 <close> =
413 func2close(function (self, msg) 433 func2close(function (self, msg)
434 assert(debug.getinfo(2).name == "pcall")
414 checkwarn("@y") 435 checkwarn("@y")
415 assert(msg == 4) 436 assert(msg == 4)
416 error("@x1") 437 error("@x1")
@@ -420,6 +441,7 @@ do print("testing errors in __close")
420 441
421 local y <close> = 442 local y <close> =
422 func2close(function (self, msg) 443 func2close(function (self, msg)
444 assert(debug.getinfo(2).name == "pcall")
423 assert(msg == 4) -- error in body 445 assert(msg == 4) -- error in body
424 checkwarn("@z") 446 checkwarn("@z")
425 error("@y") 447 error("@y")
@@ -428,6 +450,7 @@ do print("testing errors in __close")
428 local first = true 450 local first = true
429 local z <close> = 451 local z <close> =
430 func2close(function (self, msg) 452 func2close(function (self, msg)
453 assert(debug.getinfo(2).name == "pcall")
431 -- 'z' close is called once 454 -- 'z' close is called once
432 assert(first and msg == 4) 455 assert(first and msg == 4)
433 first = false 456 first = false