changeset 22687:d43f6d932ad5

made ShowFlags and PrintFlags denote which options had their value explicitily set (like -XX:+PrintFlagsFinal does)
author Doug Simon <doug.simon@oracle.com>
date Fri, 16 Oct 2015 00:16:51 +0200
parents 2408f05d0ae7
children ef7d87db544a
files jvmci/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsParser.java
diffstat 1 files changed, 88 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/jvmci/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsParser.java	Thu Oct 15 11:50:37 2015 -0700
+++ b/jvmci/jdk.vm.ci.options/src/jdk/vm/ci/options/OptionsParser.java	Fri Oct 16 00:16:51 2015 +0200
@@ -32,9 +32,11 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Formatter;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.ServiceLoader;
+import java.util.Set;
 import java.util.SortedMap;
 
 import jdk.vm.ci.inittimer.InitTimer;
@@ -77,6 +79,7 @@
      */
     @SuppressWarnings("try")
     public static Boolean parseOptionsFromVM(String[] options, boolean parseOptionsFile) {
+
         try (InitTimer t = timer("ParseOptions")) {
             JVMCIJarsOptionDescriptorsProvider odp = JVMCIJarsOptionDescriptorsProvider.create();
 
@@ -89,48 +92,110 @@
                     try (BufferedReader br = new BufferedReader(new FileReader(jvmciOptions))) {
                         String optionSetting = null;
                         int lineNo = 1;
+                        List<String> optionSettings = new ArrayList<>();
                         while ((optionSetting = br.readLine()) != null) {
                             if (!optionSetting.isEmpty() && optionSetting.charAt(0) != '#') {
                                 try {
-                                    parseOptionSetting(optionSetting, null, odp);
+                                    parseOptionSettingTo(optionSetting, optionSettings);
                                 } catch (Throwable e) {
                                     throw new InternalError("Error parsing " + jvmciOptions + ", line " + lineNo, e);
                                 }
                             }
                             lineNo++;
                         }
+                        try {
+                            parseOptions(optionSettings.toArray(new String[optionSettings.size()]), null, odp, null);
+                        } catch (Throwable e) {
+                            throw new InternalError("Error parsing an option from " + jvmciOptions, e);
+                        }
                     } catch (IOException e) {
                         throw new InternalError("Error reading " + jvmciOptions, e);
                     }
                 }
             }
 
-            if (options != null) {
-                assert options.length % 2 == 0;
-                for (int i = 0; i < options.length / 2; i++) {
-                    String name = options[i * 2];
-                    String value = options[i * 2 + 1];
-                    parseOption(name, value, null, odp, null);
-                }
-            }
+            parseOptions(options, null, odp, null);
         }
         return Boolean.TRUE;
     }
 
     /**
-     * Parses a given option setting.
+     * Parses an ordered list of (name, value) pairs assigning values to JVMCI options.
+     *
+     * @param optionSettings JVMCI options as serialized (name, value) pairs
+     * @param setter the object to notify of the parsed option and value
+     * @param odp if non-null, the service to use for looking up {@link OptionDescriptor}s
+     * @param options the options database to use if {@code odp == null}. If
+     *            {@code options == null && odp == null}, {@link OptionsLoader#options} is used.
+     * @throws IllegalArgumentException if there's a problem parsing {@code option}
+     */
+    public static void parseOptions(String[] optionSettings, OptionConsumer setter, OptionDescriptorsProvider odp, SortedMap<String, OptionDescriptor> options) {
+        if (optionSettings != null && optionSettings.length != 0) {
+            assert optionSettings.length % 2 == 0;
+
+            moveHelpFlagsToTail(optionSettings);
+
+            for (int i = 0; i < optionSettings.length / 2; i++) {
+                String name = optionSettings[i * 2];
+                String value = optionSettings[i * 2 + 1];
+                parseOption(name, value, setter, odp, options);
+            }
+            if (PrintFlags.getValue() || ShowFlags.getValue()) {
+                Set<String> explicitlyAssigned = new HashSet<>(optionSettings.length / 2);
+                for (int i = 0; i < optionSettings.length / 2; i++) {
+                    String name = optionSettings[i * 2];
+                    explicitlyAssigned.add(name);
+                }
+                printFlags(resolveOptions(options), "JVMCI", System.out, explicitlyAssigned);
+                if (PrintFlags.getValue()) {
+                    System.exit(0);
+                }
+            }
+        }
+    }
+
+    /**
+     * Moves all {@code PrintFlags} and {@code ShowFlags} option settings to the back of
+     * {@code optionSettings}. This allows the help message to show which options had their value
+     * explicitly set (even if to their default value).
+     */
+    private static void moveHelpFlagsToTail(String[] optionSettings) {
+        List<String> tail = null;
+        int insert = 0;
+        for (int i = 0; i < optionSettings.length / 2; i++) {
+            String name = optionSettings[i * 2];
+            String value = optionSettings[i * 2 + 1];
+            if (name.equals("ShowFlags") || name.equals("PrintFlags")) {
+                if (tail == null) {
+                    tail = new ArrayList<>(4);
+                    insert = i * 2;
+                }
+                tail.add(name);
+                tail.add(value);
+            } else if (tail != null) {
+                optionSettings[insert++] = name;
+                optionSettings[insert++] = value;
+            }
+        }
+        if (tail != null) {
+            assert tail.size() + insert == optionSettings.length;
+            String[] tailArr = tail.toArray(new String[tail.size()]);
+            System.arraycopy(tailArr, 0, optionSettings, insert, tailArr.length);
+        }
+    }
+
+    /**
+     * Parses a given option setting string to a list of (name, value) pairs.
      *
      * @param optionSetting a string matching the pattern {@code <name>=<value>}
-     * @param setter the object to notify of the parsed option and value
      */
