diff --git a/core/src/main/java/org/luaj/vm2/LuaClosure.java b/core/src/main/java/org/luaj/vm2/LuaClosure.java
index 47e7d9e8..b9bb652e 100644
--- a/core/src/main/java/org/luaj/vm2/LuaClosure.java
+++ b/core/src/main/java/org/luaj/vm2/LuaClosure.java
@@ -1,28 +1,31 @@
/*******************************************************************************
-* Copyright (c) 2009 Luaj.org. All rights reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy
-* of this software and associated documentation files (the "Software"), to deal
-* in the Software without restriction, including without limitation the rights
-* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-* copies of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included in
-* all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-* THE SOFTWARE.
-******************************************************************************/
+ * Copyright (c) 2009 Luaj.org. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
package org.luaj.vm2;
import org.luaj.vm2.libs.DebugLib.CallFrame;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Extension of {@link LuaFunction} which executes lua bytecode.
*
@@ -30,7 +33,7 @@ import org.luaj.vm2.libs.DebugLib.CallFrame;
* and a {@link LuaValue} to use as an environment for execution.
* Normally the {@link LuaValue} is a {@link Globals} in which case the environment
* will contain standard lua libraries.
- *
+ *
*
* There are three main ways {@link LuaClosure} instances are created:
*
@@ -85,13 +88,13 @@ import org.luaj.vm2.libs.DebugLib.CallFrame;
*/
public class LuaClosure extends LuaFunction {
private static final UpValue[] NOUPVALUES = new UpValue[0];
-
+
public final Prototype p;
public UpValue[] upValues;
-
+
final Globals globals;
-
+
/** Create a closure around a Prototype with a specific environment.
* If the prototype has upvalues, the environment will be written into the first upvalue.
* @param p the Prototype to construct this Closure for.
@@ -102,7 +105,7 @@ public class LuaClosure extends LuaFunction {
this.initupvalue1(env);
globals = env instanceof Globals? (Globals) env: null;
}
-
+
public void initupvalue1(LuaValue env) {
if (p.upvalues == null || p.upvalues.length == 0)
this.upValues = NOUPVALUES;
@@ -112,11 +115,11 @@ public class LuaClosure extends LuaFunction {
}
}
-
+
public boolean isclosure() {
return true;
}
-
+
public LuaClosure optclosure(LuaClosure defval) {
return this;
}
@@ -124,61 +127,119 @@ public class LuaClosure extends LuaFunction {
public LuaClosure checkclosure() {
return this;
}
-
+
public String tojstring() {
return "function: " + p.toString();
}
-
+
+
+ private List stackPool = new ArrayList<>();
private LuaValue[] getNewStack() {
+ if (stackPool.isEmpty()) {
+ return getNewStackRaw();
+ } else {
+ return stackPool.remove(stackPool.size() - 1);
+ }
+ }
+
+ private LuaValue[] getNewStackRaw() {
int max = p.maxstacksize;
LuaValue[] stack = new LuaValue[max];
System.arraycopy(NILS, 0, stack, 0, max);
return stack;
}
-
+
+ private void releaseStack(LuaValue[] stack) {
+ System.arraycopy(NILS, 0, stack, 0, stack.length);
+ stackPool.add(stack);
+ }
+
public final LuaValue call() {
LuaValue[] stack = getNewStack();
- return execute(stack,NONE).arg1();
+ LuaValue result = execute(stack,NONE).arg1();
+ releaseStack(stack);
+ return result;
}
public final LuaValue call(LuaValue arg) {
LuaValue[] stack = getNewStack();
+ LuaValue result;
switch ( p.numparams ) {
- default: stack[0]=arg; return execute(stack,NONE).arg1();
- case 0: return execute(stack,arg).arg1();
+ default:
+ stack[0]=arg;
+ result = execute(stack,NONE).arg1();
+ break;
+ case 0:
+ result = execute(stack,arg).arg1();
+ break;
}
+ releaseStack(stack);
+ return result;
}
-
+
public final LuaValue call(LuaValue arg1, LuaValue arg2) {
LuaValue[] stack = getNewStack();
+ LuaValue result;
switch ( p.numparams ) {
- default: stack[0]=arg1; stack[1]=arg2; return execute(stack,NONE).arg1();
- case 1: stack[0]=arg1; return execute(stack,arg2).arg1();
- case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2): NONE).arg1();
+ default:
+ stack[0]=arg1;
+ stack[1]=arg2;
+ result = execute(stack,NONE).arg1();
+ break;
+ case 1:
+ stack[0]=arg1;
+ result = execute(stack,arg2).arg1();
+ break;
+ case 0:
+ result = execute(stack,p.is_vararg!=0 ? varargsOf(arg1,arg2) : NONE).arg1();
+ break;
}
+ releaseStack(stack);
+ return result;
}
public final LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
LuaValue[] stack = getNewStack();
+ LuaValue result;
switch ( p.numparams ) {
- default: stack[0]=arg1; stack[1]=arg2; stack[2]=arg3; return execute(stack,NONE).arg1();
- case 2: stack[0]=arg1; stack[1]=arg2; return execute(stack,arg3).arg1();
- case 1: stack[0]=arg1; return execute(stack,p.is_vararg!=0? varargsOf(arg2,arg3): NONE).arg1();
- case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2,arg3): NONE).arg1();
+ default:
+ stack[0]=arg1;
+ stack[1]=arg2;
+ stack[2]=arg3;
+ result = execute(stack,NONE).arg1();
+ break;
+ case 2:
+ stack[0]=arg1;
+ stack[1]=arg2;
+ result = execute(stack,arg3).arg1();
+ break;
+ case 1:
+ stack[0]=arg1;
+ result = execute(stack,p.is_vararg!=0 ? varargsOf(arg2,arg3) : NONE).arg1();
+ break;
+ case 0:
+ result = execute(stack,p.is_vararg!=0 ? varargsOf(arg1,arg2,arg3) : NONE).arg1();
+ break;
}
+ releaseStack(stack);
+ return result;
}
public final Varargs invoke(Varargs varargs) {
return onInvoke(varargs).eval();
}
-
+
public final Varargs onInvoke(Varargs varargs) {
LuaValue[] stack = getNewStack();
for ( int i=0; i0? new UpValue[stack.length]: null;
-
+
// allow for debug hooks
if (globals != null && globals.debuglib != null)
globals.debuglib.onCall( this, varargs, stack );
@@ -200,116 +261,116 @@ public class LuaClosure extends LuaFunction {
for (; true; ++pc) {
if (globals != null && globals.debuglib != null)
globals.debuglib.onInstruction( pc, v, top );
-
+
// pull out instruction
i = code[pc];
a = ((i>>6) & 0xff);
-
+
// process the op code
switch ( i & 0x3f ) {
-
- case Lua.OP_MOVE:/* A B R(A):= R(B) */
- stack[a] = stack[i>>>23];
- continue;
-
- case Lua.OP_LOADK:/* A Bx R(A):= Kst(Bx) */
- stack[a] = k[i>>>14];
- continue;
-
- case Lua.OP_LOADKX:/* A R(A) := Kst(extra arg) */
- ++pc;
- i = code[pc];
- if ((i & 0x3f) != Lua.OP_EXTRAARG) {
- int op = i & 0x3f;
- throw new LuaError("OP_EXTRAARG expected after OP_LOADKX, got " +
- (op < Print.OPNAMES.length - 1 ? Print.OPNAMES[op] : "UNKNOWN_OP_" + op));
- }
- stack[a] = k[i>>>6];
- continue;
-
- case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */
- stack[a] = (i>>>23!=0)? LuaValue.TRUE: LuaValue.FALSE;
- if ((i&(0x1ff<<14)) != 0)
- ++pc; /* skip next instruction (if C) */
- continue;
-
- case Lua.OP_LOADNIL: /* A B R(A):= ...:= R(A+B):= nil */
- for ( b=i>>>23; b-->=0; )
- stack[a++] = LuaValue.NIL;
- continue;
-
- case Lua.OP_GETUPVAL: /* A B R(A):= UpValue[B] */
- stack[a] = upValues[i>>>23].getValue();
- continue;
-
- case Lua.OP_GETTABUP: /* A B C R(A) := UpValue[B][RK(C)] */
- stack[a] = upValues[i>>>23].getValue().get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
- continue;
-
- case Lua.OP_GETTABLE: /* A B C R(A):= R(B)[RK(C)] */
- stack[a] = stack[i>>>23].get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
- continue;
-
- case Lua.OP_SETTABUP: /* A B C UpValue[A][RK(B)] := RK(C) */
- upValues[a].getValue().set(((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]), (c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
- continue;
-
- case Lua.OP_SETUPVAL: /* A B UpValue[B]:= R(A) */
- upValues[i>>>23].setValue(stack[a]);
- continue;
-
- case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */
- stack[a].set(((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]), (c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
- continue;
-
- case Lua.OP_NEWTABLE: /* A B C R(A):= {} (size = B,C) */
- stack[a] = new LuaTable(i>>>23,(i>>14)&0x1ff);
- continue;
-
- case Lua.OP_SELF: /* A B C R(A+1):= R(B): R(A):= R(B)[RK(C)] */
- stack[a+1] = (o = stack[i>>>23]);
- stack[a] = o.get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
- continue;
-
- case Lua.OP_ADD: /* A B C R(A):= RK(B) + RK(C) */
- stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).add((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
- continue;
-
- case Lua.OP_SUB: /* A B C R(A):= RK(B) - RK(C) */
- stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).sub((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
- continue;
-
- case Lua.OP_MUL: /* A B C R(A):= RK(B) * RK(C) */
- stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mul((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
- continue;
-
- case Lua.OP_DIV: /* A B C R(A):= RK(B) / RK(C) */
- stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).div((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
- continue;
-
- case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */
- stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mod((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
- continue;
-
- case Lua.OP_POW: /* A B C R(A):= RK(B) ^ RK(C) */
- stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).pow((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
- continue;
-
- case Lua.OP_UNM: /* A B R(A):= -R(B) */
- stack[a] = stack[i>>>23].neg();
- continue;
-
- case Lua.OP_NOT: /* A B R(A):= not R(B) */
- stack[a] = stack[i>>>23].not();
- continue;
-
- case Lua.OP_LEN: /* A B R(A):= length of R(B) */
- stack[a] = stack[i>>>23].len();
- continue;
-
- case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */
- b = i>>>23;
- c = (i>>14)&0x1ff;
+
+ case Lua.OP_MOVE:/* A B R(A):= R(B) */
+ stack[a] = stack[i>>>23];
+ continue;
+
+ case Lua.OP_LOADK:/* A Bx R(A):= Kst(Bx) */
+ stack[a] = k[i>>>14];
+ continue;
+
+ case Lua.OP_LOADKX:/* A R(A) := Kst(extra arg) */
+ ++pc;
+ i = code[pc];
+ if ((i & 0x3f) != Lua.OP_EXTRAARG) {
+ int op = i & 0x3f;
+ throw new LuaError("OP_EXTRAARG expected after OP_LOADKX, got " +
+ (op < Print.OPNAMES.length - 1 ? Print.OPNAMES[op] : "UNKNOWN_OP_" + op));
+ }
+ stack[a] = k[i>>>6];
+ continue;
+
+ case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */
+ stack[a] = (i>>>23!=0)? LuaValue.TRUE: LuaValue.FALSE;
+ if ((i&(0x1ff<<14)) != 0)
+ ++pc; /* skip next instruction (if C) */
+ continue;
+
+ case Lua.OP_LOADNIL: /* A B R(A):= ...:= R(A+B):= nil */
+ for ( b=i>>>23; b-->=0; )
+ stack[a++] = LuaValue.NIL;
+ continue;
+
+ case Lua.OP_GETUPVAL: /* A B R(A):= UpValue[B] */
+ stack[a] = upValues[i>>>23].getValue();
+ continue;
+
+ case Lua.OP_GETTABUP: /* A B C R(A) := UpValue[B][RK(C)] */
+ stack[a] = upValues[i>>>23].getValue().get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ continue;
+
+ case Lua.OP_GETTABLE: /* A B C R(A):= R(B)[RK(C)] */
+ stack[a] = stack[i>>>23].get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ continue;
+
+ case Lua.OP_SETTABUP: /* A B C UpValue[A][RK(B)] := RK(C) */
+ upValues[a].getValue().set(((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]), (c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ continue;
+
+ case Lua.OP_SETUPVAL: /* A B UpValue[B]:= R(A) */
+ upValues[i>>>23].setValue(stack[a]);
+ continue;
+
+ case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */
+ stack[a].set(((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]), (c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ continue;
+
+ case Lua.OP_NEWTABLE: /* A B C R(A):= {} (size = B,C) */
+ stack[a] = new LuaTable(i>>>23,(i>>14)&0x1ff);
+ continue;
+
+ case Lua.OP_SELF: /* A B C R(A+1):= R(B): R(A):= R(B)[RK(C)] */
+ stack[a+1] = (o = stack[i>>>23]);
+ stack[a] = o.get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ continue;
+
+ case Lua.OP_ADD: /* A B C R(A):= RK(B) + RK(C) */
+ stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).add((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ continue;
+
+ case Lua.OP_SUB: /* A B C R(A):= RK(B) - RK(C) */
+ stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).sub((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ continue;
+
+ case Lua.OP_MUL: /* A B C R(A):= RK(B) * RK(C) */
+ stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mul((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ continue;
+
+ case Lua.OP_DIV: /* A B C R(A):= RK(B) / RK(C) */
+ stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).div((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ continue;
+
+ case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */
+ stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mod((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ continue;
+
+ case Lua.OP_POW: /* A B C R(A):= RK(B) ^ RK(C) */
+ stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).pow((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
+ continue;
+
+ case Lua.OP_UNM: /* A B R(A):= -R(B) */
+ stack[a] = stack[i>>>23].neg();
+ continue;
+
+ case Lua.OP_NOT: /* A B R(A):= not R(B) */
+ stack[a] = stack[i>>>23].not();
+ continue;
+
+ case Lua.OP_LEN: /* A B R(A):= length of R(B) */
+ stack[a] = stack[i>>>23].len();
+ continue;
+
+ case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */
+ b = i>>>23;
+ c = (i>>14)&0x1ff;
{
if ( c > b+1 ) {
Buffer sb = stack[c].buffer();
@@ -321,112 +382,112 @@ public class LuaClosure extends LuaFunction {
}
}
continue;
-
- case Lua.OP_JMP: /* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
- pc += (i>>>14)-0x1ffff;
- if (a > 0) {
- for (--a, b = openups.length; --b>=0; )
- if (openups[b] != null && openups[b].index >= a) {
- openups[b].close();
- openups[b] = null;
- }
- }
- continue;
-
- case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
- if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).eq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
- ++pc;
- continue;
-
- case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
- if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lt_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
- ++pc;
- continue;
-
- case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
- if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lteq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
- ++pc;
- continue;
-
- case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */
- if ( stack[a].toboolean() != ((i&(0x1ff<<14))!=0) )
- ++pc;
- continue;
-
- case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A):= R(B) else pc++ */
- /* note: doc appears to be reversed */
- if ( (o=stack[i>>>23]).toboolean() != ((i&(0x1ff<<14))!=0) )
- ++pc;
- else
- stack[a] = o; // TODO: should be sBx?
- continue;
-
- case Lua.OP_CALL: /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */
- switch ( i & (Lua.MASK_B | Lua.MASK_C) ) {
- case (1<>>23;
- c = (i>>14)&0x1ff;
- v = stack[a].invoke(b>0?
- varargsOf(stack, a+1, b-1): // exact arg count
- varargsOf(stack, a+1, top-v.narg()-(a+1), v)); // from prev top
- if ( c > 0 ) {
- v.copyto(stack, a, c-1);
- v = NONE;
- } else {
- top = a + v.narg();
- v = v.dealias();
+
+ case Lua.OP_JMP: /* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
+ pc += (i>>>14)-0x1ffff;
+ if (a > 0) {
+ for (--a, b = openups.length; --b>=0; )
+ if (openups[b] != null && openups[b].index >= a) {
+ openups[b].close();
+ openups[b] = null;
+ }
}
continue;
- }
-
- case Lua.OP_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
- switch ( i & Lua.MASK_B ) {
- case (1<>>23)>0xff? k[b&0x0ff]: stack[b]).eq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
+ ++pc;
+ continue;
+
+ case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
+ if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lt_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
+ ++pc;
+ continue;
+
+ case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
+ if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lteq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
+ ++pc;
+ continue;
+
+ case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */
+ if ( stack[a].toboolean() != ((i&(0x1ff<<14))!=0) )
+ ++pc;
+ continue;
+
+ case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A):= R(B) else pc++ */
+ /* note: doc appears to be reversed */
+ if ( (o=stack[i>>>23]).toboolean() != ((i&(0x1ff<<14))!=0) )
+ ++pc;
+ else
+ stack[a] = o; // TODO: should be sBx?
+ continue;
+
+ case Lua.OP_CALL: /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */
+ switch ( i & (Lua.MASK_B | Lua.MASK_C) ) {
+ case (1<>>23;
+ c = (i>>14)&0x1ff;
+ v = stack[a].invoke(b>0?
+ varargsOf(stack, a+1, b-1): // exact arg count
+ varargsOf(stack, a+1, top-v.narg()-(a+1), v)); // from prev top
+ if ( c > 0 ) {
+ v.copyto(stack, a, c-1);
+ v = NONE;
+ } else {
+ top = a + v.narg();
+ v = v.dealias();
+ }
+ continue;
+ }
+
+ case Lua.OP_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
+ switch ( i & Lua.MASK_B ) {
+ case (1<>>23;
+ v = b>0?
+ varargsOf(stack,a+1,b-1): // exact arg count
+ varargsOf(stack, a+1, top-v.narg()-(a+1), v); // from prev top
+ return new TailcallVarargs( stack[a], v );
+ }
+
+ case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */
b = i>>>23;
- v = b>0?
- varargsOf(stack,a+1,b-1): // exact arg count
- varargsOf(stack, a+1, top-v.narg()-(a+1), v); // from prev top
- return new TailcallVarargs( stack[a], v );
- }
-
- case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */
- b = i>>>23;
- switch ( b ) {
- case 0: return varargsOf(stack, a, top-v.narg()-a, v);
- case 1: return NONE;
- case 2: return stack[a];
- default:
- return varargsOf(stack, a, b-1);
- }
-
- case Lua.OP_FORLOOP: /* A sBx R(A)+=R(A+2): if R(A) = R(A+1) then { pc+=sBx: R(A+3)=R(A) }*/
+ switch ( b ) {
+ case 0: return varargsOf(stack, a, top-v.narg()-a, v);
+ case 1: return NONE;
+ case 2: return stack[a];
+ default:
+ return varargsOf(stack, a, b-1);
+ }
+
+ case Lua.OP_FORLOOP: /* A sBx R(A)+=R(A+2): if R(A) = R(A+1) then { pc+=sBx: R(A+3)=R(A) }*/
{
- LuaValue limit = stack[a + 1];
+ LuaValue limit = stack[a + 1];
LuaValue step = stack[a + 2];
LuaValue idx = stack[a].add(step);
- if (step.gt_b(0)? idx.lteq_b(limit): idx.gteq_b(limit)) {
- stack[a] = idx;
- stack[a + 3] = idx;
- pc += (i>>>14)-0x1ffff;
- }
+ if (step.gt_b(0)? idx.lteq_b(limit): idx.gteq_b(limit)) {
+ stack[a] = idx;
+ stack[a + 3] = idx;
+ pc += (i>>>14)-0x1ffff;
+ }
}
continue;
-
- case Lua.OP_FORPREP: /* A sBx R(A)-=R(A+2): pc+=sBx */
+
+ case Lua.OP_FORPREP: /* A sBx R(A)-=R(A+2): pc+=sBx */
{
LuaValue init = stack[a].checknumber("'for' initial value must be a number");
LuaValue limit = stack[a + 1].checknumber("'for' limit must be a number");
@@ -438,44 +499,44 @@ public class LuaClosure extends LuaFunction {
}
continue;
- case Lua.OP_TFORCALL: /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
- v = stack[a].invoke(varargsOf(stack[a+1],stack[a+2]));
- c = (i>>14) & 0x1ff;
- while (--c >= 0)
- stack[a+3+c] = v.arg(c+1);
- v = NONE;
+ case Lua.OP_TFORCALL: /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
+ v = stack[a].invoke(varargsOf(stack[a+1],stack[a+2]));
+ c = (i>>14) & 0x1ff;
+ while (--c >= 0)
+ stack[a+3+c] = v.arg(c+1);
+ v = NONE;
+ continue;
+
+ case Lua.OP_TFORLOOP: /* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx */
+ if (!stack[a+1].isnil()) { /* continue loop? */
+ stack[a] = stack[a+1]; /* save control varible. */
+ pc += (i>>>14)-0x1ffff;
+ }
+ continue;
+
+ case Lua.OP_SETLIST: /* A B C R(A)[(C-1)*FPF+i]:= R(A+i), 1 <= i <= B */
+ {
+ if ( (c=(i>>14)&0x1ff) == 0 )
+ c = code[++pc];
+ int offset = (c-1) * Lua.LFIELDS_PER_FLUSH;
+ o = stack[a];
+ if ( (b=i>>>23) == 0 ) {
+ b = top - a - 1;
+ int m = b - v.narg();
+ int j=1;
+ for ( ;j<=m; j++ )
+ o.set(offset+j, stack[a + j]);
+ for ( ;j<=b; j++ )
+ o.set(offset+j, v.arg(j-m));
+ } else {
+ o.presize( offset + b );
+ for (int j=1; j<=b; j++)
+ o.set(offset+j, stack[a + j]);
+ }
+ }
continue;
- case Lua.OP_TFORLOOP: /* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx */
- if (!stack[a+1].isnil()) { /* continue loop? */
- stack[a] = stack[a+1]; /* save control varible. */
- pc += (i>>>14)-0x1ffff;
- }
- continue;
-
- case Lua.OP_SETLIST: /* A B C R(A)[(C-1)*FPF+i]:= R(A+i), 1 <= i <= B */
- {
- if ( (c=(i>>14)&0x1ff) == 0 )
- c = code[++pc];
- int offset = (c-1) * Lua.LFIELDS_PER_FLUSH;
- o = stack[a];
- if ( (b=i>>>23) == 0 ) {
- b = top - a - 1;
- int m = b - v.narg();
- int j=1;
- for ( ;j<=m; j++ )
- o.set(offset+j, stack[a + j]);
- for ( ;j<=b; j++ )
- o.set(offset+j, v.arg(j-m));
- } else {
- o.presize( offset + b );
- for (int j=1; j<=b; j++)
- o.set(offset+j, stack[a + j]);
- }
- }
- continue;
-
- case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx]) */
+ case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx]) */
{
Prototype newp = p.p[i>>>14];
LuaClosure ncl = new LuaClosure(newp, globals);
@@ -489,23 +550,23 @@ public class LuaClosure extends LuaFunction {
stack[a] = ncl;
}
continue;
-
- case Lua.OP_VARARG: /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
- b = i>>>23;
- if ( b == 0 ) {
- top = a + (b = varargs.narg());
- v = varargs;
- } else {
- for ( int j=1; j>>23;
+ if ( b == 0 ) {
+ top = a + (b = varargs.narg());
+ v = varargs;
+ } else {
+ for ( int j=1; j";
}
-
-
-}
+
+
+}
\ No newline at end of file