8351952: [IR Framework]: allow ignoring methods that are not compilable

Co-authored-by: Christian Hagedorn <chagedorn@openjdk.org>
Reviewed-by: chagedorn, thartmann
This commit is contained in:
Emanuel Peter 2025-03-20 06:14:07 +00:00
parent 3ed010ab7c
commit fb210e3a71
17 changed files with 442 additions and 27 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2025, 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
@ -84,4 +84,12 @@ public @interface Test {
* available level which is usually {@link CompLevel#C2}.
*/
CompLevel compLevel() default CompLevel.ANY;
/**
* In rare cases, methods may not be compilable because of a compilation bailout. By default, this leads to a
* test failure. However, if such cases are expected in a specific test, this flag can be set to true, which
* allows the test to pass even if there is no compilation. Any associated {@link IR} rule is only executed
* if the test method was compiled, and else it is ignored silently.
*/
boolean allowNotCompilable() default false;
}

View File

@ -175,6 +175,7 @@ public class TestFramework {
private List<String> flags;
private int defaultWarmup = -1;
private boolean testClassesOnBootClassPath;
private boolean isAllowNotCompilable = false;
/*
* Public interface methods
@ -409,6 +410,19 @@ public class TestFramework {
return this;
}
/**
* In rare cases, methods may not be compilable because of a compilation bailout. By default, this leads to a
* test failure. However, if such cases are expected in multiple methods in a test class, this flag can be set to
* true, which allows any test to pass even if there is a compilation bailout. If only selected methods are prone
* to bail out, it is preferred to use {@link Test#allowNotCompilable()} instead for more fine-grained control.
* By setting this flag, any associated {@link IR} rule of a test is only executed if the test method was compiled,
* and else it is ignored silently.
*/
public TestFramework allowNotCompilable() {
this.isAllowNotCompilable = true;
return this;
}
/**
* Get the VM output of the test VM. Use {@code -DVerbose=true} to enable more debug information. If scenarios
* were run, use {@link Scenario#getTestVMOutput()}.
@ -773,10 +787,10 @@ public class TestFramework {
private void runTestVM(List<String> additionalFlags) {
TestVMProcess testVMProcess = new TestVMProcess(additionalFlags, testClass, helperClasses, defaultWarmup,
testClassesOnBootClassPath);
isAllowNotCompilable, testClassesOnBootClassPath);
if (shouldVerifyIR) {
try {
TestClassParser testClassParser = new TestClassParser(testClass);
TestClassParser testClassParser = new TestClassParser(testClass, isAllowNotCompilable);
Matchable testClassMatchable = testClassParser.parse(testVMProcess.getHotspotPidFileName(),
testVMProcess.getIrEncoding());
IRMatcher matcher = new IRMatcher(testClassMatchable);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2025, 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
@ -65,11 +65,12 @@ public class TestVMProcess {
private String irEncoding;
public TestVMProcess(List<String> additionalFlags, Class<?> testClass, Set<Class<?>> helperClasses, int defaultWarmup,
boolean testClassesOnBootClassPath) {
boolean allowNotCompilable, boolean testClassesOnBootClassPath) {
this.cmds = new ArrayList<>();
TestFrameworkSocket socket = new TestFrameworkSocket();
try (socket) {
prepareTestVMFlags(additionalFlags, socket, testClass, helperClasses, defaultWarmup, testClassesOnBootClassPath);
prepareTestVMFlags(additionalFlags, socket, testClass, helperClasses, defaultWarmup,
allowNotCompilable, testClassesOnBootClassPath);
start();
}
processSocketOutput(socket);
@ -93,7 +94,8 @@ public class TestVMProcess {
}
private void prepareTestVMFlags(List<String> additionalFlags, TestFrameworkSocket socket, Class<?> testClass,
Set<Class<?>> helperClasses, int defaultWarmup, boolean testClassesOnBootClassPath) {
Set<Class<?>> helperClasses, int defaultWarmup, boolean allowNotCompilable,
boolean testClassesOnBootClassPath) {
// Set java.library.path so JNI tests which rely on jtreg nativepath setting work
cmds.add("-Djava.library.path=" + Utils.TEST_NATIVE_PATH);
// Need White Box access in test VM.
@ -128,6 +130,10 @@ public class TestVMProcess {
cmds.add("-DWarmup=" + defaultWarmup);
}
if (allowNotCompilable) {
cmds.add("-DAllowNotCompilable=true");
}
cmds.add(TestVM.class.getName());
cmds.add(testClass.getName());
if (helperClasses != null) {

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2025, 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.irmethod;
import compiler.lib.ir_framework.IR;
import compiler.lib.ir_framework.Run;
import compiler.lib.ir_framework.RunMode;
import java.lang.reflect.Method;
/**
* This class represents a special IR method which was not compiled by the IR framework, but this was explicitly allowed
* by "allowNotCompilable". This happens when the compiler bails out of a compilation (i.e. no compilation) but we treat
* this as valid case. Any associated IR rules pass silently.
*
* @see IR
* @see Test
*/
public class NotCompilableIRMethod implements IRMethodMatchable {
private final Method method;
private final int ruleCount;
public NotCompilableIRMethod(Method method, int ruleCount) {
this.method = method;
this.ruleCount = ruleCount;
}
@Override
public String name() {
return method.getName();
}
/**
* Directly return a {@link NotCompilableIRMethodMatchResult} as we do not need to match IR rules individually.
*/
@Override
public NotCompilableIRMethodMatchResult match() {
return new NotCompilableIRMethodMatchResult(method, ruleCount);
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2025, 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.irmethod;
import compiler.lib.ir_framework.Run;
import compiler.lib.ir_framework.RunMode;
import compiler.lib.ir_framework.driver.irmatching.MatchResult;
import compiler.lib.ir_framework.driver.irmatching.visitor.MatchResultVisitor;
import java.lang.reflect.Method;
/**
* This class represents a special matching result of an IR method where the compilation output was completely empty,
* but this was exlicitly allowed by "allowNotCompilable". This happens when the compiler bails out of a compilation
* (i.e. no compilation) but we treat this as valid case. Any associated IR rules pass silently.
*
* @see NotCompilableIRMethod
* @see Test
*/
public class NotCompilableIRMethodMatchResult implements MatchResult {
private final Method method;
private final int failedIRRules;
public NotCompilableIRMethodMatchResult(Method method, int failedIRRules) {
this.method = method;
this.failedIRRules = failedIRRules;
}
@Override
public boolean fail() {
return false;
}
@Override
public void accept(MatchResultVisitor visitor) {
visitor.visitMethodNotCompilable(method, failedIRRules);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2025, 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
@ -23,10 +23,13 @@
package compiler.lib.ir_framework.driver.irmatching.parser;
import compiler.lib.ir_framework.Test;
import compiler.lib.ir_framework.TestFramework;
import compiler.lib.ir_framework.driver.irmatching.Compilation;
import compiler.lib.ir_framework.driver.irmatching.irmethod.IRMethod;
import compiler.lib.ir_framework.driver.irmatching.irmethod.IRMethodMatchable;
import compiler.lib.ir_framework.driver.irmatching.irmethod.NotCompiledIRMethod;
import compiler.lib.ir_framework.driver.irmatching.irmethod.NotCompilableIRMethod;
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;
@ -41,10 +44,12 @@ import java.util.TreeSet;
class IRMethodBuilder {
private final Map<String, LoggedMethod> loggedMethods;
private final TestMethods testMethods;
private final boolean allowNotCompilable;
public IRMethodBuilder(TestMethods testMethods, LoggedMethods loggedMethods) {
public IRMethodBuilder(TestMethods testMethods, LoggedMethods loggedMethods, boolean allowNotCompilable) {
this.testMethods = testMethods;
this.loggedMethods = loggedMethods.loggedMethods();
this.allowNotCompilable = allowNotCompilable;
}
/**
@ -64,7 +69,13 @@ class IRMethodBuilder {
return new IRMethod(testMethod.method(), testMethod.irRuleIds(), testMethod.irAnnos(),
new Compilation(loggedMethod.compilationOutput()), vmInfo);
} else {
return new NotCompiledIRMethod(testMethod.method(), testMethod.irRuleIds().length);
Test[] testAnnos = testMethod.method().getAnnotationsByType(Test.class);
boolean allowMethodNotCompilable = allowNotCompilable || testAnnos[0].allowNotCompilable();
if (allowMethodNotCompilable) {
return new NotCompilableIRMethod(testMethod.method(), testMethod.irRuleIds().length);
} else {
return new NotCompiledIRMethod(testMethod.method(), testMethod.irRuleIds().length);
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, 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
@ -42,9 +42,11 @@ import java.util.SortedSet;
*/
public class TestClassParser {
private final Class<?> testClass;
private final boolean allowNotCompilable;
public TestClassParser(Class<?> testClass) {
public TestClassParser(Class<?> testClass, boolean allowNotCompilable) {
this.testClass = testClass;
this.allowNotCompilable = allowNotCompilable;
}
/**
@ -68,7 +70,7 @@ public class TestClassParser {
* with the parsed compilation output from {@link HotSpotPidFileParser}.
*/
private Matchable createTestClass(TestMethods testMethods, LoggedMethods loggedMethods, VMInfo vmInfo) {
IRMethodBuilder irMethodBuilder = new IRMethodBuilder(testMethods, loggedMethods);
IRMethodBuilder irMethodBuilder = new IRMethodBuilder(testMethods, loggedMethods, allowNotCompilable);
SortedSet<IRMethodMatchable> irMethods = irMethodBuilder.build(vmInfo);
TestFormat.throwIfAnyFailures();
return new TestClass(irMethods);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, 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,6 +25,7 @@ package compiler.lib.ir_framework.driver.irmatching.report;
import compiler.lib.ir_framework.CompilePhase;
import compiler.lib.ir_framework.IR;
import compiler.lib.ir_framework.shared.TestFrameworkException;
import compiler.lib.ir_framework.driver.irmatching.MatchResult;
import compiler.lib.ir_framework.driver.irmatching.irrule.checkattribute.CheckAttributeType;
import compiler.lib.ir_framework.driver.irmatching.irrule.constraint.CountsConstraintFailure;
@ -121,6 +122,11 @@ public class CompilationOutputBuilder implements MatchResultVisitor {
output.append("<empty>").append(System.lineSeparator());
}
@Override
public void visitMethodNotCompilable(Method method, int failedIRRules) {
throw new TestFrameworkException("Sould not reach here");
}
@Override
public void visitIRRule(AcceptChildren acceptChildren, int irRuleId, IR irAnno) {
acceptChildren.accept(this);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, 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
@ -63,6 +63,11 @@ class FailCountVisitor implements MatchResultVisitor {
irRuleCount += failedIRRules;
}
@Override
public void visitMethodNotCompilable(Method method, int failedIRRules) {
irMethodCount++;
}
public int getIrRuleCount() {
return irRuleCount;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, 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,6 +25,7 @@ package compiler.lib.ir_framework.driver.irmatching.report;
import compiler.lib.ir_framework.CompilePhase;
import compiler.lib.ir_framework.IR;
import compiler.lib.ir_framework.shared.TestFrameworkException;
import compiler.lib.ir_framework.driver.irmatching.MatchResult;
import compiler.lib.ir_framework.driver.irmatching.irrule.checkattribute.CheckAttributeType;
import compiler.lib.ir_framework.driver.irmatching.irrule.constraint.CountsConstraintFailure;
@ -97,6 +98,10 @@ public class FailureMessageBuilder implements MatchResultVisitor {
indentation.sub();
}
public void visitMethodNotCompilable(Method method, int failedIRRules) {
throw new TestFrameworkException("Sould not reach here");
}
@Override
public void visitIRRule(AcceptChildren acceptChildren, int irRuleId, IR irAnno) {
indentation.add();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2025, 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
@ -39,6 +39,7 @@ public interface MatchResultVisitor {
void visitTestClass(AcceptChildren acceptChildren);
void visitIRMethod(AcceptChildren acceptChildren, Method method, int failedIRRules);
void visitMethodNotCompiled(Method method, int failedIRRules);
void visitMethodNotCompilable(Method method, int failedIRRules);
void visitIRRule(AcceptChildren acceptChildren, int irRuleId, IR irAnno);
void visitCompilePhaseIRRule(AcceptChildren acceptChildren, CompilePhase compilePhase, String compilationOutput);
void visitNoCompilePhaseCompilation(CompilePhase compilePhase);

View File

@ -44,6 +44,7 @@ public class TestFrameworkSocket implements AutoCloseable {
public static final String TESTLIST_TAG = "[TESTLIST]";
public static final String DEFAULT_REGEX_TAG = "[DEFAULT_REGEX]";
public static final String PRINT_TIMES_TAG = "[PRINT_TIMES]";
public static final String NOT_COMPILABLE_TAG = "[NOT_COMPILABLE]";
// Static fields used for test VM only.
private static final String SERVER_PORT_PROPERTY = "ir.framework.server.port";

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2025, 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
@ -32,6 +32,8 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import compiler.lib.ir_framework.shared.TestFrameworkSocket;
/**
* Abstract super class for base, checked and custom run tests.
*/
@ -109,7 +111,21 @@ abstract class AbstractTest {
abstract protected void compileTest();
private class MethodNotCompilableException extends Exception {}
protected void compileMethod(DeclaredTest test) {
try {
tryCompileMethod(test);
} catch (MethodNotCompilableException e) {
final Method testMethod = test.getTestMethod();
TestFrameworkSocket.write("Method not compilable: " + testMethod, TestFrameworkSocket.NOT_COMPILABLE_TAG, true);
TestRun.check(test.isAllowNotCompilable(),
"Method " + testMethod + " not compilable (anymore) at level " + test.getCompLevel() +
". Most likely, this is not expected, but if it is, you can use 'allowNotCompilable'.");
}
}
private void tryCompileMethod(DeclaredTest test) throws MethodNotCompilableException {
final Method testMethod = test.getTestMethod();
if (TestFramework.VERBOSE) {
System.out.println("Compile method " + testMethod + " after warm-up...");
@ -151,10 +167,11 @@ abstract class AbstractTest {
checkCompilationLevel(test);
}
private void enqueueMethodForCompilation(DeclaredTest test) {
private void enqueueMethodForCompilation(DeclaredTest test) throws MethodNotCompilableException {
final Method testMethod = test.getTestMethod();
TestRun.check(WHITE_BOX.isMethodCompilable(testMethod, test.getCompLevel().getValue(), false),
"Method " + testMethod + " not compilable (anymore) at level " + test.getCompLevel());
if (!WHITE_BOX.isMethodCompilable(testMethod, test.getCompLevel().getValue(), false)) {
throw new MethodNotCompilableException();
}
TestVM.enqueueForCompilation(testMethod, test.getCompLevel());
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2025, 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
@ -36,13 +36,15 @@ public class DeclaredTest {
private final ArgumentsProvider argumentsProvider;
private final int warmupIterations;
private final CompLevel compLevel;
private final boolean allowNotCompilable;
private Method attachedMethod;
public DeclaredTest(Method testMethod, ArgumentsProvider argumentsProvider, CompLevel compLevel, int warmupIterations) {
public DeclaredTest(Method testMethod, ArgumentsProvider argumentsProvider, CompLevel compLevel, int warmupIterations, boolean allowNotCompilable) {
// Make sure we can also call non-public or public methods in package private classes
testMethod.setAccessible(true);
this.testMethod = testMethod;
this.compLevel = compLevel;
this.allowNotCompilable = allowNotCompilable;
this.argumentsProvider = argumentsProvider;
this.warmupIterations = warmupIterations;
this.attachedMethod = null;
@ -60,6 +62,10 @@ public class DeclaredTest {
return warmupIterations;
}
public boolean isAllowNotCompilable() {
return allowNotCompilable;
}
public Object[] getArguments(Object invocationTarget, int invocationCounter) {
return argumentsProvider.getArguments(invocationTarget, invocationCounter);
}

View File

@ -75,6 +75,7 @@ public class TestVM {
*/
public static final int WARMUP_ITERATIONS = Integer.parseInt(System.getProperty("Warmup", "2000"));
private static final boolean ALLOW_METHOD_NOT_COMPILABLE = Boolean.getBoolean("AllowNotCompilable");
private static final boolean TIERED_COMPILATION = (Boolean)WHITE_BOX.getVMFlag("TieredCompilation");
private static final CompLevel TIERED_COMPILATION_STOP_AT_LEVEL;
private static final boolean CLIENT_VM = Platform.isClient();
@ -579,8 +580,9 @@ public class TestVM {
if (EXCLUDE_RANDOM) {
compLevel = compLevel.excludeCompilationRandomly(m);
}
boolean allowNotCompilable = testAnno.allowNotCompilable() || ALLOW_METHOD_NOT_COMPILABLE;
ArgumentsProvider argumentsProvider = ArgumentsProviderBuilder.build(m, setupMethodMap);
DeclaredTest test = new DeclaredTest(m, argumentsProvider, compLevel, warmupIterations);
DeclaredTest test = new DeclaredTest(m, argumentsProvider, compLevel, warmupIterations, allowNotCompilable);
declaredTests.put(m, test);
testMethodMap.put(m.getName(), m);
}

View File

@ -0,0 +1,205 @@
/*
* Copyright (c) 2025, 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 ir_framework.tests;
import compiler.lib.ir_framework.*;
import compiler.lib.ir_framework.shared.TestRunException;
import compiler.lib.ir_framework.driver.TestVMException;
import compiler.lib.ir_framework.driver.irmatching.IRViolationException;
/*
* @test
* @requires vm.compiler2.enabled & vm.flagless
* @summary Test the functionality of allowNotCompilable.
* @library /test/lib /
* @run driver ir_framework.tests.TestNotCompilable
*/
public class TestNotCompilable {
public static void main(String[] args) throws Exception {
runTests(false);
runTests(true);
}
private static void runTests(boolean noWarmup) {
// Run without any flags -> should pass.
runNormal(TestClassA.class, noWarmup);
runNormal(TestClassB.class, noWarmup);
runNormal(TestClassC.class, noWarmup);
runNormal(TestClassD.class, noWarmup);
runNormal(TestClassE.class, noWarmup);
runNormal(TestClassF.class, noWarmup);
// Forbid compilation -> should throw exception, because "not compilable".
runWithExcludeExpectFailure(TestClassA.class, noWarmup);
runWithExcludeExpectFailure(TestClassB.class, noWarmup);
// Note: @Run does not fail, but the @IR detects that there is no compilation, and fails.
runWithExcludeExpectFailure(TestClassE.class, noWarmup);
runOptoNoExecuteExpectFailure(TestClassA.class, noWarmup);
runOptoNoExecuteExpectFailure(TestClassB.class, noWarmup);
// Forbid compilation -> annotation allows not compilable -> should pass.
runWithExcludeExpectSuccess(TestClassC.class, noWarmup);
runWithExcludeExpectSuccess(TestClassD.class, noWarmup);
runWithExcludeExpectSuccess(TestClassF.class, noWarmup);
runOptoNoExecuteExpectSuccess(TestClassC.class, noWarmup);
runOptoNoExecuteExpectSuccess(TestClassD.class, noWarmup);
// Note: @Run does not fail because of missing compilation. And OptoNoExecute does still
// print IR before it bails out, and we can successfully match it.
runOptoNoExecuteExpectSuccess(TestClassE.class, noWarmup);
runOptoNoExecuteExpectSuccess(TestClassF.class, noWarmup);
// Forbid compilation, but allow methods not to compile -> should pass.
runWithExcludeAndGlobalAllowNotCompilable(TestClassA.class, noWarmup);
runWithExcludeAndGlobalAllowNotCompilable(TestClassB.class, noWarmup);
runWithExcludeAndGlobalAllowNotCompilable(TestClassC.class, noWarmup);
runWithExcludeAndGlobalAllowNotCompilable(TestClassD.class, noWarmup);
runWithExcludeAndGlobalAllowNotCompilable(TestClassE.class, noWarmup);
runWithExcludeAndGlobalAllowNotCompilable(TestClassF.class, noWarmup);
runOptoNoExecuteAndGlobalAllowNotCompilable(TestClassA.class, noWarmup);
runOptoNoExecuteAndGlobalAllowNotCompilable(TestClassB.class, noWarmup);
runOptoNoExecuteAndGlobalAllowNotCompilable(TestClassC.class, noWarmup);
runOptoNoExecuteAndGlobalAllowNotCompilable(TestClassD.class, noWarmup);
runOptoNoExecuteAndGlobalAllowNotCompilable(TestClassE.class, noWarmup);
runOptoNoExecuteAndGlobalAllowNotCompilable(TestClassF.class, noWarmup);
}
private static void runNormal(Class c, boolean noWarmup) {
TestFramework framework = new TestFramework(c);
if (noWarmup) { framework.setDefaultWarmup(0); }
framework.start();
}
private static void runWithExcludeExpectFailure(Class c, boolean noWarmup) {
TestFramework framework = new TestFramework(c);
framework.addFlags("-XX:CompileCommand=exclude,*TestClass*::test*");
if (noWarmup) { framework.setDefaultWarmup(0); }
try {
framework.start();
throw new RuntimeException("should have thrown TestRunException/TestVMException or IRViolationException");
} catch (TestVMException e) {
// Happens when we hit the issue during explicit compilation by the Framework.
} catch (IRViolationException e) {
// Happens in STANDALONE Run case, where the user is responsible for ensuring
// compilation. The failure happens during IR matching.
}
}
private static void runWithExcludeExpectSuccess(Class c, boolean noWarmup) {
TestFramework framework = new TestFramework(c);
framework.addFlags("-XX:CompileCommand=exclude,*TestClass*::test*");
if (noWarmup) { framework.setDefaultWarmup(0); }
framework.start();
}
private static void runOptoNoExecuteExpectFailure(Class c, boolean noWarmup) {
System.out.println("runOptoNoExecuteExpectFailure: " + c + ", noWarmup: " + noWarmup);
TestFramework framework = new TestFramework(c);
framework.addFlags("-XX:CompileCommand=compileonly,*TestClass*::test*", "-XX:+OptoNoExecute");
if (noWarmup) { framework.setDefaultWarmup(0); }
try {
framework.start();
throw new RuntimeException("should have thrown TestRunException/TestVMException");
} catch (TestVMException e) {}
}
private static void runOptoNoExecuteExpectSuccess(Class c, boolean noWarmup) {
TestFramework framework = new TestFramework(c);
framework.addFlags("-XX:CompileCommand=compileonly,*TestClass*::test*", "-XX:+OptoNoExecute");
if (noWarmup) { framework.setDefaultWarmup(0); }
framework.start();
}
private static void runWithExcludeAndGlobalAllowNotCompilable(Class c, boolean noWarmup) {
TestFramework framework = new TestFramework(c);
framework.addFlags("-XX:CompileCommand=exclude,*TestClass*::test*");
if (noWarmup) { framework.setDefaultWarmup(0); }
framework.allowNotCompilable();
framework.start();
}
private static void runOptoNoExecuteAndGlobalAllowNotCompilable(Class c, boolean noWarmup) {
TestFramework framework = new TestFramework(c);
framework.addFlags("-XX:CompileCommand=compileonly,*TestClass*::test*", "-XX:+OptoNoExecute");
if (noWarmup) { framework.setDefaultWarmup(0); }
framework.allowNotCompilable();
framework.start();
}
}
class TestClassA {
@Test
public void test() {}
}
class TestClassB {
@Test
@IR(failOn = IRNode.LOAD)
public void test() {}
}
class TestClassC {
@Test(allowNotCompilable = true)
public void test() {}
}
class TestClassD {
@Test(allowNotCompilable = true)
@IR(failOn = IRNode.LOAD)
public void test() {}
}
class TestClassE {
@Run(test = {"test1", "test2"}, mode = RunMode.STANDALONE)
public void run() {
for (int i = 0; i < 10_000; i++) {
test1(i);
test2(i);
}
}
@Test
public void test1(int i) {}
@Test
@IR(failOn = IRNode.LOAD)
public void test2(int i) {}
}
class TestClassF {
@Run(test = {"test1", "test2"}, mode = RunMode.STANDALONE)
public void run() {
for (int i = 0; i < 10_000; i++) {
test1(i);
test2(i);
}
}
@Test(allowNotCompilable = true)
public void test1(int i) {}
@Test(allowNotCompilable = true)
@IR(failOn = IRNode.LOAD)
public void test2(int i) {}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2025, 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
@ -66,8 +66,8 @@ public class TestPhaseIRMatching {
List<String> noAdditionalFlags = new ArrayList<>();
FlagVMProcess flagVMProcess = new FlagVMProcess(testClass, noAdditionalFlags);
List<String> testVMFlags = flagVMProcess.getTestVMFlags();
TestVMProcess testVMProcess = new TestVMProcess(testVMFlags, testClass, null, -1, false);
TestClassParser testClassParser = new TestClassParser(testClass);
TestVMProcess testVMProcess = new TestVMProcess(testVMFlags, testClass, null, -1, false, false);
TestClassParser testClassParser = new TestClassParser(testClass, false);
Matchable testClassMatchable = testClassParser.parse(testVMProcess.getHotspotPidFileName(),
testVMProcess.getIrEncoding());
MatchResult result = testClassMatchable.match();
@ -398,6 +398,11 @@ class FailureBuilder implements MatchResultVisitor {
failures.add(new Failure(methodName, -1, CompilePhase.DEFAULT, CheckAttributeType.FAIL_ON, -1));
}
@Override
public void visitMethodNotCompilable(Method method, int failedIRRules) {
throw new RuntimeException("No test should bailout from compilation");
}
@Override
public void visitIRRule(AcceptChildren acceptChildren, int irRuleId, IR irAnno) {
ruleId = irRuleId;