changeset 16751:4f589fa69b9c

Truffle-DSL: added shared code required for the new generation layout.
author Christian Humer <christian.humer@gmail.com>
date Mon, 11 Aug 2014 15:53:05 +0200
parents 7b196e1c3fa0
children 0e05342037d7
files graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLMetadata.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLNode.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLShare.java graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/NodeFactoryBase.java
diffstat 4 files changed, 287 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLMetadata.java	Mon Aug 11 15:53:05 2014 +0200
@@ -0,0 +1,51 @@
+package com.oracle.truffle.api.dsl.internal;
+
+/**
+ * This is NOT public API. Do not use directly. This code may change without notice.
+ */
+public final class DSLMetadata {
+
+    public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[]{};
+    public static final DSLMetadata NONE = new DSLMetadata(null, EMPTY_CLASS_ARRAY, EMPTY_CLASS_ARRAY, EMPTY_CLASS_ARRAY, 0, 0);
+
+    private final Class<?> specializationClass;
+    private final Class<?>[] includes;
+    private final Class<?>[] excludedBy;
+    private final Class<?>[] specializedTypes;
+
+    private final int costs;
+    private final int order;
+
+    public DSLMetadata(Class<?> specializationClass, Class<?>[] includes, Class<?>[] excludes, Class<?>[] specializedTypes, int costs, int order) {
+        this.specializationClass = specializationClass;
+        this.includes = includes;
+        this.excludedBy = excludes;
+        this.specializedTypes = specializedTypes;
+        this.costs = costs;
+        this.order = order;
+    }
+
+    public Class<?> getSpecializationClass() {
+        return specializationClass;
+    }
+
+    public Class<?>[] getSpecializedTypes() {
+        return specializedTypes;
+    }
+
+    Class<?>[] getIncludes() {
+        return includes;
+    }
+
+    Class<?>[] getExcludedBy() {
+        return excludedBy;
+    }
+
+    int getCosts() {
+        return costs;
+    }
+
+    int getOrder() {
+        return order;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLNode.java	Mon Aug 11 15:53:05 2014 +0200
@@ -0,0 +1,18 @@
+package com.oracle.truffle.api.dsl.internal;
+
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This is NOT public API. Do not use directly. This code may change without notice.
+ */
+public interface DSLNode {
+
+    DSLMetadata getMetadata0();
+
+    void adoptChildren0(Node other, Node next);
+
+    void updateTypes0(Class<?>[] types);
+
+    Node getNext0();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/DSLShare.java	Mon Aug 11 15:53:05 2014 +0200
@@ -0,0 +1,176 @@
+package com.oracle.truffle.api.dsl.internal;
+
+import java.util.*;
+
+import com.oracle.truffle.api.nodes.*;
+
+/** Contains utility classes shared across generated DSLNode implementations. */
+public class DSLShare {
+
+    public static boolean isExcluded(Node currentNode, DSLMetadata otherMetadata) {
+        assert otherMetadata.getExcludedBy().length > 0 : "At least one exclude must be defined for isIncluded.";
+        Node cur = findRoot(currentNode);
+        while (cur != null) {
+            Class<?> curClass = cur.getClass();
+            if (curClass == otherMetadata.getSpecializationClass()) {
+                return true;
+            } else if (containsClass(otherMetadata.getExcludedBy(), cur)) {
+                return true;
+            }
+            cur = getNext(cur);
+        }
+        return false;
+    }
+
+    private static boolean includes(Node oldNode, DSLNode newNode) {
+        return containsClass(newNode.getMetadata0().getIncludes(), oldNode);
+    }
+
+    public static <T extends Node & DSLNode> T rewrite(Node thisNode, T newNode, String message) {
+        assert newNode != null;
+        if (getNext(thisNode) != null || getPrevious(thisNode) != null) {
+            // already polymorphic -> append
+            return appendPolymorphic(findUninitialized(thisNode), newNode);
+        } else if (includes(thisNode, newNode)) {
+            // included -> remains monomorphic
+            newNode.adoptChildren0(thisNode, null);
+            return thisNode.replace(newNode, message);
+        } else {
+            // goto polymorphic
+            return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T extends Node> T findRoot(T node) {
+        Node prev = node;
+        Node cur;
+        do {
+            cur = prev;
+            prev = getPrevious(cur);
+        } while (prev != null);
+        return (T) cur;
+    }
+
+    private static Node findUninitialized(Node node) {
+        Node next = node;
+        Node cur;
+        do {
+            cur = next;
+            next = getNext(cur);
+        } while (next != null);
+        return cur;
+    }
+
+    public static <T extends Node & DSLNode> T rewriteUninitialized(Node uninitialized, T newNode) {
+        Node prev = getPrevious(uninitialized);
+        if (prev == null) {
+            newNode.adoptChildren0(uninitialized, null);
+            return uninitialized.replace(newNode, "Uninitialized monomorphic");
+        } else {
+            return appendPolymorphic(uninitialized, newNode);
+        }
+    }
+
+    public static <T extends Node & DSLNode> T rewriteToPolymorphic(Node oldNode, DSLNode uninitialized, T polymorphic, DSLNode currentCopy, DSLNode newNode, String message) {
+        assert getNext(oldNode) == null;
+        assert getPrevious(oldNode) == null;
+
+        polymorphic.adoptChildren0(oldNode, (Node) currentCopy);
+
+        if (newNode == null) {
+            // fallback
+            currentCopy.adoptChildren0(null, (Node) uninitialized);
+        } else {
+            // new specialization
+            newNode.adoptChildren0(null, (Node) uninitialized);
+            currentCopy.adoptChildren0(null, (Node) newNode);
+        }
+
+        oldNode.replace(polymorphic, message);
+
+        assert polymorphic.getNext0() == currentCopy;
+        assert newNode != null ? currentCopy.getNext0() == newNode : currentCopy.getNext0() == uninitialized;
+        assert uninitialized.getNext0() == null;
+        return polymorphic;
+    }
+
+    private static Class<?>[] mergeTypes(DSLNode node, Class<?>[] types) {
+        Class<?>[] specializedTypes = node.getMetadata0().getSpecializedTypes();
+        if (specializedTypes.length == 0) {
+            return null;
+        } else if (types == null) {
+            return Arrays.copyOf(specializedTypes, specializedTypes.length);
+        } else {
+            for (int i = 0; i < specializedTypes.length; i++) {
+                if (specializedTypes[i] != types[i]) {
+                    types[i] = Object.class;
+                }
+            }
+            return types;
+        }
+    }
+
+    private static <T extends Node & DSLNode> T appendPolymorphic(Node uninitialized, T newNode) {
+        Class<?>[] includes = newNode.getMetadata0().getIncludes();
+        Node cur = getPrevious(uninitialized);
+        Node prev = uninitialized;
+        int depth = 0;
+        Class<?>[] types = null;
+        while (cur != null) {
+            if (containsClass(includes, cur)) {
+                cur.replace(prev, "Included in other specialization");
+                cur = prev;
+            } else {
+                depth++;
+                types = mergeTypes((DSLNode) cur, types);
+            }
+            prev = cur;
+            cur = getPrevious(cur);
+        }
+        assert prev.getCost() == NodeCost.POLYMORPHIC;
+
+        if (depth == 0) {
+            newNode.adoptChildren0(prev, null);
+            return prev.replace(newNode, "Polymorphic to monomorphic.");
+        } else {
+            newNode.adoptChildren0(null, uninitialized);
+            ((DSLNode) prev).updateTypes0(mergeTypes(newNode, types));
+            return uninitialized.replace(newNode, "Appended polymorphic");
+        }
+    }
+
+    private static boolean containsClass(Class<?>[] classList, Node node) {
+        Class<?> nodeClass = node.getClass();
+        for (Class<?> toCheck : classList) {
+            if (nodeClass == toCheck) {
+                if (node.getCost() == NodeCost.UNINITIALIZED) {
+                    /*
+                     * In case a specialization is excluded by the fallback specialization the
+                     * uninitialized class is used as exclusion class. Because the fallback field in
+                     * the uninitialized specialization is not accessible we use the costs to check
+                     * if the fallback was reached or not. In case the fallback was reached in the
+                     * uninitialized version the cost is MONOMORPHIC, otherwise it is UNINITIALIZED.
+                     */
+                    continue;
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static Node getNext(Node node) {
+        return ((DSLNode) node).getNext0();
+    }
+
+    private static Node getPrevious(Node node) {
+        Node parent = node.getParent();
+        if (parent instanceof DSLNode && getNext(parent) == node) {
+            return parent;
+        } else {
+            return null;
+        }
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/internal/NodeFactoryBase.java	Mon Aug 11 15:53:05 2014 +0200
@@ -0,0 +1,42 @@
+package com.oracle.truffle.api.dsl.internal;
+
+import java.util.*;
+
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.nodes.*;
+
+/**
+ * This is NOT public API. Do not use directly. This code may change without notice.
+ */
+public abstract class NodeFactoryBase<T> implements NodeFactory<T> {
+
+    private final Class<T> nodeClass;
+    private final Class<?>[][] nodeSignatures;
+    private final Class<? extends Node>[] executionSignatures;
+
+    @SuppressWarnings("unchecked")
+    public NodeFactoryBase(Class<T> nodeClass, Class<?>[] executionSignatures, Class<?>[][] nodeSignatures) {
+        this.nodeClass = nodeClass;
+        this.nodeSignatures = nodeSignatures;
+        this.executionSignatures = (Class<? extends Node>[]) executionSignatures;
+    }
+
+    public abstract T createNode(Object... arguments);
+
+    public final Class<T> getNodeClass() {
+        return nodeClass;
+    }
+
+    public final List<List<Class<?>>> getNodeSignatures() {
+        List<List<Class<?>>> signatures = new ArrayList<>();
+        for (int i = 0; i < nodeSignatures.length; i++) {
+            signatures.add(Arrays.asList(nodeSignatures[i]));
+        }
+        return signatures;
+    }
+
+    public final List<Class<? extends Node>> getExecutionSignature() {
+        return Arrays.asList(executionSignatures);
+    }
+
+}