VerifyNodeCosts.java revision 13017:134219a5b0ec
1215911Sjfv/*
2215911Sjfv * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
3320897Serj * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4215911Sjfv *
5215911Sjfv * This code is free software; you can redistribute it and/or modify it
6215911Sjfv * under the terms of the GNU General Public License version 2 only, as
7215911Sjfv * published by the Free Software Foundation.
8215911Sjfv *
9215911Sjfv * This code is distributed in the hope that it will be useful, but WITHOUT
10215911Sjfv * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11215911Sjfv * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12215911Sjfv * version 2 for more details (a copy is included in the LICENSE file that
13215911Sjfv * accompanied this code).
14215911Sjfv *
15215911Sjfv * You should have received a copy of the GNU General Public License version
16215911Sjfv * 2 along with this work; if not, write to the Free Software Foundation,
17215911Sjfv * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18215911Sjfv *
19215911Sjfv * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20215911Sjfv * or visit www.oracle.com if you need additional information or have any
21215911Sjfv * questions.
22215911Sjfv */
23215911Sjfvpackage org.graalvm.compiler.phases.contract;
24215911Sjfv
25215911Sjfvimport java.lang.reflect.Field;
26215911Sjfvimport java.lang.reflect.Modifier;
27215911Sjfvimport java.util.function.Predicate;
28215911Sjfv
29215911Sjfvimport org.graalvm.compiler.graph.Node;
30215911Sjfvimport org.graalvm.compiler.graph.NodeClass;
31215911Sjfvimport org.graalvm.compiler.nodeinfo.NodeCycles;
32215911Sjfvimport org.graalvm.compiler.nodeinfo.NodeInfo;
33215911Sjfvimport org.graalvm.compiler.nodeinfo.NodeSize;
34215911Sjfvimport org.graalvm.compiler.phases.VerifyPhase;
35320897Serj
36320897Serj/**
37215911Sjfv * Utility class that verifies that every {@link Class} extending {@link Node} specifies non default
38230775Sjfv * values for {@link NodeCycles} and {@link NodeSize} in its {@link NodeInfo} annotation.
39230775Sjfv */
40230775Sjfvpublic class VerifyNodeCosts {
41215911Sjfv
42247822Sjfv    public static void verifyNodeClass(Class<?> clazz) {
43247822Sjfv        Class<?> nodeClass = Node.class;
44247822Sjfv        if (nodeClass.isAssignableFrom(clazz)) {
45230775Sjfv            if (!clazz.isAnnotationPresent(NodeInfo.class)) {
46230775Sjfv                throw new VerifyPhase.VerificationError("%s.java extends Node.java but does not specify a NodeInfo annotation.", clazz.getName());
47230775Sjfv            }
48230775Sjfv
49230775Sjfv            if (!Modifier.isAbstract(clazz.getModifiers())) {
50230775Sjfv                boolean cyclesSet = walkCHUntil(getType(clazz), getType(nodeClass), cur -> {
51230775Sjfv                    return cur.cycles() != NodeCycles.CYCLES_UNSET;
52230775Sjfv                });
53230775Sjfv                boolean sizeSet = walkCHUntil(getType(clazz), getType(nodeClass), cur -> {
54230775Sjfv                    return cur.size() != NodeSize.SIZE_UNSET;
55230775Sjfv                });
56230775Sjfv                if (!cyclesSet) {
57230775Sjfv                    throw new VerifyPhase.VerificationError("%s.java does not specify a NodeCycles value in its class hierarchy.", clazz.getName());
58230775Sjfv                }
59230775Sjfv                if (!sizeSet) {
60215911Sjfv                    throw new VerifyPhase.VerificationError("%s.java does not specify a NodeSize value in its class hierarchy.", clazz.getName());
61230775Sjfv                }
62230775Sjfv            }
63230775Sjfv        }
64230775Sjfv    }
65230775Sjfv
66230775Sjfv    private static NodeClass<?> getType(Class<?> c) {
67230775Sjfv        Field f;
68230775Sjfv        try {
69230775Sjfv            f = c.getField("TYPE");
70230775Sjfv            f.setAccessible(true);
71230775Sjfv            Object val = f.get(null);
72230775Sjfv            NodeClass<?> nodeType = (NodeClass<?>) val;
73230775Sjfv            return nodeType;
74230775Sjfv        } catch (Throwable t) {
75230775Sjfv            throw new VerifyPhase.VerificationError("%s.java does not specify a TYPE field.", c.getName());
76230775Sjfv        }
77230775Sjfv    }
78230775Sjfv
79230775Sjfv    private static boolean walkCHUntil(NodeClass<?> start, NodeClass<?> until, Predicate<NodeClass<?>> p) {
80230775Sjfv        NodeClass<?> cur = start;
81230775Sjfv        while (cur != until && cur != null) {
82230775Sjfv            if (p.test(cur)) {
83230775Sjfv                return true;
84230775Sjfv            }
85230775Sjfv            cur = cur.getSuperNodeClass();
86230775Sjfv        }
87280182Sjfv        return false;
88280182Sjfv    }
89280182Sjfv
90215911Sjfv}
91215911Sjfv