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);
}
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));
}
}
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);
}
}
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;
}
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;
}
Aggregations