Search in sources :

Example 21 with SpecializationData

use of com.oracle.truffle.dsl.processor.model.SpecializationData in project graal by oracle.

the class NodeParser method initializePolymorphism.

private void initializePolymorphism(NodeData node) {
    if (!node.needsRewrites(context)) {
        return;
    }
    SpecializationData generic = node.getGenericSpecialization();
    List<VariableElement> types = new ArrayList<>();
    Collection<TypeMirror> frameTypes = new HashSet<>();
    for (SpecializationData specialization : node.getSpecializations()) {
        if (specialization.getFrame() != null) {
            frameTypes.add(specialization.getFrame().getType());
        }
    }
    if (node.supportsFrame()) {
        frameTypes.add(node.getFrameType());
    }
    if (!frameTypes.isEmpty()) {
        frameTypes = ElementUtils.uniqueSortedTypes(frameTypes, false);
        TypeMirror frameType;
        if (frameTypes.size() == 1) {
            frameType = frameTypes.iterator().next();
        } else {
            frameType = context.getType(Frame.class);
        }
        types.add(new CodeVariableElement(frameType, TemplateMethod.FRAME_NAME));
    }
    TypeMirror returnType = null;
    int index = 0;
    for (Parameter genericParameter : generic.getReturnTypeAndParameters()) {
        TypeMirror polymorphicType;
        if (genericParameter.getLocalName().equals(TemplateMethod.FRAME_NAME)) {
            continue;
        }
        boolean isReturnParameter = genericParameter == generic.getReturnType();
        if (!genericParameter.getSpecification().isSignature()) {
            polymorphicType = genericParameter.getType();
        } else {
            NodeExecutionData execution = genericParameter.getSpecification().getExecution();
            Collection<TypeMirror> usedTypes = new HashSet<>();
            for (SpecializationData specialization : node.getSpecializations()) {
                if (specialization.isUninitialized()) {
                    continue;
                }
                Parameter parameter = specialization.findParameter(genericParameter.getLocalName());
                if (parameter == specialization.getReturnType() && specialization.isFallback() && specialization.getMethod() == null) {
                    continue;
                }
                if (parameter == null) {
                    throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName());
                }
                if (isReturnParameter && specialization.hasUnexpectedResultRewrite()) {
                    if (!ElementUtils.isSubtypeBoxed(context, context.getType(Object.class), node.getGenericType(execution))) {
                        specialization.addError("Implicit 'Object' return type from UnexpectedResultException not compatible with generic type '%s'.", node.getGenericType(execution));
                    } else {
                        // if any specialization throws UnexpectedResultException, Object could
                        // be returned
                        usedTypes.add(context.getType(Object.class));
                    }
                }
                usedTypes.add(parameter.getType());
            }
            usedTypes = ElementUtils.uniqueSortedTypes(usedTypes, false);
            if (usedTypes.size() == 1) {
                polymorphicType = usedTypes.iterator().next();
            } else {
                polymorphicType = ElementUtils.getCommonSuperType(context, usedTypes);
            }
            if (execution != null && !ElementUtils.isSubtypeBoxed(context, polymorphicType, node.getGenericType(execution))) {
                throw new AssertionError(String.format("Polymorphic types %s not compatible to generic type %s.", polymorphicType, node.getGenericType(execution)));
            }
        }
        if (isReturnParameter) {
            returnType = polymorphicType;
        } else {
            types.add(new CodeVariableElement(polymorphicType, "param" + index));
        }
        index++;
    }
    SpecializationMethodParser parser = new SpecializationMethodParser(context, node);
    SpecializationData polymorphic = parser.create("Polymorphic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, types);
    if (polymorphic == null) {
        throw new AssertionError("Failed to parse polymorphic signature. " + parser.createDefaultMethodSpec(null, null, false, null) + " Types: " + returnType + " - " + types);
    }
    polymorphic.setKind(SpecializationKind.POLYMORPHIC);
    node.getSpecializations().add(polymorphic);
}
Also used : Frame(com.oracle.truffle.api.frame.Frame) NodeExecutionData(com.oracle.truffle.dsl.processor.model.NodeExecutionData) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) ArrayList(java.util.ArrayList) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) VariableElement(javax.lang.model.element.VariableElement) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) Parameter(com.oracle.truffle.dsl.processor.model.Parameter) HashSet(java.util.HashSet)

Example 22 with SpecializationData

use of com.oracle.truffle.dsl.processor.model.SpecializationData in project graal by oracle.

the class NodeParser method initializeSpecializationIdsWithMethodNames.

