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) {
|
private static StackInfo[] getstackinfo(LuaState vm, int level, int countlevels) {
|
||||||
StackInfo[] si = new StackInfo[countlevels];
|
StackInfo[] si = new StackInfo[countlevels];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
LClosure prevclosure = null;
|
||||||
for (int j=vm.cc; j>=0; --j) {
|
for (int j=vm.cc; j>=0; --j) {
|
||||||
|
|
||||||
CallInfo ci = vm.calls[j];
|
CallInfo ci = vm.calls[j];
|
||||||
int instr = ci.closure.p.code[ci.pc>0? ci.pc-1: 0];
|
LFunction f = ci.currentfunc(vm);
|
||||||
|
|
||||||
// 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() ) {
|
|
||||||
|
|
||||||
// add the lua closure
|
// java, or tailcall?
|
||||||
if ( j < vm.cc ) {
|
if ( f != null && (! f.isClosure() || f!=prevclosure) ) {
|
||||||
if ( (level--) <= 0 ) {
|
if ( (level--) <= 0 ) {
|
||||||
CallInfo ci1 = vm.calls[j+1];
|
si[i++] = new StackInfo( vm, ci, ci.currentfunca(vm), null, f);
|
||||||
LValue f1 = vm.calls[j+1].closure;
|
if ( i >= countlevels )
|
||||||
if ( f != f1 )
|
return si;
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
return si;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,4 +54,30 @@ public class CallInfo {
|
|||||||
return -1;
|
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
|
* @param message message to supply
|
||||||
*/
|
*/
|
||||||
public LuaErrorException(String message) {
|
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
|
* Construct the message around a specific vm and with a particular level of debug info
|
||||||
* @param vm
|
* @param vm
|
||||||
* @param message
|
* @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) {
|
public LuaErrorException(LuaState vm, String message, int level) {
|
||||||
super( addLineInfo( vm, message, level ) );
|
super( addLineInfo( vm, message, level ) );
|
||||||
@@ -74,7 +74,7 @@ public class LuaErrorException extends RuntimeException {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private static String addLineInfo(LuaState vm, String message, int level) {
|
private static String addLineInfo(LuaState vm, String message, int level) {
|
||||||
if ( level < 1 || message == null )
|
if ( level == 0 || message == null )
|
||||||
return message;
|
return message;
|
||||||
if ( vm == null ) {
|
if ( vm == null ) {
|
||||||
if ( LThread.running != 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.
|
* 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
|
* @return
|
||||||
*/
|
*/
|
||||||
protected String getFileLine(int level) {
|
protected String getFileLine(int level) {
|
||||||
|
LClosure c = null;
|
||||||
for (int j=cc; j>=0; --j) {
|
for (int j=cc; j>=0; --j) {
|
||||||
CallInfo ci = calls[j];
|
CallInfo ci = calls[j];
|
||||||
int instr = ci.closure.p.code[ci.pc>0? ci.pc-1: 0];
|
LFunction f = ci.currentfunc(this);
|
||||||
if ( Lua.GET_OPCODE(instr) == Lua.OP_CALL ) {
|
if ( f != null && (!f.isClosure() || f!=c) ) {
|
||||||
int a = Lua.GETARG_A(instr);
|
if ( level != -1 && (level--) <= 0 ) {
|
||||||
LValue f = stack[ci.base + a];
|
return "[Java]: "+f.toString();
|
||||||
if ( f.isFunction() ) {
|
|
||||||
if ( ! f.isClosure() ) {
|
|
||||||
if ( (level--) <= 0 ) {
|
|
||||||
return "[Java]: "+f.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( (level--) <= 0 ) {
|
|
||||||
return ci.closure.p.sourceshort()+":"+ci.currentline();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
c = ci.closure;
|
||||||
|
if ( (level--) <= 0 ) {
|
||||||
|
return c.p.sourceshort()+":"+ci.currentline();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@@ -1121,7 +1117,7 @@ public class LuaState extends Lua {
|
|||||||
* Raises an error with the default level.
|
* Raises an error with the default level.
|
||||||
*/
|
*/
|
||||||
public void error(String message) {
|
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_HOOKCOUNT: this.pushstring("count"); break;
|
||||||
case LUA_HOOKCALL: this.pushstring("call"); break;
|
case LUA_HOOKCALL: this.pushstring("call"); break;
|
||||||
case LUA_HOOKRET: this.pushstring("return"); break;
|
case LUA_HOOKRET: this.pushstring("return"); break;
|
||||||
case LUA_HOOKTAILRET: this.pushstring("return"); break;
|
case LUA_HOOKTAILRET: this.pushstring("tail return"); break;
|
||||||
default:
|
default:
|
||||||
lineval = LInteger.valueOf(line);
|
lineval = LInteger.valueOf(line);
|
||||||
this.pushstring("line");
|
this.pushstring("line");
|
||||||
|
|||||||
Reference in New Issue
Block a user