diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClassNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ClassNativeGenerator.java similarity index 95% rename from teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClassNativeGenerator.java rename to teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ClassNativeGenerator.java index 5f9b27d0f..e1efe680a 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClassNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ClassNativeGenerator.java @@ -9,7 +9,7 @@ import org.teavm.model.MethodReference; * * @author Alexey Andreev */ -public class TClassNativeGenerator implements Generator { +public class ClassNativeGenerator implements Generator { @Override public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) { switch (methodRef.getClassName()) { diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObjectNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ObjectNativeGenerator.java similarity index 92% rename from teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObjectNativeGenerator.java rename to teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ObjectNativeGenerator.java index 94ee4d10e..1a64dc0d9 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObjectNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ObjectNativeGenerator.java @@ -11,7 +11,7 @@ import org.teavm.model.ValueType; * * @author Alexey Andreev */ -public class TObjectNativeGenerator implements Generator { +public class ObjectNativeGenerator implements Generator { @Override public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) { switch (methodRef.getDescriptor().getName()) { @@ -44,7 +44,8 @@ public class TObjectNativeGenerator implements Generator { writer.append("if (cls === undefined) {").newLine().indent(); MethodReference createMethodRef = new MethodReference(classClass, new MethodDescriptor("createNew", ValueType.object(classClass))); - writer.append("cls = ").appendClass(classClass).appendMethod(createMethodRef).append("();").newLine(); + writer.append("cls = ").appendClass(classClass).append('.').appendMethod(createMethodRef) + .append("();").newLine(); writer.append("cls.$data = ").append(thisArg).append(".$class;").newLine().outdent().append("}").newLine(); writer.append("return cls;").newLine(); } @@ -59,7 +60,7 @@ public class TObjectNativeGenerator implements Generator { } private void generateClone(GeneratorContext context, SourceWriter writer) { - writer.append("var copy = new ").append(context.getParameterName(0)).append("obj.$class();").newLine(); + writer.append("var copy = new ").append(context.getParameterName(0)).append(".$class();").newLine(); writer.append("for (var field in obj) {").newLine().indent(); writer.append("if (!obj.hasOwnProperty(field)) {").newLine().indent(); writer.append("continue;").newLine().outdent().append("}").newLine(); diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java index 00c01edfa..6ec3d458c 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java @@ -7,6 +7,10 @@ import org.teavm.javascript.ni.GeneratedBy; * @author Alexey Andreev */ public class TClass extends TObject { - @GeneratedBy(TClassNativeGenerator.class) + static TClass createNew() { + return new TClass<>(); + } + + @GeneratedBy(ClassNativeGenerator.class) public native boolean isInstance(TObject obj); } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java index 3e93fc065..17a7c068b 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java @@ -12,22 +12,22 @@ public class TObject { init(); } - @GeneratedBy(TObjectNativeGenerator.class) + @GeneratedBy(ObjectNativeGenerator.class) private native void init(); - @GeneratedBy(TObjectNativeGenerator.class) + @GeneratedBy(ObjectNativeGenerator.class) @Rename("getClass") public native final TClass getClass0(); @Override - @GeneratedBy(TObjectNativeGenerator.class) + @GeneratedBy(ObjectNativeGenerator.class) public native int hashCode(); - @GeneratedBy(TObjectNativeGenerator.class) + @GeneratedBy(ObjectNativeGenerator.class) public native boolean equals(TObject other); @Override - @GeneratedBy(TObjectNativeGenerator.class) + @GeneratedBy(ObjectNativeGenerator.class) protected native TObject clone(); @Rename("notify") diff --git a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java index 1bd8fd3b5..0c45b38d4 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -401,31 +401,31 @@ public class Renderer implements ExprVisitor, StatementVisitor { visitBinary(expr, "+"); break; case ADD_LONG: - visitBinaryFunction(expr, "Long.add"); + visitBinaryFunction(expr, "Long_add"); break; case SUBTRACT: visitBinary(expr, "-"); break; case SUBTRACT_LONG: - visitBinaryFunction(expr, "Long.sub"); + visitBinaryFunction(expr, "Long_sub"); break; case MULTIPLY: visitBinary(expr, "*"); break; case MULTIPLY_LONG: - visitBinaryFunction(expr, "Long.mul"); + visitBinaryFunction(expr, "Long_mul"); break; case DIVIDE: visitBinary(expr, "/"); break; case DIVIDE_LONG: - visitBinaryFunction(expr, "Long.div"); + visitBinaryFunction(expr, "Long_div"); break; case MODULO: visitBinary(expr, "%"); break; case MODULO_LONG: - visitBinaryFunction(expr, "Long.rem"); + visitBinaryFunction(expr, "Long_rem"); break; case EQUALS: visitBinary(expr, "=="); @@ -452,10 +452,10 @@ public class Renderer implements ExprVisitor, StatementVisitor { visitBinary(expr, "!=="); break; case COMPARE: - visitBinaryFunction(expr, "$rt.compare"); + visitBinaryFunction(expr, "$rt_compare"); break; case COMPARE_LONG: - visitBinaryFunction(expr, "Long.compare"); + visitBinaryFunction(expr, "Long_compare"); break; case OR: visitBinary(expr, "||"); @@ -467,37 +467,37 @@ public class Renderer implements ExprVisitor, StatementVisitor { visitBinary(expr, "|"); break; case BITWISE_OR_LONG: - visitBinaryFunction(expr, "Long.or"); + visitBinaryFunction(expr, "Long_or"); break; case BITWISE_AND: visitBinary(expr, "&"); break; case BITWISE_AND_LONG: - visitBinaryFunction(expr, "Long.and"); + visitBinaryFunction(expr, "Long_and"); break; case BITWISE_XOR: visitBinary(expr, "^"); break; case BITWISE_XOR_LONG: - visitBinaryFunction(expr, "Long.xor"); + visitBinaryFunction(expr, "Long_xor"); break; case LEFT_SHIFT: visitBinary(expr, "<<"); break; case LEFT_SHIFT_LONG: - visitBinaryFunction(expr, "Long.lsh"); + visitBinaryFunction(expr, "Long_lsh"); break; case RIGHT_SHIFT: visitBinary(expr, ">>"); break; case RIGHT_SHIFT_LONG: - visitBinaryFunction(expr, "Long.rsh"); + visitBinaryFunction(expr, "Long_rsh"); break; case UNSIGNED_RIGHT_SHIFT: visitBinary(expr, ">>>"); break; case UNSIGNED_RIGHT_SHIFT_LONG: - visitBinaryFunction(expr, "Long.rshu"); + visitBinaryFunction(expr, "Long_rshu"); break; } } @@ -520,27 +520,27 @@ public class Renderer implements ExprVisitor, StatementVisitor { writer.append(".length"); break; case INT_TO_LONG: - writer.append("Long.fromInt("); + writer.append("Long_fromInt("); expr.getOperand().acceptVisitor(this); writer.append(')'); break; case NUM_TO_LONG: - writer.append("Long.fromNumber("); + writer.append("Long_fromNumber("); expr.getOperand().acceptVisitor(this); writer.append(')'); break; case LONG_TO_NUM: - writer.append("Long.toNumber("); + writer.append("Long_toNumber("); expr.getOperand().acceptVisitor(this); writer.append(')'); break; case NEGATE_LONG: - writer.append("Long.neg("); + writer.append("Long_neg("); expr.getOperand().acceptVisitor(this); writer.append(')'); break; case NOT_LONG: - writer.append("Long.not("); + writer.append("Long_not("); expr.getOperand().acceptVisitor(this); writer.append(')'); break; @@ -569,15 +569,15 @@ public class Renderer implements ExprVisitor, StatementVisitor { } if (cst instanceof ValueType) { ValueType type = (ValueType)cst; - return "$rt.cls(" + typeToClsString(naming, type) + ")"; + return "$rt_cls(" + typeToClsString(naming, type) + ")"; } else if (cst instanceof String) { - return "$rt.str(\"" + escapeString((String)cst) + "\")"; + return "$rt_str(\"" + escapeString((String)cst) + "\")"; } else if (cst instanceof Long) { long value = (Long)cst; if (value == 0) { - return "Long.ZERO"; + return "Long_ZERO"; } else if ((int)value == value) { - return "Long.fromInt(" + value + ")"; + return "Long_fromInt(" + value + ")"; } else { return "new Long(" + (value & 0xFFFFFFFF) + ", " + (value >>> 32) + ")"; } @@ -597,33 +597,33 @@ public class Renderer implements ExprVisitor, StatementVisitor { ValueType.Object objType = (ValueType.Object)type; value = naming.getNameFor(objType.getClassName()); } else if (type instanceof ValueType.Void) { - value = "$rt.voidcls()"; + value = "$rt_voidcls()"; } else if (type instanceof ValueType.Primitive) { ValueType.Primitive primitiveType = (ValueType.Primitive)type; switch (primitiveType.getKind()) { case BOOLEAN: - value = "$rt.booleancls()"; + value = "$rt_booleancls()"; break; case CHARACTER: - value = "$rt.charcls()"; + value = "$rt_charcls()"; break; case BYTE: - value = "$rt.bytecls()"; + value = "$rt_bytecls()"; break; case SHORT: - value = "$rt.shortcls()"; + value = "$rt_shortcls()"; break; case INTEGER: - value = "$rt.intcls()"; + value = "$rt_intcls()"; break; case LONG: - value = "$rt.longcls()"; + value = "$rt_longcls()"; break; case FLOAT: - value = "$rt.floatcls()"; + value = "$rt_floatcls()"; break; case DOUBLE: - value = "$rt.doublecls()"; + value = "$rt_doublecls()"; break; default: throw new IllegalArgumentException("The type is not renderable"); @@ -633,7 +633,7 @@ public class Renderer implements ExprVisitor, StatementVisitor { } for (int i = 0; i < arrayCount; ++i) { - value = "$rt.arraycls(" + value + ")"; + value = "$rt_arraycls(" + value + ")"; } return value; } @@ -755,48 +755,48 @@ public class Renderer implements ExprVisitor, StatementVisitor { if (type instanceof ValueType.Primitive) { switch (((ValueType.Primitive)type).getKind()) { case BOOLEAN: - writer.append("$rt.createBooleanArray($rt.booleancls(), "); + writer.append("$rt_createBooleanArray($rt_booleancls(), "); expr.getLength().acceptVisitor(this); writer.append(")"); break; case BYTE: - writer.append("$rt.createNumericArray($rt.bytecls(), "); + writer.append("$rt_createNumericArray($rt_bytecls(), "); expr.getLength().acceptVisitor(this); writer.append(")"); break; case SHORT: - writer.append("$rt.createNumericArray($rt.shortcls(), "); + writer.append("$rt_createNumericArray($rt_shortcls(), "); expr.getLength().acceptVisitor(this); writer.append(")"); break; case INTEGER: - writer.append("$rt.createNumericArray($rt.intcls(), "); + writer.append("$rt_createNumericArray($rt_intcls(), "); expr.getLength().acceptVisitor(this); writer.append(")"); break; case LONG: - writer.append("$rt.createLongArray("); + writer.append("$rt_createLongArray("); expr.getLength().acceptVisitor(this); writer.append(")"); break; case FLOAT: - writer.append("$rt.createNumericArray($rt.floatcls(), "); + writer.append("$rt_createNumericArray($rt_floatcls(), "); expr.getLength().acceptVisitor(this); writer.append(")"); break; case DOUBLE: - writer.append("$rt.createNumericArray($rt.doublecls(), "); + writer.append("$rt_createNumericArray($rt_doublecls(), "); expr.getLength().acceptVisitor(this); writer.append(")"); break; case CHARACTER: - writer.append("$rt.createNumericArray($rt.charcls(), "); + writer.append("$rt_createNumericArray($rt_charcls(), "); expr.getLength().acceptVisitor(this); writer.append(")"); break; } } else { - writer.append("$rt.createArray(").append(typeToClsString(naming, expr.getType())).append(", "); + writer.append("$rt_createArray(").append(typeToClsString(naming, expr.getType())).append(", "); expr.getLength().acceptVisitor(this); writer.append(")"); } @@ -804,7 +804,7 @@ public class Renderer implements ExprVisitor, StatementVisitor { @Override public void visit(NewMultiArrayExpr expr) { - writer.append("$rt.createMultiArray(").append(typeToClsString(naming, expr.getType())) + writer.append("$rt_createMultiArray(").append(typeToClsString(naming, expr.getType())) .append(", ["); boolean first = true; for (Expr dimension : expr.getDimensions()) { @@ -829,7 +829,7 @@ public class Renderer implements ExprVisitor, StatementVisitor { return; } } - writer.append("$rt.isInstance("); + writer.append("$rt_isInstance("); expr.getExpr().acceptVisitor(this); writer.append(", ").append(typeToClsString(naming, expr.getType())).append(")"); } diff --git a/teavm-core/src/main/java/org/teavm/model/resource/ClassRefsRenamer.java b/teavm-core/src/main/java/org/teavm/model/resource/ClassRefsRenamer.java index 1c78c19ee..685ea2afa 100644 --- a/teavm-core/src/main/java/org/teavm/model/resource/ClassRefsRenamer.java +++ b/teavm-core/src/main/java/org/teavm/model/resource/ClassRefsRenamer.java @@ -21,7 +21,7 @@ class ClassRefsRenamer implements InstructionVisitor { ClassHolder renamedCls = new ClassHolder(classNameMapper.map(cls.getName())); renamedCls.getModifiers().addAll(cls.getModifiers()); renamedCls.setLevel(cls.getLevel()); - if (cls != null) { + if (cls.getParent() != null) { renamedCls.setParent(classNameMapper.map(cls.getParent())); } for (MethodHolder method : cls.getMethods()) { @@ -79,7 +79,7 @@ class ClassRefsRenamer implements InstructionVisitor { private AnnotationHolder rename(AnnotationHolder annot) { AnnotationHolder renamedAnnot = new AnnotationHolder(classNameMapper.map(annot.getType())); - for (Map.Entry entry : renamedAnnot.getValues().entrySet()) { + for (Map.Entry entry : annot.getValues().entrySet()) { renamedAnnot.getValues().put(entry.getKey(), entry.getValue()); } return renamedAnnot; @@ -216,6 +216,11 @@ class ClassRefsRenamer implements InstructionVisitor { @Override public void visit(InvokeInstruction insn) { insn.setClassName(classNameMapper.map(insn.getClassName())); + ValueType[] signature = insn.getMethod().getSignature(); + for (int i = 0; i < signature.length; ++i) { + signature[i] = rename(signature[i]); + } + insn.setMethod(new MethodDescriptor(insn.getMethod().getName(), signature)); } @Override diff --git a/teavm-core/src/main/java/org/teavm/model/resource/ClasspathResourceMapper.java b/teavm-core/src/main/java/org/teavm/model/resource/ClasspathResourceMapper.java index a97a19dff..29f3bd4f3 100644 --- a/teavm-core/src/main/java/org/teavm/model/resource/ClasspathResourceMapper.java +++ b/teavm-core/src/main/java/org/teavm/model/resource/ClasspathResourceMapper.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.*; +import org.teavm.codegen.ConcurrentCachedMapper; import org.teavm.codegen.Mapper; import org.teavm.model.ClassHolder; @@ -16,6 +17,7 @@ public class ClasspathResourceMapper implements Mapper { private static String CLASS_PREFIX = "classPrefix."; private Mapper innerMapper; private List transformations = new ArrayList<>(); + private ClassRefsRenamer renamer; private static class Transformation { String packageName; @@ -41,6 +43,7 @@ public class ClasspathResourceMapper implements Mapper { } catch (IOException e) { throw new RuntimeException("Error reading resources", e); } + renamer = new ClassRefsRenamer(new ConcurrentCachedMapper<>(classNameMapper)); } private void loadProperties(Properties properties, Map cache) { @@ -78,24 +81,31 @@ public class ClasspathResourceMapper implements Mapper { String packageName = name.substring(0, index); ClassHolder classHolder = innerMapper.map(transformation.packagePrefix + "." + packageName + "." + transformation.classPrefix + className); - return classHolder; + return renamer.rename(classHolder); } } return innerMapper.map(name); } - String renameClass(String name) { + private String renameClass(String name) { for (Transformation transformation : transformations) { if (name.startsWith(transformation.fullPrefix)) { int index = name.lastIndexOf('.'); String className = name.substring(index + 1); String packageName = name.substring(0, index); if (className.startsWith(transformation.classPrefix)) { - return packageName.substring(transformation.fullPrefix.length()) + "." + + return packageName.substring(transformation.packagePrefix.length()) + "." + className.substring(transformation.classPrefix.length()); } } } return name; } + + private Mapper classNameMapper = new Mapper() { + @Override + public String map(String preimage) { + return renameClass(preimage); + } + }; }