8378243: [IR Framework] Create separate VMInfo and ApplicableIRRules JavaMessage classes

Reviewed-by: mchevalier, dfenacci, thartmann
This commit is contained in:
Christian Hagedorn 2026-03-23 07:11:33 +00:00
parent 206c9cd6e1
commit db49e8d083
25 changed files with 453 additions and 248 deletions

View File

@ -24,7 +24,7 @@
package compiler.lib.ir_framework;
import compiler.lib.ir_framework.driver.irmatching.mapping.*;
import compiler.lib.ir_framework.driver.irmatching.parser.VMInfo;
import compiler.lib.ir_framework.driver.network.testvm.java.VMInfo;
import compiler.lib.ir_framework.shared.CheckedTestFrameworkException;
import compiler.lib.ir_framework.shared.TestFormat;
import compiler.lib.ir_framework.shared.TestFormatException;

View File

@ -31,8 +31,8 @@ import compiler.lib.ir_framework.driver.irmatching.MatchResult;
import compiler.lib.ir_framework.driver.irmatching.Matchable;
import compiler.lib.ir_framework.driver.irmatching.MatchableMatcher;
import compiler.lib.ir_framework.driver.irmatching.irrule.IRRule;
import compiler.lib.ir_framework.driver.irmatching.parser.VMInfo;
import compiler.lib.ir_framework.driver.network.testvm.java.IRRuleIds;
import compiler.lib.ir_framework.driver.network.testvm.java.VMInfo;
import compiler.lib.ir_framework.shared.TestFormat;
import compiler.lib.ir_framework.shared.TestFormatException;

View File

