# HG changeset patch # User Doug Simon # Date 1441725038 -7200 # Node ID bab91f9ae79579f97ed2b7148fe0c9e917ceb090 # Parent df053711614bbad30c2b885f7a49ee1d7f0c180d added support for embedding spaces in JVMCI options using % as the escape character (note: do not use with -G:, only with -Djvmci.option=...) diff -r df053711614b -r bab91f9ae795 jvmci/jdk.internal.jvmci.common/src/jdk/internal/jvmci/common/JVMCIError.java --- a/jvmci/jdk.internal.jvmci.common/src/jdk/internal/jvmci/common/JVMCIError.java Tue Sep 08 14:13:38 2015 +0200 +++ b/jvmci/jdk.internal.jvmci.common/src/jdk/internal/jvmci/common/JVMCIError.java Tue Sep 08 17:10:38 2015 +0200 @@ -70,6 +70,15 @@ } /** + * This constructor creates a {@link JVMCIError} with a given message. + * + * @param msg the message that will be associated with the error + */ + public JVMCIError(String msg) { + super(msg); + } + + /** * This constructor creates a {@link JVMCIError} with a message assembled via * {@link String#format(String, Object...)}. It always uses the ENGLISH locale in order to * always generate the same output. diff -r df053711614b -r bab91f9ae795 jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/OptionsParser.java --- a/jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/OptionsParser.java Tue Sep 08 14:13:38 2015 +0200 +++ b/jvmci/jdk.internal.jvmci.options/src/jdk/internal/jvmci/options/OptionsParser.java Tue Sep 08 17:10:38 2015 +0200 @@ -36,6 +36,11 @@ */ public class OptionsParser { + /** + * Character used to escape a space or a literal % in a JVMCI option value. + */ + private static final char ESCAPE = '%'; + private static final OptionValue PrintFlags = new OptionValue<>(false); /** @@ -54,27 +59,68 @@ } /** - * Finds the index of the next character in {@code s} starting at {@code from} that is a space - * iff {@code spaces == true}. + * Finds the index of the next character in {@code s} starting at {@code from} that is a + * {@linkplain #ESCAPE non-escaped} space iff {@code spaces == true}. */ private static int skip(String s, int from, boolean spaces) { - for (int i = from; i < s.length(); i++) { - if ((s.charAt(i) != ' ') == spaces) { + int len = s.length(); + int i = from; + while (i < len) { + char ch = s.charAt(i); + if (ch == ESCAPE) { + if (i == len - 1) { + throw new InternalError("Escape character " + ESCAPE + " cannot be at end of jvmci.options value: " + s); + } + ch = s.charAt(i + 1); + if (ch != ESCAPE && ch != ' ') { + throw new InternalError("Escape character " + ESCAPE + " must be followed by space or another " + ESCAPE + " character"); + } + if (spaces) { + return i; + } + i++; + } else if (ch == ' ' != spaces) { return i; } + i++; } - return s.length(); + return len; + } + + private static String unescape(String s) { + int esc = s.indexOf(ESCAPE); + if (esc == -1) { + return s; + } + StringBuilder sb = new StringBuilder(s.length()); + int start = 0; + do { + sb.append(s.substring(start, esc)); + char escaped = s.charAt(esc + 1); + if (escaped == ' ') { + sb.append(' '); + } else { + assert escaped == ESCAPE; + sb.append(ESCAPE); + } + start = esc + 2; + esc = s.indexOf(ESCAPE, start); + } while (esc != -1); + if (start < s.length()) { + sb.append(s.substring(start)); + } + return sb.toString(); } /** * Parses the options in {@code /lib/jvmci/options} if {@code parseOptionsFile == true} and - * the file exists followed by the space separated JVMCI options in {@code options} if - * {@code options != null}. + * the file exists followed by the {@linkplain #ESCAPE non-escaped} space separated JVMCI + * options in {@code options} if {@code options != null}. * * Called from VM. This method has an object return type to allow it to be called with a VM * utility function used to call other static initialization methods. * - * @param options space separated set of JVMCI options to parse + * @param options {@linkplain #ESCAPE non-escaped} space separated set of JVMCI options to parse * @param parseOptionsFile specifies whether to look for and parse * {@code /lib/jvmci.options} */ @@ -107,7 +153,7 @@ int index = skip(options, 0, true); while (index < options.length()) { int end = skip(options, index, false); - String option = options.substring(index, end); + String option = unescape(options.substring(index, end)); parseOption(option, null, odp); index = skip(options, end, true); } diff -r df053711614b -r bab91f9ae795 mx.jvmci/mx_jvmci.py --- a/mx.jvmci/mx_jvmci.py Tue Sep 08 14:13:38 2015 +0200 +++ b/mx.jvmci/mx_jvmci.py Tue Sep 08 17:10:38 2015 +0200 @@ -1756,9 +1756,9 @@ existingJvmciOptionsProperty = None for a in args: if a.startswith('-G:'): - jvmciArg = a[len('-G:'):] - assert ' ' not in jvmciArg, 'space not supported in JVMCI arg: ' + a - jvmciArgs.append(a[len('-G:'):]) + # Escape space with % and % with %% + jvmciArg = a[len('-G:'):].replace('%', '%%').replace(' ', '% ') + jvmciArgs.append(jvmciArg) else: if a.startswith('-Djvmci.options=') or a == '-Djvmci.options': existingJvmciOptionsProperty = a