diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/text/TDecimalFormat.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/text/TDecimalFormat.java index 5db006aac..e1387c283 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/text/TDecimalFormat.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/text/TDecimalFormat.java @@ -343,16 +343,18 @@ public class TDecimalFormat extends TNumberFormat { int mantissaLength = fastLn10(mantissa) + 1; ++exponent; - int multiplierDigits = fastLn10(multiplier); - int tenMultiplier = POW10_INT_ARRAY[multiplierDigits]; - if (tenMultiplier == multiplier) { - exponent += multiplierDigits; - } else if (mantissa >= Long.MAX_VALUE / multiplier || mantissa <= Long.MIN_VALUE / multiplier) { - formatRegular(new BigDecimal(BigInteger.valueOf(mantissa), mantissaLength - exponent), buffer); - return; - } else { - mantissa *= multiplier; - mantissaLength = fastLn10(mantissa) + 1; + if (multiplier != 1) { + int multiplierDigits = fastLn10(multiplier); + int tenMultiplier = POW10_INT_ARRAY[multiplierDigits]; + if (tenMultiplier == multiplier) { + exponent += multiplierDigits; + } else if (mantissa >= Long.MAX_VALUE / multiplier || mantissa <= Long.MIN_VALUE / multiplier) { + formatRegular(new BigDecimal(BigInteger.valueOf(mantissa), mantissaLength - exponent), buffer); + return; + } else { + mantissa *= multiplier; + mantissaLength = fastLn10(mantissa) + 1; + } } // Apply rounding if necessary diff --git a/teavm-cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java b/teavm-cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java index 8d4f627d0..af9941e38 100644 --- a/teavm-cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java +++ b/teavm-cli/src/main/java/org/teavm/cli/TeaVMTestRunner.java @@ -65,6 +65,10 @@ public final class TeaVMTestRunner { .withDescription("qualified class names of transformers") .withLongOpt("transformers") .create("T")); + options.addOption(OptionBuilder + .withDescription("Incremental build") + .withLongOpt("incremental") + .create('i')); if (args.length == 0) { printUsage(options); @@ -97,6 +101,10 @@ public final class TeaVMTestRunner { tool.getTransformers().add(instantiateTransformer(transformerType)); } } + if (commandLine.hasOption('i')) { + tool.setIncremental(true); + } + args = commandLine.getArgs(); if (args.length == 0) { System.err.println("You did not specify any test classes"); diff --git a/teavm-core/src/main/java/org/teavm/cache/NoCache.java b/teavm-core/src/main/java/org/teavm/cache/NoCache.java new file mode 100644 index 000000000..02ac35c36 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/cache/NoCache.java @@ -0,0 +1,30 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.cache; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * + * @author Alexey Andreev + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface NoCache { +} diff --git a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java index 290cbc094..80969bd09 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import org.teavm.cache.NoCache; import org.teavm.common.Graph; import org.teavm.common.GraphIndexer; import org.teavm.common.Loop; @@ -245,7 +246,7 @@ public class Decompiler { } public RegularMethodNode decompileRegular(MethodHolder method) { - if (regularMethodCache == null) { + if (regularMethodCache == null || method.getAnnotations().get(NoCache.class.getName()) != null) { return decompileRegularCacheMiss(method); } RegularMethodNode node = regularMethodCache.get(method.getReference()); @@ -283,7 +284,7 @@ public class Decompiler { } public AsyncMethodNode decompileAsync(MethodHolder method) { - if (regularMethodCache == null) { + if (regularMethodCache == null || method.getAnnotations().get(NoCache.class.getName()) != null) { return decompileAsyncCacheMiss(method); } AsyncMethodNode node = regularMethodCache.getAsync(method.getReference()); diff --git a/teavm-core/src/main/java/org/teavm/model/InMemoryProgramCache.java b/teavm-core/src/main/java/org/teavm/model/InMemoryProgramCache.java index e9046950a..6d085a704 100644 --- a/teavm-core/src/main/java/org/teavm/model/InMemoryProgramCache.java +++ b/teavm-core/src/main/java/org/teavm/model/InMemoryProgramCache.java @@ -17,6 +17,7 @@ package org.teavm.model; import java.util.HashMap; import java.util.Map; +import org.teavm.model.util.ProgramUtils; /** * @@ -27,11 +28,12 @@ public class InMemoryProgramCache implements ProgramCache { @Override public Program get(MethodReference method) { - return cache.get(method); + Program program = cache.get(method); + return program != null ? ProgramUtils.copy(program) : null; } @Override public void store(MethodReference method, Program program) { - cache.put(method, program); + cache.put(method, ProgramUtils.copy(program)); } } diff --git a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java index 413421a0c..83ffe6def 100644 --- a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java +++ b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java @@ -236,7 +236,7 @@ public class TeaVMTool { symbolTable.update(); fileTable.update(); } catch (IOException e) { - log.info("Cache was not read"); + log.info("Cache is missing"); } vmBuilder.setClassLoader(classLoader).setClassSource(cachedClassSource); } else { diff --git a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java index f06967cd5..086b7e7c7 100644 --- a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java +++ b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java @@ -17,6 +17,7 @@ package org.teavm.vm; import java.io.*; import java.util.*; +import org.teavm.cache.NoCache; import org.teavm.codegen.*; import org.teavm.common.ServiceRepository; import org.teavm.debugging.information.DebugInformationEmitter; @@ -616,7 +617,9 @@ public class TeaVM implements TeaVMHost, ServiceRepository { if (method.getProgram() == null) { return; } - Program optimizedProgram = incremental && programCache != null ? + + boolean noCache = method.getAnnotations().get(NoCache.class.getName()) != null; + Program optimizedProgram = incremental && !noCache && programCache != null ? programCache.get(method.getReference()) : null; if (optimizedProgram == null) { optimizedProgram = ProgramUtils.copy(method.getProgram()); diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java index 2ac8a0bc9..65e4235c7 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java @@ -15,6 +15,7 @@ */ package org.teavm.platform.plugin; +import org.teavm.cache.NoCache; import org.teavm.diagnostics.Diagnostics; import org.teavm.javascript.spi.GeneratedBy; import org.teavm.model.*; @@ -49,10 +50,14 @@ class MetadataProviderTransformer implements ClassHolderTransformer { method.getReference(), ClassScopedMetadataProvider.class.getName(), PlatformClass.class.getName()); } + AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName()); genAnnot.getValues().put("value", new AnnotationValue(ValueType.object( ClassScopedMetadataProviderNativeGenerator.class.getName()))); method.getAnnotations().add(genAnnot); + + AnnotationHolder noCacheAnnot = new AnnotationHolder(NoCache.class.getName()); + method.getAnnotations().add(noCacheAnnot); } } } @@ -95,6 +100,9 @@ class MetadataProviderTransformer implements ClassHolderTransformer { fork.setElse(pe.createBlock()); pe.setField(field.getReference(), field.getType(), pe.invoke(createMethod.getReference())); pe.jump(resourceFound); + + AnnotationHolder noCacheAnnot = new AnnotationHolder(NoCache.class.getName()); + method.getAnnotations().add(noCacheAnnot); } private boolean validate(MethodHolder method, Diagnostics diagnostics) {