Fix bugs in runtime. Add support for System.out

This commit is contained in:
Alexey Andreev 2016-09-15 18:53:25 +03:00
parent 67098a60ef
commit bb2f23b19b
6 changed files with 74 additions and 46 deletions

View File

@ -17,6 +17,8 @@ package org.teavm.classlib.java.lang;
import org.teavm.classlib.java.io.TIOException; import org.teavm.classlib.java.io.TIOException;
import org.teavm.classlib.java.io.TOutputStream; import org.teavm.classlib.java.io.TOutputStream;
import org.teavm.interop.DelegateTo;
import org.teavm.interop.Import;
import org.teavm.platform.Platform; import org.teavm.platform.Platform;
/** /**
@ -25,7 +27,15 @@ import org.teavm.platform.Platform;
*/ */
class TConsoleOutputStreamStderr extends TOutputStream { class TConsoleOutputStreamStderr extends TOutputStream {
@Override @Override
@DelegateTo("writeLowLevel")
public void write(int b) throws TIOException { public void write(int b) throws TIOException {
Platform.getConsole().error(b); Platform.getConsole().error(b);
} }
private void writeLowLevel(int b) {
writeImpl(b);
}
@Import(name = "putchar", module = "runtime")
static native void writeImpl(int b);
} }

View File

@ -17,6 +17,7 @@ package org.teavm.classlib.java.lang;
import org.teavm.classlib.java.io.TIOException; import org.teavm.classlib.java.io.TIOException;
import org.teavm.classlib.java.io.TOutputStream; import org.teavm.classlib.java.io.TOutputStream;
import org.teavm.interop.DelegateTo;
import org.teavm.platform.Platform; import org.teavm.platform.Platform;
/** /**
@ -25,7 +26,12 @@ import org.teavm.platform.Platform;
*/ */
class TConsoleOutputStreamStdout extends TOutputStream { class TConsoleOutputStreamStdout extends TOutputStream {
@Override @Override
@DelegateTo("writeLowLevel")
public void write(int b) throws TIOException { public void write(int b) throws TIOException {
Platform.getConsole().output(b); Platform.getConsole().output(b);
} }
private void writeLowLevel(int b) {
TConsoleOutputStreamStderr.writeImpl(b);
}
} }

View File

