diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java index c4c43d061..676a9edf0 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java @@ -41,7 +41,7 @@ import org.teavm.classlib.java.lang.reflect.TModifier; import org.teavm.dependency.PluggableDependency; import org.teavm.interop.Address; import org.teavm.interop.DelegateTo; -import org.teavm.interop.DoesNotModifyStaticFields; +import org.teavm.interop.NoSideEffects; import org.teavm.interop.Unmanaged; import org.teavm.jso.core.JSArray; import org.teavm.platform.Platform; @@ -210,7 +210,7 @@ public class TClass extends TObject implements TAnnotatedElement { } @GeneratedBy(ClassGenerator.class) - @DoesNotModifyStaticFields + @NoSideEffects private static native void createMetadata(); public TField[] getFields() throws TSecurityException { diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TClassLoader.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TClassLoader.java index d9c59910b..c7e1acd72 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TClassLoader.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TClassLoader.java @@ -19,7 +19,7 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import org.teavm.backend.javascript.spi.InjectedBy; import org.teavm.classlib.impl.Base64Impl; -import org.teavm.interop.DoesNotModifyStaticFields; +import org.teavm.interop.NoSideEffects; import org.teavm.jso.JSBody; import org.teavm.jso.JSIndexer; import org.teavm.jso.JSObject; @@ -69,7 +69,7 @@ public abstract class TClassLoader extends TObject { private static native String resourceToString(JSObject resource); @InjectedBy(ClassLoaderNativeGenerator.class) - @DoesNotModifyStaticFields + @NoSideEffects private static native ResourceContainer supplyResources(); interface ResourceContainer extends JSObject { diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TDouble.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TDouble.java index 8ff43cb61..ef7f44a21 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TDouble.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TDouble.java @@ -16,11 +16,11 @@ package org.teavm.classlib.java.lang; import org.teavm.backend.javascript.spi.InjectedBy; -import org.teavm.interop.DoesNotModifyStaticFields; import org.teavm.interop.Import; +import org.teavm.interop.NoSideEffects; import org.teavm.jso.JSBody; -@DoesNotModifyStaticFields +@NoSideEffects public class TDouble extends TNumber implements TComparable { public static final double POSITIVE_INFINITY = 1 / 0.0; public static final double NEGATIVE_INFINITY = -POSITIVE_INFINITY; @@ -210,7 +210,7 @@ public class TDouble extends TNumber implements TComparable { return (int) (h >>> 32) ^ (int) h; } - @DoesNotModifyStaticFields + @NoSideEffects public static native int compare(double a, double b); @Override @@ -228,18 +228,22 @@ public class TDouble extends TNumber implements TComparable { @JSBody(params = "v", script = "return isNaN(v);") @Import(module = "teavm", name = "isnan") + @NoSideEffects public static native boolean isNaN(double v); @JSBody(script = "return NaN;") @Import(module = "teavm", name = "TeaVM_getNaN") + @NoSideEffects private static native double getNaN(); @JSBody(params = "v", script = "return !isFinite(v);") @Import(module = "teavm", name = "isinf") + @NoSideEffects public static native boolean isInfinite(double v); @JSBody(params = "v", script = "return isFinite(v);") @Import(module = "teavm", name = "isfinite") + @NoSideEffects public static native boolean isFinite(double v); public static long doubleToRawLongBits(double value) { @@ -248,10 +252,12 @@ public class TDouble extends TNumber implements TComparable { @InjectedBy(DoubleGenerator.class) @Import(name = "teavm_reinterpretDoubleToLong") + @NoSideEffects public static native long doubleToLongBits(double value); @InjectedBy(DoubleGenerator.class) @Import(name = "teavm_reinterpretLongToDouble") + @NoSideEffects public static native double longBitsToDouble(long bits); public static String toHexString(double d) { diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TFloat.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TFloat.java index 1d71b8059..16600faaf 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TFloat.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TFloat.java @@ -15,8 +15,8 @@ */ package org.teavm.classlib.java.lang; -import org.teavm.interop.DoesNotModifyStaticFields; import org.teavm.interop.Import; +import org.teavm.interop.NoSideEffects; import org.teavm.jso.JSBody; public class TFloat extends TNumber implements TComparable { @@ -92,18 +92,22 @@ public class TFloat extends TNumber implements TComparable { @JSBody(params = "v", script = "return isNaN(v);") @Import(module = "teavm", name = "isnan") + @NoSideEffects public static native boolean isNaN(float v); @JSBody(params = "v", script = "return !isFinite(v);") @Import(module = "teavm", name = "isinf") + @NoSideEffects public static native boolean isInfinite(float v); @JSBody(params = "v", script = "return isFinite(v);") @Import(module = "teavm", name = "isfinite") + @NoSideEffects public static native boolean isFinite(float v); @JSBody(script = "return NaN;") @Import(module = "teavm", name = "TeaVM_getNaN") + @NoSideEffects private static native float getNaN(); public static float parseFloat(TString string) throws TNumberFormatException { @@ -238,7 +242,7 @@ public class TFloat extends TNumber implements TComparable { return isInfinite(value); } - @DoesNotModifyStaticFields + @NoSideEffects public static native int compare(float f1, float f2); @Override @@ -252,10 +256,12 @@ public class TFloat extends TNumber implements TComparable { @JSBody(params = "value", script = "return $rt_floatToIntBits(value);") @Import(name = "teavm_reinterpretFloatToInt") + @NoSideEffects public static native int floatToIntBits(float value); @JSBody(params = "bits", script = "return $rt_intBitsToFloat(bits);") @Import(name = "teavm_reinterpretIntToFloat") + @NoSideEffects public static native float intBitsToFloat(int bits); public static String toHexString(float f) { diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TInteger.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TInteger.java index 7f1daf576..b407aaaf0 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TInteger.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TInteger.java @@ -17,7 +17,7 @@ package org.teavm.classlib.java.lang; import static org.teavm.classlib.impl.IntegerUtil.toUnsignedLogRadixString; import org.teavm.backend.javascript.spi.InjectedBy; -import org.teavm.interop.DoesNotModifyStaticFields; +import org.teavm.interop.NoSideEffects; public class TInteger extends TNumber implements TComparable { public static final int SIZE = 32; @@ -252,7 +252,7 @@ public class TInteger extends TNumber implements TComparable { return compare(value, other.value); } - @DoesNotModifyStaticFields + @NoSideEffects public static native int compare(int x, int y); public static int numberOfLeadingZeros(int i) { @@ -358,10 +358,10 @@ public class TInteger extends TNumber implements TComparable { } @InjectedBy(IntegerNativeGenerator.class) - @DoesNotModifyStaticFields + @NoSideEffects public static native int divideUnsigned(int dividend, int divisor); @InjectedBy(IntegerNativeGenerator.class) - @DoesNotModifyStaticFields + @NoSideEffects public static native int remainderUnsigned(int dividend, int divisor); } diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TLong.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TLong.java index 6bf0dc5aa..8c38bae93 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TLong.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TLong.java @@ -17,7 +17,7 @@ package org.teavm.classlib.java.lang; import static org.teavm.classlib.impl.IntegerUtil.toUnsignedLogRadixString; import org.teavm.backend.javascript.spi.GeneratedBy; -import org.teavm.interop.DoesNotModifyStaticFields; +import org.teavm.interop.NoSideEffects; public class TLong extends TNumber implements TComparable { public static final long MIN_VALUE = -0x8000000000000000L; @@ -213,7 +213,7 @@ public class TLong extends TNumber implements TComparable { return other instanceof TLong && ((TLong) other).value == value; } - @DoesNotModifyStaticFields + @NoSideEffects public static native int compare(long a, long b); @Override @@ -353,10 +353,10 @@ public class TLong extends TNumber implements TComparable { } @GeneratedBy(LongNativeGenerator.class) - @DoesNotModifyStaticFields + @NoSideEffects public static native long divideUnsigned(long dividend, long divisor); @GeneratedBy(LongNativeGenerator.class) - @DoesNotModifyStaticFields + @NoSideEffects public static native long remainderUnsigned(long dividend, long divisor); } diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java index 1a3f47647..8f11261f8 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java @@ -16,10 +16,10 @@ package org.teavm.classlib.java.lang; import org.teavm.backend.javascript.spi.GeneratedBy; -import org.teavm.interop.DoesNotModifyStaticFields; import org.teavm.interop.Import; +import org.teavm.interop.NoSideEffects; -@DoesNotModifyStaticFields +@NoSideEffects public final class TMath extends TObject { public static final double E = 2.71828182845904523536; public static final double PI = 3.14159265358979323846; diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java index 48bdb11bc..e54364c60 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java @@ -21,7 +21,7 @@ import org.teavm.interop.Address; import org.teavm.interop.Async; import org.teavm.interop.AsyncCallback; import org.teavm.interop.DelegateTo; -import org.teavm.interop.DoesNotModifyStaticFields; +import org.teavm.interop.NoSideEffects; import org.teavm.interop.Rename; import org.teavm.interop.Structure; import org.teavm.interop.Superclass; @@ -273,7 +273,7 @@ public class TObject { } @DelegateTo("hashCodeLowLevelImpl") - @DoesNotModifyStaticFields + @NoSideEffects private static native int hashCodeLowLevel(TObject obj); @Unmanaged @@ -282,7 +282,7 @@ public class TObject { } @DelegateTo("setHashCodeLowLevelImpl") - @DoesNotModifyStaticFields + @NoSideEffects private static native void setHashCodeLowLevel(TObject obj, int value); @Unmanaged @@ -303,7 +303,7 @@ public class TObject { } @DelegateTo("identityOrMonitorLowLevel") - @DoesNotModifyStaticFields + @NoSideEffects private native int identityOrMonitor(); private static int identityOrMonitorLowLevel(RuntimeObject object) { @@ -311,7 +311,7 @@ public class TObject { } @DelegateTo("setIdentityLowLevel") - @DoesNotModifyStaticFields + @NoSideEffects native void setIdentity(int id); private static void setIdentityLowLevel(RuntimeObject object, int id) { diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TString.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TString.java index bc4383ac7..2afc65212 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TString.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TString.java @@ -30,7 +30,7 @@ import org.teavm.classlib.java.util.TFormatter; import org.teavm.classlib.java.util.TLocale; import org.teavm.classlib.java.util.regex.TPattern; import org.teavm.dependency.PluggableDependency; -import org.teavm.interop.DoesNotModifyStaticFields; +import org.teavm.interop.NoSideEffects; public class TString extends TObject implements TSerializable, TComparable, TCharSequence { public static final TComparator CASE_INSENSITIVE_ORDER = (o1, o2) -> o1.compareToIgnoreCase(o2); @@ -628,7 +628,7 @@ public class TString extends TObject implements TSerializable, TComparable", ValueType.VOID)); - first.insertPrevious(invoke); + InitClassInstruction clinit = new InitClassInstruction(); + clinit.setClassName(className); + first.insertPrevious(clinit); } } diff --git a/interop/core/src/main/java/org/teavm/interop/DoesNotModifyStaticFields.java b/interop/core/src/main/java/org/teavm/interop/NoSideEffects.java similarity index 95% rename from interop/core/src/main/java/org/teavm/interop/DoesNotModifyStaticFields.java rename to interop/core/src/main/java/org/teavm/interop/NoSideEffects.java index 1f4cbcc73..8496b7b2b 100644 --- a/interop/core/src/main/java/org/teavm/interop/DoesNotModifyStaticFields.java +++ b/interop/core/src/main/java/org/teavm/interop/NoSideEffects.java @@ -22,5 +22,5 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD, ElementType.TYPE }) -public @interface DoesNotModifyStaticFields { +public @interface NoSideEffects { } diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java index 01a661188..7bd3a8fab 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java @@ -32,7 +32,7 @@ import org.mozilla.javascript.ast.FunctionNode; import org.teavm.backend.javascript.rendering.JSParser; import org.teavm.cache.IncrementalDependencyRegistration; import org.teavm.diagnostics.Diagnostics; -import org.teavm.interop.DoesNotModifyStaticFields; +import org.teavm.interop.NoSideEffects; import org.teavm.interop.Sync; import org.teavm.jso.JSBody; import org.teavm.jso.JSByRef; @@ -654,7 +654,9 @@ class JSClassProcessor { MethodHolder proxyMethod = new MethodHolder(proxyRef.getDescriptor()); proxyMethod.getModifiers().add(ElementModifier.NATIVE); proxyMethod.getModifiers().add(ElementModifier.STATIC); - proxyMethod.getAnnotations().add(new AnnotationHolder(DoesNotModifyStaticFields.class.getName())); + if (method.getAnnotations().get(NoSideEffects.class.getName()) != null) { + proxyMethod.getAnnotations().add(new AnnotationHolder(NoSideEffects.class.getName())); + } boolean inline = repository.inlineMethods.contains(methodRef); AnnotationHolder generatorAnnot = new AnnotationHolder(inline ? DynamicInjector.class.getName() : DynamicGenerator.class.getName()); diff --git a/platform/src/main/java/org/teavm/platform/Platform.java b/platform/src/main/java/org/teavm/platform/Platform.java index 74f2b5a53..f1eff2919 100644 --- a/platform/src/main/java/org/teavm/platform/Platform.java +++ b/platform/src/main/java/org/teavm/platform/Platform.java @@ -21,6 +21,7 @@ import org.teavm.backend.javascript.spi.InjectedBy; import org.teavm.dependency.PluggableDependency; import org.teavm.interop.Address; import org.teavm.interop.DelegateTo; +import org.teavm.interop.NoSideEffects; import org.teavm.interop.PlatformMarker; import org.teavm.interop.PlatformMarkers; import org.teavm.interop.Unmanaged; @@ -42,10 +43,12 @@ public final class Platform { @InjectedBy(PlatformGenerator.class) @Unmanaged + @NoSideEffects public static native PlatformObject getPlatformObject(Object obj); @GeneratedBy(PlatformGenerator.class) @PluggableDependency(PlatformGenerator.class) + @NoSideEffects public static native Object clone(Object obj); @DelegateTo("isInstanceLowLevel") @@ -61,6 +64,7 @@ public final class Platform { } @JSBody(params = "object", script = "return typeof object === 'undefined';") + @NoSideEffects private static native boolean isUndefined(JSObject object); @DelegateTo("isAssignableLowLevel") @@ -86,9 +90,11 @@ public final class Platform { @InjectedBy(PlatformGenerator.class) @PluggableDependency(PlatformGenerator.class) @Unmanaged + @NoSideEffects public static native Class asJavaClass(PlatformObject obj); @JSBody(script = "return $rt_nextId();") + @NoSideEffects public static native int nextObjectId(); public static T newInstance(PlatformClass cls) { @@ -100,6 +106,7 @@ public final class Platform { } @GeneratedBy(PlatformGenerator.class) + @NoSideEffects private static native void prepareNewInstance(); @GeneratedBy(PlatformGenerator.class) @@ -108,6 +115,7 @@ public final class Platform { @GeneratedBy(PlatformGenerator.class) @PluggableDependency(PlatformGenerator.class) + @NoSideEffects public static native PlatformClass lookupClass(String name); @PluggableDependency(PlatformGenerator.class) @@ -133,6 +141,7 @@ public final class Platform { @GeneratedBy(PlatformGenerator.class) @PluggableDependency(PlatformGenerator.class) @DelegateTo("getEnumConstantsLowLevel") + @NoSideEffects public static native Enum[] getEnumConstants(PlatformClass cls); private static Enum[] getEnumConstantsLowLevel(PlatformClass cls) { @@ -194,7 +203,6 @@ public final class Platform { Window.clearTimeout(id); } - @JSBody(script = "return [];") public static PlatformQueue createQueue() { if (isLowLevel()) { return new LowLevelQueue<>(); @@ -204,6 +212,7 @@ public final class Platform { } @JSBody(script = "return [];") + @NoSideEffects private static native PlatformQueue createQueueJs(); public static PlatformString stringFromCharCode(int charCode) { diff --git a/platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java b/platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java index 6f8d0a432..0d97359e2 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java +++ b/platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java @@ -18,7 +18,7 @@ package org.teavm.platform.plugin; import java.util.HashSet; import java.util.Set; import org.teavm.backend.javascript.spi.GeneratedBy; -import org.teavm.interop.DoesNotModifyStaticFields; +import org.teavm.interop.NoSideEffects; import org.teavm.model.AccessLevel; import org.teavm.model.AnnotationHolder; import org.teavm.model.AnnotationValue; @@ -68,8 +68,8 @@ class MetadataProviderTransformer implements ClassHolderTransformer { MetadataProviderNativeGenerator.class.getName()))); createMethod.getAnnotations().add(genAnnot); ModelUtils.copyAnnotations(method.getAnnotations(), createMethod.getAnnotations()); - if (createMethod.getAnnotations().get(DoesNotModifyStaticFields.class.getName()) == null) { - createMethod.getAnnotations().add(new AnnotationHolder(DoesNotModifyStaticFields.class.getName())); + if (createMethod.getAnnotations().get(NoSideEffects.class.getName()) == null) { + createMethod.getAnnotations().add(new AnnotationHolder(NoSideEffects.class.getName())); } AnnotationHolder refAnnot = new AnnotationHolder(MetadataProviderRef.class.getName()); diff --git a/tools/junit/src/main/java/org/teavm/junit/TeaVMTestConfiguration.java b/tools/junit/src/main/java/org/teavm/junit/TeaVMTestConfiguration.java index bdb5ad0f4..f568ca8d1 100644 --- a/tools/junit/src/main/java/org/teavm/junit/TeaVMTestConfiguration.java +++ b/tools/junit/src/main/java/org/teavm/junit/TeaVMTestConfiguration.java @@ -37,7 +37,7 @@ interface TeaVMTestConfiguration { @Override public void apply(TeaVM vm) { - vm.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE); + vm.setOptimizationLevel(TeaVMOptimizationLevel.ADVANCED); } @Override