diff --git a/src/core/org/luaj/vm2/LuaClosure.java b/src/core/org/luaj/vm2/LuaClosure.java
index 365ca255..d11a0556 100644
--- a/src/core/org/luaj/vm2/LuaClosure.java
+++ b/src/core/org/luaj/vm2/LuaClosure.java
@@ -89,6 +89,8 @@ public class LuaClosure extends LuaFunction {
private static final UpValue[] NOUPVALUES = new UpValue[0];
public final Prototype p;
+
+ public UpValue[] upValues;
/** Create a closure around a Prototype with the default global environment.
* If the prototype has upvalues, the environment will be written into the first upvalue.
diff --git a/src/core/org/luaj/vm2/LuaFunction.java b/src/core/org/luaj/vm2/LuaFunction.java
index 541c63fc..7138d52f 100644
--- a/src/core/org/luaj/vm2/LuaFunction.java
+++ b/src/core/org/luaj/vm2/LuaFunction.java
@@ -38,8 +38,6 @@ public class LuaFunction extends LuaValue {
/** Shared static metatable for all functions and closures. */
public static LuaValue s_metatable;
- public UpValue[] upValues;
-
public int type() {
return TFUNCTION;
}
@@ -64,8 +62,11 @@ public class LuaFunction extends LuaValue {
return s_metatable;
}
+ /** Hook for implementations such as LuaJC to load the environment of the main chunk
+ * into the first upvalue location. If the function has no upvalues or is not a main chunk,
+ * calling this will be no effect.
+ * @param env The environment to load into the first upvalue, if there is one.
+ */
public void initupvalue1(LuaValue env) {
- if (upValues != null && upValues.length > 0)
- upValues[0] = new UpValue(new LuaValue[] {env}, 0);
}
}
diff --git a/src/core/org/luaj/vm2/compiler/FuncState.java b/src/core/org/luaj/vm2/compiler/FuncState.java
index 89bdb13b..0e9188d7 100644
--- a/src/core/org/luaj/vm2/compiler/FuncState.java
+++ b/src/core/org/luaj/vm2/compiler/FuncState.java
@@ -474,20 +474,23 @@ public class FuncState extends LuaC {
this.freereg(e.u.info);
}
+ static final LuaUserdata NIL_PROXY = new LuaUserdata(LuaValue.NIL);
+
int addk(LuaValue v) {
+ LuaValue key = v.isnil()? NIL_PROXY: v;
if (this.h == null) {
this.h = new LuaTable();
} else {
- LuaValue idx = this.h.get(v);
+ LuaValue idx = this.h.get(key);
if (idx.isnumber())
return idx.toint();
}
int idx = this.nk;
- this.h.set(v, LuaValue.valueOf(idx));
+ this.h.set(key, LuaValue.valueOf(idx));
final Prototype f = this.f;
if (f.k == null || nk + 1 >= f.k.length)
f.k = realloc( f.k, nk*2 + 1 );
- f.k[this.nk++] = v.isuserdata()? LuaValue.NIL: v;
+ f.k[this.nk++] = v;
return idx;
}
@@ -509,11 +512,8 @@ public class FuncState extends LuaC {
return this.addk((b ? LuaValue.TRUE : LuaValue.FALSE));
}
- static final LuaUserdata NIL_PROXY = new LuaUserdata(LuaValue.NIL);
-
int nilK() {
- /* cannot use nil as key; instead use table itself to represent nil */
- return this.addk(NIL_PROXY);
+ return this.addk(LuaValue.NIL);
}
void setreturns(expdesc e, int nresults) {
diff --git a/src/core/org/luaj/vm2/lib/VarArgFunction.java b/src/core/org/luaj/vm2/lib/VarArgFunction.java
index 42c78f80..1ceb5389 100644
--- a/src/core/org/luaj/vm2/lib/VarArgFunction.java
+++ b/src/core/org/luaj/vm2/lib/VarArgFunction.java
@@ -21,7 +21,6 @@
******************************************************************************/
package org.luaj.vm2.lib;
-import org.luaj.vm2.LuaThread;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
@@ -77,6 +76,11 @@ abstract public class VarArgFunction extends LibFunction {
* - function has a possibility of returning a TailcallVarargs
* @param args the arguments to the function call.
*/
- abstract public Varargs invoke(Varargs args);
+ public Varargs invoke(Varargs args) {
+ return onInvoke(args).eval();
+ }
+ public Varargs onInvoke(Varargs args) {
+ return invoke(args);
+ }
}
diff --git a/src/jse/org/luaj/vm2/luajc/JavaBuilder.java b/src/jse/org/luaj/vm2/luajc/JavaBuilder.java
index b533de97..18c9c4ee 100644
--- a/src/jse/org/luaj/vm2/luajc/JavaBuilder.java
+++ b/src/jse/org/luaj/vm2/luajc/JavaBuilder.java
@@ -250,6 +250,7 @@ public class JavaBuilder {
}
// nil parameters
+ // TODO: remove this for lua 5.2, not needed
for ( ; slot
", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
- append(InstructionConstants.DUP);
- loadEnv();
- append(factory.createInvoke(STR_LUAVALUE, "setfenv", Type.VOID, ARG_TYPES_LUAVALUE, Constants.INVOKEVIRTUAL));
}
public void closureInitUpvalueFromUpvalue(String protoname, int newup, int upindex) {
@@ -779,4 +797,8 @@ public class JavaBuilder {
public void tovalue() {
append(factory.createInvoke(STR_BUFFER, "value", TYPE_LUAVALUE, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
}
+
+ public void closeUpvalue(int pc, int i) {
+ // TODO: assign the upvalue location the value null;
+ }
}
diff --git a/src/jse/org/luaj/vm2/luajc/JavaGen.java b/src/jse/org/luaj/vm2/luajc/JavaGen.java
index 398dfa78..f9c6ff8e 100644
--- a/src/jse/org/luaj/vm2/luajc/JavaGen.java
+++ b/src/jse/org/luaj/vm2/luajc/JavaGen.java
@@ -21,9 +21,9 @@
******************************************************************************/
package org.luaj.vm2.luajc;
-import org.luaj.vm2.Buffer;
import org.luaj.vm2.Lua;
import org.luaj.vm2.Prototype;
+import org.luaj.vm2.Upvaldesc;
/**
* TODO:
@@ -202,6 +202,11 @@ public class JavaGen {
break;
case Lua.OP_JMP: /* sBx pc+=sBx */
+ if (a > 0) {
+ for (int i = a-1; i < pi.openups.length; ++i) {
+ builder.closeUpvalue(pc, i);
+ }
+ }
builder.addBranch(pc, JavaBuilder.BRANCH_GOTO, pc+1+sbx);
break;
@@ -228,7 +233,7 @@ public class JavaGen {
builder.storeLocal( pc, a );
break;
- case Lua.OP_CALL: /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */
+ case Lua.OP_CALL: { /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */
// load function
builder.loadLocal(pc, a);
@@ -280,6 +285,7 @@ public class JavaGen {
builder.storeVarresult();
break;
}
+ }
break;
case Lua.OP_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
@@ -343,45 +349,24 @@ public class JavaGen {
break;
case Lua.OP_TFORCALL: /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
- throw new RuntimeException("Unimplemented OP_TFORCALL");
-
- case Lua.OP_TFORLOOP: /*
- * A C R(A+3), ... ,R(A+2+C):= R(A)(R(A+1),
- * R(A+2)): if R(A+3) ~= nil then R(A+2)=R(A+3)
- * else pc++
- */
- // v = stack[a].invoke(varargsOf(stack[a+1],stack[a+2]));
- // if ( (o=v.arg1()).isnil() )
- // ++pc;
builder.loadLocal(pc, a);
builder.loadLocal(pc, a+1);
builder.loadLocal(pc, a+2);
- builder.invoke(2); // varresult on stack
- builder.dup();
- builder.storeVarresult();
- builder.arg( 1 );
- builder.isNil();
- builder.addBranch(pc, JavaBuilder.BRANCH_IFNE, pc+2);
-
- // a[2] = a[3] = v[1], leave varargs on stack
- builder.createUpvalues(pc, a+3, c);
- builder.loadVarresult();
- if (c>=2)
- builder.dup();
- builder.arg( 1 );
- builder.dup();
- builder.storeLocal(pc, a+2);
- builder.storeLocal(pc, a+3);
-
- // v[2]..v[c], use varargs from stack
- for ( int j=2; j<=c; j++ ) {
- if ( j 0 )
builder.dup();
builder.storeLocal( pc, a );
- if ( nup > 0 ) {
- for ( int up=0; up b0.pc0 )
propogateVars( v, pc-1, pc );
- int a,b,c,nups;
+ int a,b,c;
int ins = prototype.code[pc];
int op = Lua.GET_OPCODE(ins);
@@ -164,7 +167,6 @@ public class ProtoInfo {
case Lua.OP_LOADK:/* A Bx R(A) := Kst(Bx) */
case Lua.OP_LOADBOOL:/* A B C R(A) := (Bool)B; if (C) pc++ */
case Lua.OP_GETUPVAL: /* A B R(A) := UpValue[B] */
- case Lua.OP_GETTABUP: /* A B C R(A) := UpValue[B][RK(C)] */
case Lua.OP_NEWTABLE: /* A B C R(A) := {} (size = B,C) */
a = Lua.GETARG_A( ins );
v[a][pc] = new VarInfo(a,pc);
@@ -235,6 +237,13 @@ public class ProtoInfo {
v[a][pc] = new VarInfo(a,pc);
break;
+ case Lua.OP_GETTABUP: /* A B C R(A) := UpValue[B][RK(C)] */
+ a = Lua.GETARG_A( ins );
+ c = Lua.GETARG_C( ins );
+ if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
+ v[a][pc] = new VarInfo(a,pc);
+ break;
+
case Lua.OP_SELF: /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
a = Lua.GETARG_A( ins );
b = Lua.GETARG_B( ins );
@@ -316,22 +325,16 @@ public class ProtoInfo {
v[a][pc] = VarInfo.INVALID;
break;
- case Lua.OP_CLOSURE: /* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
+ case Lua.OP_CLOSURE: { /* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
a = Lua.GETARG_A( ins );
b = Lua.GETARG_Bx( ins );
- nups = prototype.p[b].upvalues.length;
- for ( int k=1; k<=nups; ++k ) {
- int i = prototype.code[pc+k];
- if ( (i&4) == 0 ) {
- b = Lua.GETARG_B(i);
- v[b][pc].isreferenced = true;
- }
- }
+ Upvaldesc[] upvalues = prototype.p[b].upvalues;
+ for (int k = 0, nups = upvalues.length; k < nups; ++k)
+ if (upvalues[k].instack)
+ v[upvalues[k].idx][pc].isreferenced = true;
v[a][pc] = new VarInfo(a,pc);
- for ( int k=1; k<=nups; k++ )
- propogateVars( v, pc, pc+k );
- pc += nups;
break;
+ }
case Lua.OP_SETLIST: /* A B C R(A)[(C-1)*FPF+i]:= R(A+i), 1 <= i <= B */
a = Lua.GETARG_A( ins );
@@ -407,9 +410,8 @@ public class ProtoInfo {
UpvalInfo[] newu = new UpvalInfo[newp.upvalues.length];
String newname = name + "$" + bx;
for ( int j=0; j