comparison graal/com.oracle.jvmci.debug/src/com/oracle/jvmci/debug/MethodFilter.java @ 21780:3d15183f3c93

Introduce Compiler interface in jvmci. Use it from jvmci.hotspot.CompilationTask
author Gilles Duboscq <gilles.m.duboscq@oracle.com>
date Wed, 03 Jun 2015 15:47:54 +0200
parents graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/MethodFilter.java@f5b549811bac
children
comparison
equal deleted inserted replaced
21779:20ace3139510 21780:3d15183f3c93
1 /*
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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 com.oracle.jvmci.debug;
24
25 import com.oracle.jvmci.meta.JavaType;
26 import com.oracle.jvmci.meta.JavaMethod;
27 import com.oracle.jvmci.meta.Signature;
28 import java.util.*;
29 import java.util.regex.*;
30
31 /**
32 * This class implements a method filter that can filter based on class name, method name and
33 * parameters. The syntax for the source pattern that is passed to the constructor is as follows:
34 *
35 * <pre>
36 * SourcePatterns = SourcePattern ["," SourcePatterns] .
37 * SourcePattern = [ Class "." ] method [ "(" [ Parameter { ";" Parameter } ] ")" ] .
38 * Parameter = Class | "int" | "long" | "float" | "double" | "short" | "char" | "boolean" .
39 * Class = { package "." } class .
40 * </pre>
41 *
42 *
43 * Glob pattern matching (*, ?) is allowed in all parts of the source pattern. Examples for valid
44 * filters are:
45 *
46 * <ul>
47 * <li>
48 *
49 * <pre>
50 * visit(Argument;BlockScope)
51 * </pre>
52 *
53 * Matches all methods named "visit", with the first parameter of type "Argument", and the second
54 * parameter of type "BlockScope". The packages of the parameter types are irrelevant.</li>
55 * <li>
56 *
57 * <pre>
58 * arraycopy(Object;;;;)
59 * </pre>
60 *
61 * Matches all methods named "arraycopy", with the first parameter of type "Object", and four more
62 * parameters of any type. The packages of the parameter types are irrelevant.</li>
63 * <li>
64 *
65 * <pre>
66 * com.oracle.graal.compiler.graph.PostOrderNodeIterator.*
67 * </pre>
68 *
69 * Matches all methods in the class "com.oracle.graal.compiler.graph.PostOrderNodeIterator".</li>
70 * <li>
71 *
72 * <pre>
73 * *
74 * </pre>
75 *
76 * Matches all methods in all classes</li>
77 * <li>
78 *
79 * <pre>
80 * com.oracle.graal.compiler.graph.*.visit
81 * </pre>
82 *
83 * Matches all methods named "visit" in classes in the package "com.oracle.graal.compiler.graph".
84 * <li>
85 *
86 * <pre>
87 * arraycopy,toString
88 * </pre>
89 *
90 * Matches all methods named "arraycopy" or "toString", meaning that ',' acts as an <i>or</i>
91 * operator.</li>
92 * </ul>
93 */
94 public class MethodFilter {
95
96 private final Pattern clazz;
97 private final Pattern methodName;
98 private final Pattern[] signature;
99
100 /**
101 * Parses a string containing list of comma separated filter patterns into an array of
102 * {@link MethodFilter}s.
103 */
104 public static MethodFilter[] parse(String commaSeparatedPatterns) {
105 String[] filters = commaSeparatedPatterns.split(",");
106 MethodFilter[] methodFilters = new MethodFilter[filters.length];
107 for (int i = 0; i < filters.length; i++) {
108 methodFilters[i] = new MethodFilter(filters[i]);
109 }
110 return methodFilters;
111 }
112
113 /**
114 * Determines if a given method is matched by a given array of filters.
115 */
116 public static boolean matches(MethodFilter[] filters, JavaMethod method) {
117 for (MethodFilter filter : filters) {
118 if (filter.matches(method)) {
119 return true;
120 }
121 }
122 return false;
123 }
124
125 /**
126 * Determines if a given class name is matched by a given array of filters.
127 */
128 public static boolean matchesClassName(MethodFilter[] filters, String className) {
129 for (MethodFilter filter : filters) {
130 if (filter.matchesClassName(className)) {
131 return true;
132 }
133 }
134 return false;
135 }
136
137 public MethodFilter(String sourcePattern) {
138 String pattern = sourcePattern.trim();
139
140 // extract parameter part
141 int pos = pattern.indexOf('(');
142 if (pos != -1) {
143 if (pattern.charAt(pattern.length() - 1) != ')') {
144 throw new IllegalArgumentException("missing ')' at end of method filter pattern: " + pattern);
145 }
146 String[] signatureClasses = pattern.substring(pos + 1, pattern.length() - 1).split(";", -1);
147 signature = new Pattern[signatureClasses.length];
148 for (int i = 0; i < signatureClasses.length; i++) {
149 signature[i] = createClassGlobPattern(signatureClasses[i].trim());
150 }
151 pattern = pattern.substring(0, pos);
152 } else {
153 signature = null;
154 }
155
156 // If there is at least one "." then everything before the last "." is the class name.
157 // Otherwise, the pattern contains only the method name.
158 pos = pattern.lastIndexOf('.');
159 if (pos != -1) {
160 clazz = createClassGlobPattern(pattern.substring(0, pos));
161 methodName = Pattern.compile(createGlobString(pattern.substring(pos + 1)));
162 } else {
163 clazz = null;
164 methodName = Pattern.compile(createGlobString(pattern));
165 }
166 }
167
168 static String createGlobString(String pattern) {
169 return Pattern.quote(pattern).replace("?", "\\E.\\Q").replace("*", "\\E.*\\Q");
170 }
171
172 private static Pattern createClassGlobPattern(String pattern) {
173 if (pattern.length() == 0) {
174 return null;
175 } else if (pattern.contains(".")) {
176 return Pattern.compile(createGlobString(pattern));
177 } else {
178 return Pattern.compile("([^\\.\\$]*[\\.\\$])*" + createGlobString(pattern));
179 }
180 }
181
182 /**
183 * Determines if the class part of this filter matches a given class name.
184 */
185 public boolean matchesClassName(String className) {
186 return clazz == null || clazz.matcher(className).matches();
187 }
188
189 public boolean matches(JavaMethod o) {
190 // check method name first, since MetaUtil.toJavaName is expensive
191 if (methodName != null && !methodName.matcher(o.getName()).matches()) {
192 return false;
193 }
194 if (clazz != null && !clazz.matcher(o.getDeclaringClass().toJavaName()).matches()) {
195 return false;
196 }
197 if (signature != null) {
198 Signature sig = o.getSignature();
199 if (sig.getParameterCount(false) != signature.length) {
200 return false;
201 }
202 for (int i = 0; i < signature.length; i++) {
203 JavaType type = sig.getParameterType(i, null);
204 String javaName = type.toJavaName();
205 if (signature[i] != null && !signature[i].matcher(javaName).matches()) {
206 return false;
207 }
208 }
209 }
210 return true;
211 }
212
213 @Override
214 public String toString() {
215 StringBuilder buf = new StringBuilder("MethodFilter[");
216 String sep = "";
217 if (clazz != null) {
218 buf.append(sep).append("clazz=").append(clazz);
219 sep = ", ";
220 }
221 if (methodName != null) {
222 buf.append(sep).append("methodName=").append(methodName);
223 sep = ", ";
224 }
225 if (signature != null) {
226 buf.append(sep).append("signature=").append(Arrays.toString(signature));
227 sep = ", ";
228 }
229 return buf.append("]").toString();
230 }
231 }