# HG changeset patch # User Gilles Duboscq # Date 1432741226 -7200 # Node ID cecb4e39521ceca20ee982e16b79cffa13edf197 # Parent c2e58b2a2a761001541571eb6302abc202bf880a Use files in lib/graal/options to define Graal options (-G:...) instead of generating code for them diff -r c2e58b2a2a76 -r cecb4e39521c graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Mon May 18 18:30:43 2015 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Wed May 27 17:40:26 2015 +0200 @@ -327,7 +327,7 @@ @Option(help = "Enable expensive assertions", type = OptionType.Debug) public static final OptionValue DetailedAsserts = new StableOptionValue() { @Override - protected Boolean initialValue() { + protected Boolean defaultValue() { boolean enabled = false; // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this) assert (enabled = true) == true; diff -r c2e58b2a2a76 -r cecb4e39521c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon May 18 18:30:43 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Wed May 27 17:40:26 2015 +0200 @@ -29,7 +29,6 @@ import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.debug.Debug.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.hotspot.InitTimer.*; import static com.oracle.graal.hotspot.meta.HotSpotSuitesProvider.*; import static com.oracle.graal.nodes.StructuredGraph.*; import static com.oracle.graal.phases.common.inlining.InliningUtil.*; @@ -62,15 +61,6 @@ //JaCoCo Exclude public class CompilationTask { - - static { - try (InitTimer t = timer("initialize CompilationTask")) { - // Must be first to ensure any options accessed by the rest of the class - // initializer are initialized from the command line. - HotSpotOptions.initialize(); - } - } - private static final DebugMetric BAILOUTS = Debug.metric("Bailouts"); private final HotSpotBackend backend; diff -r c2e58b2a2a76 -r cecb4e39521c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Mon May 18 18:30:43 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Wed May 27 17:40:26 2015 +0200 @@ -40,7 +40,6 @@ import com.oracle.graal.bytecode.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.CompilerThreadFactory.DebugConfigAccess; -import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; import com.oracle.graal.hotspot.meta.*; @@ -120,14 +119,12 @@ * * @param options a space separated set of option value settings with each option setting in * a format compatible with - * {@link HotSpotOptions#parseOption(String, OptionConsumer)}. Ignored if null. + * {@link OptionUtils#parseOption(String, OptionConsumer)}. Ignored if null. */ public Config(String options) { if (options != null) { for (String option : options.split("\\s+")) { - if (!HotSpotOptions.parseOption(option, this)) { - throw new GraalInternalError("Invalid option specified: %s", option); - } + OptionUtils.parseOption(option, this); } } } @@ -213,7 +210,7 @@ */ public void compile() throws Throwable { // By default only report statistics for the CTW threads themselves - if (GraalDebugConfig.DebugValueThreadFilter.hasInitialValue()) { + if (GraalDebugConfig.DebugValueThreadFilter.hasDefaultValue()) { GraalDebugConfig.DebugValueThreadFilter.setValue("^CompileTheWorld"); } diff -r c2e58b2a2a76 -r cecb4e39521c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon May 18 18:30:43 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Wed May 27 17:40:26 2015 +0200 @@ -65,10 +65,6 @@ private static final HotSpotGraalRuntime instance; static { - try (InitTimer t = timer("initialize HotSpotOptions")) { - HotSpotOptions.initialize(); - } - try (InitTimer t = timer("HotSpotGraalRuntime.")) { instance = new HotSpotGraalRuntime(); } diff -r c2e58b2a2a76 -r cecb4e39521c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Mon May 18 18:30:43 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Wed May 27 17:40:26 2015 +0200 @@ -23,8 +23,7 @@ package com.oracle.graal.hotspot; import static com.oracle.graal.compiler.GraalDebugConfig.*; -import static com.oracle.graal.hotspot.HotSpotOptionsLoader.*; -import static java.lang.Double.*; +import static com.oracle.graal.options.OptionsLoader.*; import java.lang.reflect.*; @@ -32,7 +31,6 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.options.*; -import com.oracle.graal.options.OptionUtils.OptionConsumer; import com.oracle.graal.phases.common.inlining.*; //JaCoCo Exclude @@ -45,16 +43,10 @@ private static final String GRAAL_OPTION_PREFIX = "-G:"; - /** - * Parses the Graal specific options specified to HotSpot (e.g., on the command line). - * - * @return true if the CITime or CITimeEach HotSpot VM options are set - */ - private static native boolean parseVMOptions(); + private static native boolean isCITimingEnabled(); static { - boolean timeCompilations = parseVMOptions(); - if (timeCompilations) { + if (isCITimingEnabled()) { unconditionallyEnableTimerOrMetric(InliningUtil.class, "InlinedBytecodes"); unconditionallyEnableTimerOrMetric(CompilationTask.class, "CompilationTime"); } @@ -74,58 +66,8 @@ } } - /** - * Ensures {@link HotSpotOptions} is initialized. - */ - public static void initialize() { - } - - /** - * Helper for the VM code called by {@link #parseVMOptions()}. - * - * @param name the name of a parsed option - * @param option the object encapsulating the option - * @param spec specification of boolean option value, type of option value or action to take - */ - static void setOption(String name, OptionValue option, char spec, String stringValue, long primitiveValue) { - switch (spec) { - case '+': - option.setValue(Boolean.TRUE); - break; - case '-': - option.setValue(Boolean.FALSE); - break; - case '?': - OptionUtils.printFlags(options, GRAAL_OPTION_PREFIX); - break; - case ' ': - OptionUtils.printNoMatchMessage(options, name, GRAAL_OPTION_PREFIX); - break; - case 'i': - option.setValue((int) primitiveValue); - break; - case 'f': - option.setValue((float) longBitsToDouble(primitiveValue)); - break; - case 'd': - option.setValue(longBitsToDouble(primitiveValue)); - break; - case 's': - option.setValue(stringValue); - break; - } - } - - /** - * Parses a given option value specification. - * - * @param option the specification of an option and its value - * @param setter the object to notify of the parsed option and value. If null, the - * {@link OptionValue#setValue(Object)} method of the specified option is called - * instead. - */ - public static boolean parseOption(String option, OptionConsumer setter) { - return OptionUtils.parseOption(options, option, GRAAL_OPTION_PREFIX, setter); + static void printFlags() { + OptionUtils.printFlags(options, GRAAL_OPTION_PREFIX); } /** @@ -156,4 +98,6 @@ throw new GraalInternalError(e); } } + + public native Object getOptionValue(String optionName); } diff -r c2e58b2a2a76 -r cecb4e39521c graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java Mon May 18 18:30:43 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2014, 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.hotspot; - -import java.util.*; - -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.options.*; - -/** - * Helper class for separating loading of options from option initialization at runtime. - */ -class HotSpotOptionsLoader { - static final SortedMap options = new TreeMap<>(); - - /** - * Initializes {@link #options} from {@link Options} services. - */ - static { - for (Options opts : Services.load(Options.class)) { - for (OptionDescriptor desc : opts) { - if (isHotSpotOption(desc)) { - String name = desc.getName(); - OptionDescriptor existing = options.put(name, desc); - assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation(); - } - } - } - } - - /** - * Determines if a given option is a HotSpot command line option. - */ - private static boolean isHotSpotOption(OptionDescriptor desc) { - return desc.getClass().getName().startsWith("com.oracle.graal"); - } -} diff -r c2e58b2a2a76 -r cecb4e39521c graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/OptionProcessor.java --- a/graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/OptionProcessor.java Mon May 18 18:30:43 2015 +0200 +++ b/graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/OptionProcessor.java Wed May 27 17:40:26 2015 +0200 @@ -229,6 +229,7 @@ String filename = "META-INF/options/" + pkg + "." + relativeName; FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, originatingElements); PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8")); + Types types = processingEnv.getTypeUtils(); for (OptionInfo option : info.options) { String help = option.help; if (help.indexOf('\t') >= 0 || help.indexOf('\r') >= 0 || help.indexOf('\n') >= 0) { @@ -237,13 +238,20 @@ } try { char optionTypeToChar = optionTypeToChar(option); - writer.printf("%s\t%s\t%s%n", option.name, optionTypeToChar, help); + String fqDeclaringClass = className(types.erasure(option.field.getEnclosingElement().asType())); + String fqFieldType = className(types.erasure(option.field.asType())); + writer.printf("%s\t%s\t%s\t%s\t%s%n", option.name, optionTypeToChar, help, fqDeclaringClass, fqFieldType); } catch (IllegalArgumentException iae) { } } writer.close(); } + private String className(TypeMirror t) { + DeclaredType dt = (DeclaredType) t; + return processingEnv.getElementUtils().getBinaryName((TypeElement) dt.asElement()).toString(); + } + private char optionTypeToChar(OptionInfo option) { switch (option.type) { case "Boolean": diff -r c2e58b2a2a76 -r cecb4e39521c graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionUtils.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionUtils.java Mon May 18 18:30:43 2015 +0200 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionUtils.java Wed May 27 17:40:26 2015 +0200 @@ -34,24 +34,19 @@ * Parses a given option value specification. * * @param option the specification of an option and its value - * @param setter the object to notify of the parsed option and value. If null, the - * {@link OptionValue#setValue(Object)} method of the specified option is called - * instead. + * @param setter the object to notify of the parsed option and value. */ - public static boolean parseOption(SortedMap options, String option, String prefix, OptionConsumer setter) { + public static void parseOption(String option, OptionConsumer setter) { + SortedMap options = OptionsLoader.options; + Objects.requireNonNull(setter); if (option.length() == 0) { - return false; + return; } Object value = null; String optionName = null; String valueString = null; - if (option.equals("+PrintFlags")) { - printFlags(options, prefix); - return true; - } - char first = option.charAt(0); if (first == '+' || first == '-') { optionName = option.substring(1); @@ -69,21 +64,18 @@ OptionDescriptor desc = options.get(optionName); if (desc == null) { - printNoMatchMessage(options, optionName, prefix); - return false; + throw new IllegalArgumentException("Option '" + optionName + "' not found"); } Class optionType = desc.getType(); if (value == null) { if (optionType == Boolean.TYPE || optionType == Boolean.class) { - System.err.println("Value for boolean option '" + optionName + "' must use '" + prefix + "+" + optionName + "' or '" + prefix + "-" + optionName + "' format"); - return false; + throw new IllegalArgumentException("Boolean option '" + optionName + "' must use +/- prefix"); } if (valueString == null) { - System.err.println("Value for option '" + optionName + "' must use '" + prefix + optionName + "=' format"); - return false; + throw new IllegalArgumentException("Missing value for non-boolean option '" + optionName + "' must use " + optionName + "= format"); } if (optionType == Float.class) { @@ -96,28 +88,16 @@ value = Long.valueOf(parseLong(valueString)); } else if (optionType == String.class) { value = valueString; + } else { + throw new IllegalArgumentException("Wrong value for option '" + optionName + "'"); } } else { if (optionType != Boolean.class) { - System.err.println("Value for option '" + optionName + "' must use '" + prefix + optionName + "=' format"); - return false; + throw new IllegalArgumentException("Non-boolean option '" + optionName + "' can not use +/- prefix. Use " + optionName + "= format"); } } - if (value != null) { - if (setter != null) { - setter.set(desc, value); - } else { - OptionValue optionValue = desc.getOptionValue(); - optionValue.setValue(value); - // System.err.println("Set option " + desc.getName() + " to " + value); - } - } else { - System.err.println("Wrong value \"" + valueString + "\" for option " + optionName); - return false; - } - - return true; + setter.set(desc, value); } private static long parseLong(String v) { @@ -141,27 +121,6 @@ return Long.parseLong(valueString) * scale; } - public static void printNoMatchMessage(SortedMap options, String optionName, String prefix) { - OptionDescriptor desc = options.get(optionName); - if (desc != null) { - if (desc.getType() == Boolean.class) { - System.err.println("Boolean option " + optionName + " must be prefixed with '+' or '-'"); - } else { - System.err.println(desc.getType().getSimpleName() + " option " + optionName + " must not be prefixed with '+' or '-'"); - } - } else { - System.err.println("Could not find option " + optionName + " (use " + prefix + "+PrintFlags to see options)"); - List matches = fuzzyMatch(options, optionName); - if (!matches.isEmpty()) { - System.err.println("Did you mean one of the following?"); - for (OptionDescriptor match : matches) { - boolean isBoolean = match.getType() == Boolean.class; - System.err.println(String.format(" %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=")); - } - } - } - } - /** * Wraps some given text to one or more lines of a given maximum width. * @@ -220,38 +179,4 @@ System.exit(0); } - - /** - * Compute string similarity based on Dice's coefficient. - * - * Ported from str_similar() in globals.cpp. - */ - static float stringSimiliarity(String str1, String str2) { - int hit = 0; - for (int i = 0; i < str1.length() - 1; ++i) { - for (int j = 0; j < str2.length() - 1; ++j) { - if ((str1.charAt(i) == str2.charAt(j)) && (str1.charAt(i + 1) == str2.charAt(j + 1))) { - ++hit; - break; - } - } - } - return 2.0f * hit / (str1.length() + str2.length()); - } - - private static final float FUZZY_MATCH_THRESHOLD = 0.7F; - - /** - * Returns the set of options that fuzzy match a given option name. - */ - private static List fuzzyMatch(SortedMap options, String optionName) { - List matches = new ArrayList<>(); - for (Map.Entry e : options.entrySet()) { - float score = stringSimiliarity(e.getKey(), optionName); - if (score >= FUZZY_MATCH_THRESHOLD) { - matches.add(e.getValue()); - } - } - return matches; - } } diff -r c2e58b2a2a76 -r cecb4e39521c graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java Mon May 18 18:30:43 2015 +0200 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java Wed May 27 17:40:26 2015 +0200 @@ -30,7 +30,6 @@ * An option value. */ public class OptionValue { - /** * Temporarily changes the value for an option. The {@linkplain OptionValue#getValue() value} of * {@code option} is set to {@code value} until {@link OverrideScope#close()} is called on the @@ -138,7 +137,7 @@ overrideScopeTL.set(overrideScope); } - private T initialValue; + private T defaultValue; /** * The raw option value. @@ -164,29 +163,30 @@ @SuppressWarnings("unchecked") public OptionValue(T value) { - this.initialValue = value; - this.value = (T) UNINITIALIZED; + this.defaultValue = value; + this.value = (T) DEFAULT; addToHistogram(this); } + private static final Object DEFAULT = "DEFAULT"; private static final Object UNINITIALIZED = "UNINITIALIZED"; /** * Creates an uninitialized option value for a subclass that initializes itself - * {@link #initialValue() lazily}. + * {@link #defaultValue() lazily}. */ @SuppressWarnings("unchecked") protected OptionValue() { - this.initialValue = (T) UNINITIALIZED; - this.value = (T) UNINITIALIZED; + this.defaultValue = (T) UNINITIALIZED; + this.value = (T) DEFAULT; addToHistogram(this); } /** - * Lazy initialization of value. + * Lazy initialization of default value. */ - protected T initialValue() { - throw new InternalError("Uninitialized option value must override initialValue()"); + protected T defaultValue() { + throw new InternalError("Option without a default value value must override defaultValue()"); } /** @@ -223,27 +223,19 @@ * {@link #setValue(Object)} or registering {@link OverrideScope}s. Therefore, it is also not * affected by options set on the command line. */ - public T getInitialValue() { - if (initialValue == UNINITIALIZED) { - initialValue = initialValue(); + public T getDefaultValue() { + if (defaultValue == UNINITIALIZED) { + defaultValue = defaultValue(); } - return initialValue; + return defaultValue; } /** * Returns true if the option has the same value that was set in the source code. */ - public boolean hasInitialValue() { - if (!(this instanceof StableOptionValue)) { - OverrideScope overrideScope = getOverrideScope(); - if (overrideScope != null) { - T override = overrideScope.getOverride(this); - if (override != null) { - return false; - } - } - } - return value == UNINITIALIZED || Objects.equals(value, getInitialValue()); + public boolean hasDefaultValue() { + getValue(); // ensure initialized + return value == DEFAULT || Objects.equals(value, getDefaultValue()); } /** @@ -262,10 +254,10 @@ } } } - if (value != UNINITIALIZED) { + if (value != DEFAULT) { return value; } else { - return getInitialValue(); + return getDefaultValue(); } } @@ -285,10 +277,10 @@ overrideScope.getOverrides(this, (Collection) values); } } - if (value != UNINITIALIZED) { + if (value != DEFAULT) { values.add(value); } else { - values.add(getInitialValue()); + values.add(getDefaultValue()); } return values; } diff -r c2e58b2a2a76 -r cecb4e39521c graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionsLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionsLoader.java Wed May 27 17:40:26 2015 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, 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.*; + +import com.oracle.graal.api.runtime.*; + +/** + * Helper class used to load option descriptors. Only to be used in the slow-path. + */ +public class OptionsLoader { + public static final SortedMap options = new TreeMap<>(); + + /** + * Initializes {@link #options} from {@link Options} services. + */ + static { + for (Options opts : Services.load(Options.class)) { + for (OptionDescriptor desc : opts) { + String name = desc.getName(); + OptionDescriptor existing = options.put(name, desc); + assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation(); + } + } + } +} diff -r c2e58b2a2a76 -r cecb4e39521c graal/com.oracle.graal.options/src/com/oracle/graal/options/StableOptionValue.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/StableOptionValue.java Mon May 18 18:30:43 2015 +0200 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/StableOptionValue.java Wed May 27 17:40:26 2015 +0200 @@ -42,7 +42,7 @@ /** * Creates an uninitialized stable option value for a subclass that initializes itself - * {@link #initialValue() lazily}. + * {@link #defaultValue() lazily}. */ public StableOptionValue() { } diff -r c2e58b2a2a76 -r cecb4e39521c mx/suite.py --- a/mx/suite.py Mon May 18 18:30:43 2015 +0200 +++ b/mx/suite.py Wed May 27 17:40:26 2015 +0200 @@ -442,6 +442,9 @@ "com.oracle.graal.options" : { "subDir" : "graal", "sourceDirs" : ["src"], + "dependencies" : [ + "com.oracle.graal.api.runtime", + ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", "workingSets" : "Graal", @@ -496,7 +499,6 @@ "com.oracle.graal.nodeinfo", "com.oracle.graal.compiler.common", "com.oracle.graal.api.collections", - "com.oracle.graal.api.runtime", "FINDBUGS", ], "javaCompliance" : "1.8", diff -r c2e58b2a2a76 -r cecb4e39521c src/share/vm/graal/graalHashtable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalHashtable.cpp Wed May 27 17:40:26 2015 +0200 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 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. + */ + +#include "graal/graalHashtable.hpp" + +template bool GraalHashtable::add(V value, bool replace) { + K key = get_key(value); + unsigned int hash = compute_hash(key); + unsigned int index = hash_to_index(hash); + for (GraalHashtableEntry* e = bucket(index); e != NULL; e = e->next()) { + if (key_equals(get_key(e->literal_addr()), key)) { + if (replace) { + e->set_literal(value); + } + return false; + } + } + GraalHashtableEntry* e = new GraalHashtableEntry(value); + e->set_next(_buckets[index]); + _buckets[index] = e; + ++_number_of_entries; + return true; +} + +template V* GraalHashtable::get(K key) { + unsigned int index = index_for(key); + for (GraalHashtableEntry* e = bucket(index); e != NULL; e = e->next()) { + if (key_equals(get_key(e->literal_addr()), key)) { + return e->literal_addr(); + } + } + return NULL; +} + +template void GraalHashtable::for_each(ValueClosure* closure) { + for (size_t i = 0; i < table_size(); ++i) { + for (GraalHashtableEntry* e = bucket(i); e != NULL && !closure->is_aborted(); e = e->next()) { + closure->do_value(e->literal_addr()); + } + } +} + +template GraalHashtable::~GraalHashtable() { + for (size_t i = 0; i < table_size(); ++i) { + GraalHashtableEntry* e = bucket(i); + while (e != NULL) { + GraalHashtableEntry* current = e; + e = e->next(); + delete current; + } + } + FREE_C_HEAP_ARRAY(GraalHashtableEntry*, _buckets, mtCompiler); +} + +// Instantiation +#include "graal/graalOptions.hpp" +template class GraalHashtable; +template class GraalHashtable; diff -r c2e58b2a2a76 -r cecb4e39521c src/share/vm/graal/graalHashtable.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalHashtable.hpp Wed May 27 17:40:26 2015 +0200 @@ -0,0 +1,137 @@ +/* + * Copyright (c) 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. + */ + +#ifndef SHARE_VM_GRAAL_GRAAL_HASHTABLE_HPP +#define SHARE_VM_GRAAL_GRAAL_HASHTABLE_HPP + +#include "memory/allocation.hpp" +#include "memory/allocation.inline.hpp" + +// based on hashtable.hpp + +template class GraalHashtableEntry : public CHeapObj { + friend class VMStructs; +private: + T _literal; // ref to item in table. + GraalHashtableEntry* _next; // Link to next element in the linked list for this bucket + +public: + GraalHashtableEntry(T literal) : _literal(literal), _next(NULL) {} + + T literal() { + return _literal; + } + + void set_literal(T value) { + _literal = value; + } + + T* literal_addr() { + return &_literal; + } + + GraalHashtableEntry* next() const { + return _next; + } + + void set_next(GraalHashtableEntry* next) { + _next = next; + } +}; + +template +class ValueClosure : public StackObj { + bool _abort; +protected: + void abort() { _abort = true; } +public: + ValueClosure() : _abort(false) {} + virtual void do_value(V* value) = 0; + bool is_aborted() { return _abort; } +}; + +template class GraalHashtable : public CHeapObj { + friend class VMStructs; +private: + // Instance variables + unsigned int _table_size; + GraalHashtableEntry** _buckets; + unsigned int _number_of_entries; + +public: + GraalHashtable(size_t size) : _table_size(size), _number_of_entries(0) { + _buckets = NEW_C_HEAP_ARRAY(GraalHashtableEntry*, table_size(), mtCompiler); + for (size_t i = 0; i < table_size(); ++i) { + _buckets[i] = NULL; + } + } + virtual ~GraalHashtable(); + +private: + // Bucket handling + unsigned int hash_to_index(unsigned int full_hash) { + unsigned int h = full_hash % _table_size; + assert(h >= 0 && h < _table_size, "Illegal hash value"); + return h; + } + + unsigned int index_for(K key) { + return hash_to_index(compute_hash(key)); + } + + size_t entry_size() { + return sizeof(V); + } + + size_t table_size() { return _table_size; } + + GraalHashtableEntry* bucket(unsigned int index) { + return _buckets[index]; + } + + bool add(V v, bool replace); + +protected: + virtual unsigned int compute_hash(K key) = 0; + virtual bool key_equals(K k1, K k2) = 0; + virtual K get_key(V value) = 0; + virtual K get_key(V* value) = 0; + +public: + /** + * Tries to insert the value in the hash table. Returns false if an entry with the same key already exists. + * In this case it does *not* replace the existing entry. + */ + bool add(V v) { return add(v, false); } + /** + * Inserts the value in the hash table. Returns false if an entry with the same key already exists. + * In this case it replaces the existing entry. + */ + bool put(V v) { return add(v, true); } + V* get(K k); + void for_each(ValueClosure* closure); + int number_of_entries() { return _number_of_entries; } + +}; + +#endif // SHARE_VM_GRAAL_GRAAL_HASHTABLE_HPP diff -r c2e58b2a2a76 -r cecb4e39521c src/share/vm/graal/graalOptions.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalOptions.cpp Wed May 27 17:40:26 2015 +0200 @@ -0,0 +1,241 @@ +/* + * Copyright (c) 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. + */ + +#include "precompiled.hpp" +#include "graal/graalOptions.hpp" +#include "graal/graalRuntime.hpp" +#include "runtime/arguments.hpp" +#include "utilities/hashtable.inline.hpp" + +class OptionsParseClosure : public ParseClosure { + OptionsTable* _table; +public: + OptionsParseClosure(OptionsTable* table) : _table(table) {} + void do_line(char* line) { + char* idx = strchr(line, '\t'); + if (idx == NULL) { + warn_and_abort("invalid format: could not find first tab"); + return; + } + *idx = '\0'; + char* name = line; + line = idx + 1; + idx = strchr(line, '\t'); + if (idx == NULL) { + warn_and_abort("invalid format: could not find second tab"); + return; + } + *idx = '\0'; + if (strlen(line) != 1) { + warn_and_abort("invalid format: type should be 1 char long"); + return; + } + char typeChar = *line; + line = idx + 1; + idx = strchr(line, '\t'); + if (idx == NULL) { + warn_and_abort("invalid format: could not find third tab"); + return; + } + *idx = '\0'; + char* help = line; + line = idx + 1; + idx = strchr(line, '\t'); + if (idx == NULL) { + warn_and_abort("invalid format: could not find fourth tab"); + return; + } + *idx = '\0'; + char* declaringClass = line; + line = idx + 1; + char* fieldClass = line; + OptionType type; + switch(typeChar) { + case 's': + type = _string; + break; + case 'i': + type = _int; + break; + case 'j': + type = _long; + break; + case 'f': + type = _float; + break; + case 'd': + type = _double; + break; + case 'z': + type = _boolean; + break; + default: + warn_and_abort("unkown type"); + return; + } + char* name2 = NEW_C_HEAP_ARRAY(char, (strlen(name) + 1 + strlen(help) + 1 + strlen(declaringClass) + 1 + strlen(fieldClass) + 1), mtCompiler); + char* help2 = name2 + strlen(name) + 1; + char* declaringClass2 = help2 + strlen(help) + 1; + char* fieldClass2 = declaringClass2 + strlen(declaringClass) + 1; + strcpy(name2, name); + strcpy(help2, help); + strcpy(declaringClass2, declaringClass); + strcpy(fieldClass2, fieldClass); + OptionDesc desc = {name2, help2, type, declaringClass2, fieldClass2}; + if (!_table->add(desc)) { + warn_and_abort("duplicate option"); + return; + } + } +}; + +class FreeNamesClosure : public ValueClosure { + void do_value(OptionDesc* desc) { + FREE_C_HEAP_ARRAY(char, desc->name, mtCompiler); + } +}; + +OptionsTable::~OptionsTable() { + FreeNamesClosure closure; + for_each(&closure); +} + +OptionsTable* OptionsTable::load_options() { + OptionsTable* table = new OptionsTable(); + // Add PrintFlags option manually + OptionDesc printFlagsDesc; + printFlagsDesc.name = PRINT_FLAGS_ARG; + printFlagsDesc.type = _boolean; + printFlagsDesc.help = PRINT_FLAGS_HELP; + printFlagsDesc.declaringClass = NULL; + printFlagsDesc.fieldClass = NULL; + table->add(printFlagsDesc); + + char optionsDir[JVM_MAXPATHLEN]; + const char* fileSep = os::file_separator(); + jio_snprintf(optionsDir, sizeof(optionsDir), "%s%slib%sgraal%soptions", + Arguments::get_java_home(), fileSep, fileSep, fileSep); + DIR* dir = os::opendir(optionsDir); + if (dir != NULL) { + struct dirent *entry; + char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(optionsDir), mtInternal); + OptionsParseClosure closure(table); + while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL && !closure.is_aborted()) { + const char* name = entry->d_name; + char optionFilePath[JVM_MAXPATHLEN]; + jio_snprintf(optionFilePath, sizeof(optionFilePath), "%s%s%s",optionsDir, fileSep, name); + GraalRuntime::parse_lines(optionFilePath, &closure, false); + } + FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); + os::closedir(dir); + if (closure.is_aborted()) { + delete table; + return NULL; + } + return table; + } + // TODO(gd) should this be silent? + warning("Could not open graal options directory (%s)",optionsDir); + return table; +} + +OptionDesc* OptionsTable::get(const char* name, size_t arglen) { + char nameOnly[256]; + guarantee(arglen < 256, "Max supported option name len is 256"); + strncpy(nameOnly, name, arglen); + nameOnly[arglen] = '\0'; + return GraalHashtable::get(nameOnly); +} + +// Compute string similarity based on Dice's coefficient +static float str_similar(const char* str1, const char* str2) { + size_t len1 = strlen(str1); + size_t len2 = strlen(str2); + + if (len1 == 0 || len2 == 0) { + return 0; + } + + int hits = 0; + for (size_t i = 0; i < len1 - 1; ++i) { + for (size_t j = 0; j < len2 -1; ++j) { + if ((str1[i] == str2[j]) && (str1[i+1] == str2[j+1])) { + ++hits; + break; + } + } + } + + size_t total = len1 + len2; + return 2.0f * (float) hits / (float) total; +} + +float VMOptionsFuzzyMatchSimilarity = 0.7f; + +class FuzzyMatchClosure : public ValueClosure { + OptionDesc* _match; + float _max_score; + const char* _name; +public: + FuzzyMatchClosure(const char* name) : _name(name), _match(NULL), _max_score(-1) {} + void do_value(OptionDesc* value) { + float score = str_similar(value->name, _name); + if (score > VMOptionsFuzzyMatchSimilarity && score > _max_score) { + _max_score = score; + _match = value; + } + } + OptionDesc* get_match() { + return _match; + } +}; + +OptionDesc * OptionsTable::fuzzy_match(const char* name, size_t length) { + FuzzyMatchClosure closure(name); + for_each(&closure); + return closure.get_match(); +} + +class FreeStringsClosure : public ValueClosure { + void do_value(OptionValue* value) { + if (value->desc.type == _string) { + FREE_C_HEAP_ARRAY(char, value->string_value, mtCompiler); + } + } +}; + +OptionsValueTable::~OptionsValueTable() { + FreeStringsClosure closure; + for_each(&closure); + delete _table; +} + + + +OptionValue* OptionsValueTable::get(const char* name, size_t arglen) { + char nameOnly[256]; + guarantee(arglen < 256, "Max supported option name len is 256"); + strncpy(nameOnly, name, arglen); + nameOnly[arglen] = '\0'; + return GraalHashtable::get(nameOnly); +} diff -r c2e58b2a2a76 -r cecb4e39521c src/share/vm/graal/graalOptions.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalOptions.hpp Wed May 27 17:40:26 2015 +0200 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 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. + */ + +#ifndef SHARE_VM_GRAAL_GRAAL_OPTIONS_HPP +#define SHARE_VM_GRAAL_GRAAL_OPTIONS_HPP + +#include "memory/allocation.hpp" +#include "utilities/exceptions.hpp" +#include "graal/graalHashtable.hpp" + +#define PRINT_FLAGS_ARG "PrintFlags" +#define PRINT_FLAGS_HELP "Prints all Graal flags (similar to XX's PrintFlagsFinal)" + +enum OptionType { + _string, + _int, + _long, + _float, + _double, + _boolean +}; + +struct OptionDesc { + const char* name; + const char* help; + OptionType type; + const char* declaringClass; + const char* fieldClass; +}; + +inline unsigned int compute_string_hash(const char *s, int n) { + unsigned int val = 0; + while (--n >= 0) { + val = *s++ + 31 * val; + } + return val; +} + +class OptionsTable : public GraalHashtable { +protected: + unsigned int compute_hash(const char* key) { return compute_string_hash(key, strlen(key)); } + bool key_equals(const char* k1, const char* k2) { return strcmp(k1, k2) == 0; } + const char* get_key(OptionDesc value) { return value.name; } ; + const char* get_key(OptionDesc* value) { return value->name; } ; +public: + OptionsTable() : GraalHashtable(100) {} + ~OptionsTable(); + using GraalHashtable::get; + OptionDesc* get(const char* name, size_t arglen); + OptionDesc * fuzzy_match(const char* name, size_t length); + + static OptionsTable* load_options(); +}; + +struct OptionValue { + OptionDesc desc; + union { + const char* string_value; + jint int_value; + jlong long_value; + jfloat float_value; + jdouble double_value; + jboolean boolean_value; + }; +}; + +class OptionsValueTable : public GraalHashtable { + OptionsTable* _table; +protected: + unsigned int compute_hash(const char* key) { return compute_string_hash(key, strlen(key)); } + bool key_equals(const char* k1, const char* k2) { return strcmp(k1, k2) == 0; } + const char* get_key(OptionValue value) { return value.desc.name; } ; + const char* get_key(OptionValue* value) { return value->desc.name; } ; +public: + OptionsValueTable(OptionsTable* table) : _table(table), GraalHashtable(100) {} + ~OptionsValueTable(); + using GraalHashtable::get; + OptionValue* get(const char* name, size_t arglen); + OptionsTable* options_table() { return _table; } +}; + + +#endif // SHARE_VM_GRAAL_GRAAL_OPTIONS_HPP diff -r c2e58b2a2a76 -r cecb4e39521c src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Mon May 18 18:30:43 2015 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Wed May 27 17:40:26 2015 +0200 @@ -37,6 +37,7 @@ #include "runtime/arguments.hpp" #include "runtime/reflection.hpp" #include "utilities/debug.hpp" +#include "utilities/defaultStream.hpp" jobject GraalRuntime::_HotSpotGraalRuntime_instance = NULL; bool GraalRuntime::_HotSpotGraalRuntime_initialized = false; @@ -625,6 +626,11 @@ SystemDictionary::initialize_wk_klasses_through(SystemDictionary::LAST_GRAAL_WKID, scan, CHECK); JVM_END +// boolean com.oracle.graal.hotspot.HotSpotOptions.isCITimingEnabled() +JVM_ENTRY(jboolean, JVM_IsCITimingEnabled(JNIEnv *env, jclass c)) + return CITime || CITimeEach; +JVM_END + // private static GraalRuntime Graal.initializeRuntime() JVM_ENTRY(jobject, JVM_GetGraalRuntime(JNIEnv *env, jclass c)) GraalRuntime::initialize_HotSpotGraalRuntime(); @@ -665,26 +671,9 @@ return JNIHandles::make_local(THREAD, (oop) result.get_jobject()); JVM_END -void GraalRuntime::check_generated_sources_sha1(TRAPS) { - TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/sourcegen/GeneratedSourcesSha1", CHECK_ABORT); - KlassHandle klass = load_required_class(name); - fieldDescriptor fd; - if (!InstanceKlass::cast(klass())->find_field(vmSymbols::value_name(), vmSymbols::string_signature(), true, &fd)) { - THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), "GeneratedSourcesSha1.value"); - } - - Symbol* value = java_lang_String::as_symbol(klass->java_mirror()->obj_field(fd.offset()), CHECK); - if (!value->equals(_generated_sources_sha1)) { - char buf[200]; - jio_snprintf(buf, sizeof(buf), "Generated sources SHA1 check failed (%s != %s) - need to rebuild the VM", value->as_C_string(), _generated_sources_sha1); - THROW_MSG(vmSymbols::java_lang_InternalError(), buf); - } -} - Handle GraalRuntime::callInitializer(const char* className, const char* methodName, const char* returnType) { guarantee(!_HotSpotGraalRuntime_initialized, "cannot reinitialize HotSpotGraalRuntime"); Thread* THREAD = Thread::current(); - check_generated_sources_sha1(CHECK_ABORT_(Handle())); TempNewSymbol name = SymbolTable::new_symbol(className, CHECK_ABORT_(Handle())); KlassHandle klass = load_required_class(name); @@ -725,15 +714,6 @@ GraalRuntime::initialize_natives(env, c2vmClass); JVM_END -// private static boolean HotSpotOptions.parseVMOptions() -JVM_ENTRY(jboolean, JVM_ParseGraalOptions(JNIEnv *env, jclass c)) - HandleMark hm; - KlassHandle hotSpotOptionsClass(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c))); - bool result = GraalRuntime::parse_arguments(hotSpotOptionsClass, CHECK_false); - return result; -JVM_END - - void GraalRuntime::ensure_graal_class_loader_is_initialized() { // This initialization code is guarded by a static pointer to the Factory class. // Once it is non-null, the Graal class loader and well known Graal classes are @@ -772,212 +752,316 @@ *((jboolean *) addr) = (jboolean) UseGraalClassLoader; klass->initialize(CHECK_ABORT); _FactoryKlass = klass(); + assert(!UseGraalClassLoader || SystemDictionary::graal_loader() != NULL, "Graal classloader should have been initialized"); } } -jint GraalRuntime::check_arguments(TRAPS) { - KlassHandle nullHandle; - parse_arguments(nullHandle, THREAD); - if (HAS_PENDING_EXCEPTION) { - // Errors in parsing Graal arguments cause exceptions. - // We now load and initialize HotSpotOptions which in turn - // causes argument parsing to be redone with better error messages. - CLEAR_PENDING_EXCEPTION; - TempNewSymbol name = SymbolTable::new_symbol("Lcom/oracle/graal/hotspot/HotSpotOptions;", CHECK_ABORT_(JNI_ERR)); - instanceKlassHandle hotSpotOptionsClass = resolve_or_fail(name, CHECK_ABORT_(JNI_ERR)); - - parse_arguments(hotSpotOptionsClass, THREAD); - assert(HAS_PENDING_EXCEPTION, "must be"); +OptionsValueTable* GraalRuntime::parse_arguments() { + OptionsTable* table = OptionsTable::load_options(); + if (table == NULL) { + return NULL; + } - ResourceMark rm; - Handle exception = PENDING_EXCEPTION; - CLEAR_PENDING_EXCEPTION; - oop message = java_lang_Throwable::message(exception); - if (message != NULL) { - tty->print_cr("Error parsing Graal options: %s", java_lang_String::as_utf8_string(message)); - } else { - call_printStackTrace(exception, THREAD); - } - return JNI_ERR; - } - return JNI_OK; -} - -bool GraalRuntime::parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS) { - ResourceMark rm(THREAD); + OptionsValueTable* options = new OptionsValueTable(table); // Process option overrides from graal.options first - parse_graal_options_file(hotSpotOptionsClass, CHECK_false); + parse_graal_options_file(options); // Now process options on the command line int numOptions = Arguments::num_graal_args(); for (int i = 0; i < numOptions; i++) { char* arg = Arguments::graal_args_array()[i]; - parse_argument(hotSpotOptionsClass, arg, CHECK_false); + if (!parse_argument(options, arg)) { + delete options; + return NULL; + } } - return CITime || CITimeEach; + return options; } -void GraalRuntime::check_required_value(const char* name, size_t name_len, const char* value, TRAPS) { - if (value == NULL) { - char buf[200]; - jio_snprintf(buf, sizeof(buf), "Must use '-G:%.*s=' format for %.*s option", name_len, name, name_len, name); - THROW_MSG(vmSymbols::java_lang_InternalError(), buf); +void not_found(OptionsTable* table, const char* argname, size_t namelen) { + jio_fprintf(defaultStream::error_stream(),"Unrecognized VM option '%.*s'\n", namelen, argname); + OptionDesc* fuzzy_matched = table->fuzzy_match(argname, strlen(argname)); + if (fuzzy_matched != NULL) { + jio_fprintf(defaultStream::error_stream(), + "Did you mean '%s%s%s'?\n", + (fuzzy_matched->type == _boolean) ? "(+/-)" : "", + fuzzy_matched->name, + (fuzzy_matched->type == _boolean) ? "" : "="); } } -void GraalRuntime::parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS) { - ensure_graal_class_loader_is_initialized(); +bool GraalRuntime::parse_argument(OptionsValueTable* options, const char* arg) { + OptionsTable* table = options->options_table(); char first = arg[0]; - char* name; + const char* name; size_t name_len; - bool recognized = true; if (first == '+' || first == '-') { name = arg + 1; - name_len = strlen(name); - recognized = set_option_bool(hotSpotOptionsClass, name, name_len, first, CHECK); + OptionDesc* optionDesc = table->get(name); + if (optionDesc == NULL) { + not_found(table, name, strlen(name)); + return false; + } + if (optionDesc->type != _boolean) { + jio_fprintf(defaultStream::error_stream(), "Unexpected +/- setting in VM option '%s'\n", name); + return false; + } + OptionValue value; + value.desc = *optionDesc; + value.boolean_value = first == '+'; + options->put(value); + return true; } else { - char* sep = strchr(arg, '='); + const char* sep = strchr(arg, '='); name = arg; - char* value = NULL; + const char* value = NULL; if (sep != NULL) { name_len = sep - name; value = sep + 1; } else { name_len = strlen(name); } - recognized = set_option(hotSpotOptionsClass, name, name_len, value, CHECK); - } - - if (!recognized) { - bool throw_err = hotSpotOptionsClass.is_null(); - if (!hotSpotOptionsClass.is_null()) { - set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), ' ', Handle(), 0L); - if (!HAS_PENDING_EXCEPTION) { - throw_err = true; + OptionDesc* optionDesc = table->get(name, name_len); + if (optionDesc == NULL) { + not_found(table, name, name_len); + return false; + } + if (optionDesc->type == _boolean) { + jio_fprintf(defaultStream::error_stream(), "Missing +/- setting for VM option '%s'\n", name); + return false; + } + if (value == NULL) { + jio_fprintf(defaultStream::error_stream(), "Must use '-G:%.*s=' format for %.*s option", name_len, name, name_len, name); + return false; + } + OptionValue optionValue; + optionValue.desc = *optionDesc; + char* check; + errno = 0; + switch(optionDesc->type) { + case _int: { + long int int_value = ::strtol(value, &check, 10); + if (*check != '\0' || errno == ERANGE || int_value > max_jint || int_value < min_jint) { + jio_fprintf(defaultStream::error_stream(), "Expected int value for VM option '%s'\n", name); + return false; + } + optionValue.int_value = int_value; + break; } + case _long: { + long long int long_value = ::strtoll(value, &check, 10); + if (*check != '\0' || errno == ERANGE || long_value > max_jlong || long_value < min_jlong) { + jio_fprintf(defaultStream::error_stream(), "Expected long value for VM option '%s'\n", name); + return false; + } + optionValue.long_value = long_value; + break; + } + case _float: { + optionValue.float_value = ::strtof(value, &check); + if (*check != '\0' || errno == ERANGE) { + jio_fprintf(defaultStream::error_stream(), "Expected float value for VM option '%s'\n", name); + return false; + } + break; + } + case _double: { + optionValue.double_value = ::strtod(value, &check); + if (*check != '\0' || errno == ERANGE) { + jio_fprintf(defaultStream::error_stream(), "Expected double value for VM option '%s'\n", name); + return false; + } + break; + } + case _string: { + char* copy = NEW_C_HEAP_ARRAY(char, strlen(value) + 1, mtCompiler); + strcpy(copy, value); + optionValue.string_value = copy; + break; + } + default: + ShouldNotReachHere(); } - - if (throw_err) { - char buf[200]; - jio_snprintf(buf, sizeof(buf), "Unrecognized Graal option %.*s", name_len, name); - THROW_MSG(vmSymbols::java_lang_InternalError(), buf); - } + options->put(optionValue); + return true; } } class GraalOptionParseClosure : public ParseClosure { - TRAPS; - KlassHandle _hotSpotOptionsClass; + OptionsValueTable* _options; public: - GraalOptionParseClosure(KlassHandle hotSpotOptionsClass, TRAPS) : THREAD(THREAD), _hotSpotOptionsClass(hotSpotOptionsClass) {} + GraalOptionParseClosure(OptionsValueTable* options) : _options(options) {} void do_line(char* line) { - GraalRuntime::parse_argument(_hotSpotOptionsClass, line, THREAD); - if (HAS_PENDING_EXCEPTION) { - warn_and_abort("Exception thrown while parsing argument"); + if (!GraalRuntime::parse_argument(_options, line)) { + warn("There was an error parsing an argument. Skipping it."); } } }; -void GraalRuntime::parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS) { +void GraalRuntime::parse_graal_options_file(OptionsValueTable* options) { const char* home = Arguments::get_java_home(); size_t path_len = strlen(home) + strlen("/lib/graal.options") + 1; - char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len); + char path[JVM_MAXPATHLEN]; char sep = os::file_separator()[0]; - sprintf(path, "%s%clib%cgraal.options", home, sep, sep); - GraalOptionParseClosure closure(hotSpotOptionsClass, THREAD); - parse_lines(path, &closure, false, THREAD); -} - -jlong GraalRuntime::parse_primitive_option_value(char spec, const char* name, size_t name_len, const char* value, TRAPS) { - check_required_value(name, name_len, value, CHECK_(0L)); - union { - jint i; - jlong l; - double d; - } uu; - uu.l = 0L; - char dummy; - switch (spec) { - case 'd': - case 'f': { - if (sscanf(value, "%lf%c", &uu.d, &dummy) == 1) { - return uu.l; - } - break; - } - case 'i': { - if (sscanf(value, "%d%c", &uu.i, &dummy) == 1) { - return (jlong)uu.i; - } - break; - } - default: - ShouldNotReachHere(); - } - ResourceMark rm(THREAD); - char buf[200]; - bool missing = strlen(value) == 0; - if (missing) { - jio_snprintf(buf, sizeof(buf), "Missing %s value for Graal option %.*s", (spec == 'i' ? "numeric" : "float/double"), name_len, name); - } else { - jio_snprintf(buf, sizeof(buf), "Invalid %s value for Graal option %.*s: %s", (spec == 'i' ? "numeric" : "float/double"), name_len, name, value); - } - THROW_MSG_(vmSymbols::java_lang_InternalError(), buf, 0L); + jio_snprintf(path, JVM_MAXPATHLEN, "%s%clib%cgraal.options", home, sep, sep); + GraalOptionParseClosure closure(options); + parse_lines(path, &closure, false); } -void GraalRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) { - Thread* THREAD = Thread::current(); - Handle name_handle; - if (name != NULL) { - if (strlen(name) > name_len) { - // Temporarily replace '=' with NULL to create the Java string for the option name - char save = name[name_len]; - name[name_len] = '\0'; - name_handle = java_lang_String::create_from_str(name, THREAD); - name[name_len] = '='; - if (HAS_PENDING_EXCEPTION) { - return; +#define CHECK_WARN_ABORT_(message) THREAD); \ + if (HAS_PENDING_EXCEPTION) { \ + warning(message); \ + char buf[512]; \ + jio_snprintf(buf, 512, "Uncaught exception at %s:%d", __FILE__, __LINE__); \ + GraalRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \ + return; \ + } \ + (void)(0 + +class SetOptionClosure : public ValueClosure { + Thread* _thread; +public: + SetOptionClosure(TRAPS) : _thread(THREAD) {} + void do_value(OptionValue* optionValue) { + TRAPS = _thread; + const char* declaringClass = optionValue->desc.declaringClass; + if (declaringClass == NULL) { + // skip PrintFlags pseudo-option + return; + } + const char* fieldName = optionValue->desc.name; + const char* fieldClass = optionValue->desc.fieldClass; + + size_t fieldSigLen = 2 + strlen(fieldClass); + char* fieldSig = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, fieldSigLen + 1); + jio_snprintf(fieldSig, fieldSigLen + 1, "L%s;", fieldClass); + for (size_t i = 0; i < fieldSigLen; ++i) { + if (fieldSig[i] == '.') { + fieldSig[i] = '/'; + } + } + fieldSig[fieldSigLen] = '\0'; + size_t declaringClassLen = strlen(declaringClass); + char* declaringClassBinary = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, declaringClassLen + 1); + for (size_t i = 0; i < declaringClassLen; ++i) { + if (declaringClass[i] == '.') { + declaringClassBinary[i] = '/'; + } else { + declaringClassBinary[i] = declaringClass[i]; } - } else { - assert(strlen(name) == name_len, "must be"); - name_handle = java_lang_String::create_from_str(name, CHECK); + } + declaringClassBinary[declaringClassLen] = '\0'; + + TempNewSymbol name = SymbolTable::new_symbol(declaringClassBinary, CHECK_WARN_ABORT_("Declaring class could not be found")); + Klass* klass = GraalRuntime::resolve_or_null(name, CHECK_WARN_ABORT_("Declaring class could not be resolved")); + + if (klass == NULL) { + warning("Declaring class for option %s could not be resolved", declaringClass); + abort(); + return; + } + + // The class has been loaded so the field and signature should already be in the symbol + // table. If they're not there, the field doesn't exist. + TempNewSymbol fieldname = SymbolTable::probe(fieldName, (int)strlen(fieldName)); + TempNewSymbol signame = SymbolTable::probe(fieldSig, (int)fieldSigLen); + if (fieldname == NULL || signame == NULL) { + warning("Symbols for field for option %s not found (in %s)", fieldName, declaringClass); + abort(); + return; + } + // Make sure class is initialized before handing id's out to fields + klass->initialize(CHECK_WARN_ABORT_("Error while initializing declaring class for option")); + + fieldDescriptor fd; + if (!InstanceKlass::cast(klass)->find_field(fieldname, signame, true, &fd)) { + warning("Field for option %s not found (in %s)", fieldName, declaringClass); + abort(); + return; + } + oop value; + switch(optionValue->desc.type) { + case _boolean: { + jvalue jv; + jv.z = optionValue->boolean_value; + value = java_lang_boxing_object::create(T_BOOLEAN, &jv, THREAD); + break; + } + case _int: { + jvalue jv; + jv.i = optionValue->int_value; + value = java_lang_boxing_object::create(T_INT, &jv, THREAD); + break; + } + case _long: { + jvalue jv; + jv.j = optionValue->long_value; + value = java_lang_boxing_object::create(T_LONG, &jv, THREAD); + break; + } + case _float: { + jvalue jv; + jv.f = optionValue->float_value; + value = java_lang_boxing_object::create(T_FLOAT, &jv, THREAD); + break; + } + case _double: { + jvalue jv; + jv.d = optionValue->double_value; + value = java_lang_boxing_object::create(T_DOUBLE, &jv, THREAD); + break; + } + case _string: + value = java_lang_String::create_from_str(optionValue->string_value, THREAD)(); + break; + default: + ShouldNotReachHere(); + } + + oop optionValueOop = klass->java_mirror()->obj_field(fd.offset()); + + if (optionValueOop == NULL) { + warning("Option field was null, can not set %s", fieldName); + abort(); + return; + } + + if (!InstanceKlass::cast(optionValueOop->klass())->find_field(vmSymbols::value_name(), vmSymbols::object_signature(), false, &fd)) { + warning("'Object value' field not found in option class %s, can not set option %s", fieldClass, fieldName); + abort(); + return; + } + + optionValueOop->obj_field_put(fd.offset(), value); + } +}; + +void GraalRuntime::set_options(OptionsValueTable* options, TRAPS) { + ensure_graal_class_loader_is_initialized(); + { + ResourceMark rm; + SetOptionClosure closure(THREAD); + options->for_each(&closure); + if (closure.is_aborted()) { + vm_abort(false); } } + OptionValue* printFlags = options->get(PRINT_FLAGS_ARG); + if (printFlags != NULL && printFlags->boolean_value) { + print_flags_helper(CHECK_ABORT); + } +} - TempNewSymbol setOption = SymbolTable::new_symbol("setOption", CHECK); - TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;Lcom/oracle/graal/options/OptionValue;CLjava/lang/String;J)V", CHECK); +void GraalRuntime::print_flags_helper(TRAPS) { + // TODO(gd) write this in C++? + HandleMark hm(THREAD); + TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotOptions", CHECK_ABORT); + KlassHandle hotSpotOptionsClass = load_required_class(name); + TempNewSymbol setOption = SymbolTable::new_symbol("printFlags", CHECK); JavaValue result(T_VOID); JavaCallArguments args; - args.push_oop(name_handle()); - args.push_oop(option()); - args.push_int(spec); - args.push_oop(stringValue()); - args.push_long(primitiveValue); - JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, sig, &args, CHECK); -} - -Handle GraalRuntime::get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS) { - TempNewSymbol name = SymbolTable::new_symbol(declaringClass, CHECK_NH); - Klass* klass = resolve_or_fail(name, CHECK_NH); - - // The class has been loaded so the field and signature should already be in the symbol - // table. If they're not there, the field doesn't exist. - TempNewSymbol fieldname = SymbolTable::probe(fieldName, (int)strlen(fieldName)); - TempNewSymbol signame = SymbolTable::probe(fieldSig, (int)strlen(fieldSig)); - if (fieldname == NULL || signame == NULL) { - THROW_MSG_(vmSymbols::java_lang_NoSuchFieldError(), (char*) fieldName, Handle()); - } - // Make sure class is initialized before handing id's out to fields - klass->initialize(CHECK_NH); - - fieldDescriptor fd; - if (!InstanceKlass::cast(klass)->find_field(fieldname, signame, true, &fd)) { - THROW_MSG_(vmSymbols::java_lang_NoSuchFieldError(), (char*) fieldName, Handle()); - } - - Handle ret = klass->java_mirror()->obj_field(fd.offset()); - return ret; + JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, vmSymbols::void_method_signature(), &args, CHECK); } Handle GraalRuntime::create_Service(const char* name, TRAPS) { @@ -1052,68 +1136,69 @@ return klass; } -void GraalRuntime::parse_lines(char* path, ParseClosure* closure, bool warnStatFailure, TRAPS) { +void GraalRuntime::parse_lines(char* path, ParseClosure* closure, bool warnStatFailure) { struct stat st; - if (os::stat(path, &st) == 0) { - int file_handle = os::open(path, 0, 0); - if (file_handle != -1) { - char* buffer = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, st.st_size + 1); - int num_read = (int) os::read(file_handle, (char*) buffer, st.st_size); - if (num_read == -1) { - warning("Error reading file %s due to %s", path, strerror(errno)); - } else if (num_read != st.st_size) { - warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path); - } - os::close(file_handle); - closure->set_filename(path); - if (num_read == st.st_size) { - buffer[num_read] = '\0'; + if (os::stat(path, &st) == 0 && (st.st_mode & S_IFREG) == S_IFREG) { // exists & is regular file + int file_handle = os::open(path, 0, 0); + if (file_handle != -1) { + char* buffer = NEW_C_HEAP_ARRAY(char, st.st_size + 1, mtInternal); + int num_read = (int) os::read(file_handle, (char*) buffer, st.st_size); + if (num_read == -1) { + warning("Error reading file %s due to %s", path, strerror(errno)); + } else if (num_read != st.st_size) { + warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path); + } + os::close(file_handle); + closure->set_filename(path); + if (num_read == st.st_size) { + buffer[num_read] = '\0'; - char* line = buffer; - while (line - buffer < num_read && !closure->is_aborted()) { - // find line end (\r, \n or \r\n) - char* nextline = NULL; - char* cr = strchr(line, '\r'); - char* lf = strchr(line, '\n'); - if (cr != NULL && lf != NULL) { - char* min = MIN2(cr, lf); - *min = '\0'; - if (lf == cr + 1) { - nextline = lf + 1; - } else { - nextline = min + 1; - } - } else if (cr != NULL) { - *cr = '\0'; - nextline = cr + 1; - } else if (lf != NULL) { - *lf = '\0'; + char* line = buffer; + while (line - buffer < num_read && !closure->is_aborted()) { + // find line end (\r, \n or \r\n) + char* nextline = NULL; + char* cr = strchr(line, '\r'); + char* lf = strchr(line, '\n'); + if (cr != NULL && lf != NULL) { + char* min = MIN2(cr, lf); + *min = '\0'; + if (lf == cr + 1) { nextline = lf + 1; + } else { + nextline = min + 1; } - // trim left - while (*line == ' ' || *line == '\t') line++; - char* end = line + strlen(line); - // trim right - while (end > line && (*(end -1) == ' ' || *(end -1) == '\t')) end--; - *end = '\0'; - // skip comments and empty lines - if (*line != '#' && strlen(line) > 0) { - closure->parse_line(line); - } - if (nextline != NULL) { - line = nextline; - } else { - // File without newline at the end - break; - } + } else if (cr != NULL) { + *cr = '\0'; + nextline = cr + 1; + } else if (lf != NULL) { + *lf = '\0'; + nextline = lf + 1; + } + // trim left + while (*line == ' ' || *line == '\t') line++; + char* end = line + strlen(line); + // trim right + while (end > line && (*(end -1) == ' ' || *(end -1) == '\t')) end--; + *end = '\0'; + // skip comments and empty lines + if (*line != '#' && strlen(line) > 0) { + closure->parse_line(line); + } + if (nextline != NULL) { + line = nextline; + } else { + // File without newline at the end + break; } } - } else { - warning("Error opening file %s due to %s", path, strerror(errno)); } - } else if (warnStatFailure) { - warning("Could not stat file %s due to %s", path, strerror(errno)); + FREE_C_HEAP_ARRAY(char, buffer, mtInternal); + } else { + warning("Error opening file %s due to %s", path, strerror(errno)); } + } else if (warnStatFailure) { + warning("Could not stat file %s due to %s", path, strerror(errno)); + } } class ServiceParseClosure : public ParseClosure { @@ -1121,13 +1206,18 @@ public: ServiceParseClosure() : _implNames() {} void do_line(char* line) { + size_t lineLen = strlen(line); + char* implName = NEW_C_HEAP_ARRAY(char, lineLen + 1, mtCompiler); // TODO (gd) i'm leaking // Turn all '.'s into '/'s - for (size_t index = 0; line[index] != '\0'; index++) { + for (size_t index = 0; index < lineLen; ++index) { if (line[index] == '.') { - line[index] = '/'; + implName[index] = '/'; + } else { + implName[index] = line[index]; } } - _implNames.append(line); + implName[lineLen] = '\0'; + _implNames.append(implName); } GrowableArray* implNames() {return &_implNames;} }; @@ -1141,7 +1231,7 @@ char sep = os::file_separator()[0]; sprintf(path, "%s%clib%cgraal%cservices%c%s", home, sep, sep, sep, sep, serviceName); ServiceParseClosure closure; - parse_lines(path, &closure, true, THREAD); + parse_lines(path, &closure, true); // TODO(gd) cache parsing results? GrowableArray* implNames = closure.implNames(); objArrayOop servicesOop = oopFactory::new_objArray(serviceKlass(), implNames->length(), CHECK_NH); @@ -1153,5 +1243,3 @@ } return services; } - -#include "graalRuntime.inline.hpp" diff -r c2e58b2a2a76 -r cecb4e39521c src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Mon May 18 18:30:43 2015 +0200 +++ b/src/share/vm/graal/graalRuntime.hpp Wed May 27 17:40:26 2015 +0200 @@ -27,19 +27,23 @@ #include "interpreter/interpreter.hpp" #include "memory/allocation.hpp" #include "runtime/deoptimization.hpp" +#include "graal/graalOptions.hpp" class ParseClosure : public StackObj { -protected: int _lineNo; char* _filename; bool _abort; +protected: void abort() { _abort = true; } void warn_and_abort(const char* message) { - warning("Error at line %d while parsing %s: %s", _lineNo, _filename == NULL ? "?" : _filename, message); + warn(message); abort(); } + void warn(const char* message) { + warning("Error at line %d while parsing %s: %s", _lineNo, _filename == NULL ? "?" : _filename, message); + } public: - ParseClosure() : _lineNo(0), _filename(NULL) {} + ParseClosure() : _lineNo(0), _filename(NULL), _abort(false) {} void parse_line(char* line) { _lineNo++; do_line(line); @@ -47,86 +51,31 @@ virtual void do_line(char* line) = 0; int lineNo() { return _lineNo; } bool is_aborted() { return _abort; } - void set_filename(char* path) {_filename = path; } + void set_filename(char* path) {_filename = path; _lineNo = 0;} }; +class GraalOptionParseClosure; + class GraalRuntime: public CHeapObj { + friend GraalOptionParseClosure; private: static jobject _HotSpotGraalRuntime_instance; static bool _HotSpotGraalRuntime_initialized; - static const char* _generated_sources_sha1; static bool _shutdown_called; /** - * Reads the OptionValue object from a specified static field. - * - * @throws LinkageError if the field could not be resolved - */ - static Handle get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS); - - /** - * Parses the string form of a numeric, float or double option into a jlong (using raw bits for floats/doubles). - * - * @param spec 'i', 'f' or 'd' (see HotSpotOptions.setOption()) - * @param name option name - * @param name_len length of option name - * @param value string value to parse - * @throws InternalError if value could not be parsed according to spec - */ - static jlong parse_primitive_option_value(char spec, const char* name, size_t name_len, const char* value, TRAPS); - - /** * Loads default option value overrides from a /lib/graal.options if it exists. Each * line in this file must have the format of a Graal command line option without the * leading "-G:" prefix. These option values are set prior to processing of any Graal * options present on the command line. */ - static void parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS); - - /** - * Searches for a Boolean Graal option denoted by a given name and sets it value. - * - * The definition of this method is in graalRuntime.inline.hpp - * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp. - * - * @param hotSpotOptionsClass the HotSpotOptions klass or NULL if only checking for valid option - * @param name option name - * @param name_len length of option name - * @param value '+' to set the option, '-' to reset the option - * @returns true if the option was found - * @throws InternalError if there was a problem setting the option's value - */ - static bool set_option_bool(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, char value, TRAPS); + static void parse_graal_options_file(OptionsValueTable* options); - /** - * Searches for a Graal option denoted by a given name and sets it value. - * - * The definition of this method is in graalRuntime.inline.hpp - * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp. - * - * @param hotSpotOptionsClass the HotSpotOptions klass or NULL if only checking for valid option - * @param name option name - * @param name_len length of option name - * @returns true if the option was found - * @throws InternalError if there was a problem setting the option's value - */ - static bool set_option(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, const char* value, TRAPS); + static bool parse_argument(OptionsValueTable* options, const char* arg); - /** - * Raises an InternalError for an option that expects a value but was specified without a "=" prefix. - */ - static void check_required_value(const char* name, size_t name_len, const char* value, TRAPS); - - /** - * Java call to HotSpotOptions.setOption(String name, OptionValue option, char spec, String stringValue, long primitiveValue) - * - * @param name option name - * @param name_len length of option name - */ - static void set_option_helper(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue); - + static void print_flags_helper(TRAPS); /** * Instantiates a service object, calls its default constructor and returns it. * @@ -134,19 +83,15 @@ */ static Handle create_Service(const char* name, TRAPS); - /** - * Checks that _generated_sources_sha1 equals GeneratedSourcesSha1.value. - */ - static void check_generated_sources_sha1(TRAPS); - public: /** - * Parses a given argument and sets the denoted Graal option. - * - * @throws InternalError if there was a problem parsing or setting the option + * Parses the Graal specific VM options that were presented by the launcher and sets + * the relevants Java fields. */ - static void parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS); + static OptionsValueTable* parse_arguments(); + + static void set_options(OptionsValueTable* options, TRAPS); /** * Ensures that the Graal class loader is initialized and the well known Graal classes are loaded. @@ -199,7 +144,7 @@ */ static Handle get_service_impls(KlassHandle serviceKlass, TRAPS); - static void parse_lines(char* path, ParseClosure* closure, bool warnStatFailure, TRAPS); + static void parse_lines(char* path, ParseClosure* closure, bool warnStatFailure); /** * Aborts the VM due to an unexpected exception. @@ -246,20 +191,6 @@ static BufferBlob* initialize_buffer_blob(); - /** - * Checks that all Graal specific VM options presented by the launcher are recognized - * and formatted correctly. To set relevant Java fields from the option, parse_arguments() - * must be called. This method makes no Java calls apart from creating exception objects - * if there is an errors in the Graal options. - */ - static jint check_arguments(TRAPS); - - /** - * Parses the Graal specific VM options that were presented by the launcher and sets - * the relevants Java fields. - */ - static bool parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS); - static BasicType kindToBasicType(jchar ch); // The following routines are all called from compiled Graal code diff -r c2e58b2a2a76 -r cecb4e39521c src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Mon May 18 18:30:43 2015 +0200 +++ b/src/share/vm/prims/nativeLookup.cpp Wed May 27 17:40:26 2015 +0200 @@ -133,7 +133,7 @@ jobject JNICALL JVM_GetGraalServiceImpls(JNIEnv *env, jclass c, jclass serviceClass); jobject JNICALL JVM_CreateTruffleRuntime(JNIEnv *env, jclass c); jobject JNICALL JVM_CreateNativeFunctionInterface(JNIEnv *env, jclass c); - jboolean JNICALL JVM_ParseGraalOptions(JNIEnv *env, jclass hotspotOptionsClass); + jboolean JNICALL JVM_IsCITimingEnabled(JNIEnv *env); #ifdef COMPILERGRAAL void JNICALL JVM_PrintAndResetGraalCompRate(JNIEnv *env, jclass c); #endif @@ -155,7 +155,7 @@ { CC"Java_com_oracle_truffle_api_Truffle_createRuntime", NULL, FN_PTR(JVM_CreateTruffleRuntime) }, { CC"Java_com_oracle_nfi_NativeFunctionInterfaceRuntime_createInterface", NULL, FN_PTR(JVM_CreateNativeFunctionInterface) }, { CC"Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_init", NULL, FN_PTR(JVM_InitializeGraalNatives) }, - { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_parseVMOptions", NULL, FN_PTR(JVM_ParseGraalOptions) }, + { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_isCITimingEnabled", NULL, FN_PTR(JVM_IsCITimingEnabled) }, #endif }; diff -r c2e58b2a2a76 -r cecb4e39521c src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Mon May 18 18:30:43 2015 +0200 +++ b/src/share/vm/runtime/thread.cpp Wed May 27 17:40:26 2015 +0200 @@ -3395,6 +3395,13 @@ jint parse_result = Arguments::parse(args); if (parse_result != JNI_OK) return parse_result; +#ifdef GRAAL + OptionsValueTable* options = GraalRuntime::parse_arguments(); + if (options == NULL) { + return JNI_ERR; + } +#endif + os::init_before_ergo(); jint ergo_result = Arguments::apply_ergo(); @@ -3703,11 +3710,7 @@ } #ifdef GRAAL - status = GraalRuntime::check_arguments(main_thread); - if (status != JNI_OK) { - *canTryAgain = false; // don't let caller call JNI_CreateJavaVM again - return status; - } + GraalRuntime::set_options(options, main_thread); #endif // initialize compiler(s)