new implementation for tailcalls and error handling

This commit is contained in:
Roberto Ierusalimschy
2002-08-05 11:51:21 -03:00
parent 5037196f6f
commit 0417a4bb0b
2 changed files with 35 additions and 40 deletions

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ldebug.c,v 1.124 2002/07/08 18:21:33 roberto Exp roberto $ ** $Id: ldebug.c,v 1.125 2002/07/16 14:26:56 roberto Exp roberto $
** Debug Interface ** Debug Interface
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -29,14 +29,16 @@
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
static int isLua (CallInfo *ci) {
return isLfunction (ci->base - 1);
}
static int currentpc (lua_State *L, CallInfo *ci) { static int currentpc (lua_State *L, CallInfo *ci) {
if (!isLua(ci)) return -1; /* function is not a Lua function? */ if (!isLua(ci)) return -1; /* function is not a Lua function? */
/* next function is not using the same `pc'? (not a Lua->Lua call?) */ if (ci->pc && ci->pc != &luaV_callingmark)
if (ci == L->ci || !isLua(ci+1) || ci->u.l.pc != (ci+1)->u.l.pc) ci->u.l.savedpc = *ci->pc; /* `pc' may not be saved; save it */
ci->savedpc = *ci->u.l.pc; /* may not be saved; save it */
/* function's pc is saved */ /* function's pc is saved */
return pcRel(ci->savedpc, ci_func(ci)->l.p); return pcRel(ci->u.l.savedpc, ci_func(ci)->l.p);
} }
@@ -49,8 +51,18 @@ static int currentline (lua_State *L, CallInfo *ci) {
} }
LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask) { /*
** save all `pc's from active Lua functions
*/
void luaG_saveallpcs (lua_State *L) {
CallInfo *ci; CallInfo *ci;
/* first save all not saved `pc's */
for (ci = L->ci; ci != L->base_ci; ci--)
currentpc(L, ci); /* save `pc', if necessary */
}
LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask) {
int allow; int allow;
lua_lock(L); lua_lock(L);
allow = allowhook(L); allow = allowhook(L);
@@ -60,8 +72,7 @@ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask) {
L->hookmask = mask; L->hookmask = mask;
setallowhook(L, allow); setallowhook(L, allow);
resethookcount(L); resethookcount(L);
for (ci = L->base_ci; ci <= L->ci; ci++) luaG_saveallpcs(L);
currentpc(L, ci); /* update `savedpc' */
lua_unlock(L); lua_unlock(L);
return 1; return 1;
} }
@@ -143,7 +154,7 @@ static void infoLproto (lua_Debug *ar, Proto *f) {
static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) { static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) {
Closure *cl; Closure *cl;
if (ttype(func) == LUA_TFUNCTION) if (ttisfunction(func))
cl = clvalue(func); cl = clvalue(func);
else { else {
luaG_runerror(L, "value for `lua_getinfo' is not a function"); luaG_runerror(L, "value for `lua_getinfo' is not a function");
@@ -167,7 +178,7 @@ static const char *travglobals (lua_State *L, const TObject *o) {
int i = sizenode(g); int i = sizenode(g);
while (i--) { while (i--) {
Node *n = node(g, i); Node *n = node(g, i);
if (luaO_rawequalObj(o, val(n)) && ttype(key(n)) == LUA_TSTRING) if (luaO_rawequalObj(o, val(n)) && ttisstring(key(n)))
return getstr(tsvalue(key(n))); return getstr(tsvalue(key(n)));
} }
return NULL; return NULL;
@@ -208,7 +219,7 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
break; break;
} }
case 'u': { case 'u': {
ar->nups = (ttype(f) == LUA_TFUNCTION) ? clvalue(f)->c.nupvalues : 0; ar->nups = (ttisfunction(f)) ? clvalue(f)->c.nupvalues : 0;
break; break;
} }
case 'n': { case 'n': {
@@ -222,10 +233,6 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
status = 2; status = 2;
break; break;
} }
case 'c': {
ar->isprotected = (ci && luaD_isprotected(L, ci));
break;
}
default: status = 0; /* invalid option */ default: status = 0; /* invalid option */
} }
} }
@@ -330,7 +337,7 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
} }
case OP_GETGLOBAL: case OP_GETGLOBAL:
case OP_SETGLOBAL: { case OP_SETGLOBAL: {
check(ttype(&pt->k[b]) == LUA_TSTRING); check(ttisstring(&pt->k[b]));
break; break;
} }
case OP_SELF: { case OP_SELF: {
@@ -357,7 +364,8 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
pc += b; /* do the jump */ pc += b; /* do the jump */
break; break;
} }
case OP_CALL: { case OP_CALL:
case OP_TAILCALL: {
if (b != 0) { if (b != 0) {
checkreg(pt, a+b-1); checkreg(pt, a+b-1);
} }
@@ -370,7 +378,6 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) {
if (reg >= a) last = pc; /* affect all registers above base */ if (reg >= a) last = pc; /* affect all registers above base */
break; break;
} }
case OP_TAILCALL:
case OP_RETURN: { case OP_RETURN: {
b--; /* b = num. returns */ b--; /* b = num. returns */
if (b > 0) checkreg(pt, a+b-1); if (b > 0) checkreg(pt, a+b-1);
@@ -411,7 +418,7 @@ int luaG_checkcode (const Proto *pt) {
static const char *kname (Proto *p, int c) { static const char *kname (Proto *p, int c) {
c = c - MAXSTACK; c = c - MAXSTACK;
if (c >= 0 && ttype(&p->k[c]) == LUA_TSTRING) if (c >= 0 && ttisstring(&p->k[c]))
return svalue(&p->k[c]); return svalue(&p->k[c]);
else else
return "?"; return "?";
@@ -420,7 +427,7 @@ static const char *kname (Proto *p, int c) {
static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,
const char **name) { const char **name) {
if (isLua(ci)) { /* an active Lua function? */ if (isLua(ci)) { /* a Lua function? */
Proto *p = ci_func(ci)->l.p; Proto *p = ci_func(ci)->l.p;
int pc = currentpc(L, ci); int pc = currentpc(L, ci);
Instruction i; Instruction i;
@@ -431,7 +438,7 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,
lua_assert(pc != -1); lua_assert(pc != -1);
switch (GET_OPCODE(i)) { switch (GET_OPCODE(i)) {
case OP_GETGLOBAL: { case OP_GETGLOBAL: {
lua_assert(ttype(&p->k[GETARG_Bx(i)]) == LUA_TSTRING); lua_assert(ttisstring(&p->k[GETARG_Bx(i)]));
*name = svalue(&p->k[GETARG_Bx(i)]); *name = svalue(&p->k[GETARG_Bx(i)]);
return "global"; return "global";
} }
@@ -458,10 +465,8 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,
static Instruction getcurrentinstr (lua_State *L, CallInfo *ci) { static Instruction getcurrentinstr (lua_State *L, CallInfo *ci) {
if (ci == L->base_ci || !isLua(ci)) return (!isLua(ci)) ? (Instruction)(-1) :
return (Instruction)(-1); /* not an active Lua function */ ci_func(ci)->l.p->code[currentpc(L, ci)];
else
return ci_func(ci)->l.p->code[currentpc(L, ci)];
} }
@@ -497,8 +502,8 @@ void luaG_typeerror (lua_State *L, const TObject *o, const char *op) {
void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { void luaG_concaterror (lua_State *L, StkId p1, StkId p2) {
if (ttype(p1) == LUA_TSTRING) p1 = p2; if (ttisstring(p1)) p1 = p2;
lua_assert(ttype(p1) != LUA_TSTRING); lua_assert(!ttisstring(p1));
luaG_typeerror(L, p1, "concat"); luaG_typeerror(L, p1, "concat");
} }
@@ -540,19 +545,8 @@ static void addinfo (lua_State *L, int internal) {
void luaG_errormsg (lua_State *L, int internal) { void luaG_errormsg (lua_State *L, int internal) {
const TObject *errfunc; if (ttisstring(L->top - 1))
if (ttype(L->top - 1) == LUA_TSTRING)
addinfo(L, internal); addinfo(L, internal);
errfunc = luaH_getstr(hvalue(registry(L)), luaS_new(L, LUA_TRACEBACK));
if (ttype(errfunc) != LUA_TNIL) { /* is there an error function? */
setobj(L->top, errfunc); /* push function */
setobj(L->top + 1, L->top - 1); /* push error message */
L->top += 2;
luaD_call(L, L->top - 2, 1); /* call error function? */
}
else {
setnilvalue(L->top++);
}
luaD_throw(L, LUA_ERRRUN); luaD_throw(L, LUA_ERRRUN);
} }

View File

@@ -1,5 +1,5 @@
/* /*
** $Id: ldebug.h,v 1.24 2002/07/08 18:21:33 roberto Exp roberto $ ** $Id: ldebug.h,v 1.25 2002/07/08 20:22:08 roberto Exp roberto $
** Auxiliary functions from Debug Interface module ** Auxiliary functions from Debug Interface module
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@@ -23,6 +23,7 @@
#define allowhook(L) ((L->hookmask) & 1) #define allowhook(L) ((L->hookmask) & 1)
void luaG_saveallpcs (lua_State *L);
void luaG_typeerror (lua_State *L, const TObject *o, const char *opname); void luaG_typeerror (lua_State *L, const TObject *o, const char *opname);
void luaG_concaterror (lua_State *L, StkId p1, StkId p2); void luaG_concaterror (lua_State *L, StkId p1, StkId p2);
void luaG_aritherror (lua_State *L, StkId p1, const TObject *p2); void luaG_aritherror (lua_State *L, StkId p1, const TObject *p2);