Mercurial > hg > truffle
diff truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java @ 21951:9c8c0937da41
Moving all sources into truffle subdirectory
author | Jaroslav Tulach <jaroslav.tulach@oracle.com> |
---|---|
date | Wed, 17 Jun 2015 10:58:08 +0200 |
parents | graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java@8e5f9310f3aa |
children | dc83cc1f94f2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/NodeData.java Wed Jun 17 10:58:08 2015 +0200 @@ -0,0 +1,599 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.dsl.processor.model; + +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.dsl.processor.*; +import com.oracle.truffle.dsl.processor.java.*; +import com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality; + +public class NodeData extends Template implements Comparable<NodeData> { + + private final String nodeId; + private final String shortName; + private final List<NodeData> enclosingNodes = new ArrayList<>(); + private NodeData declaringNode; + + private final TypeSystemData typeSystem; + private final List<NodeChildData> children; + private final List<NodeExecutionData> childExecutions; + private final List<NodeFieldData> fields; + + private ParameterSpec instanceParameterSpec; + + private final List<SpecializationData> specializations = new ArrayList<>(); + private final List<ShortCircuitData> shortCircuits = new ArrayList<>(); + private final List<CreateCastData> casts = new ArrayList<>(); + private final List<ExecutableTypeData> executableTypes = new ArrayList<>(); + + private final NodeExecutionData thisExecution; + private final boolean generateFactory; + + private TypeMirror frameType; + + public NodeData(ProcessorContext context, TypeElement type, String shortName, TypeSystemData typeSystem, boolean generateFactory) { + super(context, type, null); + this.nodeId = ElementUtils.getSimpleName(type); + this.shortName = shortName; + this.typeSystem = typeSystem; + this.fields = new ArrayList<>(); + this.children = new ArrayList<>(); + this.childExecutions = new ArrayList<>(); + this.thisExecution = new NodeExecutionData(new NodeChildData(null, null, "this", getNodeType(), getNodeType(), null, Cardinality.ONE), -1, -1, false); + this.thisExecution.getChild().setNode(this); + this.generateFactory = generateFactory; + } + + public NodeData(ProcessorContext context, TypeElement type) { + this(context, type, null, null, false); + } + + public boolean isGenerateFactory() { + return generateFactory; + } + + public NodeExecutionData getThisExecution() { + return thisExecution; + } + + public boolean isFallbackReachable() { + SpecializationData generic = getGenericSpecialization(); + if (generic != null) { + return generic.isReachable(); + } + return false; + } + + public void setFrameType(TypeMirror frameType) { + this.frameType = frameType; + } + + public TypeMirror getFrameType() { + return frameType; + } + + public void addEnclosedNode(NodeData node) { + this.enclosingNodes.add(node); + node.declaringNode = this; + } + + public List<NodeExecutionData> getChildExecutions() { + return childExecutions; + } + + public Set<TypeMirror> findSpecializedTypes(NodeExecutionData execution) { + Set<TypeMirror> types = new HashSet<>(); + for (SpecializationData specialization : getSpecializations()) { + if (!specialization.isSpecialized()) { + continue; + } + List<Parameter> parameters = specialization.findByExecutionData(execution); + for (Parameter parameter : parameters) { + TypeMirror type = parameter.getType(); + if (type == null) { + throw new AssertionError(); + } + types.add(type); + } + } + return types; + } + + public Collection<TypeMirror> findSpecializedReturnTypes() { + Set<TypeMirror> types = new HashSet<>(); + for (SpecializationData specialization : getSpecializations()) { + if (!specialization.isSpecialized()) { + continue; + } + types.add(specialization.getReturnType().getType()); + } + return types; + } + + public int getExecutionCount() { + return getChildExecutions().size(); + } + + public int getSignatureSize() { + int count = 0; + for (NodeExecutionData execution : getChildExecutions()) { + if (execution.isShortCircuit()) { + count++; + } + count++; + } + return count; + } + + public boolean isFrameUsedByAnyGuard() { + for (SpecializationData specialization : specializations) { + if (!specialization.isReachable()) { + continue; + } + Parameter frame = specialization.getFrame(); + if (frame != null) { + for (GuardExpression guard : specialization.getGuards()) { + if (guard.getExpression().findBoundVariableElements().contains(frame.getVariableElement())) { + return true; + } + } + for (CacheExpression cache : specialization.getCaches()) { + if (cache.getExpression().findBoundVariableElements().contains(frame.getVariableElement())) { + return true; + } + } + } + } + return false; + } + + public List<CreateCastData> getCasts() { + return casts; + } + + public String getShortName() { + return shortName; + } + + public List<NodeFieldData> getFields() { + return fields; + } + + @Override + protected List<MessageContainer> findChildContainers() { + List<MessageContainer> containerChildren = new ArrayList<>(); + if (enclosingNodes != null) { + containerChildren.addAll(enclosingNodes); + } + if (typeSystem != null) { + containerChildren.add(typeSystem); + } + if (specializations != null) { + for (MessageContainer specialization : specializations) { + if (specialization.getMessageElement() != null) { + containerChildren.add(specialization); + } + } + } + if (executableTypes != null) { + containerChildren.addAll(getExecutableTypes()); + } + if (shortCircuits != null) { + containerChildren.addAll(shortCircuits); + } + if (children != null) { + containerChildren.addAll(children); + } + if (fields != null) { + containerChildren.addAll(fields); + } + if (casts != null) { + containerChildren.addAll(casts); + } + return containerChildren; + } + + public ParameterSpec getInstanceParameterSpec() { + return instanceParameterSpec; + } + + public void setInstanceParameterSpec(ParameterSpec instanceParameter) { + this.instanceParameterSpec = instanceParameter; + } + + public String getNodeId() { + return nodeId; + } + + public TypeMirror getNodeType() { + return getTemplateType().asType(); + } + + public boolean needsFactory() { + if (specializations == null) { + return false; + } + if (getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { + return false; + } + + boolean noSpecialization = true; + for (SpecializationData specialization : specializations) { + noSpecialization = noSpecialization && !specialization.isSpecialized(); + } + return !noSpecialization; + } + + public boolean supportsFrame() { + if (executableTypes != null) { + for (ExecutableTypeData execType : getExecutableTypes(-1)) { + if (execType.getFrameParameter() == null) { + return false; + } + } + } + return true; + } + + public NodeExecutionData findExecutionByExpression(String childNameExpression) { + String childName = childNameExpression; + int index = -1; + + int start = childName.indexOf('['); + int end = childName.lastIndexOf(']'); + if (start != -1 && end != -1 && start < end) { + try { + index = Integer.parseInt(childName.substring(start + 1, end)); + childName = childName.substring(0, start); + childName = NodeExecutionData.createName(childName, index); + } catch (NumberFormatException e) { + // ignore + } + } + + for (NodeExecutionData execution : childExecutions) { + if (execution.getName().equals(childName) && (execution.getChildIndex() == -1 || execution.getChildIndex() == index)) { + return execution; + } + } + return null; + } + + public List<NodeData> getNodesWithFactories() { + List<NodeData> nodeChildren = new ArrayList<>(); + for (NodeData child : getEnclosingNodes()) { + if (child.needsFactory() && child.isGenerateFactory()) { + nodeChildren.add(child); + } + nodeChildren.addAll(child.getNodesWithFactories()); + } + return nodeChildren; + } + + public NodeData getDeclaringNode() { + return declaringNode; + } + + public List<NodeData> getEnclosingNodes() { + return enclosingNodes; + } + + public List<ExecutableElement> getAllTemplateMethods() { + List<ExecutableElement> methods = new ArrayList<>(); + + for (SpecializationData specialization : getSpecializations()) { + methods.add(specialization.getMethod()); + } + + for (ExecutableTypeData execType : getExecutableTypes()) { + if (execType.getMethod() != null) { + methods.add(execType.getMethod()); + } + } + for (ShortCircuitData shortcircuit : getShortCircuits()) { + methods.add(shortcircuit.getMethod()); + } + + if (getCasts() != null) { + for (CreateCastData castData : getCasts()) { + methods.add(castData.getMethod()); + } + } + + return methods; + } + + public ExecutableTypeData findAnyGenericExecutableType(ProcessorContext context, int evaluatedCount) { + List<ExecutableTypeData> types = findGenericExecutableTypes(context, evaluatedCount); + for (ExecutableTypeData type : types) { + if (context.isType(type.getReturnType(), Object.class)) { + return type; + } + } + + for (ExecutableTypeData type : types) { + if (!context.isType(type.getReturnType(), void.class)) { + return type; + } + } + + for (ExecutableTypeData type : types) { + return type; + } + return null; + } + + public List<ExecutableTypeData> getExecutableTypes(int evaluatedCount) { + if (evaluatedCount == -1) { + return executableTypes; + } else { + List<ExecutableTypeData> filteredTypes = new ArrayList<>(); + for (ExecutableTypeData type : executableTypes) { + if (type.getEvaluatedCount() == evaluatedCount) { + filteredTypes.add(type); + } + } + return filteredTypes; + } + } + + public List<ExecutableTypeData> findGenericExecutableTypes(ProcessorContext context, int evaluatedCount) { + List<ExecutableTypeData> types = new ArrayList<>(); + for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) { + if (!type.hasUnexpectedValue(context)) { + types.add(type); + } + } + return types; + } + + public ExecutableTypeData findExecutableType(TypeMirror primitiveType, int evaluatedCount) { + for (ExecutableTypeData type : getExecutableTypes(evaluatedCount)) { + if (ElementUtils.typeEquals(type.getReturnType(), primitiveType)) { + return type; + } + } + return null; + } + + public boolean needsRewrites(ProcessorContext context) { + boolean needsRewrites = false; + + for (SpecializationData specialization : getSpecializations()) { + if (specialization.hasRewrite(context)) { + needsRewrites = true; + break; + } + } + return needsRewrites || getSpecializations().size() > 1; + } + + public SpecializationData getPolymorphicSpecialization() { + for (SpecializationData specialization : specializations) { + if (specialization.isPolymorphic()) { + return specialization; + } + } + return null; + } + + public SpecializationData getGenericSpecialization() { + for (SpecializationData specialization : specializations) { + if (specialization.isFallback()) { + return specialization; + } + } + return null; + } + + public SpecializationData getUninitializedSpecialization() { + for (SpecializationData specialization : specializations) { + if (specialization.isUninitialized()) { + return specialization; + } + } + return null; + } + + @Override + public TypeSystemData getTypeSystem() { + return typeSystem; + } + + @Override + public String dump() { + return dump(0); + } + + private String dump(int level) { + String indent = ""; + for (int i = 0; i < level; i++) { + indent += " "; + } + StringBuilder builder = new StringBuilder(); + + builder.append(String.format("%s%s {", indent, toString())); + + dumpProperty(builder, indent, "templateClass", ElementUtils.getQualifiedName(getTemplateType())); + dumpProperty(builder, indent, "typeSystem", getTypeSystem()); + dumpProperty(builder, indent, "fields", getChildren()); + dumpProperty(builder, indent, "executableTypes", getExecutableTypes()); + dumpProperty(builder, indent, "specializations", getSpecializations()); + dumpProperty(builder, indent, "casts", getCasts()); + dumpProperty(builder, indent, "messages", collectMessages()); + if (getEnclosingNodes().size() > 0) { + builder.append(String.format("\n%s children = [", indent)); + for (NodeData node : getEnclosingNodes()) { + builder.append("\n"); + builder.append(node.dump(level + 1)); + } + builder.append(String.format("\n%s ]", indent)); + } + builder.append(String.format("%s}", indent)); + return builder.toString(); + } + + private static void dumpProperty(StringBuilder b, String indent, String propertyName, Object value) { + if (value instanceof List) { + List<?> list = (List<?>) value; + if (!list.isEmpty()) { + b.append(String.format("\n%s %s = %s", indent, propertyName, dumpList(indent, (List<?>) value))); + } + } else { + if (value != null) { + b.append(String.format("\n%s %s = %s", indent, propertyName, value)); + } + } + } + + private static String dumpList(String indent, List<?> array) { + if (array == null) { + return "null"; + } + + if (array.isEmpty()) { + return "[]"; + } else if (array.size() == 1) { + return "[" + array.get(0).toString() + "]"; + } + + StringBuilder b = new StringBuilder(); + b.append("["); + for (Object object : array) { + b.append("\n "); + b.append(indent); + b.append(object); + b.append(", "); + } + b.append("\n ").append(indent).append("]"); + return b.toString(); + } + + public NodeChildData findChild(String name) { + for (NodeChildData field : getChildren()) { + if (field.getName().equals(name)) { + return field; + } + } + return null; + } + + public List<NodeChildData> getChildren() { + return children; + } + + public List<SpecializationData> getSpecializations() { + return specializations; + } + + public ExecutableTypeData getGenericExecutableType(ExecutableTypeData typeHint) { + ExecutableTypeData polymorphicDelegate = null; + if (typeHint != null) { + polymorphicDelegate = typeHint; + while (polymorphicDelegate.getDelegatedTo() != null && polymorphicDelegate.getEvaluatedCount() != getSignatureSize()) { + polymorphicDelegate = polymorphicDelegate.getDelegatedTo(); + } + } + if (polymorphicDelegate == null) { + for (ExecutableTypeData type : getExecutableTypes()) { + if (type.getDelegatedTo() == null && type.getEvaluatedCount() == getSignatureSize()) { + polymorphicDelegate = type; + break; + } + } + } + return polymorphicDelegate; + } + + public List<ExecutableTypeData> getExecutableTypes() { + return getExecutableTypes(-1); + } + + public List<ShortCircuitData> getShortCircuits() { + return shortCircuits; + } + + public int getMinimalEvaluatedParameters() { + int minimalEvaluatedParameters = Integer.MAX_VALUE; + for (ExecutableTypeData type : getExecutableTypes()) { + minimalEvaluatedParameters = Math.min(minimalEvaluatedParameters, type.getEvaluatedCount()); + } + return minimalEvaluatedParameters; + } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + getNodeId() + "]"; + } + + public CreateCastData findCast(String name) { + if (getCasts() != null) { + for (CreateCastData cast : getCasts()) { + if (cast.getChildNames().contains(name)) { + return cast; + } + } + } + return null; + } + + public int compareTo(NodeData o) { + return getNodeId().compareTo(o.getNodeId()); + } + + public TypeMirror getGenericType(NodeExecutionData execution) { + return ElementUtils.getCommonSuperType(getContext(), getGenericTypes(execution)); + } + + public List<TypeMirror> getGenericTypes(NodeExecutionData execution) { + List<TypeMirror> types = new ArrayList<>(); + + // add types possible through return types and evaluated parameters in execute methods + if (execution.getChild() != null) { + for (ExecutableTypeData executable : execution.getChild().getNodeData().getExecutableTypes()) { + if (executable.hasUnexpectedValue(getContext())) { + continue; + } + types.add(executable.getReturnType()); + } + } + + int executionIndex = execution.getIndex(); + if (executionIndex >= 0) { + for (ExecutableTypeData typeData : getExecutableTypes()) { + List<TypeMirror> signatureParameters = typeData.getSignatureParameters(); + if (executionIndex < signatureParameters.size()) { + TypeMirror genericType = signatureParameters.get(executionIndex); + types.add(genericType); + } + } + } + + return ElementUtils.uniqueSortedTypes(types, false); + } + +}