8376291: [IR Framework] Create classes for separate Test VM messages

Reviewed-by: mchevalier, dfenacci, epeter
This commit is contained in:
Christian Hagedorn 2026-02-24 07:23:41 +00:00
parent f0da04a40a
commit 14cb5ddfc5
18 changed files with 444 additions and 146 deletions

View File

@ -75,6 +75,7 @@ public class TestVMProcess {
checkTestVMExitCode();
String hotspotPidFileName = String.format("hotspot_pid%d.log", oa.pid());
testVmData = socket.testVmData(hotspotPidFileName, allowNotCompilable);
testVmData.printJavaMessages();
}
public String getCommandLine() {

View File

@ -98,7 +98,7 @@ public class IRMethod implements IRMethodMatchable {
List<MatchResult> match = matcher.match();
long endTime = System.nanoTime();
long duration = (endTime - startTime);
System.out.println("Verifying IR rules for " + name() + ": " + duration + " ns = " + (duration / 1000000) + " ms");
System.out.println("Verifying IR rules for " + name() + ": " + duration + " ns = " + (duration / 1_000_000) + " ms");
return new IRMethodMatchResult(method, match);
}
}

View File

@ -36,8 +36,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Class to parse the Applicable IR Rules emitted by the Test VM and creating {@link TestMethod} objects for each entry.
@ -45,11 +43,6 @@ import java.util.regex.Pattern;
* @see TestMethod
*/
public class ApplicableIRRulesParser {
private static final boolean PRINT_APPLICABLE_IR_RULES = Boolean.parseBoolean(System.getProperty("PrintApplicableIRRules", "false"));
private static final Pattern APPLICABLE_IR_RULES_PATTERN =
Pattern.compile("(?<=" + ApplicableIRRulesPrinter.START + "\r?\n).*\\R([\\s\\S]*)(?=" + ApplicableIRRulesPrinter.END + ")");
private final Map<String, TestMethod> testMethods;
private final Class<?> testClass;
@ -63,10 +56,6 @@ public class ApplicableIRRulesParser {
* entry for each method that needs to be IR matched on.
*/
public TestMethods parse(String applicableIRRules) {
if (TestFramework.VERBOSE || PRINT_APPLICABLE_IR_RULES) {
System.out.println("Read Applicable IR Rules from Test VM:");
System.out.println(applicableIRRules);
}
createTestMethodMap(applicableIRRules, testClass);
// We could have found format errors in @IR annotations. Report them now with an exception.
TestFormat.throwIfAnyFailures();
@ -105,15 +94,11 @@ public class ApplicableIRRulesParser {
* Parse the Applicable IR Rules lines without header, explanation line and footer and return them in an array.
*/
private String[] getApplicableIRRulesLines(String applicableIRRules) {
Matcher matcher = APPLICABLE_IR_RULES_PATTERN.matcher(applicableIRRules);
TestFramework.check(matcher.find(), "Did not find Applicable IR Rules in:" +
System.lineSeparator() + applicableIRRules);
String lines = matcher.group(1).trim();
if (lines.isEmpty()) {
if (applicableIRRules.isEmpty()) {
// Nothing to IR match.
return new String[0];
}
return lines.split("\\R");
return applicableIRRules.split("\\R");
}
/**
@ -148,7 +133,7 @@ public class ApplicableIRRulesParser {
private void validateIRRuleIds(Method m, IR[] irAnnos, IRRuleIds irRuleIds) {
TestFramework.check(irRuleIds != null, "Should find method name in validIrRulesMap for " + m);
TestFramework.check(!irRuleIds.isEmpty(), "Did not find any rule indices for " + m);
TestFramework.check((irRuleIds.first() >= 1 || irRuleIds.first() == ApplicableIRRulesPrinter.NO_RULE_APPLIED)
TestFramework.check((irRuleIds.first() >= 1 || irRuleIds.first() == ApplicableIRRulesPrinter.NO_RULES)
&& irRuleIds.last() <= irAnnos.length,
"Invalid IR rule index found in validIrRulesMap for " + m);
}
@ -157,6 +142,6 @@ public class ApplicableIRRulesParser {
* Does the list of IR rules contain any applicable IR rules for the given conditions?
*/
private boolean hasAnyApplicableIRRules(IRRuleIds irRuleIds) {
return irRuleIds.first() != ApplicableIRRulesPrinter.NO_RULE_APPLIED;
return irRuleIds.first() != ApplicableIRRulesPrinter.NO_RULES;
}
}

View File

@ -57,7 +57,7 @@ public class TestClassParser {
public Matchable parse(TestVMData testVmData) {
ApplicableIRRulesParser applicableIRRulesParser = new ApplicableIRRulesParser(testClass);
TestMethods testMethods = applicableIRRulesParser.parse(testVmData.applicableIRRules());
VMInfo vmInfo = VMInfoParser.parseVMInfo(testVmData.applicableIRRules());
VMInfo vmInfo = VMInfoParser.parseVMInfo(testVmData.vmInfo());
if (testMethods.hasTestMethods()) {
HotSpotPidFileParser hotSpotPidFileParser = new HotSpotPidFileParser(testClass.getName(), testMethods);
LoggedMethods loggedMethods = hotSpotPidFileParser.parse(testVmData.hotspotPidFileName());

View File

@ -23,14 +23,10 @@
package compiler.lib.ir_framework.driver.irmatching.parser;
import compiler.lib.ir_framework.TestFramework;
import compiler.lib.ir_framework.shared.TestFrameworkException;
import compiler.lib.ir_framework.test.VMInfoPrinter;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Class to parse the VMInfo emitted by the Test VM and creating {@link VMInfo} objects for each entry.
@ -39,15 +35,12 @@ import java.util.regex.Pattern;
*/
public class VMInfoParser {
private static final Pattern VM_INFO_PATTERN =
Pattern.compile("(?<=" + VMInfoPrinter.START_VM_INFO + "\r?\n).*\\R([\\s\\S]*)(?=" + VMInfoPrinter.END_VM_INFO + ")");
/**
* Extract VMInfo from the applicableIRRules.
* Create a new VMInfo object from the vmInfo string.
*/
public static VMInfo parseVMInfo(String applicableIRRules) {
public static VMInfo parseVMInfo(String vmInfo) {
Map<String, String> map = new HashMap<>();
String[] lines = getVMInfoLines(applicableIRRules);
String[] lines = getVMInfoLines(vmInfo);
for (String s : lines) {
String line = s.trim();
String[] splitLine = line.split(":", 2);
@ -64,14 +57,11 @@ public class VMInfoParser {
/**
* Extract the VMInfo from the applicableIRRules string, strip away the header and return the individual key-value lines.
*/
private static String[] getVMInfoLines(String applicableIRRules) {
Matcher matcher = VM_INFO_PATTERN.matcher(applicableIRRules);
TestFramework.check(matcher.find(), "Did not find VMInfo in:" + System.lineSeparator() + applicableIRRules);
String lines = matcher.group(1).trim();
if (lines.isEmpty()) {
private static String[] getVMInfoLines(String vmInfo) {
if (vmInfo.isEmpty()) {
// Nothing to IR match.
return new String[0];
}
return lines.split("\\R");
return vmInfo.split("\\R");
}
}

View File

@ -26,25 +26,30 @@ package compiler.lib.ir_framework.driver.network;
import compiler.lib.ir_framework.driver.irmatching.IRMatcher;
import compiler.lib.ir_framework.driver.network.testvm.java.JavaMessages;
import compiler.lib.ir_framework.shared.TestFrameworkSocket;
import compiler.lib.ir_framework.test.network.MessageTag;
import java.util.Scanner;
/**
* This class collects all the parsed data received over the {@link TestFrameworkSocket}. This data is required later
* in the {@link IRMatcher}.
*/
public class TestVMData {
private final JavaMessages javaMessages;
private final boolean allowNotCompilable;
private final String hotspotPidFileName;
private final String applicableIRRules;
public TestVMData(JavaMessages javaMessages, String hotspotPidFileName, boolean allowNotCompilable) {
this.applicableIRRules = processOutput(javaMessages);
this.javaMessages = javaMessages;
this.hotspotPidFileName = hotspotPidFileName;
this.allowNotCompilable = allowNotCompilable;
}
public String applicableIRRules() {
return javaMessages.applicableIRRules();
}
public String vmInfo() {
return javaMessages.vmInfo();
}
public String hotspotPidFileName() {
return hotspotPidFileName;
}
@ -53,52 +58,7 @@ public class TestVMData {
return allowNotCompilable;
}
public String applicableIRRules() {
return applicableIRRules;
}
/**
* Process the socket output: All prefixed lines are dumped to the standard output while the remaining lines
* represent the Applicable IR Rules used for IR matching later.
*/
private String processOutput(JavaMessages javaMessages) {
String output = javaMessages.output();
if (javaMessages.hasStdOut()) {
StringBuilder testListBuilder = new StringBuilder();
StringBuilder messagesBuilder = new StringBuilder();
StringBuilder nonStdOutBuilder = new StringBuilder();
Scanner scanner = new Scanner(output);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith(MessageTag.STDOUT)) {
// Exclude [STDOUT] from message.
line = line.substring(MessageTag.STDOUT.length());
if (line.startsWith(MessageTag.TEST_LIST)) {
// Exclude [TEST_LIST] from message for better formatting.
line = "> " + line.substring(MessageTag.TEST_LIST.length() + 1);
testListBuilder.append(line).append(System.lineSeparator());
} else {
messagesBuilder.append(line).append(System.lineSeparator());
}
} else {
nonStdOutBuilder.append(line).append(System.lineSeparator());
}
}
System.out.println();
if (!testListBuilder.isEmpty()) {
System.out.println("Run flag defined test list");
System.out.println("--------------------------");
System.out.println(testListBuilder);
System.out.println();
}
if (!messagesBuilder.isEmpty()) {
System.out.println("Messages from Test VM");
System.out.println("---------------------");
System.out.println(messagesBuilder);
}
return nonStdOutBuilder.toString();
} else {
return output;
}
public void printJavaMessages() {
javaMessages.print();
}
}

View File

@ -23,10 +23,10 @@
package compiler.lib.ir_framework.driver.network.testvm;
import compiler.lib.ir_framework.driver.network.testvm.java.JavaMessageParser;
import compiler.lib.ir_framework.driver.network.testvm.java.JavaMessages;
import compiler.lib.ir_framework.shared.TestFrameworkException;
import compiler.lib.ir_framework.shared.TestFrameworkSocket;
import compiler.lib.ir_framework.test.network.MessageTag;
import java.io.BufferedReader;
import java.net.Socket;
@ -35,33 +35,29 @@ import java.util.concurrent.Future;
/**
* Dedicated reader for Test VM messages received by the {@link TestFrameworkSocket}. The reader is used as a task
* wrapped in a {@link Future}. The received messages are returned in a new {@link JavaMessages} wrapper. Once the
* Test VM is terminated, the client connection is closed and the parsed messages can be fetched with
* {@link Future#get()} which calls {@link #call()}.
* wrapped in a {@link Future}. The received messages are parsed with the {@link JavaMessageParser}. Once the Test VM
* is terminated, client connection is closed and the parsed messages can be fetched with {@link Future#get()} which
* calls {@link #call()}.
*/
public class TestVmMessageReader implements Callable<JavaMessages> {
private final Socket socket;
private final BufferedReader reader;
private boolean receivedStdOut;
private final JavaMessageParser messageParser;
public TestVmMessageReader(Socket socket, BufferedReader reader) {
this.socket = socket;
this.reader = reader;
this.receivedStdOut = false;
this.messageParser = new JavaMessageParser();
}
@Override
public JavaMessages call() {
try (socket; reader) {
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line).append(System.lineSeparator());
if (line.startsWith(MessageTag.STDOUT)) {
receivedStdOut = true;
}
messageParser.parseLine(line);
}
return new JavaMessages(builder.toString(), receivedStdOut);
return messageParser.output();
} catch (Exception e) {
throw new TestFrameworkException("Error while reading Test VM socket messages", e);
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2026, 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.lib.ir_framework.driver.network.testvm.java;
import compiler.lib.ir_framework.test.network.MessageTag;
import java.util.List;
/**
* Class to collect all Java Messages sent with tag {@link MessageTag#TEST_LIST}. These are only generated when the
* user runs with {@code -DTest=myTest} and represent the executed tests.
*/
class ExecutedTests implements JavaMessage {
private final List<String> tests;
public ExecutedTests(List<String> tests) {
this.tests = tests;
}
@Override
public void print() {
if (tests.isEmpty()) {
return;
}
System.out.println();
System.out.println("Executed Subset of Tests");
System.out.println("------------------------");
for (String test : tests) {
System.out.println("- " + test);
}
System.out.println();
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2026, 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.lib.ir_framework.driver.network.testvm.java;
import compiler.lib.ir_framework.shared.TestFrameworkSocket;
import compiler.lib.ir_framework.test.network.MessageTag;
/**
* Interface for a message sent from Java code to the Driver VM via the {@link TestFrameworkSocket}. We differentiate
* between different messages depending on the leading {@link MessageTag} of a received message.
*/
public interface JavaMessage {
void print();
}

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 2026, 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.lib.ir_framework.driver.network.testvm.java;
import compiler.lib.ir_framework.TestFramework;
import compiler.lib.ir_framework.shared.TestFrameworkException;
import compiler.lib.ir_framework.test.network.MessageTag;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static compiler.lib.ir_framework.test.network.MessageTag.*;
/**
* Dedicated parser for {@link JavaMessages} received from the Test VM. Depending on the parsed {@link MessageTag}, the
* message is parsed differently.
*/
public class JavaMessageParser {
private static final Pattern TAG_PATTERN = Pattern.compile("^(\\[[^]]+])\\s*(.*)$");
private final List<String> stdoutMessages;
private final List<String> executedTests;
private final Map<String, Long> methodTimes;
private final StringBuilder vmInfoBuilder;
private final StringBuilder applicableIrRules;
private StringBuilder currentBuilder;
public JavaMessageParser() {
this.stdoutMessages = new ArrayList<>();
this.methodTimes = new HashMap<>();
this.executedTests = new ArrayList<>();
this.vmInfoBuilder = new StringBuilder();
this.applicableIrRules = new StringBuilder();
this.currentBuilder = null;
}
public void parseLine(String line) {
line = line.trim();
Matcher tagLineMatcher = TAG_PATTERN.matcher(line);
if (tagLineMatcher.matches()) {
// New tag
assertNoActiveParser();
parseTagLine(tagLineMatcher);
return;
}
assertActiveParser();
if (line.equals(END_MARKER)) {
// End tag
parseEndTag();
return;
}
// Multi-line message for single tag.
currentBuilder.append(line).append(System.lineSeparator());
}
private void assertNoActiveParser() {
TestFramework.check(currentBuilder == null, "Unexpected new tag while parsing block");
}
private void parseTagLine(Matcher tagLineMatcher) {
String tag = tagLineMatcher.group(1);
String message = tagLineMatcher.group(2);
switch (tag) {
case STDOUT -> stdoutMessages.add(message);
case TEST_LIST -> executedTests.add(message);
case PRINT_TIMES -> parsePrintTimes(message);
case VM_INFO -> currentBuilder = vmInfoBuilder;
case APPLICABLE_IR_RULES -> currentBuilder = applicableIrRules;
default -> throw new TestFrameworkException("unknown tag");
}
}
private void parsePrintTimes(String message) {
String[] split = message.split(",");
TestFramework.check(split.length == 2, "unexpected format");
String methodName = split[0];
try {
long duration = Long.parseLong(split[1]);
methodTimes.put(methodName, duration);
} catch (NumberFormatException e) {
throw new TestFrameworkException("invalid duration", e);
}
}
private void assertActiveParser() {
TestFramework.check(currentBuilder != null, "Received non-tag line outside of any tag block");
}
private void parseEndTag() {
currentBuilder = null;
}
public JavaMessages output() {
return new JavaMessages(new StdoutMessages(stdoutMessages),
new ExecutedTests(executedTests),
new MethodTimes(methodTimes),
applicableIrRules.toString(),
vmInfoBuilder.toString());
}
}

View File

@ -23,28 +23,44 @@
package compiler.lib.ir_framework.driver.network.testvm.java;
import compiler.lib.ir_framework.test.network.MessageTag;
import compiler.lib.ir_framework.TestFramework;
/**
* Class to collect all Java messages sent from the Test VM to the Driver VM.
*/
public class JavaMessages {
private final String output;
private final boolean receivedStdOut;
private static final boolean PRINT_APPLICABLE_IR_RULES = Boolean.parseBoolean(System.getProperty("PrintApplicableIRRules", "false"));
public JavaMessages(String output, boolean receivedStdOut) {
this.output = output;
this.receivedStdOut = receivedStdOut;
private final StdoutMessages stdoutMessages;
private final ExecutedTests executedTests;
private final MethodTimes methodTimes;
private final String applicableIrRules;
private final String vmInfo;
JavaMessages(StdoutMessages stdoutMessages, ExecutedTests executedTests, MethodTimes methodTimes,
String applicableIrRules, String vmInfo) {
this.stdoutMessages = stdoutMessages;
this.executedTests = executedTests;
this.methodTimes = methodTimes;
this.applicableIrRules = applicableIrRules;
this.vmInfo = vmInfo;
}
public String output() {
return output;
public String applicableIRRules() {
return applicableIrRules;
}
/**
* Return whether Test VM sent messages to be put on stdout (starting with {@link MessageTag#STDOUT}).
*/
public boolean hasStdOut() {
return receivedStdOut;
public String vmInfo() {
return vmInfo;
}
public void print() {
stdoutMessages.print();
methodTimes.print();
executedTests.print();
if (TestFramework.VERBOSE || PRINT_APPLICABLE_IR_RULES) {
System.out.println("Read Applicable IR Rules from Test VM:");
System.out.println(applicableIrRules);
}
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2026, 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.lib.ir_framework.driver.network.testvm.java;
import compiler.lib.ir_framework.test.network.MessageTag;
import java.util.List;
import java.util.Map;
/**
* Class to collect all Java Messages sent with tag {@link MessageTag#PRINT_TIMES}. These are only generated when the
* user runs with {@code -DPrintTimes=true} and represent the execution times for methods.
*/
class MethodTimes implements JavaMessage {
private final Map<String, Long> methodTimes;
public MethodTimes(Map<String, Long> methodTimes) {
this.methodTimes = methodTimes;
}
@Override
public void print() {
if (methodTimes.isEmpty()) {
return;
}
System.out.println();
System.out.println("Test Execution Times");
System.out.println("--------------------");
int maxWidthNames = maxMethodNameWidth();
int maxDurationsWidth = maxDurationsWidth();
List<Map.Entry<String, Long>> sortedMethodTimes = sortByDurationAsc();
for (Map.Entry<String, Long> entry : sortedMethodTimes) {
System.out.printf("- %-" + (maxWidthNames + 3) + "s %" + maxDurationsWidth + "d ns%n",
entry.getKey() + ":", entry.getValue());
}
System.out.println();
}
private int maxMethodNameWidth() {
return methodTimes.keySet().stream()
.mapToInt(String::length)
.max()
.orElseThrow();
}
private int maxDurationsWidth() {
return methodTimes.values().stream()
.mapToInt(v -> Long.toString(v).length())
.max()
.orElseThrow();
}
private List<Map.Entry<String, Long>> sortByDurationAsc() {
return methodTimes.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.toList();
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2026, 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.lib.ir_framework.driver.network.testvm.java;
import compiler.lib.ir_framework.test.network.MessageTag;
import java.util.List;
/**
* Class to collect all Java Messages sent with tag {@link MessageTag#STDOUT}. These messages are generated at various
* places in the Test VM and are unconditionally shown in the Driver VM output.
*/
class StdoutMessages implements JavaMessage {
private final List<String> messages;
public StdoutMessages(List<String> messages) {
this.messages = messages;
}
@Override
public void print() {
if (messages.isEmpty()) {
return;
}
System.out.println();
System.out.println("Test VM Messages");
System.out.println("----------------");
for (String message : messages) {
System.out.println("- " + message);
}
}
}

View File

@ -47,9 +47,7 @@ import java.util.function.Function;
* termination of the Test VM. IR rule indices start at 1.
*/
public class ApplicableIRRulesPrinter {
public static final String START = "##### ApplicableIRRules - used by TestFramework #####";
public static final String END = "----- END -----";
public static final int NO_RULE_APPLIED = -1;
public static final int NO_RULES = -1;
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
private static final List<Function<String, Object>> LONG_GETTERS = Arrays.asList(
@ -131,11 +129,6 @@ public class ApplicableIRRulesPrinter {
"zvkn"
));
public ApplicableIRRulesPrinter() {
output.append(START).append(System.lineSeparator());
output.append("<method>,{comma separated applied @IR rule ids}").append(System.lineSeparator());
}
/**
* Emits "<method>,{ids}" where {ids} is either:
* - indices of all @IR rules that should be applied, separated by a comma
@ -162,7 +155,7 @@ public class ApplicableIRRulesPrinter {
if (irAnnos.length != 0) {
output.append(m.getName());
if (validRules.isEmpty()) {
output.append("," + NO_RULE_APPLIED);
output.append("," + NO_RULES);
} else {
for (i = 0; i < validRules.size(); i++) {
output.append(",").append(validRules.get(i));
@ -524,8 +517,8 @@ public class ApplicableIRRulesPrinter {
}
public void emit() {
output.append(END);
TestVmSocket.sendWithTag(MessageTag.APPLICABLE_IR_RULES, output.toString());
output.append(MessageTag.END_MARKER);
TestVmSocket.sendMultiLine(MessageTag.APPLICABLE_IR_RULES, output.toString());
}
}

View File

@ -594,8 +594,8 @@ public class TestVM {
"Cannot overload @Test methods, but method " + m + " has " + overloads.size() + " overload" + (overloads.size() == 1 ? "" : "s") + ":" +
overloads.stream().map(String::valueOf).collect(Collectors.joining("\n - ", "\n - ", ""))
);
TestFormat.check(!testMethodMap.containsKey(m.getName()),
"Cannot overload two @Test methods: " + m + ", " + testMethodMap.get(m.getName()));
TestFramework.check(!testMethodMap.containsKey(m.getName()),
"Cannot overload two @Test methods: " + m + ", " + testMethodMap.get(m.getName()));
TestFormat.check(testAnno != null, m + " must be a method with a @Test annotation");
Check checkAnno = getAnnotation(m, Check.class);
@ -836,7 +836,6 @@ public class TestVM {
* Once all framework tests are collected, they are run in this method.
*/
private void runTests() {
TreeMap<Long, String> durations = PRINT_TIMES ? new TreeMap<>() : null;
long startTime = System.nanoTime();
List<AbstractTest> testList;
boolean testFilterPresent = testFilterPresent();
@ -865,7 +864,7 @@ public class TestVM {
System.out.println("Run " + test.toString());
}
if (testFilterPresent) {
TestVmSocket.send(MessageTag.TEST_LIST + "Run " + test.toString());
TestVmSocket.sendWithTag(MessageTag.TEST_LIST, "Run " + test.toString());
}
try {
test.run();
@ -880,10 +879,11 @@ public class TestVM {
if (PRINT_TIMES) {
long endTime = System.nanoTime();
long duration = (endTime - startTime);
durations.put(duration, test.getName());
if (VERBOSE) {
System.out.println("Done " + test.getName() + ": " + duration + " ns = " + (duration / 1000000) + " ms");
System.out.println("Done " + test.getName() + ": " + duration + " ns = " + (duration / 1_000_000) + " ms");
}
// Will be correctly formatted later.
TestVmSocket.sendWithTag(MessageTag.PRINT_TIMES, test.getName() + "," + duration);
}
if (GC_AFTER) {
System.out.println("doing GC");
@ -891,14 +891,6 @@ public class TestVM {
}
}
// Print execution times
if (PRINT_TIMES) {
TestVmSocket.send(MessageTag.PRINT_TIMES + " Test execution times:");
for (Map.Entry<Long, String> entry : durations.entrySet()) {
TestVmSocket.send(MessageTag.PRINT_TIMES + String.format("%-25s%15d ns%n", entry.getValue() + ":", entry.getKey()));
}
}
if (failures > 0) {
// Finally, report all occurred exceptions in a nice format.
String msg = System.lineSeparator() + System.lineSeparator() + "Test Failures (" + failures + ")"

View File

@ -31,15 +31,10 @@ import jdk.test.whitebox.WhiteBox;
* Prints some Test VM info to the socket.
*/
public class VMInfoPrinter {
public static final String START_VM_INFO = "##### IRMatchingVMInfo - used by TestFramework #####";
public static final String END_VM_INFO = "----- END VMInfo -----";
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
public static void emit() {
StringBuilder vmInfo = new StringBuilder();
vmInfo.append(START_VM_INFO).append(System.lineSeparator());
vmInfo.append("<key>:<value>").append(System.lineSeparator());
// CPU feature independent info
String cpuFeatures = WHITE_BOX.getCPUFeatures();
@ -65,7 +60,7 @@ public class VMInfoPrinter {
.append(useAVXIsDefault ? 1 : 0)
.append(System.lineSeparator());
vmInfo.append(END_VM_INFO);
TestVmSocket.sendWithTag(MessageTag.VM_INFO, vmInfo.toString());
vmInfo.append(MessageTag.END_MARKER);
TestVmSocket.sendMultiLine(MessageTag.VM_INFO, vmInfo.toString());
}
}

View File

@ -29,4 +29,5 @@ public class MessageTag {
public static final String PRINT_TIMES = "[PRINT_TIMES]";
public static final String VM_INFO = "[VM_INFO]";
public static final String APPLICABLE_IR_RULES = "[APPLICABLE_IR_RULES]";
public static final String END_MARKER = "#END#";
}

View File

@ -25,6 +25,7 @@ package compiler.lib.ir_framework.test.network;
import compiler.lib.ir_framework.TestFramework;
import compiler.lib.ir_framework.shared.TestRunException;
import compiler.lib.ir_framework.test.TestVM;
import java.io.IOException;
import java.io.PrintWriter;
@ -46,6 +47,20 @@ public class TestVmSocket {
sendWithTag(MessageTag.STDOUT, message);
}
/**
* Send a message with multiple lines to the Driver VM with a {@link MessageTag}. Not all messages are shown by
* default in the Driver VM output and require setting some property flags first like {@code -DPrintTimes=true}.
*/
public static void sendMultiLine(String tag, String message) {
if (REPRODUCE) {
// Debugging Test VM: Skip writing due to -DReproduce;
return;
}
TestFramework.check(socket != null, "must be connected");
writer.println(tag + System.lineSeparator() + message);
}
/**
* Send a message to the Driver VM with a {@link MessageTag}. Not all messages are shown by default in the
* Driver VM output and require setting some property flags first like {@code -DPrintTimes=true}.