Mercurial > hg > graal-compiler
comparison graal/com.oracle.jvmci.debug/src/com/oracle/jvmci/debug/JVMCIDebugConfig.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/GraalDebugConfig.java@a9f347ae6f5f |
children | 5b9adb645217 |
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 java.io.*; | |
26 import java.util.*; | |
27 | |
28 import com.oracle.jvmci.code.*; | |
29 import com.oracle.jvmci.meta.*; | |
30 import com.oracle.jvmci.options.*; | |
31 | |
32 public class JVMCIDebugConfig implements DebugConfig { | |
33 @SuppressWarnings("all") | |
34 private static boolean assertionsEnabled() { | |
35 boolean assertionsEnabled = false; | |
36 assert assertionsEnabled = true; | |
37 return assertionsEnabled; | |
38 } | |
39 | |
40 // @formatter:off | |
41 @Option(help = "Pattern for scope(s) in which dumping is enabled (see DebugFilter and Debug.dump)", type = OptionType.Debug) | |
42 public static final OptionValue<String> Dump = new OptionValue<>(null); | |
43 @Option(help = "Pattern for scope(s) in which metering is enabled (see DebugFilter and Debug.metric). " + | |
44 "An empty value enables all metrics unconditionally.", type = OptionType.Debug) | |
45 public static final OptionValue<String> Meter = new OptionValue<>(null); | |
46 @Option(help = "Pattern for scope(s) in which verification is enabled (see DebugFilter and Debug.verify).", type = OptionType.Debug) | |
47 public static final OptionValue<String> Verify = new OptionValue<String>() { | |
48 @Override | |
49 protected String defaultValue() { | |
50 return assertionsEnabled() ? "" : null; | |
51 } | |
52 }; | |
53 @Option(help = "Pattern for scope(s) in which memory use tracking is enabled (see DebugFilter and Debug.metric). " + | |
54 "An empty value enables all memory use trackers unconditionally.", type = OptionType.Debug) | |
55 public static final OptionValue<String> TrackMemUse = new OptionValue<>(null); | |
56 @Option(help = "Pattern for scope(s) in which timing is enabled (see DebugFilter and Debug.timer). " + | |
57 "An empty value enables all timers unconditionally.", type = OptionType.Debug) | |
58 public static final OptionValue<String> Time = new OptionValue<>(null); | |
59 @Option(help = "Pattern for scope(s) in which logging is enabled (see DebugFilter and Debug.log)", type = OptionType.Debug) | |
60 public static final OptionValue<String> Log = new OptionValue<>(null); | |
61 @Option(help = "Pattern for filtering debug scope output based on method context (see MethodFilter)", type = OptionType.Debug) | |
62 public static final OptionValue<String> MethodFilter = new OptionValue<>(null); | |
63 @Option(help = "Only check MethodFilter against the root method in the context if true, otherwise check all methods", type = OptionType.Debug) | |
64 public static final OptionValue<Boolean> MethodFilterRootOnly = new OptionValue<>(false); | |
65 | |
66 @Option(help = "How to print metric and timing values:%n" + | |
67 "Name - aggregate by unqualified name%n" + | |
68 "Partial - aggregate by partially qualified name (e.g., A.B.C.D.Counter and X.Y.Z.D.Counter will be merged to D.Counter)%n" + | |
69 "Complete - aggregate by qualified name%n" + | |
70 "Thread - aggregate by qualified name and thread", type = OptionType.Debug) | |
71 public static final OptionValue<String> DebugValueSummary = new OptionValue<>("Name"); | |
72 @Option(help = "Omit reporting 0-value metrics", type = OptionType.Debug) | |
73 public static final OptionValue<Boolean> SuppressZeroDebugValues = new OptionValue<>(true); | |
74 @Option(help = "Only report debug values for maps which match the regular expression.", type = OptionType.Debug) | |
75 public static final OptionValue<String> DebugValueThreadFilter = new OptionValue<>(null); | |
76 @Option(help = "Send Graal IR to dump handlers on error", type = OptionType.Debug) | |
77 public static final OptionValue<Boolean> DumpOnError = new OptionValue<>(false); | |
78 @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug) | |
79 public static final OptionValue<Boolean> InterceptBailout = new OptionValue<>(false); | |
80 @Option(help = "Enable more verbose log output when available", type = OptionType.Debug) | |
81 public static final OptionValue<Boolean> LogVerbose = new OptionValue<>(false); | |
82 // @formatter:on | |
83 | |
84 static boolean isNotEmpty(OptionValue<String> option) { | |
85 return option.getValue() != null && !option.getValue().isEmpty(); | |
86 } | |
87 | |
88 public static boolean areDebugScopePatternsEnabled() { | |
89 return DumpOnError.getValue() || Dump.getValue() != null || Log.getValue() != null || areScopedMetricsOrTimersEnabled(); | |
90 } | |
91 | |
92 /** | |
93 * Determines if any of {@link #Meter}, {@link #Time} or {@link #TrackMemUse} has a non-null, | |
94 * non-empty value. | |
95 */ | |
96 public static boolean areScopedMetricsOrTimersEnabled() { | |
97 return isNotEmpty(Meter) || isNotEmpty(Time) || isNotEmpty(TrackMemUse); | |
98 } | |
99 | |
100 private final DebugFilter logFilter; | |
101 private final DebugFilter meterFilter; | |
102 private final DebugFilter trackMemUseFilter; | |
103 private final DebugFilter timerFilter; | |
104 private final DebugFilter dumpFilter; | |
105 private final DebugFilter verifyFilter; | |
106 private final MethodFilter[] methodFilter; | |
107 private final List<DebugDumpHandler> dumpHandlers; | |
108 private final List<DebugVerifyHandler> verifyHandlers; | |
109 private final PrintStream output; | |
110 private final Set<Object> extraFilters = new HashSet<>(); | |
111 | |
112 public JVMCIDebugConfig(String logFilter, String meterFilter, String trackMemUseFilter, String timerFilter, String dumpFilter, String verifyFilter, String methodFilter, PrintStream output, | |
113 List<DebugDumpHandler> dumpHandlers, List<DebugVerifyHandler> verifyHandlers) { | |
114 this.logFilter = DebugFilter.parse(logFilter); | |
115 this.meterFilter = DebugFilter.parse(meterFilter); | |
116 this.trackMemUseFilter = DebugFilter.parse(trackMemUseFilter); | |
117 this.timerFilter = DebugFilter.parse(timerFilter); | |
118 this.dumpFilter = DebugFilter.parse(dumpFilter); | |
119 this.verifyFilter = DebugFilter.parse(verifyFilter); | |
120 if (methodFilter == null || methodFilter.isEmpty()) { | |
121 this.methodFilter = null; | |
122 } else { | |
123 this.methodFilter = com.oracle.jvmci.debug.MethodFilter.parse(methodFilter); | |
124 } | |
125 | |
126 // Report the filters that have been configured so the user can verify it's what they expect | |
127 if (logFilter != null || meterFilter != null || timerFilter != null || dumpFilter != null || methodFilter != null) { | |
128 // TTY.println(Thread.currentThread().getName() + ": " + toString()); | |
129 } | |
130 this.dumpHandlers = dumpHandlers; | |
131 this.verifyHandlers = verifyHandlers; | |
132 this.output = output; | |
133 } | |
134 | |
135 public int getLogLevel() { | |
136 return getLevel(logFilter); | |
137 } | |
138 | |
139 public boolean isLogEnabledForMethod() { | |
140 return isEnabledForMethod(logFilter); | |
141 } | |
142 | |
143 public boolean isMeterEnabled() { | |
144 return isEnabled(meterFilter); | |
145 } | |
146 | |
147 public boolean isMemUseTrackingEnabled() { | |
148 return isEnabled(trackMemUseFilter); | |
149 } | |
150 | |
151 public int getDumpLevel() { | |
152 return getLevel(dumpFilter); | |
153 } | |
154 | |
155 public boolean isDumpEnabledForMethod() { | |
156 return isEnabledForMethod(dumpFilter); | |
157 } | |
158 | |
159 public boolean isVerifyEnabled() { | |
160 return isEnabled(verifyFilter); | |
161 } | |
162 | |
163 public boolean isVerifyEnabledForMethod() { | |
164 return isEnabledForMethod(verifyFilter); | |
165 } | |
166 | |
167 public boolean isTimeEnabled() { | |
168 return isEnabled(timerFilter); | |
169 } | |
170 | |
171 public PrintStream output() { | |
172 return output; | |
173 } | |
174 | |
175 private boolean isEnabled(DebugFilter filter) { | |
176 return getLevel(filter) > 0; | |
177 } | |
178 | |
179 private int getLevel(DebugFilter filter) { | |
180 int level; | |
181 if (filter == null) { | |
182 level = 0; | |
183 } else { | |
184 level = filter.matchLevel(Debug.currentScope()); | |
185 } | |
186 if (level > 0 && !checkMethodFilter()) { | |
187 level = 0; | |
188 } | |
189 return level; | |
190 } | |
191 | |
192 private boolean isEnabledForMethod(DebugFilter filter) { | |
193 return filter != null && checkMethodFilter(); | |
194 } | |
195 | |
196 /** | |
197 * Extracts a {@link JavaMethod} from an opaque debug context. | |
198 * | |
199 * @return the {@link JavaMethod} represented by {@code context} or null | |
200 */ | |
201 public static JavaMethod asJavaMethod(Object context) { | |
202 if (context instanceof JavaMethodContex) { | |
203 return ((JavaMethodContex) context).asJavaMethod(); | |
204 } | |
205 return null; | |
206 } | |
207 | |
208 private boolean checkMethodFilter() { | |
209 if (methodFilter == null && extraFilters.isEmpty()) { | |
210 return true; | |
211 } else { | |
212 JavaMethod lastMethod = null; | |
213 for (Object o : Debug.context()) { | |
214 if (extraFilters.contains(o)) { | |
215 return true; | |
216 } else if (methodFilter != null) { | |
217 JavaMethod method = asJavaMethod(o); | |
218 if (method != null) { | |
219 if (!MethodFilterRootOnly.getValue()) { | |
220 if (com.oracle.jvmci.debug.MethodFilter.matches(methodFilter, method)) { | |
221 return true; | |
222 } | |
223 } else { | |
224 /* | |
225 * The context values operate as a stack so if we want MethodFilter to | |
226 * only apply to the root method we have to check only the last method | |
227 * seen. | |
228 */ | |
229 lastMethod = method; | |
230 } | |
231 } | |
232 } | |
233 } | |
234 if (lastMethod != null && com.oracle.jvmci.debug.MethodFilter.matches(methodFilter, lastMethod)) { | |
235 return true; | |
236 } | |
237 return false; | |
238 } | |
239 } | |
240 | |
241 @Override | |
242 public String toString() { | |
243 StringBuilder sb = new StringBuilder(); | |
244 sb.append("Debug config:"); | |
245 add(sb, "Log", logFilter); | |
246 add(sb, "Meter", meterFilter); | |
247 add(sb, "Time", timerFilter); | |
248 add(sb, "Dump", dumpFilter); | |
249 add(sb, "MethodFilter", methodFilter); | |
250 return sb.toString(); | |
251 } | |
252 | |
253 private static void add(StringBuilder sb, String name, Object filter) { | |
254 if (filter != null) { | |
255 sb.append(' '); | |
256 sb.append(name); | |
257 sb.append('='); | |
258 if (filter instanceof Object[]) { | |
259 sb.append(Arrays.toString((Object[]) filter)); | |
260 } else { | |
261 sb.append(String.valueOf(filter)); | |
262 } | |
263 } | |
264 } | |
265 | |
266 @Override | |
267 public RuntimeException interceptException(Throwable e) { | |
268 if (e instanceof BailoutException && !InterceptBailout.getValue()) { | |
269 return null; | |
270 } | |
271 Debug.setConfig(Debug.fixedConfig(Debug.DEFAULT_LOG_LEVEL, Debug.DEFAULT_LOG_LEVEL, false, false, false, false, dumpHandlers, verifyHandlers, output)); | |
272 Debug.log(String.format("Exception occurred in scope: %s", Debug.currentScope())); | |
273 for (Object o : Debug.context()) { | |
274 if (DumpOnError.getValue()) { | |
275 Debug.dump(o, "Exception"); | |
276 } else { | |
277 Debug.log("Context obj %s", o); | |
278 } | |
279 | |
280 } | |
281 return null; | |
282 } | |
283 | |
284 @Override | |
285 public Collection<DebugDumpHandler> dumpHandlers() { | |
286 return dumpHandlers; | |
287 } | |
288 | |
289 @Override | |
290 public Collection<DebugVerifyHandler> verifyHandlers() { | |
291 return verifyHandlers; | |
292 } | |
293 | |
294 @Override | |
295 public void addToContext(Object o) { | |
296 extraFilters.add(o); | |
297 } | |
298 | |
299 @Override | |
300 public void removeFromContext(Object o) { | |
301 extraFilters.remove(o); | |
302 } | |
303 } |