From 88770a36304fb81e40148d3100eaf0b1751473ab Mon Sep 17 00:00:00 2001 From: James Roseborough Date: Sun, 29 Jun 2008 18:34:22 +0000 Subject: [PATCH] Add control flow extraction to jit compiler. --- src/script/org/luaj/jit/LuaJit.java | 213 ++++++------------ .../java/org/luaj/jit/LuaJitBasicTest.java | 53 +++++ 2 files changed, 125 insertions(+), 141 deletions(-) create mode 100644 src/test/java/org/luaj/jit/LuaJitBasicTest.java diff --git a/src/script/org/luaj/jit/LuaJit.java b/src/script/org/luaj/jit/LuaJit.java index 4ad55981..0c6c2b6d 100644 --- a/src/script/org/luaj/jit/LuaJit.java +++ b/src/script/org/luaj/jit/LuaJit.java @@ -21,7 +21,6 @@ ******************************************************************************/ package org.luaj.jit; -import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -38,14 +37,11 @@ import javax.tools.JavaCompiler.CompilationTask; import org.luaj.compiler.LuaC; import org.luaj.debug.Print; -import org.luaj.platform.J2sePlatform; -import org.luaj.vm.LClosure; import org.luaj.vm.LPrototype; import org.luaj.vm.LValue; import org.luaj.vm.LoadState; import org.luaj.vm.Lua; import org.luaj.vm.LuaState; -import org.luaj.vm.Platform; import org.luaj.vm.LoadState.LuaCompiler; public class LuaJit extends Lua implements LuaCompiler { @@ -57,42 +53,6 @@ public class LuaJit extends Lua implements LuaCompiler { LoadState.compiler = new LuaJit(); } - public static void main(String[] args) throws IOException { - - Platform.setInstance(new J2sePlatform()); - LuaC.install(); - - String program = "print 'starting'\n" + - "for i=1,10 do\n" + - " print 'hello, world'\n" + - "end"; - program = "print 'a'\n" + - "if a then\n" + - " print 'a'\n" + - "elseif b then\n" + - " print 'b'\n" + - "else\n" + - " print 'c'\n" + - "end\n" + - "print 'd'\n"; - InputStream is = new ByteArrayInputStream(program.getBytes()); - LPrototype p = LuaC.compile(is, "program"); - test( p ); - LPrototype q = LuaJit.jitCompile( p ); - test( q ); - } - - private static void test(LPrototype p) { - try { - LuaState vm = Platform.newLuaState(); - LClosure c = p.newClosure(vm._G); - vm.pushlvalue(c); - vm.call(0, 0); - } catch ( Throwable e ) { - e.printStackTrace(); - } - } - private static int filenum = 0; private static synchronized String filename() { @@ -166,17 +126,76 @@ public class LuaJit extends Lua implements LuaCompiler { private static boolean isjump(int i) { return Lua.GET_OPCODE(i) == OP_JMP; } + + private static String append( String s, String t ) { + return (s==null? t: t==null? s: s+t); + } + + private static String[] extractControlFlow( int[] code ) { + int n = code.length; + String[] s = new String[n]; + int jmp; + + for ( int pc=0; pc 0 ) { + s[pc+jmp+1] = append( s[pc+jmp+1], "else { /* ELSE */ " ); + s[pc+jmp+jmp2+1] = append( "} /* ENDELSE */ ", s[pc+jmp+jmp2+1] ); + } + } + + } + break; + case OP_FORLOOP: + jmp = LuaState.GETARG_sBx(code[pc]); + s[pc+jmp] = append( s[pc+jmp], "{ /* FORTOP */ " ); + s[pc] = append( "} /* LOOPBOT */ ", s[pc] ); + break; + } + } + + + // find local variables, jump points + return s; + } private static void writeSource( PrintStream ps, String name, LPrototype p ) { - int i, a, b, c, o, n, cb; - LValue rkb, rkc, nvarargs, key, val; - LValue i0, table; - boolean body; + int i, a, b, c, o; String bs, cs; int[] code = p.code; LValue[] k = p.k; + String[] controlflow = extractControlFlow(code); // class header ps.print( @@ -227,32 +246,6 @@ public class LuaJit extends Lua implements LuaCompiler { } ps.println(); - - // find local variables, jump points - int forlevel=0,maxforlevels=0; - int[] closes = new int[code.length]; - boolean[] iselse = new boolean[code.length]; - for ( int pc=0; pc> POS_OP) & MAX_OP; - switch (o) { - case OP_FORPREP: - maxforlevels = Math.max(maxforlevels, ++forlevel); - break; - case OP_FORLOOP: - forlevel--; - break; - case OP_JMP: { - int delta = LuaState.GETARG_sBx(code[pc]); - ++closes[pc+delta+1]; - if ( istest(code[pc-1]) && isjump(code[pc+delta]) ) - iselse[pc+delta+1] = true; - break; - } - } - } - for ( int j=0; j0 || iselse[pc] ) { - ps.print("\t\t"); - while ( closes[pc]-- > 0 ) - ps.print("} "); - if ( iselse[pc] ) - ps.print(" else {"); - ps.println(); - } - // get opcode and first arg o = (i >> POS_OP) & MAX_OP; a = (i >> POS_A) & MAXARG_A; @@ -323,85 +308,42 @@ public class LuaJit extends Lua implements LuaCompiler { break; } case LuaState.OP_GETGLOBAL: { - // b = LuaState.GETARG_Bx(i); - // key = k[b]; - // table = cl.env; - // top = base + a; - // table.luaGetTable(this, table, key); - // pw.println("\t\tvm.top = base+"+a+";"); - // continue b = LuaState.GETARG_Bx(i); - ps.println("\t\tenv.luaGetTable(vm, env, k"+b+");"); - ps.println("\t\ts"+a+" = vm.stack[--vm.top];"); + ps.println("\t\ts"+a+" = vm.luaV_gettable(env, k"+b+");"); break; } case LuaState.OP_GETTABLE: { - //b = GETARG_B(i); - //key = GETARG_RKC(k, i); - //table = this.stack[base + b]; - //top = base + a; - //table.luaGetTable(this, table, key); - //continue; b = GETARG_B(i); cs = GETARG_RKC_jit(i); - ps.println("\t\ts"+b+".luaGetTable(vm, s"+b+", "+cs+");"); - ps.println("\t\ts"+a+" = vm.stack[--vm.top];"); + ps.println("\t\ts"+a+" = vm.luaV_gettable(s"+b+", "+cs+");"); break; } case LuaState.OP_SETGLOBAL: { - //b = LuaState.GETARG_Bx(i); - //key = k[b]; - //val = this.stack[base + a]; - //table = cl.env; - //table.luaSetTable(this, table, key, val); - //continue; b = LuaState.GETARG_Bx(i); - ps.println("\t\tenv.luaSetTable(vm, env, k"+b+", s"+a+");"); + ps.println("\t\tvm.luaV_settable(env, k"+b+", s"+a+");"); break; } case LuaState.OP_SETUPVAL: { - //b = LuaState.GETARG_B(i); - //cl.upVals[b].setValue( this.stack[base + a] ); - //continue; b = LuaState.GETARG_B(i); ps.println("\t\t\tjcl.upVals["+b+"].setValue(s"+a+");"); break; } case LuaState.OP_SETTABLE: { - //key = GETARG_RKB(k, i); - //val = GETARG_RKC(k, i); - //table = this.stack[base + a]; - //table.luaSetTable(this, table, key, val); - //continue; bs = GETARG_RKB_jit(i); cs = GETARG_RKC_jit(i); - ps.println("\t\ts"+a+".luaSetTable(vm, s"+a+", "+bs+", "+cs+");"); + ps.println("\t\tvm.luaV_settable(s"+a+", "+bs+", "+cs+");"); break; } case LuaState.OP_NEWTABLE: { - //b = LuaState.GETARG_B(i); - //c = LuaState.GETARG_C(i); - //this.stack[base + a] = new LTable(b, c); - //continue; b = GETARG_B(i); c = GETARG_C(i); ps.println("\t\ts"+a+" = new LTable("+b+","+c+");"); break; } case LuaState.OP_SELF: { - //rkb = GETARG_RKB(k, i); - //rkc = GETARG_RKC(k, i); - //top = base + a; - //rkb.luaGetTable(this, rkb, rkc); - //this.stack[base + a + 1] = rkb; - //// StkId rb = RB(i); - //// setobjs2s(L, ra+1, rb); - //// Protect(luaV_gettable(L, rb, RKC(i), ra)); - //continue; bs = GETARG_RKB_jit(i); cs = GETARG_RKC_jit(i); - ps.println("\t\t"+bs+".luaGetTable(vm, "+bs+", "+cs+");"); - ps.println("\t\ts"+(a+1)+" = "+bs+";"); + ps.println("\t\ts"+a+" = vm.luaV_gettable((s"+(a+1)+"="+bs+"), "+cs+");"); break; } case LuaState.OP_ADD: @@ -420,25 +362,15 @@ public class LuaJit extends Lua implements LuaCompiler { break; } case LuaState.OP_UNM: { - //rkb = GETARG_RKB(k, i); - //this.stack[base + a] = rkb.luaUnaryMinus(); - //continue; bs = GETARG_RKB_jit(i); ps.println("\t\ts"+a+" = "+bs+".luaUnaryMinus();"); } case LuaState.OP_NOT: { - //rkb = GETARG_RKB(k, i); - //this.stack[base + a] = (!rkb.toJavaBoolean() ? LBoolean.TRUE - // : LBoolean.FALSE); - //continue; bs = GETARG_RKB_jit(i); ps.println("\t\ts"+a+" = ("+bs+".toJavaBoolean()? LBoolean.TRUE: LBoolean.FALSE);"); break; } case LuaState.OP_LEN: { - //rkb = GETARG_RKB(k, i); - //this.stack[base + a] = LInteger.valueOf( rkb.luaLength() ); - //continue; bs = GETARG_RKB_jit(i); ps.println("\t\ts"+a+" = LInteger.valueOf("+bs+".luaLength());"); } @@ -484,7 +416,6 @@ public class LuaJit extends Lua implements LuaCompiler { //continue; c = LuaState.GETARG_C(i); ps.println("\t\tif ( "+(c!=0?"!":"")+" s"+a+".toJavaBoolean())"); - ps.println("\t\t{"); break; } /* @@ -644,14 +575,14 @@ public class LuaJit extends Lua implements LuaCompiler { String limit = "s"+(a+1); String step = "s"+(a+2); String idx = "s"+(a+3); - String back = "back"+(forlevel++); + String back = "back"+pc; + ps.println( "\t\tboolean "+back+";"); ps.println( "\t\tfor ( "+idx+"="+init+", "+back+"="+step+".luaBinCmpInteger(Lua.OP_LT,0);\n" + "\t\t\t"+back+"? "+idx+".luaBinCmpUnknown(Lua.OP_LE, "+limit+"): "+limit+".luaBinCmpUnknown(Lua.OP_LE, "+idx+");\n" + "\t\t\t"+idx+"="+idx+".luaBinOpUnknown(Lua.OP_ADD,"+step+") ) {"); break; } case LuaState.OP_FORLOOP: { - --forlevel; ps.println( "\t\t}"); //i0 = this.stack[base + a]; //step = this.stack[base + a + 2]; diff --git a/src/test/java/org/luaj/jit/LuaJitBasicTest.java b/src/test/java/org/luaj/jit/LuaJitBasicTest.java new file mode 100644 index 00000000..f6295186 --- /dev/null +++ b/src/test/java/org/luaj/jit/LuaJitBasicTest.java @@ -0,0 +1,53 @@ +package org.luaj.jit; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import junit.framework.TestCase; + +import org.luaj.compiler.LuaC; +import org.luaj.platform.J2sePlatform; +import org.luaj.vm.LClosure; +import org.luaj.vm.LPrototype; +import org.luaj.vm.LuaState; +import org.luaj.vm.Platform; + +/** + * Simple test cases for lua jit basic functional test + */ +public class LuaJitBasicTest extends TestCase { + + static { + Platform.setInstance(new J2sePlatform()); + LuaC.install(); + } + + public void testPrintHelloWorld() throws IOException { + stringTest( "print( 'hello, world' )" ); + } + + public void testForLoop() throws IOException { + stringTest( "print 'starting'\n" + + "for i=1,3 do\n" + + " print( 'i', i )\n" + + "end"); + } + + private void stringTest(String program) throws IOException { + InputStream is = new ByteArrayInputStream(program.getBytes()); + LPrototype p = LuaC.compile(is, "program"); + run( p ); + LPrototype q = LuaJit.jitCompile( p ); + assertTrue(p!=q); + run( q ); + } + + private static void run(LPrototype p) { + LuaState vm = Platform.newLuaState(); + LClosure c = p.newClosure(vm._G); + vm.pushlvalue(c); + vm.call(0, 0); + } + +}