5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.core.match; 24 25 import org.graalvm.compiler.debug.Debug; 26 import org.graalvm.compiler.debug.DebugCounter; 27 import org.graalvm.compiler.graph.Node; 28 import org.graalvm.compiler.graph.Position; 29 import org.graalvm.compiler.nodeinfo.InputType; 30 import org.graalvm.compiler.nodeinfo.Verbosity; 31 32 /** 33 * A simple recursive pattern matcher for a DAG of nodes. 34 */ 35 36 public class MatchPattern { 37 38 enum MatchResultCode { 39 OK, 40 WRONG_CLASS, 41 NAMED_VALUE_MISMATCH, 42 TOO_MANY_USERS, 43 NOT_IN_BLOCK, 44 NOT_SAFE, 45 ALREADY_USED, 46 } 47 48 /** 49 * A descriptive result for match failures. This can be helpful for debugging why a match 50 * doesn't work as expected. 51 */ 52 static class Result { 53 final MatchResultCode code; 54 55 final Node node; 56 57 final MatchPattern matcher; 58 59 Result(MatchResultCode result, Node node, MatchPattern matcher) { 60 this.code = result; 61 this.node = node; 62 this.matcher = matcher; 63 } 64 65 private static final DebugCounter MatchResult_WRONG_CLASS = Debug.counter("MatchResult_WRONG_CLASS"); 66 private static final DebugCounter MatchResult_NAMED_VALUE_MISMATCH = Debug.counter("MatchResult_NAMED_VALUE_MISMATCH"); 67 private static final DebugCounter MatchResult_TOO_MANY_USERS = Debug.counter("MatchResult_TOO_MANY_USERS"); 68 private static final DebugCounter MatchResult_NOT_IN_BLOCK = Debug.counter("MatchResult_NOT_IN_BLOCK"); 69 private static final DebugCounter MatchResult_NOT_SAFE = Debug.counter("MatchResult_NOT_SAFE"); 70 private static final DebugCounter MatchResult_ALREADY_USED = Debug.counter("MatchResult_ALREADY_USED"); 71 72 static final Result OK = new Result(MatchResultCode.OK, null, null); 73 private static final Result CACHED_WRONG_CLASS = new Result(MatchResultCode.WRONG_CLASS, null, null); 74 private static final Result CACHED_NAMED_VALUE_MISMATCH = new Result(MatchResultCode.NAMED_VALUE_MISMATCH, null, null); 75 private static final Result CACHED_TOO_MANY_USERS = new Result(MatchResultCode.TOO_MANY_USERS, null, null); 76 private static final Result CACHED_NOT_IN_BLOCK = new Result(MatchResultCode.NOT_IN_BLOCK, null, null); 77 private static final Result CACHED_NOT_SAFE = new Result(MatchResultCode.NOT_SAFE, null, null); 78 private static final Result CACHED_ALREADY_USED = new Result(MatchResultCode.ALREADY_USED, null, null); 79 80 static Result wrongClass(Node node, MatchPattern matcher) { 81 MatchResult_WRONG_CLASS.increment(); 82 return Debug.isLogEnabled() ? new Result(MatchResultCode.WRONG_CLASS, node, matcher) : CACHED_WRONG_CLASS; 83 } 84 85 static Result namedValueMismatch(Node node, MatchPattern matcher) { 86 MatchResult_NAMED_VALUE_MISMATCH.increment(); 87 return Debug.isLogEnabled() ? new Result(MatchResultCode.NAMED_VALUE_MISMATCH, node, matcher) : CACHED_NAMED_VALUE_MISMATCH; 88 } 89 90 static Result tooManyUsers(Node node, MatchPattern matcher) { 91 MatchResult_TOO_MANY_USERS.increment(); 92 return Debug.isLogEnabled() ? new Result(MatchResultCode.TOO_MANY_USERS, node, matcher) : CACHED_TOO_MANY_USERS; 93 } 94 95 static Result notInBlock(Node node, MatchPattern matcher) { 96 MatchResult_NOT_IN_BLOCK.increment(); 97 return Debug.isLogEnabled() ? new Result(MatchResultCode.NOT_IN_BLOCK, node, matcher) : CACHED_NOT_IN_BLOCK; 98 } 99 100 static Result notSafe(Node node, MatchPattern matcher) { 101 MatchResult_NOT_SAFE.increment(); 102 return Debug.isLogEnabled() ? new Result(MatchResultCode.NOT_SAFE, node, matcher) : CACHED_NOT_SAFE; 103 } 104 105 static Result alreadyUsed(Node node, MatchPattern matcher) { 106 MatchResult_ALREADY_USED.increment(); 107 return Debug.isLogEnabled() ? new Result(MatchResultCode.ALREADY_USED, node, matcher) : CACHED_ALREADY_USED; 108 } 109 110 @Override 111 public String toString() { 112 if (code == MatchResultCode.OK) { 113 return "OK"; 114 } 115 if (node == null) { 116 return code.toString(); 117 } else { 118 return code + " " + node.toString(Verbosity.Id) + "|" + node.getClass().getSimpleName() + " " + matcher; 119 } 120 } 121 } 122 123 /** 124 * The expected type of the node. It must match exactly. 125 */ 126 private final Class<? extends Node> nodeClass; 127 | 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.core.match; 24 25 import org.graalvm.compiler.debug.CounterKey; 26 import org.graalvm.compiler.debug.DebugContext; 27 import org.graalvm.compiler.graph.Node; 28 import org.graalvm.compiler.graph.Position; 29 import org.graalvm.compiler.nodeinfo.InputType; 30 import org.graalvm.compiler.nodeinfo.Verbosity; 31 32 /** 33 * A simple recursive pattern matcher for a DAG of nodes. 34 */ 35 36 public class MatchPattern { 37 38 enum MatchResultCode { 39 OK, 40 WRONG_CLASS, 41 NAMED_VALUE_MISMATCH, 42 TOO_MANY_USERS, 43 NOT_IN_BLOCK, 44 NOT_SAFE, 45 ALREADY_USED, 46 } 47 48 /** 49 * A descriptive result for match failures. This can be helpful for debugging why a match 50 * doesn't work as expected. 51 */ 52 static class Result { 53 final MatchResultCode code; 54 55 final Node node; 56 57 final MatchPattern matcher; 58 59 Result(MatchResultCode result, Node node, MatchPattern matcher) { 60 this.code = result; 61 this.node = node; 62 this.matcher = matcher; 63 } 64 65 private static final CounterKey MatchResult_WRONG_CLASS = DebugContext.counter("MatchResult_WRONG_CLASS"); 66 private static final CounterKey MatchResult_NAMED_VALUE_MISMATCH = DebugContext.counter("MatchResult_NAMED_VALUE_MISMATCH"); 67 private static final CounterKey MatchResult_TOO_MANY_USERS = DebugContext.counter("MatchResult_TOO_MANY_USERS"); 68 private static final CounterKey MatchResult_NOT_IN_BLOCK = DebugContext.counter("MatchResult_NOT_IN_BLOCK"); 69 private static final CounterKey MatchResult_NOT_SAFE = DebugContext.counter("MatchResult_NOT_SAFE"); 70 private static final CounterKey MatchResult_ALREADY_USED = DebugContext.counter("MatchResult_ALREADY_USED"); 71 72 static final Result OK = new Result(MatchResultCode.OK, null, null); 73 private static final Result CACHED_WRONG_CLASS = new Result(MatchResultCode.WRONG_CLASS, null, null); 74 private static final Result CACHED_NAMED_VALUE_MISMATCH = new Result(MatchResultCode.NAMED_VALUE_MISMATCH, null, null); 75 private static final Result CACHED_TOO_MANY_USERS = new Result(MatchResultCode.TOO_MANY_USERS, null, null); 76 private static final Result CACHED_NOT_IN_BLOCK = new Result(MatchResultCode.NOT_IN_BLOCK, null, null); 77 private static final Result CACHED_NOT_SAFE = new Result(MatchResultCode.NOT_SAFE, null, null); 78 private static final Result CACHED_ALREADY_USED = new Result(MatchResultCode.ALREADY_USED, null, null); 79 80 static Result wrongClass(Node node, MatchPattern matcher) { 81 MatchResult_WRONG_CLASS.increment(node.getDebug()); 82 return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.WRONG_CLASS, node, matcher) : CACHED_WRONG_CLASS; 83 } 84 85 static Result namedValueMismatch(Node node, MatchPattern matcher) { 86 MatchResult_NAMED_VALUE_MISMATCH.increment(node.getDebug()); 87 return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.NAMED_VALUE_MISMATCH, node, matcher) : CACHED_NAMED_VALUE_MISMATCH; 88 } 89 90 static Result tooManyUsers(Node node, MatchPattern matcher) { 91 MatchResult_TOO_MANY_USERS.increment(node.getDebug()); 92 return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.TOO_MANY_USERS, node, matcher) : CACHED_TOO_MANY_USERS; 93 } 94 95 static Result notInBlock(Node node, MatchPattern matcher) { 96 MatchResult_NOT_IN_BLOCK.increment(node.getDebug()); 97 return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.NOT_IN_BLOCK, node, matcher) : CACHED_NOT_IN_BLOCK; 98 } 99 100 static Result notSafe(Node node, MatchPattern matcher) { 101 MatchResult_NOT_SAFE.increment(node.getDebug()); 102 return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.NOT_SAFE, node, matcher) : CACHED_NOT_SAFE; 103 } 104 105 static Result alreadyUsed(Node node, MatchPattern matcher) { 106 MatchResult_ALREADY_USED.increment(node.getDebug()); 107 return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.ALREADY_USED, node, matcher) : CACHED_ALREADY_USED; 108 } 109 110 @Override 111 public String toString() { 112 if (code == MatchResultCode.OK) { 113 return "OK"; 114 } 115 if (node == null) { 116 return code.toString(); 117 } else { 118 return code + " " + node.toString(Verbosity.Id) + "|" + node.getClass().getSimpleName() + " " + matcher; 119 } 120 } 121 } 122 123 /** 124 * The expected type of the node. It must match exactly. 125 */ 126 private final Class<? extends Node> nodeClass; 127 |