Mercurial > hg > truffle
changeset 22516:687bc1dda125
Truffle-DSL: fix wrong resolution when multiple public static methods are imported from a cached type.
author | Christian Humer <christian.humer@oracle.com> |
---|---|
date | Fri, 18 Dec 2015 14:41:06 +0100 |
parents | d51cc0af8612 |
children | 60c68f691534 |
files | truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/CachedTest.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java |
diffstat | 3 files changed, 98 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- 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")
--- 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<String> t1SuperSet, TypeMirror t2, Set<String> 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<? extends TypeMirror> thrownTypes, TypeMirror exceptionType) { if (ElementUtils.containsType(thrownTypes, exceptionType)) { return true;
--- 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<NodeData> { @@ -354,6 +355,7 @@ TypeElement typeElement = ElementUtils.fromTypeMirror(context.reloadType(importGuardClass.asType())); List<Element> 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<Element>() { + Map<TypeMirror, Set<String>> 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<String> e1SuperTypes = getCachedSuperTypes(e1); + Set<String> e2SuperTypes = getCachedSuperTypes(e2); + return ElementUtils.compareByTypeHierarchy(e1, e1SuperTypes, e2, e2SuperTypes); + } + + private Set<String> getCachedSuperTypes(TypeMirror e) { + if (e == null) { + return Collections.emptySet(); + } + Set<String> superTypes = cachedQualifiedNames.get(e); + if (superTypes == null) { + superTypes = new HashSet<>(ElementUtils.getQualifiedSuperTypeNames(ElementUtils.fromTypeMirror(e))); + cachedQualifiedNames.put(e, superTypes); + } + return superTypes; + } + }); + return members; }