8146096: [TEST BUG] compiler/loopopts/UseCountedLoopSafepoints.java Timeouts
Reviewed-by: kvn
--- a/hotspot/test/compiler/loopopts/UseCountedLoopSafepoints.java Thu Sep 01 21:12:07 2016 +0300
+++ b/hotspot/test/compiler/loopopts/UseCountedLoopSafepoints.java Thu Sep 01 21:13:20 2016 +0300
@@ -22,51 +22,32 @@
*
*/
-/**
- * @test
- * @bug 6869327
- * @summary Test that C2 flag UseCountedLoopSafepoints ensures a safepoint is kept in a CountedLoop
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @ignore 8146096
- * @run driver compiler.loopopts.UseCountedLoopSafepoints
- */
-
package compiler.loopopts;
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
-import java.util.concurrent.atomic.AtomicLong;
+import java.lang.reflect.Method;
+import sun.hotspot.WhiteBox;
+import jdk.test.lib.Asserts;
+import compiler.whitebox.CompilerWhiteBoxTest;
public class UseCountedLoopSafepoints {
- private static final AtomicLong _num = new AtomicLong(0);
+ private static final WhiteBox WB = WhiteBox.getWhiteBox();
+ private static final String METHOD_NAME = "testMethod";
- // Uses the fact that an EnableBiasedLocking vmop will be started
- // after 500ms, while we are still in the loop. If there is a
- // safepoint in the counted loop, then we will reach safepoint
- // very quickly. Otherwise SafepointTimeout will be hit.
+ private long accum = 0;
+
public static void main (String args[]) throws Exception {
- if (args.length == 1) {
- final int loops = Integer.parseInt(args[0]);
- for (int i = 0; i < loops; i++) {
- _num.addAndGet(1);
- }
- } else {
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
- "-XX:+IgnoreUnrecognizedVMOptions",
- "-XX:-TieredCompilation",
- "-XX:+UseBiasedLocking",
- "-XX:BiasedLockingStartupDelay=500",
- "-XX:+SafepointTimeout",
- "-XX:SafepointTimeoutDelay=2000",
- "-XX:+UseCountedLoopSafepoints",
- UseCountedLoopSafepoints.class.getName(),
- "2000000000"
- );
- OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldNotContain("Timeout detected");
- output.shouldHaveExitValue(0);
+ new UseCountedLoopSafepoints().testMethod();
+ Method m = UseCountedLoopSafepoints.class.getDeclaredMethod(METHOD_NAME);
+ String directive = "[{ match: \"" + UseCountedLoopSafepoints.class.getName().replace('.', '/')
+ + "." + METHOD_NAME + "\", " + "BackgroundCompilation: false }]";
+ Asserts.assertTrue(WB.addCompilerDirective(directive) == 1, "Can't add compiler directive");
+ Asserts.assertTrue(WB.enqueueMethodForCompilation(m,
+ CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION), "Can't enqueue method");
+ }
+
+ private void testMethod() {
+ for (int i = 0; i < 100; i++) {
+ accum += accum << 5 + accum >> 4 - accum >>> 5;
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/loopopts/UseCountedLoopSafepointsTest.java Thu Sep 01 21:13:20 2016 +0300
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6869327
+ * @summary Test that C2 flag UseCountedLoopSafepoints ensures a safepoint is kept in a CountedLoop
+ * @library /test/lib /
+ * @requires vm.compMode != "Xint" & vm.flavor == "server" & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4)
+ * @modules java.base/jdk.internal.misc
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run driver compiler.loopopts.UseCountedLoopSafepointsTest
+ */
+
+package compiler.loopopts;
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import jdk.test.lib.Asserts;
+
+/* Idea of this test is to check if ideal graph has CountedLoopEnd->SafePoint edge in case
+ of UseCountedLoopSafepoint enabled and has no such edge in case it's disabled. Restricting
+ compilation to testMethod only will leave only one counted loop (the one in testedMethod) */
+public class UseCountedLoopSafepointsTest {
+
+ public static void main (String args[]) {
+ check(true); // check ideal graph with UseCountedLoopSafepoint enabled
+ check(false); // ... and disabled
+ }
+
+ private static void check(boolean enabled) {
+ OutputAnalyzer oa;
+ try {
+ oa = ProcessTools.executeTestJvm("-XX:+UnlockDiagnosticVMOptions", "-Xbootclasspath/a:.",
+ "-XX:" + (enabled ? "+" : "-") + "UseCountedLoopSafepoints", "-XX:+WhiteBoxAPI",
+ "-XX:-Inline", "-Xbatch", "-XX:+PrintIdeal", "-XX:LoopUnrollLimit=0",
+ "-XX:CompileOnly=" + UseCountedLoopSafepoints.class.getName() + "::testMethod",
+ UseCountedLoopSafepoints.class.getName());
+ } catch (Exception e) {
+ throw new Error("Exception launching child for case enabled=" + enabled + " : " + e, e);
+ }
+ oa.shouldHaveExitValue(0);
+ // parse output in seach of SafePoint and CountedLoopEnd nodes
+ List<Node> safePoints = new ArrayList<>();
+ List<Node> loopEnds = new ArrayList<>();
+ for (String line : oa.getOutput().split("\\n")) {
+ int separatorIndex = line.indexOf("\t===");
+ if (separatorIndex > -1) {
+ String header = line.substring(0, separatorIndex);
+ if (header.endsWith("\tSafePoint")) {
+ safePoints.add(new Node("SafePoint", line));
+ } else if (header.endsWith("\tCountedLoopEnd")) {
+ loopEnds.add(new Node("CountedLoopEnd", line));
+ }
+ }
+ }
+ // now, find CountedLoopEnd -> SafePoint edge
+ boolean found = false;
+ for (Node loopEnd : loopEnds) {
+ found |= loopEnd.to.stream()
+ .filter(id -> nodeListHasElementWithId(safePoints, id))
+ .findAny()
+ .isPresent();
+ }
+ Asserts.assertEQ(enabled, found, "Safepoint " + (found ? "" : "not ") + "found");
+ }
+
+ private static boolean nodeListHasElementWithId(List<Node> list, int id) {
+ return list.stream()
+ .filter(node -> node.id == id)
+ .findAny()
+ .isPresent();
+ }
+
+ private static class Node {
+ public final int id;
+ public final List<Integer> from;
+ public final List<Integer> to;
+
+ public Node(String name, String str) {
+ List<Integer> tmpFrom = new ArrayList<>();
+ List<Integer> tmpTo = new ArrayList<>();
+ // parse string like: " $id $name === $to1 $to2 ... [[ $from1 $from2 ... ]] $anything"
+ // example: 318 SafePoint === 317 1 304 1 1 10 308 [[ 97 74 ]] ...
+ id = Integer.parseInt(str.substring(1, str.indexOf(name)).trim());
+ Arrays.stream(str.substring(str.indexOf("===") + 4, str.indexOf("[[")).trim().split("\\s+"))
+ .map(Integer::parseInt)
+ .forEach(tmpTo::add);
+ Arrays.stream(str.substring(str.indexOf("[[") + 3, str.indexOf("]]")).trim().split("\\s+"))
+ .map(Integer::parseInt)
+ .forEach(tmpFrom::add);
+ this.from = Collections.unmodifiableList(tmpFrom);
+ this.to = Collections.unmodifiableList(tmpTo);
+ }
+ }
+}