Adds some JVM classes.

This commit is contained in:
Alexey Andreev 2013-11-22 17:19:51 +04:00
parent 04e12562a0
commit 18e35b80e6
15 changed files with 253 additions and 55 deletions

View File

@ -0,0 +1,25 @@
package org.teavm.classlib.java.lang;
import org.teavm.codegen.SourceWriter;
import org.teavm.javascript.ni.Generator;
import org.teavm.javascript.ni.GeneratorContext;
import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public class StringNativeGenerator implements Generator {
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
switch (methodRef.getName()) {
case "wrap":
generateWrap(context, writer);
break;
}
}
private void generateWrap(GeneratorContext context, SourceWriter writer) {
writer.append("return ").append(context.getParameterName(1)).newLine();
}
}

View File

@ -0,0 +1,52 @@
package org.teavm.classlib.java.lang;
import org.teavm.codegen.SourceWriter;
import org.teavm.dependency.DependencyChecker;
import org.teavm.dependency.DependencyNode;
import org.teavm.dependency.DependencyPlugin;
import org.teavm.dependency.MethodGraph;
import org.teavm.javascript.ni.Generator;
import org.teavm.javascript.ni.GeneratorContext;
import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
public class SystemNativeGenerator implements Generator, DependencyPlugin {
@Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) {
switch (methodRef.getName()) {
case "doArrayCopy":
generateArrayCopy(context, writer);
break;
}
}
@Override
public void methodAchieved(DependencyChecker checker, MethodReference method) {
switch (method.getName()) {
case "doArrayCopy":
achieveArrayCopy(checker, method);
break;
}
}
private void generateArrayCopy(GeneratorContext context, SourceWriter writer) {
String src = context.getParameterName(1);
String srcPos = context.getParameterName(2);
String dest = context.getParameterName(3);
String destPos = context.getParameterName(4);
String length = context.getParameterName(5);
writer.append("for (var i = 0; i < " + length + "; i = (i + 1) | 0) {").indent().newLine();
writer.append(dest + "[" + srcPos + "++] = " + src + "[" + destPos + "++];").newLine();
writer.outdent().append("}").newLine();
}
private void achieveArrayCopy(DependencyChecker checker, MethodReference method) {
MethodGraph graph = checker.attachMethodGraph(method);
DependencyNode src = graph.getVariableNode(1);
DependencyNode dest = graph.getVariableNode(3);
src.getArrayItemNode().connect(dest.getArrayItemNode());
}
}

View File

@ -0,0 +1,9 @@
package org.teavm.classlib.java.lang;
/**
*
* @author Alexey Andreev
*/
public class TException extends TThrowable {
private static final long serialVersionUID = -2188339106250208952L;
}

View File

@ -31,6 +31,9 @@ public class TObject {
@GeneratedBy(ObjectNativeGenerator.class) @GeneratedBy(ObjectNativeGenerator.class)
public native boolean equals(TObject other); public native boolean equals(TObject other);
@Rename("toString")
public native TString toString0();
@Override @Override
@GeneratedBy(ObjectNativeGenerator.class) @GeneratedBy(ObjectNativeGenerator.class)
@PluggableDependency(ObjectNativeGenerator.class) @PluggableDependency(ObjectNativeGenerator.class)

View File

@ -45,4 +45,9 @@ class TObjectTests {
public void properInstanceDetected() { public void properInstanceDetected() {
assertTrue(Object.class.isInstance(new Object())); assertTrue(Object.class.isInstance(new Object()));
} }
@Test
public void alwaysFails() {
fail();
}
} }

View File

@ -1,9 +1,36 @@
package org.teavm.classlib.java.lang; package org.teavm.classlib.java.lang;
import org.teavm.javascript.ni.GeneratedBy;
/** /**
* *
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
public class TString { public class TString extends TObject {
private char[] characters;
public TString() {
this.characters = new char[0];
}
public TString(TString other) {
characters = other.characters;
}
public TString(char[] characters) {
this.characters = new char[characters.length];
for (int i = 0; i < characters.length; ++i) {
this.characters[i] = characters[i];
}
}
public TString(char[] value, int offset, int count) {
this.characters = new char[count];
for (int i = 0; i < count; ++i) {
this.characters[i] = value[i + offset];
}
}
@GeneratedBy(StringNativeGenerator.class)
public static native TString wrap(String str);
} }

View File

@ -0,0 +1,19 @@
package org.teavm.classlib.java.lang;
import org.teavm.javascript.ni.GeneratedBy;
/**
*
* @author Alexey Andreev
*/
public final class TSystem extends TObject {
private TSystem() {
}
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) {
doArrayCopy(src, srcPos, dest, destPos, length);
}
@GeneratedBy(SystemNativeGenerator.class)
private static native void doArrayCopy(Object src, int srcPos, Object dest, int destPos, int length);
}

View File

