Improve bytecode generation.
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 );
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 );
|
||||||
|
|||||||
@@ -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" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user