Skip to content

Commit

Permalink
8284115: [IR Framework] Compilation is not found due to rare safepoin…
Browse files Browse the repository at this point in the history
…t while dumping PrintIdeal/PrintOptoAssembly

Backport-of: 39842538004c5fca57701070484c78cacf95ed64
  • Loading branch information
GoeLin committed Jan 30, 2023
1 parent 4a9bd23 commit 4be1ed4
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 51 deletions.
Expand Up @@ -25,16 +25,20 @@

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.
*/
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() {
Expand All @@ -48,4 +52,37 @@ public boolean readLine() throws IOException {
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='");
}
}
@@ -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;
}
}
Expand Up @@ -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);
}

/**
Expand Down
Expand Up @@ -25,27 +25,36 @@

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);
}

/**
Expand Down
Expand Up @@ -56,6 +56,7 @@ public HotSpotPidFileParser(String testClass) {
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).
Expand All @@ -75,18 +76,28 @@ private void processFileLines(String hotspotPidFileName) throws IOException {
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)) {
Expand All @@ -101,6 +112,9 @@ private String parseMethodName(String line) {
return matcher.group(2);
}

/**
* Is this a @Test method?
*/
private boolean isTestAnnotatedMethod(String testMethodName) {
return compilationsMap.containsKey(testMethodName);
}
Expand All @@ -109,8 +123,6 @@ private IRMethod getIrMethod(String testMethodName) {
return compilationsMap.get(testMethodName);
}



private int getCompileId(String line) {
Matcher matcher = COMPILE_ID_PATTERN.matcher(line);
if (!matcher.find()) {
Expand All @@ -119,6 +131,9 @@ private int getCompileId(String line) {
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);
}
Expand Down
Expand Up @@ -31,44 +31,8 @@
* 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);
}

/**
Expand Down

1 comment on commit 4be1ed4

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.