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;
     }