-    public static void parseOptionSetting(String optionSetting, OptionConsumer setter, OptionDescriptorsProvider odp) {
+    public static void parseOptionSettingTo(String optionSetting, List<String> dst) {
         int eqIndex = optionSetting.indexOf('=');
         if (eqIndex == -1) {
             throw new InternalError("Option setting has does not match the pattern <name>=<value>: " + optionSetting);
         }
-        String name = optionSetting.substring(0, eqIndex);
-        String value = optionSetting.substring(eqIndex + 1);
-        parseOption(name, value, setter, odp, null);
+        dst.add(optionSetting.substring(0, eqIndex));
+        dst.add(optionSetting.substring(eqIndex + 1));
     }
 
     /**
@@ -148,10 +213,11 @@
      * @param valueString the option value as a string
      * @param setter the object to notify of the parsed option and value
      * @param odp if non-null, the service to use for looking up {@link OptionDescriptor}s
-     * @param options the options database to use if {@code odp} is null
+     * @param options the options database to use if {@code odp == null}. If
+     *            {@code options == null && odp == null}, {@link OptionsLoader#options} is used.
      * @throws IllegalArgumentException if there's a problem parsing {@code option}
      */
-    public static void parseOption(String name, String valueString, OptionConsumer setter, OptionDescriptorsProvider odp, SortedMap<String, OptionDescriptor> options) {
+    private static void parseOption(String name, String valueString, OptionConsumer setter, OptionDescriptorsProvider odp, SortedMap<String, OptionDescriptor> options) {
 
         OptionDescriptor desc = odp != null ? odp.get(name) : resolveOptions(options).get(name);
         if (desc == null) {
@@ -202,13 +268,6 @@
         } else {
             setter.set(desc, value);
         }
-
-        if (PrintFlags.getValue() || ShowFlags.getValue()) {
-            printFlags(resolveOptions(options), "JVMCI", System.out);
-            if (PrintFlags.getValue()) {
-                System.exit(0);
-            }
-        }
     }
 
     private static long parseLong(String v) {
@@ -274,16 +333,18 @@
         return lines;
     }
 
-    public static void printFlags(SortedMap<String, OptionDescriptor> sortedOptions, String prefix, PrintStream out) {
+    private static void printFlags(SortedMap<String, OptionDescriptor> sortedOptions, String prefix, PrintStream out, Set<String> explicitlyAssigned) {
         out.println("[List of " + prefix + " options]");
         for (Map.Entry<String, OptionDescriptor> e : sortedOptions.entrySet()) {
             e.getKey();
             OptionDescriptor desc = e.getValue();
             Object value = desc.getOptionValue().getValue();
             List<String> helpLines = wrap(desc.getHelp(), 70);
-            out.println(String.format("%9s %-40s = %-14s %s", desc.getType().getSimpleName(), e.getKey(), value, helpLines.get(0)));
+            String name = e.getKey();
+            String assign = explicitlyAssigned.contains(name) ? ":=" : " =";
+            out.printf("%9s %-40s %s %-14s %s%n", desc.getType().getSimpleName(), name, assign, value, helpLines.get(0));
             for (int i = 1; i < helpLines.size(); i++) {
-                out.println(String.format("%67s %s", " ", helpLines.get(i)));
+                out.printf("%67s %s%n", " ", helpLines.get(i));
             }
         }
     }