private static void initializeSpecializationIdsWithMethodNames(List<SpecializationData> specializations) {
    List<String> signatures = new ArrayList<>();
    for (SpecializationData specialization : specializations) {
        if (specialization.isFallback()) {
            signatures.add("Fallback");
        } else if (specialization.isUninitialized()) {
            signatures.add("Uninitialized");
        } else if (specialization.isPolymorphic()) {
            signatures.add("Polymorphic");
        } else {
            String name = specialization.getMethodName();
            // hack for name clashes with BaseNode.
            if (name.equalsIgnoreCase("base")) {
                name = name + "0";
            } else if (name.startsWith("do")) {
                String filteredDo = name.substring(2, name.length());
                if (!filteredDo.isEmpty() && Character.isJavaIdentifierStart(filteredDo.charAt(0))) {
                    name = filteredDo;
                }
            }
            signatures.add(ElementUtils.firstLetterUpperCase(name));
        }
    }
    while (renameDuplicateIds(signatures)) {
    // fix point
    }
    for (int i = 0; i < specializations.size(); i++) {
        specializations.get(i).setId(signatures.get(i));
    }
}
Also used : ArrayList(java.util.ArrayList) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData)

Example 23 with SpecializationData

use of com.oracle.truffle.dsl.processor.model.SpecializationData in project graal by oracle.

the class NodeParser method initializeExpressions.

private void initializeExpressions(List<? extends Element> elements, NodeData node) {
    List<Element> members = filterNotAccessibleElements(node.getTemplateType(), elements);
    List<VariableElement> fields = new ArrayList<>();
    for (NodeFieldData field : node.getFields()) {
        fields.add(field.getVariable());
    }
    for (SpecializationData specialization : node.getSpecializations()) {
        if (specialization.getMethod() == null) {
            continue;
        }
        List<Element> specializationMembers = new ArrayList<>(members.size() + specialization.getParameters().size() + fields.size());
        for (Parameter p : specialization.getParameters()) {
            specializationMembers.add(p.getVariableElement());
        }
        specializationMembers.addAll(fields);
        specializationMembers.addAll(members);
        DSLExpressionResolver resolver = new DSLExpressionResolver(context, specializationMembers);
        initializeCaches(specialization, resolver);
        initializeGuards(specialization, resolver);
        if (specialization.hasErrors()) {
            continue;
        }
        initializeLimit(specialization, resolver);
        initializeAssumptions(specialization, resolver);
    }
}
Also used : NodeFieldData(com.oracle.truffle.dsl.processor.model.NodeFieldData) TypeElement(javax.lang.model.element.TypeElement) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) Parameter(com.oracle.truffle.dsl.processor.model.Parameter) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) VariableElement(javax.lang.model.element.VariableElement) DSLExpressionResolver(com.oracle.truffle.dsl.processor.expression.DSLExpressionResolver)

Example 24 with SpecializationData

use of com.oracle.truffle.dsl.processor.model.SpecializationData in project graal by oracle.

the class SpecializationGroup method create.

public static SpecializationGroup create(List<SpecializationData> specializations) {
    List<SpecializationGroup> groups = new ArrayList<>();
    for (SpecializationData specialization : specializations) {
        groups.add(new SpecializationGroup(specialization));
    }
    SpecializationGroup group1 = new SpecializationGroup(createCombinationalGroups(groups), Collections.<TypeGuard>emptyList(), Collections.<GuardExpression>emptyList());
    SpecializationGroup group = group1;
    // trim groups
    while (group.isEmpty() && group.getChildren().size() == 1) {
        group = group.getChildren().iterator().next();
    }
    return group;
}
Also used : ArrayList(java.util.ArrayList) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData)

Example 25 with SpecializationData

use of com.oracle.truffle.dsl.processor.model.SpecializationData in project graal by oracle.

the class SpecializationMethodParser method parseSpecialization.

