Mercurial > hg > graal-compiler
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); + } + +}