Don't generate redundant clinit instructions

This commit is contained in:
Alexey Andreev 2016-09-08 00:00:11 +03:00
parent 74db07537d
commit bfc37b10b5
4 changed files with 95 additions and 1 deletions

View File

@ -316,7 +316,7 @@ public class WasmTarget implements TeaVMTarget {
private void emitC(WasmModule module, BuildTarget buildTarget, String outputName) throws IOException { private void emitC(WasmModule module, BuildTarget buildTarget, String outputName) throws IOException {
WasmCRenderer renderer = new WasmCRenderer(); WasmCRenderer renderer = new WasmCRenderer();
renderer.setLineNumbersEmitted(debugging); //renderer.setLineNumbersEmitted(debugging);
renderer.render(module); renderer.render(module);
try (OutputStream output = buildTarget.createResource(outputName); try (OutputStream output = buildTarget.createResource(outputName);
Writer writer = new OutputStreamWriter(output, "UTF-8")) { Writer writer = new OutputStreamWriter(output, "UTF-8")) {

View File

@ -30,6 +30,7 @@ import org.teavm.model.MethodReference;
import org.teavm.model.Program; import org.teavm.model.Program;
import org.teavm.model.ValueType; import org.teavm.model.ValueType;
import org.teavm.model.instructions.InitClassInstruction; import org.teavm.model.instructions.InitClassInstruction;
import org.teavm.model.lowlevel.ClassInitializerEliminator;
import org.teavm.model.lowlevel.ClassInitializerTransformer; import org.teavm.model.lowlevel.ClassInitializerTransformer;
public class WasmGenerator { public class WasmGenerator {
@ -58,6 +59,7 @@ public class WasmGenerator {
entryBlock.getInstructions().add(0, initInsn); entryBlock.getInstructions().add(0, initInsn);
} }
new ClassInitializerEliminator(classSource).apply(program);
new ClassInitializerTransformer().transform(program); new ClassInitializerTransformer().transform(program);
RegularMethodNode methodAst = decompiler.decompileRegular(bodyMethod); RegularMethodNode methodAst = decompiler.decompileRegular(bodyMethod);

View File

@ -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<String, Boolean> 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<Instruction> 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("<clinit>", 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;
}
}

View File

@ -15,6 +15,7 @@
*/ */
package org.teavm.interop; package org.teavm.interop;
@StaticInit
public final class Address { public final class Address {
public native Address add(int offset); public native Address add(int offset);