Mercurial > hg > graal-compiler
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 } |