Mercurial > hg > graal-compiler
view graal/com.oracle.graal.nodeinfo.processor/src/com/oracle/graal/nodeinfo/processor/GraphNodeVerifier.java @ 21463:b1072d72fa2e
Lower checkcast arraycopy idiom after frame state assignment and convert arraycopy lowering into snippets
author | Tom Rodriguez <tom.rodriguez@oracle.com> |
---|---|
date | Thu, 21 May 2015 22:20:41 -0700 |
parents | 88e4916f246a |
children | 05183a084a08 |
line wrap: on
line source
/* * Copyright (c) 2014, 2015, 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.graal.nodeinfo.processor; import static javax.lang.model.element.Modifier.*; import java.util.*; import javax.annotation.processing.*; import javax.lang.model.element.*; import javax.lang.model.type.*; import javax.lang.model.util.*; /** * Verifies static constraints on nodes. */ public class GraphNodeVerifier { private final GraphNodeProcessor env; private final Types types; private final Elements elements; // Checkstyle: stop private final TypeElement Input; private final TypeElement OptionalInput; private final TypeElement Successor; final TypeElement Node; private final TypeElement NodeInputList; private final TypeElement NodeSuccessorList; private final TypeElement object; // Checkstyle: resume public GraphNodeVerifier(GraphNodeProcessor processor) { this.env = processor; this.types = processor.getProcessingEnv().getTypeUtils(); this.elements = processor.getProcessingEnv().getElementUtils(); this.Input = getTypeElement("com.oracle.graal.graph.Node.Input"); this.OptionalInput = getTypeElement("com.oracle.graal.graph.Node.OptionalInput"); this.Successor = getTypeElement("com.oracle.graal.graph.Node.Successor"); this.Node = getTypeElement("com.oracle.graal.graph.Node"); this.NodeInputList = getTypeElement("com.oracle.graal.graph.NodeInputList"); this.NodeSuccessorList = getTypeElement("com.oracle.graal.graph.NodeSuccessorList"); this.object = getTypeElement("java.lang.Object"); } /** * Returns a type element given a canonical name. * * @throw {@link NoClassDefFoundError} if a type element does not exist for {@code name} */ public TypeElement getTypeElement(String name) { TypeElement typeElement = elements.getTypeElement(name); if (typeElement == null) { throw new NoClassDefFoundError(name); } return typeElement; } public TypeElement getTypeElement(Class<?> cls) { return getTypeElement(cls.getName()); } public TypeMirror getType(String name) { return getTypeElement(name).asType(); } public ProcessingEnvironment getProcessingEnv() { return env.getProcessingEnv(); } public boolean isAssignableWithErasure(Element from, Element to) { TypeMirror fromType = types.erasure(from.asType()); TypeMirror toType = types.erasure(to.asType()); return types.isAssignable(fromType, toType); } private void scanFields(TypeElement node) { TypeElement currentClazz = node; do { for (VariableElement field : ElementFilter.fieldsIn(currentClazz.getEnclosedElements())) { Set<Modifier> modifiers = field.getModifiers(); if (modifiers.contains(STATIC) || modifiers.contains(TRANSIENT)) { continue; } List<? extends AnnotationMirror> annotations = field.getAnnotationMirrors(); boolean isNonOptionalInput = findAnnotationMirror(annotations, Input) != null; boolean isOptionalInput = findAnnotationMirror(annotations, OptionalInput) != null; boolean isSuccessor = findAnnotationMirror(annotations, Successor) != null; if (isNonOptionalInput || isOptionalInput) { if (findAnnotationMirror(annotations, Successor) != null) { throw new ElementException(field, "Field cannot be both input and successor"); } else if (isNonOptionalInput && isOptionalInput) { throw new ElementException(field, "Inputs must be either optional or non-optional"); } else if (isAssignableWithErasure(field, NodeInputList)) { if (modifiers.contains(FINAL)) { throw new ElementException(field, "Input list field must not be final"); } if (modifiers.contains(PUBLIC)) { throw new ElementException(field, "Input list field must not be public"); } } else { if (!isAssignableWithErasure(field, Node) && field.getKind() == ElementKind.INTERFACE) { throw new ElementException(field, "Input field type must be an interface or assignable to Node"); } if (modifiers.contains(FINAL)) { throw new ElementException(field, "Input field must not be final"); } if (modifiers.contains(PUBLIC)) { throw new ElementException(field, "Input field must not be public"); } } } else if (isSuccessor) { if (isAssignableWithErasure(field, NodeSuccessorList)) { if (modifiers.contains(FINAL)) { throw new ElementException(field, "Successor list field must not be final"); } if (modifiers.contains(PUBLIC)) { throw new ElementException(field, "Successor list field must not be public"); } } else { if (!isAssignableWithErasure(field, Node)) { throw new ElementException(field, "Successor field must be a Node type"); } if (modifiers.contains(FINAL)) { throw new ElementException(field, "Successor field must not be final"); } if (modifiers.contains(PUBLIC)) { throw new ElementException(field, "Successor field must not be public"); } } } else { if (isAssignableWithErasure(field, Node) && !field.getSimpleName().contentEquals("Null")) { throw new ElementException(field, "Node field must be annotated with @" + Input.getSimpleName() + ", @" + OptionalInput.getSimpleName() + " or @" + Successor.getSimpleName()); } if (isAssignableWithErasure(field, NodeInputList)) { throw new ElementException(field, "NodeInputList field must be annotated with @" + Input.getSimpleName() + " or @" + OptionalInput.getSimpleName()); } if (isAssignableWithErasure(field, NodeSuccessorList)) { throw new ElementException(field, "NodeSuccessorList field must be annotated with @" + Successor.getSimpleName()); } if (modifiers.contains(PUBLIC) && !modifiers.contains(FINAL)) { throw new ElementException(field, "Data field must be final if public"); } } } currentClazz = getSuperType(currentClazz); } while (!isObject(getSuperType(currentClazz).asType())); } private AnnotationMirror findAnnotationMirror(List<? extends AnnotationMirror> mirrors, TypeElement expectedAnnotationType) { for (AnnotationMirror mirror : mirrors) { if (sameType(mirror.getAnnotationType(), expectedAnnotationType.asType())) { return mirror; } } return null; } private boolean isObject(TypeMirror type) { return sameType(object.asType(), type); } private boolean sameType(TypeMirror type1, TypeMirror type2) { return env.getProcessingEnv().getTypeUtils().isSameType(type1, type2); } private TypeElement getSuperType(TypeElement element) { if (element.getSuperclass() != null) { return (TypeElement) env.getProcessingEnv().getTypeUtils().asElement(element.getSuperclass()); } return null; } void verify(TypeElement node) { scanFields(node); boolean foundValidConstructor = false; for (ExecutableElement constructor : ElementFilter.constructorsIn(node.getEnclosedElements())) { if (constructor.getModifiers().contains(PRIVATE)) { continue; } else if (!constructor.getModifiers().contains(PUBLIC) && !constructor.getModifiers().contains(PROTECTED)) { throw new ElementException(constructor, "Node class constructor must be public or protected"); } foundValidConstructor = true; } if (!foundValidConstructor) { throw new ElementException(node, "Node class must have at least one protected constructor"); } } }