Improve handling of tail calls in debug info
This commit is contained in:
@@ -483,47 +483,35 @@ public class DebugLib extends LFunction {
|
||||
private static StackInfo[] getstackinfo(LuaState vm, int level, int countlevels) {
|
||||
StackInfo[] si = new StackInfo[countlevels];
|
||||
int i = 0;
|
||||
LClosure prevclosure = null;
|
||||
for (int j=vm.cc; j>=0; --j) {
|
||||
|
||||
CallInfo ci = vm.calls[j];
|
||||
int instr = ci.closure.p.code[ci.pc>0? ci.pc-1: 0];
|
||||
|
||||
// java function?
|
||||
if ( Lua.GET_OPCODE(instr) == Lua.OP_CALL ) {
|
||||
int a = Lua.GETARG_A(instr);
|
||||
LValue f = vm.stack[ci.base + a];
|
||||
if ( f.isFunction() ) {
|
||||
LFunction f = ci.currentfunc(vm);
|
||||
|
||||
// add the lua closure
|
||||
if ( j < vm.cc ) {
|
||||
if ( (level--) <= 0 ) {
|
||||
CallInfo ci1 = vm.calls[j+1];
|
||||
LValue f1 = vm.calls[j+1].closure;
|
||||
if ( f != f1 )
|
||||
a = ci1.resultbase-ci.base;
|
||||
si[i++] = new StackInfo( vm, ci, a, ci1, null);
|
||||
if ( i >= countlevels )
|
||||
return si;
|
||||
}
|
||||
}
|
||||
|
||||
// is there also a java call?
|
||||
if ( ! f.isClosure() ) {
|
||||
if ( (level--) <= 0 ) {
|
||||
si[i++] = new StackInfo( vm, ci, a, null, (LFunction) f);
|
||||
if ( i >= countlevels )
|
||||
return si;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: tail calls, for loops
|
||||
// java, or tailcall?
|
||||
if ( f != null && (! f.isClosure() || f!=prevclosure) ) {
|
||||
if ( (level--) <= 0 ) {
|
||||
si[i++] = new StackInfo( vm, ci, ci.currentfunca(vm), null, f);
|
||||
if ( i >= countlevels )
|
||||
return si;
|
||||
}
|
||||
}
|
||||
|
||||
// add the lua closure
|
||||
if ( (level--) <= 0 ) {
|
||||
if (j>0 && vm.calls[j-1].currentfunc(vm) == ci.closure) {
|
||||
CallInfo caller = vm.calls[j-1];
|
||||
int callera = caller.currentfunca(vm);
|
||||
si[i++] = new StackInfo( vm, caller, callera, ci, ci.closure);
|
||||
} else {
|
||||
si[i++] = new StackInfo( vm, null, -1, ci, ci.closure);
|
||||
}
|
||||
if ( i >= countlevels )
|
||||
return si;
|
||||
}
|
||||
prevclosure = ci.closure;
|
||||
}
|
||||
|
||||
// first call is a plain call with no enclosing frame
|
||||
if ( (level--) <= 0 )
|
||||
si[i++] = new StackInfo(vm, null, -1, vm.calls[0], null);
|
||||
|
||||
return si;
|
||||
}
|
||||
|
||||
@@ -54,4 +54,30 @@ public class CallInfo {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param vm
|
||||
* @return current function executing, or null
|
||||
*/
|
||||
public LFunction currentfunc(LuaState vm) {
|
||||
int a = currentfunca(vm);
|
||||
if ( a >= 0 ) {
|
||||
LValue v = vm.stack[base + a];
|
||||
if ( v.isFunction() )
|
||||
return (LFunction) v;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param vm
|
||||
* @return register of the current function executing, or null
|
||||
*/
|
||||
public int currentfunca(LuaState vm) {
|
||||
int i = closure.p.code[pc>0? pc-1: 0];
|
||||
int op = Lua.GET_OPCODE(i);
|
||||
if ( op == Lua.OP_CALL || op == Lua.OP_TAILCALL )
|
||||
return Lua.GETARG_A(i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,14 +53,14 @@ public class LuaErrorException extends RuntimeException {
|
||||
* @param message message to supply
|
||||
*/
|
||||
public LuaErrorException(String message) {
|
||||
this(null, message, 1);
|
||||
this(null, message, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the message around a specific vm and with a particular level of debug info
|
||||
* @param vm
|
||||
* @param message
|
||||
* @param level
|
||||
* @param level 0 for no message, >=1 for current call or above, -1 for most recent lua call
|
||||
*/
|
||||
public LuaErrorException(LuaState vm, String message, int level) {
|
||||
super( addLineInfo( vm, message, level ) );
|
||||
@@ -74,7 +74,7 @@ public class LuaErrorException extends RuntimeException {
|
||||
* @return
|
||||
*/
|
||||
private static String addLineInfo(LuaState vm, String message, int level) {
|
||||
if ( level < 1 || message == null )
|
||||
if ( level == 0 || message == null )
|
||||
return message;
|
||||
if ( vm == null ) {
|
||||
if ( LThread.running != null )
|
||||
|
||||
@@ -1080,27 +1080,23 @@ public class LuaState extends Lua {
|
||||
|
||||
/**
|
||||
* Get the file line number info for a particular call frame.
|
||||
* @param cindex index into call stack
|
||||
* @param cindex index into call stack, or -1 to get first lua location
|
||||
* @return
|
||||
*/
|
||||
protected String getFileLine(int level) {
|
||||
LClosure c = null;
|
||||
for (int j=cc; j>=0; --j) {
|
||||
CallInfo ci = calls[j];
|
||||
int instr = ci.closure.p.code[ci.pc>0? ci.pc-1: 0];
|
||||
if ( Lua.GET_OPCODE(instr) == Lua.OP_CALL ) {
|
||||
int a = Lua.GETARG_A(instr);
|
||||
LValue f = stack[ci.base + a];
|
||||
if ( f.isFunction() ) {
|
||||
if ( ! f.isClosure() ) {
|
||||
if ( (level--) <= 0 ) {
|
||||
return "[Java]: "+f.toString();
|
||||
}
|
||||
}
|
||||
if ( (level--) <= 0 ) {
|
||||
return ci.closure.p.sourceshort()+":"+ci.currentline();
|
||||
}
|
||||
LFunction f = ci.currentfunc(this);
|
||||
if ( f != null && (!f.isClosure() || f!=c) ) {
|
||||
if ( level != -1 && (level--) <= 0 ) {
|
||||
return "[Java]: "+f.toString();
|
||||
}
|
||||
}
|
||||
c = ci.closure;
|
||||
if ( (level--) <= 0 ) {
|
||||
return c.p.sourceshort()+":"+ci.currentline();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -1121,7 +1117,7 @@ public class LuaState extends Lua {
|
||||
* Raises an error with the default level.
|
||||
*/
|
||||
public void error(String message) {
|
||||
throw new LuaErrorException( this, message, 1 );
|
||||
throw new LuaErrorException( this, message, -1 );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2462,7 +2458,7 @@ public class LuaState extends Lua {
|
||||
case LUA_HOOKCOUNT: this.pushstring("count"); break;
|
||||
case LUA_HOOKCALL: this.pushstring("call"); break;
|
||||
case LUA_HOOKRET: this.pushstring("return"); break;
|
||||
case LUA_HOOKTAILRET: this.pushstring("return"); break;
|
||||
case LUA_HOOKTAILRET: this.pushstring("tail return"); break;
|
||||
default:
|
||||
lineval = LInteger.valueOf(line);
|
||||
this.pushstring("line");
|
||||
|
||||
Reference in New Issue
Block a user