Improve bytecode generation.
This commit is contained in:
@@ -239,7 +239,9 @@ public class luajc {
|
||||
}
|
||||
|
||||
} catch ( Throwable t ) {
|
||||
System.err.println(" failed to load "+inf.srcfilename+": "+t );
|
||||
t.printStackTrace( System.err );
|
||||
System.err.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,18 +102,17 @@ public class BasicBlock {
|
||||
}
|
||||
|
||||
public static void visitBranches( Prototype p, BranchVisitor visitor ) {
|
||||
int sbx,j;
|
||||
int sbx,j,c;
|
||||
int[] code = p.code;
|
||||
int n = code.length;
|
||||
for ( int i=0; i<n; i++ ) {
|
||||
int ins = code[i];
|
||||
switch ( Lua.GET_OPCODE( ins ) ) {
|
||||
case Lua.OP_LOADBOOL:
|
||||
if ( Lua.GETARG_C(ins) == 0 )
|
||||
if ( 0 == Lua.GETARG_C(ins) )
|
||||
break;
|
||||
if ( Lua.GET_OPCODE(code[i+1]) == Lua.OP_JMP )
|
||||
throw new IllegalArgumentException("OP_LOADBOOL followed by jump at "+i);
|
||||
visitor.visitBranch( i, i+1 );
|
||||
visitor.visitBranch( i, i+2 );
|
||||
continue;
|
||||
case Lua.OP_EQ:
|
||||
@@ -130,9 +129,14 @@ public class BasicBlock {
|
||||
visitor.visitBranch( i, j );
|
||||
visitor.visitBranch( i, i+1 );
|
||||
continue;
|
||||
case Lua.OP_FORLOOP:
|
||||
sbx = Lua.GETARG_sBx(ins);
|
||||
j = i + sbx + 1;
|
||||
visitor.visitBranch( i, j );
|
||||
visitor.visitBranch( i, i+1 );
|
||||
continue;
|
||||
case Lua.OP_JMP:
|
||||
case Lua.OP_FORPREP:
|
||||
case Lua.OP_FORLOOP:
|
||||
sbx = Lua.GETARG_sBx(ins);
|
||||
j = i + sbx + 1;
|
||||
visitor.visitBranch( i, j );
|
||||
|
||||
@@ -44,7 +44,7 @@ public class JavaGen {
|
||||
|
||||
// build this class
|
||||
JavaBuilder builder = new JavaBuilder(pi, classname, filename);
|
||||
scanInstructions(pi.prototype, classname, builder);
|
||||
scanInstructions(pi, classname, builder);
|
||||
this.bytecode = builder.completeClass();
|
||||
|
||||
// build sub-prototypes
|
||||
@@ -62,10 +62,19 @@ public class JavaGen {
|
||||
return classname+"$"+subprotoindex;
|
||||
}
|
||||
|
||||
private void scanInstructions(Prototype p, String classname, JavaBuilder builder) {
|
||||
private void scanInstructions(ProtoInfo pi, String classname, JavaBuilder builder) {
|
||||
Prototype p = pi.prototype;
|
||||
int vresultbase = -1;
|
||||
|
||||
for ( int pc=0, n=p.code.length; pc<n; pc++ ) {
|
||||
|
||||
// skip dead blocks
|
||||
BasicBlock b0 = pi.blocks[pc];
|
||||
if ( b0.pc0>0 && b0.prev == null ) {
|
||||
pc = b0.pc1;
|
||||
continue;
|
||||
}
|
||||
|
||||
int pc0 = pc; // closure changes pc
|
||||
int ins = p.code[pc];
|
||||
final int o = Lua.GET_OPCODE(ins);
|
||||
@@ -342,20 +351,22 @@ public class JavaGen {
|
||||
builder.isNil();
|
||||
builder.addBranch(pc, JavaBuilder.BRANCH_IFNE, pc+2);
|
||||
|
||||
// a[2] = a[3] = v[1]
|
||||
// a[2] = a[3] = v[1], leave varargs on stack
|
||||
builder.createUpvalues(pc, a+3, c);
|
||||
builder.loadVarresult();
|
||||
if ( c>=2 ) builder.dup();
|
||||
if (c>=2)
|
||||
builder.dup();
|
||||
builder.arg( 1 );
|
||||
builder.dup();
|
||||
builder.storeLocal(pc, a+2);
|
||||
builder.storeLocal(pc, a+3);
|
||||
|
||||
// a[a+2+i] = v[2+i], i=2..c
|
||||
for ( int i=2; i<=c; i++ ) {
|
||||
if ( i<c ) builder.dup();
|
||||
builder.arg( i );
|
||||
builder.storeLocal(pc, a+2+c);
|
||||
// v[2]..v[c], use varargs from stack
|
||||
for ( int j=2; j<=c; j++ ) {
|
||||
if ( j<c )
|
||||
builder.dup();
|
||||
builder.arg( j );
|
||||
builder.storeLocal(pc, a+2+j);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -380,6 +391,28 @@ public class JavaGen {
|
||||
|
||||
case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
|
||||
{
|
||||
/*
|
||||
String protoname = closureName(classname, bx);
|
||||
int nups = p.p[bx].nups;
|
||||
for ( int k=1; k<=nups; ++k ) {
|
||||
builder.dup();
|
||||
int i = p.code[pc+k];
|
||||
b = Lua.GETARG_B(i);
|
||||
if ( (i&4) == 0 ) {
|
||||
builder.closureInitUpvalueFromUpvalue( protoname, k-1, b );
|
||||
} else {
|
||||
builder.closureInitUpvalueFromLocal( protoname, k-1, pc, b );
|
||||
}
|
||||
}
|
||||
v[a][pc] = new VarInfo(a,pc);
|
||||
for ( int k=1; k<=nups; ++k ) {
|
||||
for ( int j=0; j<m; j++ )
|
||||
v[j][pc+k] = v[j][pc];
|
||||
}
|
||||
pc += nups;
|
||||
/*/
|
||||
|
||||
|
||||
Prototype newp = p.p[bx];
|
||||
String protoname = closureName(classname, bx);
|
||||
int nup = newp.nups;
|
||||
@@ -391,15 +424,17 @@ public class JavaGen {
|
||||
for ( int up=0; up<nup; ++up ) {
|
||||
if ( up+1 < nup )
|
||||
builder.dup();
|
||||
ins = p.code[++pc];
|
||||
ins = p.code[pc+up+1];
|
||||
b = Lua.GETARG_B(ins);
|
||||
if ( (ins&4) != 0 ) {
|
||||
builder.closureInitUpvalueFromUpvalue( protoname, up, b );
|
||||
} else {
|
||||
builder.closureInitUpvalueFromLocal( protoname, up, pc0, b );
|
||||
builder.closureInitUpvalueFromLocal( protoname, up, pc, b );
|
||||
}
|
||||
}
|
||||
pc += nup;
|
||||
}
|
||||
//*/
|
||||
break;
|
||||
}
|
||||
case Lua.OP_VARARG: /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
|
||||
|
||||
@@ -65,12 +65,13 @@ public class ProtoInfo {
|
||||
sb.append( " up["+i+"]: "+upvals[i]+"\n" );
|
||||
|
||||
// basic blocks
|
||||
for ( int i=0; i<blocklist.length; i++ ) {
|
||||
sb.append( " block "+blocklist[i].toString() );
|
||||
for ( int pc0=blocks[0].pc0; pc0<prototype.code.length; pc0=blocks[pc0].pc1+1 ) {
|
||||
BasicBlock b = blocks[pc0];
|
||||
sb.append( " block "+b.toString() );
|
||||
appendOpenUps( sb, -1 );
|
||||
|
||||
// instructions
|
||||
for ( int pc=blocklist[i].pc0; pc<=blocklist[i].pc1; pc++ ) {
|
||||
for ( int pc=pc0; pc<=b.pc1; pc++ ) {
|
||||
|
||||
// open upvalue storage
|
||||
appendOpenUps( sb, pc );
|
||||
@@ -79,8 +80,8 @@ public class ProtoInfo {
|
||||
sb.append( " " );
|
||||
for ( int j=0; j<prototype.maxstacksize; j++ ) {
|
||||
VarInfo v = vars[j][pc];
|
||||
String u = (v.upvalue!=null? !v.upvalue.rw? "[C] ": (v.allocupvalue&&v.pc==pc? "[*] ": "[] "): " ");
|
||||
String s = String.valueOf(v);
|
||||
String u = (v==null? "": v.upvalue!=null? !v.upvalue.rw? "[C] ": (v.allocupvalue&&v.pc==pc? "[*] ": "[] "): " ");
|
||||
String s = v==null? "null ": String.valueOf(v);
|
||||
sb.append( s+u);
|
||||
}
|
||||
sb.append( " " );
|
||||
@@ -109,7 +110,7 @@ public class ProtoInfo {
|
||||
private void appendOpenUps(StringBuffer sb, int pc) {
|
||||
for ( int j=0; j<prototype.maxstacksize; j++ ) {
|
||||
VarInfo v = (pc<0? params[j]: vars[j][pc]);
|
||||
if ( v.pc == pc && v.allocupvalue ) {
|
||||
if ( v != null && v.pc == pc && v.allocupvalue ) {
|
||||
sb.append( " open: "+v.upvalue+"\n" );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public class UpvalInfo {
|
||||
VarInfo v = pi.vars[slot][b.pc0];
|
||||
if ( v == poster ) {
|
||||
for ( int j=0, m=b.prev!=null? b.prev.length: 0; j<m; j++ ) {
|
||||
BasicBlock b0 = b.next[j];
|
||||
BasicBlock b0 = b.prev[j];
|
||||
VarInfo v0 = pi.vars[slot][b0.pc1];
|
||||
if ( v0 != poster )
|
||||
includeVarAndPosteriorVars( v0 );
|
||||
|
||||
@@ -480,5 +480,26 @@ public class FragmentsTest extends TestSuite {
|
||||
" end\n"+
|
||||
"end\n" );
|
||||
}
|
||||
|
||||
public void testBasicForLoop() {
|
||||
runFragment( LuaValue.valueOf(2),
|
||||
"local data\n"+
|
||||
"for i = 1, 2 do\n"+
|
||||
" data = i\n"+
|
||||
"end\n"+
|
||||
"local bar = function()\n"+
|
||||
" return data\n"+
|
||||
"end\n" +
|
||||
"return bar()\n" );
|
||||
}
|
||||
|
||||
public void testGenericForMultipleValues() {
|
||||
runFragment( LuaValue.varargsOf(LuaValue.valueOf(3),LuaValue.valueOf(2),LuaValue.valueOf(1)),
|
||||
"local iter = function() return 1,2,3,4 end\n" +
|
||||
"local foo = function() return iter,5 end\n" +
|
||||
"for a,b,c in foo() do\n" +
|
||||
" return c,b,a\n" +
|
||||
"end\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user