summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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) {
uv->v = &uv->u.value; /* make it closed */
setnilvalue(uv->v);
cl->upvals[i] = uv;
- luaC_objbarrier(L, cl, o);
+ luaC_objbarrier(L, cl, uv);
}
}
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) {
if (upisopen(uv))
set2gray(uv); /* open upvalues are kept gray */
else
- set2black(o); /* closed upvalues are visited here */
+ set2black(uv); /* closed upvalues are visited here */
markvalue(g, uv->v); /* mark its content */
break;
}
@@ -309,7 +309,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
Udata *u = gco2u(o);
if (u->nuvalue == 0) { /* no user values? */
markobjectN(g, u->metatable); /* mark its metatable */
- set2black(o); /* nothing else to mark */
+ set2black(u); /* nothing else to mark */
break;
}
/* else... */
@@ -770,12 +770,16 @@ static void freeobj (lua_State *L, GCObject *o) {
case LUA_VUPVAL:
freeupval(L, gco2upv(o));
break;
- case LUA_VLCL:
- luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues));
+ case LUA_VLCL: {
+ LClosure *cl = gco2lcl(o);
+ luaM_freemem(L, cl, sizeLclosure(cl->nupvalues));
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;
+ }
case LUA_VTABLE:
luaH_free(L, gco2t(o));
break;
@@ -787,13 +791,17 @@ static void freeobj (lua_State *L, GCObject *o) {
luaM_freemem(L, o, sizeudata(u->nuvalue, u->len));
break;
}
- case LUA_VSHRSTR:
- luaS_remove(L, gco2ts(o)); /* remove it from hash table */
- luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen));
+ case LUA_VSHRSTR: {
+ TString *ts = gco2ts(o);
+ luaS_remove(L, ts); /* remove it from hash table */
+ luaM_freemem(L, ts, sizelstring(ts->shrlen));
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;
+ }
default: lua_assert(0);
}
}
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] */
OP_UNM,/* A B R[A] := -R[B] */
OP_BNOT,/* A B R[A] := ~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] */
@@ -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_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]) */
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
X = false
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 y = 15
return y
@@ -343,6 +348,18 @@ local function endwarn ()
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)
if T then
assert(string.find(_WARN, msg))
@@ -406,11 +423,15 @@ do print("testing errors in __close")
local x <close> =
func2close(function (self, msg)
+ -- after error, 'foo' was discarded, so caller now
+ -- must be 'pcall'
+ assert(debug.getinfo(2).name == "pcall")
assert(msg == 4)
end)
local x1 <close> =
func2close(function (self, msg)
+ assert(debug.getinfo(2).name == "pcall")
checkwarn("@y")
assert(msg == 4)
error("@x1")
@@ -420,6 +441,7 @@ do print("testing errors in __close")
local y <close> =
func2close(function (self, msg)
+ assert(debug.getinfo(2).name == "pcall")
assert(msg == 4) -- error in body
checkwarn("@z")
error("@y")
@@ -428,6 +450,7 @@ do print("testing errors in __close")
local first = true
local z <close> =
func2close(function (self, msg)
+ assert(debug.getinfo(2).name == "pcall")
-- 'z' close is called once
assert(first and msg == 4)
first = false