diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-10-07 11:45:23 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-10-12 12:29:09 -0300 |
commit | c23cc86c542449db47bdb21e9550203309bef045 (patch) | |
tree | 1b7876f7ad26feef4a3ab18f29d3b0b03deabfb2 | |
parent | 171dcd7d745566e69c61845599705707500a104e (diff) | |
download | lua-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.c | 2 | ||||
-rw-r--r-- | lgc.c | 30 | ||||
-rw-r--r-- | lopcodes.h | 4 | ||||
-rw-r--r-- | testes/locals.lua | 23 |
4 files changed, 45 insertions, 14 deletions
@@ -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 | ||
@@ -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 | } |
@@ -261,7 +261,7 @@ OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */ | |||
261 | OP_UNM,/* A B R[A] := -R[B] */ | 261 | OP_UNM,/* A B R[A] := -R[B] */ |
262 | OP_BNOT,/* A B R[A] := ~R[B] */ | 262 | OP_BNOT,/* A B R[A] := ~R[B] */ |
263 | OP_NOT,/* A B R[A] := not R[B] */ | 263 | OP_NOT,/* A B R[A] := not R[B] */ |
264 | OP_LEN,/* A B R[A] := length of R[B] */ | 264 | OP_LEN,/* A B R[A] := #R[B] (length operator) */ |
265 | 265 | ||
266 | OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */ | 266 | OP_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 */ | |||
297 | OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */ | 297 | OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */ |
298 | OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */ | 298 | OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */ |
299 | 299 | ||
300 | OP_SETLIST,/* A B C k R[A][(C-1)*FPF+i] := R[A+i], 1 <= i <= B */ | 300 | OP_SETLIST,/* A B C k R[A][C+i] := R[A+i], 1 <= i <= B */ |
301 | 301 | ||
302 | OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */ | 302 | OP_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 () | |||
343 | end | 348 | end |
344 | 349 | ||
345 | 350 | ||
351 | -- errors inside __close can generate a warning instead of an | ||
352 | -- error. This new 'assert' force them to appear. | ||
353 | local 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 | ||
360 | end | ||
361 | |||
362 | |||
346 | local function checkwarn (msg) | 363 | local 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 |