mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Add lazy compilation pipeline that can work a little bit faster in incremental compiler
This commit is contained in:
parent
5be34dcf44
commit
35ca7fd152
|
@ -200,12 +200,12 @@ public class CTarget implements TeaVMTarget, TeaVMCHost {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeOptimizations(Program program, MethodReader method, ListableClassReaderSource classSource) {
|
public void beforeOptimizations(Program program, MethodReader method) {
|
||||||
nullCheckInsertion.transformProgram(program, method.getReference());
|
nullCheckInsertion.transformProgram(program, method.getReference());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterOptimizations(Program program, MethodReader method, ListableClassReaderSource classSource) {
|
public void afterOptimizations(Program program, MethodReader method) {
|
||||||
clinitInsertionTransformer.apply(method, program);
|
clinitInsertionTransformer.apply(method, program);
|
||||||
classInitializerEliminator.apply(program);
|
classInitializerEliminator.apply(program);
|
||||||
classInitializerTransformer.transform(program);
|
classInitializerTransformer.transform(program);
|
||||||
|
|
|
@ -70,7 +70,6 @@ import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.ElementModifier;
|
import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.ListableClassHolderSource;
|
import org.teavm.model.ListableClassHolderSource;
|
||||||
import org.teavm.model.ListableClassReaderSource;
|
|
||||||
import org.teavm.model.MethodHolder;
|
import org.teavm.model.MethodHolder;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
@ -293,11 +292,11 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeOptimizations(Program program, MethodReader method, ListableClassReaderSource classSource) {
|
public void beforeOptimizations(Program program, MethodReader method) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterOptimizations(Program program, MethodReader method, ListableClassReaderSource classSource) {
|
public void afterOptimizations(Program program, MethodReader method) {
|
||||||
clinitInsertionTransformer.apply(method, program);
|
clinitInsertionTransformer.apply(method, program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -628,5 +627,5 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
public ClassReaderSource getClassSource() {
|
public ClassReaderSource getClassSource() {
|
||||||
return classSource;
|
return classSource;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -301,11 +301,11 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeOptimizations(Program program, MethodReader method, ListableClassReaderSource classSource) {
|
public void beforeOptimizations(Program program, MethodReader method) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterOptimizations(Program program, MethodReader method, ListableClassReaderSource classes) {
|
public void afterOptimizations(Program program, MethodReader method) {
|
||||||
clinitInsertionTransformer.apply(method, program);
|
clinitInsertionTransformer.apply(method, program);
|
||||||
classInitializerEliminator.apply(program);
|
classInitializerEliminator.apply(program);
|
||||||
classInitializerTransformer.transform(program);
|
classInitializerTransformer.transform(program);
|
||||||
|
|
|
@ -736,6 +736,15 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
||||||
node.transitions = null;
|
node.transitions = null;
|
||||||
node.transitionList = null;
|
node.transitionList = null;
|
||||||
node.method = null;
|
node.method = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
allNodes.clear();
|
||||||
|
classSource.cleanup();
|
||||||
|
agent.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanupTypes() {
|
||||||
|
for (DependencyNode node : allNodes) {
|
||||||
if (node.typeSet != null) {
|
if (node.typeSet != null) {
|
||||||
node.typeSet.cleanup();
|
node.typeSet.cleanup();
|
||||||
}
|
}
|
||||||
|
@ -747,10 +756,6 @@ public abstract class DependencyAnalyzer implements DependencyInfo {
|
||||||
dependency.variableNodes[i] = null;
|
dependency.variableNodes[i] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allNodes.clear();
|
|
||||||
classSource.cleanup();
|
|
||||||
agent.cleanup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ReportEntry {
|
static class ReportEntry {
|
||||||
|
|
|
@ -34,8 +34,13 @@ import org.teavm.model.instructions.PutFieldInstruction;
|
||||||
|
|
||||||
public class Linker {
|
public class Linker {
|
||||||
private static final MethodDescriptor clinitDescriptor = new MethodDescriptor("<clinit>", void.class);
|
private static final MethodDescriptor clinitDescriptor = new MethodDescriptor("<clinit>", void.class);
|
||||||
|
private DependencyInfo dependency;
|
||||||
|
|
||||||
public void link(DependencyInfo dependency, ClassHolder cls) {
|
public Linker(DependencyInfo dependency) {
|
||||||
|
this.dependency = dependency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void link(ClassHolder cls) {
|
||||||
for (MethodHolder method : cls.getMethods().toArray(new MethodHolder[0])) {
|
for (MethodHolder method : cls.getMethods().toArray(new MethodHolder[0])) {
|
||||||
MethodReference methodRef = method.getReference();
|
MethodReference methodRef = method.getReference();
|
||||||
MethodDependencyInfo methodDep = dependency.getMethod(methodRef);
|
MethodDependencyInfo methodDep = dependency.getMethod(methodRef);
|
||||||
|
@ -45,7 +50,7 @@ public class Linker {
|
||||||
method.getModifiers().add(ElementModifier.ABSTRACT);
|
method.getModifiers().add(ElementModifier.ABSTRACT);
|
||||||
method.setProgram(null);
|
method.setProgram(null);
|
||||||
} else if (method.getProgram() != null) {
|
} else if (method.getProgram() != null) {
|
||||||
link(dependency, method);
|
link(method.getReference(), method.getProgram());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (FieldHolder field : cls.getFields().toArray(new FieldHolder[0])) {
|
for (FieldHolder field : cls.getFields().toArray(new FieldHolder[0])) {
|
||||||
|
@ -56,8 +61,7 @@ public class Linker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void link(DependencyInfo dependency, MethodHolder method) {
|
public void link(MethodReference method, Program program) {
|
||||||
Program program = method.getProgram();
|
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
BasicBlock block = program.basicBlockAt(i);
|
BasicBlock block = program.basicBlockAt(i);
|
||||||
for (Instruction insn : block) {
|
for (Instruction insn : block) {
|
||||||
|
@ -96,8 +100,8 @@ public class Linker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void insertClinit(DependencyInfo dependency, String className, MethodHolder method, Instruction insn) {
|
private void insertClinit(DependencyInfo dependency, String className, MethodReference method, Instruction insn) {
|
||||||
if (className.equals(method.getOwnerName())) {
|
if (className.equals(method.getClassName())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ClassReader cls = dependency.getClassSource().get(className);
|
ClassReader cls = dependency.getClassSource().get(className);
|
||||||
|
|
|
@ -15,10 +15,13 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.model;
|
package org.teavm.model;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class MethodHolder extends MemberHolder implements MethodReader {
|
public class MethodHolder extends MemberHolder implements MethodReader {
|
||||||
private MethodDescriptor descriptor;
|
private MethodDescriptor descriptor;
|
||||||
private ClassHolder owner;
|
private ClassHolder owner;
|
||||||
private Program program;
|
private Program program;
|
||||||
|
private Function<MethodHolder, Program> programSupplier;
|
||||||
private AnnotationValue annotationDefault;
|
private AnnotationValue annotationDefault;
|
||||||
private AnnotationContainer[] parameterAnnotations;
|
private AnnotationContainer[] parameterAnnotations;
|
||||||
private MethodReference reference;
|
private MethodReference reference;
|
||||||
|
@ -110,6 +113,13 @@ public class MethodHolder extends MemberHolder implements MethodReader {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Program getProgram() {
|
public Program getProgram() {
|
||||||
|
if (program == null && programSupplier != null) {
|
||||||
|
program = programSupplier.apply(this);
|
||||||
|
if (program != null) {
|
||||||
|
program.setMethod(this);
|
||||||
|
}
|
||||||
|
programSupplier = null;
|
||||||
|
}
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,11 +128,20 @@ public class MethodHolder extends MemberHolder implements MethodReader {
|
||||||
this.program.setMethod(null);
|
this.program.setMethod(null);
|
||||||
}
|
}
|
||||||
this.program = program;
|
this.program = program;
|
||||||
|
this.programSupplier = null;
|
||||||
if (this.program != null) {
|
if (this.program != null) {
|
||||||
this.program.setMethod(this);
|
this.program.setMethod(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setProgramSupplier(Function<MethodHolder, Program> programSupplier) {
|
||||||
|
if (this.program != null) {
|
||||||
|
this.program.setMethod(null);
|
||||||
|
}
|
||||||
|
this.program = null;
|
||||||
|
this.programSupplier = programSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AnnotationValue getAnnotationDefault() {
|
public AnnotationValue getAnnotationDefault() {
|
||||||
return annotationDefault;
|
return annotationDefault;
|
||||||
|
|
|
@ -25,7 +25,6 @@ import org.teavm.dependency.ValueDependencyInfo;
|
||||||
import org.teavm.model.BasicBlock;
|
import org.teavm.model.BasicBlock;
|
||||||
import org.teavm.model.ClassHierarchy;
|
import org.teavm.model.ClassHierarchy;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ClassReaderSource;
|
|
||||||
import org.teavm.model.Instruction;
|
import org.teavm.model.Instruction;
|
||||||
import org.teavm.model.MethodHolder;
|
import org.teavm.model.MethodHolder;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
@ -35,15 +34,13 @@ import org.teavm.model.instructions.InvokeInstruction;
|
||||||
|
|
||||||
public class Devirtualization {
|
public class Devirtualization {
|
||||||
private DependencyInfo dependency;
|
private DependencyInfo dependency;
|
||||||
private ClassReaderSource classSource;
|
|
||||||
private ClassHierarchy hierarchy;
|
private ClassHierarchy hierarchy;
|
||||||
private Set<MethodReference> virtualMethods = new HashSet<>();
|
private Set<MethodReference> virtualMethods = new HashSet<>();
|
||||||
private Set<? extends MethodReference> readonlyVirtualMethods = Collections.unmodifiableSet(virtualMethods);
|
private Set<? extends MethodReference> readonlyVirtualMethods = Collections.unmodifiableSet(virtualMethods);
|
||||||
|
|
||||||
public Devirtualization(DependencyInfo dependency, ClassReaderSource classSource) {
|
public Devirtualization(DependencyInfo dependency, ClassHierarchy hierarchy) {
|
||||||
this.dependency = dependency;
|
this.dependency = dependency;
|
||||||
this.classSource = classSource;
|
this.hierarchy = hierarchy;
|
||||||
hierarchy = new ClassHierarchy(classSource);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void apply(MethodHolder method) {
|
public void apply(MethodHolder method) {
|
||||||
|
@ -82,7 +79,7 @@ public class Devirtualization {
|
||||||
if (className.startsWith("[")) {
|
if (className.startsWith("[")) {
|
||||||
className = "java.lang.Object";
|
className = "java.lang.Object";
|
||||||
}
|
}
|
||||||
ClassReader cls = classSource.get(className);
|
ClassReader cls = hierarchy.getClassSource().get(className);
|
||||||
if (cls == null || !isSuperclass.test(cls.getName(), false)) {
|
if (cls == null || !isSuperclass.test(cls.getName(), false)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,10 @@
|
||||||
package org.teavm.model.optimization;
|
package org.teavm.model.optimization;
|
||||||
|
|
||||||
import org.teavm.dependency.DependencyInfo;
|
import org.teavm.dependency.DependencyInfo;
|
||||||
import org.teavm.model.ClassReaderSource;
|
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
|
|
||||||
public interface MethodOptimizationContext {
|
public interface MethodOptimizationContext {
|
||||||
MethodReader getMethod();
|
MethodReader getMethod();
|
||||||
|
|
||||||
DependencyInfo getDependencyInfo();
|
DependencyInfo getDependencyInfo();
|
||||||
|
|
||||||
ClassReaderSource getClassSource();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,9 +56,6 @@ public class UnusedVariableElimination implements MethodOptimization {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean optimize(MethodReader method, Program program) {
|
public boolean optimize(MethodReader method, Program program) {
|
||||||
if (method.getProgram() == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Graph graph = VariableUsageGraphBuilder.build(program);
|
Graph graph = VariableUsageGraphBuilder.build(program);
|
||||||
boolean[] escaping = VariableEscapeAnalyzer.findEscapingVariables(program);
|
boolean[] escaping = VariableEscapeAnalyzer.findEscapingVariables(program);
|
||||||
boolean[] used = new boolean[escaping.length];
|
boolean[] used = new boolean[escaping.length];
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class MissingItemsProcessor {
|
||||||
private ClassHierarchy hierarchy;
|
private ClassHierarchy hierarchy;
|
||||||
private Diagnostics diagnostics;
|
private Diagnostics diagnostics;
|
||||||
private List<Instruction> instructionsToAdd = new ArrayList<>();
|
private List<Instruction> instructionsToAdd = new ArrayList<>();
|
||||||
private MethodHolder methodHolder;
|
private MethodReference methodRef;
|
||||||
private Program program;
|
private Program program;
|
||||||
private Collection<String> reachableClasses;
|
private Collection<String> reachableClasses;
|
||||||
private Collection<MethodReference> reachableMethods;
|
private Collection<MethodReference> reachableMethods;
|
||||||
|
@ -54,8 +54,12 @@ public class MissingItemsProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processMethod(MethodHolder method) {
|
public void processMethod(MethodHolder method) {
|
||||||
this.methodHolder = method;
|
processMethod(method.getReference(), method.getProgram());
|
||||||
this.program = method.getProgram();
|
}
|
||||||
|
|
||||||
|
public void processMethod(MethodReference method, Program program) {
|
||||||
|
this.methodRef = method;
|
||||||
|
this.program = program;
|
||||||
boolean wasModified = false;
|
boolean wasModified = false;
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
BasicBlock block = program.basicBlockAt(i);
|
BasicBlock block = program.basicBlockAt(i);
|
||||||
|
@ -131,7 +135,7 @@ public class MissingItemsProcessor {
|
||||||
if (!reachableClasses.contains(className) || !dependencyInfo.getClass(className).isMissing()) {
|
if (!reachableClasses.contains(className) || !dependencyInfo.getClass(className).isMissing()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
diagnostics.error(new CallLocation(methodHolder.getReference(), location), "Class {{c0}} was not found",
|
diagnostics.error(new CallLocation(methodRef, location), "Class {{c0}} was not found",
|
||||||
className);
|
className);
|
||||||
emitExceptionThrow(location, NoClassDefFoundError.class.getName(), "Class not found: " + className);
|
emitExceptionThrow(location, NoClassDefFoundError.class.getName(), "Class not found: " + className);
|
||||||
return false;
|
return false;
|
||||||
|
@ -159,7 +163,7 @@ public class MissingItemsProcessor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
diagnostics.error(new CallLocation(methodHolder.getReference(), location), "Method {{m0}} was not found",
|
diagnostics.error(new CallLocation(methodRef, location), "Method {{m0}} was not found",
|
||||||
method);
|
method);
|
||||||
emitExceptionThrow(location, NoSuchMethodError.class.getName(), "Method not found: " + method);
|
emitExceptionThrow(location, NoSuchMethodError.class.getName(), "Method not found: " + method);
|
||||||
return true;
|
return true;
|
||||||
|
@ -177,7 +181,7 @@ public class MissingItemsProcessor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
diagnostics.error(new CallLocation(methodHolder.getReference(), location), "Method {{m0}} was not found",
|
diagnostics.error(new CallLocation(methodRef, location), "Method {{m0}} was not found",
|
||||||
method);
|
method);
|
||||||
emitExceptionThrow(location, NoSuchMethodError.class.getName(), "Method not found: " + method);
|
emitExceptionThrow(location, NoSuchMethodError.class.getName(), "Method not found: " + method);
|
||||||
return true;
|
return true;
|
||||||
|
@ -190,7 +194,7 @@ public class MissingItemsProcessor {
|
||||||
if (!reachableFields.contains(field) || !dependencyInfo.getField(field).isMissing()) {
|
if (!reachableFields.contains(field) || !dependencyInfo.getField(field).isMissing()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
diagnostics.error(new CallLocation(methodHolder.getReference(), location), "Field {{f0}} was not found",
|
diagnostics.error(new CallLocation(methodRef, location), "Field {{f0}} was not found",
|
||||||
field);
|
field);
|
||||||
emitExceptionThrow(location, NoSuchFieldError.class.getName(), "Field not found: " + field);
|
emitExceptionThrow(location, NoSuchFieldError.class.getName(), "Field not found: " + field);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -17,19 +17,33 @@ package org.teavm.model.util;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.AnnotationContainer;
|
||||||
|
import org.teavm.model.AnnotationContainerReader;
|
||||||
|
import org.teavm.model.AnnotationHolder;
|
||||||
|
import org.teavm.model.AnnotationReader;
|
||||||
|
import org.teavm.model.AnnotationValue;
|
||||||
|
import org.teavm.model.ClassHolder;
|
||||||
|
import org.teavm.model.ClassReader;
|
||||||
|
import org.teavm.model.FieldHolder;
|
||||||
|
import org.teavm.model.FieldReader;
|
||||||
|
import org.teavm.model.MethodHolder;
|
||||||
|
import org.teavm.model.MethodReader;
|
||||||
|
|
||||||
public final class ModelUtils {
|
public final class ModelUtils {
|
||||||
private ModelUtils() {
|
private ModelUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ClassHolder copyClass(ClassReader original, ClassHolder target) {
|
public static ClassHolder copyClass(ClassReader original, ClassHolder target) {
|
||||||
|
return copyClass(original, target, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ClassHolder copyClass(ClassReader original, ClassHolder target, boolean withPrograms) {
|
||||||
target.setLevel(original.getLevel());
|
target.setLevel(original.getLevel());
|
||||||
target.getModifiers().addAll(original.readModifiers());
|
target.getModifiers().addAll(original.readModifiers());
|
||||||
target.setParent(original.getParent());
|
target.setParent(original.getParent());
|
||||||
target.getInterfaces().addAll(original.getInterfaces());
|
target.getInterfaces().addAll(original.getInterfaces());
|
||||||
for (MethodReader method : original.getMethods()) {
|
for (MethodReader method : original.getMethods()) {
|
||||||
target.addMethod(copyMethod(method));
|
target.addMethod(copyMethod(method, withPrograms));
|
||||||
}
|
}
|
||||||
for (FieldReader field : original.getFields()) {
|
for (FieldReader field : original.getFields()) {
|
||||||
target.addField(copyField(field));
|
target.addField(copyField(field));
|
||||||
|
@ -40,14 +54,22 @@ public final class ModelUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ClassHolder copyClass(ClassReader original) {
|
public static ClassHolder copyClass(ClassReader original) {
|
||||||
return copyClass(original, new ClassHolder(original.getName()));
|
return copyClass(original, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ClassHolder copyClass(ClassReader original, boolean withPrograms) {
|
||||||
|
return copyClass(original, new ClassHolder(original.getName()), withPrograms);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MethodHolder copyMethod(MethodReader method) {
|
public static MethodHolder copyMethod(MethodReader method) {
|
||||||
|
return copyMethod(method, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MethodHolder copyMethod(MethodReader method, boolean withProgram) {
|
||||||
MethodHolder copy = new MethodHolder(method.getDescriptor());
|
MethodHolder copy = new MethodHolder(method.getDescriptor());
|
||||||
copy.setLevel(method.getLevel());
|
copy.setLevel(method.getLevel());
|
||||||
copy.getModifiers().addAll(method.readModifiers());
|
copy.getModifiers().addAll(method.readModifiers());
|
||||||
if (method.getProgram() != null) {
|
if (method.getProgram() != null && withProgram) {
|
||||||
copy.setProgram(ProgramUtils.copy(method.getProgram()));
|
copy.setProgram(ProgramUtils.copy(method.getProgram()));
|
||||||
}
|
}
|
||||||
copyAnnotations(method.getAnnotations(), copy.getAnnotations());
|
copyAnnotations(method.getAnnotations(), copy.getAnnotations());
|
||||||
|
|
|
@ -26,7 +26,6 @@ import org.teavm.common.MutableGraphNode;
|
||||||
import org.teavm.model.BasicBlock;
|
import org.teavm.model.BasicBlock;
|
||||||
import org.teavm.model.Incoming;
|
import org.teavm.model.Incoming;
|
||||||
import org.teavm.model.Instruction;
|
import org.teavm.model.Instruction;
|
||||||
import org.teavm.model.MethodReader;
|
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.Phi;
|
import org.teavm.model.Phi;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
|
@ -36,7 +35,7 @@ import org.teavm.model.instructions.AssignInstruction;
|
||||||
import org.teavm.model.instructions.JumpInstruction;
|
import org.teavm.model.instructions.JumpInstruction;
|
||||||
|
|
||||||
public class RegisterAllocator {
|
public class RegisterAllocator {
|
||||||
public void allocateRegisters(MethodReader method, Program program, boolean debuggerFriendly) {
|
public void allocateRegisters(MethodReference method, Program program, boolean debuggerFriendly) {
|
||||||
insertPhiArgumentsCopies(program);
|
insertPhiArgumentsCopies(program);
|
||||||
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
||||||
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
||||||
|
@ -60,7 +59,7 @@ public class RegisterAllocator {
|
||||||
for (int cls : classArray) {
|
for (int cls : classArray) {
|
||||||
maxClass = Math.max(maxClass, cls + 1);
|
maxClass = Math.max(maxClass, cls + 1);
|
||||||
}
|
}
|
||||||
int[] categories = getVariableCategories(program, method.getReference());
|
int[] categories = getVariableCategories(program, method);
|
||||||
String[] names = getVariableNames(program, debuggerFriendly);
|
String[] names = getVariableNames(program, debuggerFriendly);
|
||||||
colorer.colorize(MutableGraphNode.toGraph(interferenceGraph), colors, categories, names);
|
colorer.colorize(MutableGraphNode.toGraph(interferenceGraph), colors, categories, names);
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import org.teavm.cache.AlwaysStaleCacheStatus;
|
import org.teavm.cache.AlwaysStaleCacheStatus;
|
||||||
|
@ -44,6 +45,7 @@ import org.teavm.dependency.DependencyListener;
|
||||||
import org.teavm.dependency.DependencyPlugin;
|
import org.teavm.dependency.DependencyPlugin;
|
||||||
import org.teavm.dependency.Linker;
|
import org.teavm.dependency.Linker;
|
||||||
import org.teavm.dependency.MethodDependency;
|
import org.teavm.dependency.MethodDependency;
|
||||||
|
import org.teavm.dependency.MethodDependencyInfo;
|
||||||
import org.teavm.diagnostics.AccumulationDiagnostics;
|
import org.teavm.diagnostics.AccumulationDiagnostics;
|
||||||
import org.teavm.diagnostics.Diagnostics;
|
import org.teavm.diagnostics.Diagnostics;
|
||||||
import org.teavm.diagnostics.ProblemProvider;
|
import org.teavm.diagnostics.ProblemProvider;
|
||||||
|
@ -52,6 +54,9 @@ import org.teavm.model.ClassHolder;
|
||||||
import org.teavm.model.ClassHolderTransformer;
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
import org.teavm.model.ElementModifier;
|
||||||
|
import org.teavm.model.FieldHolder;
|
||||||
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.ListableClassHolderSource;
|
import org.teavm.model.ListableClassHolderSource;
|
||||||
import org.teavm.model.ListableClassReaderSource;
|
import org.teavm.model.ListableClassReaderSource;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
@ -141,6 +146,10 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
private ProgramDependencyExtractor programDependencyExtractor = new ProgramDependencyExtractor();
|
private ProgramDependencyExtractor programDependencyExtractor = new ProgramDependencyExtractor();
|
||||||
private List<Predicate<MethodReference>> additionalVirtualMethods = new ArrayList<>();
|
private List<Predicate<MethodReference>> additionalVirtualMethods = new ArrayList<>();
|
||||||
private int lastKnownClasses;
|
private int lastKnownClasses;
|
||||||
|
private int compileProgressReportStart;
|
||||||
|
private int compileProgressReportLimit;
|
||||||
|
private int compileProgressLimit;
|
||||||
|
private int compileProgressValue;
|
||||||
|
|
||||||
TeaVM(TeaVMBuilder builder) {
|
TeaVM(TeaVMBuilder builder) {
|
||||||
target = builder.target;
|
target = builder.target;
|
||||||
|
@ -378,63 +387,97 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
cacheStatus.addSynthesizedClasses(dependencyAnalyzer::isSynthesizedClass);
|
cacheStatus.addSynthesizedClasses(dependencyAnalyzer::isSynthesizedClass);
|
||||||
dependencyAnalyzer.setInterruptor(null);
|
dependencyAnalyzer.setInterruptor(null);
|
||||||
|
|
||||||
// Link
|
|
||||||
if (wasCancelled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ListableClassHolderSource classSet = link(dependencyAnalyzer);
|
|
||||||
writtenClasses = classSet;
|
|
||||||
if (wasCancelled()) {
|
if (wasCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimize and allocate registers
|
boolean isLazy = optimizationLevel == TeaVMOptimizationLevel.SIMPLE;
|
||||||
int maxOptimizationProgress = classSet.getClassNames().size();
|
ListableClassHolderSource classSet;
|
||||||
if (optimizationLevel == TeaVMOptimizationLevel.ADVANCED) {
|
if (isLazy) {
|
||||||
maxOptimizationProgress *= 2;
|
initCompileProgress(1000);
|
||||||
} else if (optimizationLevel == TeaVMOptimizationLevel.FULL) {
|
classSet = lazyPipeline();
|
||||||
maxOptimizationProgress *= 3;
|
} else {
|
||||||
}
|
initCompileProgress(500);
|
||||||
reportPhase(TeaVMPhase.OPTIMIZATION, maxOptimizationProgress);
|
classSet = eagerPipeline();
|
||||||
|
|
||||||
int progress = 0;
|
|
||||||
if (optimizationLevel != TeaVMOptimizationLevel.SIMPLE) {
|
|
||||||
progress = devirtualize(progress, classSet, dependencyAnalyzer);
|
|
||||||
if (wasCancelled()) {
|
if (wasCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyAnalyzer.cleanup();
|
|
||||||
progress = inline(progress, classSet, dependencyAnalyzer);
|
|
||||||
if (wasCancelled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
optimize(progress, classSet);
|
|
||||||
if (wasCancelled()) {
|
if (wasCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
try {
|
try {
|
||||||
reportPhase(TeaVMPhase.RENDERING, 1000);
|
if (!isLazy) {
|
||||||
|
compileProgressReportStart = 500;
|
||||||
|
compileProgressReportLimit = 1000;
|
||||||
|
}
|
||||||
target.emit(classSet, buildTarget, outputName);
|
target.emit(classSet, buildTarget, outputName);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Error generating output files", e);
|
throw new RuntimeException("Error generating output files", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initCompileProgress(int limit) {
|
||||||
|
reportPhase(TeaVMPhase.COMPILING, 1000);
|
||||||
|
compileProgressReportStart = 0;
|
||||||
|
compileProgressReportLimit = limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ListableClassHolderSource eagerPipeline() {
|
||||||
|
compileProgressValue = 0;
|
||||||
|
compileProgressLimit = dependencyAnalyzer.getReachableClasses().size();
|
||||||
|
if (optimizationLevel == TeaVMOptimizationLevel.ADVANCED) {
|
||||||
|
compileProgressLimit *= 3;
|
||||||
|
} else if (optimizationLevel == TeaVMOptimizationLevel.FULL) {
|
||||||
|
compileProgressLimit *= 4;
|
||||||
|
} else {
|
||||||
|
compileProgressLimit *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
ListableClassHolderSource classSet = link(dependencyAnalyzer);
|
||||||
|
writtenClasses = classSet;
|
||||||
|
if (wasCancelled()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optimizationLevel != TeaVMOptimizationLevel.SIMPLE) {
|
||||||
|
devirtualize(classSet);
|
||||||
|
if (wasCancelled()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencyAnalyzer.cleanupTypes();
|
||||||
|
|
||||||
|
inline(classSet);
|
||||||
|
if (wasCancelled()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimize and allocate registers
|
||||||
|
optimize(classSet);
|
||||||
|
if (wasCancelled()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return classSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ListableClassHolderSource lazyPipeline() {
|
||||||
|
return new PostProcessingClassHolderSource();
|
||||||
|
}
|
||||||
|
|
||||||
public ListableClassHolderSource link(DependencyAnalyzer dependency) {
|
public ListableClassHolderSource link(DependencyAnalyzer dependency) {
|
||||||
reportPhase(TeaVMPhase.LINKING, dependency.getReachableClasses().size());
|
Linker linker = new Linker(dependency);
|
||||||
Linker linker = new Linker();
|
|
||||||
MutableClassHolderSource cutClasses = new MutableClassHolderSource();
|
MutableClassHolderSource cutClasses = new MutableClassHolderSource();
|
||||||
MissingItemsProcessor missingItemsProcessor = new MissingItemsProcessor(dependency,
|
MissingItemsProcessor missingItemsProcessor = new MissingItemsProcessor(dependency,
|
||||||
dependency.getClassHierarchy(), diagnostics);
|
dependency.getClassHierarchy(), diagnostics);
|
||||||
if (wasCancelled()) {
|
if (wasCancelled()) {
|
||||||
return cutClasses;
|
return cutClasses;
|
||||||
}
|
}
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
if (wasCancelled()) {
|
if (wasCancelled()) {
|
||||||
return cutClasses;
|
return cutClasses;
|
||||||
|
@ -442,14 +485,13 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
|
|
||||||
for (String className : dependency.getReachableClasses()) {
|
for (String className : dependency.getReachableClasses()) {
|
||||||
ClassReader clsReader = dependency.getClassSource().get(className);
|
ClassReader clsReader = dependency.getClassSource().get(className);
|
||||||
if (clsReader == null) {
|
if (clsReader != null) {
|
||||||
continue;
|
ClassHolder cls = ModelUtils.copyClass(clsReader);
|
||||||
|
cutClasses.putClassHolder(cls);
|
||||||
|
missingItemsProcessor.processClass(cls);
|
||||||
|
linker.link(cls);
|
||||||
}
|
}
|
||||||
ClassHolder cls = ModelUtils.copyClass(clsReader);
|
reportCompileProgress(++compileProgressValue);
|
||||||
cutClasses.putClassHolder(cls);
|
|
||||||
missingItemsProcessor.processClass(cls);
|
|
||||||
linker.link(dependency, cls);
|
|
||||||
reportProgress(++index);
|
|
||||||
if (wasCancelled()) {
|
if (wasCancelled()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -469,12 +511,17 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int devirtualize(int progress, ListableClassHolderSource classes, DependencyInfo dependency) {
|
private void reportCompileProgress(int progress) {
|
||||||
|
reportProgress(compileProgressReportStart
|
||||||
|
+ progress * (compileProgressReportLimit - compileProgressReportStart) / compileProgressLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void devirtualize(ListableClassHolderSource classes) {
|
||||||
if (wasCancelled()) {
|
if (wasCancelled()) {
|
||||||
return progress;
|
return;
|
||||||
}
|
}
|
||||||
Devirtualization devirtualization = new Devirtualization(dependency, classes);
|
Devirtualization devirtualization = new Devirtualization(dependencyAnalyzer,
|
||||||
int index = 0;
|
dependencyAnalyzer.getClassHierarchy());
|
||||||
for (String className : classes.getClassNames()) {
|
for (String className : classes.getClassNames()) {
|
||||||
ClassHolder cls = classes.get(className);
|
ClassHolder cls = classes.get(className);
|
||||||
for (MethodHolder method : cls.getMethods()) {
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
|
@ -482,34 +529,33 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
devirtualization.apply(method);
|
devirtualization.apply(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reportProgress(++index);
|
reportCompileProgress(++compileProgressValue);
|
||||||
if (wasCancelled()) {
|
if (wasCancelled()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
virtualMethods = devirtualization.getVirtualMethods();
|
virtualMethods = devirtualization.getVirtualMethods();
|
||||||
return progress;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int inline(int progress, ListableClassHolderSource classes, DependencyInfo dependencyInfo) {
|
private void inline(ListableClassHolderSource classes) {
|
||||||
if (optimizationLevel != TeaVMOptimizationLevel.FULL) {
|
if (optimizationLevel != TeaVMOptimizationLevel.FULL) {
|
||||||
return progress;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<MethodReference, Program> inlinedPrograms = new HashMap<>();
|
Map<MethodReference, Program> inlinedPrograms = new HashMap<>();
|
||||||
Inlining inlining = new Inlining(new ClassHierarchy(classes), dependencyInfo);
|
Inlining inlining = new Inlining(new ClassHierarchy(classes), dependencyAnalyzer);
|
||||||
for (String className : classes.getClassNames()) {
|
for (String className : classes.getClassNames()) {
|
||||||
ClassHolder cls = classes.get(className);
|
ClassHolder cls = classes.get(className);
|
||||||
for (MethodHolder method : cls.getMethods()) {
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
if (method.getProgram() != null) {
|
if (method.getProgram() != null) {
|
||||||
Program program = ProgramUtils.copy(method.getProgram());
|
Program program = ProgramUtils.copy(method.getProgram());
|
||||||
MethodOptimizationContextImpl context = new MethodOptimizationContextImpl(method, classes);
|
MethodOptimizationContextImpl context = new MethodOptimizationContextImpl(method);
|
||||||
inlining.apply(program, method.getReference());
|
inlining.apply(program, method.getReference());
|
||||||
new UnusedVariableElimination().optimize(context, program);
|
new UnusedVariableElimination().optimize(context, program);
|
||||||
inlinedPrograms.put(method.getReference(), program);
|
inlinedPrograms.put(method.getReference(), program);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reportProgress(++progress);
|
reportCompileProgress(++compileProgressValue);
|
||||||
if (wasCancelled()) {
|
if (wasCancelled()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -523,25 +569,22 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return progress;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int optimize(int progress, ListableClassHolderSource classSource) {
|
private void optimize(ListableClassHolderSource classSource) {
|
||||||
for (String className : classSource.getClassNames()) {
|
for (String className : classSource.getClassNames()) {
|
||||||
ClassHolder cls = classSource.get(className);
|
ClassHolder cls = classSource.get(className);
|
||||||
for (MethodHolder method : cls.getMethods()) {
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
processMethod(method, classSource);
|
optimizeMethod(method);
|
||||||
}
|
}
|
||||||
reportProgress(++progress);
|
reportCompileProgress(++compileProgressValue);
|
||||||
if (wasCancelled()) {
|
if (wasCancelled()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return progress;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processMethod(MethodHolder method, ListableClassReaderSource classSource) {
|
private void optimizeMethod(MethodHolder method) {
|
||||||
if (method.getProgram() == null) {
|
if (method.getProgram() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -549,36 +592,8 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
Program optimizedProgram = !cacheStatus.isStaleMethod(method.getReference())
|
Program optimizedProgram = !cacheStatus.isStaleMethod(method.getReference())
|
||||||
? programCache.get(method.getReference(), cacheStatus)
|
? programCache.get(method.getReference(), cacheStatus)
|
||||||
: null;
|
: null;
|
||||||
MethodOptimizationContextImpl context = new MethodOptimizationContextImpl(method, classSource);
|
|
||||||
if (optimizedProgram == null) {
|
if (optimizedProgram == null) {
|
||||||
optimizedProgram = ProgramUtils.copy(method.getProgram());
|
optimizedProgram = optimizeMethodCacheMiss(method, ProgramUtils.copy(method.getProgram()));
|
||||||
target.beforeOptimizations(optimizedProgram, method, classSource);
|
|
||||||
|
|
||||||
if (optimizedProgram.basicBlockCount() > 0) {
|
|
||||||
boolean changed;
|
|
||||||
do {
|
|
||||||
changed = false;
|
|
||||||
for (MethodOptimization optimization : getOptimizations()) {
|
|
||||||
try {
|
|
||||||
changed |= optimization.optimize(context, optimizedProgram);
|
|
||||||
} catch (Exception | AssertionError e) {
|
|
||||||
ListingBuilder listingBuilder = new ListingBuilder();
|
|
||||||
String listing = listingBuilder.buildListing(optimizedProgram, "");
|
|
||||||
System.err.println("Error optimizing program for method " + method.getReference()
|
|
||||||
+ ":\n" + listing);
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (changed);
|
|
||||||
|
|
||||||
target.afterOptimizations(optimizedProgram, method, classSource);
|
|
||||||
if (target.requiresRegisterAllocation()) {
|
|
||||||
RegisterAllocator allocator = new RegisterAllocator();
|
|
||||||
allocator.allocateRegisters(method, optimizedProgram,
|
|
||||||
optimizationLevel == TeaVMOptimizationLevel.SIMPLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Program finalProgram = optimizedProgram;
|
Program finalProgram = optimizedProgram;
|
||||||
programCache.store(method.getReference(), finalProgram,
|
programCache.store(method.getReference(), finalProgram,
|
||||||
() -> programDependencyExtractor.extractDependencies(finalProgram));
|
() -> programDependencyExtractor.extractDependencies(finalProgram));
|
||||||
|
@ -586,13 +601,43 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
method.setProgram(optimizedProgram);
|
method.setProgram(optimizedProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Program optimizeMethodCacheMiss(MethodHolder method, Program optimizedProgram) {
|
||||||
|
target.beforeOptimizations(optimizedProgram, method);
|
||||||
|
|
||||||
|
if (optimizedProgram.basicBlockCount() > 0) {
|
||||||
|
MethodOptimizationContextImpl context = new MethodOptimizationContextImpl(method);
|
||||||
|
boolean changed;
|
||||||
|
do {
|
||||||
|
changed = false;
|
||||||
|
for (MethodOptimization optimization : getOptimizations()) {
|
||||||
|
try {
|
||||||
|
changed |= optimization.optimize(context, optimizedProgram);
|
||||||
|
} catch (Exception | AssertionError e) {
|
||||||
|
ListingBuilder listingBuilder = new ListingBuilder();
|
||||||
|
String listing = listingBuilder.buildListing(optimizedProgram, "");
|
||||||
|
System.err.println("Error optimizing program for method " + method.getReference()
|
||||||
|
+ ":\n" + listing);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (changed);
|
||||||
|
|
||||||
|
target.afterOptimizations(optimizedProgram, method);
|
||||||
|
if (target.requiresRegisterAllocation()) {
|
||||||
|
RegisterAllocator allocator = new RegisterAllocator();
|
||||||
|
allocator.allocateRegisters(method.getReference(), optimizedProgram,
|
||||||
|
optimizationLevel == TeaVMOptimizationLevel.SIMPLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return optimizedProgram;
|
||||||
|
}
|
||||||
|
|
||||||
class MethodOptimizationContextImpl implements MethodOptimizationContext {
|
class MethodOptimizationContextImpl implements MethodOptimizationContext {
|
||||||
private MethodReader method;
|
private MethodReader method;
|
||||||
private ClassReaderSource classSource;
|
|
||||||
|
|
||||||
MethodOptimizationContextImpl(MethodReader method, ClassReaderSource classSource) {
|
MethodOptimizationContextImpl(MethodReader method) {
|
||||||
this.method = method;
|
this.method = method;
|
||||||
this.classSource = classSource;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -604,11 +649,6 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
public DependencyInfo getDependencyInfo() {
|
public DependencyInfo getDependencyInfo() {
|
||||||
return dependencyAnalyzer;
|
return dependencyAnalyzer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClassReaderSource getClassSource() {
|
|
||||||
return classSource;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MethodOptimization> getOptimizations() {
|
private List<MethodOptimization> getOptimizations() {
|
||||||
|
@ -742,8 +782,72 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TeaVMProgressFeedback reportProgress(int progres) {
|
public TeaVMProgressFeedback reportProgress(int progress) {
|
||||||
return progressListener.progressReached(progres);
|
progress = progress * (compileProgressReportLimit - compileProgressReportStart) / 1000
|
||||||
|
+ compileProgressReportStart;
|
||||||
|
return progressListener.progressReached(progress);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PostProcessingClassHolderSource implements ListableClassHolderSource {
|
||||||
|
private Linker linker = new Linker(dependencyAnalyzer);
|
||||||
|
private MissingItemsProcessor missingItemsProcessor = new MissingItemsProcessor(dependencyAnalyzer,
|
||||||
|
dependencyAnalyzer.getClassHierarchy(), diagnostics);
|
||||||
|
private Map<String, ClassHolder> cache = new HashMap<>();
|
||||||
|
private Set<String> classNames = Collections.unmodifiableSet(new HashSet<>(
|
||||||
|
dependencyAnalyzer.getReachableClasses()));
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassHolder get(String name) {
|
||||||
|
return cache.computeIfAbsent(name, className -> {
|
||||||
|
ClassReader classReader = dependencyAnalyzer.getClassSource().get(className);
|
||||||
|
if (classReader == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ClassHolder cls = ModelUtils.copyClass(classReader, false);
|
||||||
|
|
||||||
|
for (FieldHolder field : cls.getFields().toArray(new FieldHolder[0])) {
|
||||||
|
FieldReference fieldRef = new FieldReference(cls.getName(), field.getName());
|
||||||
|
if (dependencyAnalyzer.getField(fieldRef) == null) {
|
||||||
|
cls.removeField(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Function<MethodHolder, Program> programSupplier = method -> {
|
||||||
|
Program program = !cacheStatus.isStaleMethod(method.getReference())
|
||||||
|
? programCache.get(method.getReference(), cacheStatus)
|
||||||
|
: null;
|
||||||
|
if (program == null) {
|
||||||
|
program = ProgramUtils.copy(classReader.getMethod(method.getDescriptor()).getProgram());
|
||||||
|
missingItemsProcessor.processMethod(method.getReference(), program);
|
||||||
|
linker.link(method.getReference(), program);
|
||||||
|
program = optimizeMethodCacheMiss(method, program);
|
||||||
|
Program finalProgram = program;
|
||||||
|
programCache.store(method.getReference(), finalProgram,
|
||||||
|
() -> programDependencyExtractor.extractDependencies(finalProgram));
|
||||||
|
}
|
||||||
|
return program;
|
||||||
|
};
|
||||||
|
for (MethodHolder method : cls.getMethods().toArray(new MethodHolder[0])) {
|
||||||
|
MethodDependencyInfo methodDep = dependencyAnalyzer.getMethod(method.getReference());
|
||||||
|
if (methodDep == null) {
|
||||||
|
cls.removeMethod(method);
|
||||||
|
} else if (!methodDep.isUsed()) {
|
||||||
|
method.getModifiers().add(ElementModifier.ABSTRACT);
|
||||||
|
} else {
|
||||||
|
MethodReader methodReader = classReader.getMethod(method.getDescriptor());
|
||||||
|
if (methodReader != null && methodReader.getProgram() != null) {
|
||||||
|
method.setProgramSupplier(programSupplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cls;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getClassNames() {
|
||||||
|
return classNames;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,5 @@ package org.teavm.vm;
|
||||||
|
|
||||||
public enum TeaVMPhase {
|
public enum TeaVMPhase {
|
||||||
DEPENDENCY_ANALYSIS,
|
DEPENDENCY_ANALYSIS,
|
||||||
LINKING,
|
COMPILING
|
||||||
OPTIMIZATION,
|
|
||||||
RENDERING
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ import org.teavm.dependency.DependencyAnalyzer;
|
||||||
import org.teavm.dependency.DependencyListener;
|
import org.teavm.dependency.DependencyListener;
|
||||||
import org.teavm.model.ClassHolderTransformer;
|
import org.teavm.model.ClassHolderTransformer;
|
||||||
import org.teavm.model.ListableClassHolderSource;
|
import org.teavm.model.ListableClassHolderSource;
|
||||||
import org.teavm.model.ListableClassReaderSource;
|
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.vm.spi.TeaVMHostExtension;
|
import org.teavm.vm.spi.TeaVMHostExtension;
|
||||||
|
@ -39,9 +38,9 @@ public interface TeaVMTarget {
|
||||||
|
|
||||||
void contributeDependencies(DependencyAnalyzer dependencyAnalyzer);
|
void contributeDependencies(DependencyAnalyzer dependencyAnalyzer);
|
||||||
|
|
||||||
void beforeOptimizations(Program program, MethodReader method, ListableClassReaderSource classSource);
|
void beforeOptimizations(Program program, MethodReader method);
|
||||||
|
|
||||||
void afterOptimizations(Program program, MethodReader method, ListableClassReaderSource classSource);
|
void afterOptimizations(Program program, MethodReader method);
|
||||||
|
|
||||||
void emit(ListableClassHolderSource classes, BuildTarget buildTarget, String outputName) throws IOException;
|
void emit(ListableClassHolderSource classes, BuildTarget buildTarget, String outputName) throws IOException;
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ import org.junit.Test;
|
||||||
import org.junit.rules.TestName;
|
import org.junit.rules.TestName;
|
||||||
import org.teavm.dependency.DependencyInfo;
|
import org.teavm.dependency.DependencyInfo;
|
||||||
import org.teavm.model.ClassHolder;
|
import org.teavm.model.ClassHolder;
|
||||||
import org.teavm.model.ClassReaderSource;
|
|
||||||
import org.teavm.model.ListingParseUtils;
|
import org.teavm.model.ListingParseUtils;
|
||||||
import org.teavm.model.MethodHolder;
|
import org.teavm.model.MethodHolder;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
|
@ -111,11 +110,6 @@ public class ScalarReplacementTest {
|
||||||
public DependencyInfo getDependencyInfo() {
|
public DependencyInfo getDependencyInfo() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClassReaderSource getClassSource() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
new ScalarReplacement().optimize(context, program);
|
new ScalarReplacement().optimize(context, program);
|
||||||
|
|
|
@ -426,14 +426,8 @@ public final class TeaVMRunner {
|
||||||
case DEPENDENCY_ANALYSIS:
|
case DEPENDENCY_ANALYSIS:
|
||||||
System.out.print("Analyzing classes...");
|
System.out.print("Analyzing classes...");
|
||||||
break;
|
break;
|
||||||
case LINKING:
|
case COMPILING:
|
||||||
System.out.print("Linking methods...");
|
System.out.print("Compiling...");
|
||||||
break;
|
|
||||||
case OPTIMIZATION:
|
|
||||||
System.out.print("Optimizing code...");
|
|
||||||
break;
|
|
||||||
case RENDERING:
|
|
||||||
System.out.print("Generating output...");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
currentPhase = phase;
|
currentPhase = phase;
|
||||||
|
|
|
@ -981,18 +981,10 @@ public class CodeServlet extends HttpServlet {
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case DEPENDENCY_ANALYSIS:
|
case DEPENDENCY_ANALYSIS:
|
||||||
start = 0;
|
start = 0;
|
||||||
end = 400;
|
|
||||||
break;
|
|
||||||
case LINKING:
|
|
||||||
start = 400;
|
|
||||||
end = 500;
|
end = 500;
|
||||||
break;
|
break;
|
||||||
case OPTIMIZATION:
|
case COMPILING:
|
||||||
start = 500;
|
start = 500;
|
||||||
end = 750;
|
|
||||||
break;
|
|
||||||
case RENDERING:
|
|
||||||
start = 750;
|
|
||||||
end = 1000;
|
end = 1000;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,12 +180,8 @@ class TeaVMBuild {
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case DEPENDENCY_ANALYSIS:
|
case DEPENDENCY_ANALYSIS:
|
||||||
return "Discovering classes to compile";
|
return "Discovering classes to compile";
|
||||||
case LINKING:
|
case COMPILING:
|
||||||
return "Resolving method invocations";
|
return "Compiling";
|
||||||
case OPTIMIZATION:
|
|
||||||
return "Optimizing code";
|
|
||||||
case RENDERING:
|
|
||||||
return "Building JS file";
|
|
||||||
default:
|
default:
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user