diff --git a/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java b/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java index f66b9db8b..dd5046ec4 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java +++ b/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java @@ -158,8 +158,8 @@ public class JavascriptBuilder implements JavascriptBuilderHost { Linker linker = new Linker(dependencyChecker); ListableClassHolderSource classSet = linker.link(classSource); Decompiler decompiler = new Decompiler(classSet, classLoader, executor); - /*devirtualize(classSet, dependencyChecker); - executor.complete();*/ + devirtualize(classSet, dependencyChecker); + executor.complete(); ClassSetOptimizer optimizer = new ClassSetOptimizer(executor); optimizer.optimizeAll(classSet); executor.complete(); @@ -199,7 +199,6 @@ public class JavascriptBuilder implements JavascriptBuilderHost { } // TODO: repair devirtualization - @SuppressWarnings("unused") private void devirtualize(ListableClassHolderSource classes, DependencyInfo dependency) { final Devirtualization devirtualization = new Devirtualization(dependency, classes); for (String className : classes.getClassNames()) { diff --git a/teavm-core/src/main/java/org/teavm/optimization/Devirtualization.java b/teavm-core/src/main/java/org/teavm/optimization/Devirtualization.java index 69f9182cb..4bec24cfa 100644 --- a/teavm-core/src/main/java/org/teavm/optimization/Devirtualization.java +++ b/teavm-core/src/main/java/org/teavm/optimization/Devirtualization.java @@ -55,7 +55,7 @@ public class Devirtualization { } ValueDependencyInfo var = methodDep.getVariable(invoke.getInstance().getIndex()); Set implementations = getImplementations(var.getTypes(), - invoke.getMethod().getDescriptor()); + invoke.getMethod()); if (implementations.size() == 1) { invoke.setType(InvocationType.SPECIAL); invoke.setMethod(implementations.iterator().next()); @@ -64,14 +64,37 @@ public class Devirtualization { } } - private Set getImplementations(String[] classNames, MethodDescriptor desc) { + private Set getImplementations(String[] classNames, MethodReference ref) { Set methods = new HashSet<>(); for (String className : classNames) { ClassReader cls = classSource.get(className); - if (cls != null && cls.getMethod(desc) != null) { - methods.add(new MethodReference(className, desc)); + if (cls == null || !isAssignable(ref.getClassName(), cls)) { + break; + } + MethodDependencyInfo methodDep = dependency.getMethod(new MethodReference(className, ref.getDescriptor())); + if (methodDep != null) { + methods.add(methodDep.getReference()); } } return methods; } + + private boolean isAssignable(String target, ClassReader cls) { + if (cls.getName().equals(target)) { + return true; + } + if (cls.getParent() != null) { + ClassReader parent = classSource.get(cls.getParent()); + if (parent != null && isAssignable(target, parent)) { + return true; + } + } + for (String ifaceName : cls.getInterfaces()) { + ClassReader iface = classSource.get(ifaceName); + if (iface != null && isAssignable(target, iface)) { + return true; + } + } + return false; + } } diff --git a/teavm-html4j/pom.xml b/teavm-html4j/pom.xml index 0e6ff5096..3990ca7bc 100644 --- a/teavm-html4j/pom.xml +++ b/teavm-html4j/pom.xml @@ -85,7 +85,7 @@ process-test-classes - true + false 1 true ${project.build.directory}/javascript-tck