@ -31,7 +31,7 @@ import compiler.lib.ir_framework.driver.irmatching.Matchable;
import compiler.lib.ir_framework.driver.irmatching.MatchableMatcher;
import compiler.lib.ir_framework.driver.irmatching.irrule.phase.CompilePhaseIRRule;
import compiler.lib.ir_framework.driver.irmatching.irrule.phase.CompilePhaseIRRuleBuilder;
import compiler.lib.ir_framework.driver.irmatching.parser.VMInfo;
import compiler.lib.ir_framework.driver.network.testvm.java.VMInfo;
/**
* This class represents a generic {@link IR @IR} rule of an IR method. It contains a list of compile phase specific

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 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
@ -25,10 +25,10 @@ package compiler.lib.ir_framework.driver.irmatching.irrule.checkattribute.parsin
import compiler.lib.ir_framework.CompilePhase;
import compiler.lib.ir_framework.IRNode;
import compiler.lib.ir_framework.driver.SuccessOnlyConstraintException;
import compiler.lib.ir_framework.driver.network.testvm.java.VMInfo;
import compiler.lib.ir_framework.shared.Comparison;
import compiler.lib.ir_framework.shared.TestFormat;
import compiler.lib.ir_framework.driver.irmatching.parser.VMInfo;
import compiler.lib.ir_framework.driver.SuccessOnlyConstraintException;
import java.util.regex.Matcher;

View File

@ -27,12 +27,12 @@ import compiler.lib.ir_framework.CompilePhase;
import compiler.lib.ir_framework.IR;
import compiler.lib.ir_framework.IRNode;
import compiler.lib.ir_framework.driver.irmatching.irrule.constraint.Constraint;
import compiler.lib.ir_framework.driver.irmatching.parser.VMInfo;
import compiler.lib.ir_framework.driver.network.testvm.java.VMInfo;
/**
* Interface to represent a single raw constraint as found in the {@link IR @IR} annotation (i.e. {@link IRNode}
* placeholder strings are not replaced by regexes, yet). A raw constraint can be parsed into a {@link Constraint} by
* calling {@link #parse(CompilePhase, String)}. This replaces the IR node placeholder strings by actual regexes and
* calling {@link #parse(CompilePhase, String, VMInfo)}. This replaces the IR node placeholder strings by actual regexes and
* merges composite nodes together.
*
* @see Constraint

View File

@ -26,12 +26,11 @@ package compiler.lib.ir_framework.driver.irmatching.irrule.constraint.raw;
import compiler.lib.ir_framework.CompilePhase;
import compiler.lib.ir_framework.IR;
import compiler.lib.ir_framework.IRNode;
import compiler.lib.ir_framework.TestFramework;
import compiler.lib.ir_framework.driver.irmatching.irrule.checkattribute.parsing.RawIRNode;
import compiler.lib.ir_framework.driver.irmatching.irrule.constraint.Constraint;
import compiler.lib.ir_framework.driver.irmatching.parser.VMInfo;
import compiler.lib.ir_framework.driver.SuccessOnlyConstraintException;
import compiler.lib.ir_framework.driver.network.testvm.java.VMInfo;
import compiler.lib.ir_framework.shared.Comparison;
import compiler.lib.ir_framework.shared.TestFormat;
import compiler.lib.ir_framework.shared.TestFormatException;

View File

@ -29,7 +29,7 @@ import compiler.lib.ir_framework.TestFramework;
import compiler.lib.ir_framework.driver.SuccessOnlyConstraintException;
import compiler.lib.ir_framework.driver.irmatching.irrule.checkattribute.parsing.RawIRNode;
import compiler.lib.ir_framework.driver.irmatching.irrule.constraint.Constraint;
import compiler.lib.ir_framework.driver.irmatching.parser.VMInfo;
import compiler.lib.ir_framework.driver.network.testvm.java.VMInfo;
import compiler.lib.ir_framework.shared.Comparison;
/**

View File

@ -34,7 +34,7 @@ import compiler.lib.ir_framework.driver.irmatching.irrule.checkattribute.parsing
import compiler.lib.ir_framework.driver.irmatching.irrule.checkattribute.parsing.RawFailOn;
import compiler.lib.ir_framework.driver.irmatching.irrule.constraint.Constraint;
import compiler.lib.ir_framework.driver.irmatching.irrule.constraint.raw.RawConstraint;
import compiler.lib.ir_framework.driver.irmatching.parser.VMInfo;
import compiler.lib.ir_framework.driver.network.testvm.java.VMInfo;
import compiler.lib.ir_framework.shared.TestFormat;
import java.util.*;

View File

@ -31,7 +31,7 @@ import compiler.lib.ir_framework.driver.irmatching.irrule.checkattribute.Counts;
import compiler.lib.ir_framework.driver.irmatching.irrule.checkattribute.FailOn;
import compiler.lib.ir_framework.driver.irmatching.irrule.constraint.Constraint;
import compiler.lib.ir_framework.driver.irmatching.irrule.constraint.raw.RawConstraint;
import compiler.lib.ir_framework.driver.irmatching.parser.VMInfo;
import compiler.lib.ir_framework.driver.network.testvm.java.VMInfo;
import compiler.lib.ir_framework.shared.TestFrameworkException;
import java.util.ArrayList;
@ -71,7 +71,7 @@ class DefaultPhaseRawConstraintParser {
for (RawConstraint rawConstraint : rawConstraints) {
CompilePhase compilePhase = rawConstraint.defaultCompilePhase();
List<Constraint> checkAttribute =
matchableForCompilePhase.computeIfAbsent(compilePhase, k -> new ArrayList<>());
matchableForCompilePhase.computeIfAbsent(compilePhase, _ -> new ArrayList<>());
checkAttribute.add(rawConstraint.parse(compilePhase, compilation.output(compilePhase), vmInfo));
}
return replaceConstraintsWithCheckAttribute(matchableForCompilePhase, checkAttributeType);
@ -113,7 +113,7 @@ class DefaultPhaseRawConstraintParser {
private static void addCheckAttribute(Map<CompilePhase, Matchable> failOnForCompilePhase,
Map<CompilePhase, List<Matchable>> result) {
failOnForCompilePhase.forEach((compilePhase, matchable) -> {
List<Matchable> list = result.computeIfAbsent(compilePhase, k -> new ArrayList<>());
List<Matchable> list = result.computeIfAbsent(compilePhase, _ -> new ArrayList<>());
list.add(matchable);
});
}

View File

@ -25,16 +25,12 @@ package compiler.lib.ir_framework.driver.irmatching.parser;
import compiler.lib.ir_framework.IR;
import compiler.lib.ir_framework.TestFramework;
import compiler.lib.ir_framework.driver.irmatching.parser.hotspot.HotSpotPidFileParser;
import compiler.lib.ir_framework.driver.network.testvm.java.ApplicableIRRules;
import compiler.lib.ir_framework.driver.network.testvm.java.IRRuleIds;
import compiler.lib.ir_framework.shared.TestFormat;
import compiler.lib.ir_framework.shared.TestFrameworkException;
import compiler.lib.ir_framework.test.ApplicableIRRulesPrinter;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@ -55,73 +51,19 @@ public class ApplicableIRRulesParser {
* Parse the Applicable IR rules passed as parameter and return a "test name" -> TestMethod map that contains an
* entry for each method that needs to be IR matched on.
*/
public TestMethods parse(String applicableIRRules) {
createTestMethodMap(applicableIRRules, testClass);
public TestMethods parse(ApplicableIRRules applicableIRRules) {
createTestMethodMap(applicableIRRules);
// We could have found format errors in @IR annotations. Report them now with an exception.
TestFormat.throwIfAnyFailures();
return new TestMethods(testMethods);
}
/**
* Sets up a map testname -> TestMethod map. The TestMethod object will later be filled with the ideal and opto
* assembly output in {@link HotSpotPidFileParser}.
*/
private void createTestMethodMap(String applicableIRRules, Class<?> testClass) {
Map<String, IRRuleIds> irRulesMap = parseApplicableIRRules(applicableIRRules);
createTestMethodsWithApplicableIRRules(testClass, irRulesMap);
}
/**
* Read the Applicable IR Rules emitted by the Test VM to decide if an @IR rule must be checked for a method.
*/
private Map<String, IRRuleIds> parseApplicableIRRules(String applicableIRRules) {
Map<String, IRRuleIds> irRulesMap = new HashMap<>();
String[] applicableIRRulesLines = getApplicableIRRulesLines(applicableIRRules);
for (String s : applicableIRRulesLines) {
String line = s.trim();
String[] splitLine = line.split(",");
if (splitLine.length < 2) {
throw new TestFrameworkException("Invalid Applicable IR Rules format. No comma found: " + splitLine[0]);
}
String testName = splitLine[0];
IRRuleIds irRuleIds = parseIrRulesIds(splitLine);
irRulesMap.put(testName, irRuleIds);
}
return irRulesMap;
}
/**
* Parse the Applicable IR Rules lines without header, explanation line and footer and return them in an array.
*/
private String[] getApplicableIRRulesLines(String applicableIRRules) {
if (applicableIRRules.isEmpty()) {
// Nothing to IR match.
return new String[0];
}
return applicableIRRules.split("\\R");
}
/**
* Parse rule indexes from a single line of the Applicable IR Rules in the format: <method,idx1,idx2,...>
*/
private IRRuleIds parseIrRulesIds(String[] splitLine) {
List<Integer> irRuleIds = new ArrayList<>();
for (int i = 1; i < splitLine.length; i++) {
try {
irRuleIds.add(Integer.parseInt(splitLine[i]));
} catch (NumberFormatException e) {
throw new TestFrameworkException("Invalid Applicable IR Rules format. No number found: " + splitLine[i]);
}
}
return new IRRuleIds(irRuleIds);
}
private void createTestMethodsWithApplicableIRRules(Class<?> testClass, Map<String, IRRuleIds> irRulesMap) {
private void createTestMethodMap(ApplicableIRRules applicableIRRules) {
for (Method m : testClass.getDeclaredMethods()) {
IR[] irAnnos = m.getAnnotationsByType(IR.class);
if (irAnnos.length > 0) {
// Validation of legal @IR attributes and placement of the annotation was already done in Test VM.
IRRuleIds irRuleIds = irRulesMap.get(m.getName());
IRRuleIds irRuleIds = applicableIRRules.ruleIds(m.getName());
validateIRRuleIds(m, irAnnos, irRuleIds);
if (hasAnyApplicableIRRules(irRuleIds)) {
testMethods.put(m.getName(), new TestMethod(m, irAnnos, irRuleIds));
@ -131,10 +73,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_RULES)
&& irRuleIds.last() <= irAnnos.length,
TestFramework.check((irRuleIds.isEmpty() || (irRuleIds.first() >= 1 && irRuleIds.last() <= irAnnos.length)),
"Invalid IR rule index found in validIrRulesMap for " + m);
}
@ -142,6 +81,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_RULES;
return !irRuleIds.isEmpty();
}
}

View File

@ -32,6 +32,7 @@ import compiler.lib.ir_framework.driver.irmatching.irmethod.NotCompilableIRMetho
import compiler.lib.ir_framework.driver.irmatching.parser.hotspot.HotSpotPidFileParser;
import compiler.lib.ir_framework.driver.irmatching.parser.hotspot.LoggedMethod;
import compiler.lib.ir_framework.driver.irmatching.parser.hotspot.LoggedMethods;
import compiler.lib.ir_framework.driver.network.testvm.java.VMInfo;
import java.util.Map;
import java.util.SortedSet;

View File

@ -23,6 +23,7 @@
package compiler.lib.ir_framework.driver.irmatching.parser;
import compiler.lib.ir_framework.TestFramework;
import compiler.lib.ir_framework.driver.irmatching.Matchable;
import compiler.lib.ir_framework.driver.irmatching.NonIRTestClass;
import compiler.lib.ir_framework.driver.irmatching.TestClass;
@ -31,6 +32,8 @@ import compiler.lib.ir_framework.driver.irmatching.irmethod.IRMethodMatchable;
import compiler.lib.ir_framework.driver.irmatching.parser.hotspot.HotSpotPidFileParser;
import compiler.lib.ir_framework.driver.irmatching.parser.hotspot.LoggedMethods;
import compiler.lib.ir_framework.driver.network.TestVMData;
import compiler.lib.ir_framework.driver.network.testvm.java.ApplicableIRRules;
import compiler.lib.ir_framework.driver.network.testvm.java.VMInfo;
import compiler.lib.ir_framework.shared.TestFormat;
import java.util.SortedSet;
@ -55,19 +58,20 @@ public class TestClassParser {
* Return a default/empty TestClass object if there are no applicable @IR rules in any method of the test class.
*/
public Matchable parse(TestVMData testVmData) {
ApplicableIRRules applicableIrRules = testVmData.applicableIRRules();
if (applicableIrRules.hasNoMethods()) {
return new NonIRTestClass();
}
ApplicableIRRulesParser applicableIRRulesParser = new ApplicableIRRulesParser(testClass);
TestMethods testMethods = applicableIRRulesParser.parse(testVmData.applicableIRRules());
VMInfo vmInfo = VMInfoParser.parseVMInfo(testVmData.vmInfo());
if (testMethods.hasTestMethods()) {
HotSpotPidFileParser hotSpotPidFileParser = new HotSpotPidFileParser(testClass.getName(), testMethods);
LoggedMethods loggedMethods = hotSpotPidFileParser.parse(testVmData.hotspotPidFileName());
return createTestClass(testMethods, loggedMethods, vmInfo);
}
return new NonIRTestClass();
TestFramework.check(testMethods.hasTestMethods(), "must have at least one");
HotSpotPidFileParser hotSpotPidFileParser = new HotSpotPidFileParser(testClass.getName(), testMethods);
LoggedMethods loggedMethods = hotSpotPidFileParser.parse(testVmData.hotspotPidFileName());
return createTestClass(testMethods, loggedMethods, testVmData.vmInfo());
}
/**
* Create test class with IR methods for all test methods identified by {@link ApplicableIRRulesParser} by combining them
* Create test class with IR methods for all test methods found in {@link ApplicableIRRules} by combining them
* with the parsed compilation output from {@link HotSpotPidFileParser}.
*/
private Matchable createTestClass(TestMethods testMethods, LoggedMethods loggedMethods, VMInfo vmInfo) {

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) 2023, 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.irmatching.parser;
import compiler.lib.ir_framework.shared.TestFrameworkException;
import java.util.HashMap;
import java.util.Map;
/**
* Class to parse the VMInfo emitted by the Test VM and creating {@link VMInfo} objects for each entry.
*
* @see VMInfo
*/
public class VMInfoParser {
/**
* Create a new VMInfo object from the vmInfo string.
*/
public static VMInfo parseVMInfo(String vmInfo) {
Map<String, String> map = new HashMap<>();
String[] lines = getVMInfoLines(vmInfo);
for (String s : lines) {
String line = s.trim();
String[] splitLine = line.split(":", 2);
if (splitLine.length != 2) {
throw new TestFrameworkException("Invalid VMInfo key:value encoding. Found: " + splitLine[0]);
}
String key = splitLine[0];
String value = splitLine[1];
map.put(key, value);
}
return new VMInfo(map);
}
/**
* Extract the VMInfo from the applicableIRRules string, strip away the header and return the individual key-value lines.
*/
private static String[] getVMInfoLines(String vmInfo) {
if (vmInfo.isEmpty()) {
// Nothing to IR match.
return new String[0];
}
return vmInfo.split("\\R");
}
}

View File

@ -24,7 +24,9 @@
package compiler.lib.ir_framework.driver.network;
import compiler.lib.ir_framework.driver.irmatching.IRMatcher;
import compiler.lib.ir_framework.driver.network.testvm.java.ApplicableIRRules;
import compiler.lib.ir_framework.driver.network.testvm.java.JavaMessages;
import compiler.lib.ir_framework.driver.network.testvm.java.VMInfo;
import compiler.lib.ir_framework.shared.TestFrameworkSocket;
/**
@ -42,11 +44,11 @@ public class TestVMData {
this.allowNotCompilable = allowNotCompilable;
}
public String applicableIRRules() {
public ApplicableIRRules applicableIRRules() {
return javaMessages.applicableIRRules();
}
public String vmInfo() {
public VMInfo vmInfo() {
return javaMessages.vmInfo();
}

View File

@ -0,0 +1,81 @@
/*
* 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.IR;
import compiler.lib.ir_framework.TestFramework;
import compiler.lib.ir_framework.driver.irmatching.IRMatcher;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Class to hold the Applicable IR Rules sent by the Test VM. It specifies which {@link IR @IR} rules the
* {@link IRMatcher} need to check. This can be different depending on the used VM flags or the machine the test is run
* on itself.
*/
public class ApplicableIRRules implements JavaMessage {
private static final boolean PRINT_APPLICABLE_IR_RULES =
Boolean.parseBoolean(System.getProperty("PrintApplicableIRRules", "false"))
|| TestFramework.VERBOSE;
private final Map<String, IRRuleIds> methods;
public ApplicableIRRules() {
this.methods = new LinkedHashMap<>();
}
public void add(String method, IRRuleIds irRuleIds) {
methods.put(method, irRuleIds);
}
public IRRuleIds ruleIds(String methodName) {
return methods.computeIfAbsent(methodName, _ -> IRRuleIds.createEmpty());
}
public boolean hasNoMethods() {
return methods.isEmpty();
}
@Override
public void print() {
if (!PRINT_APPLICABLE_IR_RULES) {
return;
}
System.out.println();
System.out.println("Applicable IR Rules");
System.out.println("-------------------");
if (methods.isEmpty()) {
System.out.println("<none>");
return;
}
for (var entry : methods.entrySet()) {
String method = entry.getKey();
String ruleIds = entry.getValue().stream().map(String::valueOf).collect(Collectors.joining(", "));
System.out.println("- " + method + ": " + ruleIds);
}
}
}

View File

@ -49,6 +49,10 @@ public class IRRuleIds implements Iterable<Integer> {
return ruleIds.getLast();
}
public static IRRuleIds createEmpty() {
return new IRRuleIds(new ArrayList<>());
}
public boolean isEmpty() {
return ruleIds.isEmpty();
}

View File

@ -24,6 +24,9 @@
package compiler.lib.ir_framework.driver.network.testvm.java;
import compiler.lib.ir_framework.TestFramework;
import compiler.lib.ir_framework.driver.network.testvm.java.multiline.ApplicableIRRulesStrategy;
import compiler.lib.ir_framework.driver.network.testvm.java.multiline.MultiLineParser;
import compiler.lib.ir_framework.driver.network.testvm.java.multiline.VMInfoStrategy;
import compiler.lib.ir_framework.shared.TestFrameworkException;
import compiler.lib.ir_framework.test.network.MessageTag;
@ -43,18 +46,18 @@ public class JavaMessageParser {
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 final MultiLineParser<VMInfo> vmInfoParser;
private final MultiLineParser<ApplicableIRRules> applicableIRRulesParser;
private StringBuilder currentBuilder;
private MultiLineParser<? extends JavaMessage> currentMultiLineParser;
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;
this.vmInfoParser = new MultiLineParser<>(new VMInfoStrategy());
this.applicableIRRulesParser = new MultiLineParser<>(new ApplicableIRRulesStrategy());
this.currentMultiLineParser = null;
}
public void parseLine(String line) {
@ -74,12 +77,11 @@ public class JavaMessageParser {
return;
}
// Multi-line message for single tag.
currentBuilder.append(line).append(System.lineSeparator());
currentMultiLineParser.parseLine(line);
}
private void assertNoActiveParser() {
TestFramework.check(currentBuilder == null, "Unexpected new tag while parsing block");
TestFramework.check(currentMultiLineParser == null, "Unexpected new tag while parsing block");
}
private void parseTagLine(Matcher tagLineMatcher) {
@ -89,8 +91,8 @@ public class JavaMessageParser {
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;
case VM_INFO -> currentMultiLineParser = vmInfoParser;
case APPLICABLE_IR_RULES -> currentMultiLineParser = applicableIRRulesParser;
default -> throw new TestFrameworkException("unknown tag");
}
}
@ -108,18 +110,19 @@ public class JavaMessageParser {
}
private void assertActiveParser() {
TestFramework.check(currentBuilder != null, "Received non-tag line outside of any tag block");
TestFramework.check(currentMultiLineParser != null, "Received non-tag line outside of any tag block");
}
private void parseEndTag() {
currentBuilder = null;
currentMultiLineParser.markFinished();
currentMultiLineParser = null;
}
public JavaMessages output() {
return new JavaMessages(new StdoutMessages(stdoutMessages),
new ExecutedTests(executedTests),
new MethodTimes(methodTimes),
applicableIrRules.toString(),
vmInfoBuilder.toString());
applicableIRRulesParser.output(),
vmInfoParser.output());
}
}

View File

@ -23,22 +23,18 @@
package compiler.lib.ir_framework.driver.network.testvm.java;
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 static final boolean PRINT_APPLICABLE_IR_RULES = Boolean.parseBoolean(System.getProperty("PrintApplicableIRRules", "false"));
private final StdoutMessages stdoutMessages;
private final ExecutedTests executedTests;
private final MethodTimes methodTimes;
private final String applicableIrRules;
private final String vmInfo;
private final ApplicableIRRules applicableIrRules;
private final VMInfo vmInfo;
JavaMessages(StdoutMessages stdoutMessages, ExecutedTests executedTests, MethodTimes methodTimes,
String applicableIrRules, String vmInfo) {
ApplicableIRRules applicableIrRules, VMInfo vmInfo) {
this.stdoutMessages = stdoutMessages;
this.executedTests = executedTests;
this.methodTimes = methodTimes;
@ -46,21 +42,19 @@ public class JavaMessages {
this.vmInfo = vmInfo;
}
public String applicableIRRules() {
return applicableIrRules;
public VMInfo vmInfo() {
return vmInfo;
}
public String vmInfo() {
return vmInfo;
public ApplicableIRRules applicableIRRules() {
return applicableIrRules;
}
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);
}
vmInfo.print();
applicableIrRules.print();
}
}

