corda/sgx-jvm/avian/test/Subroutine.java
Andras Slemmer 9bb3d6b972 Add 'sgx-jvm/avian/' from commit '09e4fe60d01f4f4bfb6b2976973bb4913ef61edc'
git-subtree-dir: sgx-jvm/avian
git-subtree-mainline: f978eab8d1
git-subtree-split: 09e4fe60d0
2017-03-13 12:18:24 +00:00

348 lines
8.0 KiB
Java

import avian.Stream;
import avian.ConstantPool;
import avian.ConstantPool.PoolEntry;
import avian.Assembler;
import avian.Assembler.FieldData;
import avian.Assembler.MethodData;
import java.util.ArrayList;
import java.util.List;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.IOException;
public class Subroutine {
private static void expect(boolean v) {
if (! v) throw new RuntimeException();
}
private static void stackMap(Object x) {
while (true) {
try {
try {
System.gc();
} catch (DummyException e) {
// ignore
} finally {
x.toString();
}
break;
} catch (DummyException e) {
// ignore
}
}
}
private static byte[] makeTestCode(List pool) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
Stream.write2(out, 1); // max stack
Stream.write2(out, 1); // max locals
Stream.write4(out, 0); // length (we'll set the real value later)
// 0:
Stream.write1(out, Assembler.ldc_w);
Stream.write2(out, ConstantPool.addString(pool, "foo") + 1);
// 3:
Stream.write1(out, Assembler.astore_0);
// 4:
Stream.write1(out, Assembler.invokestatic);
Stream.write2(out, ConstantPool.addMethodRef
(pool, "java/lang/System", "gc", "()V") + 1);
// 7:
Stream.write1(out, Assembler.goto_);
Stream.write2(out, 9); // 16
// 10:
Stream.write1(out, Assembler.astore_0);
// 11:
Stream.write1(out, Assembler.invokestatic);
Stream.write2(out, ConstantPool.addMethodRef
(pool, "java/lang/System", "gc", "()V") + 1);
// 14:
Stream.write1(out, Assembler.ret);
Stream.write1(out, 0);
// 16:
Stream.write1(out, Assembler.jsr);
Stream.write2(out, -6); // 10
// 19:
Stream.write1(out, Assembler.invokestatic);
Stream.write2(out, ConstantPool.addMethodRef
(pool, "java/lang/System", "gc", "()V") + 1);
// 22:
Stream.write1(out, Assembler.return_);
Stream.write2(out, 0); // exception handler table length
Stream.write2(out, 0); // attribute count
byte[] result = out.toByteArray();
Stream.set4(result, 4, result.length - 12);
return result;
}
private static Class makeTestClass() throws IOException {
List pool = new ArrayList();
ByteArrayOutputStream out = new ByteArrayOutputStream();
String name = "$SubroutineTest$";
Assembler.writeClass
(out, pool, ConstantPool.addClass(pool, name),
ConstantPool.addClass(pool, "java/lang/Object"),
new int[0], new FieldData[0], new MethodData[]
{ new MethodData(Assembler.ACC_STATIC | Assembler.ACC_PUBLIC,
ConstantPool.addUtf8(pool, "test"),
ConstantPool.addUtf8(pool, "()V"),
makeTestCode(pool)) });
return new MyClassLoader(Subroutine.class.getClassLoader())
.defineClass(name, out.toByteArray());
}
// These tests are intended to cover the jsr and ret instructions.
// However, recent Sun javac versions avoid generating these
// instructions by default, so we must compile this class using
// -source 1.2 -target 1.1 -XDjsrlimit=0.
//
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4381996
//
private static void test(boolean throw_, boolean predicate) {
int x = 42;
int y = 99;
int a = 0;
try {
try {
int z = x + y;
if (throw_) throw new DummyException();
if (predicate) {
return;
}
Integer.valueOf(z).toString();
} finally {
a = x + y;
System.gc();
}
expect(a == x + y);
} catch (DummyException e) {
e.printStackTrace();
}
}
private static Object test2(int path) {
try {
try {
switch (path) {
case 1:
return new Object();
case 2: {
int a = 42;
return Integer.valueOf(a);
}
case 3:
throw new DummyException();
}
} finally {
System.gc();
}
return null;
} catch (DummyException e) {
e.printStackTrace();
return null;
}
}
private static Object test3(int path1, int path2, int path3) {
try {
try {
switch (path1) {
case 1:
return new Object();
case 2: {
int a = 42;
return Integer.valueOf(a);
}
case 3:
throw new DummyException();
}
} finally {
try {
switch (path2) {
case 1:
return new Object();
case 2: {
int a = 42;
return Integer.valueOf(a);
}
case 3:
throw new DummyException();
}
} finally {
try {
switch (path3) {
case 1:
return new Object();
case 2: {
int a = 42;
return Integer.valueOf(a);
}
case 3:
throw new DummyException();
}
} finally {
System.gc();
}
}
}
return null;
} catch (DummyException e) {
e.printStackTrace();
return null;
}
}
private static long test4(int path) {
try {
try {
switch (path) {
case 1:
return 0xFABFABFABFL;
case 2: {
int a = 42;
return 52L;
}
case 3:
throw new DummyException();
}
} finally {
System.gc();
}
return 0L;
} catch (DummyException e) {
e.printStackTrace();
return 0L;
}
}
private boolean test5(boolean predicate) {
try {
if (predicate) {
return false;
}
} finally {
synchronized (this) {
notifyAll();
}
}
return true;
}
private static int test6(boolean predicate) {
try {
if (predicate) {
return -2;
}
} finally {
return new Throwable().getStackTrace()[0].getLineNumber();
}
}
public static void main(String[] args) throws Exception {
test(false, false);
test(false, true);
test(true, false);
String.valueOf(test2(1));
String.valueOf(test2(2));
String.valueOf(test2(3));
String.valueOf(test3(1, 1, 1));
String.valueOf(test3(2, 1, 1));
String.valueOf(test3(3, 1, 1));
String.valueOf(test3(1, 2, 1));
String.valueOf(test3(2, 2, 1));
String.valueOf(test3(3, 2, 1));
String.valueOf(test3(1, 3, 1));
String.valueOf(test3(2, 3, 1));
String.valueOf(test3(3, 3, 1));
String.valueOf(test3(1, 1, 2));
String.valueOf(test3(2, 1, 2));
String.valueOf(test3(3, 1, 2));
String.valueOf(test3(1, 2, 2));
String.valueOf(test3(2, 2, 2));
String.valueOf(test3(3, 2, 2));
String.valueOf(test3(1, 3, 2));
String.valueOf(test3(2, 3, 2));
String.valueOf(test3(3, 3, 2));
String.valueOf(test3(1, 1, 3));
String.valueOf(test3(2, 1, 3));
String.valueOf(test3(3, 1, 3));
String.valueOf(test3(1, 2, 3));
String.valueOf(test3(2, 2, 3));
String.valueOf(test3(3, 2, 3));
String.valueOf(test3(1, 3, 3));
String.valueOf(test3(2, 3, 3));
String.valueOf(test3(3, 3, 3));
String.valueOf(test4(1));
String.valueOf(test4(2));
String.valueOf(test4(3));
expect(test4(1) == 0xFABFABFABFL);
new Subroutine().test5(true);
new Subroutine().test5(false);
makeTestClass().getMethod("test", new Class[0]).invoke
(null, new Object[0]);
stackMap(new Object());
{
int f = test6(false);
int t = test6(true);
System.out.println("line: " + f);
expect(f > 0);
expect(f == t);
}
}
private static class DummyException extends RuntimeException { }
private static class MyClassLoader extends ClassLoader {
public MyClassLoader(ClassLoader parent) {
super(parent);
}
public Class defineClass(String name, byte[] bytes) {
return super.defineClass(name, bytes, 0, bytes.length);
}
}
}