@ -0,0 +1,22 @@
package org.teavm.classlib.java.lang;
import static org.junit.Assert.*;
import org.junit.Test;
/**
*
* @author Alexey Andreev
*/
class TSystemTests {
@Test
public void copiesArray() {
TObject a = new TObject();
TObject b = new TObject();
TObject[] src = { a, b, a };
TObject[] dest = new TObject[3];
TSystem.arraycopy(src, 0, dest, 0, 3);
assertSame(a, dest[0]);
assertSame(b, dest[1]);
assertSame(a, dest[2]);
}
}

View File

@ -6,4 +6,6 @@ package org.teavm.classlib.java.lang;
*/ */
public class TThrowable extends Throwable { public class TThrowable extends Throwable {
private static final long serialVersionUID = 2026791432677149320L; private static final long serialVersionUID = 2026791432677149320L;
private TString message;
private TThrowable cause;
} }

View File

@ -1,7 +1,9 @@
package org.teavm.classlibgen; package org.teavm.classlibgen;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.PrintStream;
import java.util.*; import java.util.*;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.teavm.codegen.DefaultAliasProvider; import org.teavm.codegen.DefaultAliasProvider;
@ -19,6 +21,7 @@ import org.teavm.model.resource.ClasspathClassHolderSource;
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
public class ClasslibTestGenerator { public class ClasslibTestGenerator {
private static PrintStream out;
private static ClasspathClassHolderSource classSource; private static ClasspathClassHolderSource classSource;
private static Decompiler decompiler; private static Decompiler decompiler;
private static DefaultAliasProvider aliasProvider; private static DefaultAliasProvider aliasProvider;
@ -27,9 +30,13 @@ public class ClasslibTestGenerator {
private static Renderer renderer; private static Renderer renderer;
private static List<MethodReference> testMethods = new ArrayList<>(); private static List<MethodReference> testMethods = new ArrayList<>();
private static Map<String, List<MethodReference>> groupedMethods = new HashMap<>(); private static Map<String, List<MethodReference>> groupedMethods = new HashMap<>();
private static String[] testClasses = { "java.lang.ObjectTests" }; private static String[] testClasses = { "java.lang.ObjectTests", "java.lang.SystemTests" };
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
out = System.out;
if (args.length > 0) {
out = new PrintStream(new FileOutputStream(args[0]));
}
classSource = new ClasspathClassHolderSource(); classSource = new ClasspathClassHolderSource();
decompiler = new Decompiler(classSource); decompiler = new Decompiler(classSource);
aliasProvider = new DefaultAliasProvider(); aliasProvider = new DefaultAliasProvider();
@ -52,15 +59,16 @@ public class ClasslibTestGenerator {
renderHead(); renderHead();
ClassLoader classLoader = ClasslibTestGenerator.class.getClassLoader(); ClassLoader classLoader = ClasslibTestGenerator.class.getClassLoader();
try (InputStream input = classLoader.getResourceAsStream("org/teavm/classlib/junit-support.js")) { try (InputStream input = classLoader.getResourceAsStream("org/teavm/classlib/junit-support.js")) {
System.out.println(IOUtils.toString(input)); out.println(IOUtils.toString(input));
} }
try (InputStream input = classLoader.getResourceAsStream("org/teavm/javascript/runtime.js")) { try (InputStream input = classLoader.getResourceAsStream("org/teavm/javascript/runtime.js")) {
System.out.println(IOUtils.toString(input)); out.println(IOUtils.toString(input));
} }
renderer.renderRuntime();
for (String testClass : testClasses) { for (String testClass : testClasses) {
renderClassTest(classSource.getClassHolder(testClass)); renderClassTest(classSource.getClassHolder(testClass));
} }
System.out.println(writer); out.println(writer);
renderFoot(); renderFoot();
} }
@ -72,21 +80,21 @@ public class ClasslibTestGenerator {
} }
private static void renderHead() { private static void renderHead() {
System.out.println("<!DOCTYPE html>"); out.println("<!DOCTYPE html>");
System.out.println("<html>"); out.println("<html>");
System.out.println(" <head>"); out.println(" <head>");
System.out.println(" <title>TeaVM JUnit tests</title>"); out.println(" <title>TeaVM JUnit tests</title>");
System.out.println(" <meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\"/>"); out.println(" <meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\"/>");
System.out.println(" <title>TeaVM JUnit tests</title>"); out.println(" <title>TeaVM JUnit tests</title>");
System.out.println(" </head>"); out.println(" </head>");
System.out.println(" <body>"); out.println(" <body>");
System.out.println(" <script type=\"text/javascript\">"); out.println(" <script type=\"text/javascript\">");
} }
private static void renderFoot() { private static void renderFoot() {
System.out.println(" </script>"); out.println(" </script>");
System.out.println(" </body>"); out.println(" </body>");
System.out.println("</html>"); out.println("</html>");
} }
private static void renderClassTest(ClassHolder cls) { private static void renderClassTest(ClassHolder cls) {

View File

@ -19,10 +19,14 @@ runTestCase = function(instance, methodName, realMethodName) {
} catch (e) { } catch (e) {
if (e instanceof JUnitAssertionFailure) { if (e instanceof JUnitAssertionFailure) {
statusCell.appendChild(document.createTextNode("assertion failed")); statusCell.appendChild(document.createTextNode("assertion failed"));
exceptionCell.appendChild(document.createTextNode(e.stack)); var exceptionText = document.createElement("pre");
exceptionText.appendChild(document.createTextNode(e.stack));
exceptionCell.appendChild(exceptionText);
} else { } else {
statusCell.appendChild(document.createTextNode("unexpected exception")); statusCell.appendChild(document.createTextNode("unexpected exception"));
exceptionCell.appendChild(document.createTextNode(e.stack)); var exceptionText = document.createElement("pre");
exceptionText.appendChild(document.createTextNode(e.stack));
exceptionCell.appendChild(exceptionText);
} }
} }
} }