private SpecializationData parseSpecialization(TemplateMethod method) {
    List<SpecializationThrowsData> exceptionData = new ArrayList<>();
    boolean unexpectedResultRewrite = false;
    if (method.getMethod() != null) {
        AnnotationValue rewriteValue = ElementUtils.getAnnotationValue(method.getMarkerAnnotation(), "rewriteOn");
        List<TypeMirror> exceptionTypes = ElementUtils.getAnnotationValueList(TypeMirror.class, method.getMarkerAnnotation(), "rewriteOn");
        List<TypeMirror> rewriteOnTypes = new ArrayList<>();
        for (TypeMirror exceptionType : exceptionTypes) {
            SpecializationThrowsData throwsData = new SpecializationThrowsData(method.getMarkerAnnotation(), rewriteValue, exceptionType);
            if (!ElementUtils.canThrowType(method.getMethod().getThrownTypes(), exceptionType)) {
                method.addError("A rewriteOn checked exception was specified but not thrown in the method's throws clause. The @%s method must specify a throws clause with the exception type '%s'.", Specialization.class.getSimpleName(), ElementUtils.getQualifiedName(exceptionType));
            }
            if (ElementUtils.typeEquals(exceptionType, getContext().getType(UnexpectedResultException.class))) {
                if (ElementUtils.typeEquals(method.getMethod().getReturnType(), getContext().getType(Object.class))) {
                    method.addError("A specialization with return type 'Object' cannot throw UnexpectedResultException.");
                }
                unexpectedResultRewrite = true;
            }
            rewriteOnTypes.add(throwsData.getJavaClass());
            exceptionData.add(throwsData);
        }
        for (TypeMirror typeMirror : method.getMethod().getThrownTypes()) {
            if (!ElementUtils.canThrowType(rewriteOnTypes, typeMirror)) {
                method.addError(rewriteValue, "A checked exception '%s' is thrown but is not specified using the rewriteOn property. " + "Checked exceptions that are not used for rewriting are not handled by the DSL. Use RuntimeExceptions for this purpose instead.", ElementUtils.getQualifiedName(typeMirror));
            }
        }
        Collections.sort(exceptionData, new Comparator<SpecializationThrowsData>() {

            @Override
            public int compare(SpecializationThrowsData o1, SpecializationThrowsData o2) {
                return ElementUtils.compareByTypeHierarchy(o1.getJavaClass(), o2.getJavaClass());
            }
        });
    }
    SpecializationData specialization = new SpecializationData(getNode(), method, SpecializationKind.SPECIALIZED, exceptionData, unexpectedResultRewrite);
    if (method.getMethod() != null) {
        String insertBeforeName = ElementUtils.getAnnotationValue(String.class, method.getMarkerAnnotation(), "insertBefore");
        if (!insertBeforeName.equals("")) {
            specialization.setInsertBeforeName(insertBeforeName);
        }
        List<String> replacesDefs = new ArrayList<>();
        replacesDefs.addAll(ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "replaces"));
        // TODO remove if deprecated contains api is removed.
        replacesDefs.addAll(ElementUtils.getAnnotationValueList(String.class, specialization.getMarkerAnnotation(), "contains"));
        Set<String> containsNames = specialization.getReplacesNames();
        containsNames.clear();
        if (replacesDefs != null) {
            for (String include : replacesDefs) {
                if (!containsNames.contains(include)) {
                    specialization.getReplacesNames().add(include);
                } else {
                    AnnotationValue value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "replaces");
                    if (value == null) {
                        // TODO remove if deprecated api was removed.
                        value = ElementUtils.getAnnotationValue(specialization.getMarkerAnnotation(), "contains");
                    }
                    specialization.addError(value, "Duplicate replace declaration '%s'.", include);
                }
            }
        }
    }
    return specialization;
}
Also used : ArrayList(java.util.ArrayList) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) Specialization(com.oracle.truffle.api.dsl.Specialization) UnexpectedResultException(com.oracle.truffle.api.nodes.UnexpectedResultException) TypeMirror(javax.lang.model.type.TypeMirror) SpecializationThrowsData(com.oracle.truffle.dsl.processor.model.SpecializationThrowsData) AnnotationValue(javax.lang.model.element.AnnotationValue)

Aggregations

SpecializationData (com.oracle.truffle.dsl.processor.model.SpecializationData)35 ArrayList (java.util.ArrayList)22 TypeMirror (javax.lang.model.type.TypeMirror)17 ArrayCodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror)16 CodeTreeBuilder (com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder)12 CodeExecutableElement (com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement)11 DeclaredCodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror)11 GeneratedTypeMirror (com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror)11 Parameter (com.oracle.truffle.dsl.processor.model.Parameter)9 CodeVariableElement (com.oracle.truffle.dsl.processor.java.model.CodeVariableElement)8 ExecutableTypeData (com.oracle.truffle.dsl.processor.model.ExecutableTypeData)7 CodeTree (com.oracle.truffle.dsl.processor.java.model.CodeTree)6 HashSet (java.util.HashSet)6 NodeExecutionData (com.oracle.truffle.dsl.processor.model.NodeExecutionData)5 VariableElement (javax.lang.model.element.VariableElement)5 AnnotationValue (javax.lang.model.element.AnnotationValue)4 ExecutableElement (javax.lang.model.element.ExecutableElement)4 Child (com.oracle.truffle.api.nodes.Node.Child)3 DSLExpression (com.oracle.truffle.dsl.processor.expression.DSLExpression)3 ElementUtils.isObject (com.oracle.truffle.dsl.processor.java.ElementUtils.isObject)3