Add tests for jit argument passing
This commit is contained in:
@@ -93,6 +93,15 @@ public class LuaJit extends Lua implements LuaCompiler {
|
|||||||
|
|
||||||
// instantiate, config and return
|
// instantiate, config and return
|
||||||
if (success) {
|
if (success) {
|
||||||
|
// compile sub-prototypes
|
||||||
|
if ( p.p != null ) {
|
||||||
|
for ( int i=0, n=p.p.length; i<n; i++ ) {
|
||||||
|
if ( ! (p.p[i] instanceof JitPrototype) )
|
||||||
|
p.p[i] = jitCompile( p.p[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create JitPrototype instance
|
||||||
Class clazz = Class.forName(name);
|
Class clazz = Class.forName(name);
|
||||||
Object instance = clazz.newInstance();
|
Object instance = clazz.newInstance();
|
||||||
JitPrototype jp = (JitPrototype) instance;
|
JitPrototype jp = (JitPrototype) instance;
|
||||||
@@ -126,6 +135,7 @@ public class LuaJit extends Lua implements LuaCompiler {
|
|||||||
TESTS.add( OP_EQ );
|
TESTS.add( OP_EQ );
|
||||||
TESTS.add( OP_LT );
|
TESTS.add( OP_LT );
|
||||||
TESTS.add( OP_LE );
|
TESTS.add( OP_LE );
|
||||||
|
TESTS.add( OP_TESTSET );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean istest(int instr) {
|
private static boolean istest(int instr) {
|
||||||
@@ -170,7 +180,7 @@ public class LuaJit extends Lua implements LuaCompiler {
|
|||||||
// any backward jump is a loop bottom
|
// any backward jump is a loop bottom
|
||||||
if ( isbackwardjump(i) ) {
|
if ( isbackwardjump(i) ) {
|
||||||
int jmp = LuaState.GETARG_sBx(i);
|
int jmp = LuaState.GETARG_sBx(i);
|
||||||
s[pc+jmp+1] = append( s[pc+jmp+1], "while (true) { /* WHILETOP */ " );
|
s[pc+jmp+1] = append( s[pc+jmp+1], "while (true) { if(false)break; /* WHILETOP */ " );
|
||||||
s[pc] = append( "} /* LOOPBOT */ ", s[pc] );
|
s[pc] = append( "} /* LOOPBOT */ ", s[pc] );
|
||||||
int i2 = code[pc-1];
|
int i2 = code[pc-1];
|
||||||
if ( istest(i2) ) {
|
if ( istest(i2) ) {
|
||||||
@@ -262,13 +272,14 @@ public class LuaJit extends Lua implements LuaCompiler {
|
|||||||
|
|
||||||
// jit call
|
// jit call
|
||||||
ps.println( "\tpublic void jitCall(LuaState vm, LTable env, JitClosure jcl) {" );
|
ps.println( "\tpublic void jitCall(LuaState vm, LTable env, JitClosure jcl) {" );
|
||||||
ps.println( "\t\tint base = vm.base;" );
|
|
||||||
|
|
||||||
// parameters
|
// parameters
|
||||||
int ns = p.maxstacksize;
|
int ns = p.maxstacksize;
|
||||||
int is = 0;
|
int is = 0;
|
||||||
if ( ! p.is_vararg ) {
|
if ( ! p.is_vararg ) {
|
||||||
ps.println( "\t\tvm.settop("+p.numparams+");");
|
ps.println( "\t\tvm.checkstack("+(p.maxstacksize+1)+");" );
|
||||||
|
ps.println( "\t\tvm.settop("+(p.numparams+1)+");");
|
||||||
|
ps.println( "\t\tint base = vm.base + 1;" );
|
||||||
for (; is<p.numparams; is++ )
|
for (; is<p.numparams; is++ )
|
||||||
ps.println( "\t\tLValue s"+is+" = vm.stack[base+"+is+"];" );
|
ps.println( "\t\tLValue s"+is+" = vm.stack[base+"+is+"];" );
|
||||||
}
|
}
|
||||||
@@ -276,13 +287,14 @@ public class LuaJit extends Lua implements LuaCompiler {
|
|||||||
ps.println( "\t\tLValue s"+is+" = LNil.NIL;" );
|
ps.println( "\t\tLValue s"+is+" = LNil.NIL;" );
|
||||||
ps.println("\t\tLClosure newcl;");
|
ps.println("\t\tLClosure newcl;");
|
||||||
ps.println("\t\tByteArrayOutputStream baos;");
|
ps.println("\t\tByteArrayOutputStream baos;");
|
||||||
|
ps.println("\t\tLTable t;");
|
||||||
ps.println();
|
ps.println();
|
||||||
|
|
||||||
// save var args
|
// save var args
|
||||||
if ( p.is_vararg ) {
|
if ( p.is_vararg ) {
|
||||||
ps.println( "\t\tint ncopy, ntotal;" );
|
ps.println( "\t\tint ncopy, ntotal;" );
|
||||||
ps.println( "\t\tint nvarargs = vm.top - vm.base;" );
|
ps.println( "\t\tint nvarargs = vm.top - vm.base - 1;" );
|
||||||
ps.println( "\t\tbase = base + nvarargs;" );
|
ps.println( "\t\tint base = vm.base + 1 + nvarargs;" );
|
||||||
}
|
}
|
||||||
ps.println();
|
ps.println();
|
||||||
|
|
||||||
@@ -319,16 +331,20 @@ public class LuaJit extends Lua implements LuaCompiler {
|
|||||||
ps.println( "\t\ts"+a+" = k"+b+";" );
|
ps.println( "\t\ts"+a+" = k"+b+";" );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
case LuaState.OP_LOADBOOL: {
|
case LuaState.OP_LOADBOOL: {
|
||||||
|
// b = LuaState.GETARG_B(i);
|
||||||
|
// c = LuaState.GETARG_C(i);
|
||||||
|
// this.stack[base + a] = (b != 0 ? LBoolean.TRUE : LBoolean.FALSE);
|
||||||
|
// if (c != 0)
|
||||||
|
// ci.pc++; // skip next instruction (if C)
|
||||||
|
// continue;
|
||||||
b = LuaState.GETARG_B(i);
|
b = LuaState.GETARG_B(i);
|
||||||
c = LuaState.GETARG_C(i);
|
c = LuaState.GETARG_C(i);
|
||||||
this.stack[base + a] = (b != 0 ? LBoolean.TRUE : LBoolean.FALSE);
|
ps.println( "\t\ts"+a+" = LBoolean."+(b!=0? "TRUE": "FALSE")+";" );
|
||||||
if ( c != 0 )
|
if ( c != 0 )
|
||||||
ci.pc++; // skip next instruction (if C)
|
throw new java.lang.UnsupportedOperationException("can't jit compile LOADBOOL with c != 0");
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
case LuaState.OP_LOADNIL: {
|
case LuaState.OP_LOADNIL: {
|
||||||
b = LuaState.GETARG_B(i);
|
b = LuaState.GETARG_B(i);
|
||||||
ps.print("\t\t");
|
ps.print("\t\t");
|
||||||
@@ -434,17 +450,21 @@ public class LuaJit extends Lua implements LuaCompiler {
|
|||||||
ps.println( "\t\tif ( "+(c!=0?"!":"")+" s"+a+".toJavaBoolean() )" );
|
ps.println( "\t\tif ( "+(c!=0?"!":"")+" s"+a+".toJavaBoolean() )" );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
case LuaState.OP_TESTSET: {
|
case LuaState.OP_TESTSET: {
|
||||||
rkb = GETARG_RKB(k, i);
|
// rkb = GETARG_RKB(k, i);
|
||||||
|
// c = LuaState.GETARG_C(i);
|
||||||
|
// if (rkb.toJavaBoolean() != (c != 0))
|
||||||
|
// ci.pc++;
|
||||||
|
// else
|
||||||
|
// this.stack[base + a] = rkb;
|
||||||
|
// continue;
|
||||||
|
bs = GETARG_RKB_jit(i);
|
||||||
c = LuaState.GETARG_C(i);
|
c = LuaState.GETARG_C(i);
|
||||||
if (rkb.toJavaBoolean() != (c != 0))
|
ps.println( "\t\tif ( "+(c!=0?"!":"")+" "+bs+".toJavaBoolean() )" );
|
||||||
ci.pc++;
|
ps.println( "\t\t\ts"+a+" = "+bs+";" );
|
||||||
else
|
ps.println( "\t\telse" );
|
||||||
this.stack[base + a] = rkb;
|
break;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
case LuaState.OP_CALL: {
|
case LuaState.OP_CALL: {
|
||||||
//
|
//
|
||||||
//// ra is base of new call frame
|
//// ra is base of new call frame
|
||||||
@@ -474,22 +494,21 @@ public class LuaJit extends Lua implements LuaCompiler {
|
|||||||
//
|
//
|
||||||
//continue;
|
//continue;
|
||||||
|
|
||||||
|
b = LuaState.GETARG_B(i);
|
||||||
|
c = LuaState.GETARG_C(i);
|
||||||
|
|
||||||
// copy call to vm stack
|
// copy call to vm stack
|
||||||
ps.println( "\t\tvm.stack[base+"+a+"] = s"+a+";" );
|
ps.println( "\t\tvm.stack[base+"+a+"] = s"+a+";" );
|
||||||
|
|
||||||
// number of args
|
// number of args
|
||||||
b = LuaState.GETARG_B(i);
|
|
||||||
if (b > 0) { // else use previous instruction set top
|
if (b > 0) { // else use previous instruction set top
|
||||||
for ( int j=1; j<b; j++ )
|
for ( int j=1; j<b; j++ )
|
||||||
ps.println( "\t\tvm.stack[base+"+(a+j)+"] = s"+(a+j)+";" );
|
ps.println( "\t\tvm.stack[base+"+(a+j)+"] = s"+(a+j)+";" );
|
||||||
ps.println( "\t\tvm.top = base+"+(a+b)+";" );
|
ps.println( "\t\tvm.top = base+"+(a+b)+";" );
|
||||||
}
|
|
||||||
|
|
||||||
// number of return values we need
|
|
||||||
c = LuaState.GETARG_C(i);
|
|
||||||
|
|
||||||
// make the call
|
|
||||||
ps.println("\t\tvm.call("+(b-1)+","+(c-1)+");");
|
ps.println("\t\tvm.call("+(b-1)+","+(c-1)+");");
|
||||||
|
} else {
|
||||||
|
ps.println("\t\tvm.call(vm.top-base+"+(a-1)+","+(c-1)+");");
|
||||||
|
}
|
||||||
|
|
||||||
// copy results to local vars
|
// copy results to local vars
|
||||||
if ( c > 0 )
|
if ( c > 0 )
|
||||||
@@ -562,15 +581,19 @@ public class LuaJit extends Lua implements LuaCompiler {
|
|||||||
//// force a reload of the calling context
|
//// force a reload of the calling context
|
||||||
//return;
|
//return;
|
||||||
// number of return vals to return
|
// number of return vals to return
|
||||||
|
if ( Lua.GET_OPCODE(code[pc-1]) == Lua.OP_RETURN )
|
||||||
|
break;
|
||||||
|
|
||||||
if ( p.is_vararg )
|
if ( p.is_vararg )
|
||||||
ps.println( "\t\tbase -= nvarargs;" );
|
ps.println( "\t\tbase -= nvarargs;" );
|
||||||
|
else
|
||||||
|
ps.println( "\t\tbase -= 1;" );
|
||||||
|
|
||||||
b = LuaState.GETARG_B(i);
|
b = LuaState.GETARG_B(i);
|
||||||
if (b > 0) {
|
if (b > 0) {
|
||||||
for ( int j=1; j<b; j++ )
|
for ( int j=1; j<b; j++ )
|
||||||
ps.println( "\t\tvm.stack[base+"+(a+j-1)+"] = s"+(a+j-1)+";" );
|
ps.println( "\t\tvm.stack[base+"+(j-1)+"] = s"+(a+j-1)+";" );
|
||||||
ps.println( "\t\tvm.top = base+"+(a+b)+";" );
|
ps.println( "\t\tvm.top = base+"+(b-1)+";" );
|
||||||
}
|
}
|
||||||
ps.println( "\t\treturn;" );
|
ps.println( "\t\treturn;" );
|
||||||
break;
|
break;
|
||||||
@@ -606,11 +629,13 @@ public class LuaJit extends Lua implements LuaCompiler {
|
|||||||
c = code[++pc];
|
c = code[++pc];
|
||||||
int offset = (c-1) * LFIELDS_PER_FLUSH;
|
int offset = (c-1) * LFIELDS_PER_FLUSH;
|
||||||
if ( b == 0 ) {
|
if ( b == 0 ) {
|
||||||
|
ps.println("\t\tt = (LTable) s"+(a)+";");
|
||||||
ps.println("\t\tfor ( int j=0, nj=vm.top-base-"+(a+1)+"; j<nj; j++ )");
|
ps.println("\t\tfor ( int j=0, nj=vm.top-base-"+(a+1)+"; j<nj; j++ )");
|
||||||
ps.println("\t\t\ts"+(a)+".put("+offset+"+j,vm.stack[base+"+a+"+j]);");
|
ps.println("\t\t\tt.put("+offset+"+j,vm.stack[base+"+a+"+j]);");
|
||||||
} else {
|
} else {
|
||||||
|
ps.println("\t\tt = (LTable) s"+(a)+";");
|
||||||
for (int j=1; j<=b; j++)
|
for (int j=1; j<=b; j++)
|
||||||
ps.println("\t\ts"+(a)+".put("+(offset+j)+",s"+(a+j)+");");
|
ps.println("\t\tt.put("+(offset+j)+",s"+(a+j)+");");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,17 @@ public class LuaJitBasicTest extends TestCase {
|
|||||||
stringTest( "print( 'hello, world' )" );
|
stringTest( "print( 'hello, world' )" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testArgPassing() throws IOException {
|
||||||
|
stringTest(
|
||||||
|
"local function f(a,b)\n" +
|
||||||
|
" print('a',a,'b',b)\n" +
|
||||||
|
" return 'c','d'\n" +
|
||||||
|
"end\n" +
|
||||||
|
"print( 'f1', f(123) )\n" +
|
||||||
|
"print( 'f2', f(456,789) )\n" +
|
||||||
|
"print( 'f3', f(12,34,56) )\n" );
|
||||||
|
}
|
||||||
|
|
||||||
public void testForInDoEnd() throws IOException {
|
public void testForInDoEnd() throws IOException {
|
||||||
stringTest(
|
stringTest(
|
||||||
"local t = {abc=123,def=456}\n" +
|
"local t = {abc=123,def=456}\n" +
|
||||||
|
|||||||
92
src/test/java/org/luaj/jit/LuaJitPerfTest.java
Normal file
92
src/test/java/org/luaj/jit/LuaJitPerfTest.java
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package org.luaj.jit;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.luaj.compiler.LuaC;
|
||||||
|
import org.luaj.lib.BaseLib;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public class LuaJitPerfTest extends TestCase {
|
||||||
|
|
||||||
|
static {
|
||||||
|
Platform.setInstance(new J2sePlatform());
|
||||||
|
LuaC.install();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// public void testFannkuch() throws IOException {
|
||||||
|
// timedFileTest( "fannkuch.lua" );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public void testMandelbrot() throws IOException {
|
||||||
|
// timedFileTest( "mandelbrot.lua" );
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void testNbody() throws IOException {
|
||||||
|
timedFileTest( "nbody.lua" );
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// public void testForLoop() throws IOException {
|
||||||
|
// timedTest( "for loop",
|
||||||
|
// "local sum=0\n" +
|
||||||
|
// "for i=1,10000,1 do\n" +
|
||||||
|
// " sum = sum + i\n" +
|
||||||
|
// "end");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
|
private void timedFileTest(String filename) throws IOException {
|
||||||
|
File file = new File("src/test/perf/"+filename);
|
||||||
|
int len = (int) file.length();
|
||||||
|
byte[] b = new byte[len];
|
||||||
|
DataInputStream dis = new DataInputStream( new FileInputStream( file ) );
|
||||||
|
dis.readFully(b);
|
||||||
|
dis.close();
|
||||||
|
timedTest( filename, new String(b) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timedTest(String testName, String script) throws IOException {
|
||||||
|
System.out.println("---- "+testName+" ----");
|
||||||
|
InputStream is = new ByteArrayInputStream(script.getBytes());
|
||||||
|
LPrototype p = LuaC.compile(is, "script");
|
||||||
|
int plain = timeTrial( "plain", p );
|
||||||
|
LPrototype q = LuaJit.jitCompile( p );
|
||||||
|
assertTrue(p!=q);
|
||||||
|
int jit = timeTrial( "jit", q );
|
||||||
|
System.out.println("plain="+plain+" jit="+jit+" ratio="+(double)jit/(double)plain);
|
||||||
|
assertTrue( "jit faster than plain", jit > plain );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int timeTrial(String type, LPrototype p) {
|
||||||
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
BaseLib.redirectOutput(outputStream);
|
||||||
|
LuaState vm = Platform.newLuaState();
|
||||||
|
LClosure c = p.newClosure(vm._G);
|
||||||
|
int globalCount = 0;
|
||||||
|
for ( int i=0; i<5; i++ ) {
|
||||||
|
int localCount = 0;
|
||||||
|
long t1 = System.currentTimeMillis() + 1000;
|
||||||
|
while ( t1 > System.currentTimeMillis() ) {
|
||||||
|
vm.pushlvalue(c);
|
||||||
|
vm.call(0, 0);
|
||||||
|
localCount++;
|
||||||
|
}
|
||||||
|
System.out.println(type+": "+(localCount));
|
||||||
|
System.out.flush();
|
||||||
|
globalCount += localCount;
|
||||||
|
}
|
||||||
|
return globalCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user