Implements some of JVM class library

This commit is contained in:
Alexey Andreev 2013-11-27 10:11:21 +04:00
parent 1355e211e3
commit c244c596c9
8 changed files with 123 additions and 15 deletions

View File

@ -2,24 +2,25 @@ package org.teavm.classlib.java.lang;
import org.teavm.classlib.java.lang.io.TSerializable; import org.teavm.classlib.java.lang.io.TSerializable;
import org.teavm.classlib.java.util.TArrays; import org.teavm.classlib.java.util.TArrays;
import org.teavm.javascript.ni.Rename;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
class AbstractStringBuilder extends TObject implements TSerializable { class TAbstractStringBuilder extends TObject implements TSerializable {
private char[] buffer; private char[] buffer;
private int length; private int length;
public AbstractStringBuilder() { public TAbstractStringBuilder() {
this(16); this(16);
} }
public AbstractStringBuilder(int capacity) { public TAbstractStringBuilder(int capacity) {
buffer = new char[capacity]; buffer = new char[capacity];
} }
protected AbstractStringBuilder append(TString string) { protected TAbstractStringBuilder append(TString string) {
ensureCapacity(length + string.length()); ensureCapacity(length + string.length());
int j = length; int j = length;
for (int i = 0; i < string.length(); ++i) { for (int i = 0; i < string.length(); ++i) {
@ -29,13 +30,20 @@ class AbstractStringBuilder extends TObject implements TSerializable {
return this; return this;
} }
protected AbstractStringBuilder append(int value) { protected TAbstractStringBuilder append(int value) {
boolean positive = true;
if (value < 0) { if (value < 0) {
append('-'); positive = false;
value = -value; value = -value;
} }
if (value < 10) { if (value < 10) {
append((char)('0' + value)); if (!positive) {
ensureCapacity(length + 2);
buffer[length++] = '-';
} else {
ensureCapacity(length + 1);
}
buffer[length++] = (char)('0' + value);
} else { } else {
int pos = 10; int pos = 10;
int sz = 1; int sz = 1;
@ -43,7 +51,14 @@ class AbstractStringBuilder extends TObject implements TSerializable {
pos *= 10; pos *= 10;
++sz; ++sz;
} }
if (!positive) {
++sz;
}
ensureCapacity(length + sz); ensureCapacity(length + sz);
if (!positive) {
buffer[length++] = '-';
}
pos /= 10;
while (pos > 0) { while (pos > 0) {
buffer[length++] = (char)('0' + value / pos); buffer[length++] = (char)('0' + value / pos);
value %= pos; value %= pos;
@ -53,7 +68,7 @@ class AbstractStringBuilder extends TObject implements TSerializable {
return this; return this;
} }
protected AbstractStringBuilder append(char c) { protected TAbstractStringBuilder append(char c) {
ensureCapacity(length + 1); ensureCapacity(length + 1);
buffer[length++] = c; buffer[length++] = c;
return this; return this;
@ -65,4 +80,10 @@ class AbstractStringBuilder extends TObject implements TSerializable {
} }
buffer = TArrays.copyOf(buffer, capacity * 2 + 1); buffer = TArrays.copyOf(buffer, capacity * 2 + 1);
} }
@Override
@Rename("toString")
public TString toString0() {
return new TString(buffer, 0, length);
}
} }

View File

@ -0,0 +1,14 @@
package org.teavm.classlib.java.lang;
/**
*
* @author Alexey Andreev
*/
public final class TMath extends TObject {
private TMath() {
}
public static int min(int a, int b) {
return a < b ? a : b;
}
}

View File

@ -9,6 +9,7 @@ import org.teavm.javascript.ni.GeneratedBy;
*/ */
public class TString extends TObject implements TSerializable { public class TString extends TObject implements TSerializable {
private char[] characters; private char[] characters;
private transient int hashCode;
public TString() { public TString() {
this.characters = new char[0]; this.characters = new char[0];
@ -47,6 +48,41 @@ public class TString extends TObject implements TSerializable {
return new TStringBuilder().append(index).toString0(); return new TStringBuilder().append(index).toString0();
} }
@Override
public boolean equals(TObject other) {
if (this == other) {
return true;
}
if (!(other instanceof TString)) {
return false;
}
TString str = (TString)other;
if (str.length() != length()) {
return false;
}
for (int i = 0; i < str.length(); ++i) {
if (charAt(i) != str.charAt(i)) {
return false;
}
}
return true;
}
@Override
public int hashCode() {
if (hashCode == 0) {
hashCode ^= 734262231;
for (char c : characters) {
hashCode = (hashCode << 4) | (hashCode >>> 28);
hashCode ^= 347236277 ^ c;
if (hashCode == 0) {
++hashCode;
}
}
}
return hashCode;
}
@GeneratedBy(StringNativeGenerator.class) @GeneratedBy(StringNativeGenerator.class)
public static native TString wrap(String str); public static native TString wrap(String str);
} }

View File

@ -4,7 +4,7 @@ package org.teavm.classlib.java.lang;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public class TStringBuilder extends AbstractStringBuilder { public class TStringBuilder extends TAbstractStringBuilder {
@Override @Override
public TStringBuilder append(TString string) { public TStringBuilder append(TString string) {
super.append(string); super.append(string);

View File

@ -0,0 +1,17 @@
package org.teavm.classlib.java.lang;
import static org.junit.Assert.*;
import org.junit.Test;
/**
*
* @author Alexey Andreev
*/
class TStringBuilderTests {
@Test
public void integerAppended() {
TStringBuilder sb = new TStringBuilder();
sb.append(23);
assertEquals("23", sb.toString());
}
}

View File

@ -30,7 +30,8 @@ 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", "java.lang.SystemTests" }; private static String[] testClasses = { "java.lang.ObjectTests", "java.lang.SystemTests",
"java.lang.StringBuilderTests" };
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
out = System.out; out = System.out;

View File

@ -159,10 +159,20 @@ public class DependencyChecker {
} }
} }
private MethodGraph createMethodGraph(MethodReference methodRef) { private MethodGraph createMethodGraph(final MethodReference methodRef) {
initClass(methodRef.getClassName()); initClass(methodRef.getClassName());
ClassHolder cls = classSource.getClassHolder(methodRef.getClassName()); ClassHolder cls = classSource.getClassHolder(methodRef.getClassName());
MethodHolder method = cls.getMethod(methodRef.getDescriptor()); MethodHolder method = cls.getMethod(methodRef.getDescriptor());
if (method == null) {
while (cls != null) {
method = cls.getMethod(methodRef.getDescriptor());
if (method != null) {
return methodCache.map(new MethodReference(cls.getName(), methodRef.getDescriptor()));
}
cls = classSource.getClassHolder(cls.getParent());
}
throw new RuntimeException("Method not found: " + methodRef);
}
ValueType[] arguments = method.getParameterTypes(); ValueType[] arguments = method.getParameterTypes();
int paramCount = arguments.length + 1; int paramCount = arguments.length + 1;
int varCount = Math.max(paramCount, method.getProgram().variableCount()); int varCount = Math.max(paramCount, method.getProgram().variableCount());
@ -184,10 +194,15 @@ public class DependencyChecker {
method.getName() + MethodDescriptor.get(method) + ":RESULT"); method.getName() + MethodDescriptor.get(method) + ":RESULT");
} }
} }
MethodGraph graph = new MethodGraph(parameterNodes, paramCount, resultNode, this); final MethodGraph graph = new MethodGraph(parameterNodes, paramCount, resultNode, this);
DependencyGraphBuilder graphBuilder = new DependencyGraphBuilder(this); final MethodHolder currentMethod = method;
graphBuilder.buildGraph(method, graph); executor.submit(new Runnable() {
@Override public void run() {
DependencyGraphBuilder graphBuilder = new DependencyGraphBuilder(DependencyChecker.this);
graphBuilder.buildGraph(currentMethod, graph);
achieveClass(methodRef.getClassName()); achieveClass(methodRef.getClassName());
}
});
return graph; return graph;
} }
@ -223,6 +238,9 @@ public class DependencyChecker {
private void activateDependencyPlugin(MethodReference methodRef) { private void activateDependencyPlugin(MethodReference methodRef) {
ClassHolder cls = classSource.getClassHolder(methodRef.getClassName()); ClassHolder cls = classSource.getClassHolder(methodRef.getClassName());
MethodHolder method = cls.getMethod(methodRef.getDescriptor()); MethodHolder method = cls.getMethod(methodRef.getDescriptor());
if (method == null) {
return;
}
AnnotationHolder depAnnot = method.getAnnotations().get(PluggableDependency.class.getName()); AnnotationHolder depAnnot = method.getAnnotations().get(PluggableDependency.class.getName());
if (depAnnot == null) { if (depAnnot == null) {
return; return;

View File

@ -98,5 +98,6 @@ public class ClassHolder extends ElementHolder {
field.getName() + " is not a member of " + getName()); field.getName() + " is not a member of " + getName());
} }
fields.remove(field.getName()); fields.remove(field.getName());
field.setOwner(null);
} }
} }