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 e97f1c493..88e5e7bca 100644 --- a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java +++ b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java @@ -316,7 +316,7 @@ public class WasmTarget implements TeaVMTarget { private void emitC(WasmModule module, BuildTarget buildTarget, String outputName) throws IOException { WasmCRenderer renderer = new WasmCRenderer(); - renderer.setLineNumbersEmitted(debugging); + //renderer.setLineNumbersEmitted(debugging); renderer.render(module); try (OutputStream output = buildTarget.createResource(outputName); Writer writer = new OutputStreamWriter(output, "UTF-8")) { diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerator.java b/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerator.java index 2495f5958..1de814e8d 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerator.java @@ -30,6 +30,7 @@ import org.teavm.model.MethodReference; import org.teavm.model.Program; import org.teavm.model.ValueType; import org.teavm.model.instructions.InitClassInstruction; +import org.teavm.model.lowlevel.ClassInitializerEliminator; import org.teavm.model.lowlevel.ClassInitializerTransformer; public class WasmGenerator { @@ -58,6 +59,7 @@ public class WasmGenerator { entryBlock.getInstructions().add(0, initInsn); } + new ClassInitializerEliminator(classSource).apply(program); new ClassInitializerTransformer().transform(program); RegularMethodNode methodAst = decompiler.decompileRegular(bodyMethod); diff --git a/core/src/main/java/org/teavm/model/lowlevel/ClassInitializerEliminator.java b/core/src/main/java/org/teavm/model/lowlevel/ClassInitializerEliminator.java new file mode 100644 index 000000000..1a32fd72d --- /dev/null +++ b/core/src/main/java/org/teavm/model/lowlevel/ClassInitializerEliminator.java @@ -0,0 +1,91 @@ +/* + * Copyright 2016 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.model.lowlevel; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.teavm.interop.StaticInit; +import org.teavm.interop.Structure; +import org.teavm.model.BasicBlock; +import org.teavm.model.ClassReader; +import org.teavm.model.ClassReaderSource; +import org.teavm.model.Instruction; +import org.teavm.model.MethodDescriptor; +import org.teavm.model.Program; +import org.teavm.model.instructions.EmptyInstruction; +import org.teavm.model.instructions.InitClassInstruction; + +public class ClassInitializerEliminator { + private ClassReaderSource unprocessedClassSource; + private Map cache = new HashMap<>(); + + public ClassInitializerEliminator(ClassReaderSource unprocessedClassSource) { + this.unprocessedClassSource = unprocessedClassSource; + } + + public void apply(Program program) { + for (int i = 0; i < program.basicBlockCount(); ++i) { + BasicBlock block = program.basicBlockAt(i); + List instructions = block.getInstructions(); + for (int j = 0; j < instructions.size(); ++j) { + Instruction insn = instructions.get(j); + if (insn instanceof InitClassInstruction) { + if (!filter(((InitClassInstruction) insn).getClassName())) { + EmptyInstruction empty = new EmptyInstruction(); + empty.setLocation(insn.getLocation()); + instructions.set(j, empty); + } + } + } + } + } + + private boolean filter(String className) { + return cache.computeIfAbsent(className, key -> clinitNeeded(key) && !isStaticInit(key) && !isStructure(key)); + } + + private boolean clinitNeeded(String className) { + ClassReader cls = unprocessedClassSource.get(className); + if (cls == null) { + return true; + } + + return cls.getMethod(new MethodDescriptor("", void.class)) != null; + } + + private boolean isStaticInit(String className) { + ClassReader cls = unprocessedClassSource.get(className); + if (cls == null) { + return false; + } + return cls.getAnnotations().get(StaticInit.class.getName()) != null; + } + + private boolean isStructure(String className) { + while (!className.equals(Structure.class.getName())) { + ClassReader cls = unprocessedClassSource.get(className); + if (cls == null) { + return false; + } + if (cls.getParent() == null || cls.getName().equals(cls.getParent())) { + return false; + } + className = cls.getParent(); + } + return true; + } +} diff --git a/interop/core/src/main/java/org/teavm/interop/Address.java b/interop/core/src/main/java/org/teavm/interop/Address.java index dd4875ec2..af8cfede5 100644 --- a/interop/core/src/main/java/org/teavm/interop/Address.java +++ b/interop/core/src/main/java/org/teavm/interop/Address.java @@ -15,6 +15,7 @@ */ package org.teavm.interop; +@StaticInit public final class Address { public native Address add(int offset);