8268963: [IR Framework] Some default regexes matching on PrintOptoAssembly in IRNode.java do not work on all platforms

Reviewed-by: kvn, thartmann
This commit is contained in:
Christian Hagedorn 2021-07-30 12:28:57 +00:00
parent b59418f47d
commit 9856ace828
7 changed files with 305 additions and 138 deletions

View File

@ -24,12 +24,12 @@
package compiler.lib.ir_framework;
import compiler.lib.ir_framework.driver.IRMatcher;
import compiler.lib.ir_framework.shared.TestFormat;
import compiler.lib.ir_framework.shared.TestFormatException;
import compiler.lib.ir_framework.shared.*;
import jdk.test.lib.Platform;
import sun.hotspot.WhiteBox;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
/**
* This class provides default regex strings that can be used in {@link IR @IR} annotations to specify IR constraints.
@ -48,15 +48,20 @@ public class IRNode {
private static final String START = "(\\d+(\\s){2}(";
private static final String MID = ".*)+(\\s){2}===.*";
private static final String END = ")";
private static final String COMPOSITE_PREFIX = "#PRE#"; // Prefix for regexes that require an additional user-defined string.
private static final String IS_REPLACED = "#IS_REPLACED#"; // Is replaced by an additional user-defined string.
private static final String STORE_OF_CLASS_POSTFIX = "(:|\\+)\\S* \\*" + END;
private static final String LOAD_OF_CLASS_POSTFIX = "(:|\\+)\\S* \\*" + END;
public static final String ALLOC = "(.*precise klass .*\\R(.*(movl|xorl|nop|spill).*\\R)*.*call,static wrapper for: _new_instance_Java" + END;
public static final String ALLOC_OF = "(.*precise klass .*";
public static final String ALLOC_ARRAY = "(.*precise klass \\[L.*\\R(.*(movl|xorl|nop|spill).*\\R)*.*call,static wrapper for: _new_array_Java" + END;
public static final String ALLOC_ARRAY_OF = "(.*precise klass \\[L.*";
public static final String ALLOC = "(.*precise klass .*\\R((.*(?i:mov|xorl|nop|spill).*|\\s*|.*LGHI.*)\\R)*.*(?i:call,static).*wrapper for: _new_instance_Java" + END;
public static final String ALLOC_OF = COMPOSITE_PREFIX + "(.*precise klass .*" + IS_REPLACED + ":.*\\R((.*(?i:mov|xorl|nop|spill).*|\\s*|.*LGHI.*)\\R)*.*(?i:call,static).*wrapper for: _new_instance_Java" + END;
public static final String ALLOC_ARRAY = "(.*precise klass \\[L.*\\R((.*(?i:mov|xor|nop|spill).*|\\s*|.*LGHI.*)\\R)*.*(?i:call,static).*wrapper for: _new_array_Java" + END;
public static final String ALLOC_ARRAY_OF = COMPOSITE_PREFIX + "(.*precise klass \\[L.*" + IS_REPLACED + ";:.*\\R((.*(?i:mov|xorl|nop|spill).*|\\s*|.*LGHI.*)\\R)*.*(?i:call,static).*wrapper for: _new_array_Java" + END;
public static final String CHECKCAST_ARRAY = "(cmp.*precise klass \\[.*;:" + END;
public static final String CHECKCAST_ARRAY_OF = "(cmp.*precise klass \\[.*";
public static final String CHECKCAST_ARRAYCOPY = "(.*call_leaf_nofp,runtime checkcast_arraycopy.*" + END;
public static final String CHECKCAST_ARRAY = "(((?i:cmp|CLFI|CLR).*precise klass \\[.*;:|.*(?i:mov|or).*precise klass \\[.*;:.*\\R.*(cmp|CMP|CLR))" + END;
public static final String CHECKCAST_ARRAY_OF = COMPOSITE_PREFIX + "(((?i:cmp|CLFI|CLR).*precise klass \\[.*" + IS_REPLACED + ";:|.*(?i:mov|or).*precise klass \\[.*" + IS_REPLACED + ";:.*\\R.*(cmp|CMP|CLR))" + END;
// Does not work on s390 (a rule containing this regex will be skipped on s390).
public static final String CHECKCAST_ARRAYCOPY = "(.*((?i:call_leaf_nofp,runtime)|CALL,\\s?runtime leaf nofp|BCTRL.*.leaf call).*checkcast_arraycopy.*" + END;
public static final String FIELD_ACCESS = "(.*Field: *" + END;
@ -69,16 +74,16 @@ public class IRNode {
public static final String STORE_D = START + "StoreD" + MID + END;
public static final String STORE_P = START + "StoreP" + MID + END;
public static final String STORE_N = START + "StoreN" + MID + END;
public static final String STORE_OF_CLASS = START + "Store(B|C|S|I|L|F|D|P|N)" + MID + "@\\S*";
public static final String STORE_B_OF_CLASS = START + "StoreB" + MID + "@\\S*";
public static final String STORE_C_OF_CLASS = START + "StoreC" + MID + "@\\S*";
public static final String STORE_I_OF_CLASS = START + "StoreI" + MID + "@\\S*";
public static final String STORE_L_OF_CLASS = START + "StoreL" + MID + "@\\S*";
public static final String STORE_F_OF_CLASS = START + "StoreF" + MID + "@\\S*";
public static final String STORE_D_OF_CLASS = START + "StoreD" + MID + "@\\S*";
public static final String STORE_P_OF_CLASS = START + "StoreP" + MID + "@\\S*";
public static final String STORE_N_OF_CLASS = START + "StoreN" + MID + "@\\S*";
public static final String STORE_OF_FIELD = START + "Store(B|C|S|I|L|F|D|P|N)" + MID + "@.*name=";
public static final String STORE_OF_CLASS = COMPOSITE_PREFIX + START + "Store(B|C|S|I|L|F|D|P|N)" + MID + "@\\S*" + IS_REPLACED + STORE_OF_CLASS_POSTFIX;
public static final String STORE_B_OF_CLASS = COMPOSITE_PREFIX + START + "StoreB" + MID + "@\\S*" + IS_REPLACED + STORE_OF_CLASS_POSTFIX;
public static final String STORE_C_OF_CLASS = COMPOSITE_PREFIX + START + "StoreC" + MID + "@\\S*" + IS_REPLACED + STORE_OF_CLASS_POSTFIX;
public static final String STORE_I_OF_CLASS = COMPOSITE_PREFIX + START + "StoreI" + MID + "@\\S*" + IS_REPLACED + STORE_OF_CLASS_POSTFIX;
public static final String STORE_L_OF_CLASS = COMPOSITE_PREFIX + START + "StoreL" + MID + "@\\S*" + IS_REPLACED + STORE_OF_CLASS_POSTFIX;
public static final String STORE_F_OF_CLASS = COMPOSITE_PREFIX + START + "StoreF" + MID + "@\\S*" + IS_REPLACED + STORE_OF_CLASS_POSTFIX;
public static final String STORE_D_OF_CLASS = COMPOSITE_PREFIX + START + "StoreD" + MID + "@\\S*" + IS_REPLACED + STORE_OF_CLASS_POSTFIX;
public static final String STORE_P_OF_CLASS = COMPOSITE_PREFIX + START + "StoreP" + MID + "@\\S*" + IS_REPLACED + STORE_OF_CLASS_POSTFIX;
public static final String STORE_N_OF_CLASS = COMPOSITE_PREFIX + START + "StoreN" + MID + "@\\S*" + IS_REPLACED + STORE_OF_CLASS_POSTFIX;
public static final String STORE_OF_FIELD = COMPOSITE_PREFIX + START + "Store(B|C|S|I|L|F|D|P|N)" + MID + "@.*name=" + IS_REPLACED + ",.*" + END;
public static final String LOAD = START + "Load(B|UB|S|US|I|L|F|D|P|N)" + MID + END;
public static final String LOAD_B = START + "LoadB" + MID + END;
@ -91,22 +96,22 @@ public class IRNode {
public static final String LOAD_D = START + "LoadD" + MID + END;
public static final String LOAD_P = START + "LoadP" + MID + END;
public static final String LOAD_N = START + "LoadN" + MID + END;
public static final String LOAD_OF_CLASS = START + "Load(B|UB|S|US|I|L|F|D|P|N)" + MID + "@\\S*";
public static final String LOAD_B_OF_CLASS = START + "LoadB" + MID + "@\\S*";
public static final String LOAD_UB_OF_CLASS = START + "LoadUB" + MID + "@\\S*";
public static final String LOAD_S_OF_CLASS = START + "LoadS" + MID + "@\\S*";
public static final String LOAD_US_OF_CLASS = START + "LoadUS" + MID + "@\\S*";
public static final String LOAD_I_OF_CLASS = START + "LoadI" + MID + "@\\S*";
public static final String LOAD_L_OF_CLASS = START + "LoadL" + MID + "@\\S*";
public static final String LOAD_F_OF_CLASS = START + "LoadF" + MID + "@\\S*";
public static final String LOAD_D_OF_CLASS = START + "LoadD" + MID + "@\\S*";
public static final String LOAD_P_OF_CLASS = START + "LoadP" + MID + "@\\S*";
public static final String LOAD_N_OF_CLASS = START + "LoadN" + MID + "@\\S*";
public static final String LOAD_OF_FIELD = START + "Load(B|C|S|I|L|F|D|P|N)" + MID + "@.*name=";
public static final String LOAD_OF_CLASS = COMPOSITE_PREFIX + START + "Load(B|UB|S|US|I|L|F|D|P|N)" + MID + "@\\S*"+ IS_REPLACED + LOAD_OF_CLASS_POSTFIX;
public static final String LOAD_B_OF_CLASS = COMPOSITE_PREFIX + START + "LoadB" + MID + "@\\S*" + IS_REPLACED + LOAD_OF_CLASS_POSTFIX;
public static final String LOAD_UB_OF_CLASS = COMPOSITE_PREFIX + START + "LoadUB" + MID + "@\\S*" + IS_REPLACED + LOAD_OF_CLASS_POSTFIX;
public static final String LOAD_S_OF_CLASS = COMPOSITE_PREFIX + START + "LoadS" + MID + "@\\S*" + IS_REPLACED + LOAD_OF_CLASS_POSTFIX;
public static final String LOAD_US_OF_CLASS = COMPOSITE_PREFIX + START + "LoadUS" + MID + "@\\S*" + IS_REPLACED + LOAD_OF_CLASS_POSTFIX;
public static final String LOAD_I_OF_CLASS = COMPOSITE_PREFIX + START + "LoadI" + MID + "@\\S*" + IS_REPLACED + LOAD_OF_CLASS_POSTFIX;
public static final String LOAD_L_OF_CLASS = COMPOSITE_PREFIX + START + "LoadL" + MID + "@\\S*" + IS_REPLACED + LOAD_OF_CLASS_POSTFIX;
public static final String LOAD_F_OF_CLASS = COMPOSITE_PREFIX + START + "LoadF" + MID + "@\\S*" + IS_REPLACED + LOAD_OF_CLASS_POSTFIX;
public static final String LOAD_D_OF_CLASS = COMPOSITE_PREFIX + START + "LoadD" + MID + "@\\S*" + IS_REPLACED + LOAD_OF_CLASS_POSTFIX;
public static final String LOAD_P_OF_CLASS = COMPOSITE_PREFIX + START + "LoadP" + MID + "@\\S*" + IS_REPLACED + LOAD_OF_CLASS_POSTFIX;
public static final String LOAD_N_OF_CLASS = COMPOSITE_PREFIX + START + "LoadN" + MID + "@\\S*" + IS_REPLACED + LOAD_OF_CLASS_POSTFIX;
public static final String LOAD_OF_FIELD = COMPOSITE_PREFIX + START + "Load(B|C|S|I|L|F|D|P|N)" + MID + "@.*name=" + IS_REPLACED + ",.*" + END;
public static final String LOAD_KLASS = START + "LoadK" + MID + END;
public static final String LOOP = START + "Loop" + MID + "" + END;
public static final String COUNTEDLOOP = START + "CountedLoop\\b" + MID + "" + END;
public static final String LOOP = START + "Loop" + MID + END;
public static final String COUNTEDLOOP = START + "CountedLoop\\b" + MID + END;
public static final String COUNTEDLOOP_MAIN = START + "CountedLoop\\b" + MID + "main" + END;
public static final String CALL = START + "CallStaticJava" + MID + END;
@ -118,20 +123,12 @@ public class IRNode {
public static final String NULL_ASSERT_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*null_assert" + END;
public static final String RANGE_CHECK_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*range_check" + END;
public static final String UNHANDLED_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*unhandled" + END;
// Does not work for VM builds without JVMCI like x86_32 (a rule containing this regex will be skipped without having JVMCI built).
public static final String INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*intrinsic_or_type_checked_inlining" + END;
public static final String SCOPE_OBJECT = "(.*# ScObj.*" + END;
public static final String MEMBAR = START + "MemBar" + MID + END;
private static final String ALLOC_OF_POSTFIX = ":.*\\R(.*(movl|xorl|nop|spill).*\\R)*.*call,static wrapper for: _new_instance_Java" + END;
private static final String ALLOC_ARRAY_OF_POSTFIX = ";:.*\\R(.*(movl|xorl|nop|spill).*\\R)*.*call,static wrapper for: _new_array_Java" + END;
private static final String CHECKCAST_ARRAY_OF_POSTFIX = ";:" + END;
private static final String STORE_OF_FIELD_POSTFIX = ",.*" + END;
private static final String STORE_OF_CLASS_POSTFIX = "(:|\\+)\\S* \\*" + END;
private static final String LOAD_OF_CLASS_POSTFIX = "(:|\\+)\\S* \\*" + END;
private static final String LOAD_OF_FIELD_POSTFIX = ",.*" + END;
/**
* Called by {@link IRMatcher} to merge special composite nodes together with additional user-defined input.
*/
@ -139,29 +136,72 @@ public class IRNode {
List<String> mergedNodes = new ArrayList<>();
for (int i = 0; i < nodes.length; i += 2) {
String node = nodes[i];
switch (node) {
case ALLOC_OF -> mergeCompositeNodes(nodes, mergedNodes, i, node, ALLOC_OF_POSTFIX, "ALLOC_OF");
case ALLOC_ARRAY_OF -> mergeCompositeNodes(nodes, mergedNodes, i, node, ALLOC_ARRAY_OF_POSTFIX, "ALLOC_ARRAY_OF");
case CHECKCAST_ARRAY_OF -> mergeCompositeNodes(nodes, mergedNodes, i, node, CHECKCAST_ARRAY_OF_POSTFIX, "CHECKCAST_ARRAY_OF");
case STORE_OF_CLASS, STORE_B_OF_CLASS, STORE_C_OF_CLASS, STORE_D_OF_CLASS, STORE_F_OF_CLASS, STORE_I_OF_CLASS,
STORE_L_OF_CLASS, STORE_N_OF_CLASS, STORE_P_OF_CLASS
-> mergeCompositeNodes(nodes, mergedNodes, i, node, STORE_OF_CLASS_POSTFIX, "STORE_OF_CLASS");
case STORE_OF_FIELD -> mergeCompositeNodes(nodes, mergedNodes, i, node, STORE_OF_FIELD_POSTFIX, "STORE_OF_FIELD");
case LOAD_OF_CLASS, LOAD_B_OF_CLASS, LOAD_UB_OF_CLASS, LOAD_D_OF_CLASS, LOAD_F_OF_CLASS, LOAD_I_OF_CLASS, LOAD_L_OF_CLASS,
LOAD_N_OF_CLASS, LOAD_P_OF_CLASS, LOAD_S_OF_CLASS, LOAD_US_OF_CLASS
-> mergeCompositeNodes(nodes, mergedNodes, i, node, LOAD_OF_CLASS_POSTFIX, "LOAD_OF_CLASS");
case LOAD_OF_FIELD -> mergeCompositeNodes(nodes, mergedNodes, i, node, LOAD_OF_FIELD_POSTFIX, "LOAD_OF_FIELD");
default -> {
i--; // No composite node, do not increment by 2.
mergedNodes.add(node);
if (node.startsWith(COMPOSITE_PREFIX)) {
if (i + 1 == nodes.length) {
reportMissingCompositeValue(node, i);
}
// Replace placeholder with user defined string.
node = node.substring(COMPOSITE_PREFIX.length()).replaceAll(IS_REPLACED, nodes[i + 1]);
} else {
i--; // No composite node, do not increment by 2.
}
mergedNodes.add(node);
}
return mergedNodes;
}
private static void mergeCompositeNodes(String[] nodes, List<String> mergedNodes, int i, String node, String postFix, String varName) {
TestFormat.check(i + 1 < nodes.length, "Must provide class name at index " + (i + 1) + " right after " + varName);
mergedNodes.add(node + Pattern.quote(nodes[i + 1]) + postFix);
/**
* Is default regex supported on current platform, used VM build, etc.?
* Throws a {@link CheckedTestFrameworkException} if the default regex is unsupported.
*/
public static void checkDefaultRegexSupported(String node) throws CheckedTestFrameworkException {
switch (node) {
case INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP -> {
if (!WhiteBox.getWhiteBox().isJVMCISupportedByGC()) {
throw new CheckedTestFrameworkException("INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP is unsupported in builds without JVMCI.");
}
}
case CHECKCAST_ARRAYCOPY -> {
if (Platform.isS390x()) {
throw new CheckedTestFrameworkException("CHECKCAST_ARRAYCOPY is unsupported on s390.");
}
}
// default: do nothing -> default regex is supported
}
}
/**
* Mapping from string variable value to string variable name for better error reporting.
*/
private static void reportMissingCompositeValue(String node, int i) {
String varName = switch (node) {
case ALLOC_OF -> "ALLOC_OF";
case ALLOC_ARRAY_OF -> "ALLOC_ARRAY_OF";
case CHECKCAST_ARRAY_OF -> "CHECKCAST_ARRAY_OF";
case STORE_OF_CLASS -> "STORE_OF_CLASS";
case STORE_B_OF_CLASS -> "STORE_B_OF_CLASS";
case STORE_C_OF_CLASS -> "STORE_C_OF_CLASS";
case STORE_D_OF_CLASS -> "STORE_D_OF_CLASS";
case STORE_F_OF_CLASS -> "STORE_F_OF_CLASS";
case STORE_I_OF_CLASS -> "STORE_I_OF_CLASS";
case STORE_L_OF_CLASS -> "STORE_L_OF_CLASS";
case STORE_N_OF_CLASS -> "STORE_N_OF_CLASS";
case STORE_P_OF_CLASS -> "STORE_P_OF_CLASS";
case STORE_OF_FIELD -> "STORE_OF_FIELD";
case LOAD_OF_CLASS -> "LOAD_OF_CLASS";
case LOAD_B_OF_CLASS -> "LOAD_B_OF_CLASS";
case LOAD_UB_OF_CLASS -> "LOAD_UB_OF_CLASS";
case LOAD_D_OF_CLASS -> "LOAD_D_OF_CLASS";
case LOAD_F_OF_CLASS -> "LOAD_F_OF_CLASS";
case LOAD_I_OF_CLASS -> "LOAD_I_OF_CLASS";
case LOAD_L_OF_CLASS -> "LOAD_L_OF_CLASS";
case LOAD_N_OF_CLASS -> "LOAD_N_OF_CLASS";
case LOAD_P_OF_CLASS -> "LOAD_P_OF_CLASS";
case LOAD_S_OF_CLASS -> "LOAD_S_OF_CLASS";
case LOAD_US_OF_CLASS -> "LOAD_US_OF_CLASS";
case LOAD_OF_FIELD -> "LOAD_OF_FIELD";
default -> throw new TestFrameworkException("Missing variable mapping for " + node);
};
TestFormat.fail("Must provide additional value at index " + (i + 1) + " right after " + varName);
}
}

View File

@ -71,8 +71,8 @@ import java.lang.annotation.RetentionPolicy;
* </ul>
*
* <p>
* Examples on how to write base tests can be found in {@link jdk.test.lib.hotspot.ir_framework.examples.BaseTestExample}
* and also as part of the internal testing in the package {@link jdk.test.lib.hotspot.ir_framework.tests}.
* Examples on how to write base tests can be found in {@link ir_framework.examples.BaseTestExample}
* and also as part of the internal testing in the package {@link ir_framework.tests}.
*
* @see Arguments
*/

View File

@ -69,7 +69,7 @@ public class TestVMProcess {
prepareTestVMFlags(additionalFlags, socket, testClass, helperClasses, defaultWarmup);
start();
}
processSocketOutput(socket.getOutput());
processSocketOutput(socket);
checkTestVMExitCode();
}
@ -163,23 +163,42 @@ public class TestVMProcess {
* Process the socket output: All prefixed lines are dumped to the standard output while the remaining lines
* represent the IR encoding used for IR matching later.
*/
private void processSocketOutput(String output) {
if (TestFramework.TESTLIST || TestFramework.EXCLUDELIST) {
StringBuilder builder = new StringBuilder();
private void processSocketOutput(TestFrameworkSocket socket) {
String output = socket.getOutput();
if (socket.hasStdOut()) {
StringBuilder testListBuilder = new StringBuilder();
StringBuilder messagesBuilder = new StringBuilder();
StringBuilder nonStdOutBuilder = new StringBuilder();
Scanner scanner = new Scanner(output);
System.out.println(System.lineSeparator() + "Run flag defined test list");
System.out.println("--------------------------");
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith(TestFrameworkSocket.STDOUT_PREFIX)) {
line = "> " + line.substring(TestFrameworkSocket.STDOUT_PREFIX.length());
System.out.println(line);
// Exclude [STDOUT] from message.
line = line.substring(TestFrameworkSocket.STDOUT_PREFIX.length());
if (line.startsWith(TestFrameworkSocket.TESTLIST_TAG)) {
// Exclude [TESTLIST] from message for better formatting.
line = "> " + line.substring(TestFrameworkSocket.TESTLIST_TAG.length() + 1);
testListBuilder.append(line).append(System.lineSeparator());
} else {
messagesBuilder.append(line).append(System.lineSeparator());
}
} else {
builder.append(line).append(System.lineSeparator());
nonStdOutBuilder.append(line).append(System.lineSeparator());
}
}
System.out.println();
irEncoding = builder.toString();
if (!testListBuilder.isEmpty()) {
System.out.println("Run flag defined test list");
System.out.println("--------------------------");
System.out.println(testListBuilder.toString());
System.out.println();
}
if (!messagesBuilder.isEmpty()) {
System.out.println("Messages from Test VM");
System.out.println("---------------------");
System.out.println(messagesBuilder.toString());
}
irEncoding = nonStdOutBuilder.toString();
} else {
irEncoding = output;
}

View File

@ -39,6 +39,9 @@ import java.util.concurrent.FutureTask;
*/
public class TestFrameworkSocket implements AutoCloseable {
public static final String STDOUT_PREFIX = "[STDOUT]";
public static final String TESTLIST_TAG = "[TESTLIST]";
public static final String DEFAULT_REGEX_TAG = "[DEFAULT_REGEX]";
// Static fields used for test VM only.
private static final String SERVER_PORT_PROPERTY = "ir.framework.server.port";
private static final int SERVER_PORT = Integer.getInteger(SERVER_PORT_PROPERTY, -1);
@ -51,6 +54,7 @@ public class TestFrameworkSocket implements AutoCloseable {
private final String serverPortPropertyFlag;
private FutureTask<String> socketTask;
private final ServerSocket serverSocket;
private boolean receivedStdOut = false;
public TestFrameworkSocket() {
try {
@ -88,6 +92,9 @@ public class TestFrameworkSocket implements AutoCloseable {
String next;
while ((next = in.readLine()) != null) {
builder.append(next).append(System.lineSeparator());
if (next.startsWith(STDOUT_PREFIX)) {
receivedStdOut = true;
}
}
return builder.toString();
} catch (IOException e) {
@ -108,14 +115,14 @@ public class TestFrameworkSocket implements AutoCloseable {
/**
* Only called by test VM to write to server socket.
*/
public static void write(String msg, String type) {
write(msg, type, false);
public static void write(String msg, String tag) {
write(msg, tag, false);
}
/**
* Only called by test VM to write to server socket.
*/
public static void write(String msg, String type, boolean stdout) {
public static void write(String msg, String tag, boolean stdout) {
if (REPRODUCE) {
System.out.println("Debugging Test VM: Skip writing due to -DReproduce");
return;
@ -129,7 +136,7 @@ public class TestFrameworkSocket implements AutoCloseable {
clientWriter = new PrintWriter(clientSocket.getOutputStream(), true);
}
if (stdout) {
msg = STDOUT_PREFIX + msg;
msg = STDOUT_PREFIX + tag + " " + msg;
}
clientWriter.println(msg);
} catch (Exception e) {
@ -145,7 +152,7 @@ public class TestFrameworkSocket implements AutoCloseable {
throw new TestRunException(failMsg, e);
}
if (TestFramework.VERBOSE) {
System.out.println("Written " + type + " to socket:");
System.out.println("Written " + tag + " to socket:");
System.out.println(msg);
}
}
@ -178,4 +185,11 @@ public class TestFrameworkSocket implements AutoCloseable {
throw new TestFrameworkException("Could not read from socket task", e);
}
}
/**
* Return whether test VM sent messages to be put on stdout (starting with {@link ::STDOUT_PREFIX}).
*/
public boolean hasStdOut() {
return receivedStdOut;
}
}

View File

@ -96,6 +96,9 @@ public class IREncodingPrinter {
private boolean shouldApplyIrRule(IR irAnno) {
checkIRAnnotations(irAnno);
if (isDefaultRegexUnsupported(irAnno)) {
return false;
}
if (irAnno.applyIf().length != 0) {
return hasAllRequiredFlags(irAnno.applyIf(), "applyIf");
}
@ -141,7 +144,21 @@ public class IREncodingPrinter {
}
TestFormat.checkNoThrow(applyRules <= 1,
"Can only specify one apply constraint " + failAt());
}
private boolean isDefaultRegexUnsupported(IR irAnno) {
try {
for (String s : irAnno.failOn()) {
IRNode.checkDefaultRegexSupported(s);
}
for (String s : irAnno.counts()) {
IRNode.checkDefaultRegexSupported(s);
}
} catch (CheckedTestFrameworkException e) {
TestFrameworkSocket.write("Skip Rule " + ruleIndex + ": " + e.getMessage(), TestFrameworkSocket.DEFAULT_REGEX_TAG, true);
return true;
}
return false;
}
private boolean hasAllRequiredFlags(String[] andRules, String ruleType) {

View File

@ -796,7 +796,7 @@ public class TestVM {
System.out.println("Run " + test.toString());
}
if (testFilterPresent) {
TestFrameworkSocket.write("Run " + test.toString(), "testfilter", true);
TestFrameworkSocket.write("Run " + test.toString(), TestFrameworkSocket.TESTLIST_TAG, true);
}
try {
test.run();

View File

@ -26,6 +26,8 @@ package ir_framework.tests;
import compiler.lib.ir_framework.*;
import compiler.lib.ir_framework.driver.IRViolationException;
import jdk.test.lib.Asserts;
import jdk.test.lib.Platform;
import sun.hotspot.WhiteBox;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
@ -41,11 +43,21 @@ import java.util.regex.Pattern;
* @summary Test IR matcher with different default IR node regexes. Use -DPrintIREncoding.
* Normally, the framework should be called with driver.
* @library /test/lib /
* @run main/othervm -DPrintIREncoding=true ir_framework.tests.TestIRMatching
* @build sun.hotspot.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm/timeout=240 -Xbootclasspath/a:. -DSkipWhiteBoxInstall=true -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -DPrintIREncoding=true ir_framework.tests.TestIRMatching
*/
public class TestIRMatching {
private static final List<Exception> exceptions = new ArrayList<>();
private static void addException(Exception e) {
System.out.println(TestFramework.getLastTestVMOutput());
exceptions.add(e);
}
public static void main(String[] args) {
runFailOnTestsArgs(BadFailOnConstraint.create(AndOr1.class, "test1(int)", 1, "CallStaticJava"), "-XX:TLABRefillWasteFraction=50", "-XX:+UsePerfData", "-XX:+UseTLAB");
runFailOnTestsArgs(BadFailOnConstraint.create(AndOr1.class, "test2()", 1, "CallStaticJava"), "-XX:TLABRefillWasteFraction=50", "-XX:-UsePerfData", "-XX:+UseTLAB");
@ -55,7 +67,7 @@ public class TestIRMatching {
runWithArguments(GoodCount.class, "-XX:TLABRefillWasteFraction=50");
runWithArguments(MultipleFailOnGood.class, "-XX:TLABRefillWasteFraction=50");
String[] allocMatches = { "MyClass", "call,static wrapper for: _new_instance_Java" };
String[] allocMatches = { "MyClass", "wrapper for: _new_instance_Java" };
runCheck(BadFailOnConstraint.create(MultipleFailOnBad.class, "fail1()", 1, 1, "Store"),
BadFailOnConstraint.create(MultipleFailOnBad.class, "fail1()", 1, 3, "Store"),
GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail1()", 1, 2, 4),
@ -88,7 +100,7 @@ public class TestIRMatching {
BadCountsConstraint.create(BadCount.class, "bad3()", 2, 1, "Store")
);
String[] allocArrayMatches = { "MyClass", "call,static wrapper for: _new_array_Java"};
String[] allocArrayMatches = { "MyClass", "wrapper for: _new_array_Java"};
runCheck(BadFailOnConstraint.create(AllocArray.class, "allocArray()", 1, allocArrayMatches),
BadFailOnConstraint.create(AllocArray.class, "allocArray()", 2, allocArrayMatches),
GoodFailOnConstraint.create(AllocArray.class, "allocArray()", 3),
@ -105,7 +117,7 @@ public class TestIRMatching {
BadFailOnConstraint.create(RunTests.class, "bad1(int)", 2, "Load")
);
runCheck(new String[] {"-XX:-UseCompressedClassPointers"},
runCheck(new String[] {"-XX:+IgnoreUnrecognizedVMOptions", "-XX:-UseCompressedClassPointers"},
BadFailOnConstraint.create(Loads.class, "load()", 1, 1, "Load"),
BadFailOnConstraint.create(Loads.class, "load()", 1, 3, "LoadI"),
BadCountsConstraint.create(Loads.class, "load()", 1, 1, 0),
@ -170,7 +182,9 @@ public class TestIRMatching {
BadFailOnConstraint.create(Traps.class, "rangeCheck()", 3, "CallStaticJava", "uncommon_trap", "null_check"),
GoodRuleConstraint.create(Traps.class, "rangeCheck()", 4),
BadFailOnConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 1, "CallStaticJava", "uncommon_trap"),
BadFailOnConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 2, "CallStaticJava", "uncommon_trap", "intrinsic_or_type_checked_inlining"),
WhiteBox.getWhiteBox().isJVMCISupportedByGC() ?
BadFailOnConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 2, "CallStaticJava", "uncommon_trap", "intrinsic_or_type_checked_inlining")
: GoodRuleConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 2),
BadFailOnConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 3, "CallStaticJava", "uncommon_trap", "null_check"),
GoodRuleConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 4)
);
@ -184,11 +198,22 @@ public class TestIRMatching {
runCheck(BadFailOnConstraint.create(ScopeObj.class, "scopeObject()", 1, "ScObj"));
runCheck(BadFailOnConstraint.create(Membar.class, "membar()", 1, "MemBar"));
runCheck(BadFailOnConstraint.create(CheckCastArray.class, "array()", 1, "cmp", "precise klass"),
BadFailOnConstraint.create(CheckCastArray.class, "array()", 2, 1,"cmp", "precise klass", "MyClass"),
BadFailOnConstraint.create(CheckCastArray.class, "array()", 2, 2,"cmp", "precise klass", "ir_framework/tests/MyClass"),
String cmp;
if (Platform.isPPC() || Platform.isX86()) {
cmp = "CMP";
} else if (Platform.isS390x()){
cmp = "CLFI";
} else {
cmp = "cmp";
}
runCheck(BadFailOnConstraint.create(CheckCastArray.class, "array()", 1, cmp, "precise klass"),
BadFailOnConstraint.create(CheckCastArray.class, "array()", 2, 1,cmp, "precise klass", "MyClass"),
BadFailOnConstraint.create(CheckCastArray.class, "array()", 2, 2,cmp, "precise klass", "ir_framework/tests/MyClass"),
GoodFailOnConstraint.create(CheckCastArray.class, "array()", 3),
BadFailOnConstraint.create(CheckCastArray.class, "arrayCopy(java.lang.Object[],java.lang.Class)", 1, "checkcast_arraycopy")
Platform.isS390x() ? // There is no checkcast_arraycopy stub for C2 on s390
GoodFailOnConstraint.create(CheckCastArray.class, "arrayCopy(java.lang.Object[],java.lang.Class)", 1)
: BadFailOnConstraint.create(CheckCastArray.class, "arrayCopy(java.lang.Object[],java.lang.Class)", 1, "checkcast_arraycopy")
);
// Redirect stdout to stream and then check if we find required IR encoding read from socket.
@ -198,33 +223,54 @@ public class TestIRMatching {
System.setOut(ps);
try {
runWithArguments(CompilationOutputOfFails.class);
runWithArgumentsFail(CompilationOutputOfFails.class);
shouldNotReach();
} catch (IRViolationException e) {
System.out.flush();
String output = baos.toString();
baos.reset();
Pattern pattern = Pattern.compile(">>> Compilation.*both\\d.*\\RPrintIdeal:(?:(?!PrintOpto|>>> Compilation)[\\S\\s])+PrintOptoAssembly");
Matcher matcher = pattern.matcher(output);
Asserts.assertEQ(matcher.results().count(), (long)7, "Could not find all both methods: " + output);
pattern = Pattern.compile(">>> Compilation.*ideal\\d.*\\RPrintIdeal:(?:(?!>>> Compilation)[\\S\\s])+");
matcher = pattern.matcher(output);
int count = 0;
while (matcher.find()) {
String match = matcher.group();
Asserts.assertFalse(match.contains("PrintOptoAssembly"), "Cannot contain opto assembly: " + output);
count++;
try {
boolean failed = false;
System.out.flush();
String output = baos.toString();
baos.reset();
Pattern pattern = Pattern.compile(">>> Compilation.*both\\d.*\\RPrintIdeal:(?:(?!PrintOpto|>>> Compilation)[\\S\\s])+PrintOptoAssembly");
Matcher matcher = pattern.matcher(output);
long bothCount = matcher.results().count();
if (bothCount != 7L) {
exceptions.add(new RuntimeException("Could not find all both() methods, expected 7 but found " + bothCount));
failed = true;
}
pattern = Pattern.compile(">>> Compilation.*ideal\\d.*\\RPrintIdeal:(?:(?!>>> Compilation)[\\S\\s])+");
matcher = pattern.matcher(output);
int count = 0;
while (matcher.find()) {
String match = matcher.group();
Asserts.assertFalse(match.contains("PrintOptoAssembly"), "Cannot contain opto assembly: " + output);
count++;
}
if (count != 7) {
exceptions.add(new RuntimeException("Could not find all ideal() methods, expected 7 but found " + count));
failed = true;
}
pattern = Pattern.compile(">>> Compilation.*opto\\d.*\\RPrintOptoAssembly:(?:(?!>>> Compilation)[\\S\\s])+");
matcher = pattern.matcher(output);
count = 0;
while (matcher.find()) {
String match = matcher.group();
Asserts.assertFalse(match.contains("PrintIdeal"), "Cannot contain opto assembly: " + output);
count++;
}
if (count != 7) {
exceptions.add(new RuntimeException("Could not find all opto() methods, expected 7 but found " + count));
failed = true;
}
if (failed) {
System.err.println(TestFramework.getLastTestVMOutput());
System.err.println(output);
}
} catch (Exception e1) {
addException(e1);
}
Asserts.assertEQ(count, 7, "Could not find all ideal methods: " + output);
pattern = Pattern.compile(">>> Compilation.*opto\\d.*\\RPrintOptoAssembly:(?:(?!>>> Compilation)[\\S\\s])+");
matcher = pattern.matcher(output);
count = 0;
while (matcher.find()) {
String match = matcher.group();
Asserts.assertFalse(match.contains("PrintIdeal"), "Cannot contain opto assembly: " + output);
count++;
}
Asserts.assertEQ(count, 7, "Could not find all opto methods");
} catch (Exception e) {
addException(e);
}
runWithArguments(FlagComparisons.class, "-XX:TLABRefillWasteFraction=50");
@ -248,9 +294,27 @@ public class TestIRMatching {
findIrIds(output, "testMatchAllIf50", 7, 12, 19, 21);
findIrIds(output, "testMatchNoneIf50", 4, 7, 11, 16, 20, 22);
System.setOut(old);
if (!exceptions.isEmpty()) {
System.err.println("TestIRMatching failed with one or more exceptions:");
for (Exception e : exceptions) {
System.err.println(e.getMessage());
e.printStackTrace(System.err);
System.err.println("---------");
}
throw new RuntimeException("TestIRMatching failed with one or more exceptions - check stderr and stdout");
}
}
private static void runWithArguments(Class<?> clazz, String... args) {
try {
new TestFramework(clazz).addFlags(args).start();
} catch (Exception e) {
addException(e);
}
}
private static void runWithArgumentsFail(Class<?> clazz, String... args) {
new TestFramework(clazz).addFlags(args).start();
}
@ -260,6 +324,8 @@ public class TestIRMatching {
shouldNotReach();
} catch (IRViolationException e) {
checkConstraints(e, constraints);
} catch (Exception e) {
addException(e);
}
}
@ -269,6 +335,8 @@ public class TestIRMatching {
shouldNotReach();
} catch (IRViolationException e) {
checkConstraints(e, constraints);
} catch (Exception e) {
addException(e);
}
}
@ -281,7 +349,7 @@ public class TestIRMatching {
} catch (Exception e1) {
System.out.println(TestFramework.getLastTestVMOutput());
System.out.println(message);
throw e1;
exceptions.add(e1);
}
}
@ -291,7 +359,13 @@ public class TestIRMatching {
new TestFramework(constraint.getKlass()).addFlags(args).start(); // All constraints have the same class.
shouldNotReach();
} catch (IRViolationException e) {
constraint.checkConstraint(e);
try {
constraint.checkConstraint(e);
} catch (Exception e1) {
addException(e);
}
} catch (Exception e) {
addException(e);
}
}
@ -393,7 +467,7 @@ class MultipleFailOnGood {
class MultipleFailOnBad {
private int iFld;
private int myInt;
private MyClass myClass;
private MyClassEmpty myClass;
@Test
@IR(failOn = {IRNode.STORE, IRNode.CALL, IRNode.STORE_I, IRNode.LOOP})
@ -426,21 +500,21 @@ class MultipleFailOnBad {
}
@Test
@IR(failOn = {IRNode.STORE_OF_CLASS, "MyClass", IRNode.ALLOC, IRNode.CALL})
@IR(failOn = {IRNode.STORE_OF_CLASS, "MyClassEmpty", IRNode.ALLOC, IRNode.CALL})
public void fail6() {
myClass = new MyClass();
myClass = new MyClassEmpty();
}
@Test
@IR(failOn = {IRNode.STORE_OF_CLASS, "UnknownClass", IRNode.ALLOC_OF, "MyClass"})
@IR(failOn = {IRNode.STORE_OF_CLASS, "UnknownClass", IRNode.ALLOC_OF, "MyClassEmpty"})
public void fail7() {
myClass = new MyClass();
myClass = new MyClassEmpty();
}
@Test
@IR(failOn = {IRNode.STORE_OF_CLASS, "UnknownClass", IRNode.ALLOC_OF, "ir_framework/tests/MyClassSub"})
@IR(failOn = {IRNode.STORE_OF_CLASS, "UnknownClass", IRNode.ALLOC_OF, "ir_framework/tests/MyClassEmptySub"})
public void fail8() {
myClass = new MyClassSub();
myClass = new MyClassEmptySub();
}
@Test
@ -564,6 +638,7 @@ class GoodCount {
long result;
MyClass myClass = new MyClass();
MyClassEmpty myClassEmpty = new MyClassEmpty();
MyClass myClassSubPoly = new MyClassSub();
MyClassSub myClassSub = new MyClassSub();
@ -647,11 +722,11 @@ class GoodCount {
}
@Test
@IR(counts = {IRNode.STORE_OF_FIELD, "myClass", "1", IRNode.STORE_OF_CLASS, "GoodCount", "1",
IRNode.STORE_OF_CLASS, "/GoodCount", "1", IRNode.STORE_OF_CLASS, "MyClass", "0"},
failOn = {IRNode.STORE_OF_CLASS, "MyClass"})
@IR(counts = {IRNode.STORE_OF_FIELD, "myClassEmpty", "1", IRNode.STORE_OF_CLASS, "GoodCount", "1",
IRNode.STORE_OF_CLASS, "/GoodCount", "1", IRNode.STORE_OF_CLASS, "MyClassEmpty", "0"},
failOn = {IRNode.STORE_OF_CLASS, "MyClassEmpty"})
public void good6() {
myClass = new MyClass();
myClassEmpty = new MyClassEmpty();
}
@Test
@ -1122,7 +1197,7 @@ class CheckCastArray {
public void testArrayCopy() {
arrayCopy(mArr, MyClass[].class);
arrayCopy(mArr, Object[].class);
arrayCopy(mArr, MyClass2[].class);
arrayCopy(mArr, MyClassEmpty[].class);
}
}
@ -1171,7 +1246,7 @@ class CompilationOutputOfFails {
@Test
@IR(counts = {IRNode.COUNTEDLOOP, "0"})
@IR(counts = {"call", "1"})
@IR(counts = {"call", "0"})
public void both6() {
for (int i = 0; i < 100; i++) {
dontInline();
@ -1180,7 +1255,7 @@ class CompilationOutputOfFails {
@Test
@IR(failOn = IRNode.COUNTEDLOOP)
@IR(counts = {"call", "1"})
@IR(counts = {"call", "0"})
public void both7() {
for (int i = 0; i < 100; i++) {
dontInline();
@ -1275,7 +1350,7 @@ class CompilationOutputOfFails {
}
@Test
@IR(counts = {"call", "1"})
@IR(counts = {"call", "0"})
public void opto4() {
for (int i = 0; i < 100; i++) {
dontInline();
@ -1284,7 +1359,7 @@ class CompilationOutputOfFails {
@Test
@IR(failOn = IRNode.STORE) // not fail
@IR(counts = {"call", "1"})
@IR(counts = {"call", "0"})
public void opto5() {
for (int i = 0; i < 100; i++) {
dontInline();
@ -1293,7 +1368,7 @@ class CompilationOutputOfFails {
@Test
@IR(counts = {IRNode.STORE, "0"}) // not fail
@IR(counts = {"call", "1"})
@IR(counts = {"call", "0"})
public void opto6() {
for (int i = 0; i < 100; i++) {
dontInline();
@ -1302,7 +1377,7 @@ class CompilationOutputOfFails {
@Test
@IR(counts = {"call", "10"})
@IR(counts = {"call", "1"})
@IR(counts = {"call", "0"})
public void opto7() {
for (int i = 0; i < 100; i++) {
dontInline();
@ -1328,7 +1403,9 @@ class MyClass {
static long lFldStatic;
}
class MyClass2 {}
class MyClassEmpty {}
class MyClassEmptySub extends MyClassEmpty {}
class MyClassSub extends MyClass {
int iFld;
@ -1375,7 +1452,7 @@ abstract class Constraint {
@Override
public String toString() {
return "Constraint " + getClass().getSimpleName() + ", method: " + methodName + ", rule: " + ruleIdx;
return "Constraint " + getClass().getSimpleName() + ", " + errorPrefix();
}
public Class<?> getKlass() {
@ -1383,7 +1460,7 @@ abstract class Constraint {
}
protected String errorPrefix() {
return "Method " + methodName + ", Rule " + ruleIdx;
return "Class " + klass.getSimpleName() + ", Method " + methodName + ", Rule " + ruleIdx;
}
public void checkConstraint(IRViolationException e) {
@ -1405,8 +1482,6 @@ abstract class Constraint {
}
abstract protected void checkIRRule(String irRule);
protected void checkOnMethod(String method) {}
}
// Constraint for rule that does not fail.
@ -1538,7 +1613,9 @@ abstract class RegexConstraint extends Constraint {
for (int i = 1; i < splitRegex.length; i++) {
String regexString = splitRegex[i];
if (regexString.startsWith(String.valueOf(regexIndex))) {
Asserts.assertTrue(matches.stream().allMatch(regexString::contains),
// Do matching on actual match and not on regex string
String actualMatch = regexString.split("\\R", 2)[1];
Asserts.assertTrue(matches.stream().allMatch(actualMatch::contains),
errorPrefix() + " could not find all matches at Regex " + regexIndex);
matched = true;
}