diff --git a/classlib/src/main/java/org/teavm/classlib/java/io/TStreamTokenizer.java b/classlib/src/main/java/org/teavm/classlib/java/io/TStreamTokenizer.java index 1f6326357..efe44a142 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/io/TStreamTokenizer.java +++ b/classlib/src/main/java/org/teavm/classlib/java/io/TStreamTokenizer.java @@ -234,8 +234,7 @@ public class TStreamTokenizer { } } peekChar = currentChar; - sval = forceLowercase ? word.toString().toLowerCase() : word - .toString(); + sval = forceLowercase ? word.toString().toLowerCase() : word.toString(); ttype = TT_WORD; return ttype; } diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TRandom.java b/classlib/src/main/java/org/teavm/classlib/java/util/TRandom.java index dd31f9f90..20adec1d8 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TRandom.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TRandom.java @@ -40,7 +40,11 @@ public class TRandom extends TObject implements TSerializable { } protected int next(int bits) { - return (int) (nextDouble() * (1L << TMath.min(32, bits))); + if (bits == 32) { + return (int) (nextDouble() * ((1L << 32) - 1) + Integer.MIN_VALUE); + } else { + return (int) (nextDouble() * (1L << TMath.min(32, bits))); + } } public void nextBytes(byte[] bytes) { diff --git a/core/src/main/java/org/teavm/backend/wasm/WasmRuntime.java b/core/src/main/java/org/teavm/backend/wasm/WasmRuntime.java index 35838435e..4cdaddb77 100644 --- a/core/src/main/java/org/teavm/backend/wasm/WasmRuntime.java +++ b/core/src/main/java/org/teavm/backend/wasm/WasmRuntime.java @@ -129,6 +129,7 @@ public final class WasmRuntime { public static void moveMemoryBlock(Address source, Address target, int count) { if (count < 8) { slowMemoryMove(source, target, count); + return; } int diff = source.toInt() - target.toInt(); if (diff == 0) { diff --git a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java index 0090179aa..d2f9743af 100644 --- a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java +++ b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java @@ -94,6 +94,7 @@ import org.teavm.model.CallLocation; import org.teavm.model.ClassHolder; import org.teavm.model.ClassHolderTransformer; import org.teavm.model.ClassReader; +import org.teavm.model.ClassReaderSource; import org.teavm.model.ElementModifier; import org.teavm.model.FieldReader; import org.teavm.model.FieldReference; @@ -325,7 +326,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost { context.addIntrinsic(new PlatformClassMetadataIntrinsic()); context.addIntrinsic(new ClassIntrinsic()); - IntrinsicFactoryContext intrinsicFactoryContext = new IntrinsicFactoryContext(classes); + IntrinsicFactoryContext intrinsicFactoryContext = new IntrinsicFactoryContext(); for (WasmIntrinsicFactory additionalIntrinsicFactory : additionalIntrinsics) { context.addIntrinsic(additionalIntrinsicFactory.create(intrinsicFactoryContext)); } @@ -416,15 +417,9 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost { } private class IntrinsicFactoryContext implements WasmIntrinsicFactoryContext { - private ListableClassReaderSource classSource; - - IntrinsicFactoryContext(ListableClassReaderSource classSource) { - this.classSource = classSource; - } - @Override - public ListableClassReaderSource getClassSource() { - return classSource; + public ClassReaderSource getClassSource() { + return controller.getUnprocessedClassSource(); } @Override diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/WasmClassGenerator.java b/core/src/main/java/org/teavm/backend/wasm/generate/WasmClassGenerator.java index 9934a5471..301bfdca8 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/WasmClassGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/WasmClassGenerator.java @@ -175,8 +175,10 @@ public class WasmClassGenerator { binaryData.data.setInt(CLASS_IS_INSTANCE, functionTable.size()); binaryData.data.setInt(CLASS_CANARY, RuntimeClass.computeCanary(4, 0)); functionTable.add(names.forSupertypeFunction(type)); + binaryData.data.setAddress(CLASS_NAME, stringPool.getStringPointer(type.toString())); binaryData.data.setAddress(CLASS_SIMPLE_NAME, 0); binaryData.data.setInt(CLASS_INIT, -1); + binaryData.data.setAddress(CLASS_PARENT, getClassPointer(ValueType.object("java.lang.Object"))); binaryData.start = binaryWriter.append(vtableSize > 0 ? wrapper : binaryData.data); itemBinaryData.data.setAddress(CLASS_ARRAY_TYPE, binaryData.start); @@ -428,7 +430,11 @@ public class WasmClassGenerator { int desiredAlignment = getTypeSize(field.getType()); if (field.hasModifier(ElementModifier.STATIC)) { DataType type = asDataType(field.getType()); - data.fieldLayout.put(field.getName(), binaryWriter.append(type.createValue())); + DataValue value = type.createValue(); + if (field.getInitialValue() != null) { + setInitialValue(field.getType(), value, field.getInitialValue()); + } + data.fieldLayout.put(field.getName(), binaryWriter.append(value)); } else { int offset = align(data.size, desiredAlignment); data.fieldLayout.put(field.getName(), offset); @@ -440,6 +446,41 @@ public class WasmClassGenerator { } } + private void setInitialValue(ValueType type, DataValue data, Object value) { + if (value instanceof Number) { + switch (((ValueType.Primitive) type).getKind()) { + case BYTE: + data.setByte(0, ((Number) value).byteValue()); + break; + case SHORT: + data.setShort(0, ((Number) value).shortValue()); + break; + case CHARACTER: + data.setShort(0, ((Number) value).shortValue()); + break; + case INTEGER: + data.setInt(0, ((Number) value).intValue()); + break; + case LONG: + data.setLong(0, ((Number) value).longValue()); + break; + case FLOAT: + data.setFloat(0, ((Number) value).floatValue()); + break; + case DOUBLE: + data.setDouble(0, ((Number) value).doubleValue()); + break; + case BOOLEAN: + data.setByte(0, ((Number) value).byteValue()); + break; + } + } else if (value instanceof Boolean) { + data.setByte(0, (Boolean) value ? (byte) 1 : 0); + } else if (value instanceof String) { + data.setAddress(0, stringPool.getStringPointer((String) value)); + } + } + private static DataType asDataType(ValueType type) { if (type instanceof ValueType.Primitive) { switch (((ValueType.Primitive) type).getKind()) { diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerationVisitor.java b/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerationVisitor.java index cdbe7533e..44ef81ada 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerationVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerationVisitor.java @@ -813,7 +813,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor { private void translateSwitchToWasmSwitch(SwitchStatement statement, WasmExpression condition, WasmBlock initialWrapper, WasmBlock defaultTarget, WasmBlock[] targets, int min, int max) { - if (min > 0) { + if (min != 0) { condition = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SUB, condition, new WasmInt32Constant(min)); } diff --git a/core/src/main/java/org/teavm/backend/wasm/intrinsics/PlatformIntrinsic.java b/core/src/main/java/org/teavm/backend/wasm/intrinsics/PlatformIntrinsic.java index 4e11aa14d..826a173a3 100644 --- a/core/src/main/java/org/teavm/backend/wasm/intrinsics/PlatformIntrinsic.java +++ b/core/src/main/java/org/teavm/backend/wasm/intrinsics/PlatformIntrinsic.java @@ -34,7 +34,6 @@ public class PlatformIntrinsic implements WasmIntrinsic { switch (methodDescriptor.getName()) { case "getPlatformObject": case "asJavaClass": - case "getName": case "createQueue": return true; default: @@ -48,7 +47,6 @@ public class PlatformIntrinsic implements WasmIntrinsic { case "getPlatformObject": case "asJavaClass": return manager.generate(invocation.getArguments().get(0)); - case "getName": case "createQueue": return new WasmInt32Constant(0); default: diff --git a/core/src/main/java/org/teavm/backend/wasm/intrinsics/WasmIntrinsicFactoryContext.java b/core/src/main/java/org/teavm/backend/wasm/intrinsics/WasmIntrinsicFactoryContext.java index eb682f5df..c9012aef1 100644 --- a/core/src/main/java/org/teavm/backend/wasm/intrinsics/WasmIntrinsicFactoryContext.java +++ b/core/src/main/java/org/teavm/backend/wasm/intrinsics/WasmIntrinsicFactoryContext.java @@ -17,10 +17,10 @@ package org.teavm.backend.wasm.intrinsics; import java.util.Properties; import org.teavm.common.ServiceRepository; -import org.teavm.model.ListableClassReaderSource; +import org.teavm.model.ClassReaderSource; public interface WasmIntrinsicFactoryContext { - ListableClassReaderSource getClassSource(); + ClassReaderSource getClassSource(); ClassLoader getClassLoader(); diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderingVisitor.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderingVisitor.java index 52e01a0e1..219e51db1 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderingVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmCRenderingVisitor.java @@ -308,12 +308,24 @@ class WasmCRenderingVisitor implements WasmExpressionVisitor { @Override public void visit(WasmFloat32Constant expression) { - value = CExpression.relocatable(Float.toHexString(expression.getValue()) + "F"); + if (Float.isInfinite(expression.getValue())) { + value = CExpression.relocatable(expression.getValue() < 0 ? "-INFINITY" : "INFINITY"); + } else if (Float.isNaN(expression.getValue())) { + value = CExpression.relocatable("NAN"); + } else { + value = CExpression.relocatable(Float.toHexString(expression.getValue()) + "F"); + } } @Override public void visit(WasmFloat64Constant expression) { - value = CExpression.relocatable(Double.toHexString(expression.getValue())); + if (Double.isInfinite(expression.getValue())) { + value = CExpression.relocatable(expression.getValue() < 0 ? "-INFINITY" : "INFINITY"); + } else if (Double.isNaN(expression.getValue())) { + value = CExpression.relocatable("NAN"); + } else { + value = CExpression.relocatable(Double.toHexString(expression.getValue())); + } } @Override diff --git a/core/src/main/java/org/teavm/model/classes/VirtualTableProvider.java b/core/src/main/java/org/teavm/model/classes/VirtualTableProvider.java index de462e8bc..02fbd2559 100644 --- a/core/src/main/java/org/teavm/model/classes/VirtualTableProvider.java +++ b/core/src/main/java/org/teavm/model/classes/VirtualTableProvider.java @@ -78,7 +78,9 @@ public class VirtualTableProvider { Set newDescriptors = virtualMethodMap.get(className); if (newDescriptors != null) { for (MethodDescriptor method : newDescriptors) { - table.entries.put(method, new VirtualTableEntry(table, method, null, table.entries.size())); + if (!table.entries.containsKey(method)) { + table.entries.put(method, new VirtualTableEntry(table, method, null, table.entries.size())); + } } } diff --git a/core/src/main/resources/org/teavm/backend/wasm/wasm-runtime.c b/core/src/main/resources/org/teavm/backend/wasm/wasm-runtime.c index c6963450b..76dd1737a 100644 --- a/core/src/main/resources/org/teavm/backend/wasm/wasm-runtime.c +++ b/core/src/main/resources/org/teavm/backend/wasm/wasm-runtime.c @@ -6,7 +6,15 @@ #include #include #include +#include static inline float TeaVM_getNaN() { return NAN; +} + +static int64_t currentTimeMillis() { + struct timespec time; + clock_gettime(CLOCK_REALTIME, &time); + + return time.tv_sec * 1000 + (int64_t) round(time.tv_nsec / 1000000); } \ No newline at end of file diff --git a/platform/src/main/java/org/teavm/platform/Platform.java b/platform/src/main/java/org/teavm/platform/Platform.java index 1b27a767a..a54016694 100644 --- a/platform/src/main/java/org/teavm/platform/Platform.java +++ b/platform/src/main/java/org/teavm/platform/Platform.java @@ -227,6 +227,7 @@ public final class Platform { return cls.getMetadata().getArrayItem(); } + @Unmanaged public static String getName(PlatformClass cls) { return cls.getMetadata().getName(); } diff --git a/platform/src/main/java/org/teavm/platform/plugin/MetadataIntrinsic.java b/platform/src/main/java/org/teavm/platform/plugin/MetadataIntrinsic.java index da9f32cd5..f89996d3c 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/MetadataIntrinsic.java +++ b/platform/src/main/java/org/teavm/platform/plugin/MetadataIntrinsic.java @@ -33,7 +33,7 @@ import org.teavm.backend.wasm.model.expression.WasmExpression; import org.teavm.backend.wasm.model.expression.WasmInt32Constant; import org.teavm.common.ServiceRepository; import org.teavm.model.CallLocation; -import org.teavm.model.ListableClassReaderSource; +import org.teavm.model.ClassReaderSource; import org.teavm.model.MethodReader; import org.teavm.model.MethodReference; import org.teavm.platform.metadata.MetadataGenerator; @@ -41,13 +41,13 @@ import org.teavm.platform.metadata.MetadataProvider; import org.teavm.platform.metadata.Resource; public class MetadataIntrinsic implements WasmIntrinsic { - private ListableClassReaderSource classSource; + private ClassReaderSource classSource; private ClassLoader classLoader; private ServiceRepository services; private Properties properties; private Map resourceTypeCache = new HashMap<>(); - public MetadataIntrinsic(ListableClassReaderSource classSource, ClassLoader classLoader, + public MetadataIntrinsic(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services, Properties properties) { this.classSource = classSource; this.classLoader = classLoader; diff --git a/tests/src/test/java/org/teavm/classlib/java/io/StreamTokenizerTest.java b/tests/src/test/java/org/teavm/classlib/java/io/StreamTokenizerTest.java index 7719aa01b..f225aa26f 100644 --- a/tests/src/test/java/org/teavm/classlib/java/io/StreamTokenizerTest.java +++ b/tests/src/test/java/org/teavm/classlib/java/io/StreamTokenizerTest.java @@ -287,7 +287,7 @@ public class StreamTokenizerTest { public void test_toString() throws IOException { setTest("ABC Hello World"); st.nextToken(); - assertTrue("toString failed." + st.toString(), st.toString().equals("Token[ABC], line 1")); + assertEquals("toString failed.", "Token[ABC], line 1", st.toString()); // Regression test for HARMONY-4070 byte[] data = new byte[] { (byte) '-' };