diff --git a/src/core/org/luaj/vm2/LuaString.java b/src/core/org/luaj/vm2/LuaString.java index 29fa46c6..4bacc44e 100644 --- a/src/core/org/luaj/vm2/LuaString.java +++ b/src/core/org/luaj/vm2/LuaString.java @@ -56,6 +56,14 @@ public class LuaString extends LuaValue { this.m_length = bytes.length; } + public static LuaString valueOf(char[] bytes) { + int n = bytes.length; + byte[] b = new byte[n]; + for ( int i=0; i= 0 ) continue; + if ( ((c & 0xE0) == 0xC0) + && i0xff? k[c&0x0ff]: stack[c]); + ih[pc] = + loadLocal(B(i)); + if ((c=C(i))>0xff) + il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); + else + loadLocal(c); + il.append(factory.createInvoke(STR_LUAVALUE, "get", TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); + storeLocal(a); + break; + + case Lua.OP_SETGLOBAL: /* A Bx Gbl[Kst(Bx)]:= R(A) */ + // env.set(k[Bx(i)], stack[a]); + ih[pc] = + loadEnv(il); + il.append(factory.createFieldAccess(classname, k[Bx(i)].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); + loadLocal(a); + il.append(factory.createInvoke(STR_LUAVALUE, "set", Type.VOID, new Type[] { TYPE_LUAVALUE, TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); + break; + + case Lua.OP_SETUPVAL: /* A B UpValue[B]:= R(A) */ + // upValues[B(i)].setValue(stack[a]); + ih[pc] = + il.append(InstructionConstants.THIS); + il.append(factory.createFieldAccess(classname, u[B(i)].getName(), TYPE_LOCALUPVALUE, Constants.GETFIELD)); + il.append(new PUSH(cp,0)); + loadLocal(a); + il.append(InstructionConstants.AASTORE); + break; + + case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */ + // stack[a].set(((b=B(i))>0xff? k[b&0x0ff]: stack[b]), (c=C(i))>0xff? k[c&0x0ff]: stack[c]); + ih[pc] = + loadLocal(a); + if ((b=B(i))>0xff) + il.append(factory.createFieldAccess(classname, k[b&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); + else + loadLocal(b); + if ((c=C(i))>0xff) + il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); + else + loadLocal(c); + il.append(factory.createInvoke(STR_LUAVALUE, "set", Type.VOID, new Type[] { TYPE_LUAVALUE, TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); + break; + + case Lua.OP_NEWTABLE: /* A B C R(A):= {} (size = B,C) */ + // stack[a] = new LuaTable(B(i),C(i)); + ih[pc] = + il.append(new PUSH(cp, B(i))); + il.append(new PUSH(cp, C(i))); + il.append(factory.createInvoke(STR_LUAVALUE, "tableOf", TYPE_LUATABLE, new Type[] { Type.INT, Type.INT }, Constants.INVOKESTATIC)); + storeLocal(a); + break; + + case Lua.OP_SELF: /* A B C R(A+1):= R(B): R(A):= R(B)[RK(C)] */ + // stack[a+1] = (o = stack[B(i)]); + ih[pc] = + loadLocal(B(i)); + il.append(InstructionConstants.DUP); + storeLocal(a+1); + // stack[a] = o.get((c=C(i))>0xff? k[c&0x0ff]: stack[c]); + if ((c=C(i))>0xff) + il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); + else + loadLocal(c); + il.append(factory.createInvoke(STR_LUAVALUE, "get", TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); + storeLocal(a); + break; + + case Lua.OP_ADD: /* A B C R(A):= RK(B) + RK(C) */ + case Lua.OP_SUB: /* A B C R(A):= RK(B) - RK(C) */ + case Lua.OP_MUL: /* A B C R(A):= RK(B) * RK(C) */ + case Lua.OP_DIV: /* A B C R(A):= RK(B) / RK(C) */ + case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */ + case Lua.OP_POW: /* A B C R(A):= RK(B) ^ RK(C) */ + { + String op; + switch (OP(i)) { + default: + case Lua.OP_ADD: op = "add"; break; + case Lua.OP_SUB: op = "sub"; break; + case Lua.OP_MUL: op = "mul"; break; + case Lua.OP_DIV: op = "div"; break; + case Lua.OP_MOD: op = "mod"; break; + case Lua.OP_POW: op = "pow"; break; + } + // stack[a] = ((b=B(i))>0xff? k[b&0x0ff]: stack[b]).add((c=C(i))>0xff? k[c&0x0ff]: stack[c]); + if ((b=B(i))>0xff) + ih[pc] = + il.append(factory.createFieldAccess(classname, k[b&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); + else + ih[pc] = + loadLocal(b); + if ((c=C(i))>0xff) + il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); + else + loadLocal(c); + il.append(factory.createInvoke(STR_LUAVALUE, op, TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); + storeLocal(a); + break; + } + case Lua.OP_UNM: /* A B R(A):= -R(B) */ + // stack[a] = stack[B(i)].neg(); + ih[pc] = + loadLocal(B(i)); + il.append(factory.createInvoke(STR_LUAVALUE, "neg", TYPE_LUAVALUE, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); + storeLocal(a); + break; + + case Lua.OP_NOT: /* A B R(A):= not R(B) */ + // stack[a] = stack[B(i)].not(); + ih[pc] = + loadLocal(B(i)); + il.append(factory.createInvoke(STR_LUAVALUE, "not", TYPE_LUAVALUE, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); + storeLocal(a); + break; + + case Lua.OP_LEN: /* A B R(A):= length of R(B) */ + // stack[a] = stack[B(i)].len(); + ih[pc] = + loadLocal(B(i)); + il.append(factory.createInvoke(STR_LUAVALUE, "len", TYPE_LUAVALUE, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); + storeLocal(a); + break; + + case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */ + { + b = B(i); + c = C(i); + + // Buffer sb = new Buffer(); + ih[pc] = + il.append(factory.createNew(TYPE_BUFFER)); + il.append(InstructionConstants.DUP); + il.append(factory.createInvoke(STR_BUFFER, "", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); + + // concatenate + for ( ; b<=c; ) { + // sb.append( stack[b++].checkstring() ); + il.append(InstructionConstants.DUP); + loadLocal(b++); + il.append(factory.createInvoke(STR_LUAVALUE, "checkstring", TYPE_LUASTRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); + il.append(factory.createInvoke(STR_BUFFER, "append", Type.VOID, new Type[] { TYPE_LUASTRING }, Constants.INVOKEVIRTUAL)); + } + + // store + // stack[a] = sb.tostrvalue(); + il.append(factory.createInvoke(STR_BUFFER, "tostrvalue", TYPE_LUASTRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); + storeLocal(a); + } + break; + + case Lua.OP_JMP: /* sBx pc+=sBx */ + // pc += (Bx(i))-0x1ffff; + branches[pc] = new GOTO(null); + targets[pc] = pc + 1 + (Bx(i))-0x1ffff; + ih[pc] = + il.append(branches[pc]); + break; + + case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ + case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ + case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ + { + String op; + switch (OP(i)) { + default: + case Lua.OP_EQ: op = "eq_b"; break; + case Lua.OP_LT: op = "lt_b"; break; + case Lua.OP_LE: op = "lteq_b"; break; + } + if ((b=B(i))>0xff) + ih[pc] = + il.append(factory.createFieldAccess(classname, k[b&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); + else + ih[pc] = + loadLocal(b); + if ((c=C(i))>0xff) + il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); + else + loadLocal(c); + il.append(factory.createInvoke(STR_LUAVALUE, op, Type.BOOLEAN, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); + branches[pc] = (a!=0)? new IFEQ(null): new IFNE(null); + targets[pc] = pc + 2; + il.append(branches[pc]); + break; + } + case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */ + ih[pc] = + loadLocal(a); + il.append(factory.createInvoke(STR_LUAVALUE, "toboolean", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); + branches[pc] = (C(i)!=0)? new IFEQ(null): new IFNE(null); + targets[pc] = pc + 2; + il.append(branches[pc]); + break; + + 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[B(i)]).toboolean() != (C(i)!=0) ) + // ++pc; + //else + // stack[a] = o; // TODO: should be sBx? + ih[pc] = + loadLocal(B(i)); + il.append(factory.createInvoke(STR_LUAVALUE, "toboolean", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); + branches[pc] = (C(i)!=0)? new IFEQ(null): new IFNE(null); + targets[pc] = pc + 2; + il.append(branches[pc]); + loadLocal(B(i)); + storeLocal(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_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ + ih[pc] = + loadLocal(a); + b = B(i); + c = C(i); + switch ( b ) { + case 1: // noargs + loadNone(il); + break; + case 2: // one arg + loadLocal(a+1); + break; + case 3: // two args + loadLocal(a+1); + loadLocal(a+2); + il.append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, new Type[] { TYPE_LUAVALUE, TYPE_VARARGS }, Constants.INVOKESTATIC)); + break; + case 4: // three args + loadLocal(a+1); + loadLocal(a+2); + loadLocal(a+3); + il.append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, new Type[] { TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_VARARGS }, Constants.INVOKESTATIC)); + break; + default: // fixed arg count + il.append(new PUSH(cp, b-1)); + il.append(new ANEWARRAY(cp.addClass(STR_LUAVALUE))); + for ( int j=0; j=) R(A)*/ + for ( int j=nl; --j>=a; ) { + isinited[j] = true; + locals[j] = null; + } + markups( p, isup, code, pc+1, a ); + break; + + case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ + { + b = Bx(i); + Prototype newp = p.p[b]; + String protoname = classname+"$"+b; + + // instantiate the class + ih[pc] = + il.append(factory.createNew(new ObjectType(protoname))); + il.append(InstructionConstants.DUP); + il.append(factory.createInvoke(protoname, "", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); + + // set the environment + il.append(InstructionConstants.DUP); + loadEnv( il ); + il.append(factory.createInvoke(STR_LUAVALUE, "setfenv", Type.VOID, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); + + // initialize upvalues of new instance + for ( int j=0, nup=newp.nups; j 0) { + il.append(new PUSH(cp, 1 + np)); + il.append(factory.createInvoke(STR_VARARGS, "subargs", + TYPE_VARARGS, new Type[] { Type.INT }, + Constants.INVOKEVIRTUAL)); + } + storeVarreturns(il); + vbase = a; + } else { + for ( int j=1; j= nc) { + for ( pc=0; pc", cg @@ -210,13 +1071,25 @@ public class JavaBytecodeGenerator { k[i].getName(), k[i].getType())); break; case LuaValue.TSTRING: - // TODO: quote non-utf8 byte sequences - il.append(new PUSH(cp, ki.toString())); - il.append(factory.createInvoke(STR_LUASTRING, "valueOf", - TYPE_LUASTRING, new Type[] { Type.STRING }, - Constants.INVOKESTATIC)); - il.append(factory.createPutStatic(classname, - k[i].getName(), k[i].getType())); + LuaString ls = ki.checkstring(); + if ( ls.isValidUtf8() ) { + il.append(new PUSH(cp, ki.toString())); + il.append(factory.createInvoke(STR_LUASTRING, "valueOf", + TYPE_LUASTRING, new Type[] { Type.STRING }, + Constants.INVOKESTATIC)); + } else { + char[] c = new char[ls.m_length]; + for ( int j=0; j= upvalues.length || upvalues[i] == null ) + return "u"+i; + return "$"+upvalues[i].toString(); + } + + // find the upvalues implied by the subsequent instructions + private void markups(Prototype p, boolean[] isup, int[] code, int startpc, int startregister) { + int last = isup.length; + for ( int j=startregister; j 0) { - il.append(new ALOAD(1)); - il.append(new PUSH(cp, 1 + np)); - il.append(factory.createInvoke(STR_VARARGS, "subargs", - TYPE_VARARGS, new Type[] { Type.INT }, - Constants.INVOKEVIRTUAL)); - il.append(new ASTORE(1)); - } - - // this local variable stores varargs, - // and is only created by functions that need it. - // TODO: only include if necessary - LocalVariableGen v = null; - int vbase = 0; - v = mg.addLocalVariable("v", TYPE_VARARGS, null, null); - il.append(factory.createFieldAccess(STR_LUAVALUE, "NONE", - TYPE_LUAVALUE, Constants.GETSTATIC)); - il.append(new ASTORE(v.getIndex())); - - // storage for goto locations - int[] targets = new int[nc]; - BranchInstruction[] branches = new BranchInstruction[nc]; - InstructionHandle[] ih = new InstructionHandle[nc]; - - // each lua bytecode gets some java bytecodes - for (pc = 0; pc < nc; pc++) { - - // pull out instruction - i = code[pc]; - a = A(i); - - // process the op code - switch ( OP(i) ) { - - case Lua.OP_MOVE:/* A B R(A):= R(B) */ - ih[pc] = - il_append_new_ALOAD(cp,il, (locals[B(i)])); - il_append_new_ASTORE(cp,il, (locals[a])); - break; - - case Lua.OP_LOADK:/* A Bx R(A):= Kst(Bx) */ - ih[pc] = - il.append(factory.createFieldAccess(classname, k[Bx(i)].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); - il_append_new_ASTORE(cp,il, (locals[a])); - break; - - case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */ - //stack[a] = (B(i)!=0)? LuaValue.TRUE: LuaValue.FALSE; - ih[pc] = - il.append(factory.createFieldAccess(STR_LUAVALUE, ((B(i)!=0)? "TRUE": "FALSE"), TYPE_LUABOOLEAN, Constants.GETSTATIC)); - il_append_new_ASTORE(cp,il, (locals[a])); - if (C(i) != 0) { - // pc++; /* skip next instruction (if C) */ - branches[pc] = new GOTO(null); - targets[pc] = pc + 2; - il.append(branches[pc]); - } - break; - - case Lua.OP_LOADNIL: /* A B R(A):= ...:= R(B):= nil */ - ih[pc] = - il.append(factory.createFieldAccess(STR_LUAVALUE, "NIL", TYPE_LUAVALUE, Constants.GETSTATIC)); - for ( b=B(i); a<=b; ) { - il.append(InstructionConstants.DUP); - il_append_new_ASTORE(cp,il, (locals[a++])); - } - il.append(InstructionConstants.POP); - break; - - case Lua.OP_GETUPVAL: /* A B R(A):= UpValue[B] */ - ih[pc] = - il.append(InstructionConstants.THIS); - il.append(factory.createFieldAccess(classname, getUpvalueName(p.upvalues, B(i)), TYPE_LOCALUPVALUE, Constants.GETFIELD)); - il.append(new PUSH(cp,0)); - il.append(InstructionConstants.AALOAD); - il_append_new_ASTORE(cp,il, (locals[a])); - break; - - case Lua.OP_GETGLOBAL: /* A Bx R(A):= Gbl[Kst(Bx)] */ - ih[pc] = - il.append(InstructionConstants.THIS); - il.append(factory.createFieldAccess(classname, "env", TYPE_LUAVALUE, Constants.GETFIELD)); - il.append(factory.createFieldAccess(classname, k[Bx(i)].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); - il.append(factory.createInvoke(STR_LUAVALUE, "get", TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); - il_append_new_ASTORE(cp,il, (locals[a])); - break; - - case Lua.OP_GETTABLE: /* A B C R(A):= R(B)[RK(C)] */ - // stack[a] = stack[B(i)].get((c=C(i))>0xff? k[c&0x0ff]: stack[c]); - ih[pc] = - il_append_new_ALOAD(cp,il, (locals[B(i)])); - if ((c=C(i))>0xff) - il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); - else - il_append_new_ALOAD(cp,il, (locals[c])); - il.append(factory.createInvoke(STR_LUAVALUE, "get", TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); - il_append_new_ASTORE(cp,il, (locals[a])); - break; - - case Lua.OP_SETGLOBAL: /* A Bx Gbl[Kst(Bx)]:= R(A) */ - // env.set(k[Bx(i)], stack[a]); - ih[pc] = - il.append(InstructionConstants.THIS); - il.append(factory.createFieldAccess(classname, "env", TYPE_LUAVALUE, Constants.GETFIELD)); - il.append(factory.createFieldAccess(classname, k[Bx(i)].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); - il_append_new_ALOAD(cp,il, (locals[a])); - il.append(factory.createInvoke(STR_LUAVALUE, "set", Type.VOID, new Type[] { TYPE_LUAVALUE, TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); - break; - - case Lua.OP_SETUPVAL: /* A B UpValue[B]:= R(A) */ - // upValues[B(i)].setValue(stack[a]); - ih[pc] = - il.append(InstructionConstants.THIS); - il.append(factory.createFieldAccess(classname, getUpvalueName( p.upvalues, B(i)), TYPE_LOCALUPVALUE, Constants.GETFIELD)); - il.append(new PUSH(cp,0)); - il_append_new_ALOAD(cp,il, (locals[a])); - il.append(InstructionConstants.AASTORE); - break; - - case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */ - // stack[a].set(((b=B(i))>0xff? k[b&0x0ff]: stack[b]), (c=C(i))>0xff? k[c&0x0ff]: stack[c]); - ih[pc] = - il_append_new_ALOAD(cp,il, (locals[a])); - if ((b=B(i))>0xff) - il.append(factory.createFieldAccess(classname, k[b&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); - else - il_append_new_ALOAD(cp,il, (locals[b])); - if ((c=C(i))>0xff) - il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); - else - il_append_new_ALOAD(cp,il, (locals[c])); - il.append(factory.createInvoke(STR_LUAVALUE, "set", Type.VOID, new Type[] { TYPE_LUAVALUE, TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); - break; - - case Lua.OP_NEWTABLE: /* A B C R(A):= {} (size = B,C) */ - // stack[a] = new LuaTable(B(i),C(i)); - ih[pc] = - il.append(new PUSH(cp, B(i))); - il.append(new PUSH(cp, C(i))); - il.append(factory.createInvoke(STR_LUAVALUE, "tableOf", TYPE_LUATABLE, new Type[] { Type.INT, Type.INT }, Constants.INVOKESTATIC)); - il_append_new_ASTORE(cp,il, (locals[a])); - break; - - case Lua.OP_SELF: /* A B C R(A+1):= R(B): R(A):= R(B)[RK(C)] */ - // stack[a+1] = (o = stack[B(i)]); - ih[pc] = - il_append_new_ALOAD(cp,il, (locals[B(i)])); - il.append(InstructionConstants.DUP); - il_append_new_ASTORE(cp,il, (locals[a+1])); - // stack[a] = o.get((c=C(i))>0xff? k[c&0x0ff]: stack[c]); - if ((c=C(i))>0xff) - il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); - else - il_append_new_ALOAD(cp,il, (locals[c])); - il.append(factory.createInvoke(STR_LUAVALUE, "get", TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); - il_append_new_ASTORE(cp,il, (locals[a])); - break; - - case Lua.OP_ADD: /* A B C R(A):= RK(B) + RK(C) */ - case Lua.OP_SUB: /* A B C R(A):= RK(B) - RK(C) */ - case Lua.OP_MUL: /* A B C R(A):= RK(B) * RK(C) */ - case Lua.OP_DIV: /* A B C R(A):= RK(B) / RK(C) */ - case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */ - case Lua.OP_POW: /* A B C R(A):= RK(B) ^ RK(C) */ - { - String op; - switch (OP(i)) { - default: - case Lua.OP_ADD: op = "add"; break; - case Lua.OP_SUB: op = "sub"; break; - case Lua.OP_MUL: op = "mul"; break; - case Lua.OP_DIV: op = "div"; break; - case Lua.OP_MOD: op = "mod"; break; - case Lua.OP_POW: op = "pow"; break; - } - // stack[a] = ((b=B(i))>0xff? k[b&0x0ff]: stack[b]).add((c=C(i))>0xff? k[c&0x0ff]: stack[c]); - if ((b=B(i))>0xff) - ih[pc] = - il.append(factory.createFieldAccess(classname, k[b&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); - else - ih[pc] = - il_append_new_ALOAD(cp,il, (locals[b])); - if ((c=C(i))>0xff) - il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); - else - il_append_new_ALOAD(cp,il, (locals[c])); - il.append(factory.createInvoke(STR_LUAVALUE, op, TYPE_LUAVALUE, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); - il_append_new_ASTORE(cp,il, (locals[a])); - break; - } - case Lua.OP_UNM: /* A B R(A):= -R(B) */ - // stack[a] = stack[B(i)].neg(); - ih[pc] = - il_append_new_ALOAD(cp,il, (locals[B(i)])); - il.append(factory.createInvoke(STR_LUAVALUE, "neg", TYPE_LUAVALUE, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); - il_append_new_ASTORE(cp,il, (locals[a])); - break; - - case Lua.OP_NOT: /* A B R(A):= not R(B) */ - // stack[a] = stack[B(i)].not(); - ih[pc] = - il_append_new_ALOAD(cp,il, (locals[B(i)])); - il.append(factory.createInvoke(STR_LUAVALUE, "not", TYPE_LUAVALUE, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); - il_append_new_ASTORE(cp,il, (locals[a])); - break; - - case Lua.OP_LEN: /* A B R(A):= length of R(B) */ - // stack[a] = stack[B(i)].len(); - ih[pc] = - il_append_new_ALOAD(cp,il, (locals[B(i)])); - il.append(factory.createInvoke(STR_LUAVALUE, "len", TYPE_LUAVALUE, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); - il_append_new_ASTORE(cp,il, (locals[a])); - break; - - case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */ - { - b = B(i); - c = C(i); - - // Buffer sb = new Buffer(); - ih[pc] = - il.append(factory.createNew(TYPE_BUFFER)); - il.append(InstructionConstants.DUP); - il.append(factory.createInvoke(STR_BUFFER, "", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); - - // concatenate - for ( ; b<=c; ) { - // sb.append( stack[b++].checkstring() ); - il.append(InstructionConstants.DUP); - il_append_new_ALOAD(cp,il, (locals[b++])); - il.append(factory.createInvoke(STR_LUAVALUE, "checkstring", TYPE_LUASTRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); - il.append(factory.createInvoke(STR_BUFFER, "append", Type.VOID, new Type[] { TYPE_LUASTRING }, Constants.INVOKEVIRTUAL)); - } - - // store - // stack[a] = sb.tostrvalue(); - il.append(factory.createInvoke(STR_BUFFER, "tostrvalue", TYPE_LUASTRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); - il_append_new_ASTORE(cp,il, (locals[a])); - } - break; - - case Lua.OP_JMP: /* sBx pc+=sBx */ - // pc += (Bx(i))-0x1ffff; - branches[pc] = new GOTO(null); - targets[pc] = pc + 1 + (Bx(i))-0x1ffff; - ih[pc] = - il.append(branches[pc]); - break; - - case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ - case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ - case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ - { - String op; - switch (OP(i)) { - default: - case Lua.OP_EQ: op = "eq_b"; break; - case Lua.OP_LT: op = "lt_b"; break; - case Lua.OP_LE: op = "lteq_b"; break; - } - if ((b=B(i))>0xff) - ih[pc] = - il.append(factory.createFieldAccess(classname, k[b&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); - else - ih[pc] = - il_append_new_ALOAD(cp,il, (locals[b])); - if ((c=C(i))>0xff) - il.append(factory.createFieldAccess(classname, k[c&0x0ff].getName(), TYPE_LUAVALUE, Constants.GETSTATIC)); - else - il_append_new_ALOAD(cp,il, (locals[c])); - il.append(factory.createInvoke(STR_LUAVALUE, op, Type.BOOLEAN, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); - branches[pc] = (a!=0)? new IFEQ(null): new IFNE(null); - targets[pc] = pc + 2; - il.append(branches[pc]); - break; - } - case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */ - ih[pc] = - il_append_new_ALOAD(cp,il, (locals[a])); - il.append(factory.createInvoke(STR_LUAVALUE, "toboolean", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); - branches[pc] = (C(i)!=0)? new IFEQ(null): new IFNE(null); - targets[pc] = pc + 2; - il.append(branches[pc]); - break; - - 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[B(i)]).toboolean() != (C(i)!=0) ) - // ++pc; - //else - // stack[a] = o; // TODO: should be sBx? - ih[pc] = - il_append_new_ALOAD(cp,il, (locals[B(i)])); - il.append(factory.createInvoke(STR_LUAVALUE, "toboolean", Type.BOOLEAN, Type.NO_ARGS, Constants.INVOKEVIRTUAL)); - branches[pc] = (C(i)!=0)? new IFEQ(null): new IFNE(null); - targets[pc] = pc + 2; - il.append(branches[pc]); - il_append_new_ALOAD(cp,il, (locals[B(i)])); - il_append_new_ASTORE(cp,il, (locals[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_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ - ih[pc] = - il_append_new_ALOAD(cp,il, (locals[a])); - b = B(i); - c = C(i); - switch ( b ) { - case 1: // noargs - il.append(factory.createFieldAccess(STR_LUAVALUE, "NONE", TYPE_LUAVALUE, Constants.GETSTATIC)); - break; - case 2: // one arg - il_append_new_ALOAD(cp,il, (locals[a+1])); - break; - case 3: // two args - il_append_new_ALOAD(cp,il, (locals[a+1])); - il_append_new_ALOAD(cp,il, (locals[a+2])); - il.append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, new Type[] { TYPE_LUAVALUE, TYPE_VARARGS }, Constants.INVOKESTATIC)); - break; - case 4: // three args - il_append_new_ALOAD(cp,il, (locals[a+1])); - il_append_new_ALOAD(cp,il, (locals[a+2])); - il_append_new_ALOAD(cp,il, (locals[a+3])); - il.append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, new Type[] { TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_VARARGS }, Constants.INVOKESTATIC)); - break; - default: // fixed arg count - il.append(new PUSH(cp, b-1)); - il.append(new ANEWARRAY(cp.addClass(STR_LUAVALUE))); - for ( int j=0; j=) R(A)*/ - for ( int j=nl; --j>=a; ) { - if ( isup[j] ) { - il.append(new PUSH(cp, 1)); - il.append(new ANEWARRAY(cp.addClass(STR_LUAVALUE))); - il.append(new ASTORE(locals[j].getIndex())); - } - } - // markups( p, isup, code, pc+1, a ); - break; - - case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ - { - b = Bx(i); - Prototype newp = p.p[b]; - String protoname = classname+"$"+b; - - // instantiate the class - ih[pc] = - il.append(factory.createNew(new ObjectType(protoname))); - il.append(InstructionConstants.DUP); - il.append(factory.createInvoke(protoname, "", Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL)); - - // set the environment - il.append(InstructionConstants.DUP); - il.append(InstructionConstants.THIS); - il.append(factory.createFieldAccess(classname, "env", TYPE_LUAVALUE, Constants.GETFIELD)); - il.append(factory.createInvoke(STR_LUAVALUE, "setfenv", Type.VOID, new Type[] { TYPE_LUAVALUE }, Constants.INVOKEVIRTUAL)); - - // initialize upvalues of new instance - for ( int j=0, nup=newp.nups; j= nc) { - for ( pc=0; pc