--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/State.java Wed Oct 21 21:59:54 2015 +0200
@@ -0,0 +1,371 @@
+/*
+ * 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.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import jdk.test.lib.Asserts;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * Represents method compilation state
+ */
+public class State {
+ // Each of the two-elements array contains a state for each compiler
+ private Optional<Boolean>[] compile =
+ (Optional<Boolean>[]) new Optional[Scenario.Compiler.values().length];
+ private Optional<Boolean>[] forceInline =
+ (Optional<Boolean>[]) new Optional[Scenario.Compiler.values().length];
+ private Optional<Boolean>[] dontInline =
+ (Optional<Boolean>[]) new Optional[Scenario.Compiler.values().length];
+ private Optional<Boolean> printAssembly = Optional.empty();
+ private Optional<Boolean> printInline = Optional.empty();
+ private Optional<Boolean> log = Optional.empty();
+
+ public State() {
+ Arrays.fill(compile, Optional.empty());
+ Arrays.fill(forceInline, Optional.empty());
+ Arrays.fill(dontInline, Optional.empty());
+ }
+
+ /**
+ * Creates state from the string
+ *
+ * @param strings array of strings that represent the state
+ * @return State instance
+ * @see #toString()
+ */
+ public static State fromString(String[] strings) {
+ Asserts.assertNotNull(strings, "Non null array is required");
+ Asserts.assertNE(strings.length, 0, "Non empty array is required");
+ State st = new State();
+ for (String string : strings) {
+ int i = string.indexOf(' ');
+ String command = string.substring(0, i);
+ String values = string.substring(i + 1); // skip space symbol
+ switch (command) {
+ case "compile" :
+ parseArray(st.compile, values);
+ break;
+ case "force_inline" :
+ parseArray(st.forceInline, values);
+ break;
+ case "dont_inline" :
+ parseArray(st.dontInline, values);
+ break;
+ case "log" :
+ st.log = parseElement(values);
+ break;
+ case "print_assembly" :
+ st.printAssembly = parseElement(values);
+ break;
+ case "print_inline" :
+ st.printInline = parseElement(values);
+ break;
+ default:
+ throw new Error("TESTBUG: ");
+ }
+ }
+ return st;
+ }
+
+ private static void parseArray(Optional<Boolean>[] array, String str) {
+ Asserts.assertNotNull(str);
+ int beginBrace = 0;
+ int endBrace = str.length() - 1;
+ if (str.charAt(beginBrace) != '[' || str.charAt(endBrace) != ']') {
+ throw new Error("TESTBUG: not an array type: " + str);
+ }
+ // Get all elements divided with comma as an array
+ String[] strValues = str.substring(beginBrace + 1, endBrace)
+ .split(", ");
+ Asserts.assertEQ(strValues.length, array.length, "Different amount of "
+ + "elements in the string");
+ for (int i = 0; i < strValues.length; i++) {
+ array[i] = parseElement(strValues[i]);
+ }
+ }
+
+ private static Optional<Boolean> parseElement(String str) {
+ Asserts.assertNotNull(str);
+ Asserts.assertTrue(str.startsWith(Optional.class.getSimpleName()),
+ "String is not of type Optional: " + str);
+ if ("Optional.empty".equals(str)) {
+ return Optional.empty();
+ }
+ int begin = str.indexOf('[');
+ Asserts.assertNE(begin, -1, "TEST BUG: Wrong Optional string");
+ int end = str.indexOf(']');
+ Asserts.assertEQ(end, str.length() - 1);
+ boolean b = Boolean.parseBoolean(str.substring(begin + 1, end));
+ return Optional.of(b);
+ }
+
+ /**
+ * Gets string representation of this state
+ */
+ @Override
+ public String toString() {
+ return "compile " + Arrays.toString(compile)
+ + "\nforce_inline " + Arrays.toString(forceInline)
+ + "\ndont_inline " + Arrays.toString(dontInline)
+ + "\nlog " + log
+ + "\nprint_assembly " + printAssembly
+ + "\nprint_inline " + printInline;
+ }
+
+ public boolean isC1Compilable() {
+ return compile[Scenario.Compiler.C1.ordinal()].orElse(true);
+ }
+
+ public boolean isC2Compilable() {
+ return compile[Scenario.Compiler.C2.ordinal()].orElse(true);
+ }
+
+ public boolean isCompilable() {
+ return isC1Compilable() && isC2Compilable();
+ }
+
+ public void setC1Compilable(boolean value) {
+ setCompilable(Scenario.Compiler.C1.ordinal(), value);
+ }
+
+ public void setC2Compilable(boolean value) {
+ setCompilable(Scenario.Compiler.C2.ordinal(), value);
+ }
+
+ public void setCompilable(Scenario.Compiler compiler, boolean value) {
+ if (compiler == null) {
+ setC1Compilable(value);
+ setC2Compilable(value);
+ return;
+ }
+ switch (compiler) {
+ case C1:
+ setC1Compilable(value);
+ break;
+ case C2:
+ setC2Compilable(value);
+ break;
+ default:
+ throw new Error("Unknown compiler");
+ }
+ }
+
+ private void setCompilable(int level, boolean value) {
+ check(level);
+ compile[level] = Optional.of(value);
+ if (!value) {
+ setDontInline(level);
+ }
+ }
+
+ public boolean isC1Inlinable() {
+ return ! dontInline[Scenario.Compiler.C1.ordinal()].orElse(false);
+ }
+
+ public boolean isC2Inlinable() {
+ return ! dontInline[Scenario.Compiler.C2.ordinal()].orElse(false);
+ }
+
+ public boolean isInlinable() {
+ return isC1Inlinable() && isC2Inlinable();
+ }
+
+ private void setDontInline(int level) {
+ check(level);
+ dontInline[level] = Optional.of(true);
+ forceInline[level] = Optional.of(false);
+ }
+
+ private void setForceInline(int level) {
+ check(level);
+ dontInline[level] = Optional.of(false);
+ forceInline[level] = Optional.of(true);
+ }
+
+ public boolean isC1ForceInline() {
+ return forceInline[Scenario.Compiler.C1.ordinal()].orElse(false);
+ }
+
+ public boolean isC2ForceInline() {
+ return forceInline[Scenario.Compiler.C2.ordinal()].orElse(false);
+ }
+
+ public boolean isForceInline() {
+ return isC1ForceInline() && isC2ForceInline();
+ }
+
+ public void setC1Inline(boolean value) {
+ if (value && isC1Compilable()) {
+ setForceInline(Scenario.Compiler.C1.ordinal());
+ } else {
+ setDontInline(Scenario.Compiler.C1.ordinal());
+ }
+ }
+
+ public void setC2Inline(boolean value) {
+ if (value && isC2Compilable()) {
+ setForceInline(Scenario.Compiler.C2.ordinal());
+ } else {
+ setDontInline(Scenario.Compiler.C1.ordinal());
+ }
+ }
+
+ public void setInline(Scenario.Compiler compiler, boolean value) {
+ if (compiler == null) {
+ setC1Inline(value);
+ setC2Inline(value);
+ return;
+ }
+ switch (compiler) {
+ case C1:
+ setC1Inline(value);
+ break;
+ case C2:
+ setC2Inline(value);
+ break;
+ default:
+ throw new Error("Unknown compiler");
+ }
+ }
+
+ public boolean isPrintAssembly() {
+ return printAssembly.orElse(false);
+ }
+
+ public void setPrintAssembly(boolean value) {
+ printAssembly = Optional.of(value);
+ }
+
+ public boolean isPrintInline() {
+ return printInline.orElse(false);
+ }
+
+ public void setPrintInline(boolean value) {
+ printInline = Optional.of(value);
+ }
+
+ public boolean isLog() {
+ return log.orElse(false);
+ }
+
+ public void setLog(boolean log) {
+ this.log = Optional.of(log);
+ }
+
+ private void check(int level) {
+ if (level < 0 || level > compile.length) {
+ throw new IllegalArgumentException("TESTBUG: Wrong level " + level);
+ }
+ }
+
+ /**
+ * Applies given command to the state.
+ *
+ * @param compileCommand command to be applied
+ */
+ public void apply(CompileCommand compileCommand) {
+ switch (compileCommand.command) {
+ case COMPILEONLY:
+ setCompilable(compileCommand.compiler, true);
+ break;
+ case EXCLUDE:
+ setCompilable(compileCommand.compiler, false);
+ break;
+ case INLINE:
+ setInline(compileCommand.compiler, true);
+ break;
+ case DONTINLINE:
+ setInline(compileCommand.compiler, false);
+ break;
+ case LOG:
+ setLog(true);
+ break;
+ case PRINT:
+ setPrintAssembly(true);
+ break;
+ case QUIET:
+ case NONEXISTENT:
+ // doesn't apply the state
+ break;
+ default:
+ throw new Error("Wrong command: " + compileCommand.command);
+ }
+ }
+
+ /**
+ * Merges two given states with different priority
+ *
+ * @param low state with lower merge priority
+ * @param high state with higher merge priority
+ */
+ public static State merge(State low, State high) {
+ if (high == null) {
+ if (low == null) {
+ return new State();
+ }
+ return low;
+ }
+ if (low == null) {
+ return high;
+ }
+ State result = new State();
+ // Compilable
+ result.compile[Scenario.Compiler.C1.ordinal()] = mergeOptional(
+ high.compile[Scenario.Compiler.C1.ordinal()],
+ low.compile[Scenario.Compiler.C1.ordinal()]);
+ result.compile[Scenario.Compiler.C2.ordinal()] = mergeOptional(
+ high.compile[Scenario.Compiler.C2.ordinal()],
+ low.compile[Scenario.Compiler.C2.ordinal()]);
+ // Force inline
+ result.forceInline[Scenario.Compiler.C1.ordinal()] = mergeOptional(
+ high.forceInline[Scenario.Compiler.C1.ordinal()],
+ low.forceInline[Scenario.Compiler.C1.ordinal()]);
+ result.forceInline[Scenario.Compiler.C2.ordinal()] = mergeOptional(
+ high.forceInline[Scenario.Compiler.C2.ordinal()],
+ low.forceInline[Scenario.Compiler.C2.ordinal()]);
+ // Don't inline
+ result.dontInline[Scenario.Compiler.C1.ordinal()] = mergeOptional(
+ high.dontInline[Scenario.Compiler.C1.ordinal()],
+ low.dontInline[Scenario.Compiler.C1.ordinal()]);
+ result.dontInline[Scenario.Compiler.C2.ordinal()] = mergeOptional(
+ high.dontInline[Scenario.Compiler.C2.ordinal()],
+ low.dontInline[Scenario.Compiler.C2.ordinal()]);
+ // set PrintAssembly
+ result.printAssembly = mergeOptional(high.printAssembly,
+ low.printAssembly);
+ // set PrintInline
+ result.printInline = mergeOptional(high.printInline, low.printInline);
+ // set LogCompilation
+ result.log = mergeOptional(high.log, low.log);
+ return result;
+ }
+
+ private static <T> Optional<T> mergeOptional(Optional<T> high,
+ Optional<T> low) {
+ T val = high.orElse(low.orElse(null));
+ return Optional.ofNullable(val);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/compilercontrol/share/scenario/StateBuilder.java Wed Oct 21 21:59:54 2015 +0200
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+package compiler.compilercontrol.share.scenario;
+
+import java.lang.reflect.Executable;
+import java.util.List;
+import java.util.Map;
+
+public interface StateBuilder<T extends CompileCommand> {
+ /**
+ * Adds CompileCommand to builder
+ *
+ * @param command command used to build states
+ */
+ void add(T command);
+
+ /**
+ * Gets final states of methods
+ *
+ * @return a map with pairs of executables and their states
+ */
+ Map<Executable, State> getStates();
+
+ /**
+ * Gets list of VM options that will change states of methods
+ *
+ * @return a list of VM options
+ */
+ List<String> getOptions();
+
+ /**
+ * Gets list of passed commands {@link CompileCommand}
+ *
+ * @return a list of compile commands
+ */
+ List<T> getCompileCommands();
+
+ /**
+ * Shows that this state builder created a valid input for the test vm
+ *
+ * @return true if this is a valid input
+ */
+ boolean isValid();
+}
--- a/hotspot/test/testlibrary/jdk/test/lib/ProcessTools.java Wed Oct 21 18:22:47 2015 +0300
+++ b/hotspot/test/testlibrary/jdk/test/lib/ProcessTools.java Wed Oct 21 21:59:54 2015 +0200
@@ -39,7 +39,7 @@
/**
* Pumps stdout and stderr from running the process into a String.
*
- * @param processHandler ProcessHandler to run.
+ * @param processBuilder ProcessBuilder to run.
* @return Output from process.
* @throws IOException If an I/O error occurs.
*/
@@ -109,6 +109,17 @@
}
/**
+ * Gets the array of strings containing input arguments passed to the VM
+ *
+ * @return arguments
+ */
+ public static String[] getVmInputArgs() {
+ RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
+ List<String> args = runtime.getInputArguments();
+ return args.toArray(new String[args.size()]);
+ }
+
+ /**
* Get platform specific VM arguments (e.g. -d64 on 64bit Solaris)
*
* @return String[] with platform specific arguments, empty if there are none
@@ -172,6 +183,26 @@
return executeProcess(pb);
}
+ /**
+ * Executes a test jvm process, waits for it to finish and returns the process output.
+ * The default jvm options from the test's run command, jtreg, test.vm.opts and test.java.opts, are added.
+ * The java from the test.jdk is used to execute the command.
+ *
+ * The command line will be like:
+ * {test.jdk}/bin/java {test.fromRun.opts} {test.vm.opts} {test.java.opts} cmds
+ *
+ * @param cmds User specifed arguments.
+ * @return The output from the process.
+ */
+ public static OutputAnalyzer executeTestJvmAllArgs(String... cmds) throws Throwable {
+ List<String> argsList = new ArrayList<>();
+ String[] testArgs = getVmInputArgs();
+ Collections.addAll(argsList, testArgs);
+ Collections.addAll(argsList, Utils.addTestJavaOpts(cmds));
+ ProcessBuilder pb = createJavaProcessBuilder(argsList.toArray(new String[argsList.size()]));
+ return executeProcess(pb);
+ }
+
/**
* Executes a process, waits for it to finish and returns the process output.
* The process will have exited before this method returns.
--- a/hotspot/test/testlibrary/jdk/test/lib/Utils.java Wed Oct 21 18:22:47 2015 +0300
+++ b/hotspot/test/testlibrary/jdk/test/lib/Utils.java Wed Oct 21 21:59:54 2015 +0200
@@ -412,6 +412,23 @@
}
/**
+ * Returns random element of non empty array
+ *
+ * @param <T> a type of array element
+ * @param array array of elements
+ * @return random element of array
+ * @throws IllegalArgumentException if array is empty
+ */
+ public static <T> T getRandomElement(T[] array)
+ throws IllegalArgumentException {
+ if (array == null || array.length == 0) {
+ throw new IllegalArgumentException("Empty or null array");
+ }
+ Random random = getRandomInstance();
+ return array[random.nextInt(array.length)];
+ }
+
+ /**
* Wait for condition to be true
*
* @param condition, a condition to wait for