8284115: [IR Framework] Compilation is not found due to rare safepoint while dumping PrintIdeal/PrintOptoAssembly

Reviewed-by: kvn, thartmann
This commit is contained in:
Christian Hagedorn 2022-05-17 11:23:11 +00:00
parent b434b1f233
commit 3984253800
6 changed files with 120 additions and 51 deletions

View File

@ -25,6 +25,8 @@ package compiler.lib.ir_framework.driver.irmatching.parser;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Base class of a read line from the hotspot_pid* file.
@ -32,9 +34,11 @@ import java.io.IOException;
abstract class AbstractLine {
private final BufferedReader reader;
protected String line;
private final Pattern compileIdPatternForTestClass;
public AbstractLine(BufferedReader reader) {
public AbstractLine(BufferedReader reader, Pattern compileIdPatternForTestClass) {
this.reader = reader;
this.compileIdPatternForTestClass = compileIdPatternForTestClass;
}
public String getLine() {
@ -48,4 +52,37 @@ abstract class AbstractLine {
line = reader.readLine();
return line != null;
}
/**
* Is this line a start of a method in the test class? We only care about test class entries. There might be non-class
* entries as well if the user specified additional compile commands. Ignore these.
*/
public boolean isTestClassCompilation() {
if (isCompilation()) {
Matcher matcher = compileIdPatternForTestClass.matcher(line);
return matcher.find();
}
return false;
}
/**
* Is this header a C2 non-OSR compilation header entry?
*/
public boolean isCompilation() {
return line.startsWith("<task_queued") && notOSRCompilation() && notC2Compilation();
}
/**
* OSR compilations have compile_kind set.
*/
protected boolean notOSRCompilation() {
return !line.contains("compile_kind='");
}
/**
* Non-C2 compilations have level set.
*/
private boolean notC2Compilation() {
return !line.contains("level='");
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2022, 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 java.util.List;
/**
* Class representing a PrintIdeal or PrintOptoAssembly output block read from the hotspot_pid* file.
*/
record Block(String output, List<String> testClassCompilations) {
public String getOutput() {
return output;
}
public boolean containsTestClassCompilations() {
return !testClassCompilations.isEmpty();
}
public List<String> getTestClassCompilations() {
return testClassCompilations;
}
}

View File

@ -24,14 +24,15 @@
package compiler.lib.ir_framework.driver.irmatching.parser;
import java.io.BufferedReader;
import java.util.regex.Pattern;
/**
* Class representing a block line inside a PrintIdeal or PrintOptoAssembly output block read from the hotspot_pid* file.
*/
class BlockLine extends AbstractLine {
public BlockLine(BufferedReader reader) {
super(reader);
public BlockLine(BufferedReader reader, Pattern compileIdPatternForTestClass) {
super(reader, compileIdPatternForTestClass);
}
/**

View File

@ -25,27 +25,36 @@ package compiler.lib.ir_framework.driver.irmatching.parser;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
/**
* Class to read all lines of a PrintIdeal or PrintOptoAssembly block.
*/
class BlockOutputReader {
private final BufferedReader reader;
private final BlockLine line;
public BlockOutputReader(BufferedReader reader) {
this.reader = reader;
public BlockOutputReader(BufferedReader reader, Pattern compileIdPatternForTestClass) {
this.line = new BlockLine(reader, compileIdPatternForTestClass);
}
/**
* Read all lines belonging to a PrintIdeal or PrintOptoAssembly output block.
*/
public String readBlock() throws IOException {
BlockLine line = new BlockLine(reader);
public Block readBlock() throws IOException {
StringBuilder builder = new StringBuilder();
List<String> testClassCompilations = new ArrayList<>();
while (line.readLine() && !line.isBlockEnd()) {
if (line.isTestClassCompilation()) {
// Could have safepointed while writing the block (see IRMatcher.SAFEPOINT_WHILE_PRINTING_MESSAGE)
// and enqueuing the next test class method for compilation during the interruption. Record this
// method to ensure that we read the PrintIdeal/PrintOptoAssembly blocks for that method later.
testClassCompilations.add(line.getLine());
}
builder.append(escapeXML(line.getLine())).append(System.lineSeparator());
}
return builder.toString();
return new Block(builder.toString(), testClassCompilations);
}
/**

View File

@ -56,6 +56,7 @@ class HotSpotPidFileParser {
public void setCompilationsMap(Map<String, IRMethod> compilationsMap) {
this.compilationsMap = compilationsMap;
}
/**
* Parse the hotspot_pid*.log file from the test VM. Read the PrintIdeal and PrintOptoAssembly outputs for all
* methods of the test class that need to be IR matched (found in compilations map).
@ -75,18 +76,28 @@ class HotSpotPidFileParser {
Map<Integer, IRMethod> compileIdMap = new HashMap<>();
try (var reader = Files.newBufferedReader(Paths.get(hotspotPidFileName))) {
Line line = new Line(reader, compileIdPatternForTestClass);
BlockOutputReader blockOutputReader = new BlockOutputReader(reader);
BlockOutputReader blockOutputReader = new BlockOutputReader(reader, compileIdPatternForTestClass);
while (line.readLine()) {
if (line.isTestClassCompilation()) {
parseTestMethodCompileId(compileIdMap, line.getLine());
} else if (isTestMethodBlockStart(line, compileIdMap)) {
String blockOutput = blockOutputReader.readBlock();
setIRMethodOutput(blockOutput, line, compileIdMap);
processMethodBlock(compileIdMap, line, blockOutputReader);
}
}
}
}
private void processMethodBlock(Map<Integer, IRMethod> compileIdMap, Line line, BlockOutputReader blockOutputReader)
throws IOException {
Block block = blockOutputReader.readBlock();
if (block.containsTestClassCompilations()) {
// Register all test method compilations that could have been emitted during a rare safepoint while
// dumping the PrintIdeal/PrintOptoAssembly output.
block.getTestClassCompilations().forEach(l -> parseTestMethodCompileId(compileIdMap, l));
}
setIRMethodOutput(block.getOutput(), line, compileIdMap);
}
private void parseTestMethodCompileId(Map<Integer, IRMethod> compileIdMap, String line) {
String methodName = parseMethodName(line);
if (isTestAnnotatedMethod(methodName)) {
@ -101,6 +112,9 @@ class HotSpotPidFileParser {
return matcher.group(2);
}
/**
* Is this a @Test method?
*/
private boolean isTestAnnotatedMethod(String testMethodName) {
return compilationsMap.containsKey(testMethodName);
}
@ -109,8 +123,6 @@ class HotSpotPidFileParser {
return compilationsMap.get(testMethodName);
}
private int getCompileId(String line) {
Matcher matcher = COMPILE_ID_PATTERN.matcher(line);
if (!matcher.find()) {
@ -119,6 +131,9 @@ class HotSpotPidFileParser {
return Integer.parseInt(matcher.group(1));
}
/**
* Is this line the start of a PrintIdeal/PrintOptoAssembly output block of a @Test method?
*/
private boolean isTestMethodBlockStart(Line line, Map<Integer, IRMethod> compileIdMap) {
return line.isBlockStart() && isTestClassMethodBlock(line, compileIdMap);
}

View File

@ -31,44 +31,8 @@ import java.util.regex.Pattern;
* Class representing a normal line read from the hotspot_pid* file.
*/
class Line extends AbstractLine {
private final Pattern compileIdPatternForTestClass;
public Line(BufferedReader reader, Pattern compileIdPatternForTestClass) {
super(reader);
this.compileIdPatternForTestClass = compileIdPatternForTestClass;
}
/**
* Is this line a start of a @Test annotated method? We only care about test class entries. There might be non-class
* entries as well if user specified additional compile commands. Ignore these.
*/
public boolean isTestClassCompilation() {
if (isCompilation()) {
Matcher matcher = compileIdPatternForTestClass.matcher(line);
return matcher.find();
}
return false;
}
/**
* Is this header a C2 non-OSR compilation header entry?
*/
public boolean isCompilation() {
return line.startsWith("<task_queued") && notOSRCompilation() && notC2Compilation();
}
/**
* OSR compilations have compile_kind set.
*/
private boolean notOSRCompilation() {
return !line.contains("compile_kind='");
}
/**
* Non-C2 compilations have level set.
*/
private boolean notC2Compilation() {
return !line.contains("level='");
super(reader, compileIdPatternForTestClass);
}
/**