--- /dev/null 2017-07-07 09:32:04.000000000 -0700 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigImpl.java 2017-07-07 09:32:04.000000000 -0700 @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import static org.graalvm.compiler.debug.DebugContext.BASIC_LEVEL; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; + +import org.graalvm.compiler.options.OptionValues; + +import jdk.vm.ci.code.BailoutException; +import jdk.vm.ci.meta.JavaMethod; + +final class DebugConfigImpl implements DebugConfig { + + private final OptionValues options; + + private final DebugFilter countFilter; + private final DebugFilter logFilter; + private final DebugFilter trackMemUseFilter; + private final DebugFilter timerFilter; + private final DebugFilter dumpFilter; + private final DebugFilter verifyFilter; + private final MethodFilter[] methodFilter; + private final List dumpHandlers; + private final List verifyHandlers; + private final PrintStream output; + + DebugConfigImpl(OptionValues options) { + this(options, TTY.out, Collections.emptyList(), Collections.emptyList()); + } + + DebugConfigImpl(OptionValues options, PrintStream output, + List dumpHandlers, + List verifyHandlers) { + this(options, DebugOptions.Log.getValue(options), + DebugOptions.Count.getValue(options), + DebugOptions.TrackMemUse.getValue(options), + DebugOptions.Time.getValue(options), + DebugOptions.Dump.getValue(options), + DebugOptions.Verify.getValue(options), + DebugOptions.MethodFilter.getValue(options), + output, dumpHandlers, verifyHandlers); + } + + DebugConfigImpl(OptionValues options, + String logFilter, + String countFilter, + String trackMemUseFilter, + String timerFilter, + String dumpFilter, + String verifyFilter, + String methodFilter, + PrintStream output, + List dumpHandlers, + List verifyHandlers) { + this.options = options; + this.logFilter = DebugFilter.parse(logFilter); + this.countFilter = DebugFilter.parse(countFilter); + this.trackMemUseFilter = DebugFilter.parse(trackMemUseFilter); + this.timerFilter = DebugFilter.parse(timerFilter); + this.dumpFilter = DebugFilter.parse(dumpFilter); + this.verifyFilter = DebugFilter.parse(verifyFilter); + if (methodFilter == null || methodFilter.isEmpty()) { + this.methodFilter = null; + } else { + this.methodFilter = org.graalvm.compiler.debug.MethodFilter.parse(methodFilter); + } + + this.dumpHandlers = Collections.unmodifiableList(dumpHandlers); + this.verifyHandlers = Collections.unmodifiableList(verifyHandlers); + this.output = output; + } + + @Override + public OptionValues getOptions() { + return options; + } + + @Override + public int getLogLevel(DebugContext.Scope scope) { + return getLevel(scope, logFilter); + } + + @Override + public boolean isLogEnabledForMethod(DebugContext.Scope scope) { + return isEnabledForMethod(scope, logFilter); + } + + @Override + public boolean isCountEnabled(DebugContext.Scope scope) { + return isEnabled(scope, countFilter); + } + + @Override + public boolean isMemUseTrackingEnabled(DebugContext.Scope scope) { + return isEnabled(scope, trackMemUseFilter); + } + + @Override + public int getDumpLevel(DebugContext.Scope scope) { + return getLevel(scope, dumpFilter); + } + + @Override + public boolean isDumpEnabledForMethod(DebugContext.Scope scope) { + return isEnabledForMethod(scope, dumpFilter); + } + + @Override + public boolean isVerifyEnabled(DebugContext.Scope scope) { + return isEnabled(scope, verifyFilter); + } + + @Override + public boolean isVerifyEnabledForMethod(DebugContext.Scope scope) { + return isEnabledForMethod(scope, verifyFilter); + } + + @Override + public boolean isTimeEnabled(DebugContext.Scope scope) { + return isEnabled(scope, timerFilter); + } + + @Override + public PrintStream output() { + return output; + } + + private boolean isEnabled(DebugContext.Scope scope, DebugFilter filter) { + return getLevel(scope, filter) > 0; + } + + private int getLevel(DebugContext.Scope scope, DebugFilter filter) { + int level; + if (filter == null) { + level = 0; + } else { + String currentScope = scope.getQualifiedName(); + level = filter.matchLevel(currentScope); + } + if (level >= 0 && !checkMethodFilter(scope)) { + level = -1; + } + return level; + } + + private boolean isEnabledForMethod(DebugContext.Scope scope, DebugFilter filter) { + return filter != null && checkMethodFilter(scope); + } + + private boolean checkMethodFilter(DebugContext.Scope scope) { + if (methodFilter == null) { + return true; + } else { + JavaMethod lastMethod = null; + Iterable context = scope.getCurrentContext(); + for (Object o : context) { + if (methodFilter != null) { + JavaMethod method = DebugConfig.asJavaMethod(o); + if (method != null) { + if (!DebugOptions.MethodFilterRootOnly.getValue(options)) { + if (org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, method)) { + return true; + } + } else { + /* + * The context values operate as a stack so if we want MethodFilter to + * only apply to the root method we have to check only the last method + * seen. + */ + lastMethod = method; + } + } + } + } + if (lastMethod != null && org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, lastMethod)) { + return true; + } + return false; + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Debug config:"); + add(sb, "Log", logFilter); + add(sb, "Count", countFilter); + add(sb, "Time", timerFilter); + add(sb, "Dump", dumpFilter); + add(sb, "MethodFilter", methodFilter); + return sb.toString(); + } + + private static void add(StringBuilder sb, String name, Object filter) { + if (filter != null) { + sb.append(' '); + sb.append(name); + sb.append('='); + if (filter instanceof Object[]) { + sb.append(Arrays.toString((Object[]) filter)); + } else { + sb.append(String.valueOf(filter)); + } + } + } + + @Override + public RuntimeException interceptException(DebugContext debug, Throwable e) { + if (e instanceof BailoutException && !DebugOptions.InterceptBailout.getValue(options)) { + return null; + } + + OptionValues interceptOptions = new OptionValues(options, + DebugOptions.Count, null, + DebugOptions.Time, null, + DebugOptions.TrackMemUse, null, + DebugOptions.Verify, null, + DebugOptions.Dump, ":" + BASIC_LEVEL, + DebugOptions.Log, ":" + BASIC_LEVEL); + DebugConfigImpl config = new DebugConfigImpl(interceptOptions, output, dumpHandlers, verifyHandlers); + ScopeImpl scope = debug.currentScope; + scope.updateFlags(config); + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(baos)); + debug.log("Exception raised in scope %s: %s", debug.getCurrentScopeName(), baos); + Map firstSeen = new IdentityHashMap<>(); + for (Object o : debug.context()) { + // Only dump a context object once. + if (!firstSeen.containsKey(o)) { + firstSeen.put(o, o); + if (DebugOptions.DumpOnError.getValue(options) || DebugOptions.Dump.getValue(options) != null) { + debug.dump(DebugContext.BASIC_LEVEL, o, "Exception: %s", e); + } else { + debug.log("Context obj %s", o); + } + } + } + } finally { + scope.updateFlags(this); + } + return null; + } + + @Override + public Collection dumpHandlers() { + return dumpHandlers; + } + + @Override + public Collection verifyHandlers() { + return verifyHandlers; + } +}