Improve bytecode generation.

This commit is contained in:
James Roseborough
2010-08-11 18:21:20 +00:00
parent 3d4a3dbb65
commit 267e89adef
6 changed files with 87 additions and 24 deletions

View File

@@ -239,7 +239,9 @@ public class luajc {
} }
} catch ( Throwable t ) { } catch ( Throwable t ) {
System.err.println(" failed to load "+inf.srcfilename+": "+t );
t.printStackTrace( System.err ); t.printStackTrace( System.err );
System.err.flush();
} }
} }
} }

View File

@@ -102,18 +102,17 @@ public class BasicBlock {
} }
public static void visitBranches( Prototype p, BranchVisitor visitor ) { public static void visitBranches( Prototype p, BranchVisitor visitor ) {
int sbx,j; int sbx,j,c;
int[] code = p.code; int[] code = p.code;
int n = code.length; int n = code.length;
for ( int i=0; i<n; i++ ) { for ( int i=0; i<n; i++ ) {
int ins = code[i]; int ins = code[i];
switch ( Lua.GET_OPCODE( ins ) ) { switch ( Lua.GET_OPCODE( ins ) ) {
case Lua.OP_LOADBOOL: case Lua.OP_LOADBOOL:
if ( Lua.GETARG_C(ins) == 0 ) if ( 0 == Lua.GETARG_C(ins) )
break; break;
if ( Lua.GET_OPCODE(code[i+1]) == Lua.OP_JMP ) if ( Lua.GET_OPCODE(code[i+1]) == Lua.OP_JMP )
throw new IllegalArgumentException("OP_LOADBOOL followed by jump at "+i); throw new IllegalArgumentException("OP_LOADBOOL followed by jump at "+i);
visitor.visitBranch( i, i+1 );
visitor.visitBranch( i, i+2 ); visitor.visitBranch( i, i+2 );
continue; continue;
case Lua.OP_EQ: case Lua.OP_EQ:
@@ -130,9 +129,14 @@ public class BasicBlock {
visitor.visitBranch( i, j ); visitor.visitBranch( i, j );
visitor.visitBranch( i, i+1 ); visitor.visitBranch( i, i+1 );
continue; 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_JMP:
case Lua.OP_FORPREP: case Lua.OP_FORPREP:
case Lua.OP_FORLOOP:
sbx = Lua.GETARG_sBx(ins); sbx = Lua.GETARG_sBx(ins);
j = i + sbx + 1; j = i + sbx + 1;
visitor.visitBranch( i, j ); visitor.visitBranch( i, j );

View File

@@ -44,7 +44,7 @@ public class JavaGen {
// build this class // build this class
JavaBuilder builder = new JavaBuilder(pi, classname, filename); JavaBuilder builder = new JavaBuilder(pi, classname, filename);
scanInstructions(pi.prototype, classname, builder); scanInstructions(pi, classname, builder);
this.bytecode = builder.completeClass(); this.bytecode = builder.completeClass();
// build sub-prototypes // build sub-prototypes
@@ -62,10 +62,19 @@ public class JavaGen {
return classname+"$"+subprotoindex; 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; int vresultbase = -1;
for ( int pc=0, n=p.code.length; pc<n; pc++ ) { 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 pc0 = pc; // closure changes pc
int ins = p.code[pc]; int ins = p.code[pc];
final int o = Lua.GET_OPCODE(ins); final int o = Lua.GET_OPCODE(ins);
@@ -342,20 +351,22 @@ public class JavaGen {
builder.isNil(); builder.isNil();
builder.addBranch(pc, JavaBuilder.BRANCH_IFNE, pc+2); 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.createUpvalues(pc, a+3, c);
builder.loadVarresult(); builder.loadVarresult();
if ( c>=2 ) builder.dup(); if (c>=2)
builder.dup();
builder.arg( 1 ); builder.arg( 1 );
builder.dup(); builder.dup();
builder.storeLocal(pc, a+2); builder.storeLocal(pc, a+2);
builder.storeLocal(pc, a+3); builder.storeLocal(pc, a+3);
// a[a+2+i] = v[2+i], i=2..c // v[2]..v[c], use varargs from stack
for ( int i=2; i<=c; i++ ) { for ( int j=2; j<=c; j++ ) {
if ( i<c ) builder.dup(); if ( j<c )
builder.arg( i ); builder.dup();
builder.storeLocal(pc, a+2+c); builder.arg( j );
builder.storeLocal(pc, a+2+j);
} }
break; break;
@@ -380,6 +391,28 @@ public class JavaGen {
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)) */
{ {
/*
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]; Prototype newp = p.p[bx];
String protoname = closureName(classname, bx); String protoname = closureName(classname, bx);
int nup = newp.nups; int nup = newp.nups;
@@ -391,15 +424,17 @@ public class JavaGen {
for ( int up=0; up<nup; ++up ) { for ( int up=0; up<nup; ++up ) {
if ( up+1 < nup ) if ( up+1 < nup )
builder.dup(); builder.dup();
ins = p.code[++pc]; ins = p.code[pc+up+1];
b = Lua.GETARG_B(ins); b = Lua.GETARG_B(ins);
if ( (ins&4) != 0 ) { if ( (ins&4) != 0 ) {
builder.closureInitUpvalueFromUpvalue( protoname, up, b ); builder.closureInitUpvalueFromUpvalue( protoname, up, b );
} else { } else {
builder.closureInitUpvalueFromLocal( protoname, up, pc0, b ); builder.closureInitUpvalueFromLocal( protoname, up, pc, b );
} }
} }
pc += nup;
} }
//*/
break; break;
} }
case Lua.OP_VARARG: /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ case Lua.OP_VARARG: /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */

View File

@@ -65,12 +65,13 @@ public class ProtoInfo {
sb.append( " up["+i+"]: "+upvals[i]+"\n" ); sb.append( " up["+i+"]: "+upvals[i]+"\n" );
// basic blocks // basic blocks
for ( int i=0; i<blocklist.length; i++ ) { for ( int pc0=blocks[0].pc0; pc0<prototype.code.length; pc0=blocks[pc0].pc1+1 ) {
sb.append( " block "+blocklist[i].toString() ); BasicBlock b = blocks[pc0];
sb.append( " block "+b.toString() );
appendOpenUps( sb, -1 ); appendOpenUps( sb, -1 );
// instructions // instructions
for ( int pc=blocklist[i].pc0; pc<=blocklist[i].pc1; pc++ ) { for ( int pc=pc0; pc<=b.pc1; pc++ ) {
// open upvalue storage // open upvalue storage
appendOpenUps( sb, pc ); appendOpenUps( sb, pc );
@@ -79,8 +80,8 @@ public class ProtoInfo {
sb.append( " " ); sb.append( " " );
for ( int j=0; j<prototype.maxstacksize; j++ ) { for ( int j=0; j<prototype.maxstacksize; j++ ) {
VarInfo v = vars[j][pc]; VarInfo v = vars[j][pc];
String u = (v.upvalue!=null? !v.upvalue.rw? "[C] ": (v.allocupvalue&&v.pc==pc? "[*] ": "[] "): " "); String u = (v==null? "": v.upvalue!=null? !v.upvalue.rw? "[C] ": (v.allocupvalue&&v.pc==pc? "[*] ": "[] "): " ");
String s = String.valueOf(v); String s = v==null? "null ": String.valueOf(v);
sb.append( s+u); sb.append( s+u);
} }
sb.append( " " ); sb.append( " " );
@@ -109,7 +110,7 @@ public class ProtoInfo {
private void appendOpenUps(StringBuffer sb, int pc) { private void appendOpenUps(StringBuffer sb, int pc) {
for ( int j=0; j<prototype.maxstacksize; j++ ) { for ( int j=0; j<prototype.maxstacksize; j++ ) {
VarInfo v = (pc<0? params[j]: vars[j][pc]); 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" ); sb.append( " open: "+v.upvalue+"\n" );
} }
} }

View File

@@ -64,7 +64,7 @@ public class UpvalInfo {
VarInfo v = pi.vars[slot][b.pc0]; VarInfo v = pi.vars[slot][b.pc0];
if ( v == poster ) { if ( v == poster ) {
for ( int j=0, m=b.prev!=null? b.prev.length: 0; j<m; j++ ) { 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]; VarInfo v0 = pi.vars[slot][b0.pc1];
if ( v0 != poster ) if ( v0 != poster )
includeVarAndPosteriorVars( v0 ); includeVarAndPosteriorVars( v0 );

View File

@@ -480,5 +480,26 @@ public class FragmentsTest extends TestSuite {
" end\n"+ " end\n"+
"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" );
}
} }
} }