View File

@ -40,15 +40,17 @@ public class ConcurrentCachedMapper<T, R> implements Mapper<T, R> {
listener.keyAdded(preimage); listener.keyAdded(preimage);
} }
} else { } else {
CountDownLatch latch = oldWrapper.latch;
wrapper = oldWrapper; wrapper = oldWrapper;
}
}
CountDownLatch latch = wrapper.latch;
if (latch != null) {
try { try {
latch.await(); latch.await();
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
} }
}
return wrapper.value; return wrapper.value;
} }

View File

@ -76,6 +76,9 @@ public class DependencyNode {
arrayItemNodeLatch.countDown(); arrayItemNodeLatch.countDown();
arrayItemNodeLatch = null; arrayItemNodeLatch = null;
} else { } else {
result = arrayItemNode.get();
}
}
CountDownLatch latch = arrayItemNodeLatch; CountDownLatch latch = arrayItemNodeLatch;
if (latch != null) { if (latch != null) {
try { try {
@ -85,9 +88,6 @@ public class DependencyNode {
return result; return result;
} }
} }
result = arrayItemNode.get();
}
}
return result; return result;
} }

View File

@ -45,6 +45,26 @@ public class Renderer implements ExprVisitor, StatementVisitor {
return naming; return naming;
} }
public void renderRuntime() {
renderRuntimeCls();
}
private void renderRuntimeCls() {
writer.append("$rt_cls = function(cls) {").indent().newLine();
String classClass = "java.lang.Class";
writer.append("var cls = cls.classObject;").newLine();
writer.append("if (cls === undefined) {").newLine().indent();
MethodReference createMethodRef = new MethodReference(classClass, new MethodDescriptor("createNew",
ValueType.object(classClass)));
writer.append("cls = ").appendClass(classClass).append('.').appendMethod(createMethodRef)
.append("();").newLine();
writer.append("cls.$data = cls;").newLine();
writer.append("cls.classObject = cls;").newLine();
writer.outdent().append("}").newLine();
writer.append("return cls;").newLine();
writer.outdent().append("}").newLine();
}
public void render(ClassNode cls) { public void render(ClassNode cls) {
writer.appendClass(cls.getName()).append(" = function() {").indent().newLine(); writer.appendClass(cls.getName()).append(" = function() {").indent().newLine();
for (FieldNode field : cls.getFields()) { for (FieldNode field : cls.getFields()) {

View File

@ -20,6 +20,26 @@ $rt_isAssignable = function(from, to) {
} }
return false; return false;
} }
$rt_createArray = function(cls, sz) {
var arr = new Array(sz);
arr.$class = $rt_arraycls(cls);
arr.$id = $rt_lastObjectId++;
for (var i = 0; i < sz; i = (i + 1) | 0) {
arr[i] = null;
}
return arr;
}
$rt_arraycls = function(cls) {
if (cls.$array == undefined) {
cls.$array = {
$meta : { item : cls },
};
if ($rt.objcls) {
cls.$array.$meta.supertypes = [$rt.objcls()];
}
}
return cls.$array;
}
$rt = { $rt = {
createBooleanArray : function(cls, sz) { createBooleanArray : function(cls, sz) {
@ -43,15 +63,6 @@ $rt = {
} }
return arr; return arr;
}, },
createArray : function(cls, sz) {
var arr = new Array(sz);
arr.$class = $rt.arraycls(cls);
arr.$id = $rt.lastObjectId++;
for (var i = 0; i < sz; i = (i + 1) | 0) {
arr[i] = null;
}
return arr;
},
createMultiArray : function(cls, dimensions) { createMultiArray : function(cls, dimensions) {
for (var i = 1; i < dimensions.length; i = (i + 1) | 0) { for (var i = 1; i < dimensions.length; i = (i + 1) | 0) {
cls = $rt.arraycls(cls); cls = $rt.arraycls(cls);
@ -75,17 +86,6 @@ $rt = {
$rt.setId(arr, $rt.lastObjectId++); $rt.setId(arr, $rt.lastObjectId++);
return arr; return arr;
}, },
arraycls : function(cls) {
if (cls.$array == undefined) {
cls.$array = {
$meta : { item : cls },
};
if ($rt.objcls) {
cls.$array.$meta.supertypes = [$rt.objcls()];
}
}
return cls.$array;
},
createcls : function() { createcls : function() {
return { return {
$meta : { $meta : {