Improve debug support.
This commit is contained in:
@@ -28,8 +28,6 @@ import org.luaj.vm2.LoadState.LuaCompiler;
|
||||
import org.luaj.vm2.lib.BaseLib;
|
||||
import org.luaj.vm2.lib.DebugLib;
|
||||
import org.luaj.vm2.lib.ResourceFinder;
|
||||
import org.luaj.vm2.lib.jme.JmePlatform;
|
||||
import org.luaj.vm2.lib.jse.JsePlatform;
|
||||
|
||||
/**
|
||||
* Global environment used by luaj.
|
||||
@@ -65,8 +63,6 @@ public class Globals extends LuaTable {
|
||||
|
||||
public LuaCompiler compiler = null;
|
||||
|
||||
public LuaThread.CallStack callstack = new LuaThread.CallStack();
|
||||
|
||||
public BaseLib baselib;
|
||||
|
||||
public LuaValue errorfunc;
|
||||
|
||||
@@ -188,14 +188,14 @@ public class LuaClosure extends LuaFunction {
|
||||
UpValue[] openups = p.p.length>0? new UpValue[p.p.length]: null;
|
||||
|
||||
// debug wants args to this function
|
||||
if (globals != null)
|
||||
globals.callstack.onCall( this, varargs, stack );
|
||||
if (DebugLib.DEBUG_ENABLED && globals != null)
|
||||
globals.running_thread.callstack.onCall( this, varargs, stack );
|
||||
|
||||
// process instructions
|
||||
try {
|
||||
while ( true ) {
|
||||
if (DebugLib.DEBUG_ENABLED && globals != null)
|
||||
globals.callstack.onInstruction( pc, v, top );
|
||||
globals.running_thread.callstack.onInstruction( pc, v, top );
|
||||
|
||||
// pull out instruction
|
||||
i = code[pc++];
|
||||
@@ -502,8 +502,8 @@ public class LuaClosure extends LuaFunction {
|
||||
processErrorHooks(le, p, pc);
|
||||
throw le;
|
||||
} finally {
|
||||
if (globals != null)
|
||||
globals.callstack.onReturn();
|
||||
if (DebugLib.DEBUG_ENABLED && globals != null)
|
||||
globals.running_thread.callstack.onReturn();
|
||||
if ( openups != null )
|
||||
for ( int u=openups.length; --u>=0; )
|
||||
if ( openups[u] != null )
|
||||
@@ -534,7 +534,7 @@ public class LuaClosure extends LuaFunction {
|
||||
+ (p.lineinfo != null && pc >= 0 && pc < p.lineinfo.length? String.valueOf(p.lineinfo[pc]): "?");
|
||||
le.traceback = errorHook(le.getMessage());
|
||||
if (DebugLib.DEBUG_ENABLED && globals != null && globals.debuglib != null)
|
||||
le.traceback += globals.callstack.traceback(le.level);
|
||||
le.traceback += globals.running_thread.callstack.traceback(le.level);
|
||||
}
|
||||
|
||||
private UpValue findupval(LuaValue[] stack, short idx, UpValue[] openups) {
|
||||
@@ -567,7 +567,7 @@ public class LuaClosure extends LuaFunction {
|
||||
String msg = e.getMessage();
|
||||
if ( msg == null ) return null;
|
||||
if ( globals == null ) return msg;
|
||||
LuaFunction f = globals.callstack.getFunction(1);
|
||||
LuaFunction f = globals.running_thread.callstack.getFunction(1);
|
||||
if ( ! (f instanceof LuaClosure) ) return msg;
|
||||
LuaClosure c = (LuaClosure) f;
|
||||
LuaString file = c.p.source != null ? c.p.source: valueOf("?");
|
||||
|
||||
@@ -69,4 +69,10 @@ public class LuaFunction extends LuaValue {
|
||||
*/
|
||||
public void initupvalue1(LuaValue env) {
|
||||
}
|
||||
|
||||
public String tojstring() {
|
||||
String s = getClass().getName();
|
||||
return "function: " + s.substring(s.lastIndexOf('.')+1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ package org.luaj.vm2;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import org.luaj.vm2.LuaThread.CallFrame;
|
||||
import org.luaj.vm2.lib.DebugLib;
|
||||
|
||||
/**
|
||||
@@ -85,7 +84,7 @@ public class LuaThread extends LuaValue {
|
||||
|
||||
public final State state;
|
||||
|
||||
final CallStack callstack = new CallStack();
|
||||
public final CallStack callstack = new CallStack();
|
||||
|
||||
public static final int MAX_CALLSTACK = 256;
|
||||
|
||||
@@ -360,38 +359,51 @@ public class LuaThread extends LuaValue {
|
||||
if (DebugLib.DEBUG_ENABLED && DebugLib.TRACE & f.isclosure())
|
||||
Print.printState(f.checkclosure(), pc, stack, top, v);
|
||||
}
|
||||
public int getLine() {
|
||||
if (!f.isclosure())
|
||||
return 0;
|
||||
LuaClosure c = (LuaClosure) f;
|
||||
Prototype p = c.p;
|
||||
if (p.lineinfo == null || pc < 0 || pc >= p.lineinfo[pc])
|
||||
return 0;
|
||||
return p.lineinfo[pc];
|
||||
}
|
||||
public Varargs getLocal(int i) {
|
||||
if (!f.isclosure())
|
||||
return NONE;
|
||||
LuaClosure c = (LuaClosure) f;
|
||||
Prototype p = c.p;
|
||||
if (i < 1 || i > stack.length)
|
||||
if (p.locvars != null && p.locvars.length >= i)
|
||||
return varargsOf(stack[i-1], p.locvars[i-1].varname);
|
||||
else
|
||||
return stack[i-1];
|
||||
return NONE;
|
||||
LuaString name = getlocalname(i);
|
||||
if ( name != null )
|
||||
return varargsOf( name, stack[i-1] );
|
||||
else
|
||||
return NIL;
|
||||
}
|
||||
public Varargs setLocal(int i, LuaValue value) {
|
||||
if (!f.isclosure())
|
||||
return NONE;
|
||||
LuaClosure c = (LuaClosure) f;
|
||||
Prototype p = c.p;
|
||||
if (i < 1 || i > stack.length)
|
||||
return NONE;
|
||||
stack[i] = value;
|
||||
if (p.locvars != null && p.locvars.length >= i)
|
||||
return p.locvars[i-1].varname;
|
||||
return NONE;
|
||||
LuaString name = getlocalname(i);
|
||||
if ( name != null ) {
|
||||
stack[i-1] = value;
|
||||
return name;
|
||||
} else {
|
||||
return NIL;
|
||||
}
|
||||
}
|
||||
public int currentline() {
|
||||
if ( !f.isclosure() ) return -1;
|
||||
int[] li = ((LuaClosure)f).p.lineinfo;
|
||||
return li==null || pc<0 || pc>=li.length? -1: li[pc];
|
||||
}
|
||||
public LuaString[] getfunckind() {
|
||||
if ( !f.isclosure() || pc<0 ) return null;
|
||||
Prototype p = ((LuaClosure)f).p;
|
||||
int stackpos = (p.code[pc] >> 6) & 0xff;
|
||||
return DebugLib.getobjname(p, pc, stackpos);
|
||||
}
|
||||
public String sourceline() {
|
||||
if ( !f.isclosure() ) return f.tojstring();
|
||||
String s = ((LuaClosure)f).p.source.tojstring();
|
||||
int line = currentline();
|
||||
return (s.startsWith("@")||s.startsWith("=")? s.substring(1): s) + ":" + line;
|
||||
}
|
||||
public String tracename() {
|
||||
LuaString[] kind = getfunckind();
|
||||
if ( kind == null )
|
||||
return "function ?";
|
||||
return "function "+kind[0].tojstring();
|
||||
}
|
||||
public LuaString getlocalname(int index) {
|
||||
if ( !f.isclosure() ) return null;
|
||||
return ((LuaClosure)f).p.getlocalname(index, pc);
|
||||
}
|
||||
public String tojstring() {
|
||||
return tracename()+" "+sourceline();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -208,11 +208,11 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||
final class pcall extends VarArgFunction {
|
||||
public Varargs invoke(Varargs args) {
|
||||
LuaValue func = args.checkvalue(1);
|
||||
globals.callstack.onCall(this);
|
||||
globals.running_thread.callstack.onCall(this);
|
||||
try {
|
||||
return pcall(func,args.subargs(2),null);
|
||||
} finally {
|
||||
globals.callstack.onReturn();
|
||||
globals.running_thread.callstack.onReturn();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -350,11 +350,11 @@ public class BaseLib extends OneArgFunction implements ResourceFinder {
|
||||
// "xpcall", // (f, err) -> result1, ...
|
||||
final class xpcall extends VarArgFunction {
|
||||
public Varargs invoke(Varargs args) {
|
||||
globals.callstack.onCall(this);
|
||||
globals.running_thread.callstack.onCall(this);
|
||||
try {
|
||||
return pcall(args.arg1(),NONE,args.checkvalue(2));
|
||||
} finally {
|
||||
globals.callstack.onReturn();
|
||||
globals.running_thread.callstack.onReturn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ public class DebugLib extends OneArgFunction {
|
||||
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running_thread;
|
||||
LuaValue func = args.optfunction(a++, null);
|
||||
LuaValue local = args.checkvalue(a++);
|
||||
return thread.globals.callstack.findCallFrame(func).getLocal(local.toint());
|
||||
return thread.callstack.findCallFrame(func).getLocal(local.toint());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ public class DebugLib extends OneArgFunction {
|
||||
LuaValue func = args.optfunction(a++, null);
|
||||
LuaValue local = args.checkvalue(a++);
|
||||
LuaValue value = args.checkvalue(a++);
|
||||
return thread.globals.callstack.findCallFrame(func).setLocal(local.toint(), value);
|
||||
return thread.callstack.findCallFrame(func).setLocal(local.toint(), value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,7 +291,7 @@ public class DebugLib extends OneArgFunction {
|
||||
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running_thread;
|
||||
String message = args.optjstring(a++, null);
|
||||
int level = args.optint(a++,1);
|
||||
String tb = globals.callstack.traceback(level-1);
|
||||
String tb = thread.callstack.traceback(level-1);
|
||||
return valueOf(message!=null? message+"\n"+tb: tb);
|
||||
}
|
||||
}
|
||||
@@ -339,7 +339,7 @@ public class DebugLib extends OneArgFunction {
|
||||
LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running_thread;
|
||||
LuaValue func = args.arg(a++);
|
||||
String what = args.optjstring(a++, "nSluf");
|
||||
LuaThread.CallStack callstack = thread.globals.callstack;
|
||||
LuaThread.CallStack callstack = thread.callstack;
|
||||
|
||||
// find the stack info
|
||||
LuaThread.CallFrame frame;
|
||||
@@ -376,7 +376,7 @@ public class DebugLib extends OneArgFunction {
|
||||
break;
|
||||
}
|
||||
case 'l': {
|
||||
int line = frame.getLine();
|
||||
int line = frame.currentline();
|
||||
info.set( CURRENTLINE, valueOf(line) );
|
||||
break;
|
||||
}
|
||||
@@ -385,7 +385,7 @@ public class DebugLib extends OneArgFunction {
|
||||
break;
|
||||
}
|
||||
case 'n': {
|
||||
LuaString[] kind = getfunckind(frame.f);
|
||||
LuaString[] kind = frame.getfunckind();
|
||||
info.set(NAME, kind!=null? kind[0]: QMARK);
|
||||
info.set(NAMEWHAT, kind!=null? kind[1]: EMPTYSTRING);
|
||||
break;
|
||||
@@ -394,18 +394,14 @@ public class DebugLib extends OneArgFunction {
|
||||
info.set( FUNC, frame.f );
|
||||
break;
|
||||
}
|
||||
/*
|
||||
case 'L': {
|
||||
LuaTable lines = new LuaTable();
|
||||
info.set(ACTIVELINES, lines);
|
||||
if ( c !+ null && c.luainfo != null ) {
|
||||
int line = c.luainfo.currentline();
|
||||
if ( line >= 0 )
|
||||
lines.set(1, IntValue.valueOf(line));
|
||||
}
|
||||
int line = frame.currentline();
|
||||
if ( line >= 0 )
|
||||
lines.set(1, valueOf(line));
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
return info;
|
||||
@@ -427,10 +423,68 @@ public class DebugLib extends OneArgFunction {
|
||||
if (!x) throw new RuntimeException("lua_assert failed");
|
||||
}
|
||||
|
||||
private LuaString[] getfunckind(LuaFunction f) {
|
||||
return null;
|
||||
// return StrValue[] { name, namewhat } if found, null if not
|
||||
public static LuaString[] getobjname(Prototype p, int lastpc, int reg) {
|
||||
int pc = lastpc; // currentpc(L, ci);
|
||||
LuaString name = p.getlocalname(reg + 1, pc);
|
||||
if (name != null) /* is a local? */
|
||||
return new LuaString[] { name, LOCAL };
|
||||
|
||||
/* else try symbolic execution */
|
||||
pc = findsetreg(p, lastpc, reg);
|
||||
if (pc != -1) { /* could find instruction? */
|
||||
int i = p.code[pc];
|
||||
switch (Lua.GET_OPCODE(i)) {
|
||||
case Lua.OP_MOVE: {
|
||||
int a = Lua.GETARG_A(i);
|
||||
int b = Lua.GETARG_B(i); /* move from `b' to `a' */
|
||||
if (b < a)
|
||||
return getobjname(p, pc, b); /* get name for `b' */
|
||||
break;
|
||||
}
|
||||
case Lua.OP_GETTABUP:
|
||||
case Lua.OP_GETTABLE: {
|
||||
int k = Lua.GETARG_C(i); /* key index */
|
||||
int t = Lua.GETARG_Bx(i); /* table index */
|
||||
LuaString vn = (Lua.GET_OPCODE(i) == Lua.OP_GETTABLE) /* name of indexed variable */
|
||||
? p.getlocalname(t + 1, pc)
|
||||
: (t < p.upvalues.length ? p.upvalues[t].name : QMARK);
|
||||
name = kname(p, k);
|
||||
return new LuaString[] { name, vn.eq_b(ENV)? GLOBAL: FIELD };
|
||||
}
|
||||
case Lua.OP_GETUPVAL: {
|
||||
int u = Lua.GETARG_B(i); /* upvalue index */
|
||||
name = u < p.upvalues.length ? p.upvalues[u].name : QMARK;
|
||||
return new LuaString[] { name, UPVALUE };
|
||||
}
|
||||
case Lua.OP_LOADK:
|
||||
case Lua.OP_LOADKX: {
|
||||
int b = (Lua.GET_OPCODE(i) == Lua.OP_LOADK) ? Lua.GETARG_Bx(i)
|
||||
: Lua.GETARG_Ax(p.code[pc + 1]);
|
||||
if (p.k[b].isstring()) {
|
||||
name = p.k[b].strvalue();
|
||||
return new LuaString[] { name, CONSTANT };
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Lua.OP_SELF: {
|
||||
int k = Lua.GETARG_C(i); /* key index */
|
||||
name = kname(p, k);
|
||||
return new LuaString[] { name, METHOD };
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null; /* no useful name found */
|
||||
}
|
||||
|
||||
static LuaString kname(Prototype p, int c) {
|
||||
if (Lua.ISK(c) && p.k[Lua.INDEXK(c)].isstring())
|
||||
return p.k[Lua.INDEXK(c)].strvalue();
|
||||
else
|
||||
return QMARK;
|
||||
}
|
||||
|
||||
/*
|
||||
** try to find last instruction before 'lastpc' that modified register 'reg'
|
||||
|
||||
Reference in New Issue
Block a user