mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-15 18:33:41 +00:00
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:
parent
3ed010ab7c
commit
fb210e3a71
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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) {}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user