# HG changeset patch # User Christian Humer # Date 1450446066 -3600 # Node ID 687bc1dda1258d252dfe13658a2b6bab1457072e # Parent d51cc0af8612e491738e5662261f006f0590f41e Truffle-DSL: fix wrong resolution when multiple public static methods are imported from a cached type. diff -r d51cc0af8612 -r 687bc1dda125 truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java --- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java Fri Dec 18 14:47:13 2015 +0100 +++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java Fri Dec 18 14:41:06 2015 +0100 @@ -310,6 +310,30 @@ } @NodeChild + static class TestCachedWithProfile extends ValueNode { + + @Specialization + static int do1(int value, @Cached("create()") MySubClass mySubclass) { + return 42; + } + } + + public static class MyClass { + + public static MyClass create() { + return new MyClass(); + } + } + + public static class MySubClass extends MyClass { + + public static MySubClass create() { + return new MySubClass(); + } + + } + + @NodeChild static class TestCachesOrder extends ValueNode { @Specialization(guards = "boundByGuard != 0") diff -r d51cc0af8612 -r 687bc1dda125 truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java --- a/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Fri Dec 18 14:47:13 2015 +0100 +++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java Fri Dec 18 14:41:06 2015 +0100 @@ -1055,6 +1055,20 @@ return 0; } + public static int compareByTypeHierarchy(TypeMirror t1, Set t1SuperSet, TypeMirror t2, Set t2SuperSet) { + if (typeEquals(t1, t2)) { + return 0; + } + if (t1SuperSet.contains(getQualifiedName(t2))) { + return -1; + } + + if (t2SuperSet.contains(getQualifiedName(t1))) { + return 1; + } + return 0; + } + public static boolean canThrowType(List thrownTypes, TypeMirror exceptionType) { if (ElementUtils.containsType(thrownTypes, exceptionType)) { return true; diff -r d51cc0af8612 -r 687bc1dda125 truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java --- a/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Fri Dec 18 14:47:13 2015 +0100 +++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java Fri Dec 18 14:41:06 2015 +0100 @@ -22,6 +22,35 @@ */ package com.oracle.truffle.dsl.processor.parser; +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; +import javax.tools.Diagnostic.Kind; + import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.CreateCast; @@ -67,34 +96,6 @@ import com.oracle.truffle.dsl.processor.model.TemplateMethod; import com.oracle.truffle.dsl.processor.model.TypeSystemData; -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; -import javax.lang.model.type.DeclaredType; -import javax.lang.model.type.TypeKind; -import javax.lang.model.type.TypeMirror; -import javax.lang.model.util.ElementFilter; -import javax.tools.Diagnostic.Kind; - @DSLOptions public class NodeParser extends AbstractParser { @@ -354,6 +355,7 @@ TypeElement typeElement = ElementUtils.fromTypeMirror(context.reloadType(importGuardClass.asType())); List members = new ArrayList<>(); + for (Element importElement : processingEnv.getElementUtils().getAllMembers(typeElement)) { if (!importElement.getModifiers().contains(Modifier.PUBLIC)) { continue; @@ -372,6 +374,36 @@ members.add(importElement); } } + + /* + * Sort elements by enclosing type to ensure that duplicate static methods are used from the + * most concrete subtype. + */ + Collections.sort(members, new Comparator() { + Map> cachedQualifiedNames = new HashMap<>(); + + public int compare(Element o1, Element o2) { + TypeMirror e1 = o1.getEnclosingElement() != null ? o1.getEnclosingElement().asType() : null; + TypeMirror e2 = o2.getEnclosingElement() != null ? o2.getEnclosingElement().asType() : null; + + Set e1SuperTypes = getCachedSuperTypes(e1); + Set e2SuperTypes = getCachedSuperTypes(e2); + return ElementUtils.compareByTypeHierarchy(e1, e1SuperTypes, e2, e2SuperTypes); + } + + private Set getCachedSuperTypes(TypeMirror e) { + if (e == null) { + return Collections.emptySet(); + } + Set superTypes = cachedQualifiedNames.get(e); + if (superTypes == null) { + superTypes = new HashSet<>(ElementUtils.getQualifiedSuperTypeNames(ElementUtils.fromTypeMirror(e))); + cachedQualifiedNames.put(e, superTypes); + } + return superTypes; + } + }); + return members; }