diff --git a/core/src/main/java/org/teavm/model/optimization/Devirtualization.java b/core/src/main/java/org/teavm/model/optimization/Devirtualization.java index c67f3b5f7..6cf8ebebe 100644 --- a/core/src/main/java/org/teavm/model/optimization/Devirtualization.java +++ b/core/src/main/java/org/teavm/model/optimization/Devirtualization.java @@ -34,22 +34,38 @@ import org.teavm.model.instructions.InvocationType; import org.teavm.model.instructions.InvokeInstruction; public class Devirtualization { + static final boolean shouldLog = System.getProperty("org.teavm.logDevirtualization", "false").equals("true"); private DependencyInfo dependency; private ClassHierarchy hierarchy; private Set virtualMethods = new HashSet<>(); private Set readonlyVirtualMethods = Collections.unmodifiableSet(virtualMethods); + private int virtualCallSites; + private int directCallSites; public Devirtualization(DependencyInfo dependency, ClassHierarchy hierarchy) { this.dependency = dependency; this.hierarchy = hierarchy; } + public int getVirtualCallSites() { + return virtualCallSites; + } + + public int getDirectCallSites() { + return directCallSites; + } + public void apply(MethodHolder method) { MethodDependencyInfo methodDep = dependency.getMethod(method.getReference()); if (methodDep == null) { return; } Program program = method.getProgram(); + + if (shouldLog) { + System.out.println("DEVIRTUALIZATION running at " + method.getReference()); + } + for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlock block = program.basicBlockAt(i); for (Instruction insn : block) { @@ -64,13 +80,46 @@ public class Devirtualization { Set implementations = getImplementations(var.getTypes(), invoke.getMethod()); 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.setMethod(implementations.iterator().next()); + invoke.setMethod(resolvedImplementaiton); + directCallSites++; } else { 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 getImplementations(String[] classNames, MethodReference ref) { diff --git a/core/src/main/java/org/teavm/vm/TeaVM.java b/core/src/main/java/org/teavm/vm/TeaVM.java index a4ddb7cda..fef5d87de 100644 --- a/core/src/main/java/org/teavm/vm/TeaVM.java +++ b/core/src/main/java/org/teavm/vm/TeaVM.java @@ -603,6 +603,12 @@ public class TeaVM implements TeaVMHost, ServiceRepository { if (wasCancelled()) { return; } + + boolean shouldLog = System.getProperty("org.teavm.logDevirtualization", "false").equals("true"); + if (shouldLog) { + System.out.println("Running devirtualization"); + } + Devirtualization devirtualization = new Devirtualization(dependencyAnalyzer, dependencyAnalyzer.getClassHierarchy()); for (String className : classes.getClassNames()) { @@ -618,6 +624,12 @@ public class TeaVM implements TeaVMHost, ServiceRepository { } } 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) {