mirror of
https://github.com/lua/lua
synced 2024-11-22 04:41:23 +03:00
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
This commit is contained in:
parent
171dcd7d74
commit
c23cc86c54
2
lfunc.c
2
lfunc.c
@ -53,7 +53,7 @@ void luaF_initupvals (lua_State *L, LClosure *cl) {
|
|||||||
uv->v = &uv->u.value; /* make it closed */
|
uv->v = &uv->u.value; /* make it closed */
|
||||||
setnilvalue(uv->v);
|
setnilvalue(uv->v);
|
||||||
cl->upvals[i] = uv;
|
cl->upvals[i] = uv;
|
||||||
luaC_objbarrier(L, cl, o);
|
luaC_objbarrier(L, cl, uv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
30
lgc.c
30
lgc.c
@ -301,7 +301,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
|
|||||||
if (upisopen(uv))
|
if (upisopen(uv))
|
||||||
set2gray(uv); /* open upvalues are kept gray */
|
set2gray(uv); /* open upvalues are kept gray */
|
||||||
else
|
else
|
||||||
set2black(o); /* closed upvalues are visited here */
|
set2black(uv); /* closed upvalues are visited here */
|
||||||
markvalue(g, uv->v); /* mark its content */
|
markvalue(g, uv->v); /* mark its content */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -309,7 +309,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
|
|||||||
Udata *u = gco2u(o);
|
Udata *u = gco2u(o);
|
||||||
if (u->nuvalue == 0) { /* no user values? */
|
if (u->nuvalue == 0) { /* no user values? */
|
||||||
markobjectN(g, u->metatable); /* mark its metatable */
|
markobjectN(g, u->metatable); /* mark its metatable */
|
||||||
set2black(o); /* nothing else to mark */
|
set2black(u); /* nothing else to mark */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* else... */
|
/* else... */
|
||||||
@ -770,12 +770,16 @@ static void freeobj (lua_State *L, GCObject *o) {
|
|||||||
case LUA_VUPVAL:
|
case LUA_VUPVAL:
|
||||||
freeupval(L, gco2upv(o));
|
freeupval(L, gco2upv(o));
|
||||||
break;
|
break;
|
||||||
case LUA_VLCL:
|
case LUA_VLCL: {
|
||||||
luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues));
|
LClosure *cl = gco2lcl(o);
|
||||||
|
luaM_freemem(L, cl, sizeLclosure(cl->nupvalues));
|
||||||
break;
|
break;
|
||||||
case LUA_VCCL:
|
}
|
||||||
luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues));
|
case LUA_VCCL: {
|
||||||
|
CClosure *cl = gco2ccl(o);
|
||||||
|
luaM_freemem(L, cl, sizeCclosure(cl->nupvalues));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case LUA_VTABLE:
|
case LUA_VTABLE:
|
||||||
luaH_free(L, gco2t(o));
|
luaH_free(L, gco2t(o));
|
||||||
break;
|
break;
|
||||||
@ -787,13 +791,17 @@ static void freeobj (lua_State *L, GCObject *o) {
|
|||||||
luaM_freemem(L, o, sizeudata(u->nuvalue, u->len));
|
luaM_freemem(L, o, sizeudata(u->nuvalue, u->len));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_VSHRSTR:
|
case LUA_VSHRSTR: {
|
||||||
luaS_remove(L, gco2ts(o)); /* remove it from hash table */
|
TString *ts = gco2ts(o);
|
||||||
luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen));
|
luaS_remove(L, ts); /* remove it from hash table */
|
||||||
|
luaM_freemem(L, ts, sizelstring(ts->shrlen));
|
||||||
break;
|
break;
|
||||||
case LUA_VLNGSTR:
|
}
|
||||||
luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen));
|
case LUA_VLNGSTR: {
|
||||||
|
TString *ts = gco2ts(o);
|
||||||
|
luaM_freemem(L, ts, sizelstring(ts->u.lnglen));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default: lua_assert(0);
|
default: lua_assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,7 +261,7 @@ OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */
|
|||||||
OP_UNM,/* A B R[A] := -R[B] */
|
OP_UNM,/* A B R[A] := -R[B] */
|
||||||
OP_BNOT,/* A B R[A] := ~R[B] */
|
OP_BNOT,/* A B R[A] := ~R[B] */
|
||||||
OP_NOT,/* A B R[A] := not R[B] */
|
OP_NOT,/* A B R[A] := not R[B] */
|
||||||
OP_LEN,/* A B R[A] := length of R[B] */
|
OP_LEN,/* A B R[A] := #R[B] (length operator) */
|
||||||
|
|
||||||
OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */
|
OP_CONCAT,/* A B R[A] := R[A].. ... ..R[A + B - 1] */
|
||||||
|
|
||||||
@ -297,7 +297,7 @@ OP_TFORPREP,/* A Bx create upvalue for R[A + 3]; pc+=Bx */
|
|||||||
OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */
|
OP_TFORCALL,/* A C R[A+4], ... ,R[A+3+C] := R[A](R[A+1], R[A+2]); */
|
||||||
OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */
|
OP_TFORLOOP,/* A Bx if R[A+2] ~= nil then { R[A]=R[A+2]; pc -= Bx } */
|
||||||
|
|
||||||
OP_SETLIST,/* A B C k R[A][(C-1)*FPF+i] := R[A+i], 1 <= i <= B */
|
OP_SETLIST,/* A B C k R[A][C+i] := R[A+i], 1 <= i <= B */
|
||||||
|
|
||||||
OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */
|
OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */
|
||||||
|
|
||||||
|
@ -246,6 +246,11 @@ do
|
|||||||
|
|
||||||
X = false
|
X = false
|
||||||
foo = function (x)
|
foo = function (x)
|
||||||
|
local _<close> = func2close(function ()
|
||||||
|
-- without errors, enclosing function should be still active when
|
||||||
|
-- __close is called
|
||||||
|
assert(debug.getinfo(2).name == "foo")
|
||||||
|
end)
|
||||||
local _<close> = closescope
|
local _<close> = closescope
|
||||||
local y = 15
|
local y = 15
|
||||||
return y
|
return y
|
||||||
@ -343,6 +348,18 @@ local function endwarn ()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- errors inside __close can generate a warning instead of an
|
||||||
|
-- error. This new 'assert' force them to appear.
|
||||||
|
local function assert(cond, msg)
|
||||||
|
if not cond then
|
||||||
|
local line = debug.getinfo(2).currentline or "?"
|
||||||
|
msg = string.format("assertion failed! line %d (%s)\n", line, msg or "")
|
||||||
|
io.stderr:write(msg)
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
local function checkwarn (msg)
|
local function checkwarn (msg)
|
||||||
if T then
|
if T then
|
||||||
assert(string.find(_WARN, msg))
|
assert(string.find(_WARN, msg))
|
||||||
@ -406,11 +423,15 @@ do print("testing errors in __close")
|
|||||||
|
|
||||||
local x <close> =
|
local x <close> =
|
||||||
func2close(function (self, msg)
|
func2close(function (self, msg)
|
||||||
|
-- after error, 'foo' was discarded, so caller now
|
||||||
|
-- must be 'pcall'
|
||||||
|
assert(debug.getinfo(2).name == "pcall")
|
||||||
assert(msg == 4)
|
assert(msg == 4)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local x1 <close> =
|
local x1 <close> =
|
||||||
func2close(function (self, msg)
|
func2close(function (self, msg)
|
||||||
|
assert(debug.getinfo(2).name == "pcall")
|
||||||
checkwarn("@y")
|
checkwarn("@y")
|
||||||
assert(msg == 4)
|
assert(msg == 4)
|
||||||
error("@x1")
|
error("@x1")
|
||||||
@ -420,6 +441,7 @@ do print("testing errors in __close")
|
|||||||
|
|
||||||
local y <close> =
|
local y <close> =
|
||||||
func2close(function (self, msg)
|
func2close(function (self, msg)
|
||||||
|
assert(debug.getinfo(2).name == "pcall")
|
||||||
assert(msg == 4) -- error in body
|
assert(msg == 4) -- error in body
|
||||||
checkwarn("@z")
|
checkwarn("@z")
|
||||||
error("@y")
|
error("@y")
|
||||||
@ -428,6 +450,7 @@ do print("testing errors in __close")
|
|||||||
local first = true
|
local first = true
|
||||||
local z <close> =
|
local z <close> =
|
||||||
func2close(function (self, msg)
|
func2close(function (self, msg)
|
||||||
|
assert(debug.getinfo(2).name == "pcall")
|
||||||
-- 'z' close is called once
|
-- 'z' close is called once
|
||||||
assert(first and msg == 4)
|
assert(first and msg == 4)
|
||||||
first = false
|
first = false
|
||||||
|
Loading…
Reference in New Issue
Block a user