Add switch to log devirtualization process

This commit is contained in:
Alexey Andreev 2021-02-26 12:26:13 +03:00
parent 0eca9d95e1
commit e4c808c324
2 changed files with 62 additions and 1 deletions

View File

@ -34,22 +34,38 @@ import org.teavm.model.instructions.InvocationType;
import org.teavm.model.instructions.InvokeInstruction; import org.teavm.model.instructions.InvokeInstruction;
public class Devirtualization { public class Devirtualization {
static final boolean shouldLog = System.getProperty("org.teavm.logDevirtualization", "false").equals("true");
private DependencyInfo dependency; private DependencyInfo dependency;
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);
private int virtualCallSites;
private int directCallSites;
public Devirtualization(DependencyInfo dependency, ClassHierarchy hierarchy) { public Devirtualization(DependencyInfo dependency, ClassHierarchy hierarchy) {
this.dependency = dependency; this.dependency = dependency;
this.hierarchy = hierarchy; this.hierarchy = hierarchy;
} }
public int getVirtualCallSites() {
return virtualCallSites;
}
public int getDirectCallSites() {
return directCallSites;
}
public void apply(MethodHolder method) { public void apply(MethodHolder method) {
MethodDependencyInfo methodDep = dependency.getMethod(method.getReference()); MethodDependencyInfo methodDep = dependency.getMethod(method.getReference());
if (methodDep == null) { if (methodDep == null) {
return; return;
} }
Program program = method.getProgram(); Program program = method.getProgram();
if (shouldLog) {
System.out.println("DEVIRTUALIZATION running at " + method.getReference());
}
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) {
@ -64,13 +80,46 @@ public class Devirtualization {
Set<MethodReference> implementations = getImplementations(var.getTypes(), Set<MethodReference> implementations = getImplementations(var.getTypes(),
invoke.getMethod()); invoke.getMethod());
if (implementations.size() == 1) { if (implementations.size() == 1) {
MethodReference resolvedImplementaiton = implementations.iterator().next();
if (shouldLog) {
System.out.print("DIRECT CALL " + invoke.getMethod() + " resolved to "
+ resolvedImplementaiton.getClassName());
if (insn.getLocation() != null) {
System.out.print(" at " + insn.getLocation().getFileName() + ":"
+ insn.getLocation().getLine());
}
System.out.println();
}
invoke.setType(InvocationType.SPECIAL); invoke.setType(InvocationType.SPECIAL);
invoke.setMethod(implementations.iterator().next()); invoke.setMethod(resolvedImplementaiton);
directCallSites++;
} else { } else {
virtualMethods.addAll(implementations); virtualMethods.addAll(implementations);
if (shouldLog) {
System.out.print("VIRTUAL CALL " + invoke.getMethod() + " resolved to [");
boolean first = true;
for (MethodReference impl : implementations) {
if (!first) {
System.out.print(", ");
}
first = false;
System.out.print(impl.getClassName());
}
System.out.print("]");
if (insn.getLocation() != null) {
System.out.print(" at " + insn.getLocation().getFileName() + ":"
+ insn.getLocation().getLine());
}
System.out.println();
}
virtualCallSites++;
} }
} }
} }
if (shouldLog) {
System.out.println("DEVIRTUALIZATION complete for " + method.getReference());
}
} }
private Set<MethodReference> getImplementations(String[] classNames, MethodReference ref) { private Set<MethodReference> getImplementations(String[] classNames, MethodReference ref) {

View File

@ -603,6 +603,12 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
if (wasCancelled()) { if (wasCancelled()) {
return; return;
} }
boolean shouldLog = System.getProperty("org.teavm.logDevirtualization", "false").equals("true");
if (shouldLog) {
System.out.println("Running devirtualization");
}
Devirtualization devirtualization = new Devirtualization(dependencyAnalyzer, Devirtualization devirtualization = new Devirtualization(dependencyAnalyzer,
dependencyAnalyzer.getClassHierarchy()); dependencyAnalyzer.getClassHierarchy());
for (String className : classes.getClassNames()) { for (String className : classes.getClassNames()) {
@ -618,6 +624,12 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
} }
} }
virtualMethods = devirtualization.getVirtualMethods(); virtualMethods = devirtualization.getVirtualMethods();
if (shouldLog) {
System.out.println("Devirtualization complete");
System.out.println("Virtual calls: " + devirtualization.getVirtualCallSites());
System.out.println("Direct calls: " + devirtualization.getDirectCallSites());
}
} }
private void inline(ListableClassHolderSource classes) { private void inline(ListableClassHolderSource classes) {