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 ) {
System.err.println(" failed to load "+inf.srcfilename+": "+t );
t.printStackTrace( System.err );
System.err.flush();
}
}
}

View File

@@ -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 );

View File

@@ -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 */

View File

@@ -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" );
}
}

View File

@@ -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 );

View File

@@ -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" );
}
}
}