Mercurial > hg > graal-compiler
changeset 9849:e876c2a6954f
extensible option system (GRAAL-27)
partial conversion from GraalOptions to new system
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java Mon Jun 03 20:28:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/DebugFilter.java Mon Jun 03 21:59:44 2013 +0200 @@ -27,11 +27,11 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; -import com.oracle.graal.phases.*; /** - * Implements the filter specified by the {@link GraalOptions#Dump}, {@link GraalOptions#Log}, - * {@link GraalOptions#Meter} and {@link GraalOptions#Time} options. + * Implements the filter specified by the {@link GraalDebugConfig#Dump}, + * {@link GraalDebugConfig#Log}, {@link GraalDebugConfig#Meter} and {@link GraalDebugConfig#Time} + * options. * <p> * These options enable the associated debug facility if their filter matches the * {@linkplain DebugScope#getQualifiedName() name} of the {@linkplain Debug#currentScope() current
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Jun 03 20:28:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Jun 03 21:59:44 2013 +0200 @@ -38,6 +38,7 @@ import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; +import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.common.*; @@ -52,6 +53,11 @@ */ public class GraalCompiler { + // @formatter:off + @Option(help = "") + public static final OptionValue<Boolean> VerifyUsageWithEquals = new OptionValue<>(true); + // @formatter:on + /** * Requests compilation of a given graph. * @@ -125,7 +131,7 @@ } else { Debug.dump(graph, "initial state"); } - if (GraalOptions.VerifyUsageWithEquals) { + if (VerifyUsageWithEquals.getValue()) { new VerifyUsageWithEquals(runtime, Value.class).apply(graph); new VerifyUsageWithEquals(runtime, Register.class).apply(graph); }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Mon Jun 03 20:28:50 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Mon Jun 03 21:59:44 2013 +0200 @@ -31,10 +31,33 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.util.*; -import com.oracle.graal.phases.*; +import com.oracle.graal.options.*; public class GraalDebugConfig implements DebugConfig { + // @formatter:off + @Option(help = "Enable scope-based debugging", name = "Debug") + public static final OptionValue<Boolean> DebugEnabled = new OptionValue<>(true); + @Option(help = "Scopes to be dumped") + public static final OptionValue<String> Dump = new OptionValue<>(null); + @Option(help = "Scopes to be metered") + public static final OptionValue<String> Meter = new OptionValue<>(null); + @Option(help = "Scopes to be timed") + public static final OptionValue<String> Time = new OptionValue<>(null); + @Option(help = "Scopes to be logged") + public static final OptionValue<String> Log = new OptionValue<>(null); + @Option(help = "Filters debug scope output by method name/pattern") + public static final OptionValue<String> MethodFilter = new OptionValue<>(null); + @Option(help = "") + public static final OptionValue<Boolean> PerThreadDebugValues = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> SummarizeDebugValues = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue<Boolean> SummarizePerPhase = new OptionValue<>(false); + @Option(help = "Send Graal IR to dump handlers on error") + public static final OptionValue<Boolean> DumpOnError = new OptionValue<>(false); + // @formatter:on + private final DebugFilter logFilter; private final DebugFilter meterFilter; private final DebugFilter timerFilter; @@ -170,7 +193,7 @@ for (Object o : Debug.context()) { if (o instanceof Graph) { Debug.log("Context obj %s", o); - if (GraalOptions.DumpOnError) { + if (DumpOnError.getValue()) { Debug.dump(o, "Exception graph"); } else { Debug.log("Use -G:+DumpOnError to enable dumping of graphs on this error");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon Jun 03 20:28:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon Jun 03 21:59:44 2013 +0200 @@ -37,11 +37,17 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; public final class CompilationTask implements Runnable, Comparable<CompilationTask> { + //@formatter:off + @Option(help = "") + public static final OptionValue<Integer> SlowQueueCutoff = new OptionValue<>(100000); + //@formatter:on + public static final ThreadLocal<Boolean> withinEnqueue = new ThreadLocal<Boolean>() { @Override @@ -109,7 +115,7 @@ } inProgress = true; if (GraalOptions.DynamicCompilePriority) { - int threadPriority = priority < GraalOptions.SlowQueueCutoff ? Thread.NORM_PRIORITY : Thread.MIN_PRIORITY; + int threadPriority = priority < SlowQueueCutoff.getValue() ? Thread.NORM_PRIORITY : Thread.MIN_PRIORITY; if (Thread.currentThread().getPriority() != threadPriority) { Thread.currentThread().setPriority(threadPriority); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java Mon Jun 03 20:28:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilerThread.java Mon Jun 03 21:59:44 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot; +import static com.oracle.graal.compiler.GraalDebugConfig.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import java.io.*; @@ -29,7 +30,6 @@ import com.oracle.graal.compiler.*; import com.oracle.graal.debug.*; -import com.oracle.graal.phases.*; import com.oracle.graal.printer.*; public final class CompilerThread extends Thread { @@ -60,7 +60,7 @@ @Override public void run() { GraalDebugConfig hotspotDebugConfig = null; - if (GraalOptions.Debug) { + if (DebugEnabled.getValue()) { PrintStream log = graalRuntime().getVMToCompiler().log(); DebugEnvironment.initialize(log); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Mon Jun 03 20:28:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Mon Jun 03 21:59:44 2013 +0200 @@ -27,10 +27,21 @@ import java.util.*; import com.oracle.graal.hotspot.logging.*; +import com.oracle.graal.options.*; import com.oracle.graal.phases.*; public class HotSpotOptions { + private static final Map<String, OptionProvider> options = new HashMap<>(); + + static { + ServiceLoader<OptionProvider> sl = ServiceLoader.loadInstalled(OptionProvider.class); + for (OptionProvider provider : sl) { + String name = provider.getName(); + options.put(name, provider); + } + } + // Called from VM code public static boolean setOption(String option) { if (option.length() == 0) { @@ -61,6 +72,53 @@ } } + OptionProvider optionProvider = options.get(fieldName); + if (optionProvider == null) { + return setOptionLegacy(option, fieldName, value, valueString); + } + + Class<?> optionType = optionProvider.getType(); + + if (value == null) { + if (optionType == Boolean.TYPE || optionType == Boolean.class) { + Logger.info("Value for boolean option '" + fieldName + "' must use '-G:+" + fieldName + "' or '-G:-" + fieldName + "' format"); + return false; + } + + if (valueString == null) { + Logger.info("Value for option '" + fieldName + "' must use '-G:" + fieldName + "=<value>' format"); + return false; + } + + if (optionType == Float.class) { + value = Float.parseFloat(valueString); + } else if (optionType == Double.class) { + value = Double.parseDouble(valueString); + } else if (optionType == Integer.class) { + value = Integer.parseInt(valueString); + } else if (optionType == String.class) { + value = valueString; + } + } else { + if (optionType != Boolean.class) { + Logger.info("Value for option '" + fieldName + "' must use '-G:" + fieldName + "=<value>' format"); + return false; + } + } + + if (value != null) { + optionProvider.getOptionValue().setValue(value); + // Logger.info("Set option " + fieldName + " to " + value); + } else { + Logger.info("Wrong value \"" + valueString + "\" for option " + fieldName); + return false; + } + + return true; + } + + private static boolean setOptionLegacy(String option, String fieldName, Object v, String valueString) { + Object value = v; Field f; try { f = GraalOptions.class.getDeclaredField(fieldName); @@ -116,10 +174,25 @@ } return true; + } private static void printFlags() { Logger.info("[Graal flags]"); + SortedMap<String, OptionProvider> sortedOptions = new TreeMap<>(options); + for (Map.Entry<String, OptionProvider> e : sortedOptions.entrySet()) { + e.getKey(); + OptionProvider opt = e.getValue(); + Object value = opt.getOptionValue().getValue(); + Logger.info(String.format("%9s %-40s = %-14s %s", opt.getType().getSimpleName(), e.getKey(), value, opt.getHelp())); + } + + printFlagsLegacy(); + + System.exit(0); + } + + protected static void printFlagsLegacy() { Field[] flags = GraalOptions.class.getDeclaredFields(); Arrays.sort(flags, new Comparator<Field>() { @@ -137,6 +210,5 @@ } } } - System.exit(0); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Mon Jun 03 20:28:50 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Mon Jun 03 21:59:44 2013 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.bridge; +import static com.oracle.graal.compiler.GraalDebugConfig.*; import static com.oracle.graal.graph.UnsafeAccess.*; import static com.oracle.graal.hotspot.CompilationTask.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; @@ -46,10 +47,10 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.debug.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.common.*; -import com.oracle.graal.printer.*; import com.oracle.graal.replacements.*; /** @@ -57,6 +58,38 @@ */ public class VMToCompilerImpl implements VMToCompiler { + //@formatter:off + @Option(help = "File to which compiler logging is sent") + private static final OptionValue<String> LogFile = new OptionValue<>(null); + + @Option(help = "Use low priority compilation threads") + private static final OptionValue<Boolean> SlowCompileThreads = new OptionValue<>(false); + + @Option(help = "Use priority-based compilation queue") + private static final OptionValue<Boolean> PriorityCompileQueue = new OptionValue<>(true); + + @Option(help = "Print compilation queue activity periodically") + private static final OptionValue<Boolean> PrintQueue = new OptionValue<>(false); + + @Option(help = "Time limit in milliseconds for bootstrap (-1 for no limit)") + private static final OptionValue<Integer> TimedBootstrap = new OptionValue<>(-1); + + @Option(help = "Number of compilation threads to use") + private static final OptionValue<Integer> Threads = new OptionValue<Integer>(1) { + + @Override + public Integer initialValue() { + return Runtime.getRuntime().availableProcessors(); + } + }; + + @Option(help = "") + private static final OptionValue<Boolean> GenericDynamicCounters = new OptionValue<>(false); + + @Option(help = "") + private static final OptionValue<String> BenchmarkDynamicCounters = new OptionValue<>(null); + //@formatter:on + private final HotSpotGraalRuntime graalRuntime; public final HotSpotResolvedPrimitiveType typeBoolean; @@ -117,35 +150,32 @@ initMirror(typeLong, offset); initMirror(typeVoid, offset); - if (GraalOptions.LogFile != null) { + if (LogFile.getValue() != null) { try { final boolean enableAutoflush = true; - log = new PrintStream(new FileOutputStream(GraalOptions.LogFile), enableAutoflush); + log = new PrintStream(new FileOutputStream(LogFile.getValue()), enableAutoflush); } catch (FileNotFoundException e) { - throw new RuntimeException("couldn't open log file: " + GraalOptions.LogFile, e); + throw new RuntimeException("couldn't open log file: " + LogFile.getValue(), e); } } TTY.initialize(log); - if (GraalOptions.Log == null && GraalOptions.Meter == null && GraalOptions.Time == null && GraalOptions.Dump == null) { - if (GraalOptions.MethodFilter != null) { + if (Log.getValue() == null && Meter.getValue() == null && Time.getValue() == null && Dump.getValue() == null) { + if (MethodFilter.getValue() != null) { TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time and Dump options are all null"); } } if (config.ciTime) { - quietMeterAndTime = (GraalOptions.Meter == null && GraalOptions.Time == null); - GraalOptions.Debug = true; - GraalOptions.Meter = ""; - GraalOptions.Time = ""; + quietMeterAndTime = (Meter.getValue() == null && Time.getValue() == null); + DebugEnabled.setValue(true); + Meter.setValue(""); + Time.setValue(""); } - if (GraalOptions.Debug) { + if (DebugEnabled.getValue()) { Debug.enable(); - if (GraalOptions.DebugReplacements) { - DebugEnvironment.initialize(log); - } } // Install intrinsics. @@ -173,21 +203,17 @@ } - if (GraalOptions.DebugReplacements) { - phaseTransition("replacements"); - } + // Create compilation queue. + BlockingQueue<Runnable> queue = PriorityCompileQueue.getValue() ? new PriorityBlockingQueue<Runnable>() : new LinkedBlockingQueue<Runnable>(); + compileQueue = new ThreadPoolExecutor(Threads.getValue(), Threads.getValue(), 0L, TimeUnit.MILLISECONDS, queue, CompilerThread.FACTORY); - // Create compilation queue. - BlockingQueue<Runnable> queue = GraalOptions.PriorityCompileQueue ? new PriorityBlockingQueue<Runnable>() : new LinkedBlockingQueue<Runnable>(); - compileQueue = new ThreadPoolExecutor(GraalOptions.Threads, GraalOptions.Threads, 0L, TimeUnit.MILLISECONDS, queue, CompilerThread.FACTORY); - - if (GraalOptions.SlowCompileThreads) { - BlockingQueue<Runnable> slowQueue = GraalOptions.PriorityCompileQueue ? new PriorityBlockingQueue<Runnable>() : new LinkedBlockingQueue<Runnable>(); - slowCompileQueue = new ThreadPoolExecutor(GraalOptions.Threads, GraalOptions.Threads, 0L, TimeUnit.MILLISECONDS, slowQueue, CompilerThread.LOW_PRIORITY_FACTORY); + if (SlowCompileThreads.getValue()) { + BlockingQueue<Runnable> slowQueue = PriorityCompileQueue.getValue() ? new PriorityBlockingQueue<Runnable>() : new LinkedBlockingQueue<Runnable>(); + slowCompileQueue = new ThreadPoolExecutor(Threads.getValue(), Threads.getValue(), 0L, TimeUnit.MILLISECONDS, slowQueue, CompilerThread.LOW_PRIORITY_FACTORY); } // Create queue status printing thread. - if (GraalOptions.PrintQueue) { + if (PrintQueue.getValue()) { Thread t = new Thread() { @Override @@ -209,8 +235,8 @@ t.start(); } - if (GraalOptions.BenchmarkDynamicCounters != null) { - String[] arguments = GraalOptions.BenchmarkDynamicCounters.split(","); + if (BenchmarkDynamicCounters.getValue() != null) { + String[] arguments = BenchmarkDynamicCounters.getValue().split(","); if (arguments.length == 0 || (arguments.length % 3) != 0) { throw new GraalInternalError("invalid arguments to BenchmarkDynamicCounters: (err|out),start,end,(err|out),start,end,... (~ matches multiple digits)"); } @@ -228,7 +254,7 @@ DynamicCounterNode.excludedClassPrefix = "Lcom/oracle/graal/"; DynamicCounterNode.enabled = true; } - if (GraalOptions.GenericDynamicCounters) { + if (GenericDynamicCounters.getValue()) { DynamicCounterNode.enabled = true; } compilerStartTime = System.nanoTime(); @@ -382,7 +408,7 @@ TTY.flush(); } } - } while ((System.currentTimeMillis() - startTime) <= GraalOptions.TimedBootstrap); + } while ((System.currentTimeMillis() - startTime) <= TimedBootstrap.getValue()); phaseTransition("bootstrap"); @@ -413,7 +439,7 @@ private static void shutdownCompileQueue(ThreadPoolExecutor queue) throws InterruptedException { if (queue != null) { queue.shutdown(); - if (Debug.isEnabled() && GraalOptions.Dump != null) { + if (Debug.isEnabled() && Dump.getValue() != null) { // Wait 2 seconds to flush out all graph dumps that may be of interest queue.awaitTermination(2, TimeUnit.SECONDS); } @@ -437,9 +463,9 @@ ArrayList<DebugValue> sortedValues = new ArrayList<>(debugValues); Collections.sort(sortedValues); - if (GraalOptions.SummarizeDebugValues) { + if (SummarizeDebugValues.getValue()) { printSummary(topLevelMaps, sortedValues); - } else if (GraalOptions.PerThreadDebugValues) { + } else if (PerThreadDebugValues.getValue()) { for (DebugValueMap map : topLevelMaps) { TTY.println("Showing the results for thread: " + map.getName()); map.group(); @@ -449,13 +475,13 @@ } else { DebugValueMap globalMap = new DebugValueMap("Global"); for (DebugValueMap map : topLevelMaps) { - if (GraalOptions.SummarizePerPhase) { + if (SummarizePerPhase.getValue()) { flattenChildren(map, globalMap); } else { globalMap.addChild(map); } } - if (!GraalOptions.SummarizePerPhase) { + if (!SummarizePerPhase.getValue()) { globalMap.group(); } globalMap.normalize(); @@ -471,7 +497,7 @@ } SnippetCounter.printGroups(TTY.out().out()); - if (GraalOptions.GenericDynamicCounters) { + if (GenericDynamicCounters.getValue()) { DynamicCounterNode.dump(System.out, (System.nanoTime() - compilerStartTime) / 1000000000d); } } @@ -581,7 +607,7 @@ return true; } } else { - if (GraalOptions.PriorityCompileQueue) { + if (PriorityCompileQueue.getValue()) { // normally compilation tasks will only be re-queued when they get a // priority boost, so cancel the old task and add a new one current.cancel(); @@ -604,7 +630,7 @@ } else { try { method.setCurrentTask(task); - if (GraalOptions.SlowCompileThreads && priority > GraalOptions.SlowQueueCutoff) { + if (SlowCompileThreads.getValue() && priority > SlowQueueCutoff.getValue()) { slowCompileQueue.execute(task); } else { compileQueue.execute(task);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.options/src/META-INF/services/javax.annotation.processing.Processor Mon Jun 03 21:59:44 2013 +0200 @@ -0,0 +1,1 @@ +com.oracle.graal.options.OptionProcessor
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/Option.java Mon Jun 03 21:59:44 2013 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, 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 com.oracle.graal.options; + +import java.lang.annotation.*; + +/** + * Describes the attributes of an option whose {@link OptionValue value} is in a static field + * annotated by this annotation type. + */ +@Retention(RetentionPolicy.CLASS) +@Target(ElementType.FIELD) +public @interface Option { + + /** + * Gets a help message for the option. + */ + String help(); + + /** + * The name of the option. By default, the name of the annotated field should be used. + */ + String name() default ""; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProcessor.java Mon Jun 03 21:59:44 2013 +0200 @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2013, 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 com.oracle.graal.options; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; + +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.lang.model.element.Modifier; +import javax.lang.model.type.*; +import javax.lang.model.util.*; +import javax.tools.Diagnostic.Kind; +import javax.tools.*; + +/** + * Processes static fields annotated with {@link Option}. An {@link OptionProvider} is generated for + * each such field that can be accessed as a {@linkplain ServiceLoader service} as follows: + * + * <pre> + * ServiceLoader<OptionProvider> sl = ServiceLoader.loadInstalled(OptionProvider.class); + * for (OptionProvider provider : sl) { + * // use provider + * } + * </pre> + */ +@SupportedSourceVersion(SourceVersion.RELEASE_7) +@SupportedAnnotationTypes({"com.oracle.graal.options.Option"}) +public class OptionProcessor extends AbstractProcessor { + + private final Set<Element> processed = new HashSet<>(); + + private void processElement(Element element) { + if (processed.contains(element)) { + return; + } + processed.add(element); + + if (!element.getModifiers().contains(Modifier.STATIC)) { + processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be static", element); + return; + } + + Option annotation = element.getAnnotation(Option.class); + assert annotation != null; + assert element instanceof VariableElement; + assert element.getKind() == ElementKind.FIELD; + VariableElement field = (VariableElement) element; + String fieldName = field.getSimpleName().toString(); + + Elements elements = processingEnv.getElementUtils(); + Types types = processingEnv.getTypeUtils(); + + TypeMirror fieldType = field.asType(); + if (fieldType.getKind() != TypeKind.DECLARED) { + processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be of type " + OptionValue.class.getName(), element); + return; + } + DeclaredType declaredFieldType = (DeclaredType) fieldType; + + TypeMirror optionValueType = elements.getTypeElement(OptionValue.class.getName()).asType(); + if (!types.isSubtype(fieldType, types.erasure(optionValueType))) { + String msg = String.format("Option field type %s is not a subclass of %s", fieldType, optionValueType); + processingEnv.getMessager().printMessage(Kind.ERROR, msg, element); + return; + } + + if (!field.getModifiers().contains(Modifier.STATIC)) { + processingEnv.getMessager().printMessage(Kind.ERROR, "Option field must be static", element); + return; + } + + String optionName = annotation.name(); + if (optionName.equals("")) { + optionName = fieldName; + } + + String optionType = declaredFieldType.getTypeArguments().get(0).toString(); + if (optionType.startsWith("java.lang.")) { + optionType = optionType.substring("java.lang.".length()); + } + + String pkg = null; + Element enclosing = element.getEnclosingElement(); + String declaringClass = ""; + String separator = ""; + while (enclosing != null) { + if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) { + if (enclosing.getModifiers().contains(Modifier.PRIVATE)) { + String msg = String.format("Option field cannot be declared in a private %s %s", enclosing.getKind().name().toLowerCase(), enclosing); + processingEnv.getMessager().printMessage(Kind.ERROR, msg, element); + return; + } + declaringClass = enclosing.getSimpleName() + separator + declaringClass; + separator = "."; + } else { + assert enclosing.getKind() == ElementKind.PACKAGE; + pkg = ((PackageElement) enclosing).getQualifiedName().toString(); + } + enclosing = enclosing.getEnclosingElement(); + } + + String providerClassName = declaringClass.replace('.', '_') + "_" + fieldName; + + Filer filer = processingEnv.getFiler(); + try (PrintWriter out = createSourceFile(element, pkg, providerClassName, filer)) { + + out.println("/*"); + out.println(" * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved."); + out.println(" * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER."); + out.println(" *"); + out.println(" * This code is free software; you can redistribute it and/or modify it"); + out.println(" * under the terms of the GNU General Public License version 2 only, as"); + out.println(" * published by the Free Software Foundation."); + out.println(" *"); + out.println(" * This code is distributed in the hope that it will be useful, but WITHOUT"); + out.println(" * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or"); + out.println(" * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License"); + out.println(" * version 2 for more details (a copy is included in the LICENSE file that"); + out.println(" * accompanied this code)."); + out.println(" *"); + out.println(" * You should have received a copy of the GNU General Public License version"); + out.println(" * 2 along with this work; if not, write to the Free Software Foundation,"); + out.println(" * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA."); + out.println(" *"); + out.println(" * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA"); + out.println(" * or visit www.oracle.com if you need additional information or have any"); + out.println(" * questions."); + out.println(" */"); + + out.println("package " + pkg + ";"); + out.println(""); + if (element.getModifiers().contains(Modifier.PRIVATE)) { + out.println("import " + Field.class.getName() + ";"); + } + out.println("import " + OptionValue.class.getName() + ";"); + out.println("import " + OptionProvider.class.getName() + ";"); + out.println(""); + out.println("public class " + providerClassName + " implements " + OptionProvider.class.getSimpleName() + " {"); + out.println(" public String getHelp() {"); + out.println(" return \"" + annotation.help() + "\";"); + out.println(" }"); + out.println(" public String getName() {"); + out.println(" return \"" + optionName + "\";"); + out.println(" }"); + out.println(" public Class getType() {"); + out.println(" return " + optionType + ".class;"); + out.println(" }"); + out.println(" public " + OptionValue.class.getSimpleName() + "<?> getOptionValue() {"); + if (!element.getModifiers().contains(Modifier.PRIVATE)) { + out.println(" return " + declaringClass + "." + fieldName + ";"); + } else { + out.println(" try {"); + out.println(" Field field = " + declaringClass + ".class.getDeclaredField(\"" + fieldName + "\");"); + out.println(" field.setAccessible(true);"); + out.println(" return (" + OptionValue.class.getSimpleName() + ") field.get(null);"); + out.println(" } catch (Exception e) {"); + out.println(" throw (InternalError) new InternalError().initCause(e);"); + out.println(" }"); + } + out.println(" }"); + out.println("}"); + } + + try { + createProviderFile(field, pkg, providerClassName); + } catch (IOException e) { + processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), field); + } + } + + private void createProviderFile(Element field, String pkg, String providerClassName) throws IOException { + String filename = "META-INF/providers/" + pkg + "." + providerClassName; + FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, field); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8")); + writer.println(OptionProvider.class.getName()); + writer.close(); + } + + protected PrintWriter createSourceFile(Element element, String pkg, String relativeName, Filer filer) { + try { + // Ensure Unix line endings to comply with Graal code style guide checked by Checkstyle + JavaFileObject sourceFile = filer.createSourceFile(pkg + "." + relativeName, element); + return new PrintWriter(sourceFile.openWriter()) { + + @Override + public void println() { + print("\n"); + } + }; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) { + return true; + } + + for (Element element : roundEnv.getElementsAnnotatedWith(Option.class)) { + processElement(element); + } + + return true; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionProvider.java Mon Jun 03 21:59:44 2013 +0200 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013, 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 com.oracle.graal.options; + +import java.util.*; + +/** + * Describes the attributes of an {@linkplain Option option} and provides access to its + * {@linkplain OptionValue value}. The {@link OptionProcessor} auto-generates instances of this + * interface that are accessible as a {@linkplain ServiceLoader service}. + */ +public interface OptionProvider { + + /** + * Gets the type of values stored in the option. + */ + Class getType(); + + /** + * Gets a descriptive help message for the option. + */ + String getHelp(); + + /** + * Gets the name of the option. It's up to the client of this object how to use the name to get + * a user specified value for the option from the environment. + */ + String getName(); + + /** + * Gets the boxed option value. + */ + OptionValue<?> getOptionValue(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java Mon Jun 03 21:59:44 2013 +0200 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013, 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 com.oracle.graal.options; + +import java.util.*; + +/** + * A settable option value. + * <p> + * To access {@link OptionProvider} instances via a {@link ServiceLoader} for working with options, + * instances of this class should be assigned to static final fields that are annotated with + * {@link Option}. + */ +public class OptionValue<T> { + + /** + * The raw option value. + */ + protected T value; + + /** + * Guards whether {@link #initialValue()} should be called to give a subclass an opportunity to + * provide a context-sensitive initial value for this option. + */ + protected boolean initialValueCalled; + + /** + * Create an option. + * + * @param value the initial/default value of the option + */ + public OptionValue(T value) { + this.value = value; + } + + protected T initialValue() { + return value; + } + + /** + * Gets the value of this option. + */ + public final T getValue() { + if (!initialValueCalled) { + value = initialValue(); + initialValueCalled = true; + } + return value; + } + + /** + * Sets the value of this option. + */ + @SuppressWarnings("unchecked") + public final void setValue(Object v) { + this.value = (T) v; + this.initialValueCalled = true; + } +}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Mon Jun 03 20:28:50 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Mon Jun 03 21:59:44 2013 +0200 @@ -34,11 +34,6 @@ private static final boolean ____ = false; // Checkstyle: resume - public static int Threads; - static { - Threads = Runtime.getRuntime().availableProcessors(); - } - public static String CompilerConfiguration = "basic"; public static String GraalRuntime = "basic"; @@ -80,10 +75,6 @@ public static int MatureExecutionsTypeProfile = 1; // comilation queue - public static int TimedBootstrap = -1; - public static boolean PriorityCompileQueue = true; - public static int SlowQueueCutoff = 100000; - public static boolean SlowCompileThreads = ____; public static boolean DynamicCompilePriority = ____; public static String CompileTheWorld = null; public static int CompileTheWorldStartAt = 1; @@ -115,21 +106,7 @@ public static String PrintFilter = null; // Debug settings: - public static boolean Debug = true; - public static boolean DebugReplacements = ____; public static boolean BootstrapReplacements = ____; - public static boolean PerThreadDebugValues = ____; - public static boolean SummarizeDebugValues = ____; - public static boolean SummarizePerPhase = ____; - public static String Dump = null; - public static String Meter = null; - public static String Time = null; - public static String Log = null; - public static String LogFile = null; - public static String MethodFilter = null; - public static boolean DumpOnError = ____; - public static boolean GenericDynamicCounters = ____; - public static String BenchmarkDynamicCounters = null; // Ideal graph visualizer output settings public static boolean PrintBinaryGraphs = true; @@ -140,7 +117,6 @@ public static int PrintBinaryGraphPort = 4445; // Other printing settings - public static boolean PrintQueue = ____; public static boolean PrintCompilation = ____; public static boolean PrintProfilingInformation = ____; public static boolean PrintIRWithLIR = ____; @@ -211,7 +187,6 @@ public static boolean OptFilterProfiledTypes = true; public static boolean OptDevirtualizeInvokesOptimistically = true; public static boolean OptPushThroughPi = true; - public static boolean VerifyUsageWithEquals = true; // Intrinsification settings public static boolean IntrinsifyObjectClone = ____;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java Mon Jun 03 20:28:50 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/DebugEnvironment.java Mon Jun 03 21:59:44 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.printer; +import static com.oracle.graal.compiler.GraalDebugConfig.*; + import java.io.*; import java.util.*; @@ -41,7 +43,7 @@ } dumpHandlers.add(new CFGPrinterObserver()); } - GraalDebugConfig hotspotDebugConfig = new GraalDebugConfig(GraalOptions.Log, GraalOptions.Meter, GraalOptions.Time, GraalOptions.Dump, GraalOptions.MethodFilter, log, dumpHandlers); + GraalDebugConfig hotspotDebugConfig = new GraalDebugConfig(Log.getValue(), Meter.getValue(), Time.getValue(), Dump.getValue(), MethodFilter.getValue(), log, dumpHandlers); Debug.setConfig(hotspotDebugConfig); } }
--- a/make/build-graal.xml Mon Jun 03 20:28:50 2013 +0200 +++ b/make/build-graal.xml Mon Jun 03 21:59:44 2013 +0200 @@ -42,6 +42,7 @@ <src path="${src.dir}/com.oracle.graal.phases"/> <src path="${src.dir}/com.oracle.graal.phases.common"/> <src path="${src.dir}/com.oracle.graal.virtual"/> + <src path="${src.dir}/com.oracle.graal.options"/> <src path="${src.dir}/com.oracle.graal.loop"/> <src path="${src.dir}/com.oracle.graal.alloc"/> <src path="${src.dir}/com.oracle.graal.asm"/> @@ -80,9 +81,34 @@ <provider classname="com.oracle.graal.hotspot.replacements.HotSpotNmethodIntrinsics"/> <provider classname="com.oracle.graal.replacements.GraalMethodSubstitutions"/> </service> + <service type="com.oracle.graal.options.OptionProvider"> + <provider classname="com.oracle.graal.compiler.GraalCompiler_VerifyUsageWithEquals"/> + <provider classname="com.oracle.graal.compiler.GraalDebugConfig_DebugEnabled"/> + <provider classname="com.oracle.graal.compiler.GraalDebugConfig_Dump"/> + <provider classname="com.oracle.graal.compiler.GraalDebugConfig_DumpOnError"/> + <provider classname="com.oracle.graal.compiler.GraalDebugConfig_Log"/> + <provider classname="com.oracle.graal.compiler.GraalDebugConfig_Meter"/> + <provider classname="com.oracle.graal.compiler.GraalDebugConfig_MethodFilter"/> + <provider classname="com.oracle.graal.compiler.GraalDebugConfig_PerThreadDebugValues"/> + <provider classname="com.oracle.graal.compiler.GraalDebugConfig_SummarizeDebugValues"/> + <provider classname="com.oracle.graal.compiler.GraalDebugConfig_SummarizePerPhase"/> + <provider classname="com.oracle.graal.compiler.GraalDebugConfig_Time"/> + <provider classname="com.oracle.graal.hotspot.CompilationTask_SlowQueueCutoff"/> + <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_BenchmarkDynamicCounters"/> + <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_GenericDynamicCounters"/> + <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_LogFile"/> + <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_PrintQueue"/> + <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_PriorityCompileQueue"/> + <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_SlowCompileThreads"/> + <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_Threads"/> + <provider classname="com.oracle.graal.hotspot.bridge.VMToCompilerImpl_TimedBootstrap"/> + </service> <service type="com.oracle.graal.phases.tiers.CompilerConfiguration"> <provider classname="com.oracle.graal.compiler.phases.BasicCompilerConfiguration"/> </service> + <service type="javax.annotation.processing.Processor"> + <provider classname="com.oracle.graal.options.OptionProcessor"/> + </service> </jar> </target> <target name="cleanclasses">
--- a/mx/projects Mon Jun 03 20:28:50 2013 +0200 +++ b/mx/projects Mon Jun 03 21:59:44 2013 +0200 @@ -100,7 +100,7 @@ project@com.oracle.graal.hotspot@sourceDirs=src project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.replacements,com.oracle.graal.printer project@com.oracle.graal.hotspot@checkstyle=com.oracle.graal.graph -project@com.oracle.graal.hotspot@annotationProcessors=com.oracle.graal.replacements.verifier, com.oracle.graal.service.processor +project@com.oracle.graal.hotspot@annotationProcessors=com.oracle.graal.replacements.verifier,com.oracle.graal.service.processor,com.oracle.graal.options project@com.oracle.graal.hotspot@javaCompliance=1.7 # graal.hotspot.amd64 @@ -138,6 +138,12 @@ project@com.oracle.graal.hotspot.amd64.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.hotspot.amd64.test@javaCompliance=1.7 +# graal.options +project@com.oracle.graal.options@subDir=graal +project@com.oracle.graal.options@sourceDirs=src +project@com.oracle.graal.options@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.options@javaCompliance=1.7 + # graal.graph project@com.oracle.graal.graph@subDir=graal project@com.oracle.graal.graph@sourceDirs=src @@ -273,10 +279,10 @@ # graal.compiler project@com.oracle.graal.compiler@subDir=graal project@com.oracle.graal.compiler@sourceDirs=src -project@com.oracle.graal.compiler@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.virtual,com.oracle.graal.loop,com.oracle.graal.alloc,com.oracle.graal.lir +project@com.oracle.graal.compiler@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.virtual,com.oracle.graal.options,com.oracle.graal.loop,com.oracle.graal.alloc,com.oracle.graal.lir project@com.oracle.graal.compiler@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler@javaCompliance=1.7 -project@com.oracle.graal.compiler@annotationProcessors=com.oracle.graal.service.processor +project@com.oracle.graal.compiler@annotationProcessors=com.oracle.graal.service.processor,com.oracle.graal.options # graal.compiler.amd64 project@com.oracle.graal.compiler.amd64@subDir=graal