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
Diffstat (limited to '')
| -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 |