@ -42,6 +42,7 @@ public final class Example {
} }
private static void testBigInteger() { private static void testBigInteger() {
System.out.println("Running BigInteger benchmark");
BigInteger result = BigInteger.ONE; BigInteger result = BigInteger.ONE;
for (int j = 0; j < 100; ++j) { for (int j = 0; j < 100; ++j) {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
@ -59,51 +60,51 @@ public final class Example {
long end = System.currentTimeMillis(); long end = System.currentTimeMillis();
println("Operation took " + (end - start) + " milliseconds"); System.out.println("Operation took " + (end - start) + " milliseconds");
} }
println(result.toString()); System.out.println(result.toString());
} }
private static void testFibonacci() { private static void testFibonacci() {
int a = 0; int a = 0;
int b = 1; int b = 1;
println("Fibonacci numbers:"); System.out.println("Fibonacci numbers:");
for (int i = 0; i < 30; ++i) { for (int i = 0; i < 30; ++i) {
int c = a + b; int c = a + b;
a = b; a = b;
b = c; b = c;
println(String.valueOf(a)); System.out.println(String.valueOf(a));
} }
} }
private static void testClasses() { private static void testClasses() {
println("A(2) + A(3) = " + (new A(2).getValue() + new A(3).getValue())); System.out.println("A(2) + A(3) = " + (new A(2).getValue() + new A(3).getValue()));
} }
private static void testVirtualCall() { private static void testVirtualCall() {
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
println("instance(" + i + ") = " + instance(i).foo()); System.out.println("instance(" + i + ") = " + instance(i).foo());
} }
Base[] array = { new Derived1(), new Derived2() }; Base[] array = { new Derived1(), new Derived2() };
println("array.length = " + array.length); System.out.println("array.length = " + array.length);
for (Base elem : array) { for (Base elem : array) {
println("array[i] = " + elem.foo()); System.out.println("array[i] = " + elem.foo());
} }
} }
private static void testInstanceOf() { private static void testInstanceOf() {
println("Derived2 instanceof Base = " + (new Derived2() instanceof Base)); System.out.println("Derived2 instanceof Base = " + (new Derived2() instanceof Base));
println("Derived3 instanceof Base = " + (new Derived3() instanceof Base)); System.out.println("Derived3 instanceof Base = " + (new Derived3() instanceof Base));
println("Derived2 instanceof Derived1 = " + ((Object) new Derived2() instanceof Derived1)); System.out.println("Derived2 instanceof Derived1 = " + ((Object) new Derived2() instanceof Derived1));
println("Derived2 instanceof A = " + ((Object) new Derived2() instanceof A)); System.out.println("Derived2 instanceof A = " + ((Object) new Derived2() instanceof A));
println("A instanceof Base = " + (new A(23) instanceof Base)); System.out.println("A instanceof Base = " + (new A(23) instanceof Base));
} }
private static void testPrimitiveArray() { private static void testPrimitiveArray() {
byte[] bytes = { 5, 6, 10, 15 }; byte[] bytes = { 5, 6, 10, 15 };
for (byte bt : bytes) { for (byte bt : bytes) {
println("bytes[i] = " + bt); System.out.println("bytes[i] = " + bt);
} }
} }
@ -115,10 +116,10 @@ public final class Example {
private static void testHashCode() { private static void testHashCode() {
Object o = new Object(); Object o = new Object();
println("hashCode1 = " + o.hashCode()); System.out.println("hashCode1 = " + o.hashCode());
println("hashCode1 = " + o.hashCode()); System.out.println("hashCode1 = " + o.hashCode());
println("hashCode2 = " + new Object().hashCode()); System.out.println("hashCode2 = " + new Object().hashCode());
println("hashCode3 = " + new Object().hashCode()); System.out.println("hashCode3 = " + new Object().hashCode());
} }
private static void testArrayList() { private static void testArrayList() {
@ -127,7 +128,7 @@ public final class Example {
list.remove((Integer) 444); list.remove((Integer) 444);
for (int item : list) { for (int item : list) {
println("list[i] = " + item); System.out.println("list[i] = " + item);
} }
} }
@ -147,25 +148,31 @@ public final class Example {
for (int i = 0; i < array.length; ++i) { for (int i = 0; i < array.length; ++i) {
sb.append(" ").append(array[i]); sb.append(" ").append(array[i]);
} }
println(sb.toString()); System.out.println(sb.toString());
} }
private static void testArrayIsObject() { private static void testArrayIsObject() {
byte[] array = new byte[] { 1, 2, 3 }; byte[] array = new byte[] { 1, 2, 3 };
byte[] copy = array.clone(); byte[] copy = array.clone();
println("array.hashCode() = " + array.hashCode()); System.out.println("array.hashCode() = " + array.hashCode());
println("copy.hashCode() = " + copy.hashCode()); System.out.println("copy.hashCode() = " + copy.hashCode());
println("array.equals(array) = " + array.equals(array)); System.out.println("array.equals(array) = " + array.equals(array));
println("array.equals(copy) = " + array.equals(copy)); System.out.println("array.equals(copy) = " + array.equals(copy));
} }
private static void testIsAssignableFrom() { private static void testIsAssignableFrom() {
println("Object.isAssignableFrom(byte[]) = " + Object.class.isAssignableFrom(new byte[0].getClass())); System.out.println("Object.isAssignableFrom(byte[]) = "
println("Object[].isAssignableFrom(Integer[]) = " + Object[].class.isAssignableFrom(new Integer[0].getClass())); + Object.class.isAssignableFrom(new byte[0].getClass()));
println("Object[].isAssignableFrom(Integer) = " + Object[].class.isAssignableFrom(Integer.class)); System.out.println("Object[].isAssignableFrom(Integer[]) = "
println("byte[].isAssignableFrom(Object) = " + byte[].class.isAssignableFrom(ValueType.Object.class)); + Object[].class.isAssignableFrom(new Integer[0].getClass()));
println("Base.isAssignableFrom(Derived1) = " + Base.class.isAssignableFrom(Derived1.class)); System.out.println("Object[].isAssignableFrom(Integer) = "
println("Base.isAssignableFrom(A) = " + Base.class.isAssignableFrom(A.class)); + Object[].class.isAssignableFrom(Integer.class));
System.out.println("byte[].isAssignableFrom(Object) = "
+ byte[].class.isAssignableFrom(ValueType.Object.class));
System.out.println("Base.isAssignableFrom(Derived1) = "
+ Base.class.isAssignableFrom(Derived1.class));
System.out.println("Base.isAssignableFrom(A) = "
+ Base.class.isAssignableFrom(A.class));
} }
private static void testGC() { private static void testGC() {
@ -176,7 +183,7 @@ public final class Example {
list = new ArrayList<>(); list = new ArrayList<>();
} }
} }
print("GC complete"); System.out.println("GC complete");
} }
private static Base instance(int index) { private static Base instance(int index) {
@ -234,22 +241,11 @@ public final class Example {
static class Initialized { static class Initialized {
static { static {
println("Initialized.<clinit>()"); System.out.println("Initialized.<clinit>()");
} }
public static void foo() { public static void foo() {
println("Initialized.foo()"); System.out.println("Initialized.foo()");
} }
} }
static void print(String value) {
for (int i = 0; i < value.length(); ++i) {
WasmRuntime.print(value.charAt(i));
}
}
static void println(String value) {
print(value);
WasmRuntime.print('\n');
}
} }

View File

@ -193,11 +193,15 @@ public class WasmClassGenerator {
DataValue header = wrapper.getValue(0); DataValue header = wrapper.getValue(0);
binaryData.data = header; binaryData.data = header;
header.setInt(CLASS_SIZE, binaryData.size); int occupiedSize = binaryData.size;
if ((occupiedSize & 3) != 0) {
occupiedSize = occupiedSize >> 2 << 2 + 1;
}
header.setInt(CLASS_SIZE, occupiedSize);
List<TagRegistry.Range> ranges = tagRegistry.getRanges(name); List<TagRegistry.Range> ranges = tagRegistry.getRanges(name);
int tag = ranges.stream().mapToInt(range -> range.lower).min().orElse(0); int tag = ranges.stream().mapToInt(range -> range.lower).min().orElse(0);
header.setInt(CLASS_TAG, tag); header.setInt(CLASS_TAG, tag);
header.setInt(CLASS_CANARY, RuntimeClass.computeCanary(binaryData.size, tag)); header.setInt(CLASS_CANARY, RuntimeClass.computeCanary(occupiedSize, tag));
header.setInt(CLASS_IS_INSTANCE, functionTable.size()); header.setInt(CLASS_IS_INSTANCE, functionTable.size());
functionTable.add(WasmMangling.mangeIsSupertype(ValueType.object(name))); functionTable.add(WasmMangling.mangeIsSupertype(ValueType.object(name)));
header.setAddress(CLASS_PARENT, parentPtr); header.setAddress(CLASS_PARENT, parentPtr);

View File

@ -1194,6 +1194,14 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
@Override @Override
public void visit(TryCatchStatement statement) { public void visit(TryCatchStatement statement) {
WasmBlock block = new WasmBlock(false);
for (Statement bodyPart : statement.getProtectedBody()) {
accept(bodyPart);
if (result != null) {
block.getBody().add(result);
}
}
result = block;
} }
@Override @Override

View File

@ -22,6 +22,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import org.teavm.model.ClassReader; import org.teavm.model.ClassReader;
import org.teavm.model.ClassReaderSource; import org.teavm.model.ClassReaderSource;
import org.teavm.model.ElementModifier;
import org.teavm.model.ListableClassReaderSource; import org.teavm.model.ListableClassReaderSource;
import org.teavm.model.MethodDescriptor; import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReader; import org.teavm.model.MethodReader;
@ -73,6 +74,9 @@ public class VirtualTableProvider {
} }
for (MethodReader method : cls.getMethods()) { for (MethodReader method : cls.getMethods()) {
if (method.hasModifier(ElementModifier.ABSTRACT)) {
continue;
}
VirtualTableEntry entry = table.entries.get(method.getDescriptor()); VirtualTableEntry entry = table.entries.get(method.getDescriptor());
if (entry != null) { if (entry != null) {
entry.implementor = method.getReference(); entry.implementor = method.getReference();