View File

@ -21,7 +21,7 @@
* questions.
*/
package compiler.lib.ir_framework.driver.irmatching.parser;
package compiler.lib.ir_framework.driver.network.testvm.java;
import compiler.lib.ir_framework.TestFramework;
import compiler.lib.ir_framework.shared.TestFrameworkException;
@ -32,31 +32,27 @@ import java.util.regex.Pattern;
/**
* This class stores the key value mapping from the VMInfo.
*
* @see ApplicableIRRulesParser
*/
public class VMInfo {
public class VMInfo implements JavaMessage {
private static final Pattern CPU_SKYLAKE_PATTERN =
Pattern.compile("family 6 model 85 stepping (\\d+) ");
/**
* Stores the key-value mapping.
*/
private final Map<String, String> keyValueMap;
private static final Pattern CPU_SKYLAKE_PATTERN =
Pattern.compile("family 6 model 85 stepping (\\d+) ");
public VMInfo(Map<String, String> map) {
this.keyValueMap = map;
TestFramework.check(isKey("cpuFeatures"), "VMInfo does not contain cpuFeatures");
TestFramework.check(isKey("MaxVectorSize"), "VMInfo does not contain MaxVectorSize");
TestFramework.check(isKey("MaxVectorSizeIsDefault"), "VMInfo does not contain MaxVectorSizeIsDefault");
TestFramework.check(isKey("LoopMaxUnroll"), "VMInfo does not contain LoopMaxUnroll");
TestFramework.check(isKey("UseAVX"), "VMInfo does not contain UseAVX");
TestFramework.check(isKey("UseAVXIsDefault"), "VMInfo does not contain UseAVXIsDefault");
public VMInfo(Map<String, String> keyValueMap) {
this.keyValueMap = keyValueMap;
}
public String getStringValue(String key) {
TestFramework.check(isKey(key), "VMInfo does not contain \"" + key + "\"");
public boolean hasCPUFeature(String feature) {
String features = getStringValue("cpuFeatures") + ",";
return features.contains(" " + feature + ",");
}
private String getStringValue(String key) {
TestFramework.check(keyValueMap.containsKey(key), "VMInfo does not contain \"" + key + "\"");
return keyValueMap.get(key);
}
@ -68,28 +64,6 @@ public class VMInfo {
}
}
public boolean hasCPUFeature(String feature) {
String features = getStringValue("cpuFeatures") + ",";
return features.contains(" " + feature + ",");
}
public boolean isCascadeLake() {
Matcher matcher = CPU_SKYLAKE_PATTERN.matcher(getStringValue("cpuFeatures"));
if (!matcher.find()) {
return false; // skylake pattern not found
}
String stepping = matcher.group(1).trim();
return Long.parseLong(stepping) >= 5; // this makes it Cascade Lake
}
public boolean isDefaultCascadeLake() {
// See VM_Version::is_default_intel_cascade_lake
return isCascadeLake() &&
getLongValue("MaxVectorSizeIsDefault") == 1 &&
getLongValue("UseAVXIsDefault") == 1 &&
getLongValue("UseAVX") > 2;
}
/**
* Some platforms do not behave as expected, and one cannot trust that the vectors
* make use of the full MaxVectorSize. For Cascade Lake, we only use 32 bytes for
@ -101,7 +75,36 @@ public class VMInfo {
return !isDefaultCascadeLake();
}
public boolean isKey(String key) {
return keyValueMap.containsKey(key);
private boolean isDefaultCascadeLake() {
// See VM_Version::is_default_intel_cascade_lake
return isCascadeLake() &&
getLongValue("MaxVectorSizeIsDefault") == 1 &&
getLongValue("UseAVXIsDefault") == 1 &&
getLongValue("UseAVX") > 2;
}
private boolean isCascadeLake() {
Matcher matcher = CPU_SKYLAKE_PATTERN.matcher(getStringValue("cpuFeatures"));
if (!matcher.find()) {
return false; // skylake pattern not found
}
String stepping = matcher.group(1).trim();
return Long.parseLong(stepping) >= 5; // this makes it Cascade Lake
}
@Override
public void print() {
if (!TestFramework.VERBOSE) {
return;
}
System.out.println();
System.out.println("VM Info");
System.out.println("--------");
for (var entry : keyValueMap.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println("- Key: " + key + ", Value: " + value);
}
}
}

View File

@ -0,0 +1,78 @@
/*
* 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.multiline;
import compiler.lib.ir_framework.driver.network.testvm.java.ApplicableIRRules;
import compiler.lib.ir_framework.driver.network.testvm.java.IRRuleIds;
import compiler.lib.ir_framework.shared.TestFrameworkException;
import compiler.lib.ir_framework.test.ApplicableIRRulesPrinter;
import java.util.ArrayList;
import java.util.List;
/**
* Dedicated strategy to parse the multi-line Applicable IR Rules message into a new {@link ApplicableIRRules} object.
*/
public class ApplicableIRRulesStrategy implements MultiLineParsingStrategy<ApplicableIRRules> {
private final ApplicableIRRules applicableIrRules;
public ApplicableIRRulesStrategy() {
this.applicableIrRules = new ApplicableIRRules();
}
@Override
public void parseLine(String line) {
if (line.equals(ApplicableIRRulesPrinter.NO_RULES)) {
return;
}
String[] splitLine = line.split(",");
if (splitLine.length < 2) {
throw new TestFrameworkException("Invalid Applicable IR Rules format. No comma found: " + splitLine[0]);
}
String testName = splitLine[0];
IRRuleIds irRulesIds = parseIrRulesIds(splitLine);
applicableIrRules.add(testName, irRulesIds);
}
/**
* Parse rule indexes from a single line of the Applicable IR Rules in the format: <method,idx1,idx2,...>
*/
private IRRuleIds parseIrRulesIds(String[] splitLine) {
List<Integer> irRuleIds = new ArrayList<>();
for (int i = 1; i < splitLine.length; i++) {
try {
irRuleIds.add(Integer.parseInt(splitLine[i]));
} catch (NumberFormatException e) {
throw new TestFrameworkException("Invalid Applicable IR Rules format. No number found: " + splitLine[i]);
}
}
return new IRRuleIds(irRuleIds);
}
@Override
public ApplicableIRRules output() {
return applicableIrRules;
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.multiline;
import compiler.lib.ir_framework.TestFramework;
import compiler.lib.ir_framework.driver.network.testvm.java.JavaMessage;
import compiler.lib.ir_framework.test.network.MessageTag;
/**
* Generic multi-line parser that takes a {@link MultiLineParsingStrategy} to decide how to parse a single line of
* a multi line {@link JavaMessage}. Once parsing is done, the strategy is queried for the final parsed output.
*/
public class MultiLineParser<Output extends JavaMessage> {
private enum ParserState {
NOTHING_PARSED, PARSING, FINISHED_PARSING
}
private ParserState parserState;
private final MultiLineParsingStrategy<Output> multiLineParsingStrategy;
public MultiLineParser(MultiLineParsingStrategy<Output> multiLineParsingStrategy) {
this.multiLineParsingStrategy = multiLineParsingStrategy;
this.parserState = ParserState.NOTHING_PARSED;
}
public void parseLine(String line) {
TestFramework.check(parserState != ParserState.FINISHED_PARSING,
"cannot parse another block");
parserState = ParserState.PARSING;
multiLineParsingStrategy.parseLine(line);
}
/**
* Once the {@link MessageTag#END_MARKER} was seen, this method is called to mark the end of this multi-line message.
*/
public void markFinished() {
TestFramework.check(parserState == ParserState.PARSING,
"nothing parsed, cannot have empty block");
parserState = ParserState.FINISHED_PARSING;
}
public Output output() {
TestFramework.check(parserState != ParserState.PARSING, "either nothing parsed or finished");
return multiLineParsingStrategy.output();
}
}

View File

@ -0,0 +1,32 @@
/*
* 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.multiline;
/**
* Interface to define a strategy to parse a line in a {@link MultiLineParser}.
*/
public interface MultiLineParsingStrategy<Output> {
void parseLine(String line);
Output output();
}

View File

@ -0,0 +1,57 @@
/*
* 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.multiline;
import compiler.lib.ir_framework.driver.network.testvm.java.VMInfo;
import compiler.lib.ir_framework.shared.TestFrameworkException;
import java.util.HashMap;
import java.util.Map;
/**
* Dedicated strategy to parse the multi-line VM info message into a new {@link VMInfo} object.
*/
public class VMInfoStrategy implements MultiLineParsingStrategy<VMInfo> {
private final Map<String, String> keyValueMap;
public VMInfoStrategy() {
this.keyValueMap = new HashMap<>();
}
@Override
public void parseLine(String line) {
String[] splitLine = line.split(":", 2);
if (splitLine.length != 2) {
throw new TestFrameworkException("Invalid VmInfo key:value encoding. Found: " + splitLine[0]);
}
String key = splitLine[0];
String value = splitLine[1];
keyValueMap.put(key, value);
}
@Override
public VMInfo output() {
return new VMInfo(keyValueMap);
}
}

View File

@ -47,7 +47,7 @@ import java.util.function.Function;
* termination of the Test VM. IR rule indices start at 1.
*/
public class ApplicableIRRulesPrinter {
public static final int NO_RULES = -1;
public static final String NO_RULES = "<no IR rules>";
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
private static final List<Function<String, Object>> LONG_GETTERS = Arrays.asList(
@ -155,17 +155,15 @@ public class ApplicableIRRulesPrinter {
i++;
}
}
if (irAnnos.length != 0) {
output.append(m.getName());
if (validRules.isEmpty()) {
output.append("," + NO_RULES);
} else {
for (i = 0; i < validRules.size(); i++) {
output.append(",").append(validRules.get(i));
}
}
output.append(System.lineSeparator());
if (irAnnos.length == 0 || validRules.isEmpty()) {
return;
}
output.append(m.getName());
for (i = 0; i < validRules.size(); i++) {
output.append(",").append(validRules.get(i));
}
output.append(System.lineSeparator());
}
private void printDisableReason(String method, String reason, String[] apply, int ruleIndex, int ruleMax) {
@ -520,9 +518,10 @@ public class ApplicableIRRulesPrinter {
}
public void emit() {
if (output.isEmpty()) {
output.append(NO_RULES).append(System.lineSeparator());
}
output.append(MessageTag.END_MARKER);
TestVmSocket.sendMultiLine(MessageTag.APPLICABLE_IR_RULES, output.toString());
}
}

View File

@ -329,7 +329,7 @@ public class TestIRMatching {
System.out.flush();
String output = baos.toString();
findIrIds(output, "testMatchAllIf50", 1, 22);
findIrIds(output, "testMatchNoneIf50", -1, -1);
assertNoIds(output, "testMatchNoneIf50");
runWithArguments(FlagComparisons.class, "-XX:TLABRefillWasteFraction=49");
System.out.flush();
@ -431,12 +431,14 @@ public class TestIRMatching {
private static void findIrIds(String output, String method, int... numbers) {
StringBuilder builder = new StringBuilder();
builder.append(method);
builder.append(method).append(": ");
for (int i = 0; i < numbers.length; i+=2) {
int start = numbers[i];
int endIncluded = numbers[i + 1];
for (int j = start; j <= endIncluded; j++) {
builder.append(",");
if (j != numbers[0]) {
builder.append(", ");
}
builder.append(j);
}
}
@ -445,6 +447,13 @@ public class TestIRMatching {
System.lineSeparator()));
}
}
private static void assertNoIds(String output, String methodName) {
String applicableIRRules = output.split("Applicable IR Rules")[1];
if (applicableIRRules.contains(methodName)) {
addException(new RuntimeException("Should not find ids for \"" + methodName + "\"" + System.lineSeparator()));
}
}
}
class AndOr1 {