# HG changeset patch # User Christian Humer # Date 1371748209 -7200 # Node ID 746fa60be266dc1d873ca477a705d39b74bae912 # Parent f158703c308c2b6e35bdb457d0cb9ae460b3af7a Implemented CreateCast annotation for easier insertion of casts. diff -r f158703c308c -r 746fa60be266 graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/CreateCast.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.codegen/src/com/oracle/truffle/api/codegen/CreateCast.java Thu Jun 20 19:10:09 2013 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012, 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.api.codegen; + +import java.lang.annotation.*; + +import com.oracle.truffle.api.nodes.*; + +/** + * Specifies a factory method that creates a {@link Node} which is used to cast this child. + */ +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD}) +public @interface CreateCast { + + String[] value(); + +} diff -r f158703c308c -r 746fa60be266 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Tue Jun 18 10:12:27 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/Utils.java Thu Jun 20 19:10:09 2013 +0200 @@ -583,8 +583,13 @@ List values = getAnnotationValue(List.class, mirror, name); List result = new ArrayList<>(); - for (AnnotationValue value : values) { - result.add(resolveAnnotationValue(expectedListType, value)); + if (values != null) { + for (AnnotationValue value : values) { + T annotationValue = resolveAnnotationValue(expectedListType, value); + if (annotationValue != null) { + result.add(annotationValue); + } + } } return result; } @@ -595,6 +600,10 @@ @SuppressWarnings({"unchecked"}) private static T resolveAnnotationValue(Class expectedType, AnnotationValue value) { + if (value == null) { + return null; + } + Object unboxedValue = value.accept(new AnnotationValueVisitorImpl(), null); if (unboxedValue != null) { if (expectedType == TypeMirror.class && unboxedValue instanceof String) { diff -r f158703c308c -r 746fa60be266 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Tue Jun 18 10:12:27 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Thu Jun 20 19:10:09 2013 +0200 @@ -563,7 +563,7 @@ public ExecutableElement findMethod() { Element element = currentElement; - while (element != null && (element.getKind() != ElementKind.METHOD)) { + while (element != null && (element.getKind() != ElementKind.METHOD && (element.getKind() != ElementKind.CONSTRUCTOR))) { element = element.getEnclosingElement(); } ExecutableElement found = element != null ? (ExecutableElement) element : null; diff -r f158703c308c -r 746fa60be266 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/CreateCastData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/CreateCastData.java Thu Jun 20 19:10:09 2013 +0200 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012, 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.codegen.processor.node; + +import java.util.*; + +import com.oracle.truffle.codegen.processor.template.*; + +public class CreateCastData extends TemplateMethod { + + private final List childNames; + + public CreateCastData(TemplateMethod method, List childNames) { + super(method); + this.childNames = childNames; + } + + public List getChildNames() { + return childNames; + } + +} diff -r f158703c308c -r 746fa60be266 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/CreateCastParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/CreateCastParser.java Thu Jun 20 19:10:09 2013 +0200 @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2012, 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.codegen.processor.node; + +import java.lang.annotation.*; +import java.util.*; + +import javax.lang.model.element.*; +import javax.lang.model.type.*; + +import com.oracle.truffle.api.codegen.*; +import com.oracle.truffle.codegen.processor.*; +import com.oracle.truffle.codegen.processor.template.*; + +public class CreateCastParser extends NodeMethodParser { + + public CreateCastParser(ProcessorContext context, NodeData operation) { + super(context, operation); + } + + @Override + public Class getAnnotationType() { + return CreateCast.class; + } + + @Override + public MethodSpec createSpecification(ExecutableElement method, AnnotationMirror mirror) { + List childNames = Utils.getAnnotationValueList(String.class, mirror, "value"); + TypeMirror baseType = getContext().getTruffleTypes().getNode(); + for (String childName : childNames) { + NodeChildData child = getNode().findChild(childName); + if (child != null) { + baseType = child.getOriginalType(); + break; + } + } + MethodSpec spec = new MethodSpec(new InheritsParameterSpec(getContext(), "child", baseType)); + addDefaultFieldMethodSpec(method, spec); + spec.addRequired(new ParameterSpec("castedChild", baseType)).setSignature(true); + return spec; + } + + @Override + public CreateCastData create(TemplateMethod method) { + AnnotationMirror mirror = method.getMarkerAnnotation(); + List childNames = Utils.getAnnotationValueList(String.class, mirror, "value"); + CreateCastData cast = new CreateCastData(method, childNames); + AnnotationValue value = Utils.getAnnotationValue(mirror, "value"); + TypeMirror type = null; + if (childNames == null || childNames.isEmpty()) { + cast.addError(value, "No value specified but required."); + return cast; + } + + for (String childName : childNames) { + NodeChildData child = getNode().findChild(childName); + if (child == null) { + // error + cast.addError(value, "Specified child '%s' not found.", childName); + continue; + } + if (type == null) { + type = child.getNodeType(); + } else if (!Utils.typeEquals(type, child.getNodeType())) { + cast.addError(value, "All child nodes for a cast must have the same node type."); + continue; + } + } + return cast; + } + + private static class InheritsParameterSpec extends ParameterSpec { + + private final ProcessorContext context; + + public InheritsParameterSpec(ProcessorContext context, String name, TypeMirror... allowedTypes) { + super(name, Arrays.asList(allowedTypes)); + this.context = context; + } + + @Override + public boolean matches(TypeMirror actualType) { + boolean found = false; + for (TypeMirror specType : getAllowedTypes()) { + if (Utils.isAssignable(context, actualType, specType)) { + found = true; + break; + } + } + return found; + } + } +} diff -r f158703c308c -r 746fa60be266 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java Tue Jun 18 10:12:27 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeChildData.java Thu Jun 20 19:10:09 2013 +0200 @@ -54,6 +54,7 @@ private final String name; private final TypeMirror type; + private final TypeMirror originalType; private final Element accessElement; private final Cardinality cardinality; @@ -63,11 +64,13 @@ private NodeData nodeData; - public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, Element accessElement, Cardinality cardinality, ExecutionKind executionKind) { + public NodeChildData(Element sourceElement, AnnotationMirror sourceMirror, String name, TypeMirror nodeType, TypeMirror originalNodeType, Element accessElement, Cardinality cardinality, + ExecutionKind executionKind) { this.sourceElement = sourceElement; this.sourceAnnotationMirror = sourceMirror; this.name = name; this.type = nodeType; + this.originalType = originalNodeType; this.accessElement = accessElement; this.cardinality = cardinality; this.executionKind = executionKind; @@ -101,6 +104,10 @@ return nodeData.getExecutableTypes(getExecuteWith().size()); } + public TypeMirror getOriginalType() { + return originalType; + } + @Override public Element getMessageElement() { return sourceElement; diff -r f158703c308c -r 746fa60be266 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Tue Jun 18 10:12:27 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Thu Jun 20 19:10:09 2013 +0200 @@ -143,7 +143,8 @@ } } - private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName) { + private CodeTree createTemplateMethodCall(CodeTreeBuilder parent, CodeTree target, TemplateMethod sourceMethod, TemplateMethod targetMethod, String unexpectedValueName, + String... customSignatureValueNames) { CodeTreeBuilder builder = parent.create(); boolean castedValues = sourceMethod != targetMethod; @@ -199,8 +200,13 @@ } builder.startCall(method.getSimpleName().toString()); + int signatureIndex = 0; + for (ActualParameter targetParameter : targetMethod.getParameters()) { - ActualParameter valueParameter = sourceMethod.findParameter(targetParameter.getLocalName()); + ActualParameter valueParameter = null; + if (sourceMethod != null) { + valueParameter = sourceMethod.findParameter(targetParameter.getLocalName()); + } if (valueParameter == null) { valueParameter = targetParameter; } @@ -215,7 +221,10 @@ valueType = valueParameter.getTypeSystemType(); } - if (targetParameter.getSpecification().isLocal()) { + if (signatureIndex < customSignatureValueNames.length && targetParameter.getSpecification().isSignature()) { + builder.string(customSignatureValueNames[signatureIndex]); + signatureIndex++; + } else if (targetParameter.getSpecification().isLocal()) { builder.startGroup(); if (builder.findMethod().getModifiers().contains(Modifier.STATIC)) { builder.string(THIS_NODE_LOCAL_VAR_NAME).string("."); @@ -522,8 +531,25 @@ return builder.getRoot(); } - private void emitEncounteredSynthetic(CodeTreeBuilder builder) { - builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end(); + private void emitEncounteredSynthetic(CodeTreeBuilder builder, SpecializationData current) { + builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)); + builder.startGroup(); + String sep = null; + for (ActualParameter parameters : current.getParameters()) { + if (parameters.getSpecification().isSignature()) { + if (sep == null) { + builder.doubleQuote("Unsupported values: " + parameters.getLocalName() + " = "); + sep = ", "; + } else { + builder.string(" + "); + builder.doubleQuote(sep + parameters.getLocalName() + " = "); + } + builder.string(" + "); + builder.string(parameters.getLocalName()); + } + } + builder.end(); + builder.end().end(); } private static List findUserConstructors(TypeMirror nodeType) { @@ -669,7 +695,12 @@ } for (VariableElement var : type.getFields()) { - method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString())); + NodeChildData child = getModel().findChild(var.getSimpleName().toString()); + if (child != null) { + method.getParameters().add(new CodeVariableElement(child.getOriginalType(), child.getName())); + } else { + method.getParameters().add(new CodeVariableElement(var.asType(), var.getSimpleName().toString())); + } } if (superConstructor != null) { @@ -682,14 +713,25 @@ for (VariableElement var : type.getFields()) { builder.startStatement(); - String varName = var.getSimpleName().toString(); - builder.string("this.").string(varName); + String fieldName = var.getSimpleName().toString(); + + CodeTree fieldInit = CodeTreeBuilder.singleString(var.getSimpleName().toString()); + builder.string("this.").string(var.getSimpleName().toString()); + + NodeChildData child = getModel().findChild(fieldName); + if (child != null) { + CreateCastData createCast = getModel().findCast(child.getName()); + if (createCast != null) { + fieldInit = createTemplateMethodCall(builder, null, getModel().getGenericSpecialization(), createCast, null, child.getName()); + } + } + if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNode())) { - builder.string(" = adoptChild(").string(varName).string(")"); + builder.string(" = adoptChild(").tree(fieldInit).string(")"); } else if (Utils.isAssignable(getContext(), var.asType(), getContext().getTruffleTypes().getNodeArray())) { - builder.string(" = adoptChildren(").string(varName).string(")"); + builder.string(" = adoptChildren(").tree(fieldInit).string(")"); } else { - builder.string(" = ").string(varName); + builder.string(" = ").tree(fieldInit); } builder.end(); } @@ -832,7 +874,7 @@ unreachableSpecializations.add(specialization); } else { filteredSpecializations.add(specialization); - if (!specialization.isUninitialized() && !specialization.hasRewrite(getContext())) { + if (!specialization.isUninitialized() && specialization.isGenericSpecialization(getContext())) { unreachable = true; } } @@ -877,7 +919,7 @@ } if (specialize && executeCall == null && !current.getNode().getGenericSpecialization().isUseSpecializationsForGeneric()) { - emitEncounteredSynthetic(builder); + emitEncounteredSynthetic(builder, current); } else if (specialize) { if (current.getNode().getGenericSpecialization().isUseSpecializationsForGeneric()) { @@ -890,7 +932,7 @@ } builder.statement("resultIsSet = true"); } else { - emitEncounteredSynthetic(builder); + emitEncounteredSynthetic(builder, current); } builder.end(); } @@ -922,7 +964,7 @@ } } else { if (executeCall == null) { - emitEncounteredSynthetic(builder); + emitEncounteredSynthetic(builder, current); } else { builder.startReturn().tree(executeCall).end(); } @@ -1165,7 +1207,7 @@ CodeTreeBuilder builder = method.createBuilder(); if (!node.needsRewrites(getContext())) { - builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end(); + builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).doubleQuote("No specialized version.").end().end(); } else { builder.startIf(); builder.string("types.length == 1"); @@ -1668,7 +1710,7 @@ returnBuilder.doubleQuote("Uninitialized"); returnBuilder.end(); } else if (specialization.getMethod() == null && !node.needsRewrites(context)) { - emitEncounteredSynthetic(builder); + emitEncounteredSynthetic(builder, specialization); } else if (specialization.isGeneric()) { returnBuilder.startCall("super", EXECUTE_GENERIC_NAME); addInternalValueParameterNames(returnBuilder, specialization, specialization, null, true, true); diff -r f158703c308c -r 746fa60be266 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Tue Jun 18 10:12:27 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeData.java Thu Jun 20 19:10:09 2013 +0200 @@ -50,6 +50,7 @@ private Map> executableTypes; private List shortCircuits; private List assumptions; + private List casts; private String shortName; @@ -74,6 +75,14 @@ this.assumptions = splitSource.assumptions; } + public List getCasts() { + return casts; + } + + void setCasts(List casts) { + this.casts = casts; + } + void setShortName(String shortName) { this.shortName = shortName; } @@ -133,6 +142,9 @@ if (fields != null) { containerChildren.addAll(fields); } + if (casts != null) { + containerChildren.addAll(casts); + } return containerChildren; } @@ -230,6 +242,9 @@ methods.addAll(getSpecializationListeners()); methods.addAll(getExecutableTypes()); methods.addAll(getShortCircuits()); + if (getCasts() != null) { + methods.addAll(getCasts()); + } return methods; } @@ -367,6 +382,7 @@ dumpProperty(builder, indent, "executableTypes", getExecutableTypes()); dumpProperty(builder, indent, "specializations", getSpecializations()); dumpProperty(builder, indent, "assumptions", getAssumptions()); + dumpProperty(builder, indent, "casts", getCasts()); dumpProperty(builder, indent, "messages", collectMessages()); if (getDeclaredNodes().size() > 0) { builder.append(String.format("\n%s children = [", indent)); @@ -489,4 +505,15 @@ 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; + } + } diff -r f158703c308c -r 746fa60be266 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java Tue Jun 18 10:12:27 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeMethodParser.java Thu Jun 20 19:10:09 2013 +0200 @@ -78,20 +78,15 @@ protected final MethodSpec createDefaultMethodSpec(ExecutableElement method, AnnotationMirror mirror, boolean shortCircuitsEnabled, String shortCircuitName) { MethodSpec methodSpec = new MethodSpec(createReturnParameterSpec()); - if (getNode().supportsFrame()) { - methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame())); - } - - resolveAndAddImplicitThis(methodSpec, method); + addDefaultFrame(methodSpec); + addDefaultImplicitThis(method, methodSpec); + addDefaultFieldMethodSpec(method, methodSpec); + addDefaultChildren(shortCircuitsEnabled, shortCircuitName, methodSpec); - for (NodeFieldData field : getNode().getFields()) { - if (!Utils.isFieldAccessible(method, field.getVariable())) { - ParameterSpec spec = new ParameterSpec(field.getName(), field.getType()); - spec.setLocal(true); - methodSpec.addOptional(spec); - } - } + return methodSpec; + } + private void addDefaultChildren(boolean shortCircuitsEnabled, String shortCircuitName, MethodSpec methodSpec) { // children are null when parsing executable types if (getNode().getChildren() != null) { for (NodeChildData child : getNode().getChildren()) { @@ -117,11 +112,25 @@ } } } + } - return methodSpec; + private void addDefaultFrame(MethodSpec methodSpec) { + if (getNode().supportsFrame()) { + methodSpec.addOptional(new ParameterSpec("frame", getContext().getTruffleTypes().getFrame())); + } } - protected void resolveAndAddImplicitThis(MethodSpec methodSpec, ExecutableElement method) { + protected void addDefaultFieldMethodSpec(ExecutableElement method, MethodSpec methodSpec) { + for (NodeFieldData field : getNode().getFields()) { + if (!Utils.isFieldAccessible(method, field.getVariable())) { + ParameterSpec spec = new ParameterSpec(field.getName(), field.getType()); + spec.setLocal(true); + methodSpec.addOptional(spec); + } + } + } + + protected void addDefaultImplicitThis(ExecutableElement method, MethodSpec methodSpec) { TypeMirror declaredType = Utils.findNearestEnclosingType(method).asType(); if (!method.getModifiers().contains(Modifier.STATIC) && !Utils.isAssignable(getContext(), declaredType, getContext().getTruffleTypes().getNode())) { diff -r f158703c308c -r 746fa60be266 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Tue Jun 18 10:12:27 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeParser.java Thu Jun 20 19:10:09 2013 +0200 @@ -211,6 +211,7 @@ private static List splitNodeData(NodeData node) { SortedMap> groupedSpecializations = groupByNodeId(node.getSpecializations()); SortedMap> groupedListeners = groupByNodeId(node.getSpecializationListeners()); + SortedMap> groupedCasts = groupByNodeId(node.getCasts()); Set ids = new TreeSet<>(); ids.addAll(groupedSpecializations.keySet()); @@ -220,6 +221,7 @@ for (String id : ids) { List specializations = groupedSpecializations.get(id); List listeners = groupedListeners.get(id); + List casts = groupedCasts.get(id); if (specializations == null) { specializations = new ArrayList<>(); @@ -238,12 +240,14 @@ copy.setSpecializations(specializations); copy.setSpecializationListeners(listeners); + copy.setCasts(casts); splitted.add(copy); } node.setSpecializations(new ArrayList()); node.setSpecializationListeners(new ArrayList()); + node.setCasts(new ArrayList()); return splitted; } @@ -266,6 +270,7 @@ node.setSpecializationListeners(new SpecializationListenerParser(context, node).parse(elements)); List generics = new GenericParser(context, node).parse(elements); List specializations = new SpecializationMethodParser(context, node).parse(elements); + node.setCasts(new CreateCastParser(context, node).parse(elements)); List allSpecializations = new ArrayList<>(); allSpecializations.addAll(generics); @@ -736,6 +741,18 @@ shortCircuits.add(Utils.getAnnotationValue(String.class, mirror, "value")); } } + Map castNodeTypes = new HashMap<>(); + for (ExecutableElement method : ElementFilter.methodsIn(elements)) { + AnnotationMirror mirror = Utils.findAnnotationMirror(processingEnv, method, CreateCast.class); + if (mirror != null) { + List children = (Utils.getAnnotationValueList(String.class, mirror, "value")); + if (children != null) { + for (String child : children) { + castNodeTypes.put(child, method.getReturnType()); + } + } + } + } List parsedChildren = new ArrayList<>(); List typeHierarchyReversed = new ArrayList<>(typeHierarchy); @@ -768,6 +785,12 @@ cardinality = Cardinality.MANY; } + TypeMirror originalChildType = childType; + TypeMirror castNodeType = castNodeTypes.get(name); + if (castNodeType != null) { + childType = castNodeType; + } + Element getter = findGetter(elements, name, childType); ExecutionKind kind = ExecutionKind.DEFAULT; @@ -775,7 +798,7 @@ kind = ExecutionKind.SHORT_CIRCUIT; } - NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, getter, cardinality, kind); + NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childType, originalChildType, getter, cardinality, kind); parsedChildren.add(nodeChild); @@ -883,7 +906,7 @@ } for (ExecutableElement method : ElementFilter.methodsIn(elements)) { - if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.typeEquals(method.getReturnType(), type)) { + if (method.getSimpleName().toString().equals(methodName) && method.getParameters().size() == 0 && Utils.isAssignable(context, type, method.getReturnType())) { return method; } } diff -r f158703c308c -r 746fa60be266 graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Tue Jun 18 10:12:27 2013 +0200 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Thu Jun 20 19:10:09 2013 +0200 @@ -74,6 +74,24 @@ return sinks; } + public boolean isGenericSpecialization(ProcessorContext context) { + if (hasRewrite(context)) { + return false; + } + + for (ActualParameter parameter : getParameters()) { + NodeChildData child = getNode().findChild(parameter.getSpecification().getName()); + if (child == null) { + continue; + } + if (!parameter.getTypeSystemType().isGeneric()) { + return false; + } + } + + return true; + } + public boolean hasRewrite(ProcessorContext context) { if (!getExceptions().isEmpty()) { return true;