From e2646669d66bcffc9cb5a2337028dadb0cdfa53a Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Sat, 15 Sep 2012 16:11:20 +0000 Subject: [PATCH] Improve debug lib consistency with lua 5.2 --- src/core/org/luaj/vm2/LuaClosure.java | 35 +-- src/core/org/luaj/vm2/LuaError.java | 2 +- src/core/org/luaj/vm2/LuaThread.java | 187 +----------- src/core/org/luaj/vm2/lib/BaseLib.java | 14 +- src/core/org/luaj/vm2/lib/DebugLib.java | 273 ++++++++++++++++-- .../org/luaj/vm2/OrphanedThreadTest.java | 44 +-- 6 files changed, 287 insertions(+), 268 deletions(-) diff --git a/src/core/org/luaj/vm2/LuaClosure.java b/src/core/org/luaj/vm2/LuaClosure.java index 1d14cf5e..607761b1 100644 --- a/src/core/org/luaj/vm2/LuaClosure.java +++ b/src/core/org/luaj/vm2/LuaClosure.java @@ -192,15 +192,15 @@ public class LuaClosure extends LuaFunction { // TODO: use linked list. UpValue[] openups = p.p.length>0? new UpValue[stack.length]: null; - // debug wants args to this function - if (DebugLib.DEBUG_ENABLED && globals != null) - globals.running_thread.callstack.onCall( this, varargs, stack ); + // allow for debug hooks + if (globals != null && globals.debuglib != null) + globals.debuglib.onCall( this, varargs, stack ); // process instructions try { while ( true ) { - if (DebugLib.DEBUG_ENABLED && globals != null) - globals.running_thread.callstack.onInstruction( pc, v, top ); + if (globals != null && globals.debuglib != null) + globals.debuglib.onInstruction( pc, v, top ); // pull out instruction i = code[pc++]; @@ -507,12 +507,12 @@ public class LuaClosure extends LuaFunction { processErrorHooks(le, p, pc); throw le; } finally { - 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 ) openups[u].close(); + if (globals != null && globals.debuglib != null) + globals.debuglib.onReturn(); } } @@ -538,8 +538,8 @@ public class LuaClosure extends LuaFunction { le.fileline = (p.source != null? p.source.tojstring(): "?") + ":" + (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.running_thread.callstack.traceback(le.level); + if (globals != null && globals.debuglib != null) + le.traceback += globals.debuglib.traceback(le.level); } private UpValue findupval(LuaValue[] stack, short idx, UpValue[] openups) { @@ -562,21 +562,4 @@ public class LuaClosure extends LuaFunction { upValues[i].setValue(v); } - - /** - * Add file and line info to a message at a particular level - * @param message the String message to use - * @param level where to supply line info from in call stack - * */ - private String getFileLineMessage( Exception e, int pc ) { - String msg = e.getMessage(); - if ( msg == null ) return null; - if ( globals == null ) return msg; - 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("?"); - String line = c.p.lineinfo != null && pc < c.p.lineinfo.length? String.valueOf(c.p.lineinfo[pc]): "?"; - return file.tojstring() + ": " + line; - } } diff --git a/src/core/org/luaj/vm2/LuaError.java b/src/core/org/luaj/vm2/LuaError.java index 9ddcc469..c233ca41 100644 --- a/src/core/org/luaj/vm2/LuaError.java +++ b/src/core/org/luaj/vm2/LuaError.java @@ -48,7 +48,7 @@ public class LuaError extends RuntimeException { public String getMessage() { return traceback != null? traceback: - (fileline != null? fileline: "?:-1") + " " + super.getMessage(); + (fileline != null? fileline + " ": "") + super.getMessage(); } /** Construct LuaError when a program exception occurs. diff --git a/src/core/org/luaj/vm2/LuaThread.java b/src/core/org/luaj/vm2/LuaThread.java index 72c2a90c..fce6a5a3 100644 --- a/src/core/org/luaj/vm2/LuaThread.java +++ b/src/core/org/luaj/vm2/LuaThread.java @@ -84,21 +84,14 @@ public class LuaThread extends LuaValue { public final State state; - public final CallStack callstack = new CallStack(); - public static final int MAX_CALLSTACK = 256; /** Interval to check for LuaThread dereferencing. */ public static int GC_INTERVAL = 30000; - /** Thread-local used by DebugLib to store debugging state. */ - public Object debugState; - - public LuaValue hookfunc; - public boolean hookline; - public boolean hookcall; - public boolean hookrtrn; - public int hookcount; + /** Thread-local used by DebugLib to store debugging state. + * This is ano opaque value that should not be modified by applications. */ + public Object callstack; public final Globals globals; @@ -239,179 +232,5 @@ public class LuaThread extends LuaValue { } } } - - public static class CallStack { - final CallFrame[] frame = new CallFrame[MAX_CALLSTACK]; - int calls = 0; - - CallStack() { - for (int i = 0; i < MAX_CALLSTACK; ++i) - frame[i] = new CallFrame(); - } - - /** - * Method to indicate the start of a call - * @param stack - * @param varargs - * @see DebugLib - */ - public final void onCall(LuaFunction function) { - frame[calls++].set(function); -// if (DebugLib.DEBUG_ENABLED) -// DebugLib.debugOnCall(globals.running_thread, calls, function); - } - - public final void onCall(LuaClosure function, Varargs varargs, LuaValue[] stack) { - frame[calls++].set(function, varargs, stack); -// if (DebugLib.DEBUG_ENABLED) -// DebugLib.debugOnCall(globals.running_thread, calls, function); - } - - /** - * Method to signal the end of a call - * @see DebugLib - */ - public final void onReturn() { - frame[--calls].reset(); -// if (DebugLib.DEBUG_ENABLED) -// DebugLib.debugOnReturn(running_thread, calls); - } - - public final void onInstruction(int pc, Varargs v, int top) { - frame[calls-1].instr(pc, v, top); - } - - /** - * Get number of calls in stack - * @return number of calls in current call stack - * @see DebugLib - */ - public final int getCallstackDepth() { - return calls; - } - - /** - * Get the function at a particular level of the stack. - * @param level # of levels back from the top of the stack. - * @return LuaFunction, or null if beyond the stack limits. - */ - public LuaFunction getFunction(int level) { - return level>0 && level<=calls? frame[calls-level].f: null; - } - - /** - * Get the traceback starting at a specific level. - * @param level - * @return String containing the traceback. - */ - public String traceback(int level) { - StringBuffer sb = new StringBuffer(); - sb.append( "stack traceback:" ); - CallFrame c = getCallFrame(level); - if (c != null) { - sb.append("\n\t"); - sb.append( c.sourceline() ); - sb.append( " in " ); - while ( (c = getCallFrame(++level)) != null ) { - sb.append( c.tracename() ); - sb.append( "\n\t" ); - sb.append( c.sourceline() ); - sb.append( " in " ); - } - sb.append( "main chunk" ); - } - return sb.toString(); - } - - public CallFrame getCallFrame(int level) { - if (level < 1 || level >= calls) - return null; - return frame[calls-level]; - } - - public CallFrame findCallFrame(LuaValue func) { - for (int i = 1; i <= calls; ++i) - if (frame[calls-i].f == func) - return frame[i]; - return null; - } - - } - - public static class CallFrame { - public LuaFunction f; - public int pc; - int top; - Varargs v; - LuaValue[] stack; - boolean tail; - public void set(LuaClosure function, Varargs varargs, LuaValue[] stack) { - this.f = function; - this.v = varargs; - this.stack = stack; - this.tail = false; - } - public void set(LuaFunction function) { - this.f = function; - } - public void reset() { - this.f = null; - this.v = null; - this.stack = null; - } - public void instr(int pc, Varargs v, int top) { - this.pc = pc; - this.v = v; - this.top = top; - if (f.checkclosure().p.code[pc] == Lua.OP_TAILCALL) - this.tail = true; - if (DebugLib.TRACE) - Print.printState(f.checkclosure(), pc, stack, top, v); - } - public Varargs getLocal(int i) { - LuaString name = getlocalname(i); - if ( name != null ) - return varargsOf( name, stack[i-1] ); - else - return NIL; - } - public Varargs setLocal(int i, LuaValue value) { - 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 = f.checkclosure().p.lineinfo; - return li==null || pc<0 || pc>=li.length? -1: li[pc]; - } - public String sourceline() { - if ( !f.isclosure() ) return f.tojstring(); - String s = f.checkclosure().p.source.tojstring(); - int line = currentline(); - return (s.startsWith("@")||s.startsWith("=")? s.substring(1): s) + ":" + line; - } - public String tracename() { - LuaString[] kind = DebugLib.getfuncname(this); - if ( kind == null ) - return "function ?"; - return "function "+kind[0].tojstring(); - } - public LuaString getlocalname(int index) { - if ( !f.isclosure() ) return null; - return f.checkclosure().p.getlocalname(index, pc); - } - public String tojstring() { - return tracename()+" "+sourceline(); - } - public boolean istailcall() { - return tail; - } - - } } diff --git a/src/core/org/luaj/vm2/lib/BaseLib.java b/src/core/org/luaj/vm2/lib/BaseLib.java index 559a6e3e..5f2e123e 100644 --- a/src/core/org/luaj/vm2/lib/BaseLib.java +++ b/src/core/org/luaj/vm2/lib/BaseLib.java @@ -208,11 +208,13 @@ public class BaseLib extends OneArgFunction implements ResourceFinder { final class pcall extends VarArgFunction { public Varargs invoke(Varargs args) { LuaValue func = args.checkvalue(1); - globals.running_thread.callstack.onCall(this); + if (globals != null && globals.debuglib != null) + globals.debuglib.onCall(this); try { return pcall(func,args.subargs(2),null); } finally { - globals.running_thread.callstack.onReturn(); + if (globals != null && globals.debuglib != null) + globals.debuglib.onReturn(); } } } @@ -350,11 +352,13 @@ public class BaseLib extends OneArgFunction implements ResourceFinder { // "xpcall", // (f, err) -> result1, ... final class xpcall extends VarArgFunction { public Varargs invoke(Varargs args) { - globals.running_thread.callstack.onCall(this); + if (globals != null && globals.debuglib != null) + globals.debuglib.onCall(this); try { - return pcall(args.arg1(),NONE,args.checkvalue(2)); + return pcall(args.arg1(),args.subargs(3),args.checkvalue(2)); } finally { - globals.running_thread.callstack.onReturn(); + if (globals != null && globals.debuglib != null) + globals.debuglib.onReturn(); } } } diff --git a/src/core/org/luaj/vm2/lib/DebugLib.java b/src/core/org/luaj/vm2/lib/DebugLib.java index cad5074d..a0ebc7f5 100644 --- a/src/core/org/luaj/vm2/lib/DebugLib.java +++ b/src/core/org/luaj/vm2/lib/DebugLib.java @@ -26,21 +26,17 @@ import org.luaj.vm2.LoadState.LuaCompiler; import org.luaj.vm2.Lua; import org.luaj.vm2.LuaBoolean; import org.luaj.vm2.LuaClosure; -import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaFunction; import org.luaj.vm2.LuaNil; import org.luaj.vm2.LuaNumber; import org.luaj.vm2.LuaString; import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaThread; -import org.luaj.vm2.LuaThread.CallFrame; import org.luaj.vm2.LuaUserdata; import org.luaj.vm2.LuaValue; +import org.luaj.vm2.Print; import org.luaj.vm2.Prototype; import org.luaj.vm2.Varargs; -import org.luaj.vm2.lib.jme.JmePlatform; -import org.luaj.vm2.lib.jse.JsePlatform; -import org.luaj.vm2.luajc.LuaJC; /** * Subclass of {@link LibFunction} which implements the lua standard {@code debug} @@ -73,10 +69,6 @@ import org.luaj.vm2.luajc.LuaJC; public class DebugLib extends OneArgFunction { public static final boolean CALLS = (null != System.getProperty("CALLS")); public static final boolean TRACE = (null != System.getProperty("TRACE")); - - // leave this unset to allow obfuscators to - // remove it in production builds - public static boolean DEBUG_ENABLED; private static final LuaString LUA = valueOf("Lua"); private static final LuaString JAVA = valueOf("Java"); @@ -89,8 +81,7 @@ public class DebugLib extends OneArgFunction { private static final LuaString CALL = valueOf("call"); private static final LuaString LINE = valueOf("line"); private static final LuaString COUNT = valueOf("count"); - private static final LuaString RETURN = valueOf("return"); - private static final LuaString TAILRETURN = valueOf("tail return"); + private static final LuaString RETURN = valueOf("return"); private static final LuaString CONSTANT = valueOf("constant"); private static final LuaString FOR_ITERATOR = valueOf("for iterator"); private static final LuaString METAMETHOD = valueOf("metamethod"); @@ -112,10 +103,18 @@ public class DebugLib extends OneArgFunction { Globals globals; + LuaValue hookfunc; + boolean hookline; + boolean hookcall; + boolean hookrtrn; + int hookcount; + boolean inhook; + int lastline; + int bytecodes; + public LuaTable call(LuaValue env) { globals = env.checkglobals(); globals.debuglib = this; - DEBUG_ENABLED = true; LuaTable debug = new LuaTable(); debug.set("debug", new debug()); debug.set("gethook", new gethook()); @@ -148,11 +147,10 @@ public class DebugLib extends OneArgFunction { // debug.gethook ([thread]) final class gethook extends VarArgFunction { public Varargs invoke(Varargs args) { - LuaThread t = args.optthread(1, globals.running_thread); return varargsOf( - t.hookfunc, - valueOf((t.hookcall?"c":"")+(t.hookline?"l":"")+(t.hookrtrn?"r":"")), - valueOf(t.hookcount)); + hookfunc, + valueOf((hookcall?"c":"")+(hookline?"l":"")+(hookrtrn?"r":"")), + valueOf(hookcount)); } } @@ -163,10 +161,10 @@ 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++, "flnStu"); - LuaThread.CallStack callstack = thread.callstack; + DebugLib.CallStack callstack = callstack(thread); // find the stack info - LuaThread.CallFrame frame; + DebugLib.CallFrame frame; if ( func.isnumber() ) { frame = callstack.getCallFrame(func.toint()); if (frame == null) @@ -220,7 +218,7 @@ public class DebugLib extends OneArgFunction { if (what.indexOf('L') >= 0) { LuaTable lines = new LuaTable(); info.set(ACTIVELINES, lines); - CallFrame cf; + DebugLib.CallFrame cf; for (int l = 1; (cf=callstack.getCallFrame(l)) != null; ++l) if (cf.f == func) lines.insert(-1, valueOf(cf.currentline())); @@ -239,7 +237,7 @@ public class DebugLib extends OneArgFunction { LuaThread thread = args.isthread(a)? args.checkthread(a++): globals.running_thread; int level = args.checkint(a++); int local = args.checkint(a++); - return thread.callstack.getCallFrame(level).getLocal(local); + return callstack(thread).getCallFrame(level).getLocal(local); } } @@ -297,11 +295,11 @@ public class DebugLib extends OneArgFunction { case 'l': line=true; break; case 'r': rtrn=true; break; } - thread.hookfunc = func; - thread.hookcall = call; - thread.hookline = line; - thread.hookcount = count; - thread.hookrtrn = rtrn; + hookfunc = func; + hookcall = call; + hookline = line; + hookcount = count; + hookrtrn = rtrn; return NONE; } } @@ -314,7 +312,7 @@ public class DebugLib extends OneArgFunction { int level = args.checkint(a++); int local = args.checkint(a++); LuaValue value = args.arg(a++); - return thread.callstack.getCallFrame(level).setLocal(local, value); + return callstack(thread).getCallFrame(level).setLocal(local, value); } } @@ -372,7 +370,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 = thread.callstack.traceback(level); + String tb = callstack(thread).traceback(level); return valueOf(message!=null? message+"\n"+tb: tb); } } @@ -403,6 +401,223 @@ public class DebugLib extends OneArgFunction { } } + public void onCall(LuaFunction f) { + if (inhook) return; + callstack().onCall(f); + if (hookcall && hookfunc != null) + callHook(CALL, NIL); + } + + public void onCall(LuaClosure c, Varargs varargs, LuaValue[] stack) { + if (inhook) return; + callstack().onCall(c, varargs, stack); + if (hookcall && hookfunc != null) + callHook(CALL, NIL); + } + + public void onInstruction(int pc, Varargs v, int top) { + if (inhook) return; + callstack().onInstruction(pc, v, top); + if (hookfunc == null) return; + if (hookcount > 0) + if (++bytecodes % hookcount == 0) + callHook(COUNT, NIL); + if (hookline) { + int newline = callstack().currentline(); + if ( newline != lastline ) { + lastline = newline; + callHook(LINE, LuaValue.valueOf(newline)); + } + } + } + + public void onReturn() { + if (inhook) return; + callstack().onReturn(); + if (hookcall && hookfunc != null) + callHook(RETURN, NIL); + } + + public String traceback(int level) { + return callstack().traceback(level); + } + + void callHook(LuaValue type, LuaValue arg) { + inhook = true; + try { + hookfunc.call(type, arg); + } catch (Exception e) { + e.printStackTrace(); + } finally { + inhook = false; + } + } + + CallStack callstack() { + return callstack(globals.running_thread); + } + + CallStack callstack(LuaThread t) { + if (t.callstack == null) + t.callstack = new CallStack(); + return (CallStack) t.callstack; + } + + public static class CallStack { + final static CallFrame[] EMPTY = {}; + CallFrame[] frame = EMPTY; + int calls = 0; + + CallStack() {} + + int currentline() { + return calls > 0? frame[calls-1].currentline(): -1; + } + + private CallFrame pushcall() { + if (calls >= frame.length) { + int n = Math.max(4, frame.length * 3 / 2); + CallFrame[] f = new CallFrame[n]; + System.arraycopy(frame, 0, f, 0, frame.length); + for (int i = frame.length; i < n; ++i) + f[i] = new CallFrame(); + frame = f; + } + return frame[calls++]; + } + + final void onCall(LuaFunction function) { + pushcall().set(function); + } + + final void onCall(LuaClosure function, Varargs varargs, LuaValue[] stack) { + pushcall().set(function, varargs, stack); + } + + final void onReturn() { + if (calls > 0) + frame[--calls].reset(); + } + + final void onInstruction(int pc, Varargs v, int top) { + frame[calls-1].instr(pc, v, top); + } + + /** + * Get the traceback starting at a specific level. + * @param level + * @return String containing the traceback. + */ + String traceback(int level) { + StringBuffer sb = new StringBuffer(); + sb.append( "stack traceback:" ); + DebugLib.CallFrame c = getCallFrame(level); + if (c != null) { + sb.append("\n\t"); + sb.append( c.sourceline() ); + sb.append( " in " ); + while ( (c = getCallFrame(++level)) != null ) { + sb.append( c.tracename() ); + sb.append( "\n\t" ); + sb.append( c.sourceline() ); + sb.append( " in " ); + } + sb.append( "main chunk" ); + } + return sb.toString(); + } + + DebugLib.CallFrame getCallFrame(int level) { + if (level < 1 || level >= calls) + return null; + return frame[calls-level]; + } + + DebugLib.CallFrame findCallFrame(LuaValue func) { + for (int i = 1; i <= calls; ++i) + if (frame[calls-i].f == func) + return frame[i]; + return null; + } + + } + + static class CallFrame { + LuaFunction f; + int pc; + int top; + Varargs v; + LuaValue[] stack; + boolean tail; + void set(LuaClosure function, Varargs varargs, LuaValue[] stack) { + this.f = function; + this.v = varargs; + this.stack = stack; + this.tail = false; + } + void set(LuaFunction function) { + this.f = function; + } + void reset() { + this.f = null; + this.v = null; + this.stack = null; + } + void instr(int pc, Varargs v, int top) { + this.pc = pc; + this.v = v; + this.top = top; + if (f.checkclosure().p.code[pc] == Lua.OP_TAILCALL) + this.tail = true; + if (TRACE) + Print.printState(f.checkclosure(), pc, stack, top, v); + } + Varargs getLocal(int i) { + LuaString name = getlocalname(i); + if ( name != null ) + return varargsOf( name, stack[i-1] ); + else + return NIL; + } + Varargs setLocal(int i, LuaValue value) { + LuaString name = getlocalname(i); + if ( name != null ) { + stack[i-1] = value; + return name; + } else { + return NIL; + } + } + int currentline() { + if ( !f.isclosure() ) return -1; + int[] li = f.checkclosure().p.lineinfo; + return li==null || pc<0 || pc>=li.length? -1: li[pc]; + } + String sourceline() { + if ( !f.isclosure() ) return f.tojstring(); + String s = f.checkclosure().p.source.tojstring(); + int line = currentline(); + return (s.startsWith("@")||s.startsWith("=")? s.substring(1): s) + ":" + line; + } + String tracename() { + LuaString[] kind = getfuncname(this); + if ( kind == null ) + return "function ?"; + return "function "+kind[0].tojstring(); + } + LuaString getlocalname(int index) { + if ( !f.isclosure() ) return null; + return f.checkclosure().p.getlocalname(index, pc); + } + String tojstring() { + return tracename()+" "+sourceline(); + } + boolean istailcall() { + return tail; + } + + } + static LuaString findupvalue(LuaClosure c, int up) { if ( c.upValues != null && up > 0 && up <= c.upValues.length ) { if ( c.p.upvalues != null && up <= c.p.upvalues.length ) @@ -426,7 +641,7 @@ public class DebugLib extends OneArgFunction { if (!x) throw new RuntimeException("lua_assert failed"); } - public static LuaString[] getfuncname(CallFrame frame) { + public static LuaString[] getfuncname(DebugLib.CallFrame frame) { if (!frame.f.isclosure()) return new LuaString[] { frame.f.strvalue(), JAVA }; Prototype p = frame.f.checkclosure().p; @@ -572,6 +787,4 @@ public class DebugLib extends OneArgFunction { } return setreg; } - - } diff --git a/test/junit/org/luaj/vm2/OrphanedThreadTest.java b/test/junit/org/luaj/vm2/OrphanedThreadTest.java index a1dbb812..81c96a1b 100644 --- a/test/junit/org/luaj/vm2/OrphanedThreadTest.java +++ b/test/junit/org/luaj/vm2/OrphanedThreadTest.java @@ -41,11 +41,10 @@ public class OrphanedThreadTest extends TestCase { WeakReference luathr_ref; LuaValue function; WeakReference func_ref; - LuaValue env; protected void setUp() throws Exception { LuaThread.thread_orphan_check_interval = 5; - env = JsePlatform.standardGlobals(); + globals = JsePlatform.standardGlobals(); } protected void tearDown() { @@ -53,17 +52,17 @@ public class OrphanedThreadTest extends TestCase { } public void testCollectOrphanedNormalThread() throws Exception { - function = new NormalFunction(); + function = new NormalFunction(globals); doTest(LuaValue.TRUE, LuaValue.ZERO); } public void testCollectOrphanedEarlyCompletionThread() throws Exception { - function = new EarlyCompletionFunction(); + function = new EarlyCompletionFunction(globals); doTest(LuaValue.TRUE, LuaValue.ZERO); } public void testCollectOrphanedAbnormalThread() throws Exception { - function = new AbnormalFunction(); + function = new AbnormalFunction(globals); doTest(LuaValue.FALSE, LuaValue.valueOf("abnormal condition")); } @@ -76,7 +75,7 @@ public class OrphanedThreadTest extends TestCase { "print('leakage in closure.3, arg is '..arg)\n" + "return 'done'\n"; LuaC.install(); - function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", "bt", env); + function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", "bt", globals); doTest(LuaValue.TRUE, LuaValue.ZERO); } @@ -92,7 +91,7 @@ public class OrphanedThreadTest extends TestCase { "end\n" + "print( 'pcall-closre.result:', pcall( f, ... ) )\n"; LuaC.install(); - function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", "bt", env); + function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", "bt", globals); doTest(LuaValue.TRUE, LuaValue.ZERO); } @@ -109,12 +108,11 @@ public class OrphanedThreadTest extends TestCase { "end\n" + "load(f)()\n"; LuaC.install(); - function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", "bt", env); + function = LoadState.load(new ByteArrayInputStream(script.getBytes()), "script", "bt", globals); doTest(LuaValue.TRUE, LuaValue.ONE); } private void doTest(LuaValue status2, LuaValue value2) throws Exception { - globals = JsePlatform.standardGlobals(); luathread = new LuaThread(globals, function); luathr_ref = new WeakReference(luathread); func_ref = new WeakReference(function); @@ -144,7 +142,11 @@ public class OrphanedThreadTest extends TestCase { } - class NormalFunction extends OneArgFunction { + static class NormalFunction extends OneArgFunction { + final Globals globals; + public NormalFunction(Globals globals) { + this.globals = globals; + } public LuaValue call(LuaValue arg) { System.out.println("in normal.1, arg is "+arg); arg = globals.yield(ONE).arg1(); @@ -155,7 +157,11 @@ public class OrphanedThreadTest extends TestCase { } } - class EarlyCompletionFunction extends OneArgFunction { + static class EarlyCompletionFunction extends OneArgFunction { + final Globals globals; + public EarlyCompletionFunction(Globals globals) { + this.globals = globals; + } public LuaValue call(LuaValue arg) { System.out.println("in early.1, arg is "+arg); arg = globals.yield(ONE).arg1(); @@ -164,17 +170,11 @@ public class OrphanedThreadTest extends TestCase { } } - class AbnormalFunction extends OneArgFunction { - public LuaValue call(LuaValue arg) { - System.out.println("in abnormal.1, arg is "+arg); - arg = globals.yield(ONE).arg1(); - System.out.println("in abnormal.2, arg is "+arg); - error("abnormal condition"); - return ZERO; - } - } - - class ClosureFunction extends OneArgFunction { + static class AbnormalFunction extends OneArgFunction { + final Globals globals; + public AbnormalFunction(Globals globals) { + this.globals = globals; + } public LuaValue call(LuaValue arg) { System.out.println("in abnormal.1, arg is "+arg); arg = globals.yield(ONE).arg1();