mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-04 12:08:36 +00:00
Co-authored-by: Stuart Monteith <smonteith@openjdk.org> Co-authored-by: Andrew Haley <aph@openjdk.org> Reviewed-by: aph, eastigeevich
225 lines
8.4 KiB
Java
225 lines
8.4 KiB
Java
/*
|
|
* Copyright Amazon.com Inc. 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 id=TestOnSpinWaitAArch64
|
|
* @summary Checks that java.lang.Thread.onSpinWait is intrinsified with instructions specified with '-XX:OnSpinWaitInst' and '-XX:OnSpinWaitInstCount'
|
|
* @bug 8186670
|
|
* @library /test/lib
|
|
*
|
|
* @requires vm.flagless
|
|
* @requires os.arch=="aarch64"
|
|
* @requires vm.debug
|
|
*
|
|
* @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 nop 7
|
|
* @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 isb 3
|
|
* @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 yield 1
|
|
* @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 sb 1
|
|
* @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 nop 7
|
|
* @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 isb 3
|
|
* @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 yield 1
|
|
* @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 sb 1
|
|
*/
|
|
|
|
/**
|
|
* @test id=TestOnSpinWaitAArch64-wfet
|
|
* @summary Checks that java.lang.Thread.onSpinWait is intrinsified when -XX:OnSpinWaitInst=wfet is used
|
|
* @bug 8366441
|
|
* @library /test/lib
|
|
*
|
|
* @requires vm.flagless
|
|
* @requires (os.arch=="aarch64" & os.family=="linux")
|
|
* @requires vm.debug
|
|
*
|
|
* @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 wfet 1 1
|
|
* @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 wfet 1 1000
|
|
* @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 wfet 1 1
|
|
* @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 wfet 1 1000
|
|
*/
|
|
|
|
package compiler.onSpinWait;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.ArrayList;
|
|
import java.util.Iterator;
|
|
import java.util.ListIterator;
|
|
import jdk.test.lib.process.OutputAnalyzer;
|
|
import jdk.test.lib.process.ProcessTools;
|
|
|
|
public class TestOnSpinWaitAArch64 {
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
String compiler = args[0];
|
|
String spinWaitInst = args[1];
|
|
String spinWaitInstCount = args[2];
|
|
String spinWaitDelay = (args.length >= 4 ? args[3] : "");
|
|
ArrayList<String> command = new ArrayList<String>();
|
|
command.add("-XX:+IgnoreUnrecognizedVMOptions");
|
|
command.add("-showversion");
|
|
command.add("-XX:-BackgroundCompilation");
|
|
command.add("-XX:+UnlockDiagnosticVMOptions");
|
|
if (compiler.equals("c2")) {
|
|
command.add("-XX:-TieredCompilation");
|
|
} else if (compiler.equals("c1")) {
|
|
command.add("-XX:+TieredCompilation");
|
|
command.add("-XX:TieredStopAtLevel=1");
|
|
} else {
|
|
throw new RuntimeException("Unknown compiler: " + compiler);
|
|
}
|
|
command.add("-Xbatch");
|
|
if ("wfet".equals(spinWaitInst)) {
|
|
command.add("-XX:+UnlockExperimentalVMOptions");
|
|
}
|
|
command.add("-XX:OnSpinWaitInst=" + spinWaitInst);
|
|
command.add("-XX:OnSpinWaitInstCount=" + spinWaitInstCount);
|
|
if (!spinWaitDelay.isEmpty()) {
|
|
command.add("-XX:OnSpinWaitDelay=" + spinWaitDelay);
|
|
}
|
|
command.add("-XX:CompileCommand=compileonly," + Launcher.class.getName() + "::" + "test");
|
|
command.add("-XX:CompileCommand=print," + Launcher.class.getName() + "::" + "test");
|
|
command.add(Launcher.class.getName());
|
|
|
|
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(command);
|
|
|
|
OutputAnalyzer analyzer = new OutputAnalyzer(pb.start());
|
|
|
|
if ("sb".equals(spinWaitInst) && analyzer.contains("CPU does not support SB")) {
|
|
System.out.println("Skipping the test. The current CPU does not support SB instruction.");
|
|
return;
|
|
}
|
|
|
|
if ("wfet".equals(spinWaitInst) &&
|
|
(analyzer.contains("CPU does not support the SB instruction") ||
|
|
analyzer.contains("CPU does not support the FEAT_ECV") ||
|
|
analyzer.contains("CPU does not support the WFET instruction"))) {
|
|
System.out.println("Skipping the test. The CPU does not support SB or WFET instruction, or FEAT_ECV.");
|
|
return;
|
|
}
|
|
|
|
analyzer.shouldHaveExitValue(0);
|
|
|
|
System.out.println(analyzer.getOutput());
|
|
|
|
checkOutput(analyzer, spinWaitInst, Integer.parseInt(spinWaitInstCount));
|
|
}
|
|
|
|
private static String getSpinWaitInstHex(String spinWaitInst) {
|
|
if ("nop".equals(spinWaitInst)) {
|
|
return "1f2003d5";
|
|
} else if ("isb".equals(spinWaitInst)) {
|
|
return "df3f03d5";
|
|
} else if ("yield".equals(spinWaitInst)) {
|
|
return "3f2003d5";
|
|
} else if ("sb".equals(spinWaitInst)) {
|
|
return "ff3003d5";
|
|
} else if ("wfet".equals(spinWaitInst)) {
|
|
// This assumes rscratch1 is r8.
|
|
return "081003d5";
|
|
} else {
|
|
throw new RuntimeException("Unknown spin wait instruction: " + spinWaitInst);
|
|
}
|
|
}
|
|
|
|
// The expected output for a spin wait with three NOPs
|
|
// if the hsdis library is available:
|
|
//
|
|
// ;; spin_wait {
|
|
// 0x0000000111dfa58c: nop
|
|
// 0x0000000111dfa590: nop
|
|
// 0x0000000111dfa594: nop
|
|
// ;; }
|
|
//
|
|
private static void checkOutput(OutputAnalyzer output, final String spinWaitInst, final int expectedCount) {
|
|
Iterator<String> iter = output.asLines().listIterator();
|
|
|
|
// 1. Check whether printed instructions are disassembled
|
|
boolean isDisassembled = false;
|
|
while (iter.hasNext()) {
|
|
String line = iter.next();
|
|
if (line.contains("[Disassembly]")) {
|
|
isDisassembled = true;
|
|
break;
|
|
}
|
|
if (line.contains("[MachCode]")) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 2. Look for the block comment
|
|
boolean foundHead = false;
|
|
while (iter.hasNext()) {
|
|
String line = iter.next().trim();
|
|
if (line.contains(";; spin_wait {")) {
|
|
foundHead = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!foundHead) {
|
|
throw new RuntimeException("Block comment not found");
|
|
}
|
|
|
|
// 3. Count spin wait instructions
|
|
final String expectedInst = isDisassembled ? spinWaitInst : getSpinWaitInstHex(spinWaitInst);
|
|
int foundCount = 0;
|
|
while (iter.hasNext()) {
|
|
String line = iter.next().trim();
|
|
if (line.startsWith(";; }")) {
|
|
break;
|
|
}
|
|
if (!line.startsWith("0x")) {
|
|
continue;
|
|
}
|
|
int pos = line.indexOf(':');
|
|
if (pos == -1 || pos == line.length() - 1) {
|
|
continue;
|
|
}
|
|
line = line.substring(pos + 1).replaceAll("\\s", "");
|
|
if (line.startsWith(";")) {
|
|
continue;
|
|
}
|
|
// When code is disassembled, we have one instruction per line.
|
|
// Otherwise, there can be multiple hex instructions separated by '|'.
|
|
foundCount += (int)Arrays.stream(line.split("\\|"))
|
|
.filter(i -> i.startsWith(expectedInst))
|
|
.count();
|
|
}
|
|
|
|
if (foundCount != expectedCount) {
|
|
throw new RuntimeException("Expected " + expectedCount + " " + spinWaitInst + " instructions. Found: " + foundCount);
|
|
}
|
|
}
|
|
|
|
static class Launcher {
|
|
public static void main(final String[] args) throws Exception {
|
|
int end = 20_000;
|
|
|
|
for (int i=0; i < end; i++) {
|
|
test();
|
|
}
|
|
}
|
|
static void test() {
|
|
java.lang.Thread.onSpinWait();
|
|
}
|
|
}
|
|
}
|