diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/AbstractInfo.java b/test/hotspot/jtreg/compiler/lib/ir_framework/AbstractInfo.java
new file mode 100644
index 00000000000..cbaa5361589
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/AbstractInfo.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.shared.TestRunException;
+import compiler.lib.ir_framework.test.TestVM;
+import jdk.test.lib.Utils;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Random;
+import java.util.stream.Collectors;
+
+/**
+ * Base info class which provides some useful utility methods and information about a test.
+ *
+ * Let {@code t} be a test method specifying the {@link Test @Test} annotation and {@code c} be a check method specifying
+ * the {@code @Check(test = "t")} annotation. These two methods represent a so-called checked test. The only
+ * difference to a base test (see {@link Test}) is that the framework will invoke the check method {@code c}
+ * directly after the invocation of the test method {@code t} which allows to do some additional verification,
+ * including the return value of {@code t}. The framework does the following, similar as for base tests:
+ *
+ * The test method {@code t} has the same properties and follows the same constraints as stated in {@link Test}.
+ *
+ * The following additional constraints must be met for the test method {@code t} and check method {@code c}:
+ *
+ * Examples on how to write checked tests can be found in {@link jdk.test.lib.hotspot.ir_framework.examples.CheckedTestExample}
+ * and also as part of the internal testing in the package {@link jdk.test.lib.hotspot.ir_framework.tests}.
+ *
+ * @see Test
+ * @see TestInfo
+ * @see CheckAt
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Check {
+ /**
+ * The unique associated {@link Test} method for this {@code @Check} annotated check method. The framework will directly
+ * invoke the {@code @Check} method after each invocation or only after the compilation of the associated {@code @Test}
+ * method (depending on the value set with {@link #when()}).
+ *
+ * If a non-{@code @Test} annotated method or a {@code @Test} method that has already been used by another
+ * {@code @Check} or {@link Run} method is specified, then a {@link TestFormatException} is thrown.
+ *
+ * @see Test
+ */
+ String test();
+ /**
+ * When should the {@code @Check} method be invoked? By default, the check is done after each invocation which is
+ * encouraged if performance is not critical.
+ *
+ * @see CheckAt
+ */
+ CheckAt when() default CheckAt.EACH_INVOCATION;
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/CheckAt.java b/test/hotspot/jtreg/compiler/lib/ir_framework/CheckAt.java
new file mode 100644
index 00000000000..a007ebd7c00
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/CheckAt.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021, 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;
+
+/**
+ * This enum is used in {@link Check#when()} of a checked test to specify when the framework will invoke the
+ * check method after invoking the associated {@link Test} method.
+ *
+ * @see Check
+ * @see Test
+ */
+public enum CheckAt {
+ /**
+ * Default: Invoke the {@link Check} method each time after invoking the associated {@link Test} method.
+ */
+ EACH_INVOCATION,
+ /**
+ * Invoke the {@link Check} method only once after the warm-up of the associated {@link Test} method had been completed
+ * and the framework has compiled the associated {@link Test} method.
+ */
+ COMPILED,
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/CompLevel.java b/test/hotspot/jtreg/compiler/lib/ir_framework/CompLevel.java
new file mode 100644
index 00000000000..b6e55c0f617
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/CompLevel.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.shared.TestFrameworkException;
+import compiler.lib.ir_framework.shared.TestRun;
+import compiler.lib.ir_framework.shared.TestRunException;
+import compiler.lib.ir_framework.test.TestVM;
+import jdk.test.lib.Utils;
+
+import java.lang.reflect.Executable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Compilation levels used by the framework to initiate a compilation of a method. The compilation levels map to the used
+ * levels in HotSpot (apart from the framework specific values {@link #SKIP} and {@link #WAIT_FOR_COMPILATION} that cannot
+ * be found in HotSpot). The HotSpot specific levels must be in sync with hotspot/share/compiler/compilerDefinitions.hpp.
+ *
+ *
+ * The compilation levels can be specified in the {@link Test}, {@link ForceCompile}, and
+ * {@link ForceCompileClassInitializer} annotation.
+ *
+ * @see Test
+ * @see ForceCompile
+ * @see ForceCompileClassInitializer
+ */
+public enum CompLevel {
+ /**
+ * Can only be used at {@link Test#compLevel()}. After the warm-up, the framework keeps invoking the test over a span
+ * of 10s (configurable by setting the property flag {@code -DWaitForCompilationTimeout}) until HotSpot compiles the
+ * {@link Test} method. If the method was not compiled after 10s, an exception is thrown. The framework does not wait
+ * for the compilation if the test VM is run with {@code -Xcomp}, {@code -XX:-UseCompiler}, or
+ * {@code -DExcludeRandom=true}.
+ */
+ WAIT_FOR_COMPILATION(-4),
+ /**
+ * Can only be used at {@link Test#compLevel()}. Skip a compilation of the {@link Test @Test} method completely.
+ */
+ SKIP(-3),
+ /**
+ * Use any compilation level depending on the usage:
+ *
TYPES_BY_VALUE = new HashMap<>();
+ private final int value;
+
+ static {
+ for (CompLevel level : CompLevel.values()) {
+ TYPES_BY_VALUE.put(level.value, level);
+ }
+ }
+
+ CompLevel(int level) {
+ this.value = level;
+ }
+
+ /**
+ * Get the compilation level as integer value. These will match the levels specified in HotSpot (if available).
+ *
+ * @return the compilation level as integer.
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Get the compilation level enum from the specified integer.
+ *
+ * @param value the compilation level as integer.
+ * @throws TestRunException if {@code value} does not specify a valid compilation level.
+ * @return the compilation level enum for {@code value}.
+ */
+ public static CompLevel forValue(int value) {
+ CompLevel level = TYPES_BY_VALUE.get(value);
+ TestRun.check(level != null, "Invalid compilation level " + value);
+ return level;
+ }
+
+ /**
+ * Called by {@link TestFramework} to check if this compilation level is not part of the compiler.
+ */
+ public boolean isNotCompilationLevelOfCompiler(Compiler c) {
+ return switch (c) {
+ case C1 -> !isC1();
+ case C2 -> this != C2;
+ default -> throw new TestFrameworkException("Should not be called with compiler " + c);
+ };
+ }
+
+ /**
+ * Called by {@link TestFramework} to flip compilation levels.
+ */
+ public CompLevel flipCompLevel() {
+ switch (this) {
+ case C1_SIMPLE, C1_LIMITED_PROFILE, C1_FULL_PROFILE -> {
+ return CompLevel.C2;
+ }
+ case C2 -> {
+ return CompLevel.C1_SIMPLE;
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Called by {@link TestFramework}. Return the compilation level when only allowing a compilation with the specified
+ * compiler.
+ */
+ public CompLevel excludeCompilationRandomly(Executable ex) {
+ if (Utils.getRandomInstance().nextBoolean()) {
+ // No exclusion
+ return this;
+ }
+ Compiler compiler = TestVM.excludeRandomly(ex);
+ return switch (compiler) {
+ case ANY -> SKIP;
+ case C1 -> isC1() ? SKIP : this;
+ case C2 -> this == C2 ? SKIP : this;
+ };
+ }
+
+ private boolean isC1() {
+ return this == C1_SIMPLE || this == C1_LIMITED_PROFILE || this == C1_FULL_PROFILE;
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/Compiler.java b/test/hotspot/jtreg/compiler/lib/ir_framework/Compiler.java
new file mode 100644
index 00000000000..53fe50a2fbb
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/Compiler.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2021, 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;
+
+/**
+ * Compilers to select for {@link DontCompile}. HotSpot does not handle the exclusion of a C1 method at a specific level.
+ * It can only exclude a method for the entire C1 compilation. Thus, this annotation is provided for {@link DontCompile}
+ * instead of {@link CompLevel}.
+ *
+ * @see DontCompile
+ */
+public enum Compiler {
+ /**
+ * Selecting both the C1 and C2 compiler. This must be in sync with hotspot/share/compiler/compilerDefinitions.hpp.
+ */
+ ANY(-1),
+ /**
+ * The C1 compiler.
+ */
+ C1(1),
+ /**
+ * The C2 compiler.
+ */
+ C2(4),
+
+ ;
+
+ private final int value;
+
+ Compiler(int level) {
+ this.value = level;
+ }
+
+ /**
+ * Get the compilation level as integer value. These will match the levels specified in HotSpot (if available).
+ *
+ * @return the compilation level as integer.
+ */
+ public int getValue() {
+ return value;
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/DontCompile.java b/test/hotspot/jtreg/compiler/lib/ir_framework/DontCompile.java
new file mode 100644
index 00000000000..618858a4343
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/DontCompile.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.shared.TestFormatException;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Prevent a compilation of the annotated helper method (not specifying {@link Test @Test},
+ * {@link Check @Check} or {@link Run @Run}) with the specified compiler.
+ *
+ *
+ * {@link Compiler#ANY} (default): No C1 or C2 compilation.
+ * {@link Compiler#C1}: No C1 compilation, C2 compilation still possible.
+ * {@link Compiler#C2}: No C2 compilation, C1 compilation still possible.
+ *
+ *
+ * Using this annotation on non-helper methods results in a {@link TestFormatException TestFormatException}.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DontCompile {
+ /**
+ * The compiler with which a compilation of a helper method is excluded.
+ */
+ Compiler value() default Compiler.ANY;
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/DontInline.java b/test/hotspot/jtreg/compiler/lib/ir_framework/DontInline.java
new file mode 100644
index 00000000000..700ca86f0d8
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/DontInline.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.shared.TestFormatException;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Prevent an inlining of the annotated helper method (not specifying {@link Test @Test}, {@link Check @Check},
+ * or {@link Run @Run}). Non-helper methods are never inlined. Explicitly using this annotation on
+ * non-helper methods results in a {@link TestFormatException}.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DontInline {
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/ForceCompile.java b/test/hotspot/jtreg/compiler/lib/ir_framework/ForceCompile.java
new file mode 100644
index 00000000000..2cfe1a8e7d4
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/ForceCompile.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.shared.TestFormatException;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Force a compilation of the annotated helper method (not specifying {@link Test @Test}, {@link Check @Check},
+ * or {@link Test @Run}) immediately at the specified level. {@link CompLevel#SKIP} and
+ * {@link CompLevel#WAIT_FOR_COMPILATION} do not apply and result in a {@link TestFormatException}.
+ *
+ *
+ * Using this annotation on non-helper methods also results in a {@link TestFormatException}.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ForceCompile {
+ /**
+ * The compilation level to compile the helper method at.
+ */
+ CompLevel value() default CompLevel.ANY;
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/ForceCompileClassInitializer.java b/test/hotspot/jtreg/compiler/lib/ir_framework/ForceCompileClassInitializer.java
new file mode 100644
index 00000000000..0f8a9bc4b45
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/ForceCompileClassInitializer.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.shared.TestFormatException;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Force a compilation of the static class initializer method ({@code }) of the annotated test or helper class
+ * immediately at the specified level. {@link CompLevel#SKIP} and {@link CompLevel#WAIT_FOR_COMPILATION} do not apply
+ * and result in a {@link TestFormatException}.
+
+ *
+ * Using this annotation on non-classes also results in a {@link TestFormatException}.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ForceCompileClassInitializer {
+ /**
+ * The compilation level to compile the static class initializer method ({@code }) at.
+ */
+ CompLevel value() default CompLevel.ANY;
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/ForceInline.java b/test/hotspot/jtreg/compiler/lib/ir_framework/ForceInline.java
new file mode 100644
index 00000000000..aba7f057b17
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/ForceInline.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.shared.TestFormatException;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Force an inlining of the annotated helper method (not specifying {@link Test @Test}, {@link Check @Check},
+ * or {@link Test @Run}). Using this annotation on non-helper methods results in a {@link TestFormatException}.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ForceInline {
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IR.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IR.java
new file mode 100644
index 00000000000..166bfe21867
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IR.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.driver.IRViolationException;
+
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This annotation is used to define a constraint/rule/check on the resulting IR of a test method (method with
+ * {@link Test @Test} annotation). A test method can define multiple {@code @IR} rules.
+ *
+ * There are two kinds of checks that can be specified:
+ *
+ * {@link #failOn()}: Specify a list of (node) regexes that should not be matched on the {@code PrintIdeal} or
+ * {@code PrintOptoAssembly} output.
+ * {@link #counts()}: Specify a list of ({@code regex,count}) pairs: The (node) {@code regex} should be matched
+ * for the specified amount in {@code count} on the {@code PrintIdeal} or {@code PrintOptoAssembly} output.
+ *
+ * An IR rule must specify either or both of these two checks. If one or both of the checks fails, an
+ * {@link IRViolationException} is thrown. A user can provide a custom regex string or specify any of the default node
+ * regexes defined in {@link IRNode}.
+ *
+ * Sometimes, the shape of the resulting IR is changed by commonly used VM flags in such a way that an IR rule no longer
+ * applies. Generally, the framework does not apply any IR rules when any of the following flags are used:
+ * {@code -Xint, -XX:-UseCompiler, -XX:TieredStopAtLevel={1,2,3}, -DExcludeRandom=true, -DFlipC1C2=true}.
+ * Furthermore, a JTreg test could be run with additional VM and Javaoptions flags. The IR verification is not
+ * performed in this case if any of these JTreg flags is used that is not part of the whitelist specified by
+ * {@link TestFramework#JTREG_WHITELIST_FLAGS}.
+ *
+ * For any other flag specified either by user code (e.g. {@link Scenario#Scenario(int, String...)},
+ * {@link TestFramework#runWithFlags(String...) etc.} or as part of the JTreg whitelist, IR verification is applied.
+ * To restrict the application of IR rules when certain flags are present that could change the IR, each {@code @IR}
+ * annotation can specify additional preconditions on the allowed test VM flags that must hold when an IR rule is applied.
+ * If the specified preconditions fail, then the framework does not apply the IR rule. These preconditions can be
+ * set with {@link #applyIf()}, {@link #applyIfNot()}, {@link #applyIfAnd()}, or {@link #applyIfOr()}.
+ *
+ * Examples on how to write tests with IR rules can be found in {@link jdk.test.lib.hotspot.ir_framework.examples.IRExample}
+ * and also as part of the internal testing in {@link jdk.test.lib.hotspot.ir_framework.tests.TestIRMatching}.
+ *
+ * @see Test
+ * @see IRNode
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(IRs.class)
+public @interface IR {
+ /**
+ * Define a list of (node) regexes. If any of these regexes are matched on the PrintIdeal or PrintOptoAssembly, the
+ * IR rule fails and an {@link IRViolationException} is thrown.
+ */
+ String[] failOn() default {};
+
+ /**
+ * Define a list of ((node) regexes,count) string pairs: A regex to be matched on the PrintIdeal or PrintOptoAssembly
+ * is immediately followed by a number specifying how often the regex should be matched. The number can be proceeded
+ * by comparators ({@code =, !=, <, <=, =>, >}) where the equality operator is optional (default if no comparator is
+ * specified).
+ *
+ * If any constraint on the number of regexes cannot be met, the IR rule fails and an
+ * {@link IRViolationException} is thrown.
+ */
+ String[] counts() default {};
+
+ /**
+ * Define a single VM flag precondition which must hold when applying the IR rule. If the VM flag precondition
+ * fails, then the IR rule is not applied. This is useful if a commonly used flag alters the IR in such a way that an IR rule
+ * would fail.
+ *
+ * The precondition is a (flag, value) string pair where the flag must be a valid VM flag and the value must conform
+ * with the type of the VM flag. A number based flag value can be proceeded with an additional comparator
+ * ({@code =, !=, <, <=, =>, >}) where the equality operator is optional (default if no comparator is specified).
+ *
+ * This is the inverse of {@link #applyIfNot()}. For multiple preconditions, use {@link #applyIfAnd()} or
+ * {@link #applyIfOr()} depending on the use case.
+ */
+ String[] applyIf() default {};
+
+ /**
+ * Define a single VM flag precondition which must not hold when applying the IR rule. If, however,
+ * the VM flag precondition holds, then the IR rule is not applied. This could also be defined as negative
+ * precondition. This is useful if a commonly used flag alters the IR in such a way that an IR rule would fail.
+ *
+ * The precondition is a (flag, value) string pair where the flag must be a valid VM flag and the value must conform
+ * with the type of the VM flag. A number based flag value can be proceeded with an additional comparator
+ * ({@code =, !=, <, <=, =>, >}) where the equality operator is optional (default if no comparator is specified).
+ *
+ * This is the inverse of {@link #applyIf()}. For multiple preconditions, use {@link #applyIfAnd()} or
+ * {@link #applyIfOr()} depending on the use case.
+ */
+ String[] applyIfNot() default {};
+
+ /**
+ * Define a list of at least two VM flag precondition which all must hold when applying the IR rule.
+ * If the one of the VM flag preconditions does not hold, then the IR rule is not applied. This is useful if
+ * commonly used flags alter the IR in such a way that an IR rule would fail. This can also be defined as conjunction
+ * of preconditions.
+ *
+ * A precondition is a (flag, value) string pair where the flag must be a valid VM flag and the value must conform
+ * with the type of the VM flag. A number based flag value can be proceeded with an additional comparator
+ * ({@code =, !=, <, <=, =>, >}) where the equality operator is optional (default if no comparator is specified).
+ *
+ * Use {@link #applyIfOr()} for disjunction and for single precondition constraints use {@link #applyIf()} or
+ * {@link #applyIfNot()} depending on the use case.
+ */
+ String[] applyIfAnd() default {};
+
+ /**
+ * Define a list of at least two VM flag precondition from which at least one must hold when applying
+ * the IR rule. If none of the VM flag preconditions holds, then the IR rule is not applied. This is useful if
+ * commonly used flags alter the IR in such a way that an IR rule would fail. This can also be defined as disjunction
+ * of preconditions.
+ *
+ * A precondition is a (flag, value) string pair where the flag must be a valid VM flag and the value must conform
+ * with the type of the VM flag. A number based flag value can be proceeded with an additional comparator
+ * ({@code =, !=, <, <=, =>, >}) where the equality operator is optional (default if no comparator is specified).
+ *
+ * Use {@link #applyIfAnd()} for conjunction and for single precondition constraints use {@link #applyIf()} or
+ * {@link #applyIfNot()} depending on the use case.
+ */
+ String[] applyIfOr() default {};
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
new file mode 100644
index 00000000000..a5b72599668
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.driver.IRMatcher;
+import compiler.lib.ir_framework.shared.TestFormat;
+import compiler.lib.ir_framework.shared.TestFormatException;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * This class provides default regex strings that can be used in {@link IR @IR} annotations to specify IR constraints.
+ *
+ * There are two types of default regexes:
+ *
+ * Standalone regexes: Use them directly.
+ * Composite regexes: Their names contain "{@code _OF}" and expect another string in a list in
+ * {@link IR#failOn()} and {@link IR#counts()}. They cannot be use as standalone regex and will result in a
+ * {@link TestFormatException} when doing so.
+ *
+ *
+ * @see IR
+ */
+public class IRNode {
+ private static final String START = "(\\d+(\\s){2}(";
+ private static final String MID = ".*)+(\\s){2}===.*";
+ private static final String END = ")";
+
+ public static final String ALLOC = "(.*precise klass .*\\R(.*(movl|xorl|nop|spill).*\\R)*.*call,static wrapper for: _new_instance_Java" + END;
+ public static final String ALLOC_OF = "(.*precise klass .*";
+ public static final String ALLOC_ARRAY = "(.*precise klass \\[L.*\\R(.*(movl|xorl|nop|spill).*\\R)*.*call,static wrapper for: _new_array_Java" + END;
+ public static final String ALLOC_ARRAY_OF = "(.*precise klass \\[L.*";
+
+ public static final String CHECKCAST_ARRAY = "(cmp.*precise klass \\[.*;:" + END;
+ public static final String CHECKCAST_ARRAY_OF = "(cmp.*precise klass \\[.*";
+ public static final String CHECKCAST_ARRAYCOPY = "(.*call_leaf_nofp,runtime checkcast_arraycopy.*" + END;
+
+ public static final String FIELD_ACCESS = "(.*Field: *" + END;
+
+ public static final String STORE = START + "Store(B|C|S|I|L|F|D|P|N)" + MID + END;
+ public static final String STORE_B = START + "StoreB" + MID + END; // Store to boolean is also mapped to byte
+ public static final String STORE_C = START + "StoreC" + MID + END;
+ public static final String STORE_I = START + "StoreI" + MID + END; // Store to short is also mapped to int
+ public static final String STORE_L = START + "StoreL" + MID + END;
+ public static final String STORE_F = START + "StoreF" + MID + END;
+ public static final String STORE_D = START + "StoreD" + MID + END;
+ public static final String STORE_P = START + "StoreP" + MID + END;
+ public static final String STORE_N = START + "StoreN" + MID + END;
+ public static final String STORE_OF_CLASS = START + "Store(B|C|S|I|L|F|D|P|N)" + MID + "@\\S*";
+ public static final String STORE_B_OF_CLASS = START + "StoreB" + MID + "@\\S*";
+ public static final String STORE_C_OF_CLASS = START + "StoreC" + MID + "@\\S*";
+ public static final String STORE_I_OF_CLASS = START + "StoreI" + MID + "@\\S*";
+ public static final String STORE_L_OF_CLASS = START + "StoreL" + MID + "@\\S*";
+ public static final String STORE_F_OF_CLASS = START + "StoreF" + MID + "@\\S*";
+ public static final String STORE_D_OF_CLASS = START + "StoreD" + MID + "@\\S*";
+ public static final String STORE_P_OF_CLASS = START + "StoreP" + MID + "@\\S*";
+ public static final String STORE_N_OF_CLASS = START + "StoreN" + MID + "@\\S*";
+ public static final String STORE_OF_FIELD = START + "Store(B|C|S|I|L|F|D|P|N)" + MID + "@.*name=";
+
+ public static final String LOAD = START + "Load(B|UB|S|US|I|L|F|D|P|N)" + MID + END;
+ public static final String LOAD_B = START + "LoadB" + MID + END;
+ public static final String LOAD_UB = START + "LoadUB" + MID + END; // Load from boolean
+ public static final String LOAD_S = START + "LoadS" + MID + END;
+ public static final String LOAD_US = START + "LoadUS" + MID + END; // Load from char
+ public static final String LOAD_I = START + "LoadI" + MID + END;
+ public static final String LOAD_L = START + "LoadL" + MID + END;
+ public static final String LOAD_F = START + "LoadF" + MID + END;
+ public static final String LOAD_D = START + "LoadD" + MID + END;
+ public static final String LOAD_P = START + "LoadP" + MID + END;
+ public static final String LOAD_N = START + "LoadN" + MID + END;
+ public static final String LOAD_OF_CLASS = START + "Load(B|UB|S|US|I|L|F|D|P|N)" + MID + "@\\S*";
+ public static final String LOAD_B_OF_CLASS = START + "LoadB" + MID + "@\\S*";
+ public static final String LOAD_UB_OF_CLASS = START + "LoadUB" + MID + "@\\S*";
+ public static final String LOAD_S_OF_CLASS = START + "LoadS" + MID + "@\\S*";
+ public static final String LOAD_US_OF_CLASS = START + "LoadUS" + MID + "@\\S*";
+ public static final String LOAD_I_OF_CLASS = START + "LoadI" + MID + "@\\S*";
+ public static final String LOAD_L_OF_CLASS = START + "LoadL" + MID + "@\\S*";
+ public static final String LOAD_F_OF_CLASS = START + "LoadF" + MID + "@\\S*";
+ public static final String LOAD_D_OF_CLASS = START + "LoadD" + MID + "@\\S*";
+ public static final String LOAD_P_OF_CLASS = START + "LoadP" + MID + "@\\S*";
+ public static final String LOAD_N_OF_CLASS = START + "LoadN" + MID + "@\\S*";
+ public static final String LOAD_OF_FIELD = START + "Load(B|C|S|I|L|F|D|P|N)" + MID + "@.*name=";
+ public static final String LOAD_KLASS = START + "LoadK" + MID + END;
+
+ public static final String LOOP = START + "Loop" + MID + "" + END;
+ public static final String COUNTEDLOOP = START + "CountedLoop\\b" + MID + "" + END;
+ public static final String COUNTEDLOOP_MAIN = START + "CountedLoop\\b" + MID + "main" + END;
+
+ public static final String CALL = START + "CallStaticJava" + MID + END;
+ public static final String TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*reason" + END;
+ public static final String PREDICATE_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*predicate" + END;
+ public static final String UNSTABLE_IF_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*unstable_if" + END;
+ public static final String CLASS_CHECK_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*class_check" + END;
+ public static final String NULL_CHECK_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*null_check" + END;
+ public static final String NULL_ASSERT_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*null_assert" + END;
+ public static final String RANGE_CHECK_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*range_check" + END;
+ public static final String UNHANDLED_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*unhandled" + END;
+ public static final String INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*intrinsic_or_type_checked_inlining" + END;
+
+ public static final String SCOPE_OBJECT = "(.*# ScObj.*" + END;
+ public static final String MEMBAR = START + "MemBar" + MID + END;
+
+
+ private static final String ALLOC_OF_POSTFIX = ":.*\\R(.*(movl|xorl|nop|spill).*\\R)*.*call,static wrapper for: _new_instance_Java" + END;
+ private static final String ALLOC_ARRAY_OF_POSTFIX = ";:.*\\R(.*(movl|xorl|nop|spill).*\\R)*.*call,static wrapper for: _new_array_Java" + END;
+ private static final String CHECKCAST_ARRAY_OF_POSTFIX = ";:" + END;
+ private static final String STORE_OF_FIELD_POSTFIX = ",.*" + END;
+ private static final String STORE_OF_CLASS_POSTFIX = "(:|\\+)\\S* \\*" + END;
+ private static final String LOAD_OF_CLASS_POSTFIX = "(:|\\+)\\S* \\*" + END;
+ private static final String LOAD_OF_FIELD_POSTFIX = ",.*" + END;
+
+ /**
+ * Called by {@link IRMatcher} to merge special composite nodes together with additional user-defined input.
+ */
+ public static List mergeNodes(String[] nodes) {
+ List mergedNodes = new ArrayList<>();
+ for (int i = 0; i < nodes.length; i += 2) {
+ String node = nodes[i];
+ switch (node) {
+ case ALLOC_OF -> mergeCompositeNodes(nodes, mergedNodes, i, node, ALLOC_OF_POSTFIX, "ALLOC_OF");
+ case ALLOC_ARRAY_OF -> mergeCompositeNodes(nodes, mergedNodes, i, node, ALLOC_ARRAY_OF_POSTFIX, "ALLOC_ARRAY_OF");
+ case CHECKCAST_ARRAY_OF -> mergeCompositeNodes(nodes, mergedNodes, i, node, CHECKCAST_ARRAY_OF_POSTFIX, "CHECKCAST_ARRAY_OF");
+ case STORE_OF_CLASS, STORE_B_OF_CLASS, STORE_C_OF_CLASS, STORE_D_OF_CLASS, STORE_F_OF_CLASS, STORE_I_OF_CLASS,
+ STORE_L_OF_CLASS, STORE_N_OF_CLASS, STORE_P_OF_CLASS
+ -> mergeCompositeNodes(nodes, mergedNodes, i, node, STORE_OF_CLASS_POSTFIX, "STORE_OF_CLASS");
+ case STORE_OF_FIELD -> mergeCompositeNodes(nodes, mergedNodes, i, node, STORE_OF_FIELD_POSTFIX, "STORE_OF_FIELD");
+ case LOAD_OF_CLASS, LOAD_B_OF_CLASS, LOAD_UB_OF_CLASS, LOAD_D_OF_CLASS, LOAD_F_OF_CLASS, LOAD_I_OF_CLASS, LOAD_L_OF_CLASS,
+ LOAD_N_OF_CLASS, LOAD_P_OF_CLASS, LOAD_S_OF_CLASS, LOAD_US_OF_CLASS
+ -> mergeCompositeNodes(nodes, mergedNodes, i, node, LOAD_OF_CLASS_POSTFIX, "LOAD_OF_CLASS");
+ case LOAD_OF_FIELD -> mergeCompositeNodes(nodes, mergedNodes, i, node, LOAD_OF_FIELD_POSTFIX, "LOAD_OF_FIELD");
+ default -> {
+ i--; // No composite node, do not increment by 2.
+ mergedNodes.add(node);
+ }
+ }
+ }
+ return mergedNodes;
+ }
+
+ private static void mergeCompositeNodes(String[] nodes, List mergedNodes, int i, String node, String postFix, String varName) {
+ TestFormat.check(i + 1 < nodes.length, "Must provide class name at index " + (i + 1) + " right after " + varName);
+ mergedNodes.add(node + Pattern.quote(nodes[i + 1]) + postFix);
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRs.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRs.java
new file mode 100644
index 00000000000..b64d46710ed
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRs.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Annotation to allow to specify multiple {@link IR @IR} annotations at a {@link Test @Test} method.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface IRs {
+ IR[] value();
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/README.md b/test/hotspot/jtreg/compiler/lib/ir_framework/README.md
new file mode 100644
index 00000000000..8a405b3f246
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/README.md
@@ -0,0 +1,135 @@
+# IR Test Framework
+This folder contains a test framework whose main purpose is to perform regex-based checks on the C2 IR shape of test methods emitted by the VM flags _-XX:+PrintIdeal_ and _-XX:+PrintOptoAssembly_. The framework can also be used for other non-IR matching (and non-compiler) tests by providing easy to use annotations for commonly used testing patterns and compiler control flags.
+
+## 1. How to Use the Framework
+The framework is intended to be used in JTreg tests. The JTreg header of the test must contain `@library /test/lib /` (2 paths) and should be run as a driver with `@run driver`. Annotate the test code with the supported framework annotations and call the framework from within the test's `main()` method. A simple example is shown below:
+
+ /*
+ * @test
+ * @summary A simple test using the test framework.
+ * @library /test/lib /
+ * @run driver my.package.MySimpleTest
+ */
+
+ package my.package;
+
+ import compiler.lib.ir_framework.*;
+
+ public class MySimpleTest {
+
+ public static void main(String[] args) {
+ TestFramework.run(); // The framework runs all tests of this class.
+ }
+
+ @Test
+ @IR(failOn = IRNode.STORE) // Fail if the IR of myTest() contains any stores.
+ public void myTest() {
+ /* ... */
+ }
+ }
+
+There are various ways how to set up and run a test within the `main()` method of a JTreg test. These are described and can be found in the [TestFramework](./TestFramework.java) class.
+
+## 2. Features
+The framework offers various annotations and flags to control how your test code should be invoked and being checked. This section gives an overview over all these features.
+
+### 2.1 Different Tests
+There are three kinds of tests depending on how much control is needed over the test invocation.
+#### Base Tests
+The simplest form of testing provides a single `@Test` annotated method which the framework will invoke as part of the testing. The test method has no or well-defined arguments that the framework can automatically provide.
+
+More information on base tests with a precise definition can be found in the Javadocs of [Test](./Test.java). Concrete examples on how to specify a base test can be found in [BaseTestsExample](../../../testlibrary_tests/ir_framework/examples/BaseTestExample.java).
+
+#### Checked Tests
+The base tests do not provide any way of verification by user code. A checked test enables this by allowing the user to define an additional `@Check` annotated method which is invoked directly after the `@Test` annotated method. This allows the user to perform various checks about the test method including return value verification.
+
+More information on checked tests with a precise definition can be found in the Javadocs of [Check](./Check.java). Concrete examples on how to specify a checked test can be found in [CheckedTestsExample](../../../testlibrary_tests/ir_framework/examples/CheckedTestExample.java).
+
+#### Custom Run Tests
+Neither the base nor the checked tests provide any control over how a `@Test` annotated method is invoked in terms of customized argument values and/or conditions for the invocation itself. A custom run test gives full control over the invocation of the `@Test` annotated method to the user. The framework calls a dedicated `@Run` annotated method from which the user can invoke the `@Test` method according to his/her needs.
+
+More information on checked tests with a precise definition can be found in the Javadocs of [Run](./Run.java). Concrete examples on how to specify a custom run test can be found in [CustomRunTestsExample](../../../testlibrary_tests/ir_framework/examples/CustomRunTestExample.java).
+
+### 2.2 IR Verification
+The main feature of this framework is to perform a simple but yet powerful regex-based C2 IR matching on the output of _-XX:+PrintIdeal_ and _-XX:+PrintOptoAssembly_. For simplicity, we will refer to the "IR" or "IR matching" when actually meaning the combined output of _-XX:+PrintIdeal_ and _-XX:+PrintOptoAssembly_ for a C2 compilation.
+
+The user has the possibility to add an additional `@IR` annotation to any `@Test` annotated method (regardless of the kind of test mentioned in section 2.1) to specify a constraint/rule on the compiled IR shape. The `@IR` annotation provides two kinds of regex checks:
+
+ - A `failOn` check that verifies that the provided regex is not matched in the C2 IR.
+ - A `counts` check that verifies that the provided regex is matched a user defined number of times in the C2 IR.
+
+A regex can either be a custom string or any of the default regexes provided by the framework in [IRNode](./IRNode.java) for some commonly used IR nodes (also provides the possibility of composite regexes).
+
+An IR verification cannot always be performed. For example, a JTreg test could be run with _-Xint_ or not a debug build (_-XX:+PrintIdeal_ and _-XX:+PrintOptoAssembly_ are debug build flags). But also CI tier testing could add additional JTreg VM and Javaoptions flags which could make an IR rule unstable.
+
+In general, the framework will only perform IR verification if the used VM flags allow a C2 compilation and if non-critical additional JTreg VM and Javaoptions are provided (see whiteflag list in [TestFramework](./TestFramework.java)). The user test code, however, can specify any flags which still allow an IR verification to be performed if a C2 compilation is done (expected flags by user defined `@IR` annotations).
+
+An `@IR` annotation allows additional preconditions/restrictions on the currently present VM flags to enable or disable rules when certain flags are present or have a specific value (see `applyIfXX` properties of an `@IR` annotation).
+
+More information about IR matching can be found in the Javadocs of [IR](./IR.java). Concrete examples on how to specify IR constraint/rules can be found in [IRExample](../../../testlibrary_tests/ir_framework/examples/IRExample.java) and [TestIRMatching](../../../testlibrary_tests/ir_framework/tests/TestIRMatching.java) (an internal framework test).
+
+### 2.3 Test VM Flags and Scenarios
+The recommended way to use the framework is by defining a single `@run driver` statement in the JTreg header which, however, does not allow the specification of additional test VM flags. Instead, the user has the possibility to provide VM flags by calling `TestFramework.runWithFlags()` or by creating a `TestFramework` builder object on which `addFlags()` can be called.
+
+If a user wants to provide multiple flag combinations for a single test, he or she has the option to provide different scenarios. A scenario based flag will always have precedence over other user defined flags. More information about scenarios can be found in the Javadocs of [Scenario](./Scenario.java).
+
+### 2.4 Compiler Controls
+The framework allows the use of additional compiler control annotations for helper method and classes in the same fashion as JMH does. The following annotations are supported and described in the referenced Javadocs for the annotation class:
+
+- [@DontInline](./DontInline.java)
+- [@ForceInline](./ForceInline.java)
+- [@DontCompile](./DontCompile.java)
+- [@ForceCompile](./DontCompile.java)
+- [@ForceCompileClassInitializer](./ForceCompileClassInitializer.java)
+
+### 2.5 Framework Debug and Stress Flags
+The framework provides various stress and debug flags. They should mainly be used as JTreg VM and/or Javaoptions (apart from `VerifyIR`). The following (property) flags are supported:
+
+- `-DVerifyIR=false`: Explicitly disable IR verification. This is useful, for example, if some scenarios use VM flags that let `@IR` annotation rules fail and the user does not want to provide separate IR rules or add flag preconditions to the already existing IR rules.
+- `-DTest=test1,test2`: Provide a list of `@Test` method names which should be executed.
+- `-DExclude=test3`: Provide a list of `@Test` method names which should be excluded from execution.
+- `-DScenarios=1,2`: Provide a list of scenario indexes to specify which scenarios should be executed.
+- `-DWarmup=200`: Provide a new default value of the number of warm-up iterations (framework default is 2000). This might have an influence on the resulting IR and could lead to matching failures (the user can also set a fixed default warm-up value in a test with `testFrameworkObject.setDefaultWarmup(200)`).
+- `-DVerbose=true`: Enable more fain-grained logging (slows the execution down).
+- `-DReproduce=true`: Flag to use when directly running a test VM to bypass dependencies to the driver VM state (for example, when reproducing an issue).
+- `-DPrintTimes=true`: Print the execution time measurements of each executed test.
+- `-DVerifyVM=true`: The framework runs the test VM with additional verification flags (slows the execution down).
+- `-DExcluceRandom=true`: The framework randomly excludes some methods from compilation. IR verification is disabled completely with this flag.
+- `-DFlipC1C2=true`: The framework compiles all `@Test` annotated method with C1 if a C2 compilation would have been applied and vice versa. IR verification is disabled completely with this flag.
+- `-DShuffleTests=false`: Disables the random execution order of all tests (such a shuffling is always done by default).
+- `-DDumpReplay=true`: Add the `DumpReplay` directive to the test VM.
+- `-DGCAfter=true`: Perform `System.gc()` after each test (slows the execution down).
+- `-TestCompilationTimeout=20`: Change the default waiting time (default: 10s) for a compilation of a normal `@Test` annotated method.
+- `-DWaitForCompilationTimeout=20`: Change the default waiting time (default: 10s) for a compilation of a `@Test` annotated method with compilation level [WAIT\_FOR\_COMPILATION](./CompLevel.java).
+- `-DIgnoreCompilerControls=false`: Ignore all compiler controls applied in the framework. This includes any compiler control annotations (`@DontCompile`, `@DontInline`, `@ForceCompile`, `@ForceInline`, `@ForceCompileStaticInitializer`), the exclusion of `@Run` and `@Check` methods from compilation, and the directive to not inline `@Test` annotated methods.
+
+
+## 3. Test Framework Execution
+This section gives an overview of how the framework is executing a JTreg test that calls the framework from within its `main()` method.
+
+The framework will spawn a new "test VM" to execute the user defined tests. The test VM collects all tests of the test class specified by the user code in `main()` and ensures that there is no violation of the required format by the framework. In a next step, the framework does the following for each test in general:
+1. Warm the test up for a predefined number of times (default 2000). This can also be adapted for all tests by using `testFrameworkobject.setDefaultWarmup(100)` or for individual tests with an additional [@Warmup](./Warmup.java) annotation.
+2. After the warm-up is finished, the framework compiles the associated `@Test` annotated method at the specified compilation level (default: C2).
+3. After the compilation, the test is invoked one more time.
+
+Once the test VM terminates, IR verification (if possible) is performed on the output of the test VM. If any test throws an exception during its execution or if IR matching fails, the failures are collected and reported in a pretty format. Check the standard error and output for more information and how to reproduce these failures.
+
+Some of the steps above can be different due to the kind of the test or due to using non-default annotation properties. These details and differences are described in the Javadocs for the three tests (see section 2.1 Different Tests).
+
+More information about the internals and the workflow of the framework can be found in the Javadocs of [TestFramework](./TestFramework.java).
+
+## 4. Internal Framework Tests
+There are various tests to verify the correctness of the test framework. These tests can be found in [ir_framework](../../../testlibrary_tests/ir_framework) and can directly be run with JTreg. The tests are part of the normal JTreg tests of HotSpot and should be run upon changing the framework code as a minimal form of testing.
+
+Additional testing was performed by converting all compiler Inline Types tests that used the currently present IR test framework in Valhalla (see [JDK-8263024](https://bugs.openjdk.java.net/browse/JDK-8263024)). It is strongly advised to make sure a change to the framework still lets these converted tests in Valhalla pass as part of an additional testing step.
+
+## 5. Framework Package Structure
+A user only needs to import classes from the package `compiler.lib.ir_framework` (e.g. `import compiler.lib.ir_framework.*;`) which represents the interface classes to the framework. The remaining framework internal classes are kept in separate subpackages and should not directly be imported:
+
+- `compiler.lib.ir_framework.driver`: These classes are used while running the driver VM (same VM as the one running the user code's `main()` method of a JTreg test).
+- `compiler.lib.ir_framework.flag`: These classes are used while running the flag VM to determine additional flags for the test VM which are required for IR verification.
+- `compiler.lib.ir_framework.test`: These classes are used while running the test VM (i.e. the actual execution of the user tests as described in section 3).
+- `compiler.lib.ir_framework.shared`: These classes can be called from either the driver, flag, or test VM.
+
+## 6. Summary
+The initial design and feature set was kept simple and straight forward and serves well for small to medium sized tests. There are a lot of possibilities to further enhance the framework and make it more powerful. This can be tackled in additional RFEs. A few ideas can be found as subtasks of the [initial RFE](https://bugs.openjdk.java.net/browse/JDK-8254129) for this framework.
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/Run.java b/test/hotspot/jtreg/compiler/lib/ir_framework/Run.java
new file mode 100644
index 00000000000..ea83104449c
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/Run.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.shared.TestFormatException;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Annotation for a run method of a custom run test.
+ *
+ *
+ * Let {@code t} be a test method specifying the {@link Test @Test} annotation and {@code r} be a run method specifying
+ * the {@code @Run(test = "t")} annotation. These two methods represent a so-called custom run test. The only
+ * difference to a base test (see {@link Test}) is that the framework will not invoke the test method {@code t}
+ * but instead the run method {@code r} which is then responsible to invoke {@code t} in any way and optionally do any
+ * additional verification (e.g. of the return value). If {@code r} does not specify {@link RunMode#STANDALONE} as
+ * {@link #mode()} property, the framework does the following, similar as for base tests:
+ *
+ * The framework warms {@code r} up by invoking it for a predefined number of iterations (default: 2000)
+ * or any number specified by an additional {@link Warmup} annotation at the run method {@code r} or by using
+ * {@link TestFramework#setDefaultWarmup(int)} (could also be 0 which skips the warm-up completely which is
+ * similar to simulating {@code -Xcomp}). More information about the warm-up in general can be found in
+ * {@link Warmup @Warmup}.
+ * After the warm-up, the framework compiles the test method {@code t} at the specified compilation level set by
+ * {@link Test#compLevel()} (default {@link CompLevel#ANY} will pick the highest available level which is usually
+ * {@link CompLevel#C2}).
+ * The framework invokes the run method {@code r} one more time to check the compilation.
+ * The framework checks any specified {@link IR @IR} constraints at the test method {@code t}.
+ * More information about IR matching can be found at {@link IR}.
+ *
+ *
+ *
+ * If {@code r} specifies {@link RunMode#STANDALONE} as {@link #mode()} property, the framework gives complete
+ * control to the run method {@code r}:
+ *
+ * The framework invokes the run method {@code r} only one time without any warm-up or compilation of
+ * {@code t} ({@link Warmup @Warmup} is not allowed at {@code r} in this case).
+ * After this single invocation, the framework directly checks any specified {@link IR} constraints at the test
+ * method {@code t}. The run method {@code r} needs to make sure to reliably trigger a C2 compilation. Otherwise,
+ * IR matching will fail. More information about IR matching can be found at {@link IR}.
+ *
+ *
+ *
+ * The test method {@code t} and run method {@code r} have the following properties:
+ *
+ * {@code t} can specify any parameter or return type except {@link AbstractInfo} or any of its subclasses.
+ * {@code t} is not inlined.
+ *
{@code r} is not compiled nor inlined.
+ *
{@code r} is responsible to invoke {@code t} in any way (once, multiple times or even skipping on some
+ * invocations of {@code r}).
+ *
{@code r} can specify the following method parameter combinations:
+ *
+ * {@code t} and {@code r} must be part of the test class. Using {@code @Run} and {@code @Test} in nested or
+ * other helper classes is not allowed.
+ * {@code t} and {@code r} cannot specify any helper-method-specific compile command annotations
+ * ({@link ForceCompile @ForceCompile}, {@link DontCompile @DontCompile}, {@link ForceInline @ForceInline},
+ * {@link DontInline @DontInline}).
+ *
+ *
+ *
+ * Examples on how to write custom run tests can be found in {@link jdk.test.lib.hotspot.ir_framework.examples.CustomRunTestExample}
+ * and also as part of the internal testing in the package {@link jdk.test.lib.hotspot.ir_framework.tests}.
+ *
+ * @see Test
+ * @see RunInfo
+ * @see RunMode
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Run {
+ /**
+ * The associated {@link Test @Test} methods (one or more) for this {@code @Run} annotated run method.
+ * The framework directly invokes the run method instead of the associated {@code @Test} methods.
+ */
+ String[] test();
+
+ /**
+ * The mode of this custom run test.
+ *
+ * @see RunMode
+ */
+ RunMode mode() default RunMode.NORMAL;
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/RunInfo.java b/test/hotspot/jtreg/compiler/lib/ir_framework/RunInfo.java
new file mode 100644
index 00000000000..902e2d54774
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/RunInfo.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.test.DeclaredTest;
+import compiler.lib.ir_framework.shared.TestRunException;
+import compiler.lib.ir_framework.test.TestVM;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Test info class which provides some useful utility methods and information about a custom run test.
+ *
+ * @see Run
+ */
+public class RunInfo extends AbstractInfo {
+ private final Method testMethod;
+ private final DeclaredTest test;
+ private final Map tests;
+ private final boolean hasMultipleTests;
+
+ public RunInfo(List tests) {
+ super(tests.get(0).getTestMethod().getDeclaringClass());
+ this.test = tests.get(0);
+ this.testMethod = test.getTestMethod();
+ this.hasMultipleTests = tests.size() != 1;
+ if (hasMultipleTests) {
+ this.tests = new HashMap<>();
+ for (DeclaredTest test : tests) {
+ this.tests.put(test.getTestMethod().getName(), test);
+ }
+ } else {
+ this.tests = null;
+ }
+ }
+
+ /**
+ * Get the associated test method object of this custom run test. This method can only be called if one test
+ * method is specified in the custom run test ({@link Run#test()}). Otherwise, use {@link #getTest(String)}.
+ *
+ * @return the associated test method object.
+ * @throws TestRunException if called for a custom run test that specifies multiple test methods in {@link Run#test()}.
+ */
+ public Method getTest() {
+ checkSingleTest("getTest");
+ return testMethod;
+ }
+
+ /**
+ * Get the associated method object of the test method with the name {@code testName}. This method can only be called
+ * if the custom run test specifies more than one test method in ({@link Run#test()}). Otherwise, use {@link #getTest()}.
+ *
+ * @param testName the test method for which the method object should be returned.
+ * @return the associated test method object with the name {@code testName}.
+ * @throws TestRunException if there is no test method with the name {@code testName} or if called with only
+ * one associated test method.
+ */
+ public Method getTest(String testName) {
+ checkMultipleTests("getTest");
+ return getMethod(testName);
+ }
+
+ /**
+ * Return a boolean indicating if the framework skipped a compilation of the associated test method after the warm-up
+ * due to VM flags not allowing a compilation on the requested level in {@link Test#compLevel()}. This method can only
+ * be called if one test method is specified in the custom run test ({@link Run#test()}). Otherwise, use
+ * {@link #isCompilationSkipped(String)}.
+ *
+ * @return {@code true} if the framework skipped compilation of the test;
+ * {@code false} otherwise.
+ * @throws TestRunException if called for a custom run test that specifies multiple test methods in {@link Run#test()}.
+ */
+ public boolean isCompilationSkipped() {
+ checkSingleTest("isCompilationSkipped");
+ return test.getCompLevel() == CompLevel.SKIP;
+ }
+
+ /**
+ * Return a boolean indicating if the framework skipped a compilation of the associated test method with the name
+ * {@code testName} after the warm-up due to VM flags not allowing a compilation on the requested level in
+ * {@link Test#compLevel()}. This method can only be called if the custom run test specifies more than one test method
+ * in ({@link Run#test()}). Otherwise, use {@link #isCompilationSkipped()}.
+ *
+ * @param testName the test method for which the method object should be returned.
+ * @return {@code true} if the framework skipped compilation of the test;
+ * {@code false} otherwise.
+ * @throws TestRunException if there is no test method with the name {@code testName} or if called with only
+ * one associated test method.
+ */
+ public boolean isCompilationSkipped(String testName) {
+ checkMultipleTests("isCompilationSkipped");
+ return getDeclaredTest(testName).getCompLevel() == CompLevel.SKIP;
+ }
+
+ /**
+ * Returns a boolean indicating if the associated test method is C1 compiled. This method can only be called if
+ * one test method is specified in the custom run test ({@link Run#test()}). Otherwise, use
+ * {@link #isTestC1Compiled(String)}.
+ *
+ * @return {@code true} if the associated test method is C1 compiled;
+ * {@code false} otherwise.
+ * @throws TestRunException if called for a custom run test that specifies multiple test methods in {@link Run#test()}.
+ */
+ public boolean isTestC1Compiled() {
+ checkSingleTest("isTestC1Compiled");
+ return TestVM.isC1Compiled(testMethod);
+ }
+
+ /**
+ * Returns a boolean indicating if the associated test method with the name {@code testName} is C1 compiled.
+ * This method can only be called if the custom run test specifies more than one test method in ({@link Run#test()}).
+ * Otherwise, use {@link #isTestC1Compiled()}.
+ *
+ * @param testName the name of the test method.
+ * @return {@code true} if the test method with the name {@code testName} is C1 compiled;
+ * {@code false} otherwise.
+ * @throws TestRunException if there is no test method with the name {@code testName} or if called with only
+ * one associated test method.
+ */
+ public boolean isTestC1Compiled(String testName) {
+ checkMultipleTests("isTestC1Compiled");
+ return TestVM.isC1Compiled(getMethod(testName));
+ }
+
+ /**
+ * Returns a boolean indicating if the associated test method is C2 compiled. This method can only be called if
+ * one test method is specified in the custom run test ({@link Run#test()}). Otherwise, use
+ * {@link #isTestC2Compiled(String)}.
+ *
+ * @return {@code true} if the associated test method is C2 compiled;
+ * {@code false} otherwise.
+ * @throws TestRunException if called for a custom run test that specifies multiple test methods in {@link Run#test()}.
+ */
+ public boolean isTestC2Compiled() {
+ checkSingleTest("isTestC2Compiled");
+ return TestVM.isC2Compiled(testMethod);
+ }
+
+ /**
+ * Returns a boolean indicating if the associated test method with the name {@code testName} is C2 compiled.
+ * This method can only be called if the custom run test specifies more than one test method in ({@link Run#test()}).
+ * Otherwise, use {@link #isTestC2Compiled()}.
+ *
+ * @param testName the name of the test method.
+ * @return {@code true} if the test method with the name {@code testName} is C2 compiled;
+ * {@code false} otherwise.
+ * @throws TestRunException if there is no test method with the name {@code testName} or if called with only
+ * one associated test method.
+ */
+ public boolean isTestC2Compiled(String testName) {
+ checkMultipleTests("isTestC2Compiled");
+ return TestVM.isC2Compiled(getMethod(testName));
+ }
+
+ /**
+ * Returns a boolean indicating if the associated test method is compiled at {@code compLevel}. This method can only
+ * be called if one test method is specified in the custom run test ({@link Run#test()}).
+ * Otherwise, use {@link #isTestCompiledAtLevel(String, CompLevel)}.
+ *
+ * @param compLevel the compilation level
+ * @return {@code true} if the associated test method is compiled at {@code compLevel};
+ * {@code false} otherwise.
+ * @throws TestRunException if called for a custom run test that specifies multiple test methods in {@link Run#test()}.
+ */
+ public boolean isTestCompiledAtLevel(CompLevel compLevel) {
+ checkSingleTest("isTestCompiledAtLevel");
+ return TestVM.isCompiledAtLevel(testMethod, compLevel);
+ }
+
+ /**
+ * Returns a boolean indicating if the associated test method with the name {@code testName} is compiled at
+ * {@code compLevel}. This method can only be called if the custom run test specifies more than one test method
+ * in ({@link Run#test()}). Otherwise, use {@link #isTestCompiledAtLevel(CompLevel)}.
+ *
+ * @param testName the name of the test method.
+ * @param compLevel the compilation level.
+ * @return {@code true} if the test method with the name {@code testName} is compiled at {@code compLevel};
+ * {@code false} otherwise.
+ * @throws TestRunException if there is no test method with the name {@code testName} oor if called with only
+ * one associated test method.
+ */
+ public boolean isTestCompiledAtLevel(String testName, CompLevel compLevel) {
+ checkMultipleTests("isTestCompiledAtLevel");
+ return TestVM.isCompiledAtLevel(getMethod(testName), compLevel);
+ }
+
+ private void checkSingleTest(String calledMethod) {
+ if (hasMultipleTests) {
+ throw new TestRunException("Use " + calledMethod + "(String) with testName String argument in @Run method " +
+ "for custom run test that specifies more than one @Test method.");
+ }
+ }
+
+ private void checkMultipleTests(String calledMethod) {
+ if (!hasMultipleTests) {
+ throw new TestRunException("Use " + calledMethod + "() without testName String argument in @Run method " +
+ "for custom run test that specifies exactly one @Test method.");
+ }
+ }
+
+ private DeclaredTest getDeclaredTest(String testName) {
+ DeclaredTest test = tests.get(testName);
+ if (test == null) {
+ throw new TestRunException("Could not find @Test \"" + testName + "\" in " + testClass + " being associated with" +
+ " corresponding @Run method.");
+ }
+ return test;
+ }
+
+ private Method getMethod(String testName) {
+ return getDeclaredTest(testName).getTestMethod();
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/RunMode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/RunMode.java
new file mode 100644
index 00000000000..f6402dfe6ac
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/RunMode.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021, 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;
+
+/**
+ * The run mode for a custom run test specified in {@link Run#mode}.
+ *
+ * @see Run
+ */
+public enum RunMode {
+ /**
+ * Default mode: First warm up the run method (if a warm-up is done), then compile the associated {@link Test}
+ * method and finally invoke the run method once more.
+ */
+ NORMAL,
+ /**
+ * Standalone mode: There is no warm-up and no compilation done by the framework. The run method is responsible to
+ * trigger the compilation(s), especially in regard of possible {@link IR} annotations at the associated {@link Test}
+ * method.
+ */
+ STANDALONE,
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/Scenario.java b/test/hotspot/jtreg/compiler/lib/ir_framework/Scenario.java
new file mode 100644
index 00000000000..17776f7285c
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/Scenario.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.shared.TestRunException;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * This class represents a scenario that can be executed by the {@link TestFramework}.
+ *
+ * A JTreg test should use the test framework with {@code @run driver} (without directly specify any additional flags).
+ * If a test should run with additional flags, use {@link TestFramework#runWithFlags(String...)} or
+ * {@link TestFramework#addFlags(String...)}. If, however, the test should be run with different settings (equivalent
+ * to having multiple {@code @run} entries in a normal JTreg test), use scenarios. A scenario will be run with the
+ * scenario specific VM flags, if any, and optionally specified VM flags with {@link TestFramework#addFlags(String...)}
+ * whereas scenario VM flags will have precedence.
+ *
+ * There is also the possibility to specify additional VM flags for all scenarios by using {@code DScenarioFlags}.
+ *
+ * @see TestFramework
+ */
+public class Scenario {
+ private static final String ADDITIONAL_SCENARIO_FLAGS_PROPERTY = System.getProperty("ScenarioFlags", "");
+ private static final String SCENARIOS_PROPERTY = System.getProperty("Scenarios", "");
+ private static final List ADDITIONAL_SCENARIO_FLAGS;
+ private static final Set ENABLED_SCENARIOS;
+
+ private final List flags;
+ private final int index;
+ private final boolean enabled;
+ private String testVMOutput;
+
+ static {
+ if (!SCENARIOS_PROPERTY.isEmpty()) {
+ var split = SCENARIOS_PROPERTY.split("\\s*,\\s*");
+ try {
+ ENABLED_SCENARIOS = Arrays.stream(split).map(Integer::parseInt).collect(Collectors.toSet());
+ } catch (NumberFormatException e) {
+ throw new TestRunException("Provided a scenario index in the -DScenario comma-separated list which is not "
+ + "a number: " + SCENARIOS_PROPERTY);
+ }
+ } else {
+ ENABLED_SCENARIOS = Collections.emptySet();
+ }
+
+ ADDITIONAL_SCENARIO_FLAGS = ADDITIONAL_SCENARIO_FLAGS_PROPERTY.isEmpty() ? Collections.emptyList() :
+ Arrays.asList(ADDITIONAL_SCENARIO_FLAGS_PROPERTY.split("\\s*,\\s*"));
+ }
+
+ /**
+ * Create a scenario with {@code index} that will be run with the additional VM flags specified in {@code flags}
+ * (or without any if null or parameter not provided).
+ *
+ * The scenario {@code index} must be unique to be distinguishable in the stdout and stderr output and when specifying
+ * {@code -DScenarios} (see {@link Scenario}).
+ *
+ * @param index the unique scenario index.
+ * @param flags the scenario flags or null (i.e. no parameter specified) if no flags should be used.
+ */
+ public Scenario(int index, String... flags) {
+ this.index = index;
+ if (flags != null) {
+ this.flags = new ArrayList<>(Arrays.asList(flags));
+ this.flags.addAll(ADDITIONAL_SCENARIO_FLAGS);
+ } else {
+ this.flags = new ArrayList<>();
+ }
+ this.enabled = ENABLED_SCENARIOS.isEmpty() || ENABLED_SCENARIOS.contains(index);
+ }
+
+ /**
+ * Add additional VM flags to this scenario.
+ *
+ * @param flags the additional scenario VM flags.
+ */
+ public void addFlags(String... flags) {
+ if (flags != null) {
+ this.flags.addAll(Arrays.asList(flags));
+ }
+ }
+
+ /**
+ * Get all scenario specific VM flags as defined in {@link #Scenario(int, String...)}.
+ *
+ * @return the scenario VM flags.
+ */
+ public List getFlags() {
+ return flags;
+ }
+
+ /**
+ * Get the unique scenario index as defined in {@link #Scenario(int, String...)}.
+ *
+ * @return the scenario index.
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Get the test VM output (stdout + stderr) of this scenario from the last execution of the framework.
+ *
+ * @return the test VM output.
+ */
+ public String getTestVMOutput() {
+ return testVMOutput;
+ }
+
+ /**
+ * Set the test VM output, called by the framework.
+ */
+ void setTestVMOutput(String testVMOutput) {
+ this.testVMOutput = testVMOutput;
+ }
+
+ /**
+ * Returns a boolean indicating if this scenario will be executed by the test framework. This only depends on
+ * the property flag {@code -DScenarios} (see {@link Scenario}). This is only used by the framework internally.
+ *
+ * @return {@code true} if {@code -DScenarios} is either not set or if {@code -DScenarios} specifies the scenario
+ * index set by {@link #Scenario(int, String...)}.
+ * {@code false} otherwise.
+ */
+ boolean isEnabled() {
+ return enabled;
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/Test.java b/test/hotspot/jtreg/compiler/lib/ir_framework/Test.java
new file mode 100644
index 00000000000..b15a0f273b7
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/Test.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Annotate all methods in your test class which the framework should test with {@code @Test}.
+ *
+ * Let {@code m} be a test method specifying the {@code @Test} annotation. If {@code m} is neither part of a
+ * checked test (an additional method specifying {@link Check @Check} with {@code @Check(test = "m")}) nor part
+ * of a custom run test (an additional method specifying {@link Run @Run} with {@code @Run(test = "m")}),
+ * then {@code m} is a so-called base test and the the framework invokes {@code m} in the following way:
+ *
+ * The framework warms {@code m} up by invoking it for a predefined number of iterations (default: 2000)
+ * or any number specified by an additional {@link Warmup @Warmup} annotation at {@code m} or by using
+ * {@link TestFramework#setDefaultWarmup(int)} (could also be 0 which skips the warm-up completely which is similar
+ * to simulating {@code -Xcomp}). More information about the warm-up in general can be found at {@link Warmup}
+ * After the warm-up, the framework compiles {@code m} at the specified compilation level set by
+ * {@link #compLevel()} (default {@link CompLevel#ANY} will pick the highest available level which is usually
+ * {@link CompLevel#C2}).
+ * The framework invokes {@code m} one more time to run the compilation.
+ * The framework checks any specified {@link IR @IR} constraints at {@code m}. More information about IR matching
+ * can be found at {@link IR}.
+ *
+ *
+ *
+ * {@code m} has the following properties:
+ *
+ * If {@code m} specifies no parameters, the framework can directly invoke {@code m}.
+ * If {@code m} specifies parameters, the framework needs to know how to invoke {@code m}. Use {@link Arguments}
+ * with {@link Argument} properties for each parameter to use well-defined parameters by the framework. If the method
+ * requires a more specific argument value, use a custom run test (see {@link Run}).
+ * {@code m} cannot specify {@link AbstractInfo} or any of its subclasses as parameter or return type.
+ * {@code m} is not inlined by the framework.
+ * Verification of the return value of {@code m} can only be done in a checked test (see {@link Check}) or
+ * custom run test (see {@link Run}).
+ *
+ *
+ *
+ * The following constraints must be met for the test method {@code m} specifying {@code @Test}:
+ *
+ * {@code m} must be part of the test class. Using {@code @Test} in nested or helper classes is not allowed.
+ * {@code m} cannot have the same name as another {@code @Test} method in the same test class. Method
+ * overloading is only allowed (but not encouraged) with other non-{@code @Test} methods.
+ * {@code m} cannot specify any helper-method-specific compile command annotations
+ * ({@link ForceCompile @ForceCompile}, {@link DontCompile @DontCompile}, {@link ForceInline @ForceInline},
+ * {@link DontInline @DontInline}).
+ *
+ *
+ *
+ * Examples on how to write base tests can be found in {@link jdk.test.lib.hotspot.ir_framework.examples.BaseTestExample}
+ * and also as part of the internal testing in the package {@link jdk.test.lib.hotspot.ir_framework.tests}.
+ *
+ * @see Arguments
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Test {
+ /**
+ * Specify at which compilation level the framework should eventually compile the test method after an optional
+ * warm-up period. The default {@link CompLevel#ANY} will let the framework compile the method at the highest
+ * available level which is usually {@link CompLevel#C2}.
+ */
+ CompLevel compLevel() default CompLevel.ANY;
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java
new file mode 100644
index 00000000000..2b40ba73a52
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java
@@ -0,0 +1,718 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.driver.*;
+import compiler.lib.ir_framework.shared.*;
+import compiler.lib.ir_framework.test.*;
+import jdk.test.lib.Platform;
+import jdk.test.lib.Utils;
+import jdk.test.lib.helpers.ClassFileInstaller;
+import sun.hotspot.WhiteBox;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Method;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * This class represents the main entry point to the test framework whose main purpose is to perform regex-based checks on
+ * the C2 IR shape emitted by the VM flags {@code -XX:+PrintIdeal} and {@code -XX:+PrintOptoAssembly}. The framework can
+ * also be used for other non-IR matching (and non-compiler) tests by providing easy to use annotations for commonly used
+ * testing patterns and compiler control flags.
+ *
+ * The framework offers various annotations to control how your test code should be invoked and being checked. There are
+ * three kinds of tests depending on how much control is needed over the test invocation:
+ * Base tests (see {@link Test}), checked tests (see {@link Check}), and custom run tests
+ * (see {@link Run}). Each type of test needs to define a unique test method that specifies a {@link Test @Test}
+ * annotation which represents the test code that is eventually executed by the test framework. More information about
+ * the usage and how to write different tests can be found in {@link Test}, {@link Check}, and {@link Run}.
+ *
+ * Each test method can specify an arbitrary number of IR rules. This is done by using {@link IR @IR} annotations which
+ * can define regex strings that are matched on the output of {@code -XX:+PrintIdeal} and {@code -XX:+PrintOptoAssembly}.
+ * The matching is done after the test method was (optionally) warmed up and compiled. More information about the usage
+ * and how to write different IR rules can be found at {@link IR}.
+ *
+ * This framework should be used with the following JTreg setup in your Test.java file in package some.package:
+ *
+ * {@literal @}library /test/lib
+ * {@literal @}run driver some.package.Test
+ *
+ * Note that even though the framework uses the Whitebox API internally, it is not required to build and enabel it in the
+ * JTreg test if the test itself is not utilizing any Whitebox features directly.
+ *
+ * To specify additional flags, use {@link #runWithFlags(String...)}, {@link #addFlags(String...)}, or
+ * {@link #addScenarios(Scenario...)} where the scenarios can also be used to run different flag combinations
+ * (instead of specifying multiple JTreg {@code @run} entries).
+ *
+ * After annotating your test code with the framework specific annotations, the framework needs to be invoked from the
+ * {@code main()} method of your JTreg test. There are two ways to do so. The first way is by calling the various
+ * {@code runXX()} methods of {@link TestFramework}. The second way, which gives more control, is to create a new
+ * {@code TestFramework} builder object on which {@link #start()} needs to be eventually called to start the testing.
+ *
+ * The framework is called from the driver VM in which the JTreg test is initially run by specifying {@code
+ * @run driver} in the JTreg header. This strips all additionally specified JTreg VM and Javaoptions.
+ * The framework creates a new flag VM with all these flags added again in order to figure out which flags are
+ * required to run the tests specified in the test class (e.g. {@code -XX:+PrintIdeal} and {@code -XX:+PrintOptoAssembly}
+ * for IR matching).
+ *
+ * After the flag VM terminates, it starts a new test VM which performs the execution of the specified
+ * tests in the test class as described in {@link Test}, {@link Check}, and {@link Run}.
+ *
+ * In a last step, once the test VM has terminated without exceptions, IR matching is performed if there are any IR
+ * rules and if no VM flags disable it (e.g. not running with {@code -Xint}, see {@link IR} for more details).
+ * The IR regex matching is done on the output of {@code -XX:+PrintIdeal} and {@code -XX:+PrintOptoAssembly} by parsing
+ * the hotspot_pid file of the test VM. Failing IR rules are reported by throwing a {@link IRViolationException}.
+ *
+ * @see Test
+ * @see Check
+ * @see Run
+ * @see IR
+ */
+public class TestFramework {
+ /**
+ * JTreg can define additional VM (-Dtest.vm.opts) and Javaoptions (-Dtest.java.opts) flags. IR verification is only
+ * performed when all these additional JTreg flags (does not include additionally added framework and scenario flags
+ * by user code) are whitelisted.
+ *
+ * A flag is whitelisted if it is a property flag (starting with -D), -ea, -esa, or if the flag name contains any of
+ * the entries of this list as a substring (partial match).
+ */
+ public static final Set JTREG_WHITELIST_FLAGS = new HashSet<>(
+ Arrays.asList(
+ // The following substrings are part of more than one VM flag
+ "RAM",
+ "Heap",
+ "Trace",
+ "Print",
+ "Verify",
+ "TLAB",
+ "UseNewCode",
+ "Xmn",
+ "Xms",
+ "Xmx",
+ "Xss",
+ // The following substrings are only part of one VM flag (=exact match)
+ "CreateCoredumpOnCrash",
+ "IgnoreUnrecognizedVMOptions",
+ "UnlockDiagnosticVMOptions",
+ "UnlockExperimentalVMOptions",
+ "BackgroundCompilation",
+ "Xbatch",
+ "TieredCompilation",
+ "Xmixed",
+ "server",
+ "Xlog",
+ "LogCompilation"
+ )
+ );
+
+ public static final boolean VERBOSE = Boolean.getBoolean("Verbose");
+ public static final boolean TESTLIST = !System.getProperty("Test", "").isEmpty();
+ public static final boolean EXCLUDELIST = !System.getProperty("Exclude", "").isEmpty();
+ private static final boolean REPORT_STDOUT = Boolean.getBoolean("ReportStdout");
+ // Only used for internal testing and should not be used for normal user testing.
+ private static final boolean SKIP_WHITEBOX_INSTALL = Boolean.getBoolean("SkipWhiteBoxInstall");
+
+ private static final String RERUN_HINT = """
+ #############################################################
+ - To only run the failed tests use -DTest, -DExclude,
+ and/or -DScenarios.
+ - To also get the standard output of the test VM run with
+ -DReportStdout=true or for even more fine-grained logging
+ use -DVerbose=true.
+ #############################################################
+ """ + System.lineSeparator();
+
+ private boolean irVerificationPossible = Boolean.parseBoolean(System.getProperty("VerifyIR", "true"));
+ private boolean shouldVerifyIR; // Should we perform IR matching?
+ private static boolean toggleBool;
+
+ private final Class> testClass;
+ private Set> helperClasses;
+ private List scenarios;
+ private Set scenarioIndices;
+ private List flags;
+ private int defaultWarmup = -1;
+
+ /*
+ * Public interface methods
+ */
+
+ /**
+ * Creates an instance acting as a builder to test the class from which this constructor was invoked from.
+ * Use this constructor if you want to use multiple run options (flags, helper classes, scenarios).
+ * Use the associated add methods ({@link #addFlags(String...)}, {@link #addScenarios(Scenario...)},
+ * {@link #addHelperClasses(Class...)}) to set up everything and then start the testing by invoking {@link #start()}.
+ */
+ public TestFramework() {
+ this(StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).getCallerClass());
+ }
+
+ /**
+ * Creates an instance acting as a builder to test {@code testClass}.
+ * Use this constructor if you want to use multiple run options (flags, helper classes, scenarios).
+ * Use the associated add methods ({@link #addFlags(String...)}, @link #addScenarios(Scenario...)},
+ * {@link #addHelperClasses(Class...)}) to set up everything and then start the testing by invoking {@link #start()}.
+ *
+ * @param testClass the class to be tested by the framework.
+ * @see #TestFramework()
+ */
+ public TestFramework(Class> testClass) {
+ TestRun.check(testClass != null, "Test class cannot be null");
+ this.testClass = testClass;
+ if (VERBOSE) {
+ System.out.println("Test class: " + testClass);
+ }
+ }
+
+ /**
+ * Tests the class from which this method was invoked from.
+ */
+ public static void run() {
+ StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
+ run(walker.getCallerClass());
+ }
+
+ /**
+ * Tests {@code testClass}.
+ *
+ * @param testClass the class to be tested by the framework.
+ * @see #run()
+ */
+ public static void run(Class> testClass) {
+ TestFramework framework = new TestFramework(testClass);
+ framework.start();
+ }
+
+ /**
+ * Tests the class from which this method was invoked from. The test VM is called with the specified {@code flags}.
+ *
+ * The {@code flags} override any set VM or Javaoptions flags by JTreg by default.
+ * Use {@code -DPreferCommandLineFlags=true} if you want to prefer the JTreg VM and Javaoptions flags over
+ * the specified {@code flags} of this method.
+ * If you want to run your entire JTreg test with additional flags, use this method.
+ * If you want to run your entire JTreg test with additional flags but for another test class then the one
+ * from which this method was called from, use {@link #addFlags(String...)}, use this method.
+ * If you want to run your JTreg test with multiple flag combinations, use
+ * {@link #addScenarios(Scenario...)}
+ *
+ *
+ * @param flags VM flags to be used for the test VM.
+ */
+ public static void runWithFlags(String... flags) {
+ StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
+ TestFramework framework = new TestFramework(walker.getCallerClass());
+ framework.addFlags(flags);
+ framework.start();
+ }
+
+ /**
+ * Add VM flags to be used for the test VM. These flags override any VM or Javaoptions set by JTreg by default.
+ * Use {@code -DPreferCommandLineFlags=true} if you want to prefer the VM or Javaoptions over the scenario flags.
+ *
+ *
+ * The testing can be started by invoking {@link #start()}
+ *
+ * @param flags VM options to be applied to the test VM.
+ * @return the same framework instance.
+ */
+ public TestFramework addFlags(String... flags) {
+ TestRun.check(flags != null && Arrays.stream(flags).noneMatch(Objects::isNull), "A flag cannot be null");
+ if (this.flags == null) {
+ this.flags = new ArrayList<>();
+ }
+ this.flags.addAll(Arrays.asList(flags));
+ return this;
+ }
+
+ /**
+ * Add helper classes that can specify additional compile command annotations ({@link ForceCompile @ForceCompile},
+ * {@link DontCompile @DontCompile}, {@link ForceInline @ForceInline}, {@link DontInline @DontInline}) to be applied
+ * while testing {@code testClass} (also see description of {@link TestFramework}).
+ *
+ *
+ * Duplicates in {@code helperClasses} are ignored. If a class is used by the test class that does not specify any
+ * compile command annotations, you do not need to include it with this method. If no helper class specifies any
+ * compile commands, you do not need to call this method at all.
+ *
+ *
+ * The testing can be started by invoking {@link #start()}.
+ *
+ * @param helperClasses helper classes containing compile command annotations ({@link ForceCompile},
+ * {@link DontCompile}, {@link ForceInline}, {@link DontInline}) to be applied
+ * while testing {@code testClass} (also see description of {@link TestFramework}).
+ * @return the same framework instance.
+ */
+ public TestFramework addHelperClasses(Class>... helperClasses) {
+ TestRun.check(helperClasses != null && Arrays.stream(helperClasses).noneMatch(Objects::isNull),
+ "A Helper class cannot be null");
+ if (this.helperClasses == null) {
+ this.helperClasses = new HashSet<>();
+ }
+
+ this.helperClasses.addAll(Arrays.asList(helperClasses));
+ return this;
+ }
+
+ /**
+ * Add scenarios to be used for the test VM. A test VM is called for each scenario in {@code scenarios} by using the
+ * specified VM flags in the scenario. The scenario flags override any flags set by {@link #addFlags(String...)}
+ * and thus also override any VM or Javaoptions set by JTreg by default.
+ * Use {@code -DPreferCommandLineFlags=true} if you want to prefer the VM and Javaoptions over the scenario flags.
+ *
+ *
+ * The testing can be started by invoking {@link #start()}
+ *
+ * @param scenarios scenarios which specify specific flags for the test VM.
+ * @return the same framework instance.
+ */
+ public TestFramework addScenarios(Scenario... scenarios) {
+ TestFormat.check(scenarios != null && Arrays.stream(scenarios).noneMatch(Objects::isNull),
+ "A scenario cannot be null");
+ if (this.scenarios == null) {
+ this.scenarios = new ArrayList<>();
+ this.scenarioIndices = new HashSet<>();
+ }
+
+ for (Scenario scenario : scenarios) {
+ int scenarioIndex = scenario.getIndex();
+ TestFormat.check(scenarioIndices.add(scenarioIndex),
+ "Cannot define two scenarios with the same index " + scenarioIndex);
+ this.scenarios.add(scenario);
+ }
+ return this;
+ }
+
+ /**
+ * Start the testing of the implicitly (by {@link #TestFramework()}) or explicitly (by {@link #TestFramework(Class)})
+ * set test class.
+ */
+ public void start() {
+ if (!SKIP_WHITEBOX_INSTALL) {
+ installWhiteBox();
+ }
+ disableIRVerificationIfNotFeasible();
+
+ if (scenarios == null) {
+ try {
+ start(null);
+ } catch (TestVMException e) {
+ System.err.println(System.lineSeparator() + e.getExceptionInfo() + RERUN_HINT);
+ throw e;
+ } catch (IRViolationException e) {
+ System.out.println("Compilation(s) of failed match(es):");
+ System.out.println(e.getCompilations());
+ System.err.println(System.lineSeparator() + e.getExceptionInfo() + System.lineSeparator() + RERUN_HINT);
+ throw e;
+ }
+ } else {
+ startWithScenarios();
+ }
+ }
+
+ /**
+ * Set a new default warm-up (overriding the framework default of 2000 at
+ * {@link TestVM#WARMUP_ITERATIONS}) to be applied for all tests that do not specify an explicit
+ * warm-up with {@link Warmup @Warmup}.
+ *
+ * @param defaultWarmup a new non-negative default warm-up.
+ * @return the same framework instance.
+ */
+ public TestFramework setDefaultWarmup(int defaultWarmup) {
+ TestFormat.check(defaultWarmup >= 0, "Cannot specify a negative default warm-up");
+ this.defaultWarmup = defaultWarmup;
+ 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()}.
+ *
+ * @return the last test VM output.
+ */
+ public static String getLastTestVMOutput() {
+ return TestVMProcess.getLastTestVMOutput();
+ }
+
+ /*
+ * The following methods are only intended to be called from actual @Test methods and not from the main() method of
+ * a JTreg test. Calling these methods from main() results in a linking exception (Whitebox not yet loaded and enabled).
+ */
+
+ /**
+ * Compile {@code m} at compilation level {@code compLevel}. {@code m} is first enqueued and might not be compiled,
+ * yet, upon returning from this method.
+ *
+ * @param m the method to be compiled.
+ * @param compLevel the (valid) compilation level at which the method should be compiled.
+ * @throws TestRunException if compilation level is {@link CompLevel#SKIP} or {@link CompLevel#WAIT_FOR_COMPILATION}.
+ */
+ public static void compile(Method m, CompLevel compLevel) {
+ TestVM.compile(m, compLevel);
+ }
+
+ /**
+ * Deoptimize {@code m}.
+ *
+ * @param m the method to be deoptimized.
+ */
+ public static void deoptimize(Method m) {
+ TestVM.deoptimize(m);
+ }
+
+ /**
+ * Returns a boolean indicating if {@code m} is compiled at any level.
+ *
+ * @param m the method to be checked.
+ * @return {@code true} if {@code m} is compiled at any level;
+ * {@code false} otherwise.
+ */
+ public static boolean isCompiled(Method m) {
+ return TestVM.isCompiled(m);
+ }
+
+ /**
+ * Returns a boolean indicating if {@code m} is compiled with C1.
+ *
+ * @param m the method to be checked.
+ * @return {@code true} if {@code m} is compiled with C1;
+ * {@code false} otherwise.
+ */
+ public static boolean isC1Compiled(Method m) {
+ return TestVM.isC1Compiled(m);
+ }
+
+ /**
+ * Returns a boolean indicating if {@code m} is compiled with C2.
+ *
+ * @param m the method to be checked.
+ * @return {@code true} if {@code m} is compiled with C2;
+ * {@code false} otherwise.
+ */
+ public static boolean isC2Compiled(Method m) {
+ return TestVM.isC2Compiled(m);
+ }
+
+ /**
+ * Returns a boolean indicating if {@code m} is compiled at the specified {@code compLevel}.
+ *
+ * @param m the method to be checked.
+ * @param compLevel the compilation level.
+ * @return {@code true} if {@code m} is compiled at {@code compLevel};
+ * {@code false} otherwise.
+ */
+ public static boolean isCompiledAtLevel(Method m, CompLevel compLevel) {
+ return TestVM.isCompiledAtLevel(m, compLevel);
+ }
+
+ /**
+ * Checks if {@code m} is compiled at any level.
+ *
+ * @param m the method to be checked.
+ * @throws TestRunException if {@code m} is not compiled at any level.
+ */
+ public static void assertCompiled(Method m) {
+ TestVM.assertCompiled(m);
+ }
+
+ /**
+ * Checks if {@code m} is not compiled at any level.
+ *
+ * @param m the method to be checked.
+ * @throws TestRunException if {@code m} is compiled at any level.
+ */
+ public static void assertNotCompiled(Method m) {
+ TestVM.assertNotCompiled(m);
+ }
+
+ /**
+ * Verifies that {@code m} is compiled with C1.
+ *
+ * @param m the method to be verified.
+ * @throws TestRunException if {@code m} is not compiled with C1.
+ */
+ public static void assertCompiledByC1(Method m) {
+ TestVM.assertCompiledByC1(m);
+ }
+
+ /**
+ * Verifies that {@code m} is compiled with C2.
+ *
+ * @param m the method to be checked.
+ * @throws TestRunException if {@code m} is not compiled with C2.
+ */
+ public static void assertCompiledByC2(Method m) {
+ TestVM.assertCompiledByC2(m);
+ }
+
+ /**
+ * Verifies that {@code m} is compiled at the specified {@code compLevel}.
+ *
+ * @param m the method to be checked.
+ * @param compLevel the compilation level.
+ * @throws TestRunException if {@code m} is not compiled at {@code compLevel}.
+ */
+ public static void assertCompiledAtLevel(Method m, CompLevel compLevel) {
+ TestVM.assertCompiledAtLevel(m, compLevel);
+ }
+
+ /**
+ * Verifies that {@code m} was deoptimized after being C1 compiled.
+ *
+ * @param m the method to be checked.
+ * @throws TestRunException if {@code m} is was not deoptimized after being C1 compiled.
+ */
+ public static void assertDeoptimizedByC1(Method m) {
+ TestVM.assertDeoptimizedByC1(m);
+ }
+
+ /**
+ * Verifies that {@code m} was deoptimized after being C2 compiled.
+ *
+ * @param m the method to be checked.
+ * @throws TestRunException if {@code m} is was not deoptimized after being C2 compiled.
+ */
+ public static void assertDeoptimizedByC2(Method m) {
+ TestVM.assertDeoptimizedByC2(m);
+ }
+
+ /**
+ * Returns a different boolean each time this method is invoked (switching between {@code false} and {@code true}).
+ * The very first invocation returns {@code false}. Note that this method could be used by different tests and
+ * thus the first invocation for a test could be {@code true} or {@code false} depending on how many times
+ * other tests have already invoked this method.
+ *
+ * @return an inverted boolean of the result of the last invocation of this method.
+ */
+ public static boolean toggleBoolean() {
+ toggleBool = !toggleBool;
+ return toggleBool;
+ }
+
+ /*
+ * End of public interface methods
+ */
+
+ /**
+ * Used to move Whitebox class to the right folder in the JTreg test
+ */
+ private void installWhiteBox() {
+ try {
+ ClassFileInstaller.main(WhiteBox.class.getName());
+ } catch (Exception e) {
+ throw new Error("failed to install whitebox classes", e);
+ }
+ }
+
+ /**
+ * Disable IR verification completely in certain cases.
+ */
+ private void disableIRVerificationIfNotFeasible() {
+ if (irVerificationPossible) {
+ irVerificationPossible = Platform.isDebugBuild() && !Platform.isInt() && !Platform.isComp();
+ if (!irVerificationPossible) {
+ System.out.println("IR verification disabled due to not running a debug build (required for PrintIdeal" +
+ "and PrintOptoAssembly), running with -Xint, or -Xcomp (use warm-up of 0 instead)");
+ return;
+ }
+
+ irVerificationPossible = hasIRAnnotations();
+ if (!irVerificationPossible) {
+ System.out.println("IR verification disabled due to test " + testClass + " not specifying any @IR annotations");
+ return;
+ }
+
+ // No IR verification is done if additional non-whitelisted JTreg VM or Javaoptions flag is specified.
+ irVerificationPossible = onlyWhitelistedJTregVMAndJavaOptsFlags();
+ if (!irVerificationPossible) {
+ System.out.println("IR verification disabled due to using non-whitelisted JTreg VM or Javaoptions flag(s)."
+ + System.lineSeparator());
+ }
+ }
+ }
+
+ /**
+ * For scenarios: Run the tests with the scenario settings and collect all exceptions to be able to run all
+ * scenarios without prematurely throwing an exception. Format violations, however, are wrong for all scenarios
+ * and thus is reported immediately on the first scenario execution.
+ */
+ private void startWithScenarios() {
+ Map exceptionMap = new TreeMap<>(Comparator.comparingInt(Scenario::getIndex));
+ for (Scenario scenario : scenarios) {
+ try {
+ start(scenario);
+ } catch (TestFormatException e) {
+ // Test format violation is wrong for all the scenarios. Only report once.
+ throw e;
+ } catch (Exception e) {
+ exceptionMap.put(scenario, e);
+ }
+ }
+ if (!exceptionMap.isEmpty()) {
+ reportScenarioFailures(exceptionMap);
+ }
+ }
+
+ private void reportScenarioFailures(Map exceptionMap) {
+ String failedScenarios = "The following scenarios have failed: #"
+ + exceptionMap.keySet().stream()
+ .map(s -> String.valueOf(s.getIndex()))
+ .collect(Collectors.joining(", #"));
+ StringBuilder builder = new StringBuilder(failedScenarios);
+ builder.append(System.lineSeparator()).append(System.lineSeparator());
+ for (Map.Entry entry : exceptionMap.entrySet()) {
+ Exception e = entry.getValue();
+ Scenario scenario = entry.getKey();
+ String errorMsg = "";
+ if (scenario != null) {
+ errorMsg = getScenarioTitleAndFlags(scenario);
+ }
+ if (e instanceof IRViolationException irException) {
+ // For IR violations, only show the actual violations and not the (uninteresting) stack trace.
+ System.out.println((scenario != null ? "Scenario #" + scenario.getIndex() + " - " : "")
+ + "Compilation(s) of failed matche(s):");
+ System.out.println(irException.getCompilations());
+ builder.append(errorMsg).append(System.lineSeparator()).append(irException.getExceptionInfo());
+ } else if (e instanceof TestVMException testVMException) {
+ builder.append(errorMsg).append(System.lineSeparator()).append(testVMException.getExceptionInfo());
+ } else {
+ // Print stack trace otherwise
+ StringWriter errors = new StringWriter();
+ e.printStackTrace(new PrintWriter(errors));
+ builder.append(errors.toString());
+ }
+ builder.append(System.lineSeparator());
+ }
+ System.err.println(builder.toString());
+ if (!VERBOSE && !REPORT_STDOUT && !TESTLIST && !EXCLUDELIST) {
+ // Provide a hint to the user how to get additional output/debugging information.
+ System.err.println(RERUN_HINT);
+ }
+ throw new TestRunException(failedScenarios + ". Please check stderr for more information.");
+ }
+
+ private static String getScenarioTitleAndFlags(Scenario scenario) {
+ StringBuilder builder = new StringBuilder();
+ String title = "Scenario #" + scenario.getIndex();
+ builder.append(title).append(System.lineSeparator()).append("=".repeat(title.length()))
+ .append(System.lineSeparator());
+ builder.append("Scenario flags: [").append(String.join(", ", scenario.getFlags())).append("]")
+ .append(System.lineSeparator());
+ return builder.toString();
+ }
+
+ /**
+ * Execute a separate "flag" VM with White Box access to determine all test VM flags. The flag VM sends an encoding of
+ * all required flags for the test VM to the driver VM over a socket. Once the flag VM exits, this driver VM parses the
+ * test VM flags, which also determine if IR matching should be done, and then starts the test VM to execute all tests.
+ */
+ private void start(Scenario scenario) {
+ if (scenario != null && !scenario.isEnabled()) {
+ System.out.println("Disabled scenario #" + scenario.getIndex() + "! This scenario is not present in set flag " +
+ "-DScenarios and is therefore not executed.");
+ return;
+ }
+ shouldVerifyIR = irVerificationPossible;
+ try {
+ // Use TestFramework flags and scenario flags for new VMs.
+ List additionalFlags = new ArrayList<>();
+ if (flags != null) {
+ additionalFlags.addAll(flags);
+ }
+ if (scenario != null) {
+ List scenarioFlags = scenario.getFlags();
+ String scenarioFlagsString = scenarioFlags.isEmpty() ? "" : " - [" + String.join(", ", scenarioFlags) + "]";
+ System.out.println("Scenario #" + scenario.getIndex() + scenarioFlagsString + ":");
+ additionalFlags.addAll(scenarioFlags);
+ }
+ String frameworkAndScenarioFlags = additionalFlags.isEmpty() ?
+ "" : " - [" + String.join(", ", additionalFlags) + "]";
+
+ if (shouldVerifyIR) {
+ // Only need to use flag VM if an IR verification is possibly done.
+ System.out.println("Run Flag VM:");
+ FlagVMProcess flagVMProcess = new FlagVMProcess(testClass, additionalFlags);
+ shouldVerifyIR = flagVMProcess.shouldVerifyIR();
+ if (shouldVerifyIR) {
+ // Add more flags for the test VM which are required to do IR verification.
+ additionalFlags.addAll(flagVMProcess.getTestVMFlags());
+ } // else: Flag VM found a reason to not do IR verification.
+ } else {
+ System.out.println("Skip Flag VM due to not performing IR verification.");
+ }
+
+ System.out.println("Run Test VM" + frameworkAndScenarioFlags + ":");
+ runTestVM(additionalFlags);
+ } finally {
+ if (scenario != null) {
+ scenario.setTestVMOutput(TestVMProcess.getLastTestVMOutput());
+ }
+ System.out.println();
+ }
+ }
+
+ private boolean hasIRAnnotations() {
+ return Arrays.stream(testClass.getDeclaredMethods()).anyMatch(m -> m.getAnnotationsByType(IR.class) != null);
+ }
+
+ private boolean onlyWhitelistedJTregVMAndJavaOptsFlags() {
+ List flags = Arrays.stream(Utils.getTestJavaOpts())
+ .map(s -> s.replaceFirst("-XX:[+|-]?|-(?=[^D|^e])", ""))
+ .collect(Collectors.toList());
+ for (String flag : flags) {
+ // Property flags (prefix -D), -ea and -esa are whitelisted.
+ if (!flag.startsWith("-D") && !flag.startsWith("-e") && JTREG_WHITELIST_FLAGS.stream().noneMatch(flag::contains)) {
+ // Found VM flag that is not whitelisted
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void runTestVM(List additionalFlags) {
+ TestVMProcess testVMProcess = new TestVMProcess(additionalFlags, testClass, helperClasses, defaultWarmup);
+ if (shouldVerifyIR) {
+ try {
+ new IRMatcher(testVMProcess.getHotspotPidFileName(), testVMProcess.getIrEncoding(), testClass);
+ } catch (IRViolationException e) {
+ e.addCommandLine(testVMProcess.getCommandLine());
+ throw e;
+ }
+ } else {
+ System.out.println("IR verification disabled either due to no @IR annotations, through explicitly setting " +
+ "-DVerify=false, due to not running a debug build, using a non-whitelisted JTreg VM or " +
+ "Javaopts flag like -Xint, or running the test VM with other VM flags added by user code " +
+ "that make the IR verification impossible (e.g. -XX:-UseCompile, " +
+ "-XX:TieredStopAtLevel=[1,2,3], etc.).");
+ }
+ }
+
+ public static void check(boolean test, String failureMessage) {
+ if (!test) {
+ throw new TestFrameworkException(failureMessage);
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestInfo.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestInfo.java
new file mode 100644
index 00000000000..1e06ade3d80
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestInfo.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.test.DeclaredTest;
+import compiler.lib.ir_framework.test.TestVM;
+
+import java.lang.reflect.Method;
+
+/**
+ * Test info class which provides some useful utility methods and information about a checked test.
+ *
+ * @see Test
+ * @see Check
+ */
+public class TestInfo extends AbstractInfo {
+ private final Method testMethod;
+ private final boolean compilationSkipped;
+
+ public TestInfo(Method testMethod, CompLevel testCmpLevel) {
+ super(testMethod.getDeclaringClass());
+ this.testMethod = testMethod;
+ this.compilationSkipped = testCmpLevel == CompLevel.SKIP;
+ }
+
+ /**
+ * Get the associated test method object.
+ *
+ * @return the associated test method object.
+ */
+ public Method getTest() {
+ return testMethod;
+ }
+
+ /**
+ * Return a boolean indicating if the framework skipped a compilation after the warm-up due to VM flags not
+ * allowing a compilation on the requested level in {@link Test#compLevel()}.
+ *
+ * @return {@code true} if the framework skipped compilation of the test;
+ * {@code false} otherwise.
+ */
+ public boolean isCompilationSkipped() {
+ return compilationSkipped;
+ }
+
+ /**
+ * Returns a boolean indicating if the associated test method is C1 compiled.
+ *
+ * @return {@code true} if the test method is C1 compiled;
+ * {@code false} otherwise.
+ */
+ public boolean isC1Compiled() {
+ return TestVM.isC1Compiled(testMethod);
+ }
+
+ /**
+ * Returns a boolean indicating if the associated test method is C2 compiled.
+ *
+ * @return {@code true} if the test method is C2 compiled;
+ * {@code false} otherwise.
+ */
+ public boolean isC2Compiled() {
+ return TestVM.isC2Compiled(testMethod);
+ }
+
+ /**
+ * Returns a boolean indicating if the associated test method is compiled at {@code compLevel}.
+ *
+ * @param compLevel the compilation level.
+ * @return {@code true} if the test method is compiled at {@code compLevel};
+ * {@code false} otherwise.
+ */
+ public boolean isCompiledAtLevel(CompLevel compLevel) {
+ return TestVM.isCompiledAtLevel(testMethod, compLevel);
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/Warmup.java b/test/hotspot/jtreg/compiler/lib/ir_framework/Warmup.java
new file mode 100644
index 00000000000..af17acb0719
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/Warmup.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This annotation overrides the default number (2000) of times the framework should warm up a test.
+ *
+ * Any positive value or zero is permitted. A warm-up of zero allows a simulation of {@code -Xcomp}.
+ * Custom run tests (see {@link Run}) must specify a {@code @Warmup} annotation at the run method.
+ * Base and checked tests (see {@link Test}, {@link Check}) must specify a {@code @Warmup} annotation at
+ * the test method.
+ *
+ *
+ * @see Test
+ * @see Check
+ * @see Run
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Warmup {
+ /**
+ * The warm-up iterations for the test.
+ */
+ int value();
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/FlagVMProcess.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/FlagVMProcess.java
new file mode 100644
index 00000000000..c39b045b07f
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/FlagVMProcess.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.TestFramework;
+import compiler.lib.ir_framework.shared.TestFrameworkException;
+import compiler.lib.ir_framework.flag.FlagVM;
+import compiler.lib.ir_framework.shared.TestRunException;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This class prepares, creates, and runs the "flag" VM with verification of proper termination. The flag VM determines
+ * the flags required for the "test" VM. The flag VM writes these flags to a dedicated file which is then parsed by this
+ * class after the termination of the flag VM.
+ *
+ * @see FlagVM
+ */
+public class FlagVMProcess {
+ private static final boolean VERBOSE = Boolean.getBoolean("Verbose");
+
+ private final List cmds;
+ private final List testVMFlags;
+ private boolean shouldVerifyIR;
+ private String testVMFlagsFile;
+ private OutputAnalyzer oa;
+
+ public FlagVMProcess(Class> testClass, List additionalFlags) {
+ cmds = new ArrayList<>();
+ testVMFlags = new ArrayList<>();
+ prepareVMFlags(testClass, additionalFlags);
+ start();
+ parseTestVMFlags();
+ }
+
+ private void parseTestVMFlags() {
+ String flags = readFlagsFromFile();
+ if (VERBOSE) {
+ System.out.println("Read data from " + testVMFlagsFile + ":");
+ System.out.println(flags);
+ }
+ String patternString = "(.*DShouldDoIRVerification=(true|false).*)";
+ Pattern pattern = Pattern.compile(patternString);
+ Matcher matcher = pattern.matcher(flags);
+ TestFramework.check(matcher.find(), "Invalid flag encoding emitted by flag VM");
+ // Maybe we run with flags that make IR verification impossible
+ shouldVerifyIR = Boolean.parseBoolean(matcher.group(2));
+ testVMFlags.addAll(Arrays.asList(matcher.group(1).split(FlagVM.TEST_VM_FLAGS_DELIMITER)));
+ }
+
+ private String readFlagsFromFile() {
+ try (var br = Files.newBufferedReader(Paths.get(testVMFlagsFile))) {
+ String flags = br.readLine();
+ TestFramework.check(br.readLine() == null, testVMFlagsFile + " should only contain one line.");
+ return flags;
+
+ } catch (IOException e) {
+ throw new TestFrameworkException("Error while reading from file " + testVMFlagsFile, e);
+ }
+ }
+
+ /**
+ * The flag VM needs White Box access to prepare all test VM flags. The flag VM will write the test VM flags to
+ * a dedicated file which is afterwards parsed by the driver VM and added as flags to the test VM.
+ */
+ private void prepareVMFlags(Class> testClass, List additionalFlags) {
+ cmds.add("-Dtest.jdk=" + Utils.TEST_JDK);
+ // Set java.library.path so JNI tests which rely on jtreg nativepath setting work
+ cmds.add("-Djava.library.path=" + Utils.TEST_NATIVE_PATH);
+ cmds.add("-cp");
+ cmds.add(Utils.TEST_CLASS_PATH);
+ cmds.add("-Xbootclasspath/a:.");
+ cmds.add("-XX:+UnlockDiagnosticVMOptions");
+ cmds.add("-XX:+WhiteBoxAPI");
+ // TestFramework and scenario flags might have an influence on the later used test VM flags. Add them as well.
+ cmds.addAll(additionalFlags);
+ cmds.add(FlagVM.class.getCanonicalName());
+ cmds.add(testClass.getCanonicalName());
+ }
+
+ private void start() {
+ try {
+ // Run "flag" VM with White Box access to determine the test VM flags and if IR verification should be done.
+ oa = ProcessTools.executeTestJvm(cmds);
+ } catch (Exception e) {
+ throw new TestRunException("Failed to execute TestFramework flag VM", e);
+ }
+ testVMFlagsFile = FlagVM.TEST_VM_FLAGS_FILE_PREFIX + oa.pid()
+ + FlagVM.TEST_VM_FLAGS_FILE_POSTFIX;
+ checkFlagVMExitCode();
+ }
+
+ private void checkFlagVMExitCode() {
+ String flagVMOutput = oa.getOutput();
+ int exitCode = oa.getExitValue();
+ if (VERBOSE && exitCode == 0) {
+ System.out.println("--- OUTPUT TestFramework flag VM ---");
+ System.out.println(flagVMOutput);
+ }
+
+ if (exitCode != 0) {
+ System.err.println("--- OUTPUT TestFramework flag VM ---");
+ System.err.println(flagVMOutput);
+ throw new RuntimeException("TestFramework flag VM exited with " + exitCode);
+ }
+ }
+
+ public List getTestVMFlags() {
+ return testVMFlags;
+ }
+
+ public boolean shouldVerifyIR() {
+ return shouldVerifyIR;
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRMatcher.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRMatcher.java
new file mode 100644
index 00000000000..8fb94eb4a64
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRMatcher.java
@@ -0,0 +1,493 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.*;
+import compiler.lib.ir_framework.shared.*;
+import compiler.lib.ir_framework.test.*;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Parse the hotspot pid file of the test VM to match all @IR rules.
+ */
+public class IRMatcher {
+ private static final boolean PRINT_IR_ENCODING = Boolean.parseBoolean(System.getProperty("PrintIREncoding", "false"));
+ private static final Pattern IR_ENCODING_PATTERN =
+ Pattern.compile("(?<=" + IREncodingPrinter.START + "\r?\n)[\\s\\S]*(?=" + IREncodingPrinter.END + ")");
+ private static final Pattern COMPILE_ID_PATTERN = Pattern.compile("compile_id='(\\d+)'");
+
+ private final Map compilations;
+ private final Class> testClass;
+ private final Map> fails;
+ private final Pattern compileIdPatternForTestClass;
+ private final String hotspotPidFileName;
+ private IRMethod irMethod; // Current IR method to which rules are applied
+ private Method method; // Current method to which rules are applied
+ private IR irAnno; // Current IR annotation that is processed.
+ private int irRuleIndex; // Current IR rule index;
+
+ public IRMatcher(String hotspotPidFileName, String irEncoding, Class> testClass) {
+ this.compilations = new HashMap<>();
+ this.fails = new HashMap<>();
+ this.testClass = testClass;
+ this.compileIdPatternForTestClass = Pattern.compile("compile_id='(\\d+)'.*" + Pattern.quote(testClass.getCanonicalName())
+ + " (\\S+)");
+ this.hotspotPidFileName = hotspotPidFileName;
+ setupTestMethods(irEncoding);
+ if (TestFramework.VERBOSE || PRINT_IR_ENCODING) {
+ System.out.println("Read IR encoding from test VM:");
+ System.out.println(irEncoding);
+ }
+ if (!compilations.isEmpty()) {
+ parseHotspotPidFile();
+ applyRules();
+ }
+ }
+
+ /**
+ * Sets up a map testname -> IRMethod (containing the PrintIdeal and PrintOptoAssembly output for testname).
+ */
+ private void setupTestMethods(String irEncoding) {
+ Map irRulesMap = parseIREncoding(irEncoding);
+ for (Method m : testClass.getDeclaredMethods()) {
+ method = m;
+ 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.
+ int[] ids = irRulesMap.get(m.getName());
+ TestFramework.check(ids != null, "Should find method name in validIrRulesMap for " + m);
+ TestFramework.check(ids.length > 0, "Did not find any rule indices for " + m);
+ TestFramework.check(ids[ids.length - 1] < irAnnos.length, "Invalid IR rule index found in validIrRulesMap for " + m);
+ if (ids[0] != IREncodingPrinter.NO_RULE_APPLIED) {
+ // If -1, than there was no matching IR rule for the given conditions.
+ compilations.put(m.getName(), new IRMethod(m, ids, irAnnos));
+ }
+ }
+ }
+ }
+
+ /**
+ * Read the IR encoding emitted by the test VM to decide if an @IR rule must be checked for a method.
+ */
+ private Map parseIREncoding(String irEncoding) {
+ Map irRulesMap = new HashMap<>();
+ Matcher matcher = IR_ENCODING_PATTERN.matcher(irEncoding);
+ TestFramework.check(matcher.find(), "Did not find IR encoding");
+ String[] lines = matcher.group(0).split("\\R");
+
+ // Skip first line containing information about the format only
+ for (int i = 1; i < lines.length; i++) {
+ String line = lines[i].trim();
+ String[] splitComma = line.split(",");
+ if (splitComma.length < 2) {
+ throw new TestFrameworkException("Invalid IR match rule encoding. No comma found: " + splitComma[0]);
+ }
+ String testName = splitComma[0];
+ int[] irRulesIdx = new int[splitComma.length - 1];
+ for (int j = 1; j < splitComma.length; j++) {
+ try {
+ irRulesIdx[j - 1] = Integer.parseInt(splitComma[j]);
+ } catch (NumberFormatException e) {
+ throw new TestFrameworkException("Invalid IR match rule encoding. No number found: " + splitComma[j]);
+ }
+ }
+ irRulesMap.put(testName, irRulesIdx);
+ }
+ return irRulesMap;
+ }
+
+ /**
+ * Parse the hotspot_pid*.log file from the test VM. Read the PrintIdeal and PrintOptoAssembly entries for all
+ * methods of the test class that need to be IR matched (according to IR encoding).
+ */
+ private void parseHotspotPidFile() {
+ Map compileIdMap = new HashMap<>();
+ try (var br = Files.newBufferedReader(Paths.get(hotspotPidFileName))) {
+ String line;
+ StringBuilder builder = new StringBuilder();
+ boolean append = false;
+ String currentMethod = "";
+ while ((line = br.readLine()) != null) {
+ if (append && line.startsWith("")) {
+ flushOutput(line, builder, currentMethod);
+ append = false;
+ currentMethod = "";
+ continue;
+ } else if (append) {
+ appendLine(builder, line);
+ continue;
+ }
+
+ if (maybeTestEntry(line)) {
+ addTestMethodCompileId(compileIdMap, line);
+ } else if (isPrintIdealStart(line)) {
+ String methodName = getMethodName(compileIdMap, line);
+ if (methodName != null) {
+ currentMethod = methodName;
+ append = true; // Append all following lines until we hit the closing tag.
+ }
+ } else if (isPrintOptoAssemblyStart(line)) {
+ String methodName = getMethodName(compileIdMap, line);
+ if (methodName != null) {
+ TestFramework.check(compilations.containsKey(methodName), "Must be second entry of " + methodName);
+ currentMethod = methodName;
+ append = true; // Append all following lines until we hit the closing tag.
+ }
+ }
+ }
+ } catch (IOException e) {
+ throw new TestFrameworkException("Error while reading " + hotspotPidFileName, e);
+ }
+ }
+
+ /**
+ * Write the input to the IR method and reset the builder.
+ */
+ private void flushOutput(String line, StringBuilder builder, String currentMethod) {
+ TestFramework.check(!currentMethod.isEmpty(), "current method must be set");
+ IRMethod irMethod = compilations.get(currentMethod);
+ if (line.startsWith("");
+ line = line.replace(""", "\"");
+ line = line.replace("'", "'");
+ line = line.replace("&", "&");
+ }
+ builder.append(line).append(System.lineSeparator());
+ }
+
+ private static int getCompileId(Matcher matcher) {
+ int compileId;
+ try {
+ compileId = Integer.parseInt(matcher.group(1));
+ } catch (NumberFormatException e) {
+ throw new TestRunException("Could not parse compile id", e);
+ }
+ return compileId;
+ }
+
+ /**
+ * Parse the compile id from this line if it belongs to a method that needs to be IR tested (part of test class
+ * and IR encoding from the test VM specifies that this method has @IR rules to be checked).
+ */
+ private void addTestMethodCompileId(Map compileIdMap, String line) {
+ Matcher matcher = compileIdPatternForTestClass.matcher(line);
+ if (matcher.find()) {
+ // Only care about test class entries. Might have non-class entries as well if user specified additional
+ // compile commands. Ignore these.
+ String methodName = matcher.group(2);
+ if (compilations.containsKey(methodName)) {
+ // We only care about methods that we are actually gonna IR match based on IR encoding.
+ int compileId = getCompileId(matcher);
+ TestRun.check(!methodName.isEmpty(), "method name cannot be empty");
+ compileIdMap.put(compileId, methodName);
+ }
+ }
+ }
+
+ /**
+ * Make sure that line does not contain compile_kind which is used for OSR compilations which we are not
+ * interested in.
+ */
+ private static boolean isPrintIdealStart(String line) {
+ return line.startsWith(" compileIdMap, String line) {
+ Matcher matcher = COMPILE_ID_PATTERN.matcher(line);
+ TestFramework.check(matcher.find(), "Is " + hotspotPidFileName + " corrupted?");
+ int compileId = getCompileId(matcher);
+ return compileIdMap.get(compileId);
+ }
+
+ /**
+ * Do an IR matching of all methods with appliable @IR rules fetched during parsing of the hotspot pid file.
+ */
+ private void applyRules() {
+ compilations.values().forEach(this::applyRulesForMethod);
+ reportFailuresIfAny();
+ }
+
+ private void applyRulesForMethod(IRMethod irMethod) {
+ this.irMethod = irMethod;
+ method = irMethod.getMethod();
+ String testOutput = irMethod.getOutput();
+ if (testOutput.isEmpty()) {
+ String msg = "Method was not compiled. Did you specify any compiler directives preventing a compilation or used a " +
+ "@Run method in STANDALONE mode? In the latter case, make sure to always trigger a C2 compilation " +
+ "by invoking the test enough times.";
+ fails.computeIfAbsent(method, k -> new ArrayList<>()).add(msg);
+ return;
+ }
+
+ if (TestFramework.VERBOSE) {
+ System.out.println("Output of " + method + ":");
+ System.out.println(testOutput);
+ }
+ Arrays.stream(irMethod.getRuleIds()).forEach(this::applyIRRule);
+ }
+
+ /**
+ * Apply a single @IR rule as part of a method.
+ */
+ private void applyIRRule(int id) {
+ irAnno = irMethod.getIrAnno(id);
+ irRuleIndex = id;
+ StringBuilder failMsg = new StringBuilder();
+ applyFailOn(failMsg);
+ try {
+ applyCounts(failMsg);
+ } catch (TestFormatException e) {
+ // Logged. Continue to check other rules.
+ }
+ if (!failMsg.isEmpty()) {
+ failMsg.insert(0, "@IR rule " + (id + 1) + ": \"" + irAnno + "\"" + System.lineSeparator());
+ fails.computeIfAbsent(method, k -> new ArrayList<>()).add(failMsg.toString());
+ }
+ }
+
+ /**
+ * Apply the failOn regexes of the @IR rule.
+ */
+ private void applyFailOn(StringBuilder failMsg) {
+ if (irAnno.failOn().length != 0) {
+ String failOnRegex = String.join("|", IRNode.mergeNodes(irAnno.failOn()));
+ Pattern pattern = Pattern.compile(failOnRegex);
+ Matcher matcher = pattern.matcher(irMethod.getOutput());
+ long matchCount = matcher.results().count();
+ if (matchCount > 0) {
+ addFailOnFailsForOutput(failMsg, pattern, matchCount);
+ }
+ }
+ }
+
+ /**
+ * A failOn regex failed. Apply all regexes again to log the exact regex which failed. The failure is later reported
+ * to the user.
+ */
+ private void addFailOnFailsForOutput(StringBuilder failMsg, Pattern pattern, long matchCount) {
+ long idealCount = pattern.matcher(irMethod.getIdealOutput()).results().count();
+ long optoAssemblyCount = pattern.matcher(irMethod.getOptoAssemblyOutput()).results().count();
+ if (matchCount != idealCount + optoAssemblyCount || (idealCount != 0 && optoAssemblyCount != 0)) {
+ // Report with Ideal and Opto Assembly
+ addFailOnFailsForOutput(failMsg, irMethod.getOutput());
+ irMethod.needsAllOutput();
+ } else if (optoAssemblyCount == 0) {
+ // Report with Ideal only
+ addFailOnFailsForOutput(failMsg, irMethod.getIdealOutput());
+ irMethod.needsIdeal();
+ } else {
+ // Report with Opto Assembly only
+ addFailOnFailsForOutput(failMsg, irMethod.getOptoAssemblyOutput());
+ irMethod.needsOptoAssembly();
+ }
+ }
+
+ /**
+ * Apply the regexes to the testOutput and log the failures.
+ */
+ private void addFailOnFailsForOutput(StringBuilder failMsg, String testOutput) {
+ List failOnNodes = IRNode.mergeNodes(irAnno.failOn());
+ Pattern pattern;
+ Matcher matcher;
+ failMsg.append("- failOn: Graph contains forbidden nodes:").append(System.lineSeparator());
+ int nodeId = 1;
+ for (String nodeRegex : failOnNodes) {
+ pattern = Pattern.compile(nodeRegex);
+ matcher = pattern.matcher(testOutput);
+ long matchCount = matcher.results().count();
+ if (matchCount > 0) {
+ matcher.reset();
+ failMsg.append(" Regex ").append(nodeId).append(": ").append(nodeRegex).append(System.lineSeparator());
+ failMsg.append(" Matched forbidden node").append(matchCount > 1 ? "s (" + matchCount + ")" : "")
+ .append(":").append(System.lineSeparator());
+ matcher.results().forEach(r -> failMsg.append(" ").append(r.group()).append(System.lineSeparator()));
+ }
+ nodeId++;
+ }
+ }
+
+ /**
+ * Apply the counts regexes of the @IR rule.
+ */
+ private void applyCounts(StringBuilder failMsg) {
+ if (irAnno.counts().length != 0) {
+ boolean hasFails = false;
+ String testOutput = irMethod.getOutput();
+ int countsId = 1;
+ final List nodesWithCount = IRNode.mergeNodes(irAnno.counts());
+ for (int i = 0; i < nodesWithCount.size(); i += 2) {
+ String node = nodesWithCount.get(i);
+ TestFormat.check(i + 1 < nodesWithCount.size(), "Missing count" + getPostfixErrorMsg(node));
+ String countString = nodesWithCount.get(i + 1);
+ long expectedCount;
+ ParsedComparator parsedComparator;
+ try {
+ parsedComparator = ParsedComparator.parseComparator(countString);
+ expectedCount = Long.parseLong(parsedComparator.getStrippedString());
+ } catch (NumberFormatException e) {
+ TestFormat.fail("Provided invalid count \"" + countString + "\"" + getPostfixErrorMsg(node));
+ return;
+ } catch (CheckedTestFrameworkException e) {
+ TestFormat.fail("Invalid comparator \"" + e.getMessage() + "\" in \"" + countString + "\" for count" + getPostfixErrorMsg(node));
+ return;
+ } catch (IndexOutOfBoundsException e) {
+ TestFormat.fail("Provided empty value" + getPostfixErrorMsg(node));
+ return;
+ }
+ TestFormat.check(expectedCount >= 0,"Provided invalid negative count \"" + countString + "\"" + getPostfixErrorMsg(node));
+
+ Pattern pattern = Pattern.compile(node);
+ Matcher matcher = pattern.matcher(testOutput);
+ long actualCount = matcher.results().count();
+ if (!parsedComparator.getPredicate().test(actualCount, expectedCount)) {
+ if (!hasFails) {
+ failMsg.append("- counts: Graph contains wrong number of nodes:").append(System.lineSeparator());
+ hasFails = true;
+ }
+ addCountsFail(failMsg, node, pattern, expectedCount, actualCount, countsId);
+ }
+ countsId++;
+ }
+ }
+ }
+
+ private String getPostfixErrorMsg(String node) {
+ return " for IR rule " + irRuleIndex + ", node \"" + node + "\" at " + method;
+ }
+
+ /**
+ * A counts regex failed. Apply all regexes again to log the exact regex which failed. The failure is later reported
+ * to the user.
+ */
+ private void addCountsFail(StringBuilder failMsg, String node, Pattern pattern, long expectedCount, long actualCount, int countsId) {
+ failMsg.append(" Regex ").append(countsId).append(": ").append(node).append(System.lineSeparator());
+ failMsg.append(" Expected ").append(expectedCount).append(" but found ").append(actualCount);
+
+ if (actualCount > 0) {
+ Matcher matcher = pattern.matcher(irMethod.getOutput());
+ long idealCount = pattern.matcher(irMethod.getIdealOutput()).results().count();
+ long optoAssemblyCount = pattern.matcher(irMethod.getOptoAssemblyOutput()).results().count();
+ if (actualCount != idealCount + optoAssemblyCount || (idealCount != 0 && optoAssemblyCount != 0)) {
+ irMethod.needsAllOutput();
+ } else if (optoAssemblyCount == 0) {
+ irMethod.needsIdeal();
+ } else {
+ irMethod.needsOptoAssembly();
+ }
+ failMsg.append(" node").append(actualCount > 1 ? "s" : "").append(":").append(System.lineSeparator());
+ matcher.results().forEach(r -> failMsg.append(" ").append(r.group()).append(System.lineSeparator()));
+ } else {
+ irMethod.needsAllOutput();
+ failMsg.append(" nodes.").append(System.lineSeparator());
+ }
+ }
+
+ /**
+ * Report all IR violations in a pretty format to the user. Depending on the failed regex, we only report
+ * PrintIdeal or PrintOptoAssembly if the match failed there. If there were failures that matched things
+ * in both outputs than the entire output is reported. Throws IRViolationException from which the compilation
+ * can be read and reported to the stdout separately. The exception message only includes the summary of the
+ * failures.
+ */
+ private void reportFailuresIfAny() {
+ TestFormat.reportIfAnyFailures();
+ if (!fails.isEmpty()) {
+ StringBuilder failuresBuilder = new StringBuilder();
+ StringBuilder compilationsBuilder = new StringBuilder();
+ int failures = 0;
+ for (Map.Entry> entry : fails.entrySet()) {
+ Method method = entry.getKey();
+ compilationsBuilder.append(">>> Compilation of ").append(method).append(":").append(System.lineSeparator());
+ IRMethod irMethod = compilations.get(method.getName());
+ String output;
+ if (irMethod.usesIdeal() && irMethod.usesOptoAssembly()) {
+ output = irMethod.getOutput();
+ } else if (irMethod.usesIdeal()) {
+ output = irMethod.getIdealOutput();
+ } else if (irMethod.usesOptoAssembly()) {
+ output = irMethod.getOptoAssemblyOutput();
+ } else {
+ output = "";
+ }
+ compilationsBuilder.append(output).append(System.lineSeparator()).append(System.lineSeparator());
+ List list = entry.getValue();
+ failuresBuilder.append("- Method \"").append(method).append("\":").append(System.lineSeparator());
+ failures += list.size();
+ list.forEach(s -> failuresBuilder.append(" * ")
+ .append(s.replace(System.lineSeparator(),
+ System.lineSeparator() + " ").trim())
+ .append(System.lineSeparator()));
+ failuresBuilder.append(System.lineSeparator());
+ }
+ failuresBuilder.insert(0, ("One or more @IR rules failed:" + System.lineSeparator()
+ + System.lineSeparator() + "Failed IR Rules (" + failures + ")"
+ + System.lineSeparator()) + "-----------------"
+ + "-".repeat(String.valueOf(failures).length()) + System.lineSeparator());
+ failuresBuilder.append(">>> Check stdout for compilation output of the failed methods")
+ .append(System.lineSeparator()).append(System.lineSeparator());
+ throw new IRViolationException(failuresBuilder.toString(), compilationsBuilder.toString());
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRMethod.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRMethod.java
new file mode 100644
index 00000000000..dbad17034af
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRMethod.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.IR;
+
+import java.lang.reflect.Method;
+
+/**
+ * Helper class to store information about a method that needs to be IR matched.
+ */
+class IRMethod {
+ private final Method method;
+ private final int[] ruleIds;
+ private final IR[] irAnnos;
+ private final StringBuilder outputBuilder;
+ private String output;
+ private String idealOutput;
+ private String optoAssemblyOutput;
+ private boolean needsIdeal;
+ private boolean needsOptoAssembly;
+
+ public IRMethod(Method method, int[] ruleIds, IR[] irAnnos) {
+ this.method = method;
+ this.ruleIds = ruleIds;
+ this.irAnnos = irAnnos;
+ this.outputBuilder = new StringBuilder();
+ this.output = "";
+ this.idealOutput = "";
+ this.optoAssemblyOutput = "";
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+
+ public int[] getRuleIds() {
+ return ruleIds;
+ }
+
+ public IR getIrAnno(int idx) {
+ return irAnnos[idx];
+ }
+
+ /**
+ * The Ideal output comes always before the Opto Assembly output. We might parse multiple C2 compilations of this method.
+ * Only keep the very last one by overriding 'output'.
+ */
+ public void setIdealOutput(String idealOutput) {
+ outputBuilder.setLength(0);
+ this.idealOutput = "PrintIdeal:" + System.lineSeparator() + idealOutput;
+ outputBuilder.append(this.idealOutput);
+ }
+
+ /**
+ * The Opto Assembly output comes after the Ideal output. Simply append to 'output'.
+ */
+ public void setOptoAssemblyOutput(String optoAssemblyOutput) {
+ this.optoAssemblyOutput = "PrintOptoAssembly:" + System.lineSeparator() + optoAssemblyOutput;
+ outputBuilder.append(System.lineSeparator()).append(System.lineSeparator()).append(this.optoAssemblyOutput);
+ output = outputBuilder.toString();
+ }
+
+ public String getOutput() {
+ return output;
+ }
+
+ public String getIdealOutput() {
+ return idealOutput;
+ }
+
+ public String getOptoAssemblyOutput() {
+ return optoAssemblyOutput;
+ }
+
+ public void needsAllOutput() {
+ needsIdeal();
+ needsOptoAssembly();
+ }
+
+ public void needsIdeal() {
+ needsIdeal = true;
+ }
+
+ public boolean usesIdeal() {
+ return needsIdeal;
+ }
+
+ public void needsOptoAssembly() {
+ needsOptoAssembly = true;
+ }
+
+ public boolean usesOptoAssembly() {
+ return needsOptoAssembly;
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRViolationException.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRViolationException.java
new file mode 100644
index 00000000000..bacf3536dad
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/IRViolationException.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.IR;
+import compiler.lib.ir_framework.Test;
+
+/**
+ * Exception that is thrown if an {@link IR} rule/constraint failed. The exception message contains a detailed list of
+ * all failures, including failing method(s), {@code @IR} rule(s) (the first {@code @IR} constraint is rule 1) and the
+ * specific regex(es) that could not be matched.
+ *
+ * @see IR
+ * @see Test
+ */
+public class IRViolationException extends RuntimeException {
+ private final String compilations;
+ private String exceptionInfo;
+
+ IRViolationException(String message, String compilations) {
+ super("There were one or multiple IR rule failures. Please check stderr for more information.");
+ this.exceptionInfo = message;
+ this.compilations = compilations;
+ }
+
+ /**
+ * Get some more detailed information about the violated IR rule(s) and how to reproduce it.
+ *
+ * @return a formatted string containing information about the violated IR rule(s) and how to reproduce it.
+ */
+ public String getExceptionInfo() {
+ return exceptionInfo;
+ }
+
+ public String getCompilations() {
+ return compilations;
+ }
+
+ public void addCommandLine(String commandLine) {
+ this.exceptionInfo = commandLine + System.lineSeparator() + exceptionInfo;
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMException.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMException.java
new file mode 100644
index 00000000000..63b3d522b86
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMException.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.shared.TestFormatException;
+
+/**
+ * Exception that is thrown if the test VM has thrown any kind of exception (except for {@link TestFormatException}).
+ */
+public class TestVMException extends RuntimeException {
+ private final String exceptionInfo;
+
+ TestVMException(String exceptionInfo) {
+ super("There were one or multiple errors. Please check stderr for more information.");
+ this.exceptionInfo = exceptionInfo;
+ }
+
+ /**
+ * Get some more detailed information about the exception thrown in the test VM and how to reproduce it.
+ *
+ * @return a formatted string containing information about the exception of the test VM and how to reproduce it.
+ */
+ public String getExceptionInfo() {
+ return exceptionInfo;
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java
new file mode 100644
index 00000000000..ed8484e54bc
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2021, 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;
+
+import compiler.lib.ir_framework.TestFramework;
+import compiler.lib.ir_framework.shared.TestFrameworkException;
+import compiler.lib.ir_framework.shared.TestFrameworkSocket;
+import compiler.lib.ir_framework.shared.NoTestsRunException;
+import compiler.lib.ir_framework.shared.TestFormatException;
+import compiler.lib.ir_framework.test.TestVM;
+import jdk.test.lib.Platform;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This class prepares, creates, and runs the "test" VM with verification of proper termination. The class also stores
+ * information about the test VM which is later queried for IR matching. The communication between this driver VM
+ * and the test VM is done over a dedicated socket.
+ *
+ * @see TestVM
+ * @see TestFrameworkSocket
+ */
+public class TestVMProcess {
+ private static final boolean VERBOSE = Boolean.getBoolean("Verbose");
+ private static final boolean PREFER_COMMAND_LINE_FLAGS = Boolean.getBoolean("PreferCommandLineFlags");
+ private static final int WARMUP_ITERATIONS = Integer.getInteger("Warmup", -1);
+ private static final boolean VERIFY_VM = Boolean.getBoolean("VerifyVM") && Platform.isDebugBuild();
+ private static final boolean REPORT_STDOUT = Boolean.getBoolean("ReportStdout");
+ private static final boolean EXCLUDE_RANDOM = Boolean.getBoolean("ExcludeRandom");
+
+ private static String lastTestVMOutput = "";
+
+ private final ArrayList cmds;
+ private String hotspotPidFileName;
+ private String commandLine;
+ private OutputAnalyzer oa;
+ private String irEncoding;
+
+ public TestVMProcess(List additionalFlags, Class> testClass, Set> helperClasses, int defaultWarmup) {
+ this.cmds = new ArrayList<>();
+ TestFrameworkSocket socket = new TestFrameworkSocket();
+ try (socket) {
+ prepareTestVMFlags(additionalFlags, socket, testClass, helperClasses, defaultWarmup);
+ start();
+ }
+ processSocketOutput(socket.getOutput());
+ checkTestVMExitCode();
+ }
+
+ public String getCommandLine() {
+ return commandLine;
+ }
+
+ public String getIrEncoding() {
+ return irEncoding;
+ }
+
+ public String getHotspotPidFileName() {
+ return hotspotPidFileName;
+ }
+
+ public static String getLastTestVMOutput() {
+ return lastTestVMOutput;
+ }
+
+ private void prepareTestVMFlags(List additionalFlags, TestFrameworkSocket socket, Class> testClass,
+ Set> helperClasses, int defaultWarmup) {
+ // 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.
+ cmds.add("-Xbootclasspath/a:.");
+ cmds.add("-XX:+UnlockDiagnosticVMOptions");
+ cmds.add("-XX:+WhiteBoxAPI");
+ String[] jtregVMFlags = Utils.getTestJavaOpts();
+ if (!PREFER_COMMAND_LINE_FLAGS) {
+ cmds.addAll(Arrays.asList(jtregVMFlags));
+ }
+ // Add server property flag that enables test VM to print encoding for IR verification last and debug messages.
+ cmds.add(socket.getPortPropertyFlag());
+ cmds.addAll(additionalFlags);
+ cmds.addAll(Arrays.asList(getDefaultFlags()));
+ if (VERIFY_VM) {
+ cmds.addAll(Arrays.asList(getVerifyFlags()));
+ }
+
+ if (PREFER_COMMAND_LINE_FLAGS) {
+ // Prefer flags set via the command line over the ones set by scenarios.
+ cmds.addAll(Arrays.asList(jtregVMFlags));
+ }
+
+ if (WARMUP_ITERATIONS < 0 && defaultWarmup != -1) {
+ // Only use the set warmup for the framework if not overridden by a valid -DWarmup property set by a test.
+ cmds.add("-DWarmup=" + defaultWarmup);
+ }
+
+ cmds.add(TestVM.class.getName());
+ cmds.add(testClass.getName());
+ if (helperClasses != null) {
+ helperClasses.forEach(c -> cmds.add(c.getName()));
+ }
+ }
+
+ /**
+ * Default flags that are added used for the test VM.
+ */
+ private static String[] getDefaultFlags() {
+ return new String[] {"-XX:-BackgroundCompilation", "-XX:CompileCommand=quiet"};
+ }
+
+ /**
+ * Additional verification flags that are used if -DVerifyVM=true is with a debug build.
+ */
+ private static String[] getVerifyFlags() {
+ return new String[] {
+ "-XX:+UnlockDiagnosticVMOptions", "-XX:+VerifyOops", "-XX:+VerifyStack", "-XX:+VerifyLastFrame",
+ "-XX:+VerifyBeforeGC", "-XX:+VerifyAfterGC", "-XX:+VerifyDuringGC", "-XX:+VerifyAdapterSharing"
+ };
+ }
+
+ private void start() {
+ ProcessBuilder process = ProcessTools.createJavaProcessBuilder(cmds);
+ try {
+ // Calls 'main' of TestVM to run all specified tests with commands 'cmds'.
+ // Use executeProcess instead of executeTestJvm as we have already added the JTreg VM and
+ // Java options in prepareTestVMFlags().
+ oa = ProcessTools.executeProcess(process);
+ } catch (Exception e) {
+ throw new TestFrameworkException("Error while executing Test VM", e);
+ }
+ commandLine = "Command Line:" + System.lineSeparator() + String.join(" ", process.command())
+ + System.lineSeparator();
+ hotspotPidFileName = String.format("hotspot_pid%d.log", oa.pid());
+ lastTestVMOutput = oa.getOutput();
+ }
+
+ /**
+ * Process the socket output: All prefixed lines are dumped to the standard output while the remaining lines
+ * represent the IR encoding used for IR matching later.
+ */
+ private void processSocketOutput(String output) {
+ if (TestFramework.TESTLIST || TestFramework.EXCLUDELIST) {
+ StringBuilder builder = new StringBuilder();
+ Scanner scanner = new Scanner(output);
+ System.out.println(System.lineSeparator() + "Run flag defined test list");
+ System.out.println("--------------------------");
+ while (scanner.hasNextLine()) {
+ String line = scanner.nextLine();
+ if (line.startsWith(TestFrameworkSocket.STDOUT_PREFIX)) {
+ line = "> " + line.substring(TestFrameworkSocket.STDOUT_PREFIX.length());
+ System.out.println(line);
+ } else {
+ builder.append(line).append(System.lineSeparator());
+ }
+ }
+ System.out.println();
+ irEncoding = builder.toString();
+ } else {
+ irEncoding = output;
+ }
+ }
+
+ private void checkTestVMExitCode() {
+ final int exitCode = oa.getExitValue();
+ if (EXCLUDE_RANDOM || REPORT_STDOUT || (VERBOSE && exitCode == 0)) {
+ System.out.println("--- OUTPUT TestFramework test VM ---");
+ System.out.println(oa.getOutput());
+ }
+
+ if (exitCode != 0) {
+ throwTestVMException();
+ }
+ }
+
+ /**
+ * Exit code was non-zero of test VM. Check the stderr to determine what kind of exception that should be thrown to
+ * react accordingly later.
+ */
+ private void throwTestVMException() {
+ String stdErr = oa.getStderr();
+ if (stdErr.contains("TestFormat.reportIfAnyFailures")) {
+ Pattern pattern = Pattern.compile("Violations \\(\\d+\\)[\\s\\S]*(?=/============/)");
+ Matcher matcher = pattern.matcher(stdErr);
+ TestFramework.check(matcher.find(), "Must find violation matches");
+ throw new TestFormatException(System.lineSeparator() + System.lineSeparator() + matcher.group());
+ } else if (stdErr.contains("NoTestsRunException")) {
+ throw new NoTestsRunException(">>> No tests run due to empty set specified with -DTest and/or -DExclude. " +
+ "Make sure to define a set of at least one @Test method");
+ } else {
+ throw new TestVMException(getExceptionInfo());
+ }
+ }
+
+ /**
+ * Get more detailed information about the exception in a pretty format.
+ */
+ private String getExceptionInfo() {
+ int exitCode = oa.getExitValue();
+ String stdErr = oa.getStderr();
+ String stdOut = "";
+ if (exitCode == 134) {
+ // Also dump the stdout if we experience a JVM error (e.g. to show hit assertions etc.).
+ stdOut = System.lineSeparator() + System.lineSeparator() + "Standard Output" + System.lineSeparator()
+ + "---------------" + System.lineSeparator() + oa.getOutput();
+ }
+ return "TestFramework test VM exited with code " + exitCode + System.lineSeparator() + stdOut
+ + System.lineSeparator() + commandLine + System.lineSeparator() + System.lineSeparator()
+ + "Error Output" + System.lineSeparator() + "------------" + System.lineSeparator() + stdErr
+ + System.lineSeparator() + System.lineSeparator();
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/flag/FlagVM.java b/test/hotspot/jtreg/compiler/lib/ir_framework/flag/FlagVM.java
new file mode 100644
index 00000000000..52e3b93fbcb
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/flag/FlagVM.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2021, 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.flag;
+
+import compiler.lib.ir_framework.CompLevel;
+import compiler.lib.ir_framework.TestFramework;
+import compiler.lib.ir_framework.shared.TestFrameworkException;
+import compiler.lib.ir_framework.shared.TestRunException;
+import jdk.test.lib.process.ProcessTools;
+import sun.hotspot.WhiteBox;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * This class' main method is called from {@link TestFramework} and represents the so-called "flag VM". It uses the
+ * Whitebox API to determine the necessary additional flags to run the test VM (e.g. to do IR matching). It returns
+ * the flags over the dedicated TestFramework socket.
+ */
+public class FlagVM {
+ public static final String TEST_VM_FLAGS_FILE_PREFIX = "test-vm-flags-pid-";
+ public static final String TEST_VM_FLAGS_FILE_POSTFIX = ".log";
+ public static final String TEST_VM_FLAGS_DELIMITER = " ";
+
+ private static final String TEST_VM_FLAGS_FILE;
+ private static final WhiteBox WHITE_BOX;
+
+ static {
+ try {
+ WHITE_BOX = WhiteBox.getWhiteBox();
+ TEST_VM_FLAGS_FILE = TEST_VM_FLAGS_FILE_PREFIX + ProcessTools.getProcessId() + TEST_VM_FLAGS_FILE_POSTFIX;
+ } catch (UnsatisfiedLinkError e) {
+ throw new TestFrameworkException("Could not load WhiteBox", e);
+ } catch (Exception e) {
+ throw new TestFrameworkException("Could not get process id", e);
+ }
+ }
+
+
+ private static final boolean TIERED_COMPILATION = (Boolean)WHITE_BOX.getVMFlag("TieredCompilation");
+ private static final CompLevel TIERED_COMPILATION_STOP_AT_LEVEL =
+ CompLevel.forValue(((Long)WHITE_BOX.getVMFlag("TieredStopAtLevel")).intValue());
+ private static final boolean TEST_C1 = TIERED_COMPILATION
+ && TIERED_COMPILATION_STOP_AT_LEVEL.getValue() < CompLevel.C2.getValue();
+
+ private static final boolean VERBOSE = Boolean.getBoolean("Verbose");
+ private static final boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler");
+ private static final boolean EXCLUDE_RANDOM = Boolean.getBoolean("ExcludeRandom");
+ private static final boolean FLIP_C1_C2 = Boolean.getBoolean("FlipC1C2");
+ private static final boolean REQUESTED_VERIFY_IR = Boolean.parseBoolean(System.getProperty("VerifyIR", "true"));
+ private static final boolean VERIFY_IR = REQUESTED_VERIFY_IR && USE_COMPILER && !EXCLUDE_RANDOM && !FLIP_C1_C2 && !TEST_C1;
+
+ private static String[] getPrintFlags() {
+ return new String[] {"-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions"};
+ }
+
+ /**
+ * Main entry point of the flag VM.
+ */
+ public static void main(String[] args) {
+ String testClassName = args[0];
+ if (VERBOSE) {
+ System.out.println("FlagVM main() called. Prepare test VM flags to run class " + testClassName);
+ }
+ Class> testClass;
+ try {
+ testClass = Class.forName(testClassName);
+ } catch (Exception e) {
+ throw new TestRunException("Could not find test class " + testClassName, e);
+ }
+ emitTestVMFlags(prepareTestVmFlags(testClass));
+ }
+
+ /**
+ * Emit test VM flags to the dedicated test VM flags file to parse them from the TestFramework "driver" VM again
+ * which adds them to the test VM.
+ */
+ private static void emitTestVMFlags(ArrayList flags) {
+ try (var bw = Files.newBufferedWriter(Paths.get(TEST_VM_FLAGS_FILE))) {
+ bw.write(String.join(TEST_VM_FLAGS_DELIMITER, flags));
+ } catch (IOException e) {
+ throw new TestFrameworkException("Error while writing to file " + TEST_VM_FLAGS_FILE, e);
+ }
+ }
+
+ private static ArrayList prepareTestVmFlags(Class> testClass) {
+ return setupIrVerificationFlags(testClass);
+ }
+
+ private static ArrayList setupIrVerificationFlags(Class> testClass) {
+ ArrayList cmds = new ArrayList<>();
+ if (VERIFY_IR) {
+ // Add print flags for IR verification
+ cmds.addAll(Arrays.asList(getPrintFlags()));
+ cmds.add("-XX:+LogCompilation");
+ cmds.add("-XX:CompileCommand=log," + testClass.getCanonicalName() + "::*");
+ addBoolOptionForClass(cmds, testClass, "PrintIdeal");
+ addBoolOptionForClass(cmds, testClass, "PrintOptoAssembly");
+ // Always trap for exception throwing to not confuse IR verification
+ cmds.add("-XX:-OmitStackTraceInFastThrow");
+ cmds.add("-DShouldDoIRVerification=true");
+ } else {
+ cmds.add("-DShouldDoIRVerification=false");
+ }
+ return cmds;
+ }
+
+ private static void addBoolOptionForClass(ArrayList cmds, Class> testClass, String option) {
+ cmds.add("-XX:CompileCommand=option," + testClass.getCanonicalName() + "::*,bool," + option + ",true");
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/CheckedTestFrameworkException.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/CheckedTestFrameworkException.java
new file mode 100644
index 00000000000..d18584abaa1
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/CheckedTestFrameworkException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021, 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.shared;
+
+/**
+ * Checked internal exceptions in the framework to propagate error handling.
+ */
+public class CheckedTestFrameworkException extends Exception {
+ public CheckedTestFrameworkException(String msg) {
+ super(msg);
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/NoTestsRunException.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/NoTestsRunException.java
new file mode 100644
index 00000000000..02afdd4ee4f
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/NoTestsRunException.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2021, 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.shared;
+
+/**
+ * Exception that is thrown by the test VM if no tests are run as a result of specifying {@code -DTest} and/or
+ * {@code -DExclude} defining an empty set with the used test VM flags.
+ */
+public class NoTestsRunException extends RuntimeException {
+ /**
+ * Default constructor used by test VM
+ */
+ public NoTestsRunException() {}
+
+ /**
+ * Constructor used to eventually throw the exception in the driver VM.
+ */
+ public NoTestsRunException(String message) {
+ super(message);
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/ParsedComparator.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/ParsedComparator.java
new file mode 100644
index 00000000000..9d574bc50a4
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/ParsedComparator.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2021, 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.shared;
+
+import java.util.function.BiPredicate;
+
+/**
+ * Utility class to parse a comparator either in the applyIf* or in the counts properties of an @IR rules.
+ */
+public class ParsedComparator> {
+ private final String strippedString;
+ private final BiPredicate predicate;
+ private final String comparator;
+
+ public ParsedComparator(String strippedString, BiPredicate predicate, String comparator) {
+ this.strippedString = strippedString;
+ this.predicate = predicate;
+ this.comparator = comparator;
+ }
+
+ public String getStrippedString() {
+ return strippedString;
+ }
+
+ public BiPredicate getPredicate() {
+ return predicate;
+ }
+
+ public String getComparator() {
+ return comparator;
+ }
+
+ /**
+ * Return parsed comparator object which provides the predicate to perform the test.
+ * Allowed comparators: <, <=, >, =>, =, !=
+ */
+ public static > ParsedComparator parseComparator(String value) throws CheckedTestFrameworkException {
+ BiPredicate comparison;
+ value = value.trim();
+ String comparator = "";
+ switch (value.charAt(0)) {
+ case '<':
+ if (value.charAt(1) == '=') {
+ comparator = "<=";
+ comparison = (x, y) -> x.compareTo(y) <= 0;
+ value = value.substring(2).trim();
+ } else {
+ comparator = "<";
+ comparison = (x, y) -> x.compareTo(y) < 0;
+ value = value.substring(1).trim();
+ }
+ break;
+ case '>':
+ if (value.charAt(1) == '=') {
+ comparator = ">=";
+ comparison = (x, y) -> x.compareTo(y) >= 0;
+ value = value.substring(2).trim();
+ } else {
+ comparator = ">";
+ comparison = (x, y) -> x.compareTo(y) > 0;
+ value = value.substring(1).trim();
+ }
+ break;
+ case '!':
+ if (value.charAt(1) != '=') {
+ throw new CheckedTestFrameworkException(value.substring(0, 1));
+ }
+ comparator = "!=";
+ comparison = (x, y) -> x.compareTo(y) != 0;
+ value = value.substring(2).trim();
+ break;
+ case '=': // Allowed syntax, equivalent to not using any symbol.
+ comparator = "=";
+ value = value.substring(1).trim();
+ // Fall through
+ default:
+ comparison = (x, y) -> x.compareTo(y) == 0;
+ value = value.trim();
+ break;
+ }
+ return new ParsedComparator<>(value, comparison, comparator);
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFormat.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFormat.java
new file mode 100644
index 00000000000..624753fee2f
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFormat.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2021, 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.shared;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility class to report a {@link TestFormatException}.
+ */
+public class TestFormat {
+ private static final List FAILURES = new ArrayList<>();
+
+ public static void check(boolean test, String failureMessage) {
+ if (!test) {
+ fail(failureMessage);
+ }
+ }
+
+ public static void checkNoThrow(boolean test, String failureMessage) {
+ if (!test) {
+ failNoThrow(failureMessage);
+ }
+ }
+
+ public static void fail(String failureMessage) {
+ FAILURES.add(failureMessage);
+ throw new TestFormatException(failureMessage);
+ }
+
+ public static void failNoThrow(String failureMessage) {
+ FAILURES.add(failureMessage);
+ }
+
+ public static void reportIfAnyFailures() {
+ if (FAILURES.isEmpty()) {
+ // No format violation detected.
+ return;
+ }
+ StringBuilder builder = new StringBuilder();
+ builder.append(System.lineSeparator()).append("One or more format violations have been detected:")
+ .append(System.lineSeparator()).append(System.lineSeparator());
+ builder.append("Violations (").append(FAILURES.size()).append(")").append(System.lineSeparator());
+ builder.append("-------------").append("-".repeat(String.valueOf(FAILURES.size()).length()))
+ .append(System.lineSeparator());
+ for (String failure : FAILURES) {
+ builder.append(" - ").append(failure).append(System.lineSeparator());
+ }
+ builder.append("/============/");
+ FAILURES.clear();
+ throw new TestFormatException(builder.toString());
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFormatException.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFormatException.java
new file mode 100644
index 00000000000..cb44f624bfb
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFormatException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021, 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.shared;
+
+/**
+ * Exception that is thrown if a JTreg test violates the supported format by the test framework.
+ */
+public class TestFormatException extends RuntimeException {
+ public TestFormatException(String message) {
+ super(message);
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFrameworkException.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFrameworkException.java
new file mode 100644
index 00000000000..050aecf09db
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFrameworkException.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021, 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.shared;
+
+/**
+ * Exception that is thrown if there is an internal error in the framework. This is most likely an indicator of a bug
+ * in the framework.
+ */
+public class TestFrameworkException extends RuntimeException {
+ public TestFrameworkException(String message) {
+ super("Internal Test Framework exception - please file a bug:" + System.lineSeparator() + message);
+ }
+
+ public TestFrameworkException(String message, Throwable e) {
+ super("Internal Test Framework exception - please file a bug:" + System.lineSeparator() + message, e);
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFrameworkSocket.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFrameworkSocket.java
new file mode 100644
index 00000000000..aa4f3ec1c6b
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestFrameworkSocket.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2021, 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.shared;
+
+import compiler.lib.ir_framework.TestFramework;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+
+/**
+ * Dedicated socket to send data from the flag and test VM back to the driver VM.
+ */
+public class TestFrameworkSocket implements AutoCloseable {
+ public static final String STDOUT_PREFIX = "[STDOUT]";
+ // Static fields used for test VM only.
+ private static final String SERVER_PORT_PROPERTY = "ir.framework.server.port";
+ private static final int SERVER_PORT = Integer.getInteger(SERVER_PORT_PROPERTY, -1);
+
+ private static final boolean REPRODUCE = Boolean.getBoolean("Reproduce");
+ private static final String HOSTNAME = null;
+ private static Socket clientSocket = null;
+ private static PrintWriter clientWriter = null;
+
+ private final String serverPortPropertyFlag;
+ private FutureTask socketTask;
+ private final ServerSocket serverSocket;
+
+ public TestFrameworkSocket() {
+ try {
+ serverSocket = new ServerSocket(0);
+ } catch (IOException e) {
+ throw new TestFrameworkException("Failed to create TestFramework server socket", e);
+ }
+ int port = serverSocket.getLocalPort();
+ if (TestFramework.VERBOSE) {
+ System.out.println("TestFramework server socket uses port " + port);
+ }
+ serverPortPropertyFlag = "-D" + SERVER_PORT_PROPERTY + "=" + port;
+ start();
+ }
+
+ public String getPortPropertyFlag() {
+ return serverPortPropertyFlag;
+ }
+
+ private void start() {
+ socketTask = initSocketTask();
+ Thread socketThread = new Thread(socketTask);
+ socketThread.start();
+ }
+
+ /**
+ * Waits for a client (created by flag or test VM) to connect. Return the messages received from the client.
+ */
+ private FutureTask initSocketTask() {
+ return new FutureTask<>(() -> {
+ try (Socket clientSocket = serverSocket.accept();
+ BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))
+ ) {
+ StringBuilder builder = new StringBuilder();
+ String next;
+ while ((next = in.readLine()) != null) {
+ builder.append(next).append(System.lineSeparator());
+ }
+ return builder.toString();
+ } catch (IOException e) {
+ throw new TestFrameworkException("Server socket error", e);
+ }
+ });
+ }
+
+ @Override
+ public void close() {
+ try {
+ serverSocket.close();
+ } catch (IOException e) {
+ throw new TestFrameworkException("Could not close socket", e);
+ }
+ }
+
+ /**
+ * Only called by test VM to write to server socket.
+ */
+ public static void write(String msg, String type) {
+ write(msg, type, false);
+ }
+
+ /**
+ * Only called by test VM to write to server socket.
+ */
+ public static void write(String msg, String type, boolean stdout) {
+ if (REPRODUCE) {
+ System.out.println("Debugging Test VM: Skip writing due to -DReproduce");
+ return;
+ }
+ TestFramework.check(SERVER_PORT != -1, "Server port was not set correctly for flag and/or test VM "
+ + "or method not called from flag or test VM");
+ try {
+ // Keep the client socket open until the test VM terminates (calls closeClientSocket before exiting main()).
+ if (clientSocket == null) {
+ clientSocket = new Socket(HOSTNAME, SERVER_PORT);
+ clientWriter = new PrintWriter(clientSocket.getOutputStream(), true);
+ }
+ if (stdout) {
+ msg = STDOUT_PREFIX + msg;
+ }
+ clientWriter.println(msg);
+ } catch (Exception e) {
+ // When the test VM is directly run, we should ignore all messages that would normally be sent to the
+ // driver VM.
+ String failMsg = System.lineSeparator() + System.lineSeparator() + """
+ ###########################################################
+ Did you directly run the test VM (TestVM class)
+ to reproduce a bug?
+ => Append the flag -DReproduce=true and try again!
+ ###########################################################
+ """;
+ throw new TestRunException(failMsg, e);
+ }
+ if (TestFramework.VERBOSE) {
+ System.out.println("Written " + type + " to socket:");
+ System.out.println(msg);
+ }
+ }
+
+ /**
+ * Closes (and flushes) the printer to the socket and the socket itself. Is called as last thing before exiting
+ * the main() method of the flag and the test VM.
+ */
+ public static void closeClientSocket() {
+ if (clientSocket != null) {
+ try {
+ clientWriter.close();
+ clientSocket.close();
+ } catch (IOException e) {
+ throw new RuntimeException("Could not close TestVM socket", e);
+ }
+ }
+ }
+
+ /**
+ * Get the socket output of the flag VM.
+ */
+ public String getOutput() {
+ try {
+ return socketTask.get();
+ } catch (ExecutionException e) {
+ // Thrown when socket task was not finished, yet (i.e. no client sent data) but socket was already closed.
+ return "";
+ } catch (Exception e) {
+ throw new TestFrameworkException("Could not read from socket task", e);
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestRun.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestRun.java
new file mode 100644
index 00000000000..ebf5fc80c9a
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestRun.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, 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.shared;
+
+/**
+ * Utility class to report a {@link TestRunException}.
+ */
+public class TestRun {
+ public static void check(boolean test, String failureMessage) {
+ if (!test) {
+ throw new TestRunException(failureMessage);
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestRunException.java b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestRunException.java
new file mode 100644
index 00000000000..1969a755704
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/shared/TestRunException.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2021, 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.shared;
+
+/**
+ * Exception that is thrown if the JTreg test throws an exception during the execution of individual tests of the
+ * test class.
+ */
+public class TestRunException extends RuntimeException {
+ public TestRunException(String message) {
+ super(message);
+ }
+
+ public TestRunException(String message, Exception e) {
+ super(message, e);
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/AbstractTest.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/AbstractTest.java
new file mode 100644
index 00000000000..f4db830f2b0
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/AbstractTest.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2021, 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.test;
+
+import compiler.lib.ir_framework.*;
+import compiler.lib.ir_framework.shared.TestRun;
+import compiler.lib.ir_framework.shared.TestRunException;
+import sun.hotspot.WhiteBox;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * Abstract super class for base, checked and custom run tests.
+ */
+abstract class AbstractTest {
+ protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+ protected static final int TEST_COMPILATION_TIMEOUT = Integer.parseInt(System.getProperty("TestCompilationTimeout", "10000"));
+ protected static final int WAIT_FOR_COMPILATION_TIMEOUT = Integer.parseInt(System.getProperty("WaitForCompilationTimeout", "10000"));
+ protected static final boolean VERIFY_OOPS = (Boolean)WHITE_BOX.getVMFlag("VerifyOops");
+
+ protected final int warmupIterations;
+ protected final boolean skip;
+
+ AbstractTest(int warmupIterations, boolean skip) {
+ this.warmupIterations = warmupIterations;
+ this.skip = skip;
+ }
+
+ protected boolean shouldCompile(DeclaredTest test) {
+ return test.getCompLevel() != CompLevel.SKIP;
+ }
+
+ abstract String getName();
+
+ /**
+ * Should test be executed?
+ */
+ public boolean isSkipped() {
+ return skip;
+ }
+
+ /**
+ * See {@link CompLevel#WAIT_FOR_COMPILATION}.
+ */
+ protected static boolean isWaitForCompilation(DeclaredTest test) {
+ return test.getCompLevel() == CompLevel.WAIT_FOR_COMPILATION;
+ }
+
+ protected static Object createInvocationTarget(Method method) {
+ Class> clazz = method.getDeclaringClass();
+ Object invocationTarget;
+ if (Modifier.isStatic(method.getModifiers())) {
+ invocationTarget = null;
+ } else {
+ try {
+ Constructor> constructor = clazz.getDeclaredConstructor();
+ constructor.setAccessible(true);
+ invocationTarget = constructor.newInstance();
+ } catch (Exception e) {
+ throw new TestRunException("Could not create instance of " + clazz
+ + ". Make sure there is a constructor without arguments.", e);
+ }
+ }
+ return invocationTarget;
+ }
+
+ /**
+ * Run the associated test.
+ */
+ public void run() {
+ if (skip) {
+ return;
+ }
+ onStart();
+ for (int i = 0; i < warmupIterations; i++) {
+ invokeTest();
+ }
+ onWarmupFinished();
+ compileTest();
+ // Always run the test as a last step of the test execution.
+ invokeTest();
+ }
+
+ protected void onStart() {
+ // Do nothing by default.
+ }
+
+ abstract protected void invokeTest();
+
+ abstract protected void onWarmupFinished();
+
+ abstract protected void compileTest();
+
+ protected void compileMethod(DeclaredTest test) {
+ final Method testMethod = test.getTestMethod();
+ TestRun.check(WHITE_BOX.isMethodCompilable(testMethod, test.getCompLevel().getValue(), false),
+ "Method " + testMethod + " not compilable at level " + test.getCompLevel()
+ + ". Did you use compileonly without including all @Test methods?");
+ TestRun.check(WHITE_BOX.isMethodCompilable(testMethod),
+ "Method " + testMethod + " not compilable at level " + test.getCompLevel()
+ + ". Did you use compileonly without including all @Test methods?");
+ if (TestFramework.VERBOSE) {
+ System.out.println("Compile method " + testMethod + " after warm-up...");
+ }
+
+ final boolean maybeCodeBufferOverflow = (TestVM.TEST_C1 && VERIFY_OOPS);
+ final long started = System.currentTimeMillis();
+ long elapsed = 0;
+ int lastCompilationLevel = -10;
+ enqueueMethodForCompilation(test);
+
+ do {
+ if (!WHITE_BOX.isMethodQueuedForCompilation(testMethod)) {
+ if (elapsed > 0) {
+ if (TestVM.VERBOSE) {
+ System.out.println(testMethod + " is not in queue anymore due to compiling it simultaneously on " +
+ "a different level. Enqueue again.");
+ }
+ enqueueMethodForCompilation(test);
+ }
+ }
+ if (maybeCodeBufferOverflow && elapsed > 1000 && !WHITE_BOX.isMethodCompiled(testMethod, false)) {
+ // Let's disable VerifyOops temporarily and retry.
+ WHITE_BOX.setBooleanVMFlag("VerifyOops", false);
+ WHITE_BOX.clearMethodState(testMethod);
+ enqueueMethodForCompilation(test);
+ WHITE_BOX.setBooleanVMFlag("VerifyOops", true);
+ }
+
+ lastCompilationLevel = WHITE_BOX.getMethodCompilationLevel(testMethod, false);
+ if (lastCompilationLevel == test.getCompLevel().getValue()) {
+ break;
+ }
+ elapsed = System.currentTimeMillis() - started;
+ } while (elapsed < TEST_COMPILATION_TIMEOUT);
+ TestRun.check(elapsed < TEST_COMPILATION_TIMEOUT,
+ "Could not compile " + testMethod + " at level " + test.getCompLevel() + " after "
+ + TEST_COMPILATION_TIMEOUT/1000 + "s. Last compilation level: " + lastCompilationLevel);
+ checkCompilationLevel(test);
+ }
+
+ private void enqueueMethodForCompilation(DeclaredTest test) {
+ TestVM.enqueueForCompilation(test.getTestMethod(), test.getCompLevel());
+ }
+
+ protected void checkCompilationLevel(DeclaredTest test) {
+ CompLevel level = CompLevel.forValue(WHITE_BOX.getMethodCompilationLevel(test.getTestMethod()));
+ TestRun.check(level == test.getCompLevel(), "Compilation level should be " + test.getCompLevel().name()
+ + " (requested) but was " + level.name() + " for " + test.getTestMethod());
+ }
+
+ final protected void waitForCompilation(DeclaredTest test) {
+ final Method testMethod = test.getTestMethod();
+ final boolean maybeCodeBufferOverflow = (TestVM.TEST_C1 && VERIFY_OOPS);
+ final long started = System.currentTimeMillis();
+ boolean stateCleared = false;
+ long elapsed;
+ do {
+ elapsed = System.currentTimeMillis() - started;
+ int level = WHITE_BOX.getMethodCompilationLevel(testMethod);
+ if (maybeCodeBufferOverflow && elapsed > 5000
+ && (!WHITE_BOX.isMethodCompiled(testMethod, false) || level != test.getCompLevel().getValue())) {
+ retryDisabledVerifyOops(testMethod, stateCleared);
+ stateCleared = true;
+ } else {
+ invokeTest();
+ }
+
+ boolean isCompiled = WHITE_BOX.isMethodCompiled(testMethod, false);
+ if (TestVM.VERBOSE) {
+ System.out.println("Is " + testMethod + " compiled? " + isCompiled);
+ }
+ if (isCompiled || TestVM.XCOMP || TestVM.EXCLUDE_RANDOM) {
+ // Don't wait for compilation if -Xcomp is enabled or if we are randomly excluding methods from compilation.
+ return;
+ }
+ } while (elapsed < WAIT_FOR_COMPILATION_TIMEOUT);
+ throw new TestRunException(testMethod + " not compiled after waiting for "
+ + WAIT_FOR_COMPILATION_TIMEOUT/1000 + " s");
+ }
+
+ /**
+ * If it takes too long, try to disable Verify Oops.
+ */
+ private void retryDisabledVerifyOops(Method testMethod, boolean stateCleared) {
+ System.out.println("Temporarily disabling VerifyOops");
+ try {
+ WHITE_BOX.setBooleanVMFlag("VerifyOops", false);
+ if (!stateCleared) {
+ WHITE_BOX.clearMethodState(testMethod);
+ }
+ invokeTest();
+ } finally {
+ WHITE_BOX.setBooleanVMFlag("VerifyOops", true);
+ System.out.println("Re-enabled VerifyOops");
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/ArgumentValue.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/ArgumentValue.java
new file mode 100644
index 00000000000..7c5a9edec71
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/ArgumentValue.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2021, 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.test;
+
+import compiler.lib.ir_framework.Argument;
+import compiler.lib.ir_framework.Arguments;
+import compiler.lib.ir_framework.shared.TestFrameworkException;
+import compiler.lib.ir_framework.shared.TestFormat;
+import compiler.lib.ir_framework.shared.TestFormatException;
+import jdk.test.lib.Utils;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.Random;
+
+/**
+ * This class represents an argument value specified by {@link Argument} in {@link Arguments}.
+ */
+class ArgumentValue {
+ private static final Random RANDOM = Utils.getRandomInstance();
+
+ private final Object argumentValue;
+ private final boolean isRandomEach;
+ private final boolean isFixedRandom;
+ private final Class> randomClass;
+
+ ArgumentValue() {
+ this.argumentValue = null;
+ this.isRandomEach = false;
+ this.randomClass = null;
+ this.isFixedRandom = false;
+ }
+
+ private ArgumentValue(Object argumentValue, boolean isFixedRandom) {
+ this.argumentValue = argumentValue;
+ this.isRandomEach = false;
+ this.randomClass = null;
+ this.isFixedRandom = isFixedRandom;
+ }
+
+ private ArgumentValue(Object argumentValue, Class> randomClass) {
+ this.argumentValue = argumentValue;
+ this.isRandomEach = true;
+ this.randomClass = randomClass;
+ this.isFixedRandom = false;
+ }
+
+ /**
+ * Return all arguments for the @Arguments annotation.
+ *
+ * @param m The @Test method.
+ * @return Returns an array with Argument objects for each specified argument in the @Arguments annotation of m.
+ * Returns null if method has no @Arguments annotation.
+ */
+ public static ArgumentValue[] getArguments(Method m) {
+ Arguments argumentsAnno = m.getAnnotation(Arguments.class);
+ if (argumentsAnno == null) {
+ return null;
+ }
+ Argument[] values = argumentsAnno.value();
+ ArgumentValue[] arguments = new ArgumentValue[values.length];
+ Class>[] declaredParameters = m.getParameterTypes();
+ Parameter[] declaredParameterObjects = m.getParameters();
+ try {
+ TestFormat.check(values.length == declaredParameters.length,
+ "Number of argument values provided in @Arguments does not match the number " +
+ "of actual arguments in " + m);
+
+ for (int i = 0; i < values.length; i++) {
+ Argument specifiedArg = values[i];
+ Class> parameter = declaredParameters[i];
+ Parameter parameterObj = declaredParameterObjects[i];
+ try {
+ switch (specifiedArg) {
+ case DEFAULT -> {
+ try {
+ arguments[i] = createDefault(parameter);
+ } catch (NoSuchMethodException e) {
+ TestFormat.fail("Cannot create new default instance of " + parameter
+ + " for " + m + " due to missing default constructor");
+ } catch (Exception e) {
+ TestFormat.fail("Cannot create new default instance of " + parameter
+ + " for " + m + ": " + e.getCause());
+ }
+ }
+ case NUMBER_42 -> {
+ TestFormat.check(isNumber(parameter), "Provided invalid NUMBER_42 argument " +
+ "for non-number " + parameterObj + " for " + m);
+ arguments[i] = create((byte) 42);
+ }
+ case NUMBER_MINUS_42 -> {
+ TestFormat.check(isNumber(parameter), "Provided invalid NUMBER_MINUS_42 argument " +
+ "for non-number " + parameterObj + " for " + m);
+ arguments[i] = create((byte) -42);
+ }
+ case MIN -> {
+ TestFormat.check(isNumber(parameter) || isChar(parameter),
+ "Provided invalid MIN argument for non-number "
+ + parameterObj + " for " + m);
+ arguments[i] = createMin(parameter);
+ }
+ case MAX -> {
+ TestFormat.check(isNumber(parameter) || isChar(parameter),
+ "Provided invalid MAX argument for non-number "
+ + parameterObj + " for " + m);
+ arguments[i] = createMax(parameter);
+ }
+ case FALSE -> {
+ TestFormat.check(ArgumentValue.isBoolean(parameter),
+ "Provided invalid FALSE argument for non-boolean "
+ + parameterObj + " for " + m);
+ arguments[i] = create(false);
+ }
+ case TRUE -> {
+ TestFormat.check(ArgumentValue.isBoolean(parameter),
+ "Provided invalid TRUE argument for non-boolean "
+ + parameterObj + " for " + m);
+ arguments[i] = create(true);
+ }
+ case BOOLEAN_TOGGLE_FIRST_FALSE -> {
+ TestFormat.check(isBoolean(parameter),
+ "Provided invalid BOOLEAN_TOGGLE_FIRST_FALSE argument for non-boolean "
+ + parameterObj + " for " + m);
+ arguments[i] = BooleanToggleValue.create(false);
+ }
+ case BOOLEAN_TOGGLE_FIRST_TRUE -> {
+ TestFormat.check(ArgumentValue.isBoolean(parameter),
+ "Provided invalid BOOLEAN_TOGGLE_FIRST_TRUE argument for non-boolean "
+ + parameterObj + " for " + m);
+ arguments[i] = BooleanToggleValue.create(true);
+ }
+ case RANDOM_ONCE -> {
+ TestFormat.check(isPrimitiveType(parameter),
+ "Provided invalid RANDOM_ONCE argument for non-primitive type "
+ + parameterObj + " for " + m);
+ arguments[i] = createRandom(parameter);
+ }
+ case RANDOM_EACH -> {
+ TestFormat.check(isPrimitiveType(parameter),
+ "Provided invalid RANDOM_EACH argument for non-primitive type "
+ + parameterObj + " for " + m);
+ arguments[i] = createRandomEach(parameter);
+ }
+ }
+ } catch (TestFormatException e) {
+ // Catch and continue to check arguments.
+ }
+ }
+ } catch (TestFormatException e) {
+ // Catch and return empty array to check for additional failures.
+ return new ArgumentValue[0];
+ }
+ return arguments;
+ }
+
+ private static ArgumentValue create(Object argumentValue) {
+ return new ArgumentValue(argumentValue, false);
+ }
+
+ private static ArgumentValue createDefault(Class> c) throws Exception {
+ if (ArgumentValue.isNumber(c)) {
+ return ArgumentValue.create((byte)0);
+ } else if (ArgumentValue.isChar(c)) {
+ return ArgumentValue.create('\u0000');
+ } else if (ArgumentValue.isBoolean(c)) {
+ return ArgumentValue.create(false);
+ } else {
+ // Object
+ Constructor> constructor = c.getDeclaredConstructor();
+ constructor.setAccessible(true); // Make sure to have access to private default constructor
+ return ArgumentValue.create(constructor.newInstance());
+ }
+ }
+
+ private static ArgumentValue createMin(Class> c) {
+ Object argument;
+ if (c.equals(byte.class)) {
+ argument = Byte.MIN_VALUE;
+ } else if (isChar(c)) {
+ argument = Character.MIN_VALUE;
+ } else if (c.equals(short.class)) {
+ argument = Short.MIN_VALUE;
+ } else if (c.equals(int.class)) {
+ argument = Integer.MIN_VALUE;
+ } else if (c.equals(long.class)) {
+ argument = Long.MIN_VALUE;
+ } else if (c.equals(float.class)) {
+ argument = Float.MIN_VALUE;
+ } else if (c.equals(double.class)) {
+ argument = Double.MIN_VALUE;
+ } else {
+ throw new TestFrameworkException("Invalid class passed to createMin()");
+ }
+ return new ArgumentValue(argument, false);
+ }
+
+ private static ArgumentValue createMax(Class> c) {
+ Object argument;
+ if (c.equals(byte.class)) {
+ argument = Byte.MAX_VALUE;
+ } else if (isChar(c)) {
+ argument = Character.MAX_VALUE;
+ } else if (c.equals(short.class)) {
+ argument = Short.MAX_VALUE;
+ } else if (c.equals(int.class)) {
+ argument = Integer.MAX_VALUE;
+ } else if (c.equals(long.class)) {
+ argument = Long.MAX_VALUE;
+ } else if (c.equals(float.class)) {
+ argument = Float.MAX_VALUE;
+ } else if (c.equals(double.class)) {
+ argument = Double.MAX_VALUE;
+ } else {
+ throw new TestFrameworkException("Invalid class passed to createMax()");
+ }
+ return new ArgumentValue(argument, false);
+ }
+
+ private static ArgumentValue createRandom(Class> c) {
+ return new ArgumentValue(getRandom(c), true);
+ }
+
+ private static ArgumentValue createRandomEach(Class> c) {
+ return new ArgumentValue(null, c);
+ }
+
+ public boolean isFixedRandom() {
+ return isFixedRandom;
+ }
+
+ public Object getArgument() {
+ if (isRandomEach) {
+ return getRandom(randomClass);
+ } else {
+ return argumentValue;
+ }
+ }
+
+ private static boolean isPrimitiveType(Class> c) {
+ return isNumber(c) || isBoolean(c) || isChar(c);
+ }
+
+ private static boolean isBoolean(Class> c) {
+ return c.equals(boolean.class);
+ }
+
+ private static boolean isChar(Class> c) {
+ return c.equals(char.class);
+ }
+
+ private static boolean isNumber(Class> c) {
+ return isIntNumber(c) || isFloatNumber(c);
+ }
+
+ private static boolean isIntNumber(Class> c) {
+ return c.equals(byte.class)
+ || c.equals(short.class)
+ || c.equals(int.class)
+ || c.equals(long.class);
+ }
+
+ private static boolean isFloatNumber(Class> c) {
+ return c.equals(float.class) || c.equals(double.class);
+ }
+
+ private static Object getRandom(Class> c) {
+ if (isBoolean(c)) {
+ return RANDOM.nextBoolean();
+ } else if (c.equals(byte.class)) {
+ return (byte) RANDOM.nextInt(256);
+ } else if (isChar(c)) {
+ return (char) RANDOM.nextInt(65536);
+ } else if (c.equals(short.class)) {
+ return (short) RANDOM.nextInt(65536);
+ } else if (c.equals(int.class)) {
+ return RANDOM.nextInt();
+ } else if (c.equals(long.class)) {
+ return RANDOM.nextLong();
+ } else if (c.equals(float.class)) {
+ // Get float between -10000 and 10000.
+ return RANDOM.nextFloat() * 20000 - 10000;
+ } else if (c.equals(double.class)) {
+ // Get double between -10000 and 10000.
+ return RANDOM.nextDouble() * 20000 - 10000;
+ } else {
+ TestFormat.fail("Cannot generate random value for non-primitive type");
+ return null;
+ }
+ }
+}
+
+/**
+ * Special class to handle boolean toggle argument values.
+ */
+class BooleanToggleValue extends ArgumentValue {
+ private boolean previousBoolean;
+
+ BooleanToggleValue(boolean firstBoolean) {
+ this.previousBoolean = !firstBoolean;
+ }
+
+ @Override
+ public Object getArgument() {
+ previousBoolean = !previousBoolean;
+ return previousBoolean;
+ }
+
+ static BooleanToggleValue create(boolean firstBoolean) {
+ return new BooleanToggleValue(firstBoolean);
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/BaseTest.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/BaseTest.java
new file mode 100644
index 00000000000..a17eb91884d
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/BaseTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2021, 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.test;
+
+import compiler.lib.ir_framework.*;
+import compiler.lib.ir_framework.shared.TestRunException;
+
+import java.lang.reflect.Method;
+
+/**
+ * A base test only consists of a single @Test method. See {@link Test} for more details and its precise definition.
+ */
+class BaseTest extends AbstractTest {
+ private final DeclaredTest test;
+ protected final Method testMethod;
+ protected final TestInfo testInfo;
+ protected final Object invocationTarget;
+ private final boolean shouldCompile;
+ private final boolean waitForCompilation;
+
+ public BaseTest(DeclaredTest test, boolean skip) {
+ super(test.getWarmupIterations(), skip);
+ this.test = test;
+ this.testMethod = test.getTestMethod();
+ this.testInfo = new TestInfo(testMethod, test.getCompLevel());
+ this.invocationTarget = createInvocationTarget(testMethod);
+ this.shouldCompile = shouldCompile(test);
+ this.waitForCompilation = isWaitForCompilation(test);
+ }
+
+ @Override
+ public String toString() {
+ return "Base Test: @Test " + testMethod.getName();
+ }
+
+ @Override
+ public String getName() {
+ return testMethod.getName();
+ }
+
+ @Override
+ protected void onStart() {
+ test.printFixedRandomArguments();
+ }
+
+ @Override
+ public void onWarmupFinished() {
+ testInfo.setWarmUpFinished();
+ }
+
+ @Override
+ protected void invokeTest() {
+ verify(invokeTestMethod());
+ }
+
+ private Object invokeTestMethod() {
+ try {
+ if (test.hasArguments()) {
+ return testMethod.invoke(invocationTarget, test.getArguments());
+ } else {
+ return testMethod.invoke(invocationTarget);
+ }
+ } catch (Exception e) {
+ throw new TestRunException("There was an error while invoking @Test method " + testMethod
+ + ". Used arguments: " + test.getArgumentsString(), e);
+ }
+ }
+
+ @Override
+ protected void compileTest() {
+ if (shouldCompile) {
+ if (waitForCompilation) {
+ waitForCompilation(test);
+ } else {
+ compileMethod(test);
+ }
+ }
+ }
+
+ /**
+ * Verify the result
+ */
+ public void verify(Object result) { /* no verification in BaseTests */ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/CheckedTest.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/CheckedTest.java
new file mode 100644
index 00000000000..8959dbac2ee
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/CheckedTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2021, 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.test;
+
+import compiler.lib.ir_framework.Check;
+import compiler.lib.ir_framework.CheckAt;
+import compiler.lib.ir_framework.shared.TestRunException;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * A checked test is an extension of a base test with additional verification done in a @Check method.
+ * See {@link Check} for more details and its precise definition.
+ */
+class CheckedTest extends BaseTest {
+ private final Method checkMethod;
+ private final CheckAt checkAt;
+ private final Parameter parameter;
+ private final Object checkInvocationTarget;
+
+ enum Parameter {
+ NONE, RETURN_ONLY, TEST_INFO_ONLY, BOTH
+ }
+
+ public CheckedTest(DeclaredTest test, Method checkMethod, Check checkSpecification, Parameter parameter, boolean excludedByUser) {
+ super(test, excludedByUser);
+ // Make sure we can also call non-public or public methods in package private classes
+ checkMethod.setAccessible(true);
+ this.checkMethod = checkMethod;
+ this.checkAt = checkSpecification.when();
+ this.parameter = parameter;
+ // Use the same invocation target
+ if (Modifier.isStatic(checkMethod.getModifiers())) {
+ this.checkInvocationTarget = null;
+ } else {
+ // Use the same invocation target as the test method if check method is non-static.
+ this.checkInvocationTarget = this.invocationTarget != null ? this.invocationTarget : createInvocationTarget(checkMethod);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Checked Test: @Check " + checkMethod.getName() + " - @Test: " + testMethod.getName();
+ }
+
+ @Override
+ public String getName() {
+ return checkMethod.getName();
+ }
+
+ @Override
+ public void verify(Object result) {
+ boolean shouldVerify = false;
+ switch (checkAt) {
+ case EACH_INVOCATION -> shouldVerify = true;
+ case COMPILED -> shouldVerify = !testInfo.isWarmUp();
+ }
+ if (shouldVerify) {
+ try {
+ switch (parameter) {
+ case NONE -> checkMethod.invoke(checkInvocationTarget);
+ case RETURN_ONLY -> checkMethod.invoke(checkInvocationTarget, result);
+ case TEST_INFO_ONLY -> checkMethod.invoke(checkInvocationTarget, testInfo);
+ case BOTH -> checkMethod.invoke(checkInvocationTarget, result, testInfo);
+ }
+ } catch (Exception e) {
+ throw new TestRunException("There was an error while invoking @Check method " + checkMethod, e);
+ }
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/CustomRunTest.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/CustomRunTest.java
new file mode 100644
index 00000000000..f82a2ca4abf
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/CustomRunTest.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2021, 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.test;
+
+import compiler.lib.ir_framework.*;
+import compiler.lib.ir_framework.shared.TestFormat;
+import compiler.lib.ir_framework.shared.TestFrameworkException;
+import compiler.lib.ir_framework.shared.TestRunException;
+import sun.hotspot.WhiteBox;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * A custom run test allows the user to have full control over how the @Test method is invoked by specifying
+ * a dedicated @Run method. See {@link Run} for more details and its precise definition.
+ */
+class CustomRunTest extends AbstractTest {
+ private final Method runMethod;
+ private final RunMode mode;
+ private final Object runInvocationTarget;
+ private final List tests;
+ private final RunInfo runInfo;
+
+ public CustomRunTest(Method runMethod, Warmup warmUpAnno, Run runSpecification, List tests, boolean skip) {
+ // Make sure we can also call non-public or public methods in package private classes
+ super(warmUpAnno != null ? warmUpAnno.value() : TestVM.WARMUP_ITERATIONS, skip);
+ TestFormat.checkNoThrow(warmupIterations >= 0, "Cannot have negative value for @Warmup at " + runMethod);
+ runMethod.setAccessible(true);
+ this.runMethod = runMethod;
+ this.runInvocationTarget = createInvocationTarget(runMethod);
+ this.mode = runSpecification.mode();
+ this.tests = tests;
+ this.runInfo = new RunInfo(tests);
+ }
+
+ @Override
+ public String toString() {
+ String s = "Custom Run Test: @Run: " + runMethod.getName() + " - @Test";
+ if (tests.size() == 1) {
+ s += ": " + tests.get(0).getTestMethod().getName();
+ } else {
+ s += "s: {" + tests.stream().map(t -> t.getTestMethod().getName())
+ .collect(Collectors.joining(",")) + "}";
+ }
+ return s;
+ }
+
+ @Override
+ String getName() {
+ return runMethod.getName();
+ }
+
+ @Override
+ public void run() {
+ if (skip) {
+ return;
+ }
+ switch (mode) {
+ case STANDALONE -> {
+ runInfo.setWarmUpFinished();
+ invokeTest();
+ }// Invoke once but do not apply anything else.
+ case NORMAL -> super.run();
+ }
+ }
+
+ @Override
+ public void onWarmupFinished() {
+ runInfo.setWarmUpFinished();
+ }
+
+ @Override
+ protected void compileTest() {
+ if (tests.size() == 1) {
+ compileSingleTest();
+ } else {
+ compileMultipleTests();
+ }
+ }
+
+ private void compileSingleTest() {
+ DeclaredTest test = tests.get(0);
+ if (shouldCompile(test)) {
+ if (isWaitForCompilation(test)) {
+ waitForCompilation(test);
+ } else {
+ compileMethod(test);
+ }
+ }
+ }
+
+ private void compileMultipleTests() {
+ boolean anyWaitForCompilation = false;
+ boolean anyCompileMethod = false;
+ ExecutorService executor = Executors.newFixedThreadPool(tests.size());
+ for (DeclaredTest test : tests) {
+ if (shouldCompile(test)) {
+ if (isWaitForCompilation(test)) {
+ anyWaitForCompilation = true;
+ executor.execute(() -> waitForCompilation(test));
+ } else {
+ anyCompileMethod = true;
+ executor.execute(() -> compileMethod(test));
+ }
+ }
+ }
+ executor.shutdown();
+ int timeout;
+ if (anyCompileMethod && anyWaitForCompilation) {
+ timeout = Math.max(WAIT_FOR_COMPILATION_TIMEOUT, TEST_COMPILATION_TIMEOUT) + 5000;
+ } else if (anyWaitForCompilation) {
+ timeout = WAIT_FOR_COMPILATION_TIMEOUT + 5000;
+ } else {
+ timeout = TEST_COMPILATION_TIMEOUT + 5000;
+ }
+ try {
+ executor.awaitTermination(timeout, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ throw new TestRunException("Some compilations did not complete after " + timeout
+ + "ms for @Run method " + runMethod);
+ }
+ }
+
+ /**
+ * Do not directly run the test but rather the run method that is responsible for invoking the actual test.
+ */
+ @Override
+ protected void invokeTest() {
+ try {
+ if (runMethod.getParameterCount() == 1) {
+ runMethod.invoke(runInvocationTarget, runInfo);
+ } else {
+ runMethod.invoke(runInvocationTarget);
+ }
+ } catch (Exception e) {
+ throw new TestRunException("There was an error while invoking @Run method " + runMethod, e);
+ }
+ }
+
+ @Override
+ protected void checkCompilationLevel(DeclaredTest test) {
+ CompLevel level = CompLevel.forValue(WhiteBox.getWhiteBox().getMethodCompilationLevel(test.getTestMethod()));
+ if (level != test.getCompLevel()) {
+ String message = "Compilation level should be " + test.getCompLevel().name() + " (requested) but was "
+ + level.name() + " for " + test.getTestMethod() + ".";
+ switch (mode) {
+ case STANDALONE -> throw new TestFrameworkException("Should not be called for STANDALONE method " + runMethod);
+ case NORMAL -> message = message + System.lineSeparator() + "Check your @Run method " + runMethod
+ + " to ensure that " + test.getTestMethod()
+ + " is called at least once in each iteration.";
+ }
+ throw new TestRunException(message);
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/DeclaredTest.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/DeclaredTest.java
new file mode 100644
index 00000000000..3f1bfbba8b5
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/DeclaredTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2021, 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.test;
+
+import compiler.lib.ir_framework.CompLevel;
+import compiler.lib.ir_framework.shared.TestRunException;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+/**
+ * This class represents a @Test method.
+ */
+public class DeclaredTest {
+ private final Method testMethod;
+ private final ArgumentValue[] arguments;
+ private final int warmupIterations;
+ private final CompLevel compLevel;
+ private Method attachedMethod;
+
+ public DeclaredTest(Method testMethod, ArgumentValue[] arguments, CompLevel compLevel, int warmupIterations) {
+ // 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.arguments = arguments;
+ this.warmupIterations = warmupIterations;
+ this.attachedMethod = null;
+ }
+
+ public Method getTestMethod() {
+ return testMethod;
+ }
+
+ public CompLevel getCompLevel() {
+ return compLevel;
+ }
+
+ public int getWarmupIterations() {
+ return warmupIterations;
+ }
+
+ public boolean hasArguments() {
+ return arguments != null;
+ }
+
+ public Object[] getArguments() {
+ return Arrays.stream(arguments).map(ArgumentValue::getArgument).toArray();
+ }
+
+ public void setAttachedMethod(Method m) {
+ attachedMethod = m;
+ }
+
+ public Method getAttachedMethod() {
+ return attachedMethod;
+ }
+
+ public void printFixedRandomArguments() {
+ if (hasArguments()) {
+ boolean hasRandomArgs = false;
+ StringBuilder builder = new StringBuilder("Fixed random arguments for method ").append(testMethod).append(": ");
+ for (int i = 0; i < arguments.length; i++) {
+ ArgumentValue argument = arguments[i];
+ if (argument.isFixedRandom()) {
+ hasRandomArgs = true;
+ Object argumentVal = argument.getArgument();
+ builder.append("arg ").append(i).append(": ").append(argumentVal.toString());
+ if (argumentVal instanceof Character) {
+ builder.append(" (").append((int)(Character)argumentVal).append(")");
+ }
+ builder.append(", ");
+ }
+ }
+ if (hasRandomArgs) {
+ // Drop the last comma and space.
+ builder.setLength(builder.length() - 2);
+ System.out.println(builder.toString());
+ }
+ }
+ }
+
+ public String getArgumentsString() {
+ if (hasArguments()) {
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < arguments.length; i++) {
+ builder.append("arg ").append(i).append(": ").append(arguments[i].getArgument()).append(", ");
+ }
+ builder.setLength(builder.length() - 2);
+ return builder.toString();
+ } else {
+ return "";
+ }
+ }
+
+ public Object invoke(Object obj, Object... args) {
+ try {
+ return testMethod.invoke(obj, args);
+ } catch (Exception e) {
+ throw new TestRunException("There was an error while invoking @Test method " + testMethod, e);
+ }
+ }
+}
+
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java
new file mode 100644
index 00000000000..57e8bd4f2d3
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2021, 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.test;
+
+import compiler.lib.ir_framework.*;
+import compiler.lib.ir_framework.shared.*;
+import sun.hotspot.WhiteBox;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Function;
+
+/**
+ * Prints an encoding to the dedicated test framework socket whether @IR rules of @Test methods should be applied or not.
+ * This is done during the execution of the test VM by checking the active VM flags. This encoding is eventually parsed
+ * and checked by the IRMatcher class in the driver VM after the termination of the test VM.
+ */
+public class IREncodingPrinter {
+ public static final String START = "##### IRMatchRulesEncoding - used by TestFramework #####";
+ public static final String END = "----- END -----";
+ public static final int NO_RULE_APPLIED = -1;
+
+ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+ private static final List> LONG_GETTERS = Arrays.asList(
+ WHITE_BOX::getIntVMFlag, WHITE_BOX::getUintVMFlag, WHITE_BOX::getIntxVMFlag,
+ WHITE_BOX::getUintxVMFlag, WHITE_BOX::getUint64VMFlag, WHITE_BOX::getSizeTVMFlag);
+
+ private final StringBuilder output = new StringBuilder();
+ private Method method;
+ private int ruleIndex;
+
+ public IREncodingPrinter() {
+ output.append(START).append(System.lineSeparator());
+ output.append(",{comma separated applied @IR rule ids}").append(System.lineSeparator());
+ }
+
+ /**
+ * Emits ",{ids}" where {ids} is either:
+ * - indices of all @IR rules that should be applied, separated by a comma
+ * - "-1" if no @IR rule should not be applied
+ */
+ public void emitRuleEncoding(Method m, boolean skipped) {
+ method = m;
+ int i = 0;
+ ArrayList validRules = new ArrayList<>();
+ IR[] irAnnos = m.getAnnotationsByType(IR.class);
+ if (!skipped) {
+ for (IR irAnno : irAnnos) {
+ ruleIndex = i + 1;
+ try {
+ if (shouldApplyIrRule(irAnno)) {
+ validRules.add(i);
+ }
+ } catch (TestFormatException e) {
+ // Catch logged failure and continue to check other IR annotations.
+ }
+ i++;
+ }
+ }
+ if (irAnnos.length != 0) {
+ output.append(m.getName());
+ if (validRules.isEmpty()) {
+ output.append("," + NO_RULE_APPLIED);
+ } else {
+ for (i = 0; i < validRules.size(); i++) {
+ output.append(",").append(validRules.get(i));
+ }
+ }
+ output.append(System.lineSeparator());
+ }
+ }
+
+ private boolean shouldApplyIrRule(IR irAnno) {
+ checkIRAnnotations(irAnno);
+ if (irAnno.applyIf().length != 0) {
+ return hasAllRequiredFlags(irAnno.applyIf(), "applyIf");
+ }
+
+ if (irAnno.applyIfNot().length != 0) {
+ return hasNoRequiredFlags(irAnno.applyIfNot(), "applyIfNot");
+ }
+
+ if (irAnno.applyIfAnd().length != 0) {
+ return hasAllRequiredFlags(irAnno.applyIfAnd(), "applyIfAnd");
+ }
+
+ if (irAnno.applyIfOr().length != 0) {
+ return !hasNoRequiredFlags(irAnno.applyIfOr(), "applyIfOr");
+ }
+ // No conditions, always apply.
+ return true;
+ }
+
+ private void checkIRAnnotations(IR irAnno) {
+ TestFormat.checkNoThrow(irAnno.counts().length != 0 || irAnno.failOn().length != 0,
+ "Must specify either counts or failOn constraint" + failAt());
+ int applyRules = 0;
+ if (irAnno.applyIfAnd().length != 0) {
+ applyRules++;
+ TestFormat.checkNoThrow(irAnno.applyIfAnd().length > 2,
+ "Use applyIf or applyIfNot or at least 2 conditions for applyIfAnd" + failAt());
+ }
+ if (irAnno.applyIfOr().length != 0) {
+ applyRules++;
+ TestFormat.checkNoThrow(irAnno.applyIfOr().length > 2,
+ "Use applyIf or applyIfNot or at least 2 conditions for applyIfOr" + failAt());
+ }
+ if (irAnno.applyIf().length != 0) {
+ applyRules++;
+ TestFormat.checkNoThrow(irAnno.applyIf().length <= 2,
+ "Use applyIfAnd or applyIfOr or only 1 condition for applyIf" + failAt());
+ }
+ if (irAnno.applyIfNot().length != 0) {
+ applyRules++;
+ TestFormat.checkNoThrow(irAnno.applyIfNot().length <= 2,
+ "Use applyIfAnd or applyIfOr or only 1 condition for applyIfNot" + failAt());
+ }
+ TestFormat.checkNoThrow(applyRules <= 1,
+ "Can only specify one apply constraint " + failAt());
+
+ }
+
+ private boolean hasAllRequiredFlags(String[] andRules, String ruleType) {
+ boolean returnValue = true;
+ for (int i = 0; i < andRules.length; i++) {
+ String flag = andRules[i].trim();
+ i++;
+ TestFormat.check(i < andRules.length, "Missing value for flag " + flag + " in " + ruleType + failAt());
+ String value = andRules[i].trim();
+ if (!check(flag, value) && returnValue) {
+ // Rule will not be applied but keep processing the other flags to verify that they are sane.
+ returnValue = false;
+ }
+ }
+ return returnValue;
+ }
+
+ private boolean hasNoRequiredFlags(String[] orRules, String ruleType) {
+ boolean returnValue = true;
+ for (int i = 0; i < orRules.length; i++) {
+ String flag = orRules[i];
+ i++;
+ TestFormat.check(i < orRules.length, "Missing value for flag " + flag + " in " + ruleType + failAt());
+ String value = orRules[i];
+ if (check(flag, value) && returnValue) {
+ // Rule will not be applied but keep processing the other flags to verify that they are sane.
+ returnValue = false;
+ }
+ }
+ return returnValue;
+ }
+
+ private boolean check(String flag, String value) {
+ if (flag.isEmpty()) {
+ TestFormat.failNoThrow("Provided empty flag" + failAt());
+ return false;
+ }
+ if (value.isEmpty()) {
+ TestFormat.failNoThrow("Provided empty value for flag " + flag + failAt());
+ return false;
+ }
+ Object actualFlagValue = WHITE_BOX.getBooleanVMFlag(flag);
+ if (actualFlagValue != null) {
+ return checkBooleanFlag(flag, value, (Boolean) actualFlagValue);
+ }
+ actualFlagValue = LONG_GETTERS.stream().map(f -> f.apply(flag)).filter(Objects::nonNull).findAny().orElse(null);
+ if (actualFlagValue != null) {
+ return checkLongFlag(flag, value, (Long) actualFlagValue);
+ }
+ actualFlagValue = WHITE_BOX.getDoubleVMFlag(flag);
+ if (actualFlagValue != null) {
+ return checkDoubleFlag(flag, value, (Double) actualFlagValue);
+ }
+ actualFlagValue = WHITE_BOX.getStringVMFlag(flag);
+ if (actualFlagValue != null) {
+ return value.equals(actualFlagValue);
+ }
+
+ // This could be improved if the Whitebox offers a "isVMFlag" function. For now, just check if we can actually set
+ // a value for a string flag. If we find this value, it's a string flag. If null is returned, the flag is unknown.
+ WHITE_BOX.setStringVMFlag(flag, "test");
+ String stringFlagValue = WHITE_BOX.getStringVMFlag(flag);
+ if (stringFlagValue == null) {
+ TestFormat.failNoThrow("Could not find VM flag \"" + flag + "\"" + failAt());
+ return false;
+ }
+ TestFramework.check(stringFlagValue.equals("test"),
+ "Must find newly set flag value \"test\" but found " + failAt());
+ WHITE_BOX.setStringVMFlag(flag, null); // reset flag to NULL
+ return false;
+ }
+
+ private boolean checkBooleanFlag(String flag, String value, boolean actualFlagValue) {
+ boolean booleanValue = false;
+ if ("true".equalsIgnoreCase(value)) {
+ booleanValue = true;
+ } else if (!"false".equalsIgnoreCase(value)) {
+ TestFormat.failNoThrow("Invalid value \"" + value + "\" for boolean flag " + flag + failAt());
+ return false;
+ }
+ return booleanValue == actualFlagValue;
+ }
+
+ private boolean checkLongFlag(String flag, String value, long actualFlagValue) {
+ long longValue;
+ ParsedComparator parsedComparator;
+ try {
+ parsedComparator = ParsedComparator.parseComparator(value);
+ } catch (CheckedTestFrameworkException e) {
+ TestFormat.failNoThrow("Invalid comparator in \"" + value + "\" for integer based flag " + flag + failAt());
+ return false;
+ } catch (IndexOutOfBoundsException e) {
+ TestFormat.failNoThrow("Provided empty value for integer based flag " + flag + failAt());
+ return false;
+ }
+ try {
+ longValue = Long.parseLong(parsedComparator.getStrippedString());
+ } catch (NumberFormatException e) {
+ String comparator = parsedComparator.getComparator();
+ if (!comparator.isEmpty()) {
+ comparator = "after comparator \"" + parsedComparator.getComparator() + "\"";
+ }
+ TestFormat.failNoThrow("Invalid value \"" + parsedComparator.getStrippedString() + "\" "
+ + comparator + " for integer based flag " + flag + failAt());
+ return false;
+ }
+ return parsedComparator.getPredicate().test(actualFlagValue, longValue);
+ }
+
+ private boolean checkDoubleFlag(String flag, String value, double actualFlagValue) {
+ double doubleValue;
+ ParsedComparator parsedComparator;
+ try {
+ parsedComparator = ParsedComparator.parseComparator(value);
+ } catch (CheckedTestFrameworkException e) {
+ TestFormat.failNoThrow("Invalid comparator in \"" + value + "\" for floating point based flag " + flag + failAt());
+ return false;
+ } catch (IndexOutOfBoundsException e) {
+ TestFormat.failNoThrow("Provided empty value for floating point based flag " + flag + failAt());
+ return false;
+ }
+ try {
+ doubleValue = Double.parseDouble(parsedComparator.getStrippedString());
+ } catch (NumberFormatException e) {
+ String comparator = parsedComparator.getComparator();
+ if (!comparator.isEmpty()) {
+ comparator = "after comparator \"" + parsedComparator.getComparator() + "\"";
+ }
+ TestFormat.failNoThrow("Invalid value \"" + parsedComparator.getStrippedString() + "\" "
+ + comparator + " for floating point based flag " + flag + failAt());
+ return false;
+ }
+ return parsedComparator.getPredicate().test(actualFlagValue, doubleValue);
+ }
+
+ private String failAt() {
+ return " for @IR rule " + ruleIndex + " at " + method;
+ }
+
+ public void emit() {
+ output.append(END);
+ TestFrameworkSocket.write(output.toString(), "IR rule application encoding");
+ }
+}
+
+
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/TestVM.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/TestVM.java
new file mode 100644
index 00000000000..414cbc84fa5
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/TestVM.java
@@ -0,0 +1,955 @@
+/*
+ * Copyright (c) 2021, 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.test;
+
+import compiler.lib.ir_framework.*;
+import compiler.lib.ir_framework.Compiler;
+import compiler.lib.ir_framework.shared.*;
+import jdk.test.lib.Platform;
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * This class' main method is called from {@link TestFramework} and represents the so-called "test VM". The class is
+ * the heart of the framework and is responsible for executing all the specified tests in the test class. It uses the
+ * Whitebox API and reflection to achieve this task.
+ */
+public class TestVM {
+ private static final WhiteBox WHITE_BOX;
+
+ static {
+ try {
+ WHITE_BOX = WhiteBox.getWhiteBox();
+ } catch (UnsatisfiedLinkError e) {
+ System.err.println(System.lineSeparator() + """
+ ##########################################################
+ - Did you call a test-related interface method from
+ TestFramework in main() of your test? Make sure to
+ only call setup/run methods and no checks or
+ assertions from main() of your test!
+ - Are you rerunning the test VM (TestVM class)
+ directly after a JTreg run? Make sure to start it
+ from within JTwork/scratch and with the flag
+ -DReproduce=true!
+ ##########################################################
+ """);
+ throw e;
+ }
+ }
+
+ /**
+ * The default number of warm-up iterations used to warm up a {@link Test} annotated test method.
+ * Use {@code -DWarmup=XY} to specify a different default value. An individual warm-up can also be
+ * set by specifying a {@link Warmup} iteration for a test.
+ */
+ public static final int WARMUP_ITERATIONS = Integer.parseInt(System.getProperty("Warmup", "2000"));
+
+ private static final boolean TIERED_COMPILATION = (Boolean)WHITE_BOX.getVMFlag("TieredCompilation");
+ private static final CompLevel TIERED_COMPILATION_STOP_AT_LEVEL = CompLevel.forValue(((Long)WHITE_BOX.getVMFlag("TieredStopAtLevel")).intValue());
+ public static final boolean TEST_C1 = TIERED_COMPILATION && TIERED_COMPILATION_STOP_AT_LEVEL.getValue() < CompLevel.C2.getValue();
+
+ static final boolean XCOMP = Platform.isComp();
+ static final boolean VERBOSE = Boolean.getBoolean("Verbose");
+ private static final boolean PRINT_TIMES = Boolean.getBoolean("PrintTimes");
+ public static final boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler");
+ static final boolean EXCLUDE_RANDOM = Boolean.getBoolean("ExcludeRandom");
+ private static final String TESTLIST = System.getProperty("Test", "");
+ private static final String EXCLUDELIST = System.getProperty("Exclude", "");
+ private static final boolean DUMP_REPLAY = Boolean.getBoolean("DumpReplay");
+ private static final boolean GC_AFTER = Boolean.getBoolean("GCAfter");
+ private static final boolean SHUFFLE_TESTS = Boolean.parseBoolean(System.getProperty("ShuffleTests", "true"));
+ // Use separate flag as VERIFY_IR could have been set by user but due to other flags it was disabled by flag VM.
+ private static final boolean PRINT_VALID_IR_RULES = Boolean.getBoolean("ShouldDoIRVerification");
+ protected static final long PER_METHOD_TRAP_LIMIT = (Long)WHITE_BOX.getVMFlag("PerMethodTrapLimit");
+ protected static final boolean PROFILE_INTERPRETER = (Boolean)WHITE_BOX.getVMFlag("ProfileInterpreter");
+ private static final boolean FLIP_C1_C2 = Boolean.getBoolean("FlipC1C2");
+ private static final boolean IGNORE_COMPILER_CONTROLS = Boolean.getBoolean("IgnoreCompilerControls");
+
+ private final HashMap declaredTests = new HashMap<>();
+ private final List allTests = new ArrayList<>();
+ private final HashMap testMethodMap = new HashMap<>();
+ private final List excludeList;
+ private final List testList;
+ private Set> helperClasses = null; // Helper classes that contain framework annotations to be processed.
+ private final IREncodingPrinter irMatchRulePrinter;
+ private final Class> testClass;
+ private final Map forceCompileMap = new HashMap<>();
+
+ private TestVM(Class> testClass) {
+ TestRun.check(testClass != null, "Test class cannot be null");
+ this.testClass = testClass;
+ this.testList = createTestFilterList(TESTLIST, testClass);
+ this.excludeList = createTestFilterList(EXCLUDELIST, testClass);
+
+ if (PRINT_VALID_IR_RULES) {
+ irMatchRulePrinter = new IREncodingPrinter();
+ } else {
+ irMatchRulePrinter = null;
+ }
+ }
+
+ /**
+ * Parse "test1,test2,test3" into a list.
+ */
+ private static List createTestFilterList(String list, Class> testClass) {
+ List filterList = null;
+ if (!list.isEmpty()) {
+ String classPrefix = testClass.getSimpleName() + ".";
+ filterList = new ArrayList<>(Arrays.asList(list.split(",")));
+ for (int i = filterList.size() - 1; i >= 0; i--) {
+ String test = filterList.get(i);
+ if (test.indexOf(".") > 0) {
+ if (test.startsWith(classPrefix)) {
+ test = test.substring(classPrefix.length());
+ filterList.set(i, test);
+ } else {
+ filterList.remove(i);
+ }
+ }
+ }
+ }
+ return filterList;
+ }
+
+ /**
+ * Main entry point of the test VM.
+ */
+ public static void main(String[] args) {
+ try {
+ String testClassName = args[0];
+ System.out.println("TestVM main() called - about to run tests in class " + testClassName);
+ Class> testClass = getClassObject(testClassName, "test");
+
+ TestVM framework = new TestVM(testClass);
+ framework.addHelperClasses(args);
+ framework.start();
+ } finally {
+ TestFrameworkSocket.closeClientSocket();
+ }
+ }
+
+ protected static Class> getClassObject(String className, String classType) {
+ try {
+ return Class.forName(className);
+ } catch (Exception e) {
+ throw new TestRunException("Could not find " + classType + " class", e);
+ }
+ }
+
+ /**
+ * Set up all helper classes and verify they are specified correctly.
+ */
+ private void addHelperClasses(String[] args) {
+ Class>[] helperClassesList = getHelperClasses(args);
+ if (helperClassesList != null) {
+ TestRun.check(Arrays.stream(helperClassesList).noneMatch(Objects::isNull), "A Helper class cannot be null");
+ this.helperClasses = new HashSet<>();
+
+ for (Class> helperClass : helperClassesList) {
+ if (Arrays.stream(testClass.getDeclaredClasses()).anyMatch(c -> c == helperClass)) {
+ // Nested class of test class is automatically treated as helper class
+ TestFormat.failNoThrow("Nested " + helperClass + " inside test " + testClass + " is implicitly"
+ + " treated as helper class and does not need to be specified as such.");
+ continue;
+ }
+ TestRun.check(!this.helperClasses.contains(helperClass), "Cannot add the same class twice: " + helperClass);
+ this.helperClasses.add(helperClass);
+ }
+ }
+ }
+
+ private static Class>[] getHelperClasses(String[] args) {
+ if (args.length == 1) {
+ return null;
+ }
+ Class>[] helperClasses = new Class>[args.length - 1]; // First argument is test class
+ for (int i = 1; i < args.length; i++) {
+ String helperClassName = args[i];
+ helperClasses[i - 1] = getClassObject(helperClassName, "helper");
+ }
+ return helperClasses;
+ }
+
+ private void checkHelperClass(Class> clazz) {
+ checkAnnotationsInClass(clazz, "helper");
+ for (Class> c : clazz.getDeclaredClasses()) {
+ checkAnnotationsInClass(c, "nested (and helper)");
+ }
+ }
+
+ private void checkAnnotationsInClass(Class> c, String clazzType) {
+ Method[] methods = c.getDeclaredMethods();
+ for (Method m : methods) {
+ TestFormat.checkNoThrow(getAnnotation(m, Test.class) == null,
+ "Cannot use @Test annotation in " + clazzType + " " + c + " at " + m);
+ TestFormat.checkNoThrow(getAnnotation(m, Run.class) == null,
+ "Cannot use @Run annotation in " + clazzType + " " + c + " at " + m);
+ TestFormat.checkNoThrow(getAnnotation(m, Check.class) == null,
+ "Cannot use @Check annotation in " + clazzType + " " + c + " at " + m);
+ }
+ }
+
+ /**
+ * Only called by internal tests testing the framework itself. Accessed by reflection. Not exposed to normal users.
+ */
+ private static void runTestsOnSameVM(Class> testClass) {
+ if (testClass == null) {
+ StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
+ testClass = walker.getCallerClass();
+ }
+ TestVM framework = new TestVM(testClass);
+ framework.start();
+ }
+
+ /**
+ * Once everything is initialized and set up, start collecting tests and executing them afterwards.
+ */
+ private void start() {
+ setupTests();
+ checkForcedCompilationsCompleted();
+ runTests();
+ }
+
+ private void setupTests() {
+ for (Class> clazz : testClass.getDeclaredClasses()) {
+ checkAnnotationsInClass(clazz, "inner");
+ }
+ if (DUMP_REPLAY) {
+ addReplay();
+ }
+ // Make sure to first setup test methods and make them non-inlineable and only then process compile commands.
+ setupDeclaredTests();
+ processControlAnnotations(testClass);
+ processHelperClasses();
+ setupCheckedAndCustomRunTests();
+
+ // All remaining tests are simple base tests without check or specific way to run them.
+ addBaseTests();
+ if (PRINT_VALID_IR_RULES) {
+ irMatchRulePrinter.emit();
+ }
+ TestFormat.reportIfAnyFailures();
+ declaredTests.clear();
+ testMethodMap.clear();
+ }
+
+ private void addBaseTests() {
+ declaredTests.forEach((m, test) -> {
+ if (test.getAttachedMethod() == null) {
+ try {
+ Arguments argumentsAnno = getAnnotation(m, Arguments.class);
+ TestFormat.check(argumentsAnno != null || m.getParameterCount() == 0, "Missing @Arguments annotation to define arguments of " + m);
+ BaseTest baseTest = new BaseTest(test, shouldExcludeTest(m.getName()));
+ allTests.add(baseTest);
+ if (PRINT_VALID_IR_RULES) {
+ irMatchRulePrinter.emitRuleEncoding(m, baseTest.isSkipped());
+ }
+ } catch (TestFormatException e) {
+ // Failure logged. Continue and report later.
+ }
+ }
+ });
+ }
+
+ /**
+ * Check if user wants to exclude this test by checking the -DTest and -DExclude lists.
+ */
+ private boolean shouldExcludeTest(String testName) {
+ boolean hasTestList = testList != null;
+ boolean hasExcludeList = excludeList != null;
+ if (hasTestList) {
+ return !testList.contains(testName) || (hasExcludeList && excludeList.contains(testName));
+ } else if (hasExcludeList) {
+ return excludeList.contains(testName);
+ }
+ return false;
+ }
+
+ /**
+ * Generate replay compilation files.
+ */
+ private void addReplay() {
+ String directive = "[{ match: \"*.*\", DumpReplay: true }]";
+ TestFramework.check(WHITE_BOX.addCompilerDirective(directive) == 1, "Failed to add DUMP_REPLAY directive");
+ }
+
+ private void processControlAnnotations(Class> clazz) {
+ if (IGNORE_COMPILER_CONTROLS) {
+ return;
+ }
+ // Also apply compile commands to all inner classes of 'clazz'.
+ ArrayList> classes = new ArrayList<>(Arrays.asList(clazz.getDeclaredClasses()));
+ classes.add(clazz);
+ for (Class> c : classes) {
+ applyClassAnnotations(c);
+ List executables = new ArrayList<>(Arrays.asList(c.getDeclaredMethods()));
+ Collections.addAll(executables, c.getDeclaredConstructors());
+ for (Executable ex : executables) {
+ checkClassAnnotations(ex);
+ try {
+ applyIndependentCompilationCommands(ex);
+ } catch (TestFormatException e) {
+ // Failure logged. Continue and report later.
+ }
+ }
+
+ // Only force compilation now because above annotations affect inlining
+ for (Executable ex : executables) {
+ try {
+ applyForceCompileCommand(ex);
+ } catch (TestFormatException e) {
+ // Failure logged. Continue and report later.
+ }
+ }
+ }
+ }
+
+ private void applyClassAnnotations(Class> c) {
+ ForceCompileClassInitializer anno = getAnnotation(c, ForceCompileClassInitializer.class);
+ if (anno == null) {
+ return;
+ }
+
+ // Compile class initializer
+ CompLevel level = anno.value();
+ if (level == CompLevel.SKIP || level == CompLevel.WAIT_FOR_COMPILATION) {
+ TestFormat.failNoThrow("Cannot define compilation level SKIP or WAIT_FOR_COMPILATION in " +
+ "@ForceCompileClassInitializer at " + c);
+ return;
+ }
+ level = restrictCompLevel(anno.value());
+ if (level != CompLevel.SKIP) {
+ // Make sure class is initialized to avoid compilation bailout of
+ getClassObject(c.getName(), "nested"); // calls Class.forName() to initialize 'c'
+ TestFormat.checkNoThrow(WHITE_BOX.enqueueInitializerForCompilation(c, level.getValue()),
+ "Failed to enqueue of " + c + " for compilation. Did you specify "
+ + "@ForceCompileClassInitializer without providing a static class initialization? "
+ + "Make sure to provide any form of static initialization or remove the annotation.");
+ }
+ }
+
+ private void checkClassAnnotations(Executable ex) {
+ TestFormat.checkNoThrow(getAnnotation(ex, ForceCompileClassInitializer.class) == null,
+ "@ForceCompileClassInitializer only allowed at classes but not at method " + ex);
+ }
+
+ /**
+ * Exclude a method from compilation with a compiler randomly. Return the compiler for which the method was made
+ * not compilable.
+ */
+ public static Compiler excludeRandomly(Executable ex) {
+ Compiler compiler = switch (Utils.getRandomInstance().nextInt() % 3) {
+ case 1 -> Compiler.C1;
+ case 2 -> Compiler.C2;
+ default -> Compiler.ANY;
+ };
+ WHITE_BOX.makeMethodNotCompilable(ex, compiler.getValue(), false);
+ WHITE_BOX.makeMethodNotCompilable(ex, compiler.getValue(), true);
+ System.out.println("Excluding from " + compiler.name() + " compilation: " + ex);
+ return compiler;
+ }
+
+ private void applyIndependentCompilationCommands(Executable ex) {
+ ForceInline forceInlineAnno = getAnnotation(ex, ForceInline.class);
+ DontInline dontInlineAnno = getAnnotation(ex, DontInline.class);
+ ForceCompile forceCompileAnno = getAnnotation(ex, ForceCompile.class);
+ DontCompile dontCompileAnno = getAnnotation(ex, DontCompile.class);
+ checkCompilationCommandAnnotations(ex, forceInlineAnno, dontInlineAnno, forceCompileAnno, dontCompileAnno);
+ // First handle inline annotations
+ if (dontInlineAnno != null) {
+ WHITE_BOX.testSetDontInlineMethod(ex, true);
+ } else if (forceInlineAnno != null) {
+ WHITE_BOX.testSetForceInlineMethod(ex, true);
+ }
+ if (dontCompileAnno != null) {
+ dontCompileWithCompiler(ex, dontCompileAnno.value());
+ }
+ if (EXCLUDE_RANDOM && getAnnotation(ex, Test.class) == null && forceCompileAnno == null && dontCompileAnno == null) {
+ // Randomly exclude helper methods from compilation
+ if (Utils.getRandomInstance().nextBoolean()) {
+ excludeRandomly(ex);
+ }
+ }
+ }
+
+ private void checkCompilationCommandAnnotations(Executable ex, ForceInline forceInlineAnno, DontInline dontInlineAnno, ForceCompile forceCompileAnno, DontCompile dontCompileAnno) {
+ Test testAnno = getAnnotation(ex, Test.class);
+ Run runAnno = getAnnotation(ex, Run.class);
+ Check checkAnno = getAnnotation(ex, Check.class);
+ TestFormat.check((testAnno == null && runAnno == null && checkAnno == null) || Stream.of(forceCompileAnno, dontCompileAnno, forceInlineAnno, dontInlineAnno).noneMatch(Objects::nonNull),
+ "Cannot use explicit compile command annotations (@ForceInline, @DontInline, " +
+ "@ForceCompile or @DontCompile) together with @Test, @Check or @Run: " + ex + ". Use compLevel in @Test for fine tuning.");
+ if (Stream.of(forceInlineAnno, dontCompileAnno, dontInlineAnno).filter(Objects::nonNull).count() > 1) {
+ // Failure
+ TestFormat.check(dontCompileAnno == null || dontInlineAnno == null,
+ "@DontInline is implicitely done with @DontCompile annotation at " + ex);
+ TestFormat.fail("Cannot mix @ForceInline, @DontInline and @DontCompile at the same time at " + ex);
+ }
+ TestFormat.check(forceInlineAnno == null || dontInlineAnno == null, "Cannot have @ForceInline and @DontInline at the same time at " + ex);
+ if (forceCompileAnno != null && dontCompileAnno != null) {
+ CompLevel forceCompileLevel = forceCompileAnno.value();
+ Compiler dontCompileCompiler = dontCompileAnno.value();
+ TestFormat.check(dontCompileCompiler != Compiler.ANY,
+ "Cannot have @DontCompile(Compiler.ANY) and @ForceCompile at the same time at " + ex);
+ TestFormat.check(forceCompileLevel != CompLevel.ANY,
+ "Cannot have @ForceCompile(CompLevel.ANY) and @DontCompile at the same time at " + ex);
+ TestFormat.check(forceCompileLevel.isNotCompilationLevelOfCompiler(dontCompileCompiler),
+ "Overlapping compilation level and compiler with @ForceCompile and @DontCompile at " + ex);
+ }
+ }
+
+ /**
+ * Exlude the method from compilation and make sure it is not inlined.
+ */
+ private void dontCompileAndDontInlineMethod(Method m) {
+ if (!IGNORE_COMPILER_CONTROLS) {
+ WHITE_BOX.makeMethodNotCompilable(m, CompLevel.ANY.getValue(), true);
+ WHITE_BOX.makeMethodNotCompilable(m, CompLevel.ANY.getValue(), false);
+ WHITE_BOX.testSetDontInlineMethod(m, true);
+ }
+ }
+
+ private void dontCompileWithCompiler(Executable ex, Compiler compiler) {
+ if (VERBOSE) {
+ System.out.println("dontCompileWithCompiler " + ex + " , compiler = " + compiler.name());
+ }
+ WHITE_BOX.makeMethodNotCompilable(ex, compiler.getValue(), true);
+ WHITE_BOX.makeMethodNotCompilable(ex, compiler.getValue(), false);
+ if (compiler == Compiler.ANY) {
+ WHITE_BOX.testSetDontInlineMethod(ex, true);
+ }
+ }
+
+ private void applyForceCompileCommand(Executable ex) {
+ ForceCompile forceCompileAnno = getAnnotation(ex, ForceCompile.class);
+ if (forceCompileAnno != null) {
+ CompLevel complevel = forceCompileAnno.value();
+ TestFormat.check(complevel != CompLevel.SKIP && complevel != CompLevel.WAIT_FOR_COMPILATION,
+ "Cannot define compilation level SKIP or WAIT_FOR_COMPILATION in @ForceCompile at " + ex);
+ complevel = restrictCompLevel(forceCompileAnno.value());
+ if (FLIP_C1_C2) {
+ complevel = complevel.flipCompLevel();
+ }
+ if (EXCLUDE_RANDOM) {
+ complevel = complevel.excludeCompilationRandomly(ex);
+ }
+ if (complevel != CompLevel.SKIP) {
+ enqueueForCompilation(ex, complevel);
+ forceCompileMap.put(ex, complevel);
+ }
+ }
+ }
+
+ static void enqueueForCompilation(Executable ex, CompLevel requestedCompLevel) {
+ if (TestVM.VERBOSE) {
+ System.out.println("enqueueForCompilation " + ex + ", level = " + requestedCompLevel);
+ }
+ CompLevel compLevel = restrictCompLevel(requestedCompLevel);
+ if (compLevel != CompLevel.SKIP) {
+ WHITE_BOX.enqueueMethodForCompilation(ex, compLevel.getValue());
+ } else {
+ System.out.println("Skipped compilation on level " + requestedCompLevel + " due to VM flags not allowing it.");
+ }
+ }
+
+ /**
+ * Setup @Test annotated method an add them to the declaredTests map to have a convenient way of accessing them
+ * once setting up a framework test (base checked, or custom run test).
+ */
+ private void setupDeclaredTests() {
+ for (Method m : testClass.getDeclaredMethods()) {
+ Test testAnno = getAnnotation(m, Test.class);
+ try {
+ if (testAnno != null) {
+ addDeclaredTest(m);
+ } else {
+ TestFormat.checkNoThrow(!m.isAnnotationPresent(IR.class), "Found @IR annotation on non-@Test method " + m);
+ TestFormat.checkNoThrow(!m.isAnnotationPresent(Warmup.class) || getAnnotation(m, Run.class) != null,
+ "Found @Warmup annotation on non-@Test or non-@Run method " + m);
+ }
+ } catch (TestFormatException e) {
+ // Failure logged. Continue and report later.
+ }
+ }
+ TestFormat.checkNoThrow(!declaredTests.isEmpty(), "Did not specify any @Test methods in " + testClass);
+ }
+
+ private void addDeclaredTest(Method m) {
+ Test testAnno = getAnnotation(m, Test.class);
+ checkTestAnnotations(m, testAnno);
+ Warmup warmup = getAnnotation(m, Warmup.class);
+ int warmupIterations = WARMUP_ITERATIONS;
+ if (warmup != null) {
+ warmupIterations = warmup.value();
+ TestFormat.checkNoThrow(warmupIterations >= 0, "Cannot have negative value for @Warmup at " + m);
+ }
+
+ if (!IGNORE_COMPILER_CONTROLS) {
+ // Don't inline test methods by default. Do not apply this when -DIgnoreCompilerControls=true is set.
+ WHITE_BOX.testSetDontInlineMethod(m, true);
+ }
+ CompLevel compLevel = restrictCompLevel(testAnno.compLevel());
+ if (FLIP_C1_C2) {
+ compLevel = compLevel.flipCompLevel();
+ }
+ if (EXCLUDE_RANDOM) {
+ compLevel = compLevel.excludeCompilationRandomly(m);
+ }
+ DeclaredTest test = new DeclaredTest(m, ArgumentValue.getArguments(m), compLevel, warmupIterations);
+ declaredTests.put(m, test);
+ testMethodMap.put(m.getName(), m);
+ }
+
+ private void checkTestAnnotations(Method m, Test testAnno) {
+ TestFormat.check(!testMethodMap.containsKey(m.getName()),
+ "Cannot overload two @Test methods: " + m + ", " + testMethodMap.get(m.getName()));
+ TestFormat.check(testAnno != null, m + " must be a method with a @Test annotation");
+
+ Check checkAnno = getAnnotation(m, Check.class);
+ Run runAnno = getAnnotation(m, Run.class);
+ TestFormat.check(checkAnno == null && runAnno == null,
+ m + " has invalid @Check or @Run annotation while @Test annotation is present.");
+
+ TestFormat.checkNoThrow(Arrays.stream(m.getParameterTypes()).noneMatch(AbstractInfo.class::isAssignableFrom),
+ "Cannot " + AbstractInfo.class + " or any of its subclasses as parameter type at " +
+ "@Test method " + m);
+
+ TestFormat.checkNoThrow(!AbstractInfo.class.isAssignableFrom(m.getReturnType()),
+ "Cannot " + AbstractInfo.class + " or any of its subclasses as return type at " +
+ "@Test method " + m);
+ }
+
+
+ /**
+ * Get the appropriate level as permitted by the test scenario and VM flags.
+ */
+ private static CompLevel restrictCompLevel(CompLevel compLevel) {
+ if (!USE_COMPILER) {
+ return CompLevel.SKIP;
+ }
+ if (compLevel == CompLevel.ANY) {
+ // Use highest available compilation level by default (usually C2).
+ compLevel = TIERED_COMPILATION_STOP_AT_LEVEL;
+ }
+ if (!TIERED_COMPILATION && compLevel.getValue() < CompLevel.C2.getValue()) {
+ return CompLevel.SKIP;
+ }
+ if (TIERED_COMPILATION && compLevel.getValue() > TIERED_COMPILATION_STOP_AT_LEVEL.getValue()) {
+ return CompLevel.SKIP;
+ }
+ return compLevel;
+ }
+
+ /**
+ * Verify that the helper classes do not contain illegal framework annotations and then apply the actions as
+ * specified by the different helper class annotations.
+ */
+ private void processHelperClasses() {
+ if (helperClasses != null) {
+ for (Class> helperClass : helperClasses) {
+ // Process the helper classes and apply the explicit compile commands
+ TestFormat.checkNoThrow(helperClass != testClass,
+ "Cannot specify test " + testClass + " as helper class, too.");
+ checkHelperClass(helperClass);
+ processControlAnnotations(helperClass);
+ }
+ }
+ }
+
+ /**
+ * First set up checked (with @Check) and custom run tests (with @Run). All remaining unmatched/unused @Test methods
+ * are treated as base tests and set up as such later.
+ */
+ private void setupCheckedAndCustomRunTests() {
+ for (Method m : testClass.getDeclaredMethods()) {
+ Check checkAnno = getAnnotation(m, Check.class);
+ Run runAnno = getAnnotation(m, Run.class);
+ Arguments argumentsAnno = getAnnotation(m, Arguments.class);
+ try {
+ TestFormat.check(argumentsAnno == null || (checkAnno == null && runAnno == null),
+ "Cannot have @Argument annotation in combination with @Run or @Check at " + m);
+ if (checkAnno != null) {
+ addCheckedTest(m, checkAnno, runAnno);
+ } else if (runAnno != null) {
+ addCustomRunTest(m, runAnno);
+ }
+ } catch (TestFormatException e) {
+ // Failure logged. Continue and report later.
+ }
+ }
+ }
+
+ /**
+ * Set up a checked test by first verifying the correct format of the @Test and @Check method and then adding it
+ * to the allTests list which keeps track of all framework tests that are eventually executed.
+ */
+ private void addCheckedTest(Method m, Check checkAnno, Run runAnno) {
+ Method testMethod = testMethodMap.get(checkAnno.test());
+ DeclaredTest test = declaredTests.get(testMethod);
+ checkCheckedTest(m, checkAnno, runAnno, testMethod, test);
+ test.setAttachedMethod(m);
+ CheckedTest.Parameter parameter = getCheckedTestParameter(m, testMethod);
+ dontCompileAndDontInlineMethod(m);
+ CheckedTest checkedTest = new CheckedTest(test, m, checkAnno, parameter, shouldExcludeTest(testMethod.getName()));
+ allTests.add(checkedTest);
+ if (PRINT_VALID_IR_RULES) {
+ // Only need to emit IR verification information if IR verification is actually performed.
+ irMatchRulePrinter.emitRuleEncoding(m, checkedTest.isSkipped());
+ }
+ }
+
+ private void checkCheckedTest(Method m, Check checkAnno, Run runAnno, Method testMethod, DeclaredTest test) {
+ TestFormat.check(runAnno == null, m + " has invalid @Run annotation while @Check annotation is present.");
+ TestFormat.check(testMethod != null, "Did not find associated test method \"" + m.getDeclaringClass().getName()
+ + "." + checkAnno.test() + "\" for @Check at " + m);
+ TestFormat.check(test != null, "Missing @Test annotation for associated test method " + testMethod + " for @Check at " + m);
+ Method attachedMethod = test.getAttachedMethod();
+ TestFormat.check(attachedMethod == null,
+ "Cannot use @Test " + testMethod + " for more than one @Run or one @Check method. Found: " + m + ", " + attachedMethod);
+ }
+
+ /**
+ * Only allow parameters as specified in {@link Check}.
+ */
+ private CheckedTest.Parameter getCheckedTestParameter(Method m, Method testMethod) {
+ boolean firstParameterTestInfo = m.getParameterCount() > 0 && m.getParameterTypes()[0].equals(TestInfo.class);
+ boolean secondParameterTestInfo = m.getParameterCount() > 1 && m.getParameterTypes()[1].equals(TestInfo.class);
+ CheckedTest.Parameter parameter = null;
+ Class> testReturnType = testMethod.getReturnType();
+ switch (m.getParameterCount()) {
+ case 0 -> parameter = CheckedTest.Parameter.NONE;
+ case 1 -> {
+ TestFormat.checkNoThrow(firstParameterTestInfo || m.getParameterTypes()[0] == testReturnType,
+ "Single-parameter version of @Check method " + m + " must match return type of @Test " + testMethod);
+ parameter = firstParameterTestInfo ? CheckedTest.Parameter.TEST_INFO_ONLY : CheckedTest.Parameter.RETURN_ONLY;
+ }
+ case 2 -> {
+ TestFormat.checkNoThrow(m.getParameterTypes()[0] == testReturnType && secondParameterTestInfo,
+ "Two-parameter version of @Check method " + m + " must provide as first parameter the same"
+ + " return type as @Test method " + testMethod + " and as second parameter an object of " + TestInfo.class);
+ parameter = CheckedTest.Parameter.BOTH;
+ }
+ default -> TestFormat.failNoThrow("@Check method " + m + " must provide either a none, single or two-parameter variant.");
+ }
+ return parameter;
+ }
+
+ /**
+ * Set up a custom run test by first verifying the correct format of the @Test and @Run method and then adding it
+ * to the allTests list which keeps track of all framework tests that are eventually executed.
+ */
+ private void addCustomRunTest(Method m, Run runAnno) {
+ checkRunMethod(m, runAnno);
+ List tests = new ArrayList<>();
+ boolean shouldExcludeTest = true;
+ for (String testName : runAnno.test()) {
+ try {
+ Method testMethod = testMethodMap.get(testName);
+ DeclaredTest test = declaredTests.get(testMethod);
+ checkCustomRunTest(m, testName, testMethod, test, runAnno.mode());
+ test.setAttachedMethod(m);
+ tests.add(test);
+ // Only exclude custom run test if all test methods excluded
+ shouldExcludeTest &= shouldExcludeTest(testMethod.getName());
+ } catch (TestFormatException e) {
+ // Logged, continue.
+ }
+ }
+ if (tests.isEmpty()) {
+ return; // There was a format violation. Return.
+ }
+ dontCompileAndDontInlineMethod(m);
+ CustomRunTest customRunTest = new CustomRunTest(m, getAnnotation(m, Warmup.class), runAnno, tests, shouldExcludeTest);
+ allTests.add(customRunTest);
+ if (PRINT_VALID_IR_RULES) {
+ tests.forEach(test -> irMatchRulePrinter.emitRuleEncoding(test.getTestMethod(), customRunTest.isSkipped()));
+ }
+ }
+
+ /**
+ * Only allow parameters as specified in {@link Run}.
+ */
+ private void checkCustomRunTest(Method m, String testName, Method testMethod, DeclaredTest test, RunMode runMode) {
+ TestFormat.check(testMethod != null, "Did not find associated @Test method \"" + m.getDeclaringClass().getName()
+ + "." + testName + "\" specified in @Run at " + m);
+ TestFormat.check(test != null,
+ "Missing @Test annotation for associated test method " + testName + " for @Run at " + m);
+ Method attachedMethod = test.getAttachedMethod();
+ TestFormat.check(attachedMethod == null,
+ "Cannot use @Test " + testMethod + " for more than one @Run/@Check method. Found: "
+ + m + ", " + attachedMethod);
+ TestFormat.check(!test.hasArguments(),
+ "Cannot use @Arguments at test method " + testMethod + " in combination with @Run method " + m);
+ Warmup warmupAnno = getAnnotation(testMethod, Warmup.class);
+ TestFormat.checkNoThrow(warmupAnno == null,
+ "Cannot set @Warmup at @Test method " + testMethod + " when used with its @Run method "
+ + m + ". Use @Warmup at @Run method instead.");
+ Test testAnno = getAnnotation(testMethod, Test.class);
+ TestFormat.checkNoThrow(runMode != RunMode.STANDALONE || testAnno.compLevel() == CompLevel.ANY,
+ "Setting explicit compilation level for @Test method " + testMethod + " has no effect "
+ + "when used with STANDALONE @Run method " + m);
+ }
+
+ private void checkRunMethod(Method m, Run runAnno) {
+ TestFormat.check(runAnno.test().length > 0, "@Run method " + m + " must specify at least one test method");
+ TestFormat.checkNoThrow(m.getParameterCount() == 0 || (m.getParameterCount() == 1 && m.getParameterTypes()[0].equals(RunInfo.class)),
+ "@Run method " + m + " must specify either no parameter or exactly one " + RunInfo.class + " parameter.");
+ Warmup warmupAnno = getAnnotation(m, Warmup.class);
+ TestFormat.checkNoThrow(warmupAnno == null || runAnno.mode() != RunMode.STANDALONE,
+ "Cannot set @Warmup at @Run method " + m + " when used with RunMode.STANDALONE. The @Run method is only invoked once.");
+ }
+
+ private static T getAnnotation(AnnotatedElement element, Class c) {
+ T[] annos = element.getAnnotationsByType(c);
+ TestFormat.check(annos.length < 2, element + " has duplicated annotations");
+ return Arrays.stream(annos).findFirst().orElse(null);
+ }
+
+ /**
+ * Ensure that all compilations that were enforced (added to compilation queue) by framework annotations are
+ * completed. Wait if necessary for a short amount of time for their completion.
+ */
+ private void checkForcedCompilationsCompleted() {
+ if (forceCompileMap.isEmpty()) {
+ return;
+ }
+ final long started = System.currentTimeMillis();
+ long elapsed;
+ do {
+ forceCompileMap.entrySet().removeIf(entry -> WHITE_BOX.getMethodCompilationLevel(entry.getKey()) == entry.getValue().getValue());
+ if (forceCompileMap.isEmpty()) {
+ // All @ForceCompile methods are compiled at the requested level.
+ return;
+ }
+ // Retry again if not yet compiled.
+ forceCompileMap.forEach(TestVM::enqueueForCompilation);
+ elapsed = System.currentTimeMillis() - started;
+ } while (elapsed < 5000);
+ StringBuilder builder = new StringBuilder();
+ forceCompileMap.forEach((key, value) -> builder.append("- ").append(key).append(" at CompLevel.").append(value)
+ .append(System.lineSeparator()));
+ throw new TestRunException("Could not force compile the following @ForceCompile methods:"
+ + System.lineSeparator() + builder.toString());
+ }
+
+ /**
+ * Once all framework tests are collected, they are run in this method.
+ */
+ private void runTests() {
+ TreeMap durations = (PRINT_TIMES || VERBOSE) ? new TreeMap<>() : null;
+ long startTime = System.nanoTime();
+ List testList;
+ boolean testFilterPresent = testFilterPresent();
+ if (testFilterPresent) {
+ // Only run the specified tests by the user filters -DTest and/or -DExclude.
+ testList = allTests.stream().filter(test -> !test.isSkipped()).collect(Collectors.toList());
+ if (testList.isEmpty()) {
+ // Throw an exception to inform the user about an empty specified test set with -DTest and/or -DExclude
+ throw new NoTestsRunException();
+ }
+ } else {
+ testList = allTests;
+ }
+
+ if (SHUFFLE_TESTS) {
+ // Execute tests in random order (execution sequence affects profiling). This is done by default.
+ Collections.shuffle(testList, Utils.getRandomInstance());
+ }
+ StringBuilder builder = new StringBuilder();
+ int failures = 0;
+
+ // Execute all tests and keep track of each exception that is thrown. These are then reported once all tests
+ // are executing. This prevents a premature exit without running all tests.
+ for (AbstractTest test : testList) {
+ if (VERBOSE) {
+ System.out.println("Run " + test.toString());
+ }
+ if (testFilterPresent) {
+ TestFrameworkSocket.write("Run " + test.toString(), "testfilter", true);
+ }
+ try {
+ test.run();
+ } catch (TestRunException e) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ e.printStackTrace(pw);
+ builder.append(test.toString()).append(":").append(System.lineSeparator()).append(sw.toString())
+ .append(System.lineSeparator()).append(System.lineSeparator());
+ failures++;
+ }
+ if (PRINT_TIMES || VERBOSE) {
+ long endTime = System.nanoTime();
+ long duration = (endTime - startTime);
+ durations.put(duration, test.getName());
+ if (VERBOSE) {
+ System.out.println("Done " + test.getName() + ": " + duration + " ns = " + (duration / 1000000) + " ms");
+ }
+ }
+ if (GC_AFTER) {
+ System.out.println("doing GC");
+ WHITE_BOX.fullGC();
+ }
+ }
+
+ // Print execution times
+ if (VERBOSE || PRINT_TIMES) {
+ System.out.println(System.lineSeparator() + System.lineSeparator() + "Test execution times:");
+ for (Map.Entry entry : durations.entrySet()) {
+ System.out.format("%-10s%15d ns%n", entry.getValue() + ":", entry.getKey());
+ }
+ }
+
+ if (failures > 0) {
+ // Finally, report all occurred exceptions in a nice format.
+ String msg = System.lineSeparator() + System.lineSeparator() + "Test Failures (" + failures + ")"
+ + System.lineSeparator() + "----------------" + "-".repeat(String.valueOf(failures).length());
+ throw new TestRunException(msg + System.lineSeparator() + builder.toString());
+ }
+ }
+
+ private boolean testFilterPresent() {
+ return testList != null || excludeList != null;
+ }
+
+ enum TriState {
+ Maybe,
+ Yes,
+ No
+ }
+
+ public static void compile(Method m, CompLevel compLevel) {
+ TestRun.check(compLevel != CompLevel.SKIP && compLevel != CompLevel.WAIT_FOR_COMPILATION,
+ "Invalid compilation request with level " + compLevel);
+ enqueueForCompilation(m, compLevel);
+ }
+
+ public static void deoptimize(Method m) {
+ WHITE_BOX.deoptimizeMethod(m);
+ }
+
+ public static boolean isCompiled(Method m) {
+ return compiledAtLevel(m, CompLevel.ANY) == TriState.Yes;
+ }
+
+ public static boolean isC1Compiled(Method m) {
+ return compiledByC1(m) == TriState.Yes;
+ }
+
+ public static boolean isC2Compiled(Method m) {
+ return compiledByC2(m) == TriState.Yes;
+ }
+
+ public static boolean isCompiledAtLevel(Method m, CompLevel compLevel) {
+ return compiledAtLevel(m, compLevel) == TriState.Yes;
+ }
+
+ public static void assertDeoptimizedByC1(Method m) {
+ if (notUnstableDeoptAssertion(m, CompLevel.C1_SIMPLE)) {
+ TestRun.check(compiledByC1(m) != TriState.Yes || PER_METHOD_TRAP_LIMIT == 0 || !PROFILE_INTERPRETER,
+ m + " should have been deoptimized by C1");
+ }
+ }
+
+ public static void assertDeoptimizedByC2(Method m) {
+ if (notUnstableDeoptAssertion(m, CompLevel.C2)) {
+ TestRun.check(compiledByC2(m) != TriState.Yes || PER_METHOD_TRAP_LIMIT == 0 || !PROFILE_INTERPRETER,
+ m + " should have been deoptimized by C2");
+ }
+ }
+
+ /**
+ * Some VM flags could make the deopt assertions unstable.
+ */
+ private static boolean notUnstableDeoptAssertion(Method m, CompLevel level) {
+ return (USE_COMPILER && !XCOMP && !IGNORE_COMPILER_CONTROLS && !TEST_C1 &&
+ (!EXCLUDE_RANDOM || WHITE_BOX.isMethodCompilable(m, level.getValue(), false)));
+ }
+
+ public static void assertCompiledByC1(Method m) {
+ TestRun.check(compiledByC1(m) != TriState.No, m + " should have been C1 compiled");
+ }
+
+ public static void assertCompiledByC2(Method m) {
+ TestRun.check(compiledByC2(m) != TriState.No, m + " should have been C2 compiled");
+ }
+
+ public static void assertCompiledAtLevel(Method m, CompLevel level) {
+ TestRun.check(compiledAtLevel(m, level) != TriState.No, m + " should have been compiled at level " + level.name());
+ }
+
+ public static void assertNotCompiled(Method m) {
+ TestRun.check(!isC1Compiled(m), m + " should not have been compiled by C1");
+ TestRun.check(!isC2Compiled(m), m + " should not have been compiled by C2");
+ }
+
+ public static void assertCompiled(Method m) {
+ TestRun.check(compiledByC1(m) != TriState.No || compiledByC2(m) != TriState.No, m + " should have been compiled");
+ }
+
+ private static TriState compiledByC1(Method m) {
+ TriState triState = compiledAtLevel(m, CompLevel.C1_SIMPLE);
+ if (triState != TriState.No) {
+ return triState;
+ }
+ triState = compiledAtLevel(m, CompLevel.C1_LIMITED_PROFILE);
+ if (triState != TriState.No) {
+ return triState;
+ }
+ triState = compiledAtLevel(m, CompLevel.C1_FULL_PROFILE);
+ return triState;
+ }
+
+ private static TriState compiledByC2(Method m) {
+ return compiledAtLevel(m, CompLevel.C2);
+ }
+
+ private static TriState compiledAtLevel(Method m, CompLevel level) {
+ if (WHITE_BOX.isMethodCompiled(m, false)) {
+ switch (level) {
+ case C1_SIMPLE, C1_LIMITED_PROFILE, C1_FULL_PROFILE, C2 -> {
+ if (WHITE_BOX.getMethodCompilationLevel(m, false) == level.getValue()) {
+ return TriState.Yes;
+ }
+ }
+ case ANY -> {
+ return TriState.Yes;
+ }
+ default -> throw new TestRunException("compiledAtLevel() should not be called with " + level);
+ }
+ }
+ if (!USE_COMPILER || XCOMP || TEST_C1 || IGNORE_COMPILER_CONTROLS ||
+ (EXCLUDE_RANDOM && !WHITE_BOX.isMethodCompilable(m, level.getValue(), false))) {
+ return TriState.Maybe;
+ }
+ return TriState.No;
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypeTest.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypeTest.java
deleted file mode 100644
index d4516a4fd34..00000000000
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypeTest.java
+++ /dev/null
@@ -1,860 +0,0 @@
-/*
- * Copyright (c) 2017, 2020, 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.valhalla.inlinetypes;
-
-import compiler.whitebox.CompilerWhiteBoxTest;
-import jdk.test.lib.Asserts;
-import jdk.test.lib.management.InputArguments;
-import jdk.test.lib.Platform;
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.Utils;
-import sun.hotspot.WhiteBox;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Repeatable;
-import java.lang.invoke.*;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Hashtable;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Stream;
-import java.util.TreeMap;
-import java.util.function.BooleanSupplier;
-
-// Mark method as test
-@Retention(RetentionPolicy.RUNTIME)
-@Repeatable(Tests.class)
-@interface Test {
- // Regular expression used to match forbidden IR nodes
- // in the C2 IR emitted for this test.
- String failOn() default "";
- // Regular expressions used to match and count IR nodes.
- String[] match() default { };
- int[] matchCount() default { };
- int compLevel() default InlineTypeTest.COMP_LEVEL_ANY;
- int valid() default 0;
-}
-
-@Retention(RetentionPolicy.RUNTIME)
-@interface Tests {
- Test[] value();
-}
-
-// Force method inlining during compilation
-@Retention(RetentionPolicy.RUNTIME)
-@interface ForceInline { }
-
-// Prevent method inlining during compilation
-@Retention(RetentionPolicy.RUNTIME)
-@interface DontInline { }
-
-// Prevent method compilation
-@Retention(RetentionPolicy.RUNTIME)
-@interface DontCompile { }
-
-// Force method compilation
-@Retention(RetentionPolicy.RUNTIME)
-@interface ForceCompile {
- int compLevel() default InlineTypeTest.COMP_LEVEL_ANY;
-}
-
-// Number of warmup iterations
-@Retention(RetentionPolicy.RUNTIME)
-@interface Warmup {
- int value();
-}
-
-// Do not enqueue the test method for compilation immediately after warmup loops have finished. Instead
-// let the test method be compiled with on-stack-replacement.
-@Retention(RetentionPolicy.RUNTIME)
-@interface OSRCompileOnly {}
-
-// Skip this test temporarily for C1 testing
-@Retention(RetentionPolicy.RUNTIME)
-@interface TempSkipForC1 {
- String reason() default "";
-}
-
-public abstract class InlineTypeTest {
- protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
-
- protected static final int COMP_LEVEL_ANY = -1;
- protected static final int COMP_LEVEL_SIMPLE = 1; // C1
- protected static final int COMP_LEVEL_LIMITED_PROFILE = 2; // C1, invocation & backedge counters
- protected static final int COMP_LEVEL_FULL_PROFILE = 3; // C1, invocation & backedge counters + mdo
- protected static final int COMP_LEVEL_FULL_OPTIMIZATION = 4; // C2 or JVMCI
-
- protected static final boolean TieredCompilation = (Boolean)WHITE_BOX.getVMFlag("TieredCompilation");
- protected static final long TieredStopAtLevel = (Long)WHITE_BOX.getVMFlag("TieredStopAtLevel");
- static final boolean TEST_C1 = TieredCompilation && TieredStopAtLevel < COMP_LEVEL_FULL_OPTIMIZATION;
-
- // Random test values
- public static final int rI = Utils.getRandomInstance().nextInt() % 1000;
- public static final long rL = Utils.getRandomInstance().nextLong() % 1000;
- public static final double rD = Utils.getRandomInstance().nextDouble() % 1000;
-
- // User defined settings
- protected static final boolean XCOMP = Platform.isComp();
- private static final boolean PRINT_GRAPH = true;
- private static final boolean VERBOSE = Boolean.parseBoolean(System.getProperty("Verbose", "false"));
- private static final boolean PRINT_TIMES = Boolean.parseBoolean(System.getProperty("PrintTimes", "false"));
- private static final boolean COMPILE_COMMANDS = Boolean.parseBoolean(System.getProperty("CompileCommands", "true")) && !XCOMP;
- private static boolean VERIFY_IR = Boolean.parseBoolean(System.getProperty("VerifyIR", "true")) && !XCOMP && !TEST_C1 && COMPILE_COMMANDS;
- private static final String SCENARIOS = System.getProperty("Scenarios", "");
- private static final String TESTLIST = System.getProperty("Testlist", "");
- private static final String EXCLUDELIST = System.getProperty("Exclude", "");
- private static final int WARMUP = Integer.parseInt(System.getProperty("Warmup", "251"));
- private static final boolean DUMP_REPLAY = Boolean.parseBoolean(System.getProperty("DumpReplay", "false"));
- private static final boolean FLIP_C1_C2 = Boolean.parseBoolean(System.getProperty("FlipC1C2", "false"));
- private static final boolean GC_AFTER = Boolean.parseBoolean(System.getProperty("GCAfter", "false"));
- private static final int OSR_TEST_TIMEOUT = Integer.parseInt(System.getProperty("OSRTestTimeOut", "5000"));
- protected static final boolean STRESS_CC = Boolean.parseBoolean(System.getProperty("StressCC", "false"));
- private static final boolean SHUFFLE_TESTS = Boolean.parseBoolean(System.getProperty("ShuffleTests", "true"));
- private static final boolean PREFER_CL_FLAGS = Boolean.parseBoolean(System.getProperty("PreferCommandLineFlags", "false"));
-
- // Pre-defined settings
- private static final String[] defaultFlags = {
- "-XX:-BackgroundCompilation"};
- private static final String[] compileCommandFlags = {
- "-XX:CompileCommand=quiet",
- "-XX:CompileCommand=compileonly,java.lang.invoke.*::*",
- "-XX:CompileCommand=compileonly,java.lang.Long::sum",
- "-XX:CompileCommand=compileonly,java.lang.Object::",
- "-XX:CompileCommand=inline,compiler.valhalla.inlinetypes.MyValue*::",
- "-XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.*::*"};
- private static final String[] printFlags = {
- "-XX:+PrintCompilation", "-XX:+PrintIdeal", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintOptoAssembly"};
-
- protected static final int InlineTypePassFieldsAsArgsOn = 0x1;
- protected static final int InlineTypePassFieldsAsArgsOff = 0x2;
- protected static final int InlineTypeArrayFlattenOn = 0x4;
- protected static final int InlineTypeArrayFlattenOff = 0x8;
- protected static final int InlineTypeReturnedAsFieldsOn = 0x10;
- protected static final int InlineTypeReturnedAsFieldsOff = 0x20;
- protected static final int AlwaysIncrementalInlineOn = 0x40;
- protected static final int AlwaysIncrementalInlineOff = 0x80;
- protected static final int G1GCOn = 0x100;
- protected static final int G1GCOff = 0x200;
- protected static final int ZGCOn = 0x400;
- protected static final int ZGCOff = 0x800;
- protected static final int ArrayLoadStoreProfileOn = 0x1000;
- protected static final int ArrayLoadStoreProfileOff = 0x2000;
- protected static final int TypeProfileOn = 0x4000;
- protected static final int TypeProfileOff = 0x8000;
- protected static final int ACmpProfileOn = 0x10000;
- protected static final int ACmpProfileOff = 0x20000;
- protected static final boolean InlineTypePassFieldsAsArgs = (Boolean)WHITE_BOX.getVMFlag("InlineTypePassFieldsAsArgs");
- protected static final boolean InlineTypeArrayFlatten = (WHITE_BOX.getIntxVMFlag("FlatArrayElementMaxSize") == -1);
- protected static final boolean InlineTypeReturnedAsFields = (Boolean)WHITE_BOX.getVMFlag("InlineTypeReturnedAsFields");
- protected static final boolean AlwaysIncrementalInline = (Boolean)WHITE_BOX.getVMFlag("AlwaysIncrementalInline");
- protected static final boolean G1GC = (Boolean)WHITE_BOX.getVMFlag("UseG1GC");
- protected static final boolean ZGC = (Boolean)WHITE_BOX.getVMFlag("UseZGC");
- protected static final boolean VerifyOops = (Boolean)WHITE_BOX.getVMFlag("VerifyOops");
- protected static final boolean UseArrayLoadStoreProfile = (Boolean)WHITE_BOX.getVMFlag("UseArrayLoadStoreProfile");
- protected static final long TypeProfileLevel = (Long)WHITE_BOX.getVMFlag("TypeProfileLevel");
- protected static final boolean UseACmpProfile = (Boolean)WHITE_BOX.getVMFlag("UseACmpProfile");
- protected static final long PerMethodTrapLimit = (Long)WHITE_BOX.getVMFlag("PerMethodTrapLimit");
- protected static final boolean ProfileInterpreter = (Boolean)WHITE_BOX.getVMFlag("ProfileInterpreter");
-
- protected static final Hashtable tests = new Hashtable();
- protected static final boolean USE_COMPILER = WHITE_BOX.getBooleanVMFlag("UseCompiler");
- protected static final boolean PRINT_IDEAL = WHITE_BOX.getBooleanVMFlag("PrintIdeal");
-
- // Regular expressions used to match nodes in the PrintIdeal output
- protected static final String START = "(\\d+ (.*";
- protected static final String MID = ".*)+ ===.*";
- protected static final String END = ")|";
- // Generic allocation
- protected static final String ALLOC_G = "(.*call,static wrapper for: _new_instance_Java" + END;
- protected static final String ALLOCA_G = "(.*call,static wrapper for: _new_array_Java" + END;
- // Inline type allocation
- protected static final String ALLOC = "(.*precise klass compiler/valhalla/inlinetypes/MyValue.*\\R(.*(movl|xorl|nop|spill).*\\R)*.*_new_instance_Java" + END;
- protected static final String ALLOCA = "(.*precise klass \\[(L|Q)compiler/valhalla/inlinetypes/MyValue.*\\R(.*(movl|xorl|nop|spill).*\\R)*.*_new_array_Java" + END;
- protected static final String LOAD = START + "Load(B|S|I|L|F|D|P|N)" + MID + "@compiler/valhalla/inlinetypes/MyValue.*" + END;
- protected static final String LOADK = START + "LoadK" + MID + END;
- protected static final String STORE = START + "Store(B|C|S|I|L|F|D|P|N)" + MID + "@compiler/valhalla/inlinetypes/MyValue.*" + END;
- protected static final String LOOP = START + "Loop" + MID + "" + END;
- protected static final String COUNTEDLOOP = START + "CountedLoop\\b" + MID + "" + END;
- protected static final String COUNTEDLOOP_MAIN = START + "CountedLoop\\b" + MID + "main" + END;
- protected static final String TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*(unstable_if|predicate)" + END;
- protected static final String LINKTOSTATIC = START + "CallStaticJava" + MID + "linkToStatic" + END;
- protected static final String NPE = START + "CallStaticJava" + MID + "null_check" + END;
- protected static final String CALL = START + "CallStaticJava" + MID + END;
- protected static final String STORE_INLINE_FIELDS = START + "CallStaticJava" + MID + "store_inline_type_fields" + END;
- protected static final String SCOBJ = "(.*# ScObj.*" + END;
- protected static final String LOAD_UNKNOWN_INLINE = "(.*call_leaf,runtime load_unknown_inline.*" + END;
- protected static final String STORE_UNKNOWN_INLINE = "(.*call_leaf,runtime store_unknown_inline.*" + END;
- protected static final String INLINE_ARRAY_NULL_GUARD = "(.*call,static wrapper for: uncommon_trap.*reason='null_check' action='none'.*" + END;
- protected static final String INTRINSIC_SLOW_PATH = "(.*call,static wrapper for: uncommon_trap.*reason='intrinsic_or_type_checked_inlining'.*" + END;
- protected static final String CLONE_INTRINSIC_SLOW_PATH = "(.*call,static.*java.lang.Object::clone.*" + END;
- protected static final String CLASS_CHECK_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*class_check" + END;
- protected static final String NULL_CHECK_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*null_check" + END;
- protected static final String NULL_ASSERT_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*null_assert" + END;
- protected static final String RANGE_CHECK_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*range_check" + END;
- protected static final String UNHANDLED_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*unhandled" + END;
- protected static final String PREDICATE_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*predicate" + END;
- protected static final String MEMBAR = START + "MemBar" + MID + END;
- protected static final String CHECKCAST_ARRAY = "(cmp.*precise klass \\[(L|Q)compiler/valhalla/inlinetypes/MyValue.*" + END;
- protected static final String CHECKCAST_ARRAYCOPY = "(.*call_leaf_nofp,runtime checkcast_arraycopy.*" + END;
- protected static final String JLONG_ARRAYCOPY = "(.*call_leaf_nofp,runtime jlong_disjoint_arraycopy.*" + END;
- protected static final String FIELD_ACCESS = "(.*Field: *" + END;
- protected static final String SUBSTITUTABILITY_TEST = START + "CallStaticJava" + MID + "java.lang.invoke.ValueBootstrapMethods::isSubstitutable" + END;
-
- public static String[] concat(String prefix[], String... extra) {
- ArrayList list = new ArrayList();
- if (prefix != null) {
- for (String s : prefix) {
- list.add(s);
- }
- }
- if (extra != null) {
- for (String s : extra) {
- list.add(s);
- }
- }
-
- return list.toArray(new String[list.size()]);
- }
-
- /**
- * Override getNumScenarios and getVMParameters if you want to run with more than
- * the 6 built-in scenarios
- */
- public int getNumScenarios() {
- return 6;
- }
-
- /**
- * VM parameters for the 5 built-in test scenarios. If your test needs to append
- * extra parameters for (some of) these scenarios, override getExtraVMParameters().
- */
- public String[] getVMParameters(int scenario) {
- switch (scenario) {
- case 0: return new String[] {
- "-XX:-UseACmpProfile",
- "-XX:+AlwaysIncrementalInline",
- "-XX:FlatArrayElementMaxOops=5",
- "-XX:FlatArrayElementMaxSize=-1",
- "-XX:-UseArrayLoadStoreProfile",
- "-XX:InlineFieldMaxFlatSize=-1",
- "-XX:+InlineTypePassFieldsAsArgs",
- "-XX:+InlineTypeReturnedAsFields"};
- case 1: return new String[] {
- "-XX:-UseACmpProfile",
- "-XX:-UseCompressedOops",
- "-XX:FlatArrayElementMaxOops=5",
- "-XX:FlatArrayElementMaxSize=-1",
- "-XX:-UseArrayLoadStoreProfile",
- "-XX:InlineFieldMaxFlatSize=-1",
- "-XX:-InlineTypePassFieldsAsArgs",
- "-XX:-InlineTypeReturnedAsFields"};
- case 2: return new String[] {
- "-XX:-UseACmpProfile",
- "-XX:-UseCompressedOops",
- "-XX:FlatArrayElementMaxOops=0",
- "-XX:FlatArrayElementMaxSize=0",
- "-XX:-UseArrayLoadStoreProfile",
- "-XX:InlineFieldMaxFlatSize=-1",
- "-XX:+InlineTypePassFieldsAsArgs",
- "-XX:+InlineTypeReturnedAsFields",
- "-XX:+StressInlineTypeReturnedAsFields"};
- case 3: return new String[] {
- "-DVerifyIR=false",
- "-XX:+AlwaysIncrementalInline",
- "-XX:FlatArrayElementMaxOops=0",
- "-XX:FlatArrayElementMaxSize=0",
- "-XX:InlineFieldMaxFlatSize=0",
- "-XX:+InlineTypePassFieldsAsArgs",
- "-XX:+InlineTypeReturnedAsFields"};
- case 4: return new String[] {
- "-DVerifyIR=false",
- "-XX:FlatArrayElementMaxOops=-1",
- "-XX:FlatArrayElementMaxSize=-1",
- "-XX:InlineFieldMaxFlatSize=0",
- "-XX:+InlineTypePassFieldsAsArgs",
- "-XX:-InlineTypeReturnedAsFields",
- "-XX:-ReduceInitialCardMarks"};
- case 5: return new String[] {
- "-XX:-UseACmpProfile",
- "-XX:+AlwaysIncrementalInline",
- "-XX:FlatArrayElementMaxOops=5",
- "-XX:FlatArrayElementMaxSize=-1",
- "-XX:-UseArrayLoadStoreProfile",
- "-XX:InlineFieldMaxFlatSize=-1",
- "-XX:-InlineTypePassFieldsAsArgs",
- "-XX:-InlineTypeReturnedAsFields"};
- }
- return null;
- }
-
- /**
- * Override this method and return a non-null reason if the given scenario should be
- * ignored (due to an existing bug, etc).
- */
- String isScenarioIgnored(int scenario) {
- return null;
- }
-
- /**
- * Override this method to provide extra parameters for selected scenarios
- */
- public String[] getExtraVMParameters(int scenario) {
- return null;
- }
-
- public static void main(String[] args) throws Throwable {
- if (args.length != 1) {
- throw new RuntimeException("Usage: @run main/othervm/timeout=120 -Xbootclasspath/a:." +
- " -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions" +
- " -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI" +
- " compiler.valhalla.inlinetypes.InlineTypeTest ");
- }
- String testMainClassName = args[0];
- Class testMainClass = Class.forName(testMainClassName);
- InlineTypeTest test = (InlineTypeTest)testMainClass.newInstance();
- List scenarios = null;
- if (!SCENARIOS.isEmpty()) {
- scenarios = Arrays.asList(SCENARIOS.split(","));
- }
- for (int i=0; i,,...
- // Each case can be just the method name, or can be .. The latter form is useful
- // when you are running several tests at the same time.
- //
- // jtreg -DExclude=test12 TestArrays.java
- // jtreg -DExclude=test34 TestLWorld.java
- // -- or --
- // jtreg -DExclude=TestArrays.test12,TestLWorld.test34 TestArrays.java TestLWorld.java
- //
- private List buildExcludeList() {
- List exclude = null;
- String classPrefix = getClass().getSimpleName() + ".";
- if (!EXCLUDELIST.isEmpty()) {
- exclude = new ArrayList(Arrays.asList(EXCLUDELIST.split(",")));
- for (int i = exclude.size() - 1; i >= 0; i--) {
- String ex = exclude.get(i);
- if (ex.indexOf(".") > 0) {
- if (ex.startsWith(classPrefix)) {
- ex = ex.substring(classPrefix.length());
- exclude.set(i, ex);
- } else {
- exclude.remove(i);
- }
- }
- }
- }
- return exclude;
- }
-
- protected InlineTypeTest() {
- List list = null;
- if (!TESTLIST.isEmpty()) {
- list = Arrays.asList(TESTLIST.split(","));
- }
- List exclude = buildExcludeList();
-
- // Gather all test methods and put them in Hashtable
- for (Method m : getClass().getDeclaredMethods()) {
- Test[] annos = m.getAnnotationsByType(Test.class);
- if (annos.length != 0 &&
- ((list == null || list.contains(m.getName())) && (exclude == null || !exclude.contains(m.getName())))) {
- tests.put(getClass().getSimpleName() + "::" + m.getName(), m);
- } else if (annos.length == 0 && m.getName().startsWith("test")) {
- try {
- getClass().getMethod(m.getName() + "_verifier", boolean.class);
- throw new RuntimeException(m.getName() + " has a verifier method but no @Test annotation");
- } catch (NoSuchMethodException e) {
- // Expected
- }
- }
- }
- }
-
- protected void run(String[] args, Class>... classes) throws Throwable {
- if (args.length == 0) {
- // Spawn a new VM instance
- execute_vm();
- } else {
- // Execute tests in the VM spawned by the above code.
- Asserts.assertTrue(args.length == 1 && args[0].equals("run"), "must be");
- run(classes);
- }
- }
-
- private void execute_vm() throws Throwable {
- Asserts.assertFalse(tests.isEmpty(), "no tests to execute");
- String[] vmInputArgs = InputArguments.getVmInputArgs();
- for (String arg : vmInputArgs) {
- if (arg.startsWith("-XX:CompileThreshold")) {
- // Disable IR verification if non-default CompileThreshold is set
- VERIFY_IR = false;
- }
- }
- // Each VM is launched with flags in this order, so the later ones can override the earlier one:
- // VERIFY_IR flags specified below
- // vmInputArgs, which consists of:
- // @run options
- // getVMParameters()
- // getExtraVMParameters()
- // defaultFlags
- // compileCommandFlags
- String cmds[] = null;
- if (VERIFY_IR) {
- // Add print flags for IR verification
- cmds = concat(cmds, printFlags);
- // Always trap for exception throwing to not confuse IR verification
- cmds = concat(cmds, "-XX:-OmitStackTraceInFastThrow");
- }
- cmds = concat(cmds, vmInputArgs);
- cmds = concat(cmds, defaultFlags);
- if (COMPILE_COMMANDS) {
- cmds = concat(cmds, compileCommandFlags);
- }
-
- // Run tests in own process and verify output
- cmds = concat(cmds, getClass().getName(), "run");
- OutputAnalyzer oa = ProcessTools.executeTestJvm(cmds);
- // If ideal graph printing is enabled/supported, verify output
- String output = oa.getOutput();
- oa.shouldHaveExitValue(0);
- if (VERIFY_IR) {
- if (output.contains("PrintIdeal enabled")) {
- parseOutput(output);
- } else {
- System.out.println(output);
- System.out.println("WARNING: IR verification failed! Running with -Xint, -Xcomp or release build?");
- }
- }
- }
-
- static final class TestAnnotation {
- private final int flag;
- private final BooleanSupplier predicate;
-
- private static final TestAnnotation testAnnotations[] = {
- new TestAnnotation(InlineTypePassFieldsAsArgsOn, () -> InlineTypePassFieldsAsArgs),
- new TestAnnotation(InlineTypePassFieldsAsArgsOff, () -> !InlineTypePassFieldsAsArgs),
- new TestAnnotation(InlineTypeArrayFlattenOn, () -> InlineTypeArrayFlatten),
- new TestAnnotation(InlineTypeArrayFlattenOff, () -> !InlineTypeArrayFlatten),
- new TestAnnotation(InlineTypeReturnedAsFieldsOn, () -> InlineTypeReturnedAsFields),
- new TestAnnotation(InlineTypeReturnedAsFieldsOff, () -> !InlineTypeReturnedAsFields),
- new TestAnnotation(AlwaysIncrementalInlineOn, () -> AlwaysIncrementalInline),
- new TestAnnotation(AlwaysIncrementalInlineOff, () -> !AlwaysIncrementalInline),
- new TestAnnotation(G1GCOn, () -> G1GC),
- new TestAnnotation(G1GCOff, () -> !G1GC),
- new TestAnnotation(ZGCOn, () -> ZGC),
- new TestAnnotation(ZGCOff, () -> !ZGC),
- new TestAnnotation(ArrayLoadStoreProfileOn, () -> UseArrayLoadStoreProfile),
- new TestAnnotation(ArrayLoadStoreProfileOff, () -> !UseArrayLoadStoreProfile),
- new TestAnnotation(TypeProfileOn, () -> TypeProfileLevel == 222),
- new TestAnnotation(TypeProfileOff, () -> TypeProfileLevel == 0),
- new TestAnnotation(ACmpProfileOn, () -> UseACmpProfile),
- new TestAnnotation(ACmpProfileOff, () -> !UseACmpProfile),
- };
-
- private TestAnnotation(int flag, BooleanSupplier predicate) {
- this.flag = flag;
- this.predicate = predicate;
- }
-
- private boolean match(Test a) {
- return (a.valid() & flag) != 0 && predicate.getAsBoolean();
- }
-
- static boolean find(Test a) {
- Stream s = Arrays.stream(testAnnotations).filter(t -> t.match(a));
- long c = s.count();
- if (c > 1) {
- throw new RuntimeException("At most one Test annotation should match");
- }
- return c > 0;
- }
- }
-
- private void parseOutput(String output) throws Exception {
- Pattern comp_re = Pattern.compile("\\n\\s+\\d+\\s+\\d+\\s+(%| )(s| )(!| )b(n| )\\s+\\d?\\s+\\S+\\.(?[^.]+::\\S+)\\s+(?@ \\d+\\s+)?[(]\\d+ bytes[)]");
- Matcher m = comp_re.matcher(output);
- Map compilations = new LinkedHashMap<>();
- int prev = 0;
- String methodName = null;
- while (m.find()) {
- if (prev == 0) {
- // Print header
- System.out.print(output.substring(0, m.start()+1));
- } else if (methodName != null) {
- compilations.put(methodName, output.substring(prev, m.start()+1));
- }
- if (m.group("osr") != null) {
- methodName = null;
- } else {
- methodName = m.group("name");
- }
- prev = m.end();
- }
- if (prev == 0) {
- // Print header
- System.out.print(output);
- } else if (methodName != null) {
- compilations.put(methodName, output.substring(prev));
- }
- // Iterate over compilation output
- for (String testName : compilations.keySet()) {
- Method test = tests.get(testName);
- if (test == null) {
- // Skip helper methods
- continue;
- }
- String graph = compilations.get(testName);
- System.out.println("\nGraph for " + testName + "\n" + graph);
- // Parse graph using regular expressions to determine if it contains forbidden nodes
- Test[] annos = test.getAnnotationsByType(Test.class);
- Test anno = Arrays.stream(annos).filter(TestAnnotation::find).findFirst().orElse(null);
- if (anno == null) {
- Object[] res = Arrays.stream(annos).filter(a -> a.valid() == 0).toArray();
- if (res.length != 1) {
- throw new RuntimeException("Only one Test annotation should match");
- }
- anno = (Test)res[0];
- }
- String regexFail = anno.failOn();
- if (!regexFail.isEmpty()) {
- Pattern pattern = Pattern.compile(regexFail.substring(0, regexFail.length()-1));
- Matcher matcher = pattern.matcher(graph);
- boolean found = matcher.find();
- Asserts.assertFalse(found, "Graph for '" + testName + "' contains forbidden node:\n" + (found ? matcher.group() : ""));
- }
- String[] regexMatch = anno.match();
- int[] matchCount = anno.matchCount();
- for (int i = 0; i < regexMatch.length; ++i) {
- Pattern pattern = Pattern.compile(regexMatch[i].substring(0, regexMatch[i].length()-1));
- Matcher matcher = pattern.matcher(graph);
- int count = 0;
- String nodes = "";
- while (matcher.find()) {
- count++;
- nodes += matcher.group() + "\n";
- }
- if (matchCount[i] < 0) {
- Asserts.assertLTE(Math.abs(matchCount[i]), count, "Graph for '" + testName + "' contains different number of match nodes (expected >= " + Math.abs(matchCount[i]) + " but got " + count + "):\n" + nodes);
- } else {
- Asserts.assertEQ(matchCount[i], count, "Graph for '" + testName + "' contains different number of match nodes (expected " + matchCount[i] + " but got " + count + "):\n" + nodes);
- }
- }
- tests.remove(testName);
- System.out.println(testName + " passed");
- }
- // Check if all tests were compiled
- if (tests.size() != 0) {
- for (String name : tests.keySet()) {
- System.out.println("Test '" + name + "' not compiled!");
- }
- throw new RuntimeException("Not all tests were compiled");
- }
- }
-
- private void setup(Class> clazz) {
- if (XCOMP) {
- // Don't control compilation if -Xcomp is enabled
- return;
- }
- if (DUMP_REPLAY) {
- // Generate replay compilation files
- String directive = "[{ match: \"*.*\", DumpReplay: true }]";
- if (WHITE_BOX.addCompilerDirective(directive) != 1) {
- throw new RuntimeException("Failed to add compiler directive");
- }
- }
-
- Method[] methods = clazz.getDeclaredMethods();
- for (Method m : methods) {
- if (m.isAnnotationPresent(Test.class)) {
- // Don't inline tests
- WHITE_BOX.testSetDontInlineMethod(m, true);
- }
- if (m.isAnnotationPresent(DontCompile.class)) {
- WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_ANY, true);
- WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_ANY, false);
- WHITE_BOX.testSetDontInlineMethod(m, true);
- }
- if (m.isAnnotationPresent(ForceInline.class)) {
- Asserts.assertFalse(m.isAnnotationPresent(DontInline.class), "Method " + m.getName() + " has contradicting DontInline annotation");
- WHITE_BOX.testSetForceInlineMethod(m, true);
- }
- if (m.isAnnotationPresent(DontInline.class)) {
- Asserts.assertFalse(m.isAnnotationPresent(ForceInline.class), "Method " + m.getName() + " has contradicting ForceInline annotation");
- WHITE_BOX.testSetDontInlineMethod(m, true);
- }
- if (STRESS_CC) {
- // Exclude some methods from compilation with C2 to stress test the calling convention
- if (Utils.getRandomInstance().nextBoolean()) {
- System.out.println("Excluding from C2 compilation: " + m);
- WHITE_BOX.makeMethodNotCompilable(m, COMP_LEVEL_FULL_OPTIMIZATION, false);
- }
- }
- }
- // Only force compilation now because above annotations affect inlining
- for (Method m : methods) {
- if (m.isAnnotationPresent(ForceCompile.class)) {
- Asserts.assertFalse(m.isAnnotationPresent(DontCompile.class), "Method " + m.getName() + " has contradicting DontCompile annotation");
- int compLevel = getCompLevel(m.getAnnotation(ForceCompile.class));
- enqueueMethodForCompilation(m, compLevel);
- }
- }
- // Compile class initializers
- int compLevel = getCompLevel(null);
- WHITE_BOX.enqueueInitializerForCompilation(clazz, compLevel);
- }
-
- private void run(Class>... classes) throws Exception {
- if (USE_COMPILER && PRINT_IDEAL && !XCOMP && !STRESS_CC) {
- System.out.println("PrintIdeal enabled");
- }
- System.out.format("rI = %d, rL = %d\n", rI, rL);
-
- setup(getClass());
- for (Class> clazz : classes) {
- setup(clazz);
- }
-
- TreeMap durations = (PRINT_TIMES || VERBOSE) ? new TreeMap() : null;
- List testList = new ArrayList(tests.values());
- if (SHUFFLE_TESTS) {
- // Execute tests in random order (execution sequence affects profiling)
- Collections.shuffle(testList, Utils.getRandomInstance());
- }
- for (Method test : testList) {
- if (VERBOSE) {
- System.out.println("Starting " + test.getName());
- }
- TempSkipForC1 c1skip = test.getAnnotation(TempSkipForC1.class);
- if (TEST_C1 && c1skip != null) {
- System.out.println("Skipped " + test.getName() + " for C1 testing: " + c1skip.reason());
- continue;
- }
- long startTime = System.nanoTime();
- Method verifier = getClass().getMethod(test.getName() + "_verifier", boolean.class);
- // Warmup using verifier method
- Warmup anno = test.getAnnotation(Warmup.class);
- int warmup = anno == null ? WARMUP : anno.value();
- for (int i = 0; i < warmup; ++i) {
- verifier.invoke(this, true);
- }
- boolean osrOnly = (test.getAnnotation(OSRCompileOnly.class) != null);
- int compLevel = getCompLevel(test.getAnnotation(Test.class));
-
- // C1 generates a lot of code when VerifyOops is enabled and may run out of space (for a small
- // number of test cases).
- boolean maybeCodeBufferOverflow = (TEST_C1 && VerifyOops);
-
- if (osrOnly) {
- long started = System.currentTimeMillis();
- boolean stateCleared = false;
- for (;;) {
- long elapsed = System.currentTimeMillis() - started;
- int level = WHITE_BOX.getMethodCompilationLevel(test);
- if (maybeCodeBufferOverflow && elapsed > 5000 && (!WHITE_BOX.isMethodCompiled(test, false) || level != compLevel)) {
- System.out.println("Temporarily disabling VerifyOops");
- try {
- WHITE_BOX.setBooleanVMFlag("VerifyOops", false);
- if (!stateCleared) {
- WHITE_BOX.clearMethodState(test);
- stateCleared = true;
- }
- verifier.invoke(this, false);
- } finally {
- WHITE_BOX.setBooleanVMFlag("VerifyOops", true);
- System.out.println("Re-enabled VerifyOops");
- }
- } else {
- verifier.invoke(this, false);
- }
-
- boolean b = WHITE_BOX.isMethodCompiled(test, false);
- if (VERBOSE) {
- System.out.println("Is " + test.getName() + " compiled? " + b);
- }
- if (b || XCOMP || STRESS_CC || !USE_COMPILER) {
- // Don't control compilation if -Xcomp is enabled, or if compiler is disabled
- break;
- }
- Asserts.assertTrue(OSR_TEST_TIMEOUT < 0 || elapsed < OSR_TEST_TIMEOUT, test + " not compiled after " + OSR_TEST_TIMEOUT + " ms");
- }
- } else {
- // Trigger compilation
- enqueueMethodForCompilation(test, compLevel);
- if (maybeCodeBufferOverflow && !WHITE_BOX.isMethodCompiled(test, false)) {
- // Let's disable VerifyOops temporarily and retry.
- WHITE_BOX.setBooleanVMFlag("VerifyOops", false);
- WHITE_BOX.clearMethodState(test);
- enqueueMethodForCompilation(test, compLevel);
- WHITE_BOX.setBooleanVMFlag("VerifyOops", true);
- }
- if (!STRESS_CC && USE_COMPILER) {
- Asserts.assertTrue(WHITE_BOX.isMethodCompiled(test, false), test + " not compiled");
- int level = WHITE_BOX.getMethodCompilationLevel(test);
- Asserts.assertEQ(level, compLevel, "Unexpected compilation level for " + test);
- }
- // Check result
- verifier.invoke(this, false);
- }
- if (PRINT_TIMES || VERBOSE) {
- long endTime = System.nanoTime();
- long duration = (endTime - startTime);
- durations.put(duration, test.getName());
- if (VERBOSE) {
- System.out.println("Done " + test.getName() + ": " + duration + " ns = " + (duration / 1000000) + " ms");
- }
- }
- if (GC_AFTER) {
- System.out.println("doing GC");
- System.gc();
- }
- }
-
- // Print execution times
- if (PRINT_TIMES) {
- System.out.println("\n\nTest execution times:");
- for (Map.Entry entry : durations.entrySet()) {
- System.out.format("%-10s%15d ns\n", entry.getValue() + ":", entry.getKey());
- }
- }
- }
-
- // Get the appropriate compilation level for a method, according to the
- // given annotation, as well as the current test scenario and VM options.
- //
- private int getCompLevel(Object annotation) {
- int compLevel;
- if (annotation == null) {
- compLevel = COMP_LEVEL_ANY;
- } else if (annotation instanceof Test) {
- compLevel = ((Test)annotation).compLevel();
- } else {
- compLevel = ((ForceCompile)annotation).compLevel();
- }
-
- return restrictCompLevel(compLevel);
- }
-
- // Get the appropriate level as permitted by the test scenario and VM options.
- private static int restrictCompLevel(int compLevel) {
- if (compLevel == COMP_LEVEL_ANY) {
- compLevel = COMP_LEVEL_FULL_OPTIMIZATION;
- }
- if (FLIP_C1_C2) {
- // Effectively treat all (compLevel = C1) as (compLevel = C2), and
- // (compLevel = C2) as (compLevel = C1).
- if (compLevel == COMP_LEVEL_SIMPLE) {
- compLevel = COMP_LEVEL_FULL_OPTIMIZATION;
- } else if (compLevel == COMP_LEVEL_FULL_OPTIMIZATION) {
- compLevel = COMP_LEVEL_SIMPLE;
- }
- }
- if (!TEST_C1 && compLevel < COMP_LEVEL_FULL_OPTIMIZATION) {
- compLevel = COMP_LEVEL_FULL_OPTIMIZATION;
- }
- if (TieredCompilation && compLevel > (int)TieredStopAtLevel) {
- compLevel = (int)TieredStopAtLevel;
- }
- return compLevel;
- }
-
- public static void enqueueMethodForCompilation(Method m, int level) {
- level = restrictCompLevel(level);
- if (VERBOSE) {
- System.out.println("enqueueMethodForCompilation " + m + ", level = " + level);
- }
- WHITE_BOX.enqueueMethodForCompilation(m, level);
- }
-
- enum TriState {
- Maybe,
- Yes,
- No
- }
-
- static private TriState compiledByC2(Method m) {
- if (!USE_COMPILER || XCOMP || TEST_C1 ||
- (STRESS_CC && !WHITE_BOX.isMethodCompilable(m, COMP_LEVEL_FULL_OPTIMIZATION, false))) {
- return TriState.Maybe;
- }
- if (WHITE_BOX.isMethodCompiled(m, false) &&
- WHITE_BOX.getMethodCompilationLevel(m, false) >= COMP_LEVEL_FULL_OPTIMIZATION) {
- return TriState.Yes;
- }
- return TriState.No;
- }
-
- static boolean isCompiledByC2(Method m) {
- return compiledByC2(m) == TriState.Yes;
- }
-
- static void assertDeoptimizedByC2(Method m) {
- if (compiledByC2(m) == TriState.Yes && PerMethodTrapLimit != 0 && ProfileInterpreter) {
- throw new RuntimeException("Expected to have deoptimized");
- }
- }
-
- static void assertCompiledByC2(Method m) {
- if (compiledByC2(m) == TriState.No) {
- throw new RuntimeException("Expected to be compiled");
- }
- }
-}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java
new file mode 100644
index 00000000000..c2b0934e418
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2021, 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.valhalla.inlinetypes;
+
+import jdk.test.lib.Utils;
+import compiler.lib.ir_framework.Scenario;
+import compiler.lib.ir_framework.TestFramework;
+
+public class InlineTypes {
+ public static final int rI = Utils.getRandomInstance().nextInt() % 1000;
+ public static final long rL = Utils.getRandomInstance().nextLong() % 1000;
+ public static final double rD = Utils.getRandomInstance().nextDouble() % 1000;
+
+ public static final Scenario[] DEFAULT_SCENARIOS = {
+ new Scenario(0,
+ "-XX:+IgnoreUnrecognizedVMOptions",
+ "-XX:-UseACmpProfile",
+ "-XX:+AlwaysIncrementalInline",
+ "-XX:FlatArrayElementMaxOops=5",
+ "-XX:FlatArrayElementMaxSize=-1",
+ "-XX:-UseArrayLoadStoreProfile",
+ "-XX:InlineFieldMaxFlatSize=-1",
+ "-XX:+InlineTypePassFieldsAsArgs",
+ "-XX:+InlineTypeReturnedAsFields"
+ ),
+ new Scenario(1,
+ "-XX:+IgnoreUnrecognizedVMOptions",
+ "-XX:-UseACmpProfile",
+ "-XX:-UseCompressedOops",
+ "-XX:FlatArrayElementMaxOops=5",
+ "-XX:FlatArrayElementMaxSize=-1",
+ "-XX:-UseArrayLoadStoreProfile",
+ "-XX:InlineFieldMaxFlatSize=-1",
+ "-XX:-InlineTypePassFieldsAsArgs",
+ "-XX:-InlineTypeReturnedAsFields"
+ ),
+ new Scenario(2,
+ "-XX:+IgnoreUnrecognizedVMOptions",
+ "-XX:-UseACmpProfile",
+ "-XX:-UseCompressedOops",
+ "-XX:FlatArrayElementMaxOops=0",
+ "-XX:FlatArrayElementMaxSize=0",
+ "-XX:-UseArrayLoadStoreProfile",
+ "-XX:InlineFieldMaxFlatSize=-1",
+ "-XX:+InlineTypePassFieldsAsArgs",
+ "-XX:+InlineTypeReturnedAsFields",
+ "-XX:+StressInlineTypeReturnedAsFields"
+ ),
+ new Scenario(3,
+ "-XX:+IgnoreUnrecognizedVMOptions",
+ "-DVerifyIR=false",
+ "-XX:+AlwaysIncrementalInline",
+ "-XX:FlatArrayElementMaxOops=0",
+ "-XX:FlatArrayElementMaxSize=0",
+ "-XX:InlineFieldMaxFlatSize=0",
+ "-XX:+InlineTypePassFieldsAsArgs",
+ "-XX:+InlineTypeReturnedAsFields"
+ ),
+ new Scenario(4,
+ "-XX:+IgnoreUnrecognizedVMOptions",
+ "-DVerifyIR=false",
+ "-XX:FlatArrayElementMaxOops=-1",
+ "-XX:FlatArrayElementMaxSize=-1",
+ "-XX:InlineFieldMaxFlatSize=0",
+ "-XX:+InlineTypePassFieldsAsArgs",
+ "-XX:-InlineTypeReturnedAsFields",
+ "-XX:-ReduceInitialCardMarks"
+ ),
+ new Scenario(5,
+ "-XX:+IgnoreUnrecognizedVMOptions",
+ "-XX:-UseACmpProfile",
+ "-XX:+AlwaysIncrementalInline",
+ "-XX:FlatArrayElementMaxOops=5",
+ "-XX:FlatArrayElementMaxSize=-1",
+ "-XX:-UseArrayLoadStoreProfile",
+ "-XX:InlineFieldMaxFlatSize=-1",
+ "-XX:-InlineTypePassFieldsAsArgs",
+ "-XX:-InlineTypeReturnedAsFields"
+ )
+ };
+
+ public static TestFramework getFramework() {
+ StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
+ return new TestFramework(walker.getCallerClass()).setDefaultWarmup(251);
+ }
+
+ static class IRNode {
+ // Regular expressions used to match nodes in the PrintIdeal output
+ protected static final String START = "(\\d+ (.*";
+ protected static final String MID = ".*)+ ===.*";
+ protected static final String END = ")";
+ // Generic allocation
+ protected static final String ALLOC_G = "(.*call,static wrapper for: _new_instance_Java" + END;
+ protected static final String ALLOCA_G = "(.*call,static wrapper for: _new_array_Java" + END;
+ // Inline type allocation
+ protected static final String ALLOC = "(.*precise klass compiler/valhalla/inlinetypes/MyValue.*\\R(.*(movl|xorl|nop|spill).*\\R)*.*_new_instance_Java" + END;
+ protected static final String ALLOCA = "(.*precise klass \\[(L|Q)compiler/valhalla/inlinetypes/MyValue.*\\R(.*(movl|xorl|nop|spill).*\\R)*.*_new_array_Java" + END;
+ protected static final String LOAD = START + "Load(B|S|I|L|F|D|P|N)" + MID + "@compiler/valhalla/inlinetypes/MyValue.*" + END;
+ protected static final String LOADK = START + "LoadK" + MID + END;
+ protected static final String STORE = START + "Store(B|C|S|I|L|F|D|P|N)" + MID + "@compiler/valhalla/inlinetypes/MyValue.*" + END;
+ protected static final String LOOP = START + "Loop" + MID + "" + END;
+ protected static final String COUNTEDLOOP = START + "CountedLoop\\b" + MID + "" + END;
+ protected static final String COUNTEDLOOP_MAIN = START + "CountedLoop\\b" + MID + "main" + END;
+ protected static final String TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*(unstable_if|predicate)" + END;
+ protected static final String LINKTOSTATIC = START + "CallStaticJava" + MID + "linkToStatic" + END;
+ protected static final String NPE = START + "CallStaticJava" + MID + "null_check" + END;
+ protected static final String CALL = START + "CallStaticJava" + MID + END;
+ protected static final String STORE_INLINE_FIELDS = START + "CallStaticJava" + MID + "store_inline_type_fields" + END;
+ protected static final String SCOBJ = "(.*# ScObj.*" + END;
+ protected static final String LOAD_UNKNOWN_INLINE = "(.*call_leaf,runtime load_unknown_inline.*" + END;
+ protected static final String STORE_UNKNOWN_INLINE = "(.*call_leaf,runtime store_unknown_inline.*" + END;
+ protected static final String INLINE_ARRAY_NULL_GUARD = "(.*call,static wrapper for: uncommon_trap.*reason='null_check' action='none'.*" + END;
+ protected static final String INTRINSIC_SLOW_PATH = "(.*call,static wrapper for: uncommon_trap.*reason='intrinsic_or_type_checked_inlining'.*" + END;
+ protected static final String CLONE_INTRINSIC_SLOW_PATH = "(.*call,static.*java.lang.Object::clone.*" + END;
+ protected static final String CLASS_CHECK_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*class_check" + END;
+ protected static final String NULL_CHECK_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*null_check" + END;
+ protected static final String NULL_ASSERT_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*null_assert" + END;
+ protected static final String RANGE_CHECK_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*range_check" + END;
+ protected static final String UNHANDLED_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*unhandled" + END;
+ protected static final String PREDICATE_TRAP = START + "CallStaticJava" + MID + "uncommon_trap.*predicate" + END;
+ protected static final String MEMBAR = START + "MemBar" + MID + END;
+ protected static final String CHECKCAST_ARRAY = "(cmp.*precise klass \\[(L|Q)compiler/valhalla/inlinetypes/MyValue.*" + END;
+ protected static final String CHECKCAST_ARRAYCOPY = "(.*call_leaf_nofp,runtime checkcast_arraycopy.*" + END;
+ protected static final String JLONG_ARRAYCOPY = "(.*call_leaf_nofp,runtime jlong_disjoint_arraycopy.*" + END;
+ protected static final String FIELD_ACCESS = "(.*Field: *" + END;
+ protected static final String SUBSTITUTABILITY_TEST = START + "CallStaticJava" + MID + "java.lang.invoke.ValueBootstrapMethods::isSubstitutable" + END;
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue1.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue1.java
index 016ebf4dc41..4634e9e8b89 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue1.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue1.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2021, 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,9 +23,15 @@
package compiler.valhalla.inlinetypes;
+import compiler.lib.ir_framework.DontCompile;
+import compiler.lib.ir_framework.DontInline;
+import compiler.lib.ir_framework.ForceCompileClassInitializer;
+import compiler.lib.ir_framework.ForceInline;
+
+@ForceCompileClassInitializer
public final primitive class MyValue1 extends MyAbstract {
static int s;
- static final long sf = InlineTypeTest.rL;
+ static final long sf = InlineTypes.rL;
final int x;
final long y;
final short z;
@@ -33,7 +39,7 @@ public final primitive class MyValue1 extends MyAbstract {
final int[] oa;
final MyValue2 v1;
final MyValue2 v2;
- static final MyValue2 v3 = MyValue2.createWithFieldsInline(InlineTypeTest.rI, InlineTypeTest.rD);
+ static final MyValue2 v3 = MyValue2.createWithFieldsInline(InlineTypes.rI, InlineTypes.rD);
final int c;
@ForceInline
@@ -74,8 +80,8 @@ static MyValue1 createWithFieldsInline(int x, long y) {
v = setO(v, new Integer(x));
int[] oa = {x};
v = setOA(v, oa);
- v = setV1(v, MyValue2.createWithFieldsInline(x, y, InlineTypeTest.rD));
- v = setV2(v, MyValue2.createWithFieldsInline(x, y, InlineTypeTest.rD+x));
+ v = setV1(v, MyValue2.createWithFieldsInline(x, y, InlineTypes.rD));
+ v = setV2(v, MyValue2.createWithFieldsInline(x, y, InlineTypes.rD + x));
v = setC(v, (int)(x+y));
return v;
}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue2.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue2.java
index 859708d8575..7496c20e0c5 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue2.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2021, 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,6 +23,9 @@
package compiler.valhalla.inlinetypes;
+import compiler.lib.ir_framework.DontInline;
+import compiler.lib.ir_framework.ForceInline;
+
final primitive class MyValue2Inline {
final double d;
final long l;
@@ -88,7 +91,7 @@ public static MyValue2 createWithFieldsInline(int x, double d) {
MyValue2 v = createDefaultInline();
v = setX(v, x);
v = setY(v, (byte)x);
- v = setV(v, MyValue2Inline.createWithFieldsInline(d, InlineTypeTest.rL));
+ v = setV(v, MyValue2Inline.createWithFieldsInline(d, InlineTypes.rL));
return v;
}
@@ -97,7 +100,7 @@ public static MyValue2 createWithFieldsDontInline(int x, double d) {
MyValue2 v = createDefaultInline();
v = setX(v, x);
v = setY(v, (byte)x);
- v = setV(v, MyValue2Inline.createWithFieldsInline(d, InlineTypeTest.rL));
+ v = setV(v, MyValue2Inline.createWithFieldsInline(d, InlineTypes.rL));
return v;
}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue3.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue3.java
index fa3b468a790..4b6ef9df780 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue3.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue3.java
@@ -25,6 +25,8 @@
import jdk.test.lib.Asserts;
import jdk.test.lib.Utils;
+import compiler.lib.ir_framework.DontInline;
+import compiler.lib.ir_framework.ForceInline;
final primitive class MyValue3Inline {
final float f7;
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue4.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue4.java
index fcf3f38d7ea..a0e7ad47e68 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue4.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue4.java
@@ -23,6 +23,8 @@
package compiler.valhalla.inlinetypes;
+import compiler.lib.ir_framework.ForceInline;
+
// Inline type definition with too many fields to return in registers
final primitive class MyValue4 extends MyAbstract {
final MyValue3 v1;
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrays.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrays.java
index 2fc93a3bcad..a0a639ce3d3 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrays.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrays.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2021, 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,43 +23,44 @@
package compiler.valhalla.inlinetypes;
+import compiler.lib.ir_framework.*;
import jdk.test.lib.Asserts;
-import java.lang.invoke.*;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.util.Arrays;
+import static compiler.valhalla.inlinetypes.InlineTypes.IRNode.*;
+import static compiler.valhalla.inlinetypes.InlineTypes.*;
+
/*
* @test
* @key randomness
* @summary Test inline type arrays
- * @library /testlibrary /test/lib /compiler/whitebox /
+ * @library /test/lib /
* @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
- * @compile TestArrays.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestArrays
+ * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestArrays
*/
-public class TestArrays extends InlineTypeTest {
- // Extra VM parameters for some test scenarios. See InlineTypeTest.getVMParameters()
- @Override
- public String[] getExtraVMParameters(int scenario) {
- switch (scenario) {
- case 2: return new String[] {"-XX:-MonomorphicArrayCheck", "-XX:-UncommonNullCast", "-XX:+StressArrayCopyMacroNode"};
- case 3: return new String[] {"-XX:-MonomorphicArrayCheck", "-XX:FlatArrayElementMaxSize=-1", "-XX:-UncommonNullCast"};
- case 4: return new String[] {"-XX:-MonomorphicArrayCheck", "-XX:-UncommonNullCast"};
- case 5: return new String[] {"-XX:-MonomorphicArrayCheck", "-XX:-UncommonNullCast", "-XX:+StressArrayCopyMacroNode"};
- }
- return null;
- }
- public static void main(String[] args) throws Throwable {
- TestArrays test = new TestArrays();
- test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class);
+@ForceCompileClassInitializer
+public class TestArrays {
+
+ public static void main(String[] args) {
+ Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS;
+ scenarios[2].addFlags("-XX:-MonomorphicArrayCheck", "-XX:-UncommonNullCast", "-XX:+StressArrayCopyMacroNode");
+ scenarios[3].addFlags("-XX:-MonomorphicArrayCheck", "-XX:FlatArrayElementMaxSize=-1", "-XX:-UncommonNullCast");
+ scenarios[4].addFlags("-XX:-MonomorphicArrayCheck", "-XX:-UncommonNullCast");
+ scenarios[5].addFlags("-XX:-MonomorphicArrayCheck", "-XX:-UncommonNullCast", "-XX:+StressArrayCopyMacroNode");
+
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .addHelperClasses(MyValue1.class, MyValue2.class, MyValue2Inline.class)
+ .start();
}
- // Helper methods
+ // Helper methods and classes
protected long hash() {
return hash(rI, rL);
@@ -69,9 +70,68 @@ protected long hash(int x, long y) {
return MyValue1.createWithFieldsInline(x, y).hash();
}
+ static void verify(Object[] src, Object[] dst) {
+ if (src instanceof MyInterface[] && dst instanceof MyInterface[]) {
+ for (int i = 0; i < src.length; ++i) {
+ Asserts.assertEQ(((MyInterface)src[i]).hash(), ((MyInterface)dst[i]).hash());
+ }
+ } else {
+ for (int i = 0; i < src.length; ++i) {
+ Asserts.assertEQ(src[i], dst[i]);
+ }
+ }
+ }
+
+ static void verify(MyValue1[] src, MyValue1[] dst) {
+ for (int i = 0; i < src.length; ++i) {
+ Asserts.assertEQ(src[i].hash(), dst[i].hash());
+ }
+ }
+
+ static void verify(MyValue1[] src, Object[] dst) {
+ for (int i = 0; i < src.length; ++i) {
+ Asserts.assertEQ(src[i].hash(), ((MyInterface)dst[i]).hash());
+ }
+ }
+
+ static void verify(MyValue2[] src, MyValue2[] dst) {
+ for (int i = 0; i < src.length; ++i) {
+ Asserts.assertEQ(src[i].hash(), dst[i].hash());
+ }
+ }
+
+ static void verify(MyValue2[] src, Object[] dst) {
+ for (int i = 0; i < src.length; ++i) {
+ Asserts.assertEQ(src[i].hash(), ((MyInterface)dst[i]).hash());
+ }
+ }
+
+ static boolean compile_and_run_again_if_deoptimized(RunInfo info) {
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ if (TestFramework.isCompiled(m)) {
+ TestFramework.compile(m, CompLevel.C2);
+ }
+ }
+ return false;
+ }
+
+ primitive static class NotFlattenable {
+ private final Object o1 = null;
+ private final Object o2 = null;
+ private final Object o3 = null;
+ private final Object o4 = null;
+ private final Object o5 = null;
+ private final Object o6 = null;
+ }
+
// Test inline type array creation and initialization
- @Test(valid = InlineTypeArrayFlattenOn, match = { ALLOCA }, matchCount = { 1 })
- @Test(valid = InlineTypeArrayFlattenOff, match = { ALLOCA }, matchCount = { 1 }, failOn = LOAD)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ counts = {ALLOCA, "= 1"})
+ @IR(applyIf = {"FlatArrayElementMaxSize", "!= -1"},
+ counts = {ALLOCA, "= 1"},
+ failOn = LOAD)
public MyValue1[] test1(int len) {
MyValue1[] va = new MyValue1[len];
for (int i = 0; i < len; ++i) {
@@ -80,8 +140,8 @@ public MyValue1[] test1(int len) {
return va;
}
- @DontCompile
- public void test1_verifier(boolean warmup) {
+ @Run(test = "test1")
+ public void test1_verifier() {
int len = Math.abs(rI % 10);
MyValue1[] va = test1(len);
for (int i = 0; i < len; ++i) {
@@ -90,22 +150,24 @@ public void test1_verifier(boolean warmup) {
}
// Test creation of an inline type array and element access
- @Test(failOn = ALLOC + ALLOCA + LOOP + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOOP, LOAD, STORE, TRAP})
public long test2() {
MyValue1[] va = new MyValue1[1];
va[0] = MyValue1.createWithFieldsInline(rI, rL);
return va[0].hash();
}
- @DontCompile
- public void test2_verifier(boolean warmup) {
+ @Run(test = "test2")
+ public void test2_verifier() {
long result = test2();
Asserts.assertEQ(result, hash());
}
// Test receiving an inline type array from the interpreter,
// updating its elements in a loop and computing a hash.
- @Test(failOn = ALLOCA)
+ @Test
+ @IR(failOn = ALLOCA)
public long test3(MyValue1[] va) {
long result = 0;
for (int i = 0; i < 10; ++i) {
@@ -115,8 +177,8 @@ public long test3(MyValue1[] va) {
return result;
}
- @DontCompile
- public void test3_verifier(boolean warmup) {
+ @Run(test = "test3")
+ public void test3_verifier() {
MyValue1[] va = new MyValue1[10];
long expected = 0;
for (int i = 0; i < 10; ++i) {
@@ -133,13 +195,14 @@ public void test3_verifier(boolean warmup) {
}
// Test returning an inline type array received from the interpreter
- @Test(failOn = ALLOC + ALLOCA + LOAD + STORE + LOOP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOAD, STORE, LOOP, TRAP})
public MyValue1[] test4(MyValue1[] va) {
return va;
}
- @DontCompile
- public void test4_verifier(boolean warmup) {
+ @Run(test = "test4")
+ public void test4_verifier() {
MyValue1[] va = new MyValue1[10];
for (int i = 0; i < 10; ++i) {
va[i] = MyValue1.createWithFieldsDontInline(rI + i, rL + i);
@@ -174,8 +237,8 @@ public MyValue1[] test5(boolean b) {
return va;
}
- @DontCompile
- public void test5_verifier(boolean warmup) {
+ @Run(test = "test5")
+ public void test5_verifier() {
MyValue1[] va = test5(true);
Asserts.assertEQ(va.length, 5);
Asserts.assertEQ(va[0].hash(), hash(rI, hash()));
@@ -191,27 +254,29 @@ public void test5_verifier(boolean warmup) {
}
// Test creation of inline type array with single element
- @Test(failOn = ALLOC + ALLOCA + LOOP + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOOP, LOAD, STORE, TRAP})
public MyValue1 test6() {
MyValue1[] va = new MyValue1[1];
return va[0];
}
- @DontCompile
- public void test6_verifier(boolean warmup) {
+ @Run(test = "test6")
+ public void test6_verifier() {
MyValue1[] va = new MyValue1[1];
MyValue1 v = test6();
Asserts.assertEQ(v.hashPrimitive(), va[0].hashPrimitive());
}
// Test default initialization of inline type arrays
- @Test(failOn = LOAD)
+ @Test
+ @IR(failOn = LOAD)
public MyValue1[] test7(int len) {
return new MyValue1[len];
}
- @DontCompile
- public void test7_verifier(boolean warmup) {
+ @Run(test = "test7")
+ public void test7_verifier() {
int len = Math.abs(rI % 10);
MyValue1[] va = new MyValue1[len];
MyValue1[] var = test7(len);
@@ -221,13 +286,14 @@ public void test7_verifier(boolean warmup) {
}
// Test creation of inline type array with zero length
- @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, LOOP, TRAP})
public MyValue1[] test8() {
return new MyValue1[0];
}
- @DontCompile
- public void test8_verifier(boolean warmup) {
+ @Run(test = "test8")
+ public void test8_verifier() {
MyValue1[] va = test8();
Asserts.assertEQ(va.length, 0);
}
@@ -235,13 +301,14 @@ public void test8_verifier(boolean warmup) {
static MyValue1[] test9_va;
// Test that inline type array loaded from field has correct type
- @Test(failOn = LOOP)
+ @Test
+ @IR(failOn = LOOP)
public long test9() {
return test9_va[0].hash();
}
- @DontCompile
- public void test9_verifier(boolean warmup) {
+ @Run(test = "test9")
+ public void test9_verifier() {
test9_va = new MyValue1[1];
test9_va[0] = MyValue1.createWithFieldsInline(rI, rL);
long result = test9();
@@ -262,8 +329,8 @@ public MyValue1[][][] test10(int len1, int len2, int len3) {
return arr;
}
- @DontCompile
- public void test10_verifier(boolean warmup) {
+ @Run(test = "test10")
+ public void test10_verifier() {
MyValue1[][][] arr = test10(2, 3, 4);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
@@ -287,8 +354,8 @@ public void test11(MyValue1[][][] arr, long[] res) {
}
}
- @DontCompile
- public void test11_verifier(boolean warmup) {
+ @Run(test = "test11")
+ public void test11_verifier() {
MyValue1[][][] arr = new MyValue1[2][3][4];
long[] res = new long[2*3*4];
long[] verif = new long[2*3*4];
@@ -325,8 +392,8 @@ public int test12() {
}
}
- @DontCompile
- public void test12_verifier(boolean warmup) {
+ @Run(test = "test12")
+ public void test12_verifier() {
Asserts.assertEQ(test12(), rI);
}
@@ -347,8 +414,8 @@ public int test13() {
}
}
- @DontCompile
- public void test13_verifier(boolean warmup) {
+ @Run(test = "test13")
+ public void test13_verifier() {
Asserts.assertEQ(test13(), rI);
}
@@ -358,8 +425,8 @@ public int test14(MyValue1[] va, int index) {
return va[index].x;
}
- @DontCompile
- public void test14_verifier(boolean warmup) {
+ @Run(test = "test14")
+ public void test14_verifier() {
int arraySize = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[arraySize];
@@ -394,8 +461,8 @@ public int test15() {
}
}
- @DontCompile
- public void test15_verifier(boolean warmup) {
+ @Run(test = "test15")
+ public void test15_verifier() {
Asserts.assertEQ(test15(), rI);
}
@@ -415,8 +482,8 @@ public int test16() {
}
}
- @DontCompile
- public void test16_verifier(boolean warmup) {
+ @Run(test = "test16")
+ public void test16_verifier() {
Asserts.assertEQ(test16(), rI);
}
@@ -427,8 +494,8 @@ public int test17(MyValue1[] va, int index, MyValue1 vt) {
return va[index].x;
}
- @DontCompile
- public void test17_verifier(boolean warmup) {
+ @Run(test = "test17")
+ public void test17_verifier() {
int arraySize = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[arraySize];
@@ -458,8 +525,8 @@ public MyValue1[] test18(MyValue1[] va) {
return va.clone();
}
- @DontCompile
- public void test18_verifier(boolean warmup) {
+ @Run(test = "test18")
+ public void test18_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[len];
for (int i = 0; i < len; ++i) {
@@ -485,8 +552,8 @@ public MyValue1[] test19() {
return va.clone();
}
- @DontCompile
- public void test19_verifier(boolean warmup) {
+ @Run(test = "test19")
+ public void test19_verifier() {
MyValue1[] result = test19();
for (int i = 0; i < test19_orig.length; ++i) {
Asserts.assertEQ(result[i].hash(), test19_orig[i].hash());
@@ -499,8 +566,8 @@ public void test20(MyValue1[] src, MyValue1[] dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test20_verifier(boolean warmup) {
+ @Run(test = "test20")
+ public void test20_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] src = new MyValue1[len];
MyValue1[] dst = new MyValue1[len];
@@ -519,8 +586,8 @@ public void test21(MyValue2[] src, MyValue2[] dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test21_verifier(boolean warmup) {
+ @Run(test = "test21")
+ public void test21_verifier() {
int len = Math.abs(rI) % 10;
MyValue2[] src = new MyValue2[len];
MyValue2[] dst = new MyValue2[len];
@@ -542,8 +609,8 @@ public MyValue1[] test22(MyValue1[] src) {
return dst;
}
- @DontCompile
- public void test22_verifier(boolean warmup) {
+ @Run(test = "test22")
+ public void test22_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] src = new MyValue1[len];
for (int i = 0; i < len; ++i) {
@@ -564,8 +631,8 @@ public MyValue1[] test23(MyValue1[] src) {
return dst;
}
- @DontCompile
- public void test23_verifier(boolean warmup) {
+ @Run(test = "test23")
+ public void test23_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] src = new MyValue1[len];
for (int i = 0; i < len; ++i) {
@@ -583,8 +650,8 @@ public void test24(MyValue1[] src, Object dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test24_verifier(boolean warmup) {
+ @Run(test = "test24")
+ public void test24_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] src = new MyValue1[len];
MyValue1[] dst1 = new MyValue1[len];
@@ -608,8 +675,8 @@ public void test25(MyValue2[] src, MyValue2[] dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test25_verifier(boolean warmup) {
+ @Run(test = "test25")
+ public void test25_verifier() {
MyValue2[] src = new MyValue2[8];
MyValue2[] dst = new MyValue2[8];
for (int i = 0; i < 8; ++i) {
@@ -627,8 +694,8 @@ public void test26(MyValue1[] src, MyValue1[] dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test26_verifier(boolean warmup) {
+ @Run(test = "test26")
+ public void test26_verifier() {
MyValue1[] src = new MyValue1[8];
MyValue1[] dst = new MyValue1[8];
for (int i = 0; i < 8; ++i) {
@@ -646,8 +713,8 @@ public void test27(MyValue1[] src, MyValue1[] dst) {
System.arraycopy(src, 1, dst, 2, 6);
}
- @DontCompile
- public void test27_verifier(boolean warmup) {
+ @Run(test = "test27")
+ public void test27_verifier() {
MyValue1[] src = new MyValue1[8];
MyValue1[] dst = new MyValue1[8];
for (int i = 0; i < 8; ++i) {
@@ -661,8 +728,9 @@ public void test27_verifier(boolean warmup) {
// non escaping allocations
// TODO 8252027: Make sure this is optimized with ZGC
- @Test(valid = ZGCOff, failOn = ALLOCA + LOOP + LOAD + TRAP)
- @Test(valid = ZGCOn)
+ @Test
+ @IR(applyIf = {"UseZGC", "false"},
+ failOn = {ALLOCA, LOOP, LOAD, TRAP})
public MyValue2 test28() {
MyValue2[] src = new MyValue2[10];
src[0] = MyValue2.createWithFieldsInline(rI, rD);
@@ -670,8 +738,8 @@ public MyValue2 test28() {
return dst[0];
}
- @DontCompile
- public void test28_verifier(boolean warmup) {
+ @Run(test = "test28")
+ public void test28_verifier() {
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
MyValue2 result = test28();
Asserts.assertEQ(result.hash(), v.hash());
@@ -680,16 +748,19 @@ public void test28_verifier(boolean warmup) {
// non escaping allocations
// TODO 8227588: shouldn't this have the same IR matching rules as test6?
// @Test(failOn = ALLOC + ALLOCA + LOOP + LOAD + STORE + TRAP)
- @Test(valid = InlineTypeArrayFlattenOn, failOn = ALLOCA + LOOP + LOAD + TRAP)
- @Test(valid = InlineTypeArrayFlattenOff, failOn = ALLOCA + LOOP + TRAP)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ failOn = {ALLOCA, LOOP, LOAD, TRAP})
+ @IR(applyIf = {"FlatArrayElementMaxSize", "!= -1"},
+ failOn = {ALLOCA, LOOP, TRAP})
public MyValue2 test29(MyValue2[] src) {
MyValue2[] dst = new MyValue2[10];
System.arraycopy(src, 0, dst, 0, 10);
return dst[0];
}
- @DontCompile
- public void test29_verifier(boolean warmup) {
+ @Run(test = "test29")
+ public void test29_verifier() {
MyValue2[] src = new MyValue2[10];
for (int i = 0; i < 10; ++i) {
src[i] = MyValue2.createWithFieldsInline(rI+i, rD+i);
@@ -701,7 +772,6 @@ public void test29_verifier(boolean warmup) {
// non escaping allocation with uncommon trap that needs
// eliminated inline type array element as debug info
@Test
- @Warmup(10000)
public MyValue2 test30(MyValue2[] src, boolean flag) {
MyValue2[] dst = new MyValue2[10];
System.arraycopy(src, 0, dst, 0, 10);
@@ -709,19 +779,22 @@ public MyValue2 test30(MyValue2[] src, boolean flag) {
return dst[0];
}
- @DontCompile
- public void test30_verifier(boolean warmup) {
+ @Run(test = "test30")
+ @Warmup(10000)
+ public void test30_verifier(RunInfo info) {
MyValue2[] src = new MyValue2[10];
for (int i = 0; i < 10; ++i) {
src[i] = MyValue2.createWithFieldsInline(rI+i, rD+i);
}
- MyValue2 v = test30(src, !warmup);
+ MyValue2 v = test30(src, !info.isWarmUp());
Asserts.assertEQ(src[0].hash(), v.hash());
}
+
// non escaping allocation with memory phi
- @Test(failOn = ALLOC + ALLOCA + LOOP + LOAD + STORE + TRAP)
- public long test31(boolean b, boolean deopt) {
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOOP, LOAD, STORE, TRAP})
+ public long test31(boolean b, boolean deopt, Method m) {
MyValue2[] src = new MyValue2[1];
if (b) {
src[0] = MyValue2.createWithFieldsInline(rI, rD);
@@ -730,18 +803,18 @@ public long test31(boolean b, boolean deopt) {
}
if (deopt) {
// uncommon trap
- WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test31"));
+ TestFramework.deoptimize(m);
}
return src[0].hash();
}
- @DontCompile
- public void test31_verifier(boolean warmup) {
+ @Run(test = "test31")
+ public void test31_verifier(RunInfo info) {
MyValue2 v1 = MyValue2.createWithFieldsInline(rI, rD);
- long result1 = test31(true, !warmup);
+ long result1 = test31(true, !info.isWarmUp(), info.getTest());
Asserts.assertEQ(result1, v1.hash());
- MyValue2 v2 = MyValue2.createWithFieldsInline(rI+1, rD+1);
- long result2 = test31(false, !warmup);
+ MyValue2 v2 = MyValue2.createWithFieldsInline(rI + 1, rD + 1);
+ long result2 = test31(false, !info.isWarmUp(), info.getTest());
Asserts.assertEQ(result2, v2.hash());
}
@@ -752,8 +825,8 @@ public Object[] test32(Object[] va) {
return va.clone();
}
- @DontCompile
- public void test32_verifier(boolean warmup) {
+ @Run(test = "test32")
+ public void test32_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[len];
for (int i = 0; i < len; ++i) {
@@ -770,8 +843,8 @@ public Object[] test33(Object[] va) {
return va.clone();
}
- @DontCompile
- public void test33_verifier(boolean warmup) {
+ @Run(test = "test33")
+ public void test33_verifier() {
int len = Math.abs(rI) % 10;
Object[] va = new Object[len];
for (int i = 0; i < len; ++i) {
@@ -809,8 +882,8 @@ public Object[] test34(boolean flag) {
return va.clone();
}
- @DontCompile
- public void test34_verifier(boolean warmup) {
+ @Run(test = "test34")
+ public void test34_verifier(RunInfo info) {
test34(false);
for (int i = 0; i < 10; i++) { // make sure we do deopt
Object[] result = test34(true);
@@ -823,7 +896,7 @@ public void test34_verifier(boolean warmup) {
// Expected
}
}
- if (compile_and_run_again_if_deoptimized(warmup, "TestArrays::test34")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
Object[] result = test34(true);
verify(test34_orig, result);
// Check that array has correct properties (null-free)
@@ -836,64 +909,14 @@ public void test34_verifier(boolean warmup) {
}
}
- static void verify(Object[] src, Object[] dst) {
- if (src instanceof MyInterface[] && dst instanceof MyInterface[]) {
- for (int i = 0; i < src.length; ++i) {
- Asserts.assertEQ(((MyInterface)src[i]).hash(), ((MyInterface)dst[i]).hash());
- }
- } else {
- for (int i = 0; i < src.length; ++i) {
- Asserts.assertEQ(src[i], dst[i]);
- }
- }
- }
-
- static void verify(MyValue1[] src, MyValue1[] dst) {
- for (int i = 0; i < src.length; ++i) {
- Asserts.assertEQ(src[i].hash(), dst[i].hash());
- }
- }
-
- static void verify(MyValue1[] src, Object[] dst) {
- for (int i = 0; i < src.length; ++i) {
- Asserts.assertEQ(src[i].hash(), ((MyInterface)dst[i]).hash());
- }
- }
-
- static void verify(MyValue2[] src, MyValue2[] dst) {
- for (int i = 0; i < src.length; ++i) {
- Asserts.assertEQ(src[i].hash(), dst[i].hash());
- }
- }
-
- static void verify(MyValue2[] src, Object[] dst) {
- for (int i = 0; i < src.length; ++i) {
- Asserts.assertEQ(src[i].hash(), ((MyInterface)dst[i]).hash());
- }
- }
-
- static boolean compile_and_run_again_if_deoptimized(boolean warmup, String test) {
- if (!warmup) {
- Method m = tests.get(test);
- if (USE_COMPILER && !WHITE_BOX.isMethodCompiled(m, false)) {
- if (!InlineTypeArrayFlatten && !XCOMP && !STRESS_CC) {
- throw new RuntimeException("Unexpected deoptimization");
- }
- enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION);
- return true;
- }
- }
- return false;
- }
-
// arraycopy() of inline type array of unknown size
@Test
public void test35(Object src, Object dst, int len) {
System.arraycopy(src, 0, dst, 0, len);
}
- @DontCompile
- public void test35_verifier(boolean warmup) {
+ @Run(test = "test35")
+ public void test35_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
MyValue1[] src = new MyValue1[len];
MyValue1[] dst1 = new MyValue1[len];
@@ -905,7 +928,7 @@ public void test35_verifier(boolean warmup) {
verify(src, dst1);
test35(src, dst2, src.length);
verify(src, dst2);
- if (compile_and_run_again_if_deoptimized(warmup, "TestArrays::test35")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test35(src, dst1, src.length);
verify(src, dst1);
}
@@ -916,8 +939,8 @@ public void test36(Object src, MyValue2[] dst) {
System.arraycopy(src, 0, dst, 0, dst.length);
}
- @DontCompile
- public void test36_verifier(boolean warmup) {
+ @Run(test = "test36")
+ public void test36_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
MyValue2[] src = new MyValue2[len];
MyValue2[] dst = new MyValue2[len];
@@ -926,7 +949,7 @@ public void test36_verifier(boolean warmup) {
}
test36(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestArrays::test36")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test36(src, dst);
verify(src, dst);
}
@@ -937,8 +960,8 @@ public void test37(MyValue2[] src, Object dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test37_verifier(boolean warmup) {
+ @Run(test = "test37")
+ public void test37_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
MyValue2[] src = new MyValue2[len];
MyValue2[] dst = new MyValue2[len];
@@ -947,20 +970,21 @@ public void test37_verifier(boolean warmup) {
}
test37(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestArrays::test37")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test37(src, dst);
verify(src, dst);
}
}
+
@Test
- @Warmup(1) // Avoid early compilation
public void test38(Object src, MyValue2[] dst) {
System.arraycopy(src, 0, dst, 0, dst.length);
}
- @DontCompile
- public void test38_verifier(boolean warmup) {
+ @Run(test = "test38")
+ @Warmup(1) // Avoid early compilation
+ public void test38_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
Object[] src = new Object[len];
MyValue2[] dst = new MyValue2[len];
@@ -969,15 +993,13 @@ public void test38_verifier(boolean warmup) {
}
test38(src, dst);
verify(dst, src);
- if (!warmup) {
- Method m = tests.get("TestArrays::test38");
- assertDeoptimizedByC2(m);
- enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION);
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertDeoptimizedByC2(m);
+ TestFramework.compile(m, CompLevel.C2);
test38(src, dst);
verify(dst, src);
- if (USE_COMPILER && !WHITE_BOX.isMethodCompiled(m, false) && !XCOMP && !STRESS_CC) {
- throw new RuntimeException("unexpected deoptimization");
- }
+ TestFramework.assertCompiledByC2(m);
}
}
@@ -986,8 +1008,8 @@ public void test39(MyValue2[] src, Object dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test39_verifier(boolean warmup) {
+ @Run(test = "test39")
+ public void test39_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
MyValue2[] src = new MyValue2[len];
Object[] dst = new Object[len];
@@ -996,20 +1018,20 @@ public void test39_verifier(boolean warmup) {
}
test39(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestArrays::test39")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test39(src, dst);
verify(src, dst);
}
}
@Test
- @Warmup(1) // Avoid early compilation
public void test40(Object[] src, Object dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test40_verifier(boolean warmup) {
+ @Run(test = "test40")
+ @Warmup(1) // Avoid early compilation
+ public void test40_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
Object[] src = new Object[len];
MyValue2[] dst = new MyValue2[len];
@@ -1018,15 +1040,13 @@ public void test40_verifier(boolean warmup) {
}
test40(src, dst);
verify(dst, src);
- if (!warmup) {
- Method m = tests.get("TestArrays::test40");
- assertDeoptimizedByC2(m);
- enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION);
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertDeoptimizedByC2(m);
+ TestFramework.compile(m, CompLevel.C2);
test40(src, dst);
verify(dst, src);
- if (USE_COMPILER && !WHITE_BOX.isMethodCompiled(m, false) && !XCOMP && !STRESS_CC) {
- throw new RuntimeException("unexpected deoptimization");
- }
+ TestFramework.assertCompiledByC2(m);
}
}
@@ -1035,8 +1055,8 @@ public void test41(Object src, Object[] dst) {
System.arraycopy(src, 0, dst, 0, dst.length);
}
- @DontCompile
- public void test41_verifier(boolean warmup) {
+ @Run(test = "test41")
+ public void test41_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
MyValue2[] src = new MyValue2[len];
Object[] dst = new Object[len];
@@ -1045,7 +1065,7 @@ public void test41_verifier(boolean warmup) {
}
test41(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestArrays::test41")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test41(src, dst);
verify(src, dst);
}
@@ -1056,8 +1076,8 @@ public void test42(Object[] src, Object[] dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test42_verifier(boolean warmup) {
+ @Run(test = "test42")
+ public void test42_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
Object[] src = new Object[len];
Object[] dst = new Object[len];
@@ -1066,11 +1086,8 @@ public void test42_verifier(boolean warmup) {
}
test42(src, dst);
verify(src, dst);
- if (!warmup) {
- Method m = tests.get("TestArrays::test42");
- if (USE_COMPILER && !WHITE_BOX.isMethodCompiled(m, false) && !XCOMP && !STRESS_CC) {
- throw new RuntimeException("unexpected deoptimization");
- }
+ if (!info.isWarmUp()) {
+ TestFramework.assertCompiledByC2(info.getTest());
}
}
@@ -1080,8 +1097,8 @@ public void test43(Object src, Object dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test43_verifier(boolean warmup) {
+ @Run(test = "test43")
+ public void test43_verifier(RunInfo info) {
MyValue1[] src = new MyValue1[8];
MyValue1[] dst = new MyValue1[8];
for (int i = 0; i < 8; ++i) {
@@ -1089,7 +1106,7 @@ public void test43_verifier(boolean warmup) {
}
test43(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestArrays::test43")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test43(src, dst);
verify(src, dst);
}
@@ -1100,8 +1117,8 @@ public void test44(Object src, MyValue2[] dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test44_verifier(boolean warmup) {
+ @Run(test = "test44")
+ public void test44_verifier(RunInfo info) {
MyValue2[] src = new MyValue2[8];
MyValue2[] dst = new MyValue2[8];
for (int i = 0; i < 8; ++i) {
@@ -1109,7 +1126,7 @@ public void test44_verifier(boolean warmup) {
}
test44(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestArrays::test44")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test44(src, dst);
verify(src, dst);
}
@@ -1120,8 +1137,8 @@ public void test45(MyValue2[] src, Object dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test45_verifier(boolean warmup) {
+ @Run(test = "test45")
+ public void test45_verifier(RunInfo info) {
MyValue2[] src = new MyValue2[8];
MyValue2[] dst = new MyValue2[8];
for (int i = 0; i < 8; ++i) {
@@ -1129,20 +1146,20 @@ public void test45_verifier(boolean warmup) {
}
test45(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestArrays::test45")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test45(src, dst);
verify(src, dst);
}
}
@Test
- @Warmup(1) // Avoid early compilation
public void test46(Object[] src, MyValue2[] dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test46_verifier(boolean warmup) {
+ @Run(test = "test46")
+ @Warmup(1) // Avoid early compilation
+ public void test46_verifier(RunInfo info) {
Object[] src = new Object[8];
MyValue2[] dst = new MyValue2[8];
for (int i = 0; i < 8; ++i) {
@@ -1150,15 +1167,13 @@ public void test46_verifier(boolean warmup) {
}
test46(src, dst);
verify(dst, src);
- if (!warmup) {
- Method m = tests.get("TestArrays::test46");
- assertDeoptimizedByC2(m);
- enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION);
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertDeoptimizedByC2(m);
+ TestFramework.compile(m, CompLevel.C2);
test46(src, dst);
verify(dst, src);
- if (USE_COMPILER && !WHITE_BOX.isMethodCompiled(m, false) && !XCOMP && !STRESS_CC) {
- throw new RuntimeException("unexpected deoptimization");
- }
+ TestFramework.assertCompiledByC2(m);
}
}
@@ -1167,8 +1182,8 @@ public void test47(MyValue2[] src, Object[] dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test47_verifier(boolean warmup) {
+ @Run(test = "test47")
+ public void test47_verifier(RunInfo info) {
MyValue2[] src = new MyValue2[8];
Object[] dst = new Object[8];
for (int i = 0; i < 8; ++i) {
@@ -1176,20 +1191,20 @@ public void test47_verifier(boolean warmup) {
}
test47(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestArrays::test47")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test47(src, dst);
verify(src, dst);
}
}
@Test
- @Warmup(1) // Avoid early compilation
public void test48(Object[] src, Object dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test48_verifier(boolean warmup) {
+ @Run(test = "test48")
+ @Warmup(1) // Avoid early compilation
+ public void test48_verifier(RunInfo info) {
Object[] src = new Object[8];
MyValue2[] dst = new MyValue2[8];
for (int i = 0; i < 8; ++i) {
@@ -1197,15 +1212,13 @@ public void test48_verifier(boolean warmup) {
}
test48(src, dst);
verify(dst, src);
- if (!warmup) {
- Method m = tests.get("TestArrays::test48");
- assertDeoptimizedByC2(m);
- enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION);
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertDeoptimizedByC2(m);
+ TestFramework.compile(m, CompLevel.C2);
test48(src, dst);
verify(dst, src);
- if (USE_COMPILER && !WHITE_BOX.isMethodCompiled(m, false) && !XCOMP && !STRESS_CC) {
- throw new RuntimeException("unexpected deoptimization");
- }
+ TestFramework.assertCompiledByC2(m);
}
}
@@ -1214,8 +1227,8 @@ public void test49(Object src, Object[] dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test49_verifier(boolean warmup) {
+ @Run(test = "test49")
+ public void test49_verifier(RunInfo info) {
MyValue2[] src = new MyValue2[8];
Object[] dst = new Object[8];
for (int i = 0; i < 8; ++i) {
@@ -1223,7 +1236,7 @@ public void test49_verifier(boolean warmup) {
}
test49(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestArrays::test49")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test49(src, dst);
verify(src, dst);
}
@@ -1234,8 +1247,8 @@ public void test50(Object[] src, Object[] dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test50_verifier(boolean warmup) {
+ @Run(test = "test50")
+ public void test50_verifier(RunInfo info) {
Object[] src = new Object[8];
Object[] dst = new Object[8];
for (int i = 0; i < 8; ++i) {
@@ -1243,11 +1256,9 @@ public void test50_verifier(boolean warmup) {
}
test50(src, dst);
verify(src, dst);
- if (!warmup) {
- Method m = tests.get("TestArrays::test50");
- if (USE_COMPILER && !WHITE_BOX.isMethodCompiled(m, false) && !XCOMP && !STRESS_CC) {
- throw new RuntimeException("unexpected deoptimization");
- }
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
}
}
@@ -1258,8 +1269,8 @@ public MyValue1[] test51(MyValue1[] va) {
return (MyValue1[]) res;
}
- @DontCompile
- public void test51_verifier(boolean warmup) {
+ @Run(test = "test51")
+ public void test51_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[len];
for (int i = 0; i < len; ++i) {
@@ -1278,8 +1289,8 @@ public MyValue1[] test52() {
return (MyValue1[]) res;
}
- @DontCompile
- public void test52_verifier(boolean warmup) {
+ @Run(test = "test52")
+ public void test52_verifier() {
for (int i = 0; i < 8; ++i) {
test52_va[i] = MyValue1.createWithFieldsInline(rI, rL);
}
@@ -1294,8 +1305,8 @@ public MyValue1[] test53(Object[] va) {
return (MyValue1[]) res;
}
- @DontCompile
- public void test53_verifier(boolean warmup) {
+ @Run(test = "test53")
+ public void test53_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[len];
for (int i = 0; i < len; ++i) {
@@ -1310,8 +1321,8 @@ public Object[] test54(MyValue1[] va) {
return Arrays.copyOf(va, va.length, Object[].class);
}
- @DontCompile
- public void test54_verifier(boolean warmup) {
+ @Run(test = "test54")
+ public void test54_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[len];
for (int i = 0; i < len; ++i) {
@@ -1326,8 +1337,8 @@ public Object[] test55(Object[] va) {
return Arrays.copyOf(va, va.length, Object[].class);
}
- @DontCompile
- public void test55_verifier(boolean warmup) {
+ @Run(test = "test55")
+ public void test55_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[len];
for (int i = 0; i < len; ++i) {
@@ -1344,8 +1355,8 @@ public MyValue1[] test56(Object[] va) {
return (MyValue1[]) res;
}
- @DontCompile
- public void test56_verifier(boolean warmup) {
+ @Run(test = "test56")
+ public void test56_verifier() {
int len = Math.abs(rI) % 10;
Object[] va = new Object[len];
for (int i = 0; i < len; ++i) {
@@ -1355,13 +1366,13 @@ public void test56_verifier(boolean warmup) {
verify(result, va);
}
- @Test
+ @Test
public Object[] test57(Object[] va, Class klass) {
return Arrays.copyOf(va, va.length, klass);
}
- @DontCompile
- public void test57_verifier(boolean warmup) {
+ @Run(test = "test57")
+ public void test57_verifier() {
int len = Math.abs(rI) % 10;
Object[] va = new MyValue1[len];
for (int i = 0; i < len; ++i) {
@@ -1376,8 +1387,8 @@ public Object[] test58(MyValue1[] va, Class klass) {
return Arrays.copyOf(va, va.length, klass);
}
- @DontCompile
- public void test58_verifier(boolean warmup) {
+ @Run(test = "test58")
+ public void test58_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[len];
for (int i = 0; i < len; ++i) {
@@ -1387,7 +1398,7 @@ public void test58_verifier(boolean warmup) {
Object[] result = test58(va, MyValue1[].class);
verify(va, result);
}
- if (compile_and_run_again_if_deoptimized(warmup, "TestArrays::test58")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
Object[] result = test58(va, MyValue1[].class);
verify(va, result);
}
@@ -1398,8 +1409,8 @@ public Object[] test59(MyValue1[] va) {
return Arrays.copyOf(va, va.length+1, MyValue1[].class);
}
- @DontCompile
- public void test59_verifier(boolean warmup) {
+ @Run(test = "test59")
+ public void test59_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[len];
MyValue1[] verif = new MyValue1[len+1];
@@ -1416,8 +1427,8 @@ public Object[] test60(Object[] va, Class klass) {
return Arrays.copyOf(va, va.length+1, klass);
}
- @DontCompile
- public void test60_verifier(boolean warmup) {
+ @Run(test = "test60")
+ public void test60_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[len];
MyValue1[] verif = new MyValue1[len+1];
@@ -1434,8 +1445,8 @@ public Object[] test61(Object[] va, Class klass) {
return Arrays.copyOf(va, va.length+1, klass);
}
- @DontCompile
- public void test61_verifier(boolean warmup) {
+ @Run(test = "test61")
+ public void test61_verifier() {
int len = Math.abs(rI) % 10;
Object[] va = new Integer[len];
for (int i = 0; i < len; ++i) {
@@ -1468,8 +1479,8 @@ public Object[] test62(MyValue1[] va, Integer[] oa) {
return Arrays.copyOf(arr, arr.length+1, arr.getClass());
}
- @DontCompile
- public void test62_verifier(boolean warmup) {
+ @Run(test = "test62")
+ public void test62_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[len];
Integer[] oa = new Integer[len];
@@ -1504,8 +1515,8 @@ public Object[] test63(MyValue1[] va, Integer[] oa) {
return Arrays.copyOf(arr, arr.length+1, arr.getClass());
}
- @DontCompile
- public void test63_verifier(boolean warmup) {
+ @Run(test = "test63")
+ public void test63_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[len];
MyValue1[] verif = new MyValue1[len+1];
@@ -1525,8 +1536,8 @@ public MyValue1[] test64() {
return new MyValue1[8];
}
- @DontCompile
- public void test64_verifier(boolean warmup) {
+ @Run(test = "test64")
+ public void test64_verifier() {
MyValue1[] va = new MyValue1[8];
MyValue1[] var = test64();
for (int i = 0; i < 8; ++i) {
@@ -1540,8 +1551,8 @@ public MyValue1[] test65() {
return new MyValue1[32];
}
- @DontCompile
- public void test65_verifier(boolean warmup) {
+ @Run(test = "test65")
+ public void test65_verifier() {
MyValue1[] va = new MyValue1[32];
MyValue1[] var = test65();
for (int i = 0; i < 32; ++i) {
@@ -1550,15 +1561,16 @@ public void test65_verifier(boolean warmup) {
}
// Check init store elimination
- @Test(match = { ALLOCA }, matchCount = { 1 })
+ @Test
+ @IR(counts = {ALLOCA, "= 1"})
public MyValue1[] test66(MyValue1 vt) {
MyValue1[] va = new MyValue1[1];
va[0] = vt;
return va;
}
- @DontCompile
- public void test66_verifier(boolean warmup) {
+ @Run(test = "test66")
+ public void test66_verifier() {
MyValue1 vt = MyValue1.createWithFieldsDontInline(rI, rL);
MyValue1[] va = test66(vt);
Asserts.assertEQ(va[0].hashPrimitive(), vt.hashPrimitive());
@@ -1572,8 +1584,8 @@ public MyValue1[] test67(MyValue1[] src) {
return dst;
}
- @DontCompile
- public void test67_verifier(boolean warmup) {
+ @Run(test = "test67")
+ public void test67_verifier() {
MyValue1[] va = new MyValue1[16];
MyValue1[] var = test67(va);
for (int i = 0; i < 16; ++i) {
@@ -1589,8 +1601,8 @@ public MyValue1[] test68() {
return va;
}
- @DontCompile
- public void test68_verifier(boolean warmup) {
+ @Run(test = "test68")
+ public void test68_verifier() {
MyValue1[] va = new MyValue1[2];
MyValue1[] var = test68();
for (int i = 0; i < 2; ++i) {
@@ -1607,8 +1619,8 @@ public MyValue1[] test69(MyValue1 vt) {
return va;
}
- @DontCompile
- public void test69_verifier(boolean warmup) {
+ @Run(test = "test69")
+ public void test69_verifier() {
MyValue1 vt = MyValue1.createWithFieldsDontInline(rI, rL);
MyValue1[] va = new MyValue1[4];
va[0] = vt;
@@ -1630,8 +1642,8 @@ public MyValue1[] test70(MyValue1[] other) {
return va;
}
- @DontCompile
- public void test70_verifier(boolean warmup) {
+ @Run(test = "test70")
+ public void test70_verifier() {
MyValue1[] va = new MyValue1[2];
MyValue1[] var = test70(va);
for (int i = 0; i < 2; ++i) {
@@ -1654,8 +1666,8 @@ public void test71() {
}
}
- @DontCompile
- public void test71_verifier(boolean warmup) {
+ @Run(test = "test71")
+ public void test71_verifier() {
test71();
}
@@ -1671,8 +1683,8 @@ public void test72(Object[] o, boolean b, Object element) {
arr2[0] = element;
}
- @DontCompile
- public void test72_verifier(boolean warmup) {
+ @Run(test = "test72")
+ public void test72_verifier() {
Object[] arr = new Object[1];
Object elem = new Object();
test72(arr, true, elem);
@@ -1690,8 +1702,8 @@ public void test73(Object[] oa, MyValue1 v, Object o) {
oa[0] = oa; // The stored value is known to be not flattenable (an Object[])
}
- @DontCompile
- public void test73_verifier(boolean warmup) {
+ @Run(test = "test73")
+ public void test73_verifier() {
MyValue1 v0 = MyValue1.createWithFieldsDontInline(rI, rL);
MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI+1, rL+1);
MyValue1[] arr = new MyValue1[3];
@@ -1710,13 +1722,13 @@ public static void test74Callee(MyValue1[] va) { }
// Tests invoking unloaded method with inline type array in signature
@Test
- @Warmup(0)
public void test74(MethodHandle m, MyValue1[] va) throws Throwable {
m.invoke(va);
}
- @DontCompile
- public void test74_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test74")
+ @Warmup(0)
+ public void test74_verifier() throws Throwable {
MethodHandle m = MethodHandles.lookup().findStatic(TestArrays.class, "test74Callee", MethodType.methodType(void.class, MyValue1[].class));
MyValue1[] va = new MyValue1[0];
test74(m, va);
@@ -1743,8 +1755,8 @@ public Object[] test75(MyValue1[] va, Integer[] oa) {
return arr.clone();
}
- @DontCompile
- public void test75_verifier(boolean warmup) {
+ @Run(test = "test75")
+ public void test75_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[len];
Integer[] oa = new Integer[len];
@@ -1781,8 +1793,8 @@ public Object[] test76(MyValue1[] va, Integer[] oa) {
return arr.clone();
}
- @DontCompile
- public void test76_verifier(boolean warmup) {
+ @Run(test = "test76")
+ public void test76_verifier() {
int len = Math.abs(rI) % 10;
MyValue1[] va = new MyValue1[len];
MyValue1[] verif = new MyValue1[len];
@@ -1821,8 +1833,8 @@ public void test77() {
}
- @DontCompile
- public void test77_verifier(boolean warmup) {
+ @Run(test = "test77")
+ public void test77_verifier() {
test77();
}
@@ -1841,23 +1853,26 @@ public long test78(MyValue1 v, int n) {
return x;
}
- @DontCompile
- public void test78_verifier(boolean warmup) {
+ @Run(test = "test78")
+ public void test78_verifier() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
Asserts.assertEQ(test78(v, 1), v.hash());
}
// Verify that casting an array element to a non-flattenable type marks the array as not-flat
- @Test(valid = InlineTypeArrayFlattenOn, match = { ALLOC_G, LOAD_UNKNOWN_INLINE }, matchCount = { 1, 1 })
- @Test(valid = InlineTypeArrayFlattenOff, failOn = ALLOC_G + ALLOCA_G + LOAD_UNKNOWN_INLINE)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ counts = {ALLOC_G, "= 1", LOAD_UNKNOWN_INLINE, "= 1"})
+ @IR(applyIf = {"FlatArrayElementMaxSize", "!= -1"},
+ failOn = {ALLOC_G, ALLOCA_G, LOAD_UNKNOWN_INLINE})
public Object test79(Object[] array, int i) {
Integer i1 = (Integer)array[0];
Object o = array[1];
return array[i];
}
- @DontCompile
- public void test79_verifier(boolean warmup) {
+ @Run(test = "test79")
+ public void test79_verifier() {
Integer i = Integer.valueOf(rI);
Integer[] array = new Integer[2];
array[1] = i;
@@ -1865,26 +1880,20 @@ public void test79_verifier(boolean warmup) {
Asserts.assertEquals(result, i);
}
- primitive static class NotFlattenable {
- private final Object o1 = null;
- private final Object o2 = null;
- private final Object o3 = null;
- private final Object o4 = null;
- private final Object o5 = null;
- private final Object o6 = null;
- }
-
// Same as test79 but with not-flattenable inline type
- @Test(valid = InlineTypeArrayFlattenOn, match = { ALLOC_G, LOAD_UNKNOWN_INLINE }, matchCount = { 1, 1 })
- @Test(valid = InlineTypeArrayFlattenOff, failOn = ALLOC_G + ALLOCA_G + LOAD_UNKNOWN_INLINE)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ counts = {ALLOC_G, "= 1", LOAD_UNKNOWN_INLINE, "= 1"})
+ @IR(applyIf = {"FlatArrayElementMaxSize", "!= -1"},
+ failOn = {ALLOC_G, ALLOCA_G, LOAD_UNKNOWN_INLINE})
public Object test80(Object[] array, int i) {
NotFlattenable vt = (NotFlattenable)array[0];
Object o = array[1];
return array[i];
}
- @DontCompile
- public void test80_verifier(boolean warmup) {
+ @Run(test = "test80")
+ public void test80_verifier() {
NotFlattenable vt = new NotFlattenable();
NotFlattenable[] array = new NotFlattenable[2];
array[1] = vt;
@@ -1893,7 +1902,8 @@ public void test80_verifier(boolean warmup) {
}
// Verify that writing an object of a non-inline, non-null type to an array marks the array as not-null-free and not-flat
- @Test(failOn = ALLOC_G + ALLOCA_G + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD)
+ @Test
+ @IR(failOn = {ALLOC_G, ALLOCA_G, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
public Object test81(Object[] array, Integer v, Object o, int i) {
if (v == null) {
return null;
@@ -1904,8 +1914,8 @@ public Object test81(Object[] array, Integer v, Object o, int i) {
return array[i];
}
- @DontCompile
- public void test81_verifier(boolean warmup) {
+ @Run(test = "test81")
+ public void test81_verifier() {
Integer i = Integer.valueOf(rI);
Integer[] array1 = new Integer[3];
Object[] array2 = new Object[3];
@@ -1922,8 +1932,11 @@ public void test81_verifier(boolean warmup) {
}
// Verify that writing an object of a non-flattenable inline type to an array marks the array as not-flat
- @Test(valid = InlineTypePassFieldsAsArgsOn, failOn = ALLOCA_G + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE)
- @Test(valid = InlineTypePassFieldsAsArgsOff, failOn = ALLOC_G + ALLOCA_G + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE)
+ @Test
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "true"},
+ failOn = {ALLOCA_G, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE})
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "false"},
+ failOn = {ALLOC_G, ALLOCA_G, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE})
public Object test82(Object[] array, NotFlattenable vt, Object o, int i) {
array[0] = vt;
array[1] = array[0];
@@ -1931,8 +1944,8 @@ public Object test82(Object[] array, NotFlattenable vt, Object o, int i) {
return array[i];
}
- @DontCompile
- public void test82_verifier(boolean warmup) {
+ @Run(test = "test82")
+ public void test82_verifier() {
NotFlattenable vt = new NotFlattenable();
NotFlattenable[] array1 = new NotFlattenable[3];
Object[] array2 = new Object[3];
@@ -1949,15 +1962,19 @@ public void test82_verifier(boolean warmup) {
}
// Verify that casting an array element to a non-inline type type marks the array as not-null-free and not-flat
- @Test(valid = InlineTypeArrayFlattenOn, match = { ALLOC_G, LOAD_UNKNOWN_INLINE }, matchCount = { 1, 1 }, failOn = ALLOCA_G + STORE_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD)
- @Test(valid = InlineTypeArrayFlattenOff, failOn = ALLOC_G + ALLOCA_G + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ counts = {ALLOC_G, "= 1", LOAD_UNKNOWN_INLINE, "= 1"},
+ failOn = {ALLOCA_G, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
+ @IR(applyIf = {"FlatArrayElementMaxSize", "!= -1"},
+ failOn = {ALLOC_G, ALLOCA_G, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
public void test83(Object[] array, Object o) {
Integer i = (Integer)array[0];
array[1] = o;
}
- @DontCompile
- public void test83_verifier(boolean warmup) {
+ @Run(test = "test83")
+ public void test83_verifier() {
Integer i = Integer.valueOf(rI);
Integer[] array1 = new Integer[2];
Object[] array2 = new Object[2];
@@ -1968,15 +1985,17 @@ public void test83_verifier(boolean warmup) {
}
// Verify that writing constant null into an array marks the array as not-null-free and not-flat
- @Test(failOn = ALLOC_G + ALLOCA_G + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE, match = { INLINE_ARRAY_NULL_GUARD }, matchCount = { 1 })
+ @Test
+ @IR(failOn = {ALLOC_G, ALLOCA_G, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE},
+ counts = {INLINE_ARRAY_NULL_GUARD, "= 1"})
public Object test84(Object[] array, int i) {
array[0] = null;
array[1] = null;
return array[i];
}
- @DontCompile
- public void test84_verifier(boolean warmup) {
+ @Run(test = "test84")
+ public void test84_verifier(RunInfo info) {
NotFlattenable.ref[] array1 = new NotFlattenable.ref[2];
Object[] array2 = new Object[2];
Object result = test84(array1, 0);
@@ -1985,7 +2004,7 @@ public void test84_verifier(boolean warmup) {
result = test84(array2, 1);
Asserts.assertEquals(array2[0], null);
Asserts.assertEquals(result, null);
- if (!warmup) {
+ if (!info.isWarmUp()) {
NotFlattenable[] array3 = new NotFlattenable[2];
try {
test84(array3, 1);
@@ -1997,7 +2016,9 @@ public void test84_verifier(boolean warmup) {
}
// Same as test84 but with branches
- @Test(failOn = ALLOC_G + ALLOCA_G + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE, match = { INLINE_ARRAY_NULL_GUARD }, matchCount = { 2 })
+ @Test
+ @IR(failOn = {ALLOC_G, ALLOCA_G, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE},
+ counts = {INLINE_ARRAY_NULL_GUARD, "= 2"})
public void test85(Object[] array, Object o, boolean b) {
if (b) {
array[0] = null;
@@ -2007,8 +2028,8 @@ public void test85(Object[] array, Object o, boolean b) {
array[1] = o;
}
- @DontCompile
- public void test85_verifier(boolean warmup) {
+ @Run(test = "test85")
+ public void test85_verifier(RunInfo info) {
Integer i = Integer.valueOf(rI);
Integer[] array1 = new Integer[2];
Object[] array2 = new Object[2];
@@ -2020,7 +2041,7 @@ public void test85_verifier(boolean warmup) {
Asserts.assertEquals(array2[1], i);
test85(array2, null, false);
Asserts.assertEquals(array2[1], null);
- if (!warmup) {
+ if (!info.isWarmUp()) {
NotFlattenable[] array3 = new NotFlattenable[2];
try {
test85(array3, null, true);
@@ -2032,7 +2053,9 @@ public void test85_verifier(boolean warmup) {
}
// Same as test85 but with not-flattenable inline type array
- @Test(failOn = ALLOC_G + ALLOCA_G + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE, match = { INLINE_ARRAY_NULL_GUARD }, matchCount = { 2 })
+ @Test
+ @IR(failOn = {ALLOC_G, ALLOCA_G, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE},
+ counts = {INLINE_ARRAY_NULL_GUARD, "= 2"})
public void test86(NotFlattenable.ref[] array, NotFlattenable.ref o, boolean b) {
if (b) {
array[0] = null;
@@ -2042,15 +2065,15 @@ public void test86(NotFlattenable.ref[] array, NotFlattenable.ref o, boolean b)
array[1] = o;
}
- @DontCompile
- public void test86_verifier(boolean warmup) {
+ @Run(test = "test86")
+ public void test86_verifier(RunInfo info) {
NotFlattenable vt = new NotFlattenable();
NotFlattenable.ref[] array1 = new NotFlattenable.ref[2];
test86(array1, vt, true);
Asserts.assertEquals(array1[1], vt);
test86(array1, null, false);
Asserts.assertEquals(array1[1], null);
- if (!warmup) {
+ if (!info.isWarmUp()) {
NotFlattenable[] array2 = new NotFlattenable[2];
try {
test86(array2, null, true);
@@ -2062,7 +2085,9 @@ public void test86_verifier(boolean warmup) {
}
// Same as test85 but with inline type array
- @Test(failOn = ALLOC_G + ALLOCA_G + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE, match = { INLINE_ARRAY_NULL_GUARD }, matchCount = { 2 })
+ @Test
+ @IR(failOn = {ALLOC_G, ALLOCA_G, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE},
+ counts = {INLINE_ARRAY_NULL_GUARD, "= 2"})
public void test87(MyValue1.ref[] array, MyValue1.ref o, boolean b) {
if (b) {
array[0] = null;
@@ -2072,15 +2097,15 @@ public void test87(MyValue1.ref[] array, MyValue1.ref o, boolean b) {
array[1] = o;
}
- @DontCompile
- public void test87_verifier(boolean warmup) {
+ @Run(test = "test87")
+ public void test87_verifier(RunInfo info) {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
MyValue1.ref[] array1 = new MyValue1.ref[2];
test87(array1, vt, true);
Asserts.assertEquals(array1[1], vt);
test87(array1, null, false);
Asserts.assertEquals(array1[1], null);
- if (!warmup) {
+ if (!info.isWarmUp()) {
MyValue1[] array2 = new MyValue1[2];
try {
test87(array2, null, true);
@@ -2097,15 +2122,15 @@ public void test88(Object[] array, Integer v) {
array[0] = v;
}
- @DontCompile
- public void test88_verifier(boolean warmup) {
+ @Run(test = "test88")
+ public void test88_verifier(RunInfo info) {
Integer[] array1 = new Integer[1];
Object[] array2 = new Object[1];
test88(array1, null);
Asserts.assertEquals(array1[0], null);
test88(array2, null);
Asserts.assertEquals(array2[0], null);
- if (!warmup) {
+ if (!info.isWarmUp()) {
MyValue1[] array3 = new MyValue1[1];
try {
test88(array3, null);
@@ -2122,12 +2147,12 @@ public void test89(MyValue1.ref[] array, Integer v) {
array[0] = (MyValue1.ref)o;
}
- @DontCompile
- public void test89_verifier(boolean warmup) {
+ @Run(test = "test89")
+ public void test89_verifier(RunInfo info) {
MyValue1.ref[] array1 = new MyValue1.ref[1];
test89(array1, null);
Asserts.assertEquals(array1[0], null);
- if (!warmup) {
+ if (!info.isWarmUp()) {
MyValue1[] array2 = new MyValue1[1];
try {
test89(array2, null);
@@ -2157,8 +2182,8 @@ public boolean test90() {
return b;
}
- @DontCompile
- public void test90_verifier(boolean warmup) {
+ @Run(test = "test90")
+ public void test90_verifier() {
Asserts.assertEQ(test90(), true);
}
@@ -2188,7 +2213,6 @@ public void verify() {
// Test anti-dependencies between loads and stores from flattened array
@Test
- @Warmup(0)
public int test91(Test91Value[] array, int lo, int val) {
int i = 3;
while (lo < i) {
@@ -2199,8 +2223,9 @@ public int test91(Test91Value[] array, int lo, int val) {
return val;
}
- @DontCompile
- public void test91_verifier(boolean warmup) {
+ @Run(test = "test91")
+ @Warmup(0)
+ public void test91_verifier() {
Test91Value[] array = new Test91Value[5];
for (int i = 0; i < 5; ++i) {
array[i] = new Test91Value(i);
@@ -2217,8 +2242,8 @@ public void test92(Object[] src, Object[] dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test92_verifier(boolean warmup) {
+ @Run(test = "test92")
+ public void test92_verifier() {
MyValue1[] a = new MyValue1[1];
MyValue1[] b = new MyValue1[1];
try {
@@ -2238,7 +2263,6 @@ public void test92_verifier(boolean warmup) {
// Same as test30 but accessing all elements of the non-escaping array
@Test
- @Warmup(10000)
public long test93(MyValue2[] src, boolean flag) {
MyValue2[] dst = new MyValue2[10];
System.arraycopy(src, 0, dst, 0, 10);
@@ -2247,13 +2271,14 @@ public long test93(MyValue2[] src, boolean flag) {
dst[5].hash() + dst[6].hash() + dst[7].hash() + dst[8].hash() + dst[9].hash();
}
- @DontCompile
- public void test93_verifier(boolean warmup) {
+ @Run(test = "test93")
+ @Warmup(10000)
+ public void test93_verifier(RunInfo info) {
MyValue2[] src = new MyValue2[10];
for (int i = 0; i < 10; ++i) {
src[i] = MyValue2.createWithFieldsInline(rI+i, rD+i);
}
- long res = test93(src, !warmup);
+ long res = test93(src, !info.isWarmUp());
long expected = 0;
for (int i = 0; i < 10; ++i) {
expected += src[i].hash();
@@ -2263,7 +2288,6 @@ public void test93_verifier(boolean warmup) {
// Same as test93 but with variable source array offset
@Test
- @Warmup(10000)
public long test94(MyValue2[] src, int i, boolean flag) {
MyValue2[] dst = new MyValue2[10];
System.arraycopy(src, i, dst, 0, 1);
@@ -2272,21 +2296,23 @@ public long test94(MyValue2[] src, int i, boolean flag) {
dst[5].hash() + dst[6].hash() + dst[7].hash() + dst[8].hash() + dst[9].hash();
}
- @DontCompile
- public void test94_verifier(boolean warmup) {
+ @Run(test = "test94")
+ @Warmup(10000)
+ public void test94_verifier(RunInfo info) {
MyValue2[] src = new MyValue2[10];
for (int i = 0; i < 10; ++i) {
src[i] = MyValue2.createWithFieldsInline(rI+i, rD+i);
}
for (int i = 0; i < 10; ++i) {
- long res = test94(src, i, !warmup);
+ long res = test94(src, i, !info.isWarmUp());
long expected = src[i].hash() + 9*MyValue2.default.hash();
Asserts.assertEQ(res, expected);
}
}
// Test propagation of not null-free/flat information
- @Test(failOn = CHECKCAST_ARRAY)
+ @Test
+ @IR(failOn = CHECKCAST_ARRAY)
public MyValue1[] test95(Object[] array) {
array[0] = null;
// Always throws a ClassCastException because we just successfully
@@ -2294,8 +2320,8 @@ public MyValue1[] test95(Object[] array) {
return (MyValue1[])array;
}
- @DontCompile
- public void test95_verifier(boolean warmup) {
+ @Run(test = "test95")
+ public void test95_verifier() {
MyValue1[] array1 = new MyValue1[1];
Integer[] array2 = new Integer[1];
try {
@@ -2313,7 +2339,8 @@ public void test95_verifier(boolean warmup) {
}
// Same as test95 but with cmp user of cast result
- @Test(failOn = CHECKCAST_ARRAY)
+ @Test
+ @IR(failOn = CHECKCAST_ARRAY)
public boolean test96(Object[] array) {
array[0] = null;
// Always throws a ClassCastException because we just successfully
@@ -2322,8 +2349,8 @@ public boolean test96(Object[] array) {
return casted != null;
}
- @DontCompile
- public void test96_verifier(boolean warmup) {
+ @Run(test = "test96")
+ public void test96_verifier() {
MyValue1[] array1 = new MyValue1[1];
Integer[] array2 = new Integer[1];
try {
@@ -2341,7 +2368,8 @@ public void test96_verifier(boolean warmup) {
}
// Same as test95 but with instanceof instead of cast
- @Test(failOn = CHECKCAST_ARRAY)
+ @Test
+ @IR(failOn = CHECKCAST_ARRAY)
public boolean test97(Object[] array) {
array[0] = 42;
// Always throws a ClassCastException because we just successfully stored
@@ -2349,8 +2377,8 @@ public boolean test97(Object[] array) {
return array instanceof MyValue1[];
}
- @DontCompile
- public void test97_verifier(boolean warmup) {
+ @Run(test = "test97")
+ public void test97_verifier() {
MyValue1[] array1 = new MyValue1[1];
Integer[] array2 = new Integer[1];
try {
@@ -2364,8 +2392,9 @@ public void test97_verifier(boolean warmup) {
}
// Same as test95 but with non-flattenable store
- @Test(valid = InlineTypeArrayFlattenOn, failOn = CHECKCAST_ARRAY)
- @Test(valid = InlineTypeArrayFlattenOff)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ failOn = CHECKCAST_ARRAY)
public MyValue1[] test98(Object[] array) {
array[0] = NotFlattenable.default;
// Always throws a ClassCastException because we just successfully stored a
@@ -2373,8 +2402,8 @@ public MyValue1[] test98(Object[] array) {
return (MyValue1[])array;
}
- @DontCompile
- public void test98_verifier(boolean warmup) {
+ @Run(test = "test98")
+ public void test98_verifier() {
MyValue1[] array1 = new MyValue1[1];
NotFlattenable[] array2 = new NotFlattenable[1];
try {
@@ -2392,8 +2421,9 @@ public void test98_verifier(boolean warmup) {
}
// Same as test98 but with cmp user of cast result
- @Test(valid = InlineTypeArrayFlattenOn, failOn = CHECKCAST_ARRAY)
- @Test(valid = InlineTypeArrayFlattenOff)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ failOn = CHECKCAST_ARRAY)
public boolean test99(Object[] array) {
array[0] = NotFlattenable.default;
// Always throws a ClassCastException because we just successfully stored a
@@ -2402,8 +2432,8 @@ public boolean test99(Object[] array) {
return casted != null;
}
- @DontCompile
- public void test99_verifier(boolean warmup) {
+ @Run(test = "test99")
+ public void test99_verifier() {
MyValue1[] array1 = new MyValue1[1];
NotFlattenable[] array2 = new NotFlattenable[1];
try {
@@ -2421,8 +2451,9 @@ public void test99_verifier(boolean warmup) {
}
// Same as test98 but with instanceof instead of cast
- @Test(valid = InlineTypeArrayFlattenOn, failOn = CHECKCAST_ARRAY)
- @Test(valid = InlineTypeArrayFlattenOff)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ failOn = CHECKCAST_ARRAY)
public boolean test100(Object[] array) {
array[0] = NotFlattenable.default;
// Always throws a ClassCastException because we just successfully stored a
@@ -2430,8 +2461,8 @@ public boolean test100(Object[] array) {
return array instanceof MyValue1[];
}
- @DontCompile
- public void test100_verifier(boolean warmup) {
+ @Run(test = "test100")
+ public void test100_verifier() {
MyValue1[] array1 = new MyValue1[1];
NotFlattenable[] array2 = new NotFlattenable[1];
try {
@@ -2445,13 +2476,14 @@ public void test100_verifier(boolean warmup) {
}
// Test that CHECKCAST_ARRAY matching works as expected
- @Test(match = { CHECKCAST_ARRAY }, matchCount = { 1 })
+ @Test
+ @IR(counts = { CHECKCAST_ARRAY, "= 1" })
public boolean test101(Object[] array) {
return array instanceof MyValue1[];
}
- @DontCompile
- public void test101_verifier(boolean warmup) {
+ @Run(test = "test101")
+ public void test101_verifier() {
MyValue1[] array1 = new MyValue1[1];
NotFlattenable[] array2 = new NotFlattenable[1];
Asserts.assertTrue(test101(array1));
@@ -2483,62 +2515,69 @@ public void test101_verifier(boolean warmup) {
}
// Arraycopy with constant source and destination arrays
- @Test(valid = InlineTypeArrayFlattenOn, match = { INTRINSIC_SLOW_PATH }, matchCount = { 1 })
- @Test(valid = InlineTypeArrayFlattenOff, failOn = INTRINSIC_SLOW_PATH)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ counts = {INTRINSIC_SLOW_PATH, "= 1"})
+ @IR(applyIf = {"FlatArrayElementMaxSize", "!= -1"},
+ failOn = INTRINSIC_SLOW_PATH)
public void test102() {
System.arraycopy(val_src, 0, obj_dst, 0, 8);
}
- @DontCompile
- public void test102_verifier(boolean warmup) {
+ @Run(test = "test102")
+ public void test102_verifier() {
test102();
verify(val_src, obj_dst);
}
// Same as test102 but with MyValue2[] dst
- @Test(failOn = INTRINSIC_SLOW_PATH)
+ @Test
+ @IR(failOn = INTRINSIC_SLOW_PATH)
public void test103() {
System.arraycopy(val_src, 0, val_dst, 0, 8);
}
- @DontCompile
- public void test103_verifier(boolean warmup) {
+ @Run(test = "test103")
+ public void test103_verifier() {
test103();
verify(val_src, val_dst);
}
// Same as test102 but with Object[] src
- @Test(failOn = INTRINSIC_SLOW_PATH)
+ @Test
+ @IR(failOn = INTRINSIC_SLOW_PATH)
public void test104() {
System.arraycopy(obj_src, 0, obj_dst, 0, 8);
}
- @DontCompile
- public void test104_verifier(boolean warmup) {
+ @Run(test = "test104")
+ public void test104_verifier() {
test104();
verify(obj_src, obj_dst);
}
// Same as test103 but with Object[] src
- @Test(match = { INTRINSIC_SLOW_PATH }, matchCount = { 1 })
+ @Test
+ @IR(counts = {INTRINSIC_SLOW_PATH, "= 1"})
public void test105() {
System.arraycopy(obj_src, 0, val_dst, 0, 8);
}
- @DontCompile
- public void test105_verifier(boolean warmup) {
+ @Run(test = "test105")
+ public void test105_verifier() {
test105();
verify(obj_src, val_dst);
}
// Same as test103 but with Object[] src containing null
- @Test(match = { INTRINSIC_SLOW_PATH }, matchCount = { 1 })
+ @Test
+ @IR(counts = {INTRINSIC_SLOW_PATH, "= 1"})
public void test105_null() {
System.arraycopy(obj_null_src, 0, val_dst, 0, 8);
}
- @DontCompile
- public void test105_null_verifier(boolean warmup) {
+ @Run(test = "test105_null")
+ public void test105_null_verifier() {
try {
test105_null();
throw new RuntimeException("NullPointerException expected");
@@ -2549,62 +2588,68 @@ public void test105_null_verifier(boolean warmup) {
// Below tests are equal to test102-test105 but hide the src/dst types until
// after the arraycopy intrinsic is emitted (with incremental inlining).
-
- @Test(valid = InlineTypeArrayFlattenOn, match = { INTRINSIC_SLOW_PATH }, matchCount = { 1 })
- @Test(valid = InlineTypeArrayFlattenOff, failOn = INTRINSIC_SLOW_PATH)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ counts = {INTRINSIC_SLOW_PATH, "= 1"})
+ @IR(applyIf = {"FlatArrayElementMaxSize", "!= -1"},
+ failOn = INTRINSIC_SLOW_PATH)
public void test106() {
System.arraycopy(get_val_src(), 0, get_obj_dst(), 0, 8);
}
- @DontCompile
- public void test106_verifier(boolean warmup) {
+ @Run(test = "test106")
+ public void test106_verifier() {
test106();
verify(val_src, obj_dst);
}
// TODO 8251971: Should be optimized but we are bailing out because
// at parse time it looks as if src could be flat and dst could be not flat.
- @Test(valid = InlineTypeArrayFlattenOn)
- @Test(valid = InlineTypeArrayFlattenOff, failOn = INTRINSIC_SLOW_PATH)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "!= -1"},
+ failOn = INTRINSIC_SLOW_PATH)
public void test107() {
System.arraycopy(get_val_src(), 0, get_val_dst(), 0, 8);
}
- @DontCompile
- public void test107_verifier(boolean warmup) {
+ @Run(test = "test107")
+ public void test107_verifier() {
test107();
verify(val_src, val_dst);
}
- @Test(failOn = INTRINSIC_SLOW_PATH)
+ @Test
+ @IR(failOn = INTRINSIC_SLOW_PATH)
public void test108() {
System.arraycopy(get_obj_src(), 0, get_obj_dst(), 0, 8);
}
- @DontCompile
- public void test108_verifier(boolean warmup) {
+ @Run(test = "test108")
+ public void test108_verifier() {
test108();
verify(obj_src, obj_dst);
}
- @Test(match = { INTRINSIC_SLOW_PATH }, matchCount = { 1 })
+ @Test
+ @IR(counts = {INTRINSIC_SLOW_PATH, "= 1"})
public void test109() {
System.arraycopy(get_obj_src(), 0, get_val_dst(), 0, 8);
}
- @DontCompile
- public void test109_verifier(boolean warmup) {
+ @Run(test = "test109")
+ public void test109_verifier() {
test109();
verify(obj_src, val_dst);
}
- @Test(match = { INTRINSIC_SLOW_PATH }, matchCount = { 1 })
+ @Test
+ @IR(counts = {INTRINSIC_SLOW_PATH, "= 1"})
public void test109_null() {
System.arraycopy(get_obj_null_src(), 0, get_val_dst(), 0, 8);
}
- @DontCompile
- public void test109_null_verifier(boolean warmup) {
+ @Run(test = "test109_null")
+ public void test109_null_verifier() {
try {
test109_null();
throw new RuntimeException("NullPointerException expected");
@@ -2614,62 +2659,69 @@ public void test109_null_verifier(boolean warmup) {
}
// Arrays.copyOf with constant source and destination arrays
- @Test(valid = InlineTypeArrayFlattenOn, match = { INTRINSIC_SLOW_PATH }, matchCount = { 1 })
- @Test(valid = InlineTypeArrayFlattenOff, failOn = INTRINSIC_SLOW_PATH + CLASS_CHECK_TRAP)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ counts = {INTRINSIC_SLOW_PATH, "= 1"})
+ @IR(applyIf = {"FlatArrayElementMaxSize", "!= -1"},
+ failOn = {INTRINSIC_SLOW_PATH, CLASS_CHECK_TRAP})
public Object[] test110() {
return Arrays.copyOf(val_src, 8, Object[].class);
}
- @DontCompile
- public void test110_verifier(boolean warmup) {
+ @Run(test = "test110")
+ public void test110_verifier() {
Object[] res = test110();
verify(val_src, res);
}
// Same as test110 but with MyValue2[] dst
- @Test(failOn = INTRINSIC_SLOW_PATH + CLASS_CHECK_TRAP)
+ @Test
+ @IR(failOn = {INTRINSIC_SLOW_PATH, CLASS_CHECK_TRAP})
public Object[] test111() {
return Arrays.copyOf(val_src, 8, MyValue2[].class);
}
- @DontCompile
- public void test111_verifier(boolean warmup) {
+ @Run(test = "test111")
+ public void test111_verifier() {
Object[] res = test111();
verify(val_src, res);
}
// Same as test110 but with Object[] src
- @Test(failOn = INTRINSIC_SLOW_PATH + CLASS_CHECK_TRAP)
+ @Test
+ @IR(failOn = {INTRINSIC_SLOW_PATH, CLASS_CHECK_TRAP})
public Object[] test112() {
return Arrays.copyOf(obj_src, 8, Object[].class);
}
- @DontCompile
- public void test112_verifier(boolean warmup) {
+ @Run(test = "test112")
+ public void test112_verifier() {
Object[] res = test112();
verify(obj_src, res);
}
// Same as test111 but with Object[] src
- @Test(match = { INTRINSIC_SLOW_PATH + CLASS_CHECK_TRAP }, matchCount = { 1 })
+ @Test
+ @IR(counts = {INTRINSIC_SLOW_PATH + "|" + CLASS_CHECK_TRAP, " = 1"})
public Object[] test113() {
return Arrays.copyOf(obj_src, 8, MyValue2[].class);
}
- @DontCompile
- public void test113_verifier(boolean warmup) {
+ @Run(test = "test113")
+ public void test113_verifier() {
Object[] res = test113();
verify(obj_src, res);
}
// Same as test111 but with Object[] src containing null
- @Test(match = { INTRINSIC_SLOW_PATH + CLASS_CHECK_TRAP }, matchCount = { 1 })
+ @Test
+ @IR(counts = {INTRINSIC_SLOW_PATH + "|" + CLASS_CHECK_TRAP, " = 1"})
public Object[] test113_null() {
return Arrays.copyOf(obj_null_src, 8, MyValue2[].class);
}
- @DontCompile
- public void test113_null_verifier(boolean warmup) {
+ @Run(test = "test113_null")
+ public void test113_null_verifier() {
try {
test113_null();
throw new RuntimeException("NullPointerException expected");
@@ -2681,61 +2733,68 @@ public void test113_null_verifier(boolean warmup) {
// Below tests are equal to test110-test113 but hide the src/dst types until
// after the arraycopy intrinsic is emitted (with incremental inlining).
- @Test(valid = InlineTypeArrayFlattenOn, match = { INTRINSIC_SLOW_PATH }, matchCount = { 1 })
- @Test(valid = InlineTypeArrayFlattenOff, failOn = INTRINSIC_SLOW_PATH + CLASS_CHECK_TRAP)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ counts = {INTRINSIC_SLOW_PATH, "= 1"})
+ @IR(applyIf = {"FlatArrayElementMaxSize", "!= -1"},
+ failOn = {INTRINSIC_SLOW_PATH, CLASS_CHECK_TRAP})
public Object[] test114() {
return Arrays.copyOf((Object[])get_val_src(), 8, get_obj_class());
}
- @DontCompile
- public void test114_verifier(boolean warmup) {
+ @Run(test = "test114")
+ public void test114_verifier() {
Object[] res = test114();
verify(val_src, res);
}
// TODO 8251971: Should be optimized but we are bailing out because
// at parse time it looks as if src could be flat and dst could be not flat
- @Test(valid = InlineTypeArrayFlattenOn)
- @Test(valid = InlineTypeArrayFlattenOff, failOn = INTRINSIC_SLOW_PATH + CLASS_CHECK_TRAP)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "!= -1"},
+ failOn = {INTRINSIC_SLOW_PATH, CLASS_CHECK_TRAP})
public Object[] test115() {
return Arrays.copyOf((Object[])get_val_src(), 8, get_val_class());
}
- @DontCompile
- public void test115_verifier(boolean warmup) {
+ @Run(test = "test115")
+ public void test115_verifier() {
Object[] res = test115();
verify(val_src, res);
}
- @Test(failOn = INTRINSIC_SLOW_PATH + CLASS_CHECK_TRAP)
+ @Test
+ @IR(failOn = {INTRINSIC_SLOW_PATH, CLASS_CHECK_TRAP})
public Object[] test116() {
return Arrays.copyOf((Object[])get_obj_src(), 8, get_obj_class());
}
- @DontCompile
- public void test116_verifier(boolean warmup) {
+ @Run(test = "test116")
+ public void test116_verifier() {
Object[] res = test116();
verify(obj_src, res);
}
- @Test(match = { INTRINSIC_SLOW_PATH + CLASS_CHECK_TRAP }, matchCount = { 1 })
+ @Test
+ @IR(counts = {INTRINSIC_SLOW_PATH + "|" + CLASS_CHECK_TRAP, " = 1"})
public Object[] test117() {
return Arrays.copyOf((Object[])get_obj_src(), 8, get_val_class());
}
- @DontCompile
- public void test117_verifier(boolean warmup) {
+ @Run(test = "test117")
+ public void test117_verifier() {
Object[] res = test117();
verify(obj_src, res);
}
- @Test(match = { INTRINSIC_SLOW_PATH + CLASS_CHECK_TRAP }, matchCount = { 1 })
+ @Test
+ @IR(counts = {INTRINSIC_SLOW_PATH + "|" + CLASS_CHECK_TRAP, " = 1"})
public Object[] test117_null() {
return Arrays.copyOf((Object[])get_obj_null_src(), 8, get_val_class());
}
- @DontCompile
- public void test117_null_verifier(boolean warmup) {
+ @Run(test = "test117_null")
+ public void test117_null_verifier() {
try {
test117_null();
throw new RuntimeException("NullPointerException expected");
@@ -2746,13 +2805,15 @@ public void test117_null_verifier(boolean warmup) {
// Some more Arrays.copyOf tests with only constant class
- @Test(match = { CLASS_CHECK_TRAP }, matchCount = { 1 }, failOn = INTRINSIC_SLOW_PATH)
+ @Test
+ @IR(counts = {CLASS_CHECK_TRAP, "= 1"},
+ failOn = INTRINSIC_SLOW_PATH)
public Object[] test118(Object[] src) {
return Arrays.copyOf(src, 8, MyValue2[].class);
}
- @DontCompile
- public void test118_verifier(boolean warmup) {
+ @Run(test = "test118")
+ public void test118_verifier() {
Object[] res = test118(obj_src);
verify(obj_src, res);
res = test118(val_src);
@@ -2770,21 +2831,23 @@ public Object[] test119(Object[] src) {
return Arrays.copyOf(src, 8, Object[].class);
}
- @DontCompile
- public void test119_verifier(boolean warmup) {
+ @Run(test = "test119")
+ public void test119_verifier() {
Object[] res = test119(obj_src);
verify(obj_src, res);
res = test119(val_src);
verify(val_src, res);
}
- @Test(match = { CLASS_CHECK_TRAP }, matchCount = { 1 }, failOn = INTRINSIC_SLOW_PATH)
+ @Test
+ @IR(counts = {CLASS_CHECK_TRAP, "= 1"},
+ failOn = INTRINSIC_SLOW_PATH)
public Object[] test120(Object[] src) {
return Arrays.copyOf(src, 8, Integer[].class);
}
- @DontCompile
- public void test120_verifier(boolean warmup) {
+ @Run(test = "test120")
+ public void test120_verifier() {
Integer[] arr = new Integer[8];
for (int i = 0; i < 8; ++i) {
arr[i] = rI + i;
@@ -2800,13 +2863,13 @@ public void test120_verifier(boolean warmup) {
}
@Test
- @Warmup(10000) // Make sure we hit too_many_traps for the src <: dst check
public Object[] test121(Object[] src) {
return Arrays.copyOf(src, 8, MyValue2[].class);
}
- @DontCompile
- public void test121_verifier(boolean warmup) {
+ @Run(test = "test121")
+ @Warmup(10000) // Make sure we hit too_many_traps for the src <: dst check
+ public void test121_verifier() {
Object[] res = test121(obj_src);
verify(obj_src, res);
res = test121(val_src);
@@ -2820,13 +2883,13 @@ public void test121_verifier(boolean warmup) {
}
@Test
- @Warmup(10000) // Make sure we hit too_many_traps for the src <: dst check
public Object[] test122(Object[] src) {
return Arrays.copyOf(src, 8, get_val_class());
}
- @DontCompile
- public void test122_verifier(boolean warmup) {
+ @Run(test = "test122")
+ @Warmup(10000) // Make sure we hit too_many_traps for the src <: dst check
+ public void test122_verifier() {
Object[] res = test122(obj_src);
verify(obj_src, res);
res = test122(val_src);
@@ -2840,13 +2903,13 @@ public void test122_verifier(boolean warmup) {
}
@Test
- @Warmup(10000) // Make sure we hit too_many_traps for the src <: dst check
public Object[] test123(Object[] src) {
return Arrays.copyOf(src, 8, Integer[].class);
}
- @DontCompile
- public void test123_verifier(boolean warmup) {
+ @Run(test = "test123")
+ @Warmup(10000) // Make sure we hit too_many_traps for the src <: dst check
+ public void test123_verifier() {
Integer[] arr = new Integer[8];
for (int i = 0; i < 8; ++i) {
arr[i] = rI + i;
@@ -2862,13 +2925,13 @@ public void test123_verifier(boolean warmup) {
}
@Test
- @Warmup(10000) // Make sure we hit too_many_traps for the src <: dst check
public Object[] test124(Object[] src) {
return Arrays.copyOf(src, 8, get_int_class());
}
- @DontCompile
- public void test124_verifier(boolean warmup) {
+ @Run(test = "test124")
+ @Warmup(10000) // Make sure we hit too_many_traps for the src <: dst check
+ public void test124_verifier() {
Integer[] arr = new Integer[8];
for (int i = 0; i < 8; ++i) {
arr[i] = rI + i;
@@ -2884,13 +2947,13 @@ public void test124_verifier(boolean warmup) {
}
@Test
- @Warmup(10000) // Make sure we hit too_many_traps for the src <: dst check
public Object[] test125(Object[] src, Class klass) {
return Arrays.copyOf(src, 8, klass);
}
- @DontCompile
- public void test125_verifier(boolean warmup) {
+ @Run(test = "test125")
+ @Warmup(10000) // Make sure we hit too_many_traps for the src <: dst check
+ public void test125_verifier() {
Integer[] arr = new Integer[8];
for (int i = 0; i < 8; ++i) {
arr[i] = rI + i;
@@ -2921,15 +2984,20 @@ public void test125_verifier(boolean warmup) {
}
}
+
// Verify that clone from (flat) inline type array not containing oops is always optimized.
- @Test(valid = InlineTypeArrayFlattenOn, match = { JLONG_ARRAYCOPY }, matchCount = { 1 }, failOn = CHECKCAST_ARRAYCOPY + CLONE_INTRINSIC_SLOW_PATH)
- @Test(valid = InlineTypeArrayFlattenOff, failOn = CLONE_INTRINSIC_SLOW_PATH)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ counts = {JLONG_ARRAYCOPY, "= 1"},
+ failOn = {CHECKCAST_ARRAYCOPY, CLONE_INTRINSIC_SLOW_PATH})
+ @IR(applyIf = {"FlatArrayElementMaxSize", "!= -1"},
+ failOn = CLONE_INTRINSIC_SLOW_PATH)
public Object[] test126(MyValue2[] src) {
return src.clone();
}
- @DontCompile
- public void test126_verifier(boolean warmup) {
+ @Run(test = "test126")
+ public void test126_verifier() {
Object[] res = test126(val_src);
verify(val_src, res);
}
@@ -2940,8 +3008,8 @@ public void test127(Object src, Object dst, int len) {
System.arraycopy(src, 0, dst, 0, len);
}
- @DontCompile
- public void test127_verifier(boolean warmup) {
+ @Run(test = "test127")
+ public void test127_verifier() {
test127(val_src, obj_dst, 8);
verify(val_src, obj_dst);
test127(val_src, val_dst, 8);
@@ -2957,14 +3025,16 @@ public void test127_verifier(boolean warmup) {
}
// Verify that copyOf with known source and unknown destination class is optimized
- @Test(valid = InlineTypeArrayFlattenOn, match = { JLONG_ARRAYCOPY }, matchCount = { 1 }, failOn = CHECKCAST_ARRAYCOPY)
- @Test(valid = InlineTypeArrayFlattenOff)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ counts = {JLONG_ARRAYCOPY, "= 1"},
+ failOn = CHECKCAST_ARRAYCOPY)
public Object[] test128(MyValue2[] src, Class klass) {
return Arrays.copyOf(src, 8, klass);
}
- @DontCompile
- public void test128_verifier(boolean warmup) {
+ @Run(test = "test128")
+ public void test128_verifier() {
Object[] res = test128(val_src, MyValue2[].class);
verify(val_src, res);
res = test128(val_src, Object[].class);
@@ -2983,8 +3053,8 @@ public void test129(Object src, Object dst, int len) {
System.arraycopy(src, 0, dst, 0, len);
}
- @DontCompile
- public void test129_verifier(boolean warmup) {
+ @Run(test = "test129")
+ public void test129_verifier() {
try {
test129(new Object(), new Object[0], 0);
throw new RuntimeException("ArrayStoreException expected");
@@ -3000,14 +3070,15 @@ public void test129_verifier(boolean warmup) {
}
// Empty inline type array access
- @Test(failOn = ALLOC + ALLOCA + LOAD + STORE)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOAD, STORE})
public MyValueEmpty test130(MyValueEmpty[] array) {
array[0] = new MyValueEmpty();
return array[1];
}
- @DontCompile
- public void test130_verifier(boolean warmup) {
+ @Run(test = "test130")
+ public void test130_verifier() {
MyValueEmpty[] array = new MyValueEmpty[2];
MyValueEmpty empty = test130(array);
Asserts.assertEquals(array[0], MyValueEmpty.default);
@@ -3019,14 +3090,15 @@ static primitive class EmptyContainer {
}
// Empty inline type container array access
- @Test(failOn = ALLOC + ALLOCA + LOAD + STORE)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOAD, STORE})
public MyValueEmpty test131(EmptyContainer[] array) {
array[0] = new EmptyContainer();
return array[1].empty;
}
- @DontCompile
- public void test131_verifier(boolean warmup) {
+ @Run(test = "test131")
+ public void test131_verifier() {
EmptyContainer[] array = new EmptyContainer[2];
MyValueEmpty empty = test131(array);
Asserts.assertEquals(array[0], EmptyContainer.default);
@@ -3040,8 +3112,8 @@ public Object test132(Object[] array) {
return array[1];
}
- @DontCompile
- public void test132_verifier(boolean warmup) {
+ @Run(test = "test132")
+ public void test132_verifier() {
Object[] array = new MyValueEmpty[2];
Object empty = test132(array);
Asserts.assertEquals(array[0], MyValueEmpty.default);
@@ -3059,8 +3131,8 @@ public Object test133(Object[] array) {
return array[1];
}
- @DontCompile
- public void test133_verifier(boolean warmup) {
+ @Run(test = "test133")
+ public void test133_verifier() {
Object[] array = new EmptyContainer[2];
Object empty = test133(array);
Asserts.assertEquals(array[0], EmptyContainer.default);
@@ -3072,15 +3144,16 @@ public void test133_verifier(boolean warmup) {
}
// Non-escaping empty inline type array access
- @Test(failOn = ALLOC + ALLOCA + LOAD + STORE)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOAD, STORE})
public static MyValueEmpty test134(MyValueEmpty val) {
MyValueEmpty[] array = new MyValueEmpty[1];
array[0] = val;
return array[0];
}
- @DontCompile
- public void test134_verifier(boolean warmup) {
+ @Run(test = "test134")
+ public void test134_verifier() {
MyValueEmpty empty = test134(MyValueEmpty.default);
Asserts.assertEquals(empty, MyValueEmpty.default);
}
@@ -3092,8 +3165,8 @@ public Object test135(Object[] array, Object val) {
return array[1];
}
- @DontCompile
- public void test135_verifier(boolean warmup) {
+ @Run(test = "test135")
+ public void test135_verifier() {
MyValue1[] array1 = new MyValue1[2];
array1[1] = MyValue1.createWithFieldsInline(rI, rL);
synchronized (array1) {
@@ -3121,8 +3194,8 @@ public Object test136(Object[] array, Object val) {
return res;
}
- @DontCompile
- public void test136_verifier(boolean warmup) {
+ @Run(test = "test136")
+ public void test136_verifier() {
MyValue1[] array1 = new MyValue1[2];
array1[1] = MyValue1.createWithFieldsInline(rI, rL);
Object res = test136(array1, array1[1]);
@@ -3146,8 +3219,8 @@ public void test137(Object[] array1, Object[] array2) {
}
}
- @DontCompile
- public void test137_verifier(boolean warmup) {
+ @Run(test = "test137")
+ public void test137_verifier() {
MyValue1[] array1 = new MyValue1[100];
Arrays.fill(array1, MyValue1.createWithFieldsInline(rI, rL));
Integer[] array2 = new Integer[100];
@@ -3189,8 +3262,8 @@ public void test138(Object[] array1, Object[] array2) {
}
}
- @DontCompile
- public void test138_verifier(boolean warmup) {
+ @Run(test = "test138")
+ public void test138_verifier() {
MyValue1[] array1 = new MyValue1[100];
Arrays.fill(array1, MyValue1.createWithFieldsInline(rI, rL));
Integer[] array2 = new Integer[100];
@@ -3211,7 +3284,9 @@ public void test138_verifier(boolean warmup) {
}
// Test load from array that is only known to be non-inline after parsing
- @Test(failOn = ALLOC + ALLOCA + ALLOC_G + ALLOCA_G + LOOP + LOAD + STORE + TRAP + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, ALLOC_G, ALLOCA_G, LOOP, LOAD, STORE, TRAP, LOAD_UNKNOWN_INLINE,
+ STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
public Object test139() {
Object[] array = null;
Object[] iarray = new Integer[1];
@@ -3223,14 +3298,16 @@ public Object test139() {
return array[0];
}
- @DontCompile
- public void test139_verifier(boolean warmup) {
+ @Run(test = "test139")
+ public void test139_verifier() {
Object res = test139();
Asserts.assertEquals(res, null);
}
// Test store to array that is only known to be non-inline after parsing
- @Test(failOn = ALLOC + ALLOCA + ALLOC_G + LOOP + LOAD + STORE + TRAP + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, ALLOC_G, LOOP, LOAD, STORE, TRAP,
+ LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
public Object[] test140(Object val) {
Object[] array = null;
Object[] iarray = new Integer[1];
@@ -3243,8 +3320,8 @@ public Object[] test140(Object val) {
return array;
}
- @DontCompile
- public void test140_verifier(boolean warmup) {
+ @Run(test = "test140")
+ public void test140_verifier() {
Object[] res = test140(rI);
Asserts.assertEquals(res[0], rI);
res = test140(null);
@@ -3253,8 +3330,8 @@ public void test140_verifier(boolean warmup) {
// Test load from array that is only known to be inline after parsing
// TODO 8255938
- // @Test(failOn = ALLOC + ALLOCA + ALLOC_G + ALLOCA_G + LOOP + LOAD + STORE + TRAP + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD)
@Test
+ // @IR(failOn = {ALLOC, ALLOCA, ALLOC_G, ALLOCA_G, LOOP, LOAD, STORE, TRAP, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
public Object test141() {
Object[] array = null;
Object[] iarray = new Integer[1];
@@ -3266,16 +3343,16 @@ public Object test141() {
return array[0];
}
- @DontCompile
- public void test141_verifier(boolean warmup) {
+ @Run(test = "test141")
+ public void test141_verifier() {
Object res = test141();
Asserts.assertEquals(res, MyValue1.default);
}
// Test store to array that is only known to be inline after parsing
// TODO 8255938
- // @Test(failOn = ALLOC + ALLOCA + ALLOC_G + LOOP + LOAD + STORE + TRAP + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD)
@Test
+ // @IR(failOn = {ALLOC, ALLOCA, ALLOC_G, LOOP, LOAD, STORE, TRAP, LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
public Object[] test142(Object val) {
Object[] array = null;
Object[] iarray = new Integer[1];
@@ -3288,11 +3365,11 @@ public Object[] test142(Object val) {
return array;
}
- @DontCompile
- public void test142_verifier(boolean warmup) {
+ @Run(test = "test142")
+ public void test142_verifier(RunInfo info) {
Object[] res = test142(MyValue1.default);
Asserts.assertEquals(res[0], MyValue1.default);
- if (!warmup) {
+ if (!info.isWarmUp()) {
try {
test142(null);
throw new RuntimeException("Should throw NullPointerException");
@@ -3317,7 +3394,6 @@ static class MyObject143 implements MyInterface143 {
// Test that triggers an anti dependency failure when array mark word is loaded from immutable memory
@Test
- @Warmup(0)
public void test143() {
MyInterface143[] arr = array143;
int tmp = arr.length;
@@ -3328,14 +3404,14 @@ public void test143() {
}
}
- @DontCompile
- public void test143_verifier(boolean warmup) {
+ @Run(test = "test143")
+ @Warmup(0)
+ public void test143_verifier() {
test143();
}
// Same as test143 but with two flat array checks that are unswitched
@Test
- @Warmup(0)
public void test144() {
MyInterface143[] arr1 = array143;
MyInterface143[] arr2 = array143;
@@ -3348,8 +3424,9 @@ public void test144() {
}
}
- @DontCompile
- public void test144_verifier(boolean warmup) {
+ @Run(test = "test144")
+ @Warmup(0)
+ public void test144_verifier() {
test144();
}
@@ -3359,16 +3436,16 @@ public Object test145(Object[] array) {
return array[0];
}
- @DontCompile
- public void test145_verifier(boolean warmup) {
+ @Run(test = "test145")
+ public void test145_verifier() {
Object[] array = new EmptyContainer[1];
EmptyContainer empty = (EmptyContainer)test145(array);
Asserts.assertEquals(empty, EmptyContainer.default);
}
// Test that non-flattened array does not block inline type scalarization
- @Test(failOn = ALLOC + ALLOCA + LOOP + LOAD + STORE)
- @Warmup(50000)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOOP, LOAD, STORE})
public void test146(boolean b) {
MyValue2 vt = MyValue2.createWithFieldsInline(rI, rD);
MyValue2[] array = { vt };
@@ -3381,14 +3458,15 @@ public void test146(boolean b) {
}
}
- @DontCompile
- public void test146_verifier(boolean warmup) {
+ @Run(test = "test146")
+ @Warmup(50000)
+ public void test146_verifier() {
test146(true);
}
// Test that non-flattened array does not block inline type scalarization
- @Test(failOn = ALLOC + ALLOCA + LOOP + LOAD + STORE)
- @Warmup(50000)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOOP, LOAD, STORE})
public int test147(boolean deopt) {
// Both vt and array should be scalarized
MyValue2 vt = MyValue2.createWithFieldsInline(rI, rD);
@@ -3412,9 +3490,10 @@ public int test147(boolean deopt) {
return array[0].x;
}
- @DontCompile
- public void test147_verifier(boolean warmup) {
- int res = test147(!warmup);
- Asserts.assertEquals(res, MyValue2.createWithFieldsInline(rI, rD).x + (warmup ? 0 : 42));
+ @Run(test = "test147")
+ @Warmup(50000)
+ public void test147_verifier(RunInfo info) {
+ int res = test147(!info.isWarmUp());
+ Asserts.assertEquals(res, MyValue2.createWithFieldsInline(rI, rD).x + (info.isWarmUp() ? 0 : 42));
}
}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java
index 1c9e7288406..505ccb14224 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 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,39 +23,44 @@
package compiler.valhalla.inlinetypes;
+import compiler.lib.ir_framework.*;
import jdk.test.lib.Asserts;
+import java.lang.reflect.Method;
+
+import static compiler.valhalla.inlinetypes.InlineTypes.IRNode.*;
+import static compiler.valhalla.inlinetypes.InlineTypes.*;
+
/*
* @test
* @key randomness
* @summary Test the basic inline type implementation in C2
- * @library /testlibrary /test/lib /compiler/whitebox /
+ *
* @requires os.simpleArch == "x64"
- * @compile TestBasicFunctionality.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestBasicFunctionality
+ * @library /test/lib /
+ * @compile InlineTypes.java
+ * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestBasicFunctionality
*/
-public class TestBasicFunctionality extends InlineTypeTest {
- // Extra VM parameters for some test scenarios. See InlineTypeTest.getVMParameters()
- @Override
- public String[] getExtraVMParameters(int scenario) {
- switch (scenario) {
- case 2: return new String[] {"-DVerifyIR=false"};
- case 3: return new String[] {"-XX:FlatArrayElementMaxSize=0"};
- }
- return null;
- }
- public static void main(String[] args) throws Throwable {
- TestBasicFunctionality test = new TestBasicFunctionality();
- test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class, MyValue3.class, MyValue3Inline.class);
+@ForceCompileClassInitializer
+public class TestBasicFunctionality {
+
+ public static void main(String[] args) {
+ Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS;
+ scenarios[2].addFlags("-DVerifyIR=false");
+ scenarios[3].addFlags("-XX:FlatArrayElementMaxSize=0");
+
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .addHelperClasses(MyValue1.class,
+ MyValue2.class,
+ MyValue2Inline.class,
+ MyValue3.class,
+ MyValue3Inline.class)
+ .start();
}
// Helper methods
-
protected long hash() {
return hash(rI, rL);
}
@@ -64,41 +69,50 @@ protected long hash(int x, long y) {
return MyValue1.createWithFieldsInline(x, y).hash();
}
+
// Receive inline type through call to interpreter
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test1() {
MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
return v.hash();
}
- @DontCompile
- public void test1_verifier(boolean warmup) {
+ @Run(test = "test1")
+ public void test1_verifier() {
long result = test1();
Asserts.assertEQ(result, hash());
}
+
// Receive inline type from interpreter via parameter
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test2(MyValue1 v) {
return v.hash();
}
- @DontCompile
- public void test2_verifier(boolean warmup) {
+ @Run(test = "test2")
+ public void test2_verifier() {
MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
long result = test2(v);
Asserts.assertEQ(result, hash());
}
+
// Return incoming inline type without accessing fields
- @Test(valid = InlineTypePassFieldsAsArgsOn, match = {ALLOC, STORE}, matchCount = {1, 14}, failOn = LOAD + TRAP)
- @Test(valid = InlineTypePassFieldsAsArgsOff, failOn = ALLOC + LOAD + STORE + TRAP)
+ @Test
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "true"},
+ counts = {ALLOC, "= 1", STORE, "= 14"},
+ failOn = {LOAD, TRAP})
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "false"},
+ failOn = {ALLOC, LOAD, STORE, TRAP})
public MyValue1 test3(MyValue1 v) {
return v;
}
- @DontCompile
- public void test3_verifier(boolean warmup) {
+ @Run(test = "test3")
+ public void test3_verifier() {
MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL);
MyValue1 v2 = test3(v1);
Asserts.assertEQ(v1.x, v2.x);
@@ -107,21 +121,23 @@ public void test3_verifier(boolean warmup) {
// Create an inline type in compiled code and only use fields.
// Allocation should go away because inline type does not escape.
- @Test(failOn = ALLOC + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
public long test4() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
return v.hash();
}
- @DontCompile
- public void test4_verifier(boolean warmup) {
+ @Run(test = "test4")
+ public void test4_verifier() {
long result = test4();
Asserts.assertEQ(result, hash());
}
// Create an inline type in compiled code and pass it to
// an inlined compiled method via a call.
- @Test(failOn = ALLOC + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
public long test5() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
return test5Inline(v);
@@ -132,43 +148,50 @@ public long test5Inline(MyValue1 v) {
return v.hash();
}
- @DontCompile
- public void test5_verifier(boolean warmup) {
+ @Run(test = "test5")
+ public void test5_verifier() {
long result = test5();
Asserts.assertEQ(result, hash());
}
// Create an inline type in compiled code and pass it to
// the interpreter via a call.
- @Test(valid = InlineTypePassFieldsAsArgsOn, failOn = LOAD + TRAP + ALLOC)
- @Test(valid = InlineTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
+ @Test
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "true"},
+ failOn = {LOAD, TRAP, ALLOC})
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "false"},
+ counts = {ALLOC, "= 1"},
+ failOn = {LOAD, TRAP})
public long test6() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
// Pass to interpreter
return v.hashInterpreted();
}
- @DontCompile
- public void test6_verifier(boolean warmup) {
+ @Run(test = "test6")
+ public void test6_verifier() {
long result = test6();
Asserts.assertEQ(result, hash());
}
// Create an inline type in compiled code and pass it to
// the interpreter by returning.
- @Test(match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
+ @Test
+ @IR(counts = {ALLOC, "= 1"},
+ failOn = {LOAD, TRAP})
public MyValue1 test7(int x, long y) {
return MyValue1.createWithFieldsInline(x, y);
}
- @DontCompile
- public void test7_verifier(boolean warmup) {
+ @Run(test = "test7")
+ public void test7_verifier() {
MyValue1 v = test7(rI, rL);
Asserts.assertEQ(v.hash(), hash());
}
// Merge inline types created from two branches
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test8(boolean b) {
MyValue1 v;
if (b) {
@@ -179,15 +202,20 @@ public long test8(boolean b) {
return v.hash();
}
- @DontCompile
- public void test8_verifier(boolean warmup) {
+ @Run(test = "test8")
+ public void test8_verifier() {
Asserts.assertEQ(test8(true), hash());
Asserts.assertEQ(test8(false), hash(rI + 1, rL + 1));
}
// Merge inline types created from two branches
- @Test(valid = InlineTypePassFieldsAsArgsOn, match = {LOAD}, matchCount = {14}, failOn = TRAP + ALLOC + STORE)
- @Test(valid = InlineTypePassFieldsAsArgsOff, match = {ALLOC, STORE}, matchCount = {1, 13}, failOn = LOAD + TRAP)
+ @Test
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "true"},
+ counts = {LOAD, "= 14"},
+ failOn = {TRAP, ALLOC, STORE})
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "false"},
+ counts = {ALLOC, "= 1", STORE, "= 13"},
+ failOn = {LOAD, TRAP})
public MyValue1 test9(boolean b, int localrI, long localrL) {
MyValue1 v;
if (b) {
@@ -211,8 +239,8 @@ public MyValue1 test9(boolean b, int localrI, long localrL) {
return v;
}
- @DontCompile
- public void test9_verifier(boolean warmup) {
+ @Run(test = "test9")
+ public void test9_verifier() {
MyValue1 v = test9(true, rI, rL);
Asserts.assertEQ(v.x, rI);
Asserts.assertEQ(v.y, hash());
@@ -222,7 +250,8 @@ public void test9_verifier(boolean warmup) {
}
// Merge inline types created in a loop (not inlined)
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test10(int x, long y) {
MyValue1 v = MyValue1.createWithFieldsDontInline(x, y);
for (int i = 0; i < 10; ++i) {
@@ -231,14 +260,15 @@ public long test10(int x, long y) {
return v.hash();
}
- @DontCompile
- public void test10_verifier(boolean warmup) {
+ @Run(test = "test10")
+ public void test10_verifier() {
long result = test10(rI, rL);
Asserts.assertEQ(result, hash(rI + 10, rL + 10));
}
// Merge inline types created in a loop (inlined)
- @Test(failOn = ALLOC + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
public long test11(int x, long y) {
MyValue1 v = MyValue1.createWithFieldsInline(x, y);
for (int i = 0; i < 10; ++i) {
@@ -247,14 +277,16 @@ public long test11(int x, long y) {
return v.hash();
}
- @DontCompile
- public void test11_verifier(boolean warmup) {
+ @Run(test = "test11")
+ public void test11_verifier() {
long result = test11(rI, rL);
Asserts.assertEQ(result, hash(rI + 10, rL + 10));
}
// Test loop with uncommon trap referencing an inline type
- @Test(match = {SCOBJ}, matchCount = {-1 /* at least 1 */}, failOn = LOAD)
+ @Test
+ @IR(counts = {SCOBJ, ">= 1"}, // at least 1
+ failOn = LOAD)
public long test12(boolean b) {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
MyValue1[] va = new MyValue1[Math.abs(rI) % 10];
@@ -277,10 +309,10 @@ public long test12(boolean b) {
return result;
}
- @DontCompile
- public void test12_verifier(boolean warmup) {
- long result = test12(warmup);
- Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
+ @Run(test = "test12")
+ public void test12_verifier(RunInfo info) {
+ long result = test12(info.isWarmUp());
+ Asserts.assertEQ(result, info.isWarmUp() ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
}
// Test loop with uncommon trap referencing an inline type
@@ -307,66 +339,76 @@ public long test13(boolean b) {
return result;
}
- @DontCompile
- public void test13_verifier(boolean warmup) {
- long result = test13(warmup);
- Asserts.assertEQ(result, warmup ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
+ @Run(test = "test13")
+ public void test13_verifier(RunInfo info) {
+ long result = test13(info.isWarmUp());
+ Asserts.assertEQ(result, info.isWarmUp() ? rL + (1000 * rI) : ((Math.abs(rI) % 10) + 1) * hash());
}
// Create an inline type in a non-inlined method and then call a
// non-inlined method on that inline type.
- @Test(valid = InlineTypePassFieldsAsArgsOn, failOn = (ALLOC + STORE + TRAP), match = {LOAD}, matchCount = {14})
- @Test(valid = InlineTypePassFieldsAsArgsOff, failOn = (ALLOC + LOAD + STORE + TRAP))
+ @Test
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "true"},
+ failOn = {ALLOC, STORE, TRAP},
+ counts = {LOAD, "= 14"})
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "false"},
+ failOn = {ALLOC, LOAD, STORE, TRAP})
public long test14() {
MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
return v.hashInterpreted();
}
- @DontCompile
- public void test14_verifier(boolean b) {
+ @Run(test = "test14")
+ public void test14_verifier() {
long result = test14();
Asserts.assertEQ(result, hash());
}
// Create an inline type in an inlined method and then call a
// non-inlined method on that inline type.
- @Test(valid = InlineTypePassFieldsAsArgsOn, failOn = (LOAD + TRAP + ALLOC))
- @Test(valid = InlineTypePassFieldsAsArgsOff, failOn = (LOAD + TRAP), match = {ALLOC}, matchCount = {1})
+ @Test
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "true"},
+ failOn = {LOAD, TRAP, ALLOC})
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "false"},
+ failOn = {LOAD, TRAP},
+ counts = {ALLOC, "= 1"})
public long test15() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
return v.hashInterpreted();
}
- @DontCompile
- public void test15_verifier(boolean b) {
+ @Run(test = "test15")
+ public void test15_verifier() {
long result = test15();
Asserts.assertEQ(result, hash());
}
// Create an inline type in a non-inlined method and then call an
// inlined method on that inline type.
- @Test(failOn = (ALLOC + STORE + TRAP))
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test16() {
MyValue1 v = MyValue1.createWithFieldsDontInline(rI, rL);
return v.hash();
}
- @DontCompile
- public void test16_verifier(boolean b) {
+ @Run(test = "test16")
+ public void test16_verifier() {
long result = test16();
Asserts.assertEQ(result, hash());
}
// Create an inline type in an inlined method and then call an
// inlined method on that inline type.
- @Test(failOn = (ALLOC + LOAD + STORE + TRAP))
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
public long test17() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
return v.hash();
}
- @DontCompile
- public void test17_verifier(boolean b) {
+ @Run(test = "test17")
+ public void test17_verifier() {
long result = test17();
Asserts.assertEQ(result, hash());
}
@@ -374,16 +416,20 @@ public void test17_verifier(boolean b) {
// Create an inline type in compiled code and pass it to the
// interpreter via a call. The inline type is live at the first call so
// debug info should include a reference to all its fields.
- @Test(valid = InlineTypePassFieldsAsArgsOn, failOn = ALLOC + LOAD + TRAP)
- @Test(valid = InlineTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
+ @Test
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "true"},
+ failOn = {ALLOC, LOAD, TRAP})
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "false"},
+ counts = {ALLOC, "= 1"},
+ failOn = {LOAD, TRAP})
public long test18() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
v.hashInterpreted();
return v.hashInterpreted();
}
- @DontCompile
- public void test18_verifier(boolean warmup) {
+ @Run(test = "test18")
+ public void test18_verifier() {
long result = test18();
Asserts.assertEQ(result, hash());
}
@@ -391,8 +437,12 @@ public void test18_verifier(boolean warmup) {
// Create an inline type in compiled code and pass it to the
// interpreter via a call. The inline type is passed twice but
// should only be allocated once.
- @Test(valid = InlineTypePassFieldsAsArgsOn, failOn = ALLOC + LOAD + TRAP)
- @Test(valid = InlineTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD + TRAP)
+ @Test
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "true"},
+ failOn = {ALLOC, LOAD, TRAP})
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "false"},
+ counts = {ALLOC, "= 1"},
+ failOn = {LOAD, TRAP})
public long test19() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
return sumValue(v, v);
@@ -403,8 +453,8 @@ public long sumValue(MyValue1 v, MyValue1 dummy) {
return v.hash();
}
- @DontCompile
- public void test19_verifier(boolean warmup) {
+ @Run(test = "test19")
+ public void test19_verifier() {
long result = test19();
Asserts.assertEQ(result, hash());
}
@@ -413,23 +463,28 @@ public void test19_verifier(boolean warmup) {
// interpreter via a call. The inline type is live at the uncommon
// trap: verify that deoptimization causes the inline type to be
// correctly allocated.
- @Test(valid = InlineTypePassFieldsAsArgsOn, failOn = LOAD + ALLOC + STORE)
- @Test(valid = InlineTypePassFieldsAsArgsOff, match = {ALLOC}, matchCount = {1}, failOn = LOAD)
- public long test20(boolean deopt) {
+ @Test
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "true"},
+ failOn = {LOAD, ALLOC, STORE})
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "false"},
+ counts = {ALLOC, "= 1"},
+ failOn = LOAD)
+ public long test20(boolean deopt, Method m) {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
MyValue2[] va = new MyValue2[3];
if (deopt) {
// uncommon trap
- WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test20"));
+ TestFramework.deoptimize(m);
}
+
return v.hashInterpreted() + va[0].hashInterpreted() +
- va[1].hashInterpreted() + va[2].hashInterpreted();
+ va[1].hashInterpreted() + va[2].hashInterpreted();
}
- @DontCompile
- public void test20_verifier(boolean warmup) {
+ @Run(test = "test20")
+ public void test20_verifier(RunInfo info) {
MyValue2[] va = new MyValue2[42];
- long result = test20(!warmup);
+ long result = test20(!info.isWarmUp(), info.getTest());
Asserts.assertEQ(result, hash() + va[0].hash() + va[1].hash() + va[2].hash());
}
@@ -441,7 +496,9 @@ public void test20_verifier(boolean warmup) {
static final MyValue1 val5 = MyValue1.createWithFieldsInline(rI, rL);
// Test inline type fields in objects
- @Test(match = {ALLOC}, matchCount = {1}, failOn = (TRAP))
+ @Test
+ @IR(counts = {ALLOC, "= 1"},
+ failOn = TRAP)
public long test21(int x, long y) {
// Compute hash of inline type fields
long result = val1.hash() + val2.hash() + val3.hash() + val4.hash() + val5.hash();
@@ -452,8 +509,8 @@ public long test21(int x, long y) {
return result;
}
- @DontCompile
- public void test21_verifier(boolean warmup) {
+ @Run(test = "test21")
+ public void test21_verifier() {
// Check if hash computed by test18 is correct
val1 = MyValue1.createWithFieldsInline(rI, rL);
val2 = val1.v2;
@@ -470,68 +527,73 @@ public void test21_verifier(boolean warmup) {
}
// Test folding of constant inline type fields
- @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, LOOP, TRAP})
public long test22() {
// This should be constant folded
return val5.hash() + val5.v3.hash();
}
- @DontCompile
- public void test22_verifier(boolean warmup) {
+ @Run(test = "test22")
+ public void test22_verifier() {
long result = test22();
Asserts.assertEQ(result, val5.hash() + val5.v3.hash());
}
// Test defaultvalue
- @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, LOOP, TRAP})
public long test23() {
MyValue2 v = MyValue2.createDefaultInline();
return v.hash();
}
- @DontCompile
- public void test23_verifier(boolean warmup) {
+ @Run(test = "test23")
+ public void test23_verifier() {
long result = test23();
Asserts.assertEQ(result, MyValue2.createDefaultInline().hash());
}
// Test defaultvalue
- @Test(failOn = ALLOC + STORE + LOOP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, LOOP, TRAP})
public long test24() {
MyValue1 v1 = MyValue1.createDefaultInline();
MyValue1 v2 = MyValue1.createDefaultDontInline();
return v1.hashPrimitive() + v2.hashPrimitive();
}
- @DontCompile
- public void test24_verifier(boolean warmup) {
+ @Run(test = "test24")
+ public void test24_verifier() {
long result = test24();
Asserts.assertEQ(result, 2 * MyValue1.createDefaultInline().hashPrimitive());
}
// Test withfield
- @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, LOOP, TRAP})
public long test25() {
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
return v.hash();
}
- @DontCompile
- public void test25_verifier(boolean warmup) {
+ @Run(test = "test25")
+ public void test25_verifier() {
long result = test25();
Asserts.assertEQ(result, MyValue2.createWithFieldsInline(rI, rD).hash());
}
// Test withfield
- @Test(failOn = ALLOC + STORE + LOOP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, LOOP, TRAP})
public long test26() {
MyValue1 v1 = MyValue1.createWithFieldsInline(rI, rL);
MyValue1 v2 = MyValue1.createWithFieldsDontInline(rI, rL);
return v1.hash() + v2.hash();
}
- @DontCompile
- public void test26_verifier(boolean warmup) {
+ @Run(test = "test26")
+ public void test26_verifier() {
long result = test26();
Asserts.assertEQ(result, 2 * hash());
}
@@ -541,27 +603,29 @@ class TestClass27 {
}
// Test allocation elimination of unused object with initialized inline type field
- @Test(failOn = ALLOC + LOAD + STORE + LOOP)
- public void test27(boolean deopt) {
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, LOOP})
+ public void test27(boolean deopt, Method m) {
TestClass27 unused = new TestClass27();
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
unused.v = v;
if (deopt) {
// uncommon trap
- WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test27"));
+ TestFramework.deoptimize(m);
}
}
- @DontCompile
- public void test27_verifier(boolean warmup) {
- test27(!warmup);
+ @Run(test = "test27")
+ public void test27_verifier(RunInfo info) {
+ test27(!info.isWarmUp(), info.getTest());
}
static MyValue3 staticVal3;
static MyValue3 staticVal3_copy;
// Check elimination of redundant inline type allocations
- @Test(match = {ALLOC}, matchCount = {1})
+ @Test
+ @IR(counts = {ALLOC, "= 1"})
public MyValue3 test28(MyValue3[] va) {
// Create inline type and force allocation
MyValue3 vt = MyValue3.create();
@@ -578,8 +642,8 @@ public MyValue3 test28(MyValue3[] va) {
return copy;
}
- @DontCompile
- public void test28_verifier(boolean warmup) {
+ @Run(test = "test28")
+ public void test28_verifier() {
MyValue3[] va = new MyValue3[1];
MyValue3 vt = test28(va);
staticVal3.verify(vt);
@@ -603,16 +667,17 @@ public MyValue3 test29(boolean warmup) {
return copy;
}
- @DontCompile
- public void test29_verifier(boolean warmup) {
- MyValue3 vt = test29(warmup);
- if (warmup) {
+ @Run(test = "test29")
+ public void test29_verifier(RunInfo info) {
+ MyValue3 vt = test29(info.isWarmUp());
+ if (info.isWarmUp()) {
staticVal3.verify(vt);
}
}
// Verify that C2 recognizes inline type loads and re-uses the oop to avoid allocations
- @Test(failOn = ALLOC + ALLOCA + STORE)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, STORE})
public MyValue3 test30(MyValue3[] va) {
// C2 can re-use the oop of staticVal3 because staticVal3 is equal to copy
MyValue3 copy = MyValue3.copy(staticVal3);
@@ -622,8 +687,8 @@ public MyValue3 test30(MyValue3[] va) {
return copy;
}
- @DontCompile
- public void test30_verifier(boolean warmup) {
+ @Run(test = "test30")
+ public void test30_verifier() {
staticVal3 = MyValue3.create();
MyValue3[] va = new MyValue3[1];
MyValue3 vt = test30(va);
@@ -632,8 +697,9 @@ public void test30_verifier(boolean warmup) {
}
// Verify that C2 recognizes inline type loads and re-uses the oop to avoid allocations
- @Test(valid = InlineTypeReturnedAsFieldsOn)
- @Test(valid = InlineTypeReturnedAsFieldsOff, failOn = ALLOC + ALLOCA + STORE)
+ @Test
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "false"},
+ failOn = {ALLOC, ALLOCA, STORE})
public MyValue3 test31(MyValue3[] va) {
// C2 can re-use the oop returned by createDontInline()
// because the corresponding inline type is equal to 'copy'.
@@ -644,8 +710,8 @@ public MyValue3 test31(MyValue3[] va) {
return copy;
}
- @DontCompile
- public void test31_verifier(boolean warmup) {
+ @Run(test = "test31")
+ public void test31_verifier() {
MyValue3[] va = new MyValue3[1];
MyValue3 vt = test31(va);
staticVal3.verify(vt);
@@ -653,8 +719,9 @@ public void test31_verifier(boolean warmup) {
}
// Verify that C2 recognizes inline type loads and re-uses the oop to avoid allocations
- @Test(valid = InlineTypePassFieldsAsArgsOn)
- @Test(valid = InlineTypePassFieldsAsArgsOff, failOn = ALLOC + ALLOCA + STORE)
+ @Test
+ @IR(applyIf = {"InlineTypePassFieldsAsArgs", "false"},
+ failOn = {ALLOC, ALLOCA, STORE})
public MyValue3 test32(MyValue3 vt, MyValue3[] va) {
// C2 can re-use the oop of vt because vt is equal to 'copy'.
MyValue3 copy = MyValue3.copy(vt);
@@ -664,8 +731,8 @@ public MyValue3 test32(MyValue3 vt, MyValue3[] va) {
return copy;
}
- @DontCompile
- public void test32_verifier(boolean warmup) {
+ @Run(test = "test32")
+ public void test32_verifier() {
MyValue3 vt = MyValue3.create();
MyValue3[] va = new MyValue3[1];
MyValue3 result = test32(vt, va);
@@ -675,7 +742,7 @@ public void test32_verifier(boolean warmup) {
}
// Test correct identification of inline type copies
- @Test()
+ @Test
public MyValue3 test33(MyValue3[] va) {
MyValue3 vt = MyValue3.copy(staticVal3);
vt = MyValue3.setI(vt, vt.c);
@@ -686,8 +753,8 @@ public MyValue3 test33(MyValue3[] va) {
return vt;
}
- @DontCompile
- public void test33_verifier(boolean warmup) {
+ @Run(test = "test33")
+ public void test33_verifier() {
staticVal3 = MyValue3.create();
MyValue3[] va = new MyValue3[1];
MyValue3 vt = test33(va);
@@ -698,7 +765,8 @@ public void test33_verifier(boolean warmup) {
// Verify that the default inline type is never allocated.
// C2 code should load and use the default oop from the java mirror.
- @Test(failOn = ALLOC + ALLOCA + LOAD + STORE + LOOP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOAD, STORE, LOOP, TRAP})
public MyValue3 test34(MyValue3[] va) {
// Explicitly create default value
MyValue3 vt = MyValue3.createDefault();
@@ -714,8 +782,8 @@ public MyValue3 test34(MyValue3[] va) {
return vt;
}
- @DontCompile
- public void test34_verifier(boolean warmup) {
+ @Run(test = "test34")
+ public void test34_verifier() {
MyValue3 vt = MyValue3.createDefault();
MyValue3[] va = new MyValue3[2];
va[0] = MyValue3.create();
@@ -729,7 +797,8 @@ public void test34_verifier(boolean warmup) {
}
// Same as above but manually initialize inline type fields to default.
- @Test(failOn = ALLOC + ALLOCA + LOAD + STORE + LOOP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOAD, STORE, LOOP, TRAP})
public MyValue3 test35(MyValue3 vt, MyValue3[] va) {
vt = MyValue3.setC(vt, (char)0);
vt = MyValue3.setBB(vt, (byte)0);
@@ -750,8 +819,8 @@ public MyValue3 test35(MyValue3 vt, MyValue3[] va) {
return vt;
}
- @DontCompile
- public void test35_verifier(boolean warmup) {
+ @Run(test = "test35")
+ public void test35_verifier() {
MyValue3 vt = MyValue3.createDefault();
MyValue3[] va = new MyValue3[1];
va[0] = MyValue3.create();
@@ -767,7 +836,8 @@ private Object test36_helper(Object v) {
return v;
}
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test36(boolean b) {
Object o;
if (b) {
@@ -779,8 +849,8 @@ public long test36(boolean b) {
return v.hash();
}
- @DontCompile
- public void test36_verifier(boolean warmup) {
+ @Run(test = "test36")
+ public void test36_verifier() {
Asserts.assertEQ(test36(true), hash());
Asserts.assertEQ(test36(false), hash(rI + 1, rL + 1));
}
@@ -802,8 +872,8 @@ public Test37Value1 test37(Test37Value1 vt) {
return vt;
}
- @DontCompile
- public void test37_verifier(boolean warmup) {
+ @Run(test = "test37")
+ public void test37_verifier() {
Test37Value1 vt = new Test37Value1();
Asserts.assertEQ(test37(vt), vt);
}
@@ -828,8 +898,8 @@ public void test38() {
}
}
- @DontCompile
- public void test38_verifier(boolean warmup) {
+ @Run(test = "test38")
+ public void test38_verifier() {
test38Field = Test38Value.default;
test38();
Asserts.assertEQ(test38Field, new Test38Value(99));
@@ -853,26 +923,25 @@ public int[] getArray() {
}
@Test
- @Warmup(10)
public int test39() {
int result = 0;
for (int i = 0; i < 100; ++i) {
switch ((i >>> 1) % 3) {
- case 0:
- test39A1[i][i] = i;
- break;
- case 1:
- for (int j = 0; j < 100; ++j) {
- test39A1[i] = getArray();
- test39Val = new Test39Value(j, test39Val.iFld2);
- }
- break;
- case 2:
- for (float f = 142; f > i; f--) {
- test39A2[i + 1] += 3;
- }
- result += test39Val.iFld1;
- break;
+ case 0:
+ test39A1[i][i] = i;
+ break;
+ case 1:
+ for (int j = 0; j < 100; ++j) {
+ test39A1[i] = getArray();
+ test39Val = new Test39Value(j, test39Val.iFld2);
+ }
+ break;
+ case 2:
+ for (float f = 142; f > i; f--) {
+ test39A2[i + 1] += 3;
+ }
+ result += test39Val.iFld1;
+ break;
}
double d1 = 1;
while (++d1 < 142) {
@@ -883,8 +952,9 @@ public int test39() {
return result;
}
- @DontCompile
- public void test39_verifier(boolean warmup) {
+ @Run(test = "test39")
+ @Warmup(10)
+ public void test39_verifier() {
int result = test39();
Asserts.assertEQ(result, 1552);
}
@@ -902,9 +972,10 @@ public long test40(boolean b) {
return result;
}
- @DontCompile
- public void test40_verifier(boolean warmup) {
- long result = test40(warmup);
- Asserts.assertEQ(result, warmup ? 0 : hash());
+ @Run(test = "test40")
+ public void test40_verifier(RunInfo info) {
+ long result = test40(info.isWarmUp());
+ Asserts.assertEQ(result, info.isWarmUp() ? 0 : hash());
}
+
}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java
index a7f94329926..5a8d03bf8af 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2021, 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
@@ -21,74 +21,59 @@
* questions.
*/
-
package compiler.valhalla.inlinetypes;
-import java.lang.invoke.*;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-
+import compiler.lib.ir_framework.CompLevel;
+import compiler.lib.ir_framework.Run;
+import compiler.lib.ir_framework.Scenario;
+import compiler.lib.ir_framework.Test;
import jdk.test.lib.Asserts;
+import static compiler.valhalla.inlinetypes.InlineTypes.rI;
+import static compiler.valhalla.inlinetypes.InlineTypes.rL;
+
/*
* @test
* @key randomness
* @summary Various tests that are specific for C1.
- * @library /testlibrary /test/lib /compiler/whitebox /
+ * @library /test/lib /
* @requires os.simpleArch == "x64"
* @compile -XDallowWithFieldOperator TestC1.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestC1
+ * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestC1
*/
-public class TestC1 extends InlineTypeTest {
- public static final int C1 = COMP_LEVEL_SIMPLE;
- public static final int C2 = COMP_LEVEL_FULL_OPTIMIZATION;
-
- public static void main(String[] args) throws Throwable {
- TestC1 test = new TestC1();
- test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class, MyValue3.class, MyValue3Inline.class);
- }
- @Override
- public int getNumScenarios() {
- return 5;
- }
-
- @Override
- public String[] getVMParameters(int scenario) {
- switch (scenario) {
- case 0: return new String[] { // C1 only
- "-XX:TieredStopAtLevel=1",
- "-XX:+TieredCompilation",
- };
- case 1: return new String[] { // C2 only. (Make sure the tests are correctly written)
- "-XX:TieredStopAtLevel=4",
- "-XX:-TieredCompilation",
- };
- case 2: return new String[] { // interpreter only
- "-Xint",
- };
- case 3: return new String[] {
+public class TestC1 {
+ public static void main(String[] args) {
+ final Scenario[] scenarios = {
+ // C1 only
+ new Scenario(0,
+ "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation"),
+ // C2 only. (Make sure the tests are correctly written)
+ new Scenario(1,
+ "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation"),
+ // interpreter only
+ new Scenario(2,
+ "-Xint"),
// Xcomp Only C1.
- "-XX:TieredStopAtLevel=1",
- "-XX:+TieredCompilation",
- "-Xcomp",
- };
- case 4: return new String[] {
+ new Scenario(3,
+ "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation", "-Xcomp"),
// Xcomp Only C2.
- "-XX:TieredStopAtLevel=4",
- "-XX:-TieredCompilation",
- "-Xcomp",
- };
- }
- return null;
+ new Scenario(4,
+ "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation", "-Xcomp")
+ };
+
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .addHelperClasses(MyValue1.class,
+ MyValue2.class,
+ MyValue2Inline.class,
+ MyValue3.class,
+ MyValue3Inline.class)
+ .start();
}
// JDK-8229799
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public long test1(Object a, Object b, long n) {
long r;
n += (a == b) ? 0x5678123456781234L : 0x1234567812345678L;
@@ -96,8 +81,8 @@ public long test1(Object a, Object b, long n) {
return n;
}
- @DontCompile
- public void test1_verifier(boolean warmup) {
+ @Run(test = "test1")
+ public void test1_verifier() {
MyValue1 v1 = MyValue1.createWithFieldsInline(rI, rL);
MyValue1 v2 = MyValue1.createWithFieldsInline(rI, rL+1);
long r1 = test1(v1, v1, 1);
@@ -116,13 +101,13 @@ static primitive class SimpleValue2 {
// JDK-8231961
// Test that the value numbering optimization does not remove
// the second load from the buffered array element.
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public int test2(SimpleValue2[] array) {
return array[0].value + array[0].value;
}
- @DontCompile
- public void test2_verifier(boolean warmup) {
+ @Run(test = "test2")
+ public void test2_verifier() {
SimpleValue2[] array = new SimpleValue2[1];
array[0] = new SimpleValue2(rI);
int result = test2(array);
@@ -134,13 +119,13 @@ public void test2_verifier(boolean warmup) {
// sub-elements of a flattened array without copying the element first
// Test access to a null array
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public int test3(MyValue2[] array, int index) {
return array[index].x;
}
- @DontCompile
- public void test3_verifier(boolean warmup) {
+ @Run(test = "test3")
+ public void test3_verifier() {
NullPointerException npe = null;
try {
test3(null, 0);
@@ -151,13 +136,13 @@ public void test3_verifier(boolean warmup) {
}
// Test out of bound accesses
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public int test4(MyValue2[] array, int index) {
return array[index].x;
}
- @DontCompile
- public void test4_verifier(boolean warmup) {
+ @Run(test = "test4")
+ public void test4_verifier() {
MyValue2[] array = new MyValue2[2];
ArrayIndexOutOfBoundsException aioob = null;
try {
@@ -176,13 +161,13 @@ public void test4_verifier(boolean warmup) {
}
// Test 1st level sub-element access to primitive field
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public int test5(MyValue2[] array, int index) {
return array[index].x;
}
- @DontCompile
- public void test5_verifier(boolean warmup) {
+ @Run(test = "test5")
+ public void test5_verifier() {
MyValue2[] array = new MyValue2[2];
MyValue2 v = new MyValue2(1,(byte)2, new MyValue2Inline(5.0d, 345L));
array[1] = v;
@@ -191,13 +176,13 @@ public void test5_verifier(boolean warmup) {
}
// Test 1st level sub-element access to flattened field
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public MyValue2Inline test6(MyValue2[] array, int index) {
return array[index].v;
}
- @DontCompile
- public void test6_verifier(boolean warmup) {
+ @Run(test = "test6")
+ public void test6_verifier() {
MyValue2[] array = new MyValue2[2];
MyValue2Inline vi = new MyValue2Inline(3.5d, 678L);
MyValue2 v = new MyValue2(1,(byte)2, vi);
@@ -250,13 +235,13 @@ static primitive class TestValue {
}
}
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public Big test7(TestValue[] array, int index) {
return array[index].big;
}
- @DontCompile
- public void test7_verifier(boolean warmup) {
+ @Run(test = "test7")
+ public void test7_verifier() {
TestValue[] array = new TestValue[7];
Big b0 = test7(array, 3);
b0.check(0, 0);
@@ -267,13 +252,13 @@ public void test7_verifier(boolean warmup) {
}
// Test 2nd level sub-element access to primitive field
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public byte test8(MyValue1[] array, int index) {
return array[index].v2.y;
}
- @DontCompile
- public void test8_verifier(boolean warmup) {
+ @Run(test = "test8")
+ public void test8_verifier() {
MyValue1[] array = new MyValue1[23];
MyValue2 mv2a = MyValue2.createWithFieldsInline(7, 63L, 8.9d);
MyValue2 mv2b = MyValue2.createWithFieldsInline(11, 69L, 17.3d);
@@ -290,37 +275,37 @@ public void test8_verifier(boolean warmup) {
// (OOB, null pointer)
static primitive class EmptyType {}
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public EmptyType test9() {
EmptyType[] array = new EmptyType[10];
return array[4];
}
- @DontCompile
- public void test9_verifier(boolean warmup) {
+ @Run(test = "test9")
+ public void test9_verifier() {
EmptyType et = test9();
Asserts.assertEQ(et, EmptyType.default);
}
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public EmptyType test10(EmptyType[] array) {
return array[0];
}
- @DontCompile
- public void test10_verifier(boolean warmup) {
+ @Run(test = "test10")
+ public void test10_verifier() {
EmptyType[] array = new EmptyType[16];
EmptyType et = test10(array);
Asserts.assertEQ(et, EmptyType.default);
}
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public EmptyType test11(EmptyType[] array, int index) {
return array[index];
}
- @DontCompile
- public void test11_verifier(boolean warmup) {
+ @Run(test = "test11")
+ public void test11_verifier() {
Exception e = null;
EmptyType[] array = new EmptyType[10];
try {
@@ -345,13 +330,13 @@ public void test11_verifier(boolean warmup) {
Asserts.assertNotNull(e);
}
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public void test12(EmptyType[] array, int index, EmptyType value) {
array[index] = value;
}
- @DontCompile
- public void test12_verifier(boolean warmup) {
+ @Run(test = "test12")
+ public void test12_verifier() {
EmptyType[] array = new EmptyType[16];
test12(array, 2, EmptyType.default);
Exception e = null;
@@ -376,5 +361,4 @@ public void test12_verifier(boolean warmup) {
}
Asserts.assertNotNull(e);
}
-
}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConvention.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConvention.java
index 63117803890..139b469b19e 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConvention.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConvention.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2021, 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,36 +23,28 @@
package compiler.valhalla.inlinetypes;
+import compiler.lib.ir_framework.*;
import jdk.test.lib.Asserts;
-import java.lang.invoke.*;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
+import static compiler.valhalla.inlinetypes.InlineTypes.IRNode.*;
+import static compiler.valhalla.inlinetypes.InlineTypes.*;
+
/*
* @test
* @key randomness
* @summary Test inline type calling convention optimizations
- * @library /testlibrary /test/lib /compiler/whitebox /
+ * @library /test/lib /
* @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
- * @compile TestCallingConvention.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestCallingConvention
+ * @run driver/timeout=450 compiler.valhalla.inlinetypes.TestCallingConvention
*/
-public class TestCallingConvention extends InlineTypeTest {
- // Extra VM parameters for some test scenarios. See InlineTypeTest.getVMParameters()
- @Override
- public String[] getExtraVMParameters(int scenario) {
- switch (scenario) {
- case 0: return new String[] {"-Dsun.reflect.inflationThreshold=10000"}; // Don't generate bytecodes but call through runtime for reflective calls
- case 1: return new String[] {"-Dsun.reflect.inflationThreshold=10000"};
- case 3: return new String[] {"-XX:FlatArrayElementMaxSize=0"};
- case 4: return new String[] {"-XX:-UseTLAB"};
- }
- return null;
- }
+
+@ForceCompileClassInitializer
+public class TestCallingConvention {
static {
try {
@@ -73,80 +65,110 @@ public String[] getExtraVMParameters(int scenario) {
}
}
- public static void main(String[] args) throws Throwable {
- TestCallingConvention test = new TestCallingConvention();
- test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class, MyValue3.class, MyValue3Inline.class, MyValue4.class,
- Test27Value1.class, Test27Value2.class, Test27Value3.class, Test37Value.class, EmptyContainer.class, MixedContainer.class);
+ public static void main(String[] args) {
+
+ Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS;
+ // Don't generate bytecodes but call through runtime for reflective calls
+ scenarios[0].addFlags("-Dsun.reflect.inflationThreshold=10000");
+ scenarios[1].addFlags("-Dsun.reflect.inflationThreshold=10000");
+ scenarios[3].addFlags("-XX:FlatArrayElementMaxSize=0");
+ scenarios[4].addFlags("-XX:-UseTLAB");
+
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .addHelperClasses(MyValue1.class,
+ MyValue2.class,
+ MyValue2Inline.class,
+ MyValue3.class,
+ MyValue3Inline.class,
+ MyValue4.class)
+ .start();
+ }
+
+ // Helper methods and classes
+
+ private void deoptimize(String name, Class>... params) {
+ try {
+ TestFramework.deoptimize(getClass().getDeclaredMethod(name, params));
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
}
// Test interpreter to compiled code with various signatures
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test1(MyValue2 v) {
return v.hash();
}
- @DontCompile
- public void test1_verifier(boolean warmup) {
+ @Run(test = "test1")
+ public void test1_verifier() {
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
long result = test1(v);
Asserts.assertEQ(result, v.hashInterpreted());
}
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test2(int i1, MyValue2 v, int i2) {
return v.hash() + i1 - i2;
}
- @DontCompile
- public void test2_verifier(boolean warmup) {
+ @Run(test = "test2")
+ public void test2_verifier(RunInfo info) {
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
long result = test2(rI, v, 2*rI);
Asserts.assertEQ(result, v.hashInterpreted() - rI);
}
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test3(long l1, MyValue2 v, long l2) {
return v.hash() + l1 - l2;
}
- @DontCompile
- public void test3_verifier(boolean warmup) {
+ @Run(test = "test3")
+ public void test3_verifier() {
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
long result = test3(rL, v, 2*rL);
Asserts.assertEQ(result, v.hashInterpreted() - rL);
}
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test4(int i, MyValue2 v, long l) {
return v.hash() + i + l;
}
- @DontCompile
- public void test4_verifier(boolean warmup) {
+ @Run(test = "test4")
+ public void test4_verifier() {
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
long result = test4(rI, v, rL);
Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
}
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test5(long l, MyValue2 v, int i) {
return v.hash() + i + l;
}
- @DontCompile
- public void test5_verifier(boolean warmup) {
+ @Run(test = "test5")
+ public void test5_verifier() {
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
long result = test5(rL, v, rI);
Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
}
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test6(long l, MyValue1 v1, int i, MyValue2 v2) {
return v1.hash() + i + l + v2.hash();
}
- @DontCompile
- public void test6_verifier(boolean warmup) {
+ @Run(test = "test6")
+ public void test6_verifier() {
MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL);
MyValue2 v2 = MyValue2.createWithFieldsInline(rI, rD);
long result = test6(rL, v1, rI, v2);
@@ -159,13 +181,14 @@ public long test7_interp(MyValue2 v) {
return v.hash();
}
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test7(MyValue2 v) {
return test7_interp(v);
}
- @DontCompile
- public void test7_verifier(boolean warmup) {
+ @Run(test = "test7")
+ public void test7_verifier() {
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
long result = test7(v);
Asserts.assertEQ(result, v.hashInterpreted());
@@ -176,13 +199,14 @@ public long test8_interp(int i1, MyValue2 v, int i2) {
return v.hash() + i1 - i2;
}
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test8(int i1, MyValue2 v, int i2) {
return test8_interp(i1, v, i2);
}
- @DontCompile
- public void test8_verifier(boolean warmup) {
+ @Run(test = "test8")
+ public void test8_verifier() {
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
long result = test8(rI, v, 2*rI);
Asserts.assertEQ(result, v.hashInterpreted() - rI);
@@ -193,13 +217,14 @@ public long test9_interp(long l1, MyValue2 v, long l2) {
return v.hash() + l1 - l2;
}
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test9(long l1, MyValue2 v, long l2) {
return test9_interp(l1, v, l2);
}
- @DontCompile
- public void test9_verifier(boolean warmup) {
+ @Run(test = "test9")
+ public void test9_verifier() {
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
long result = test9(rL, v, 2*rL);
Asserts.assertEQ(result, v.hashInterpreted() - rL);
@@ -210,13 +235,14 @@ public long test10_interp(int i, MyValue2 v, long l) {
return v.hash() + i + l;
}
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test10(int i, MyValue2 v, long l) {
return test10_interp(i, v, l);
}
- @DontCompile
- public void test10_verifier(boolean warmup) {
+ @Run(test = "test10")
+ public void test10_verifier() {
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
long result = test10(rI, v, rL);
Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
@@ -227,13 +253,14 @@ public long test11_interp(long l, MyValue2 v, int i) {
return v.hash() + i + l;
}
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test11(long l, MyValue2 v, int i) {
return test11_interp(l, v, i);
}
- @DontCompile
- public void test11_verifier(boolean warmup) {
+ @Run(test = "test11")
+ public void test11_verifier() {
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
long result = test11(rL, v, rI);
Asserts.assertEQ(result, v.hashInterpreted() + rL + rI);
@@ -244,13 +271,14 @@ public long test12_interp(long l, MyValue1 v1, int i, MyValue2 v2) {
return v1.hash() + i + l + v2.hash();
}
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test12(long l, MyValue1 v1, int i, MyValue2 v2) {
return test12_interp(l, v1, i, v2);
}
- @DontCompile
- public void test12_verifier(boolean warmup) {
+ @Run(test = "test12")
+ public void test12_verifier() {
MyValue1 v1 = MyValue1.createWithFieldsDontInline(rI, rL);
MyValue2 v2 = MyValue2.createWithFieldsInline(rI, rD);
long result = test12(rL, v1, rI, v2);
@@ -262,23 +290,24 @@ public void test12_verifier(boolean warmup) {
public long test13_interp(MyValue2 v, MyValue1[] va, boolean deopt) {
if (deopt) {
// uncommon trap
- WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test13"));
+ deoptimize("test13", MyValue2.class, MyValue1[].class, boolean.class, long.class);
}
return v.hash() + va[0].hash() + va[1].hash();
}
- @Test(failOn = ALLOC + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, STORE, TRAP})
public long test13(MyValue2 v, MyValue1[] va, boolean flag, long l) {
return test13_interp(v, va, flag) + l;
}
- @DontCompile
- public void test13_verifier(boolean warmup) {
+ @Run(test = "test13")
+ public void test13_verifier(RunInfo info) {
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
MyValue1[] va = new MyValue1[2];
va[0] = MyValue1.createWithFieldsDontInline(rI, rL);
va[1] = MyValue1.createWithFieldsDontInline(rI, rL);
- long result = test13(v, va, !warmup, rL);
+ long result = test13(v, va, !info.isWarmUp(), rL);
Asserts.assertEQ(result, v.hashInterpreted() + va[0].hash() + va[1].hash() + rL);
}
@@ -287,19 +316,19 @@ public void test13_verifier(boolean warmup) {
public MyValue2 test14_interp(boolean deopt) {
if (deopt) {
// uncommon trap
- WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test14"));
+ deoptimize("test14", boolean.class);
}
return MyValue2.createWithFieldsInline(rI, rD);
}
- @Test()
+ @Test
public MyValue2 test14(boolean flag) {
return test14_interp(flag);
}
- @DontCompile
- public void test14_verifier(boolean warmup) {
- MyValue2 result = test14(!warmup);
+ @Run(test = "test14")
+ public void test14_verifier(RunInfo info) {
+ MyValue2 result = test14(!info.isWarmUp());
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
Asserts.assertEQ(result.hash(), v.hash());
}
@@ -312,32 +341,35 @@ public MyValue3 test15_interp() {
}
MyValue3 test15_vt2;
- @Test(valid = InlineTypeReturnedAsFieldsOn, failOn = ALLOC + LOAD + TRAP)
- @Test(valid = InlineTypeReturnedAsFieldsOff)
+ @Test
+ @IR(applyIf = {"InlineTypeReturnedAsFields", "true"},
+ failOn = {ALLOC, LOAD, TRAP})
public void test15() {
test15_vt2 = test15_interp();
}
- @DontCompile
- public void test15_verifier(boolean warmup) {
+ @Run(test = "test15")
+ public void test15_verifier() {
test15();
test15_vt.verify(test15_vt2);
}
// Return inline types in registers from compiled -> interpreter
final MyValue3 test16_vt = MyValue3.create();
- @Test(valid = InlineTypeReturnedAsFieldsOn, failOn = ALLOC + STORE + TRAP)
- @Test(valid = InlineTypeReturnedAsFieldsOff)
+ @Test
+ @IR(applyIf = {"InlineTypeReturnedAsFields", "true"},
+ failOn = {ALLOC, STORE, TRAP})
public MyValue3 test16() {
return test16_vt;
}
- @DontCompile
- public void test16_verifier(boolean warmup) {
+ @Run(test = "test16")
+ public void test16_verifier() {
MyValue3 vt = test16();
test16_vt.verify(vt);
}
+
// Return inline types in registers from compiled -> compiled
final MyValue3 test17_vt = MyValue3.create();
@DontInline
@@ -346,19 +378,21 @@ public MyValue3 test17_comp() {
}
MyValue3 test17_vt2;
- @Test(valid = InlineTypeReturnedAsFieldsOn, failOn = ALLOC + LOAD + TRAP)
- @Test(valid = InlineTypeReturnedAsFieldsOff)
+ @Test
+ @IR(applyIf = {"InlineTypeReturnedAsFields", "true"},
+ failOn = {ALLOC, LOAD, TRAP})
public void test17() {
test17_vt2 = test17_comp();
}
- @DontCompile
- public void test17_verifier(boolean warmup) throws Exception {
+ @Run(test = "test17")
+ public void test17_verifier(RunInfo info) throws Exception {
Method helper_m = getClass().getDeclaredMethod("test17_comp");
- if (!warmup && USE_COMPILER && !WHITE_BOX.isMethodCompiled(helper_m, false)) {
- enqueueMethodForCompilation(helper_m, COMP_LEVEL_FULL_OPTIMIZATION);
- Asserts.assertTrue(WHITE_BOX.isMethodCompiled(helper_m, false), "test17_comp not compiled");
+ if (!info.isWarmUp() && TestFramework.isCompiled(helper_m)) {
+ TestFramework.compile(helper_m, CompLevel.C2);
+ TestFramework.assertCompiledByC2(helper_m);
}
+
test17();
test17_vt.verify(test17_vt2);
}
@@ -378,8 +412,8 @@ public void test18() {
test18_vt2 = test18_interp();
}
- @DontCompile
- public void test18_verifier(boolean warmup) {
+ @Run(test = "test18")
+ public void test18_verifier() {
test18();
test18_vt.verify(test18_vt2);
}
@@ -391,8 +425,8 @@ public MyValue4 test19() {
return test19_vt;
}
- @DontCompile
- public void test19_verifier(boolean warmup) {
+ @Run(test = "test19")
+ public void test19_verifier() {
MyValue4 vt = test19();
test19_vt.verify(vt);
}
@@ -410,12 +444,12 @@ public void test20() {
test20_vt2 = test20_comp();
}
- @DontCompile
- public void test20_verifier(boolean warmup) throws Exception {
+ @Run(test = "test20")
+ public void test20_verifier(RunInfo info) throws Exception {
Method helper_m = getClass().getDeclaredMethod("test20_comp");
- if (!warmup && USE_COMPILER && !WHITE_BOX.isMethodCompiled(helper_m, false)) {
- enqueueMethodForCompilation(helper_m, COMP_LEVEL_FULL_OPTIMIZATION);
- Asserts.assertTrue(WHITE_BOX.isMethodCompiled(helper_m, false), "test20_comp not compiled");
+ if (!info.isWarmUp() && TestFramework.isCompiled(helper_m)) {
+ TestFramework.compile(helper_m, CompLevel.C2);
+ TestFramework.assertCompiledByC2(helper_m);
}
test20();
test20_vt.verify(test20_vt2);
@@ -436,8 +470,8 @@ public MyValue3 test21() {
}
}
- @DontCompile
- public void test21_verifier(boolean warmup) {
+ @Run(test = "test21")
+ public void test21_verifier() {
MyValue3 vt = test21();
test21_vt.verify(vt);
}
@@ -450,8 +484,8 @@ public MyValue3 test22() {
return (MyValue3) test22_vt;
}
- @DontCompile
- public void test22_verifier(boolean warmup) {
+ @Run(test = "test22")
+ public void test22_verifier() {
MyValue3 vt = test22();
test22_vt.verify(vt);
}
@@ -479,8 +513,8 @@ public double test23(int i1, int i2, int i3, int i4, int i5, int i6,
d1, d2, d3, d4, d5, d6, d7, d8);
}
- @DontCompile
- public void test23_verifier(boolean warmup) {
+ @Run(test = "test23")
+ public void test23_verifier(RunInfo info) {
TestValue23 vt = new TestValue23(rI);
double res1 = test23(rI, rI, rI, rI, rI, rI,
vt, vt, vt, vt, vt, vt, vt, vt,
@@ -499,8 +533,8 @@ public MyValue2.ref test24() {
return null;
}
- @DontCompile
- public void test24_verifier(boolean warmup) {
+ @Run(test = "test24")
+ public void test24_verifier(RunInfo info) {
MyValue2.ref vt = test24();
Asserts.assertEQ(vt, null);
}
@@ -520,8 +554,8 @@ public MyValue2.ref test26(boolean b) {
return test26_callee(b);
}
- @DontCompile
- public void test26_verifier(boolean warmup) {
+ @Run(test = "test26")
+ public void test26_verifier() {
MyValue2.ref vt = test26(true);
Asserts.assertEQ(vt, null);
vt = test26(false);
@@ -573,8 +607,8 @@ public int test27(Test27Value1 val) {
return val.test(val);
}
- @DontCompile
- public void test27_verifier(boolean warmup) {
+ @Run(test = "test27")
+ public void test27_verifier() {
Test27Value3 val3 = new Test27Value3(rI);
Test27Value2 val2 = new Test27Value2(val3);
Test27Value1 val1 = new Test27Value1(val2);
@@ -585,13 +619,13 @@ public void test27_verifier(boolean warmup) {
static final MyValue1.ref test28Val = MyValue1.createWithFieldsDontInline(rI, rL);
@Test
- @Warmup(0)
public String test28() {
return test28Val.toString();
}
- @DontCompile
- public void test28_verifier(boolean warmup) {
+ @Run(test = "test28")
+ @Warmup(0)
+ public void test28_verifier() {
String result = test28();
}
@@ -603,8 +637,8 @@ public MyValue3 test29() {
return test29_vt;
}
- @DontCompile
- public void test29_verifier(boolean warmup) throws Exception {
+ @Run(test = "test29")
+ public void test29_verifier() throws Exception {
MyValue3 vt = (MyValue3)TestCallingConvention.class.getDeclaredMethod("test29").invoke(this);
test29_vt.verify(vt);
}
@@ -616,8 +650,8 @@ public MyValue3 test30(MyValue3[] array) {
return result;
}
- @DontCompile
- public void test30_verifier(boolean warmup) throws Exception {
+ @Run(test = "test30")
+ public void test30_verifier() throws Exception {
MyValue3[] array = new MyValue3[1];
MyValue3 vt = (MyValue3)TestCallingConvention.class.getDeclaredMethod("test30", MyValue3[].class).invoke(this, (Object)array);
array[0].verify(vt);
@@ -632,8 +666,8 @@ public MyValue3 test31() {
return result;
}
- @DontCompile
- public void test31_verifier(boolean warmup) throws Exception {
+ @Run(test = "test31")
+ public void test31_verifier() throws Exception {
MyValue3 vt = (MyValue3)TestCallingConvention.class.getDeclaredMethod("test31").invoke(this);
test31_vt.verify(vt);
}
@@ -646,7 +680,7 @@ public void test31_verifier(boolean warmup) throws Exception {
public MyValue2 test32_interp(boolean deopt) {
if (deopt) {
// uncommon trap
- WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test32"));
+ deoptimize("test32", boolean.class);
}
return MyValue2.createWithFieldsInline(rI+32, rD);
}
@@ -656,9 +690,9 @@ public MyValue2 test32(boolean flag) throws Throwable {
return (MyValue2)test32_mh.invokeExact(this, flag);
}
- @DontCompile
- public void test32_verifier(boolean warmup) throws Throwable {
- MyValue2 result = test32(!warmup);
+ @Run(test = "test32")
+ public void test32_verifier(RunInfo info) throws Throwable {
+ MyValue2 result = test32(!info.isWarmUp());
MyValue2 v = MyValue2.createWithFieldsInline(rI+32, rD);
Asserts.assertEQ(result.hash(), v.hash());
}
@@ -670,7 +704,7 @@ public void test32_verifier(boolean warmup) throws Throwable {
public Object test33_interp(boolean deopt) {
if (deopt) {
// uncommon trap
- WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test33"));
+ deoptimize("test33", boolean.class);
}
return MyValue2.createWithFieldsInline(rI+33, rD);
}
@@ -681,9 +715,9 @@ public MyValue2 test33(boolean flag) throws Throwable {
return (MyValue2)o;
}
- @DontCompile
- public void test33_verifier(boolean warmup) throws Throwable {
- MyValue2 result = test33(!warmup);
+ @Run(test = "test33")
+ public void test33_verifier(RunInfo info) throws Throwable {
+ MyValue2 result = test33(!info.isWarmUp());
MyValue2 v = MyValue2.createWithFieldsInline(rI+33, rD);
Asserts.assertEQ(result.hash(), v.hash());
}
@@ -710,17 +744,17 @@ public static long test34_callee(MyValue2 vt, int i1, int i2, int i3, int i4) {
}
@Test()
- @Warmup(10000) // Make sure test34_callee is compiled
public static long test34(MyValue2 vt, int i1, int i2, int i3, int i4) {
return test34_callee(vt, i1, i2, i3, i4);
}
- @DontCompile
- public void test34_verifier(boolean warmup) {
+ @Run(test = "test34")
+ @Warmup(10000) // Make sure test34_callee is compiled
+ public void test34_verifier(RunInfo info) {
MyValue2 vt = MyValue2.createWithFieldsInline(rI, rD);
long result = test34(vt, rI, rI, rI, rI);
Asserts.assertEQ(result, vt.hash()+4*rI);
- if (!warmup) {
+ if (!info.isWarmUp()) {
test34_deopt = true;
for (int i = 0; i < 100; ++i) {
result = test34(vt, rI, rI, rI, rI);
@@ -740,8 +774,8 @@ public static long test35(MyValue2 vt, int i1, int i2, int i3, int i4) {
return vt.hash() + i1 + i2 + i3 + i4 + result;
}
- @DontCompile
- public void test35_verifier(boolean warmup) {
+ @Run(test = "test35")
+ public void test35_verifier() {
MyValue2 vt = MyValue2.createWithFieldsInline(rI, rD);
long result = test35(vt, rI, rI, rI, rI);
Asserts.assertEQ(result, vt.hash()+10004*rI);
@@ -759,8 +793,8 @@ public MyValue3 test36() {
return result;
}
- @DontCompile
- public void test36_verifier(boolean warmup) throws Exception {
+ @Run(test = "test36")
+ public void test36_verifier() throws Exception {
MyValue3 vt = (MyValue3)TestCallingConvention.class.getDeclaredMethod("test36").invoke(this);
test36_vt.verify(vt);
}
@@ -783,21 +817,22 @@ public int test37(Test37Value vt) throws Throwable {
return (int)test37_mh.invokeExact(vt);
}
- @DontCompile
- public void test37_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test37")
+ public void test37_verifier() throws Throwable {
Test37Value vt = new Test37Value();
int res = test37(vt);
Asserts.assertEQ(res, rI);
}
// Test passing/returning an empty inline type
- @Test(failOn = ALLOC + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
public MyValueEmpty test38(MyValueEmpty vt) {
return vt.copy(vt);
}
- @DontCompile
- public void test38_verifier(boolean warmup) {
+ @Run(test = "test38")
+ public void test38_verifier() {
MyValueEmpty vt = new MyValueEmpty();
MyValueEmpty res = test38(vt);
Asserts.assertEQ(res, vt);
@@ -884,8 +919,8 @@ public static LargeValueWithOops test39(LargeValueWithOops vt) {
return vt;
}
- @DontCompile
- public void test39_verifier(boolean warmup) {
+ @Run(test = "test39")
+ public void test39_verifier() {
LargeValueWithOops vt = new LargeValueWithOops();
LargeValueWithOops res = test39(vt);
Asserts.assertEQ(res, vt);
@@ -897,8 +932,8 @@ public static LargeValueWithoutOops test40(LargeValueWithoutOops vt) {
return vt;
}
- @DontCompile
- public void test40_verifier(boolean warmup) {
+ @Run(test = "test40")
+ public void test40_verifier() {
LargeValueWithoutOops vt = new LargeValueWithoutOops();
LargeValueWithoutOops res = test40(vt);
Asserts.assertEQ(res, vt);
@@ -906,13 +941,14 @@ public void test40_verifier(boolean warmup) {
// Test passing/returning an empty inline type together with non-empty
// inline types such that only some inline type arguments are scalarized.
- @Test(failOn = ALLOC + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
public MyValueEmpty test41(MyValue1 vt1, MyValueEmpty vt2, MyValue1 vt3) {
return vt2.copy(vt2);
}
- @DontCompile
- public void test41_verifier(boolean warmup) {
+ @Run(test = "test41")
+ public void test41_verifier() {
MyValueEmpty res = test41(MyValue1.default, MyValueEmpty.default, MyValue1.default);
Asserts.assertEQ(res, MyValueEmpty.default);
}
@@ -950,89 +986,97 @@ static primitive class MixedContainer {
}
// Empty inline type return
- @Test(failOn = ALLOC + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
public MyValueEmpty test42() {
EmptyContainer c = new EmptyContainer(MyValueEmpty.default);
return c.getInline();
}
- @DontCompile
- public void test42_verifier(boolean warmup) {
+ @Run(test = "test42")
+ public void test42_verifier() {
MyValueEmpty empty = test42();
Asserts.assertEquals(empty, MyValueEmpty.default);
}
// Empty inline type container return
- @Test(failOn = ALLOC + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
public EmptyContainer test43(EmptyContainer c) {
return c;
}
- @DontCompile
- public void test43_verifier(boolean warmup) {
+ @Run(test = "test43")
+ public void test43_verifier() {
EmptyContainer c = test43(EmptyContainer. default);
Asserts.assertEquals(c, EmptyContainer.default);
}
// Empty inline type container (mixed) return
- @Test(failOn = ALLOC + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
public MixedContainer test44() {
MixedContainer c = new MixedContainer(rI, EmptyContainer.default);
c = new MixedContainer(rI, c.getInline());
return c;
}
- @DontCompile
- public void test44_verifier(boolean warmup) {
+ @Run(test = "test44")
+ public void test44_verifier() {
MixedContainer c = test44();
Asserts.assertEquals(c, new MixedContainer(rI, EmptyContainer.default));
}
+
// Empty inline type container argument
- @Test(failOn = ALLOC + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
public EmptyContainer test45(EmptyContainer c) {
return new EmptyContainer(c.getInline());
}
- @DontCompile
- public void test45_verifier(boolean warmup) {
+ @Run(test = "test45")
+ public void test45_verifier() {
EmptyContainer empty = test45(EmptyContainer.default);
Asserts.assertEquals(empty, EmptyContainer.default);
}
// Empty inline type container and mixed container arguments
- @Test(failOn = ALLOC + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
public MyValueEmpty test46(EmptyContainer c1, MixedContainer c2, MyValueEmpty empty) {
c2 = new MixedContainer(c2.val, c1);
return c2.getNoInline().getNoInline();
}
- @DontCompile
- public void test46_verifier(boolean warmup) {
+ @Run(test = "test46")
+ public void test46_verifier() {
MyValueEmpty empty = test46(EmptyContainer.default, MixedContainer.default, MyValueEmpty.default);
Asserts.assertEquals(empty, MyValueEmpty.default);
}
// No receiver and only empty argument
- @Test(failOn = ALLOC + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
public static MyValueEmpty test47(MyValueEmpty empty) {
return empty;
}
- @DontCompile
- public void test47_verifier(boolean warmup) {
+ @Run(test = "test47")
+ public void test47_verifier() {
MyValueEmpty empty = test47(MyValueEmpty.default);
Asserts.assertEquals(empty, MyValueEmpty.default);
}
// No receiver and only empty container argument
- @Test(failOn = ALLOC + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
public static MyValueEmpty test48(EmptyContainer empty) {
return empty.getNoInline();
}
- @DontCompile
- public void test48_verifier(boolean warmup) {
+ @Run(test = "test48")
+ public void test48_verifier() {
MyValueEmpty empty = test48(EmptyContainer.default);
Asserts.assertEquals(empty, MyValueEmpty.default);
}
@@ -1055,8 +1099,8 @@ public void test49(boolean b) {
test49_inlined2(b);
}
- @DontCompile
- public void test49_verifier(boolean warmup) {
+ @Run(test = "test49")
+ public void test49_verifier() {
test49(true);
test49(false);
}
@@ -1083,8 +1127,8 @@ public void test50(boolean b) {
test50_vt.verify(vt);
}
- @DontCompile
- public void test50_verifier(boolean warmup) {
+ @Run(test = "test50")
+ public void test50_verifier() {
test50(true);
test50(false);
}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java
index 1baa644b75a..05b2f27cf43 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2021, 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,94 +23,65 @@
package compiler.valhalla.inlinetypes;
-import sun.hotspot.WhiteBox;
+import compiler.lib.ir_framework.*;
import jdk.test.lib.Asserts;
+import sun.hotspot.WhiteBox;
+
+import static compiler.valhalla.inlinetypes.InlineTypes.rI;
+import static compiler.valhalla.inlinetypes.InlineTypes.rL;
/*
* @test
* @key randomness
* @summary Test calls from {C1} to {C2, Interpreter}, and vice versa.
- * @library /testlibrary /test/lib /compiler/whitebox /
+ * @library /test/lib /
* @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
- * @compile TestCallingConventionC1.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestCallingConventionC1
+ * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestCallingConventionC1
*/
-public class TestCallingConventionC1 extends InlineTypeTest {
- public static final int C1 = COMP_LEVEL_SIMPLE;
- public static final int C2 = COMP_LEVEL_FULL_OPTIMIZATION;
- @Override
- public int getNumScenarios() {
- return 5;
- }
+@ForceCompileClassInitializer
+public class TestCallingConventionC1 {
- @Override
- public String[] getVMParameters(int scenario) {
- switch (scenario) {
- case 0: return new String[] {
+ public static void main(String[] args) {
+ final Scenario[] scenarios = {
// Default: both C1 and C2 are enabled, tiered compilation enabled
- "-XX:CICompilerCount=2",
- "-XX:TieredStopAtLevel=4",
- "-XX:+TieredCompilation",
- };
- case 1: return new String[] {
+ new Scenario(0,
+ "-XX:CICompilerCount=2",
+ "-XX:TieredStopAtLevel=4",
+ "-XX:+TieredCompilation"),
// Default: both C1 and C2 are enabled, tiered compilation enabled
- "-XX:CICompilerCount=2",
- "-XX:TieredStopAtLevel=4",
- "-XX:+TieredCompilation",
- "-XX:+StressInlineTypeReturnedAsFields"
- };
- case 2: return new String[] {
- // Same as above, but flip all the compLevel=C1 and compLevel=C2, so we test
+ new Scenario(1,
+ "-XX:CICompilerCount=2",
+ "-XX:TieredStopAtLevel=4",
+ "-XX:+TieredCompilation",
+ "-XX:+IgnoreUnrecognizedVMOptions",
+ "-XX:+StressInlineTypeReturnedAsFields"),
+ // Same as above, but flip all the compLevel=CompLevel.C1_SIMPLE and compLevel=CompLevel.C2, so we test
// the compliment of the above scenario.
- "-XX:CICompilerCount=2",
- "-XX:TieredStopAtLevel=4",
- "-XX:+TieredCompilation",
- "-DFlipC1C2=true"
- };
- case 3: return new String[] {
+ new Scenario(2,
+ "-XX:CICompilerCount=2",
+ "-XX:TieredStopAtLevel=4",
+ "-XX:+TieredCompilation",
+ "-DFlipC1C2=true"),
// Only C1. Tiered compilation disabled.
- "-XX:TieredStopAtLevel=1",
- "-XX:+TieredCompilation",
- };
- case 4: return new String[] {
+ new Scenario(3,
+ "-XX:TieredStopAtLevel=1",
+ "-XX:+TieredCompilation"),
// Only C2.
- "-XX:TieredStopAtLevel=4",
- "-XX:-TieredCompilation",
- };
- }
- return null;
- }
+ new Scenario(4,
+ "-XX:TieredStopAtLevel=4",
+ "-XX:-TieredCompilation")
+ };
- public static void main(String[] args) throws Throwable {
System.gc(); // Resolve this call, to avoid C1 code patching in the test cases.
- TestCallingConventionC1 test = new TestCallingConventionC1();
- test.run(args,
- Point.class,
- Functor.class,
- Functor1.class,
- Functor2.class,
- Functor3.class,
- Functor4.class,
- MyImplPojo0.class,
- MyImplPojo1.class,
- MyImplPojo2.class,
- MyImplPojo3.class,
- MyImplVal1.class,
- MyImplVal2.class,
- MyImplVal1X.class,
- MyImplVal2X.class,
- FixedPoints.class,
- FloatPoint.class,
- RefPoint.class,
- RefPoint_Access_Impl1.class,
- RefPoint_Access_Impl2.class);
+
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .start();
}
+ // Helper methods and classes
+
static primitive class Point {
final int x;
final int y;
@@ -120,13 +91,11 @@ public Point(int x, int y) {
}
@DontCompile
- @DontInline
public int func() {
return x + y;
}
- @ForceCompile(compLevel = C1)
- @DontInline
+ @ForceCompile(CompLevel.C1_SIMPLE)
public int func_c1(Point p) {
return x + y + p.x + p.y;
}
@@ -138,35 +107,34 @@ static interface FunctorInterface {
static class Functor implements FunctorInterface {
@DontCompile
- @DontInline
public int apply_interp(Point p) {
return p.func() + 0;
}
}
+
static class Functor1 extends Functor {
@DontCompile
- @DontInline
public int apply_interp(Point p) {
return p.func() + 10000;
}
}
+
static class Functor2 extends Functor {
@DontCompile
- @DontInline
public int apply_interp(Point p) {
return p.func() + 20000;
}
}
+
static class Functor3 extends Functor {
@DontCompile
- @DontInline
public int apply_interp(Point p) {
return p.func() + 30000;
}
}
+
static class Functor4 extends Functor {
@DontCompile
- @DontInline
public int apply_interp(Point p) {
return p.func() + 40000;
}
@@ -196,27 +164,27 @@ static interface Intf {
static class MyImplPojo0 implements Intf {
int field = 0;
- @DontInline @DontCompile
+ @DontCompile
public int func1(int a, int b) { return field + a + b + 1; }
- @DontInline @DontCompile
+ @DontCompile
public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 1; }
}
static class MyImplPojo1 implements Intf {
int field = 1000;
- @DontInline @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
public int func1(int a, int b) { return field + a + b + 20; }
- @DontInline @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 20; }
}
static class MyImplPojo2 implements Intf {
int field = 2000;
- @DontInline @ForceCompile(compLevel = C2)
+ @ForceCompile(CompLevel.C2)
public int func1(int a, int b) { return field + a + b + 20; }
- @DontInline @ForceCompile(compLevel = C2)
+ @ForceCompile(CompLevel.C2)
public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 20; }
}
@@ -234,10 +202,11 @@ static primitive class MyImplVal1 implements Intf {
field = 11000;
}
- @DontInline @ForceCompile(compLevel = C1)
- public int func1(int a, int b) { return field + a + b + 300; }
+ @DontInline
+ @ForceCompile(CompLevel.C1_SIMPLE)
+ public int func1(int a, int b) { return field + a + b + 300; }
- @DontInline @ForceCompile(compLevel = C1)
+ @DontInline @ForceCompile(CompLevel.C1_SIMPLE)
public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 300; }
}
@@ -247,10 +216,10 @@ static primitive class MyImplVal2 implements Intf {
field = 12000;
}
- @DontInline @ForceCompile(compLevel = C2)
+ @DontInline @ForceCompile(CompLevel.C2)
public int func1(int a, int b) { return field + a + b + 300; }
- @DontInline @ForceCompile(compLevel = C2)
+ @DontInline @ForceCompile(CompLevel.C2)
public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 300; }
}
@@ -260,10 +229,10 @@ static primitive class MyImplVal1X implements Intf {
field = 11000;
}
- @DontInline @DontCompile
+ @DontCompile
public int func1(int a, int b) { return field + a + b + 300; }
- @DontInline @DontCompile
+ @DontCompile
public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 300; }
}
@@ -311,6 +280,7 @@ public FloatPoint(float x, float y) {
this.y = y;
}
}
+
static primitive class DoublePoint {
final double x;
final double y;
@@ -365,19 +335,19 @@ public RefPoint(Number x, Number y) {
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
public final int final_func(RefPoint rp2) { // opt_virtual_call
return this.x.n + this.y.n + rp2.x.n + rp2.y.n;
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
public int func1(RefPoint rp2) {
return this.x.n + this.y.n + rp2.x.n + rp2.y.n;
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
public int func2(RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2) {
return x.n + y.n +
rp1.x.n + rp1.y.n +
@@ -390,12 +360,12 @@ public int func2(RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint r
}
static class RefPoint_Access_Impl1 implements RefPoint_Access {
- @DontInline @DontCompile
+ @DontCompile
public int func1(RefPoint rp2) {
return rp2.x.n + rp2.y.n + 1111111;
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
public int func2(RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2) {
return 111111 +
rp1.x.n + rp1.y.n +
@@ -406,13 +376,14 @@ public int func2(RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint r
n2.n;
}
}
+
static class RefPoint_Access_Impl2 implements RefPoint_Access {
- @DontInline @DontCompile
+ @DontCompile
public int func1(RefPoint rp2) {
return rp2.x.n + rp2.y.n + 2222222;
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
public int func2(RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2) {
return 222222 +
rp1.x.n + rp1.y.n +
@@ -460,44 +431,40 @@ static primitive class TooBigToReturnAsFields {
// PART 1 - C1 calls interpreted code
//**********************************************************************
-
//** C1 passes inline type to interpreter (static)
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public int test1() {
return test1_helper(pointField);
}
- @DontInline
@DontCompile
private static int test1_helper(Point p) {
return p.func();
}
- @DontCompile
- public void test1_verifier(boolean warmup) {
- int count = warmup ? 1 : 10;
+ @Run(test = "test1")
+ public void test1_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 10;
for (int i=0; iC1 invokestatic, single inline arg
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test30() {
return test30_helper(pointField);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test30_helper(Point p) {
return p.x + p.y;
}
- @DontCompile
- public void test30_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test30")
+ public void test30_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokestatic, two single inline args
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test31() {
return test31_helper(pointField1, pointField2);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test31_helper(Point p1, Point p2) {
return p1.x + p2.y;
}
- @DontCompile
- public void test31_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test31")
+ public void test31_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokestatic, two single inline args and interleaving ints (all passed in registers on x64)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test32() {
return test32_helper(0, pointField1, 1, pointField2);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test32_helper(int x, Point p1, int y, Point p2) {
return p1.x + p2.y + x + y;
}
- @DontCompile
- public void test32_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test32")
+ public void test32_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokeinterface -- no verified_ro_entry (no inline args except for receiver)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test33(Intf intf, int a, int b) {
return intf.func1(a, b);
}
- @DontCompile
- public void test33_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @Run(test = "test33")
+ public void test33_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC1 invokeinterface -- use verified_ro_entry (has inline args other than receiver)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test34(Intf intf, int a, int b) {
return intf.func2(a, b, pointField);
}
- @DontCompile
- public void test34_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @Run(test = "test34")
+ public void test34_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC1 invokestatic, Point.y is on stack (x64)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test35() {
return test35_helper(1, 2, 3, 4, 5, pointField);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test35_helper(int a1, int a2, int a3, int a4, int a5, Point p) {
return a1 + a2 + a3 + a4 + a5 + p.x + p.y;
}
- @DontCompile
- public void test35_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test35")
+ public void test35_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokestatic, shuffling arguments that are passed on stack
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test36() {
return test36_helper(pointField, 1, 2, 3, 4, 5, 6, 7, 8);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test36_helper(Point p, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) {
return a6 + a8;
}
- @DontCompile
- public void test36_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test36")
+ public void test36_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokestatic, shuffling long arguments
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test37() {
return test37_helper(pointField, 1, 2, 3, 4, 5, 6, 7, 8);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test37_helper(Point p, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) {
return (int)(a6 + a8);
}
- @DontCompile
- public void test37_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test37")
+ public void test37_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokestatic, shuffling boolean, byte, char, short, int, long arguments
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test38() {
return test38_helper(pointField, true, (byte)1, (char)2, (short)3, 4, 5, (byte)6, (short)7, 8);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test38_helper(Point p, boolean a0, byte a1, char a2, short a3, int a4, long a5, byte a6, short a7, int a8) {
if (a0) {
return (int)(a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8);
@@ -773,9 +739,9 @@ private static int test38_helper(Point p, boolean a0, byte a1, char a2, short a3
}
}
- @DontCompile
- public void test38_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test38")
+ public void test38_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokestatic, packing an inline type with all types of fixed point primitive fields.
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public long test39() {
return test39_helper(1, fixedPointsField, 2, fixedPointsField);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static long test39_helper(int a1, FixedPoints f1, int a2, FixedPoints f2) {
if (f1.Z0 == false && f1.Z1 == true && f2.Z0 == false && f2.Z1 == true) {
return f1.B + f2.C + f1.S + f2.I + f1.J;
@@ -799,9 +765,9 @@ private static long test39_helper(int a1, FixedPoints f1, int a2, FixedPoints f2
}
}
- @DontCompile
- public void test39_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test39")
+ public void test39_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokestatic, shuffling floating point args
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public double test40() {
return test40_helper(1.1f, 1.2, floatPointField, doublePointField, 1.3f, 1.4, 1.5f, 1.7, 1.7, 1.8, 1.9, 1.10, 1.11, 1.12);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static double test40_helper(float a1, double a2, FloatPoint fp, DoublePoint dp, float a3, double a4, float a5, double a6, double a7, double a8, double a9, double a10, double a11, double a12) {
return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + fp.x + fp.y - dp.x - dp.y;
}
- @DontCompile
- public void test40_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test40")
+ public void test40_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokestatic, mixing floats and ints
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public double test41() {
return test41_helper(1, 1.2, pointField, floatPointField, doublePointField, 1.3f, 4, 1.5f, 1.7, 1.7, 1.8, 9, 1.10, 1.11, 1.12);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static double test41_helper(int a1, double a2, Point p, FloatPoint fp, DoublePoint dp, float a3, int a4, float a5, double a6, double a7, double a8, long a9, double a10, double a11, double a12) {
return a1 + a2 + fp.x + fp.y - dp.x - dp.y + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12;
}
- @DontCompile
- public void test41_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test41")
+ public void test41_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokestatic, circular dependency (between rdi and first stack slot on x64)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public float test42() {
return test42_helper(eightFloatsField, pointField, 3, 4, 5, floatPointField, 7);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static float test42_helper(EightFloats ep1, // (xmm0 ... xmm7) -> rsi
Point p2, // (rsi, rdx) -> rdx
int i3, // rcx -> rcx
@@ -873,9 +839,9 @@ private static float test42_helper(EightFloats ep1, // (xmm0 ... xmm7) -> rsi
p2.x + p2.y + i3 + i4 + i5 + fp6.x + fp6.y + i7;
}
- @DontCompile
- public void test42_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test42")
+ public void test42_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokestatic, packing causes stack growth (1 extra stack word)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public float test43() {
return test43_helper(floatPointField, 1, 2, 3, 4, 5, 6);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static float test43_helper(FloatPoint fp, int a1, int a2, int a3, int a4, int a5, int a6) {
// On x64:
// Scalarized entry -- all parameters are passed in registers
@@ -898,9 +864,9 @@ private static float test43_helper(FloatPoint fp, int a1, int a2, int a3, int a4
return fp.x + fp.y + a1 + a2 + a3 + a4 + a5 + a6;
}
- @DontCompile
- public void test43_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test43")
+ public void test43_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokestatic, packing causes stack growth (2 extra stack words)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public float test44() {
return test44_helper(floatPointField, floatPointField, 1, 2, 3, 4, 5, 6);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static float test44_helper(FloatPoint fp1, FloatPoint fp2, int a1, int a2, int a3, int a4, int a5, int a6) {
// On x64:
// Scalarized entry -- all parameters are passed in registers
@@ -926,9 +892,9 @@ private static float test44_helper(FloatPoint fp1, FloatPoint fp2, int a1, int a
a1 + a2 + a3 + a4 + a5 + a6;
}
- @DontCompile
- public void test44_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test44")
+ public void test44_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokestatic, packing causes stack growth (5 extra stack words)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public float test45() {
return test45_helper(floatPointField, floatPointField, floatPointField, floatPointField, floatPointField, 1, 2, 3, 4, 5, 6, 7);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static float test45_helper(FloatPoint fp1, FloatPoint fp2, FloatPoint fp3, FloatPoint fp4, FloatPoint fp5, int a1, int a2, int a3, int a4, int a5, int a6, int a7) {
return fp1.x + fp1.y +
fp2.x + fp2.y +
@@ -953,9 +919,9 @@ private static float test45_helper(FloatPoint fp1, FloatPoint fp2, FloatPoint fp
a1 + a2 + a3 + a4 + a5 + a6 + a7;
}
- @DontCompile
- public void test45_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test45")
+ public void test45_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokestatic, packing causes stack growth (1 extra stack word -- mixing Point and FloatPoint)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public float test46() {
return test46_helper(floatPointField, floatPointField, pointField, floatPointField, floatPointField, pointField, floatPointField, 1, 2, 3, 4, 5, 6, 7);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static float test46_helper(FloatPoint fp1, FloatPoint fp2, Point p1, FloatPoint fp3, FloatPoint fp4, Point p2, FloatPoint fp5, int a1, int a2, int a3, int a4, int a5, int a6, int a7) {
return p1.x + p1.y +
p2.x + p2.y +
@@ -982,9 +948,9 @@ private static float test46_helper(FloatPoint fp1, FloatPoint fp2, Point p1, Flo
a1 + a2 + a3 + a4 + a5 + a6 + a7;
}
- @DontCompile
- public void test46_verifier(boolean warmup) {
- int count = warmup ? 1 : 2;
+ @Run(test = "test46")
+ public void test46_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 2;
for (int i=0; iC1 invokestatic, make sure stack walking works (with static variable)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public void test47(int n) {
try {
test47_helper(floatPointField, 1, 2, 3, 4, 5);
@@ -1024,13 +990,13 @@ public void test47(int n) {
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static float test47_helper(FloatPoint fp, int a1, int a2, int a3, int a4, int a5) {
test47_thrower();
return 0.0f;
}
- @DontInline @DontCompile
+ @DontCompile
private static void test47_thrower() {
MyRuntimeException e = new MyRuntimeException("This exception should have been caught!");
checkStackTrace(e, "test47_thrower", "test47_helper", "test47", "test47_verifier");
@@ -1039,9 +1005,9 @@ private static void test47_thrower() {
static int test47_value = 999;
- @DontCompile
- public void test47_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test47")
+ public void test47_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iC1 invokestatic, make sure stack walking works (with returned inline type)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test48(int n) {
try {
test48_helper(floatPointField, 1, 2, 3, 4, 5);
@@ -1062,22 +1028,22 @@ public int test48(int n) {
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static float test48_helper(FloatPoint fp, int a1, int a2, int a3, int a4, int a5) {
test48_thrower();
return 0.0f;
}
- @DontInline @DontCompile
+ @DontCompile
private static void test48_thrower() {
MyRuntimeException e = new MyRuntimeException("This exception should have been caught!");
checkStackTrace(e, "test48_thrower", "test48_helper", "test48", "test48_verifier");
throw e;
}
- @DontCompile
- public void test48_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test48")
+ public void test48_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iinterpreter invokestatic, make sure stack walking works (same as test 48, but with stack extension/repair)
// (this is the baseline for test50 --
// the only difference is: test49_helper is interpreted but test50_helper is compiled by C1).
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test49(int n) {
try {
test49_helper(floatPointField, 1, 2, 3, 4, 5, 6);
@@ -1098,22 +1064,22 @@ public int test49(int n) {
return n;
}
- @DontInline @DontCompile
+ @DontCompile
private static float test49_helper(FloatPoint fp, int a1, int a2, int a3, int a4, int a5, int a6) {
test49_thrower();
return 0.0f;
}
- @DontInline @DontCompile
+ @DontCompile
private static void test49_thrower() {
MyRuntimeException e = new MyRuntimeException("This exception should have been caught!");
checkStackTrace(e, "test49_thrower", "test49_helper", "test49", "test49_verifier");
throw e;
}
- @DontCompile
- public void test49_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test49")
+ public void test49_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iC1 invokestatic, make sure stack walking works (same as test 48, but with stack extension/repair)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test50(int n) {
try {
test50_helper(floatPointField, 1, 2, 3, 4, 5, 6);
@@ -1133,22 +1099,22 @@ public int test50(int n) {
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static float test50_helper(FloatPoint fp, int a1, int a2, int a3, int a4, int a5, int a6) {
test50_thrower();
return 0.0f;
}
- @DontInline @DontCompile
+ @DontCompile
private static void test50_thrower() {
MyRuntimeException e = new MyRuntimeException("This exception should have been caught!");
checkStackTrace(e, "test50_thrower", "test50_helper", "test50", "test50_verifier");
throw e;
}
- @DontCompile
- public void test50_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test50")
+ public void test50_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iC1 invokestatic, inline class with ref fields (RefPoint)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test51() {
return test51_helper(refPointField1);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test51_helper(RefPoint rp1) {
return rp1.x.n + rp1.y.n;
}
- @DontCompile
- public void test51_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test51")
+ public void test51_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iC1 invokestatic, inline class with ref fields (Point, RefPoint)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test52() {
return test52_helper(pointField, refPointField1);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test52_helper(Point p1, RefPoint rp1) {
return p1.x + p1.y + rp1.x.n + rp1.y.n;
}
- @DontCompile
- public void test52_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test52")
+ public void test52_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iC1 invokestatic, inline class with ref fields (RefPoint, RefPoint, RefPoint, RefPoint)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test53() {
return test53_helper(refPointField1, refPointField2, refPointField1, refPointField2);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test53_helper(RefPoint rp1, RefPoint rp2, RefPoint rp3, RefPoint rp4) {
return rp1.x.n + rp1.y.n +
rp2.x.n + rp2.y.n +
@@ -1215,9 +1181,9 @@ private static int test53_helper(RefPoint rp1, RefPoint rp2, RefPoint rp3, RefPo
rp4.x.n + rp4.y.n;
}
- @DontCompile
- public void test53_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test53")
+ public void test53_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iC1 invokestatic, inline class with ref fields (RefPoint, RefPoint, float, int, RefPoint, RefPoint)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test54() {
return test54_helper(refPointField1, refPointField2, 1.0f, 2, refPointField1, refPointField2);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test54_helper(RefPoint rp1, RefPoint rp2, float f, int i, RefPoint rp3, RefPoint rp4) {
return rp1.x.n + rp1.y.n +
rp2.x.n + rp2.y.n +
@@ -1241,9 +1207,9 @@ private static int test54_helper(RefPoint rp1, RefPoint rp2, float f, int i, Ref
rp4.x.n + rp4.y.n;
}
- @DontCompile
- public void test54_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test54")
+ public void test54_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iC1 invokestatic, force GC for every allocation when entering a C1 VEP (Point)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test55(Point p1) {
return test55_helper(p1);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test55_helper(Point p1) {
return p1.x + p1.y;
}
- @DontCompile
- public void test55_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test55")
+ public void test55_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iC1 invokestatic, force GC for every allocation when entering a C1 VEP (RefPoint)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test56(RefPoint rp1) {
return test56_helper(rp1);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test56_helper(RefPoint rp1) {
return rp1.x.n + rp1.y.n;
}
- @DontCompile
- public void test56_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test56")
+ public void test56_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iInterpreter (same as test56, but test c2i entry instead of C1)
- @Test(compLevel = C2)
+ // C2->Interpreter (same as test56, but test C2i entry instead of C1)
+ @Test(compLevel = CompLevel.C2)
public int test57(RefPoint rp1) {
return test57_helper(rp1);
}
- @DontInline @DontCompile
+ @DontCompile
private static int test57_helper(RefPoint rp1) {
return rp1.x.n + rp1.y.n;
}
- @DontCompile
- public void test57_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test57")
+ public void test57_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iC1 invokestatic, force GC for every allocation when entering a C1 VEP (a bunch of RefPoints and Numbers);
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test58(RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2) {
return test58_helper(rp1, rp2, n1, rp3, rp4, n2);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test58_helper(RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2) {
return rp1.x.n + rp1.y.n +
rp2.x.n + rp2.y.n +
@@ -1371,9 +1334,9 @@ private static int test58_helper(RefPoint rp1, RefPoint rp2, Number n1, RefPoint
n2.n;
}
- @DontCompile
- public void test58_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test58")
+ public void test58_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iC1 invokestatic, GC inside main body of C1-compiled method (caller's args should not be GC'ed).
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test59(RefPoint rp1, boolean doGC) {
return test59_helper(rp1, 11, 222, 3333, 4444, doGC);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test59_helper(RefPoint rp1, int a1, int a2, int a3, int a4, boolean doGC) {
if (doGC) {
System.gc();
@@ -1405,10 +1368,10 @@ private static int test59_helper(RefPoint rp1, int a1, int a2, int a3, int a4, b
return rp1.x.n + rp1.y.n + a1 + a2 + a3 + a4;
}
- @DontCompile
- public void test59_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
- boolean doGC = !warmup;
+ @Run(test = "test59")
+ public void test59_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
+ boolean doGC = !info.isWarmUp();
for (int i=0; iC1 invokestatic, GC inside main body of C1-compiled method (caller's args should not be GC'ed).
// same as test59, but the incoming (scalarized) oops are passed in both registers and stack.
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test60(RefPoint rp1, RefPoint rp2, boolean doGC) {
return test60_helper(555, 6666, 77777, rp1, rp2, 11, 222, 3333, 4444, doGC);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static int test60_helper(int x0, int x1, int x2, RefPoint rp1, RefPoint rp2,int a1, int a2, int a3, int a4, boolean doGC) {
// On x64, C2 passes: reg0=x1, reg1=x1, reg2=x2, reg3=rp1.x, reg4=rp1.y, reg5=rp2.x stack0=rp2.y ....
// C1 expects: reg0=x1, reg1=x1, reg2=x2, reg3=rp1, reg4=rp2, reg5=a1 stack0=a2 ...
@@ -1436,10 +1399,10 @@ private static int test60_helper(int x0, int x1, int x2, RefPoint rp1, RefPoint
return x0 + x1 + x2 + rp1.x.n + rp1.y.n + rp2.x.n + rp2.y.n + a1 + a2 + a3 + a4;
}
- @DontCompile
- public void test60_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
- boolean doGC = !warmup;
+ @Run(test = "test60")
+ public void test60_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
+ boolean doGC = !info.isWarmUp();
for (int i=0; iC1 invokeinterface via VVEP(RO)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test61(RefPoint_Access rpa, RefPoint rp2) {
return rpa.func1(rp2);
}
- @DontCompile
- public void test61_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @Run(test = "test61")
+ public void test61_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC1 invokeinterface via VVEP(RO) -- force GC for every allocation when entering a C1 VVEP(RO) (RefPoint)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test62(RefPoint_Access rpa, RefPoint rp2) {
return rpa.func1(rp2);
}
- @DontCompile
- public void test62_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @Run(test = "test62")
+ public void test62_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC1 invokeinterface via VVEP(RO) -- force GC for every allocation when entering a C1 VVEP(RO) (a bunch of RefPoints and Numbers)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test63(RefPoint_Access rpa, RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2) {
return rpa.func2(rp1, rp2, n1, rp3, rp4, n2);
}
- @DontCompile
- public void test63_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @Run(test = "test63")
+ public void test63_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC1 invokestatic (same as test63, but use invokestatic instead)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test64(RefPoint_Access rpa, RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2) {
return test64_helper(rpa, rp1, rp2, n1, rp3, rp4, n2);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
public static int test64_helper(RefPoint_Access rpa, RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2) {
return rp3.y.n;
}
- @DontCompile
- public void test64_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @Run(test = "test64")
+ public void test64_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC1 invokevirtual via VVEP(RO) (opt_virtual_call)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test76(RefPoint rp1, RefPoint rp2) {
return rp1.final_func(rp2);
}
- @DontCompile
- public void test76_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test76")
+ public void test76_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iC1 invokevirtual, force GC for every allocation when entering a C1 VEP (RefPoint)
// Same as test56, except we call the VVEP(RO) instead of VEP.
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test77(RefPoint rp1, RefPoint rp2) {
return rp1.final_func(rp2);
}
- @DontCompile
- public void test77_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test77")
+ public void test77_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iC1 invokestatic with InlineTypeReturnedAsFields (Point)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test78(Point p) {
Point np = test78_helper(p);
return np.x + np.y;
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static Point test78_helper(Point p) {
return p;
}
- @DontCompile
- public void test78_verifier(boolean warmup) {
+ @Run(test = "test78")
+ public void test78_verifier() {
int result = test78(pointField1);
int n = pointField1.x + pointField1.y;
Asserts.assertEQ(result, n);
}
// C2->C1 invokestatic with InlineTypeReturnedAsFields (RefPoint)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test79(RefPoint p) {
RefPoint np = test79_helper(p);
return np.x.n + np.y.n;
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static RefPoint test79_helper(RefPoint p) {
return p;
}
- @DontCompile
- public void test79_verifier(boolean warmup) {
+ @Run(test = "test79")
+ public void test79_verifier() {
int result = test79(refPointField1);
int n = refPointField1.x.n + refPointField1.y.n;
Asserts.assertEQ(result, n);
}
// C1->C2 invokestatic with InlineTypeReturnedAsFields (RefPoint)
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public int test80(RefPoint p) {
RefPoint np = test80_helper(p);
return np.x.n + np.y.n;
}
@DontInline
- @ForceCompile(compLevel = C2)
+ @ForceCompile(CompLevel.C2)
private static RefPoint test80_helper(RefPoint p) {
return p;
}
- @DontCompile
- public void test80_verifier(boolean warmup) {
+ @Run(test = "test80")
+ public void test80_verifier() {
int result = test80(refPointField1);
int n = refPointField1.x.n + refPointField1.y.n;
Asserts.assertEQ(result, n);
}
// Interpreter->C1 invokestatic with InlineTypeReturnedAsFields (Point)
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public Point test81(Point p) {
return p;
}
- @DontCompile
- public void test81_verifier(boolean warmup) {
+ @Run(test = "test81")
+ public void test81_verifier() {
Point p = test81(pointField1);
Asserts.assertEQ(p.x, pointField1.x);
Asserts.assertEQ(p.y, pointField1.y);
@@ -1666,19 +1629,19 @@ public void test81_verifier(boolean warmup) {
}
// C1->Interpreter invokestatic with InlineTypeReturnedAsFields (RefPoint)
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public int test82(RefPoint p) {
RefPoint np = test82_helper(p);
return np.x.n + np.y.n;
}
- @DontInline @DontCompile
+ @DontCompile
private static RefPoint test82_helper(RefPoint p) {
return p;
}
- @DontCompile
- public void test82_verifier(boolean warmup) {
+ @Run(test = "test82")
+ public void test82_verifier() {
int result = test82(refPointField1);
int n = refPointField1.x.n + refPointField1.y.n;
Asserts.assertEQ(result, n);
@@ -1689,72 +1652,72 @@ public void test82_verifier(boolean warmup) {
//-------------------------------------------------------------------------------
// C2->C1 invokestatic with InlineTypeReturnedAsFields (TooBigToReturnAsFields)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test83(TooBigToReturnAsFields p) {
TooBigToReturnAsFields np = test83_helper(p);
return p.a0 + p.a5;
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static TooBigToReturnAsFields test83_helper(TooBigToReturnAsFields p) {
return p;
}
- @DontCompile
- public void test83_verifier(boolean warmup) {
+ @Run(test = "test83")
+ public void test83_verifier() {
int result = test83(tooBig);
int n = tooBig.a0 + tooBig.a5;
Asserts.assertEQ(result, n);
}
// C1->C2 invokestatic with InlineTypeReturnedAsFields (TooBigToReturnAsFields)
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public int test84(TooBigToReturnAsFields p) {
TooBigToReturnAsFields np = test84_helper(p);
return p.a0 + p.a5;
}
@DontInline
- @ForceCompile(compLevel = C2)
+ @ForceCompile(CompLevel.C2)
private static TooBigToReturnAsFields test84_helper(TooBigToReturnAsFields p) {
return p;
}
- @DontCompile
- public void test84_verifier(boolean warmup) {
+ @Run(test = "test84")
+ public void test84_verifier() {
int result = test84(tooBig);
int n = tooBig.a0 + tooBig.a5;
Asserts.assertEQ(result, n);
}
// Interpreter->C1 invokestatic with InlineTypeReturnedAsFields (TooBigToReturnAsFields)
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public TooBigToReturnAsFields test85(TooBigToReturnAsFields p) {
return p;
}
- @DontCompile
- public void test85_verifier(boolean warmup) {
+ @Run(test = "test85")
+ public void test85_verifier() {
TooBigToReturnAsFields p = test85(tooBig);
Asserts.assertEQ(p.a0, tooBig.a0);
Asserts.assertEQ(p.a2, tooBig.a2);
}
// C1->Interpreter invokestatic with InlineTypeReturnedAsFields (TooBigToReturnAsFields)
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public int test86(TooBigToReturnAsFields p) {
TooBigToReturnAsFields np = test86_helper(p);
return p.a0 + p.a5;
}
- @DontInline @DontCompile
+ @DontCompile
private static TooBigToReturnAsFields test86_helper(TooBigToReturnAsFields p) {
return p;
}
- @DontCompile
- public void test86_verifier(boolean warmup) {
+ @Run(test = "test86")
+ public void test86_verifier() {
int result = test86(tooBig);
int n = tooBig.a0 + tooBig.a5;
Asserts.assertEQ(result, n);
@@ -1765,55 +1728,55 @@ public void test86_verifier(boolean warmup) {
//-------------------------------------------------------------------------------
// C2->C1 invokestatic with InlineTypeReturnedAsFields (RefPoint.ref)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public RefPoint.ref test87(RefPoint.ref p) {
return test87_helper(p);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static RefPoint.ref test87_helper(RefPoint.ref p) {
return p;
}
- @DontCompile
- public void test87_verifier(boolean warmup) {
+ @Run(test = "test87")
+ public void test87_verifier() {
Object result = test87(null);
Asserts.assertEQ(result, null);
}
// C2->C1 invokestatic with InlineTypeReturnedAsFields (RefPoint.ref with constant null)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public RefPoint.ref test88() {
return test88_helper();
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static RefPoint.ref test88_helper() {
return null;
}
- @DontCompile
- public void test88_verifier(boolean warmup) {
+ @Run(test = "test88")
+ public void test88_verifier() {
Object result = test88();
Asserts.assertEQ(result, null);
}
// C1->C2 invokestatic with InlineTypeReturnedAsFields (RefPoint.ref)
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public RefPoint.ref test89(RefPoint.ref p) {
return test89_helper(p);
}
@DontInline
- @ForceCompile(compLevel = C2)
+ @ForceCompile(CompLevel.C2)
private static RefPoint.ref test89_helper(RefPoint.ref p) {
return p;
}
- @DontCompile
- public void test89_verifier(boolean warmup) {
+ @Run(test = "test89")
+ public void test89_verifier() {
Object result = test89(null);
Asserts.assertEQ(result, null);
}
@@ -1829,7 +1792,7 @@ public void test89_verifier(boolean warmup) {
//----------------------------------------------------------------------------------
// C1->C1 invokeinterface -- call Unverified Value Entry of MyImplPojo1.func2 (compiled by C1)
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public int test90(Intf intf, int a, int b) {
return intf.func2(a, b, pointField);
}
@@ -1839,9 +1802,9 @@ public int test90(Intf intf, int a, int b) {
new MyImplPojo2(),
};
- @DontCompile
- public void test90_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @Run(test = "test90")
+ public void test90_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC2 invokeinterface -- call Unverified Value Entry of MyImplPojo2.func2 (compiled by C2)
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public int test91(Intf intf, int a, int b) {
return intf.func2(a, b, pointField);
}
@@ -1860,9 +1823,9 @@ public int test91(Intf intf, int a, int b) {
new MyImplPojo1(),
};
- @DontCompile
- public void test91_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @Run(test = "test91")
+ public void test91_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC1 invokeinterface -- call Unverified Entry of MyImplPojo1.func2 (compiled by C1)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test92(Intf intf, int a, int b) {
return intf.func2(a, b, pointField);
}
@@ -1881,9 +1844,9 @@ public int test92(Intf intf, int a, int b) {
new MyImplPojo2(),
};
- @DontCompile
- public void test92_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @Run(test = "test92")
+ public void test92_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC2 invokeinterface -- call Unverified Entry of MyImplPojo2.func2 (compiled by C2)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test93(Intf intf, int a, int b) {
return intf.func2(a, b, pointField);
}
@@ -1902,9 +1865,9 @@ public int test93(Intf intf, int a, int b) {
new MyImplPojo1(),
};
- @DontCompile
- public void test93_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @Run(test = "test93")
+ public void test93_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC1 invokeinterface -- call Unverified Entry of MyImplVal1.func2 (compiled by C1 - has VVEP_RO)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test94(Intf intf, int a, int b) {
return intf.func2(a, b, pointField);
}
@@ -1923,9 +1886,9 @@ public int test94(Intf intf, int a, int b) {
new MyImplVal2(),
};
- @DontCompile
- public void test94_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @Run(test = "test94")
+ public void test94_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC2 invokeinterface -- call Unverified Entry of MyImplVal2.func2 (compiled by C2 - has VVEP_RO)
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test95(Intf intf, int a, int b) {
return intf.func2(a, b, pointField);
}
@@ -1944,9 +1907,9 @@ public int test95(Intf intf, int a, int b) {
new MyImplVal1(),
};
- @DontCompile
- public void test95_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @Run(test = "test95")
+ public void test95_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC2 GC handling in StubRoutines::store_inline_type_fields_to_buf()
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public RefPoint test96(RefPoint rp, boolean b) {
RefPoint p = test96_helper(rp);
if (b) {
@@ -1964,19 +1927,20 @@ public RefPoint test96(RefPoint rp, boolean b) {
return p;
}
- @DontInline @ForceCompile(compLevel = C2)
+ @DontInline
+ @ForceCompile(CompLevel.C2)
public RefPoint test96_helper(RefPoint rp) {
return rp;
}
- @DontCompile
- public void test96_verifier(boolean warmup) {
- int count = warmup ? 1 : 20000; // Do enough iteration to cause GC inside StubRoutines::store_inline_type_fields_to_buf
+ @Run(test = "test96")
+ public void test96_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20000; // Do enough iteration to cause GC inside StubRoutines::store_inline_type_fields_to_buf
Number x = new Number(10); // old object
for (int i=0; itest97.
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public int test97(Point p1, Point p2) {
return test97_helper(p1, p2);
}
- @DontInline @DontCompile
+ @DontCompile
public int test97_helper(Point p1, Point p2) {
return p1.x + p1.y + p2.x + p2.y;
}
- @ForceCompile(compLevel = C1)
- public void test97_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @ForceCompile(CompLevel.C1_SIMPLE)
+ public void test97_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC2 - same as test97, except the callee is compiled by c2.
- @Test(compLevel = C2)
+ @Run(test = "test97")
+ public void run_test97_verifier(RunInfo info) {
+ test97_verifier(info);
+ }
+
+ // C1->C2 - same as test97, except the callee is compiled by C2.
+ @Test(compLevel = CompLevel.C2)
public int test98(Point p1, Point p2) {
return test98_helper(p1, p2);
}
- @DontInline @DontCompile
+ @DontCompile
public int test98_helper(Point p1, Point p2) {
return p1.x + p1.y + p2.x + p2.y;
}
- @ForceCompile(compLevel = C1)
- public void test98_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @ForceCompile(CompLevel.C1_SIMPLE)
+ public void test98_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC2 - same as test97, except the callee is a static method.
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public static int test99(Point p1, Point p2) {
return test99_helper(p1, p2);
}
- @DontInline @DontCompile
+ @DontCompile
public static int test99_helper(Point p1, Point p2) {
return p1.x + p1.y + p2.x + p2.y;
}
- @ForceCompile(compLevel = C1)
- public void test99_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @ForceCompile(CompLevel.C1_SIMPLE)
+ public void test99_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC1 invokestatic, packing causes stack growth (1 extra stack word).
// Make sure stack frame is set up properly for GC.
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public float test100(FloatPoint fp1, FloatPoint fp2, RefPoint rp, int a1, int a2, int a3, int a4) {
return test100_helper(fp1, fp2, rp, a1, a2, a3, a4);
}
@DontInline
- @ForceCompile(compLevel = C1)
+ @ForceCompile(CompLevel.C1_SIMPLE)
private static float test100_helper(FloatPoint fp1, FloatPoint fp2, RefPoint rp, int a1, int a2, int a3, int a4) {
// On x64:
// Scalarized entry -- all parameters are passed in registers
@@ -2084,15 +2062,15 @@ private static float test100_helper(FloatPoint fp1, FloatPoint fp2, RefPoint rp,
return fp1.x + fp1.y + fp2.x + fp2.y + rp.x.n + rp.y.n + a1 + a2 + a3 + a4;
}
- @DontCompile
- public void test100_verifier(boolean warmup) {
- int count = warmup ? 1 : 4;
+ @Run(test = "test100")
+ public void test100_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 4;
for (int i=0; iC2 force GC for every allocation when storing the returned
// fields back into a buffered object.
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public RefPoint test101(RefPoint rp) {
return test101_helper(rp);
}
- @ForceCompile(compLevel = C2) @DontInline
+ @DontInline
+ @ForceCompile(CompLevel.C2)
public RefPoint test101_helper(RefPoint rp) {
return rp;
}
- @DontCompile
- public void test101_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test101")
+ public void test101_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; iC2 instead.
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public RefPoint test102(RefPoint rp) {
return test102_interp(rp);
}
- @DontCompile @DontInline
+ @DontInline
public RefPoint test102_interp(RefPoint rp) {
return test102_helper(rp);
}
- @ForceCompile(compLevel = C2) @DontInline
+ @DontInline
+ @ForceCompile(CompLevel.C2)
public RefPoint test102_helper(RefPoint rp) {
return rp;
}
- @DontCompile
- public void test102_verifier(boolean warmup) {
- int count = warmup ? 1 : 5;
+ @Run(test = "test102")
+ public void test102_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 5;
for (int i=0; i()QTest103Value;"
@@ -2176,9 +2156,9 @@ static primitive class Test103Value {
static Object test103_v;
- @DontCompile
- public void test103_verifier(boolean warmup) {
- if (warmup) {
+ @Run(test = "test103")
+ public void test103_verifier(RunInfo info) {
+ if (info.isWarmUp()) {
// Make sure test103() is compiled before Test103Value is loaded
return;
}
@@ -2189,7 +2169,7 @@ public void test103_verifier(boolean warmup) {
// Same as test103, but with an inline class that's too big to return as fields.
- @Test(compLevel = C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public void test104() {
// when this method is compiled by C1, the Test104Value class is not yet loaded.
test104_v = new Test104Value(); // invokestatic "Test104Value.()QTest104Value;"
@@ -2216,9 +2196,9 @@ static primitive class Test104Value {
static Object test104_v;
- @DontCompile
- public void test104_verifier(boolean warmup) {
- if (warmup) {
+ @Run(test = "test104")
+ public void test104_verifier(RunInfo info) {
+ if (info.isWarmUp()) {
// Make sure test104() is compiled before Test104Value is loaded
return;
}
@@ -2229,7 +2209,7 @@ public void test104_verifier(boolean warmup) {
// C2->C1 invokeinterface -- call Unverified Entry of MyImplVal1.func1 (compiled by C1 - has VVEP_RO)
/// (same as test94, except we are calling func1, which shares VVEP and VVEP_RO
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test105(Intf intf, int a, int b) {
return intf.func1(a, b);
}
@@ -2239,9 +2219,9 @@ public int test105(Intf intf, int a, int b) {
new MyImplVal2(),
};
- @DontCompile
- public void test105_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @Run(test = "test105")
+ public void test105_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC2 invokeinterface -- call Unverified Entry of MyImplVal2.func1 (compiled by C2 - has VVEP_RO)
/// (same as test95, except we are calling func1, which shares VVEP and VVEP_RO
- @Test(compLevel = C2)
+ @Test(compLevel = CompLevel.C2)
public int test106(Intf intf, int a, int b) {
return intf.func1(a, b);
}
@@ -2261,9 +2241,9 @@ public int test106(Intf intf, int a, int b) {
new MyImplVal1(),
};
- @DontCompile
- public void test106_verifier(boolean warmup) {
- int count = warmup ? 1 : 20;
+ @Run(test = "test106")
+ public void test106_verifier(RunInfo info) {
+ int count = info.isWarmUp() ? 1 : 20;
for (int i=0; iC1 invokeinterface -- C2 calls call Unverified Entry of MyImplVal2X.func1 (compiled by
// C1, with VVEP_RO==VVEP)
// This test is developed to validate JDK-8230325.
- @Test() @Warmup(0) @OSRCompileOnly
+ @Test(compLevel = CompLevel.WAIT_FOR_COMPILATION)
public int test107(Intf intf, int a, int b) {
return intf.func1(a, b);
}
@ForceCompile
- public void test107_verifier(boolean warmup) {
+ public void test107_verifier(RunInfo info) {
Intf intf1 = new MyImplVal1X();
Intf intf2 = new MyImplVal2X();
@@ -2302,14 +2282,20 @@ public void test107_verifier(boolean warmup) {
}
}
+ @Run(test = "test107")
+ @Warmup(0)
+ public void run_test107_verifier(RunInfo info) {
+ test107_verifier(info);
+ }
+
// Same as test107, except we call MyImplVal2X.func2 (compiled by C1, VVEP_RO != VVEP)
- @Test() @Warmup(0) @OSRCompileOnly
+ @Test(compLevel = CompLevel.WAIT_FOR_COMPILATION)
public int test108(Intf intf, int a, int b) {
return intf.func2(a, b, pointField);
}
@ForceCompile
- public void test108_verifier(boolean warmup) {
+ public void test108_verifier(RunInfo info) {
Intf intf1 = new MyImplVal1X();
Intf intf2 = new MyImplVal2X();
@@ -2331,14 +2317,20 @@ public void test108_verifier(boolean warmup) {
}
}
+ @Run(test = "test108")
+ @Warmup(0)
+ public void run_test108_verifier(RunInfo info) {
+ test108_verifier(info);
+ }
+
// Same as test107, except we call MyImplPojo3.func2 (compiled by C1, VVEP_RO == VEP)
- @Test() @Warmup(0) @OSRCompileOnly
+ @Test(compLevel = CompLevel.WAIT_FOR_COMPILATION)
public int test109(Intf intf, int a, int b) {
return intf.func2(a, b, pointField);
}
@ForceCompile
- public void test109_verifier(boolean warmup) {
+ public void test109_verifier(RunInfo info) {
Intf intf1 = new MyImplPojo0();
Intf intf2 = new MyImplPojo3();
@@ -2359,4 +2351,10 @@ public void test109_verifier(boolean warmup) {
}
}
}
+
+ @Run(test = "test109")
+ @Warmup(0)
+ public void run_test109_verifier(RunInfo info) {
+ test109_verifier(info);
+ }
}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java
index cd1e91ed553..d2183100fea 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2021, 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
@@ -21,103 +21,88 @@
* questions.
*/
-
package compiler.valhalla.inlinetypes;
-import java.lang.invoke.*;
-import java.lang.reflect.Method;
-import java.nio.file.NoSuchFileException;
-import java.util.Arrays;
-
+import compiler.lib.ir_framework.CompLevel;
+import compiler.lib.ir_framework.Run;
+import compiler.lib.ir_framework.Scenario;
+import compiler.lib.ir_framework.Test;
import jdk.test.lib.Asserts;
+
/*
* @test
* @key randomness
* @summary Verify that chains of getfields on flattened fields are correctly optimized
- * @library /testlibrary /test/lib /compiler/whitebox /
+ * @library /test/lib /
* @requires os.simpleArch == "x64"
- * @compile TestGetfieldChains.java NamedRectangle.java Rectangle.java Point.java GetfieldChains.jcod
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestGetfieldChains
+ * @compile GetfieldChains.jcod
+ * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestGetfieldChains
*/
-public class TestGetfieldChains extends InlineTypeTest {
- public static final int C1 = COMP_LEVEL_SIMPLE;
- public static final int C2 = COMP_LEVEL_FULL_OPTIMIZATION;
-
- public static void main(String[] args) throws Throwable {
- TestGetfieldChains test = new TestGetfieldChains();
- test.run(args, TestGetfieldChains.class);
- }
-
- @Override
- public int getNumScenarios() {
- return 5;
- }
-
- @Override
- public String[] getVMParameters(int scenario) {
- switch (scenario) {
- case 0: return new String[] { // C1 only
- "-XX:TieredStopAtLevel=1",
- "-XX:+TieredCompilation",
- };
- case 1: return new String[] { // C2 only. (Make sure the tests are correctly written)
- "-XX:TieredStopAtLevel=4",
- "-XX:-TieredCompilation",
- "-XX:-OmitStackTraceInFastThrow",
- };
- case 2: return new String[] { // interpreter only
- "-Xint",
- };
- case 3: return new String[] {
- // Xcomp Only C1.
- "-XX:TieredStopAtLevel=1",
- "-XX:+TieredCompilation",
- "-Xcomp",
- };
- case 4: return new String[] {
- // Xcomp Only C2.
- "-XX:TieredStopAtLevel=4",
- "-XX:-TieredCompilation",
- "-XX:-OmitStackTraceInFastThrow",
- "-Xcomp",
- };
- }
- return null;
+public class TestGetfieldChains {
+
+ public static void main(String[] args) {
+
+ final Scenario[] scenarios = {
+ new Scenario(0,
+ // C1 only
+ "-XX:TieredStopAtLevel=1",
+ "-XX:+TieredCompilation"),
+ new Scenario(1,
+ // C2 only. (Make sure the tests are correctly written)
+ "-XX:TieredStopAtLevel=4",
+ "-XX:-TieredCompilation",
+ "-XX:-OmitStackTraceInFastThrow"),
+ new Scenario(2,
+ // interpreter only
+ "-Xint"),
+ new Scenario(3,
+ // Xcomp Only C1.
+ "-XX:TieredStopAtLevel=1",
+ "-XX:+TieredCompilation",
+ "-Xcomp"),
+ new Scenario(4,
+ // Xcomp Only C2.
+ "-XX:TieredStopAtLevel=4",
+ "-XX:-TieredCompilation",
+ "-XX:-OmitStackTraceInFastThrow",
+ "-Xcomp")
+ };
+
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .start();
}
+
// Simple chain of getfields ending with primitive field
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public int test1() {
return NamedRectangle.getP1X(new NamedRectangle());
}
- @DontCompile
- public void test1_verifier(boolean warmup) {
+ @Run(test = "test1")
+ public void test1_verifier() {
int res = test1();
Asserts.assertEQ(res, 4);
}
// Simple chain of getfields ending with a flattened field
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public Point test2() {
return NamedRectangle.getP1(new NamedRectangle());
}
- @DontCompile
- public void test2_verifier(boolean warmup) {
+ @Run(test = "test2")
+ public void test2_verifier() {
Point p = test2();
Asserts.assertEQ(p.x, 4);
Asserts.assertEQ(p.y, 7);
}
// Chain of getfields but the initial receiver is null
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public NullPointerException test3() {
NullPointerException npe = null;
try {
@@ -128,8 +113,8 @@ public NullPointerException test3() {
return npe;
}
- @DontCompile
- public void test3_verifier(boolean warmup) {
+ @Run(test = "test3")
+ public void test3_verifier() {
NullPointerException npe = test3();
Asserts.assertNE(npe, null);
StackTraceElement st = npe.getStackTrace()[0];
@@ -138,7 +123,7 @@ public void test3_verifier(boolean warmup) {
}
// Chain of getfields but one getfield in the middle of the chain trigger an illegal access
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public IllegalAccessError test4() {
IllegalAccessError iae = null;
try {
@@ -149,8 +134,8 @@ public IllegalAccessError test4() {
return iae;
}
- @DontCompile
- public void test4_verifier(boolean warmup) {
+ @Run(test = "test4")
+ public void test4_verifier() {
IllegalAccessError iae = test4();
Asserts.assertNE(iae, null);
StackTraceElement st = iae.getStackTrace()[0];
@@ -160,7 +145,7 @@ public void test4_verifier(boolean warmup) {
}
// Chain of getfields but the last getfield trigger a NoSuchFieldError
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public NoSuchFieldError test5() {
NoSuchFieldError nsfe = null;
try {
@@ -171,8 +156,8 @@ public NoSuchFieldError test5() {
return nsfe;
}
- @DontCompile
- public void test5_verifier(boolean warmup) {
+ @Run(test = "test5")
+ public void test5_verifier() {
NoSuchFieldError nsfe = test5();
Asserts.assertNE(nsfe, null);
StackTraceElement st = nsfe.getStackTrace()[0];
@@ -191,26 +176,26 @@ static primitive class Container {
EmptyContainer container1 = new EmptyContainer();
}
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public EmptyType test6() {
Container c = new Container();
return c.container1.et;
}
- @DontCompile
- public void test6_verifier(boolean warmup) {
+ @Run(test = "test6")
+ public void test6_verifier() {
EmptyType et = test6();
Asserts.assertEQ(et, EmptyType.default);
}
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public EmptyType test7() {
Container[] ca = new Container[10];
return ca[3].container0.et;
}
- @DontCompile
- public void test7_verifier(boolean warmup) {
+ @Run(test = "test7")
+ public void test7_verifier() {
EmptyType et = test7();
Asserts.assertEQ(et, EmptyType.default);
}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIntrinsics.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIntrinsics.java
index e9133760e9d..e8e6e09b985 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIntrinsics.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIntrinsics.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2021, 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,42 +23,46 @@
package compiler.valhalla.inlinetypes;
+import jdk.internal.misc.Unsafe;
+import jdk.test.lib.Asserts;
+import compiler.lib.ir_framework.*;
+
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.Arrays;
-import java.util.List;
-import jdk.test.lib.Asserts;
-import jdk.internal.misc.Unsafe;
+import static compiler.valhalla.inlinetypes.InlineTypes.IRNode.*;
+import static compiler.valhalla.inlinetypes.InlineTypes.rI;
+import static compiler.valhalla.inlinetypes.InlineTypes.rL;
/*
* @test
* @key randomness
* @summary Test intrinsic support for inline types
- * @library /testlibrary /test/lib /compiler/whitebox /
+ * @library /test/lib /
* @modules java.base/jdk.internal.misc
* @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
- * @compile TestIntrinsics.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestIntrinsics
+ * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestIntrinsics
*/
-public class TestIntrinsics extends InlineTypeTest {
- // Extra VM parameters for some test scenarios. See InlineTypeTest.getVMParameters()
- @Override
- public String[] getExtraVMParameters(int scenario) {
- switch (scenario) {
- case 3: return new String[] {"-XX:-MonomorphicArrayCheck", "-XX:FlatArrayElementMaxSize=-1"};
- case 4: return new String[] {"-XX:-MonomorphicArrayCheck"};
+
+@ForceCompileClassInitializer
+public class TestIntrinsics {
+
+ public static void main(String[] args) {
+
+ Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS;
+ for (Scenario scenario: scenarios) {
+ scenario.addFlags("--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED");
}
- return null;
- }
+ scenarios[3].addFlags("-XX:-MonomorphicArrayCheck", "-XX:FlatArrayElementMaxSize=-1");
+ scenarios[4].addFlags("-XX:-MonomorphicArrayCheck");
- public static void main(String[] args) throws Throwable {
- TestIntrinsics test = new TestIntrinsics();
- test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class);
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .addHelperClasses(MyValue1.class,
+ MyValue2.class,
+ MyValue2Inline.class)
+ .start();
}
// Test correctness of the Class::isAssignableFrom intrinsic
@@ -67,8 +71,8 @@ public boolean test1(Class> supercls, Class> subcls) {
return supercls.isAssignableFrom(subcls);
}
- @DontCompile
- public void test1_verifier(boolean warmup) {
+ @Run(test = "test1")
+ public void test1_verifier() {
Asserts.assertTrue(test1(java.util.AbstractList.class, java.util.ArrayList.class), "test1_1 failed");
Asserts.assertTrue(test1(MyValue1.ref.class, MyValue1.ref.class), "test1_2 failed");
Asserts.assertTrue(test1(MyValue1.class, MyValue1.class), "test1_3 failed");
@@ -82,7 +86,8 @@ public void test1_verifier(boolean warmup) {
}
// Verify that Class::isAssignableFrom checks with statically known classes are folded
- @Test(failOn = LOADK)
+ @Test
+ @IR(failOn = {LOADK})
public boolean test2() {
boolean check1 = java.util.AbstractList.class.isAssignableFrom(java.util.ArrayList.class);
boolean check2 = MyValue1.ref.class.isAssignableFrom(MyValue1.ref.class);
@@ -97,8 +102,8 @@ public boolean test2() {
return check1 && check2 && check3 && check4 && check5 && check6 && check7 && check8 && check9 && check10;
}
- @DontCompile
- public void test2_verifier(boolean warmup) {
+ @Run(test = "test2")
+ public void test2_verifier() {
Asserts.assertTrue(test2(), "test2 failed");
}
@@ -108,8 +113,8 @@ public Class> test3(Class> cls) {
return cls.getSuperclass();
}
- @DontCompile
- public void test3_verifier(boolean warmup) {
+ @Run(test = "test3")
+ public void test3_verifier() {
Asserts.assertTrue(test3(Object.class) == null, "test3_1 failed");
Asserts.assertTrue(test3(MyValue1.ref.class) == MyAbstract.class, "test3_2 failed");
Asserts.assertTrue(test3(MyValue1.val.class) == MyValue1.ref.class, "test3_3 failed");
@@ -117,7 +122,8 @@ public void test3_verifier(boolean warmup) {
}
// Verify that Class::getSuperclass checks with statically known classes are folded
- @Test(failOn = LOADK)
+ @Test
+ @IR(failOn = {LOADK})
public boolean test4() {
boolean check1 = Object.class.getSuperclass() == null;
// TODO 8244562: Remove cast as workaround once javac is fixed
@@ -128,8 +134,8 @@ public boolean test4() {
return check1 && check2 && check3 && check4;
}
- @DontCompile
- public void test4_verifier(boolean warmup) {
+ @Run(test = "test4")
+ public void test4_verifier() {
Asserts.assertTrue(test4(), "test4 failed");
}
@@ -139,8 +145,8 @@ public String test5(MyValue1 v) {
return v.toString();
}
- @DontCompile
- public void test5_verifier(boolean warmup) {
+ @Run(test = "test5")
+ public void test5_verifier() {
MyValue1 v = MyValue1.createDefaultInline();
test5(v);
}
@@ -151,8 +157,8 @@ public int test6(MyValue1 v) {
return v.hashCode();
}
- @DontCompile
- public void test6_verifier(boolean warmup) {
+ @Run(test = "test6")
+ public void test6_verifier() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
int res = test6(v);
Asserts.assertEQ(res, v.hashCode());
@@ -165,8 +171,8 @@ public Object[] test7(Class> componentType, int len) {
return va;
}
- @DontCompile
- public void test7_verifier(boolean warmup) {
+ @Run(test = "test7")
+ public void test7_verifier() {
int len = Math.abs(rI) % 42;
long hash = MyValue1.createDefaultDontInline().hashPrimitive();
Object[] va = test7(MyValue1.class, len);
@@ -181,8 +187,8 @@ public boolean test8(Class c, MyValue1 vt) {
return c.isInstance(vt);
}
- @DontCompile
- public void test8_verifier(boolean warmup) {
+ @Run(test = "test8")
+ public void test8_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
boolean result = test8(MyValue1.class, vt);
Asserts.assertTrue(result);
@@ -195,8 +201,8 @@ public boolean test9(Class c, MyValue1 vt) {
return c.isInstance(vt);
}
- @DontCompile
- public void test9_verifier(boolean warmup) {
+ @Run(test = "test9")
+ public void test9_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
boolean result = test9(MyValue2.class, vt);
Asserts.assertFalse(result);
@@ -210,8 +216,8 @@ public Object test10(Class c, MyValue1 vt) {
return c.cast(vt);
}
- @DontCompile
- public void test10_verifier(boolean warmup) {
+ @Run(test = "test10")
+ public void test10_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
Object result = test10(MyValue1.class, vt);
Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
@@ -222,8 +228,8 @@ public Object test11(Class c, MyValue1 vt) {
return c.cast(vt);
}
- @DontCompile
- public void test11_verifier(boolean warmup) {
+ @Run(test = "test11")
+ public void test11_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
try {
test11(MyValue2.class, vt);
@@ -237,8 +243,8 @@ public Object test12(MyValue1 vt) {
return MyValue1.class.cast(vt);
}
- @DontCompile
- public void test12_verifier(boolean warmup) {
+ @Run(test = "test12")
+ public void test12_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
Object result = test12(vt);
Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
@@ -249,8 +255,8 @@ public Object test13(MyValue1 vt) {
return MyValue2.class.cast(vt);
}
- @DontCompile
- public void test13_verifier(boolean warmup) {
+ @Run(test = "test13")
+ public void test13_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
try {
test13(vt);
@@ -268,8 +274,8 @@ public void test14(int len, long hash) {
}
}
- @DontCompile
- public void test14_verifier(boolean warmup) {
+ @Run(test = "test14")
+ public void test14_verifier() {
int len = Math.abs(rI) % 42;
long hash = MyValue1.createDefaultDontInline().hashPrimitive();
test14(len, hash);
@@ -281,8 +287,8 @@ public int test15(Object v) {
return v.hashCode();
}
- @DontCompile
- public void test15_verifier(boolean warmup) {
+ @Run(test = "test15")
+ public void test15_verifier() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
int res = test15(v);
Asserts.assertEQ(res, v.hashCode());
@@ -293,8 +299,8 @@ public int test16(Object v) {
return System.identityHashCode(v);
}
- @DontCompile
- public void test16_verifier(boolean warmup) {
+ @Run(test = "test16")
+ public void test16_verifier() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
int res = test16(v);
Asserts.assertEQ(res, System.identityHashCode((Object)v));
@@ -305,8 +311,8 @@ public int test17(Object v) {
return System.identityHashCode(v);
}
- @DontCompile
- public void test17_verifier(boolean warmup) {
+ @Run(test = "test17")
+ public void test17_verifier() {
Integer v = Integer.valueOf(rI);
int res = test17(v);
Asserts.assertEQ(res, System.identityHashCode(v));
@@ -317,8 +323,8 @@ public int test18(Object v) {
return System.identityHashCode(v);
}
- @DontCompile
- public void test18_verifier(boolean warmup) {
+ @Run(test = "test18")
+ public void test18_verifier() {
Object v = null;
int res = test18(v);
Asserts.assertEQ(res, System.identityHashCode(v));
@@ -331,8 +337,8 @@ public int test19(MyValue1 vt1, MyValue1 vt2, boolean b) {
return res.hashCode();
}
- @DontCompile
- public void test19_verifier(boolean warmup) {
+ @Run(test = "test19")
+ public void test19_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
int res = test19(vt, vt, true);
Asserts.assertEQ(res, vt.hashCode());
@@ -346,8 +352,8 @@ public String test20(MyValue1 vt1, MyValue1 vt2, boolean b) {
return res.toString();
}
- @DontCompile
- public void test20_verifier(boolean warmup) {
+ @Run(test = "test20")
+ public void test20_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
String res = test20(vt, vt, true);
Asserts.assertEQ(res, vt.toString());
@@ -376,20 +382,22 @@ public void test20_verifier(boolean warmup) {
protected static final String CALL_Unsafe = START + "CallStaticJava" + MID + "# Static jdk.internal.misc.Unsafe::" + END;
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public int test21(MyValue1 v) {
return U.getInt(v, X_OFFSET);
}
- @DontCompile
- public void test21_verifier(boolean warmup) {
+ @Run(test = "test21")
+ public void test21_verifier() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
int res = test21(v);
Asserts.assertEQ(res, v.x);
}
MyValue1 test22_vt;
- @Test(failOn=CALL_Unsafe + ALLOC)
+ @Test
+ @IR(failOn = {CALL_Unsafe, ALLOC})
public void test22(MyValue1 v) {
v = U.makePrivateBuffer(v);
U.putInt(v, X_OFFSET, rI);
@@ -397,20 +405,21 @@ public void test22(MyValue1 v) {
test22_vt = v;
}
- @DontCompile
- public void test22_verifier(boolean warmup) {
+ @Run(test = "test22")
+ public void test22_verifier() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
test22(v.setX(v, 0));
Asserts.assertEQ(test22_vt.hash(), v.hash());
}
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public int test23(MyValue1 v, long offset) {
return U.getInt(v, offset);
}
- @DontCompile
- public void test23_verifier(boolean warmup) {
+ @Run(test = "test23")
+ public void test23_verifier() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
int res = test23(v, X_OFFSET);
Asserts.assertEQ(res, v.x);
@@ -418,13 +427,14 @@ public void test23_verifier(boolean warmup) {
MyValue1 test24_vt = MyValue1.createWithFieldsInline(rI, rL);
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public int test24(long offset) {
return U.getInt(test24_vt, offset);
}
- @DontCompile
- public void test24_verifier(boolean warmup) {
+ @Run(test = "test24")
+ public void test24_verifier() {
int res = test24(X_OFFSET);
Asserts.assertEQ(res, test24_vt.x);
}
@@ -446,8 +456,8 @@ public Test25Value[] test25(Test25Value element) {
return (Test25Value[]) newArray;
}
- @DontCompile
- public void test25_verifier(boolean warmup) {
+ @Run(test = "test25")
+ public void test25_verifier() {
Test25Value vt = new Test25Value();
test25(vt);
}
@@ -462,8 +472,8 @@ public Object test26() {
return Array.newInstance(ca[0], 1);
}
- @DontCompile
- public void test26_verifier(boolean warmup) {
+ @Run(test = "test26")
+ public void test26_verifier() {
Object[] res = (Object[])test26();
Asserts.assertEQ(((MyValue1)res[0]).hashPrimitive(), MyValue1.createDefaultInline().hashPrimitive());
}
@@ -480,25 +490,27 @@ public void test26_verifier(boolean warmup) {
}
}
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public MyValue1 test27() {
return (MyValue1)U.getReference(this, TEST27_OFFSET);
}
- @DontCompile
- public void test27_verifier(boolean warmup) {
+ @Run(test = "test27")
+ public void test27_verifier() {
MyValue1 res = test27();
Asserts.assertEQ(res.hash(), test24_vt.hash());
}
// Mismatched type
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public int test28(MyValue1 v) {
return U.getByte(v, X_OFFSET);
}
- @DontCompile
- public void test28_verifier(boolean warmup) {
+ @Run(test = "test28")
+ public void test28_verifier() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
int res = test28(v);
if (java.nio.ByteOrder.nativeOrder() == java.nio.ByteOrder.LITTLE_ENDIAN) {
@@ -509,7 +521,8 @@ public void test28_verifier(boolean warmup) {
}
// Wrong alignment
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public long test29(MyValue1 v) {
// Read the field that's guaranteed to not be last in the
// inline type so we don't read out of bounds.
@@ -519,8 +532,8 @@ public long test29(MyValue1 v) {
return U.getLong(v, Y_OFFSET+1);
}
- @DontCompile
- public void test29_verifier(boolean warmup) {
+ @Run(test = "test29")
+ public void test29_verifier() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
long res = test29(v);
if (java.nio.ByteOrder.nativeOrder() == java.nio.ByteOrder.LITTLE_ENDIAN) {
@@ -539,7 +552,8 @@ public void test29_verifier(boolean warmup) {
}
// getValue to retrieve flattened field from inline type
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public MyValue2 test30(MyValue1 v) {
if (V1_FLATTENED) {
return U.getValue(v, V1_OFFSET, MyValue2.val.class);
@@ -547,8 +561,8 @@ public MyValue2 test30(MyValue1 v) {
return (MyValue2)U.getReference(v, V1_OFFSET);
}
- @DontCompile
- public void test30_verifier(boolean warmup) {
+ @Run(test = "test30")
+ public void test30_verifier() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
MyValue2 res = test30(v);
Asserts.assertEQ(res.hash(), v.v1.hash());
@@ -568,7 +582,8 @@ public void test30_verifier(boolean warmup) {
}
// getValue to retrieve flattened field from object
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public MyValue1 test31() {
if (TEST31_VT_FLATTENED) {
return U.getValue(this, TEST31_VT_OFFSET, MyValue1.val.class);
@@ -576,15 +591,16 @@ public MyValue1 test31() {
return (MyValue1)U.getReference(this, TEST31_VT_OFFSET);
}
- @DontCompile
- public void test31_verifier(boolean warmup) {
+ @Run(test = "test31")
+ public void test31_verifier() {
test31_vt = MyValue1.createWithFieldsInline(rI, rL);
MyValue1 res = test31();
Asserts.assertEQ(res.hash(), test31_vt.hash());
}
// putValue to set flattened field in object
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public void test32(MyValue1 vt) {
if (TEST31_VT_FLATTENED) {
U.putValue(this, TEST31_VT_OFFSET, MyValue1.val.class, vt);
@@ -593,8 +609,8 @@ public void test32(MyValue1 vt) {
}
}
- @DontCompile
- public void test32_verifier(boolean warmup) {
+ @Run(test = "test32")
+ public void test32_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
test31_vt = MyValue1.createDefaultInline();
test32(vt);
@@ -614,7 +630,8 @@ public void test32_verifier(boolean warmup) {
}
}
// getValue to retrieve flattened field from array
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public MyValue1 test33(MyValue1[] arr) {
if (TEST33_FLATTENED_ARRAY) {
return U.getValue(arr, TEST33_BASE_OFFSET + TEST33_INDEX_SCALE, MyValue1.val.class);
@@ -622,8 +639,8 @@ public MyValue1 test33(MyValue1[] arr) {
return (MyValue1)U.getReference(arr, TEST33_BASE_OFFSET + TEST33_INDEX_SCALE);
}
- @DontCompile
- public void test33_verifier(boolean warmup) {
+ @Run(test = "test33")
+ public void test33_verifier() {
MyValue1[] arr = new MyValue1[2];
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
arr[1] = vt;
@@ -632,7 +649,8 @@ public void test33_verifier(boolean warmup) {
}
// putValue to set flattened field in array
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public void test34(MyValue1[] arr, MyValue1 vt) {
if (TEST33_FLATTENED_ARRAY) {
U.putValue(arr, TEST33_BASE_OFFSET + TEST33_INDEX_SCALE, MyValue1.val.class, vt);
@@ -641,8 +659,8 @@ public void test34(MyValue1[] arr, MyValue1 vt) {
}
}
- @DontCompile
- public void test34_verifier(boolean warmup) {
+ @Run(test = "test34")
+ public void test34_verifier() {
MyValue1[] arr = new MyValue1[2];
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
test34(arr, vt);
@@ -651,7 +669,8 @@ public void test34_verifier(boolean warmup) {
// getValue to retrieve flattened field from object with unknown
// container type
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public MyValue1 test35(Object o) {
if (TEST31_VT_FLATTENED) {
return U.getValue(o, TEST31_VT_OFFSET, MyValue1.val.class);
@@ -659,8 +678,8 @@ public MyValue1 test35(Object o) {
return (MyValue1)U.getReference(o, TEST31_VT_OFFSET);
}
- @DontCompile
- public void test35_verifier(boolean warmup) {
+ @Run(test = "test35")
+ public void test35_verifier() {
test31_vt = MyValue1.createWithFieldsInline(rI, rL);
MyValue1 res = test35(this);
Asserts.assertEQ(res.hash(), test31_vt.hash());
@@ -668,7 +687,8 @@ public void test35_verifier(boolean warmup) {
// getValue to retrieve flattened field from object at unknown
// offset
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public MyValue1 test36(long offset) {
if (TEST31_VT_FLATTENED) {
return U.getValue(this, offset, MyValue1.val.class);
@@ -676,8 +696,8 @@ public MyValue1 test36(long offset) {
return (MyValue1)U.getReference(this, offset);
}
- @DontCompile
- public void test36_verifier(boolean warmup) {
+ @Run(test = "test36")
+ public void test36_verifier() {
test31_vt = MyValue1.createWithFieldsInline(rI, rL);
MyValue1 res = test36(TEST31_VT_OFFSET);
Asserts.assertEQ(res.hash(), test31_vt.hash());
@@ -685,7 +705,8 @@ public void test36_verifier(boolean warmup) {
// putValue to set flattened field in object with unknown
// container
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public void test37(Object o, MyValue1 vt) {
if (TEST31_VT_FLATTENED) {
U.putValue(o, TEST31_VT_OFFSET, MyValue1.val.class, vt);
@@ -694,8 +715,8 @@ public void test37(Object o, MyValue1 vt) {
}
}
- @DontCompile
- public void test37_verifier(boolean warmup) {
+ @Run(test = "test37")
+ public void test37_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
test31_vt = MyValue1.createDefaultInline();
test37(this, vt);
@@ -704,7 +725,8 @@ public void test37_verifier(boolean warmup) {
// putValue to set flattened field in object, non inline argument
// to store
- @Test(match = { CALL_Unsafe }, matchCount = { 1 })
+ @Test
+ @IR(counts = {CALL_Unsafe, "= 1"})
public void test38(Object o) {
if (TEST31_VT_FLATTENED) {
U.putValue(this, TEST31_VT_OFFSET, MyValue1.val.class, o);
@@ -713,15 +735,16 @@ public void test38(Object o) {
}
}
- @DontCompile
- public void test38_verifier(boolean warmup) {
+ @Run(test = "test38")
+ public void test38_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
test31_vt = MyValue1.createDefaultInline();
test38(vt);
Asserts.assertEQ(vt.hash(), test31_vt.hash());
}
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public MyValue1 test39(MyValue1 v) {
v = U.makePrivateBuffer(v);
U.putInt(v, X_OFFSET, rI);
@@ -729,8 +752,8 @@ public MyValue1 test39(MyValue1 v) {
return v;
}
- @DontCompile
- public void test39_verifier(boolean warmup) {
+ @Run(test = "test39")
+ public void test39_verifier() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
MyValue1 res = test39(v.setX(v, 0));
Asserts.assertEQ(res.hash(), v.hash());
@@ -743,8 +766,8 @@ public Object[] test40(Class> componentType, int len) {
return va;
}
- @DontCompile
- public void test40_verifier(boolean warmup) {
+ @Run(test = "test40")
+ public void test40_verifier() {
int len = Math.abs(rI) % 42;
Object[] va = test40(MyValue1.ref.class, len);
for (int i = 0; i < len; ++i) {
@@ -758,8 +781,8 @@ public boolean test41(Class c, MyValue1.ref vt) {
return c.isInstance(vt);
}
- @DontCompile
- public void test41_verifier(boolean warmup) {
+ @Run(test = "test41")
+ public void test41_verifier() {
MyValue1.ref vt = MyValue1.createWithFieldsInline(rI, rL);
boolean result = test41(MyValue1.ref.class, vt);
Asserts.assertTrue(result);
@@ -772,8 +795,8 @@ public boolean test42(Class c, MyValue1.ref vt) {
return c.isInstance(vt);
}
- @DontCompile
- public void test42_verifier(boolean warmup) {
+ @Run(test = "test42")
+ public void test42_verifier() {
MyValue1.ref vt = MyValue1.createWithFieldsInline(rI, rL);
boolean result = test42(MyValue2.ref.class, vt);
Asserts.assertFalse(result);
@@ -787,8 +810,8 @@ public Object test43(Class c, MyValue1.ref vt) {
return c.cast(vt);
}
- @DontCompile
- public void test43_verifier(boolean warmup) {
+ @Run(test = "test43")
+ public void test43_verifier() {
MyValue1.ref vt = MyValue1.createWithFieldsInline(rI, rL);
Object result = test43(MyValue1.ref.class, vt);
Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
@@ -801,8 +824,8 @@ public Object test44(Class c, MyValue1.ref vt) {
return c.cast(vt);
}
- @DontCompile
- public void test44_verifier(boolean warmup) {
+ @Run(test = "test44")
+ public void test44_verifier() {
MyValue1.ref vt = MyValue1.createWithFieldsInline(rI, rL);
try {
test44(MyValue2.ref.class, vt);
@@ -816,8 +839,8 @@ public Object test45(MyValue1.ref vt) {
return MyValue1.ref.class.cast(vt);
}
- @DontCompile
- public void test45_verifier(boolean warmup) {
+ @Run(test = "test45")
+ public void test45_verifier() {
MyValue1.ref vt = MyValue1.createWithFieldsInline(rI, rL);
Object result = test45(vt);
Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
@@ -830,8 +853,8 @@ public Object test46(MyValue1.ref vt) {
return MyValue2.ref.class.cast(vt);
}
- @DontCompile
- public void test46_verifier(boolean warmup) {
+ @Run(test = "test46")
+ public void test46_verifier() {
MyValue1.ref vt = MyValue1.createWithFieldsInline(rI, rL);
test46(null);
try {
@@ -846,8 +869,8 @@ public Object test47(MyValue1.ref vt) {
return MyValue1.val.class.cast(vt);
}
- @DontCompile
- public void test47_verifier(boolean warmup) {
+ @Run(test = "test47")
+ public void test47_verifier() {
MyValue1.ref vt = MyValue1.createWithFieldsInline(rI, rL);
Object result = test47(vt);
Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
@@ -863,8 +886,8 @@ public Object test48(Class c, MyValue1.ref vt) {
return c.cast(vt);
}
- @DontCompile
- public void test48_verifier(boolean warmup) {
+ @Run(test = "test48")
+ public void test48_verifier() {
MyValue1.ref vt = MyValue1.createWithFieldsInline(rI, rL);
Object result = test48(MyValue1.class, vt);
Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
@@ -880,8 +903,8 @@ public Object test49(MyValue1 vt) {
return MyValue1.ref.class.cast(vt);
}
- @DontCompile
- public void test49_verifier(boolean warmup) {
+ @Run(test = "test49")
+ public void test49_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
Object result = test49(vt);
Asserts.assertEQ(((MyValue1)result).hash(), vt.hash());
@@ -892,8 +915,8 @@ public Object test50(Class c, Object obj) {
return c.cast(obj);
}
- @DontCompile
- public void test50_verifier(boolean warmup) {
+ @Run(test = "test50")
+ public void test50_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
MyValue1[] va = new MyValue1[42];
MyValue1.ref[] vba = new MyValue1.ref[42];
@@ -928,8 +951,8 @@ public void test51(int len) {
}
}
- @DontCompile
- public void test51_verifier(boolean warmup) {
+ @Run(test = "test51")
+ public void test51_verifier() {
int len = Math.abs(rI) % 42;
test51(len);
}
@@ -956,8 +979,8 @@ public Object[][] test52(int len, int val) {
return result;
}
- @DontCompile
- public void test52_verifier(boolean warmup) {
+ @Run(test = "test52")
+ public void test52_verifier() {
test52(1, 1);
test52(1, 2);
}
@@ -1000,8 +1023,8 @@ public Object[][] test53(Class> c1, Class> c2, int len, int val) {
return result;
}
- @DontCompile
- public void test53_verifier(boolean warmup) {
+ @Run(test = "test53")
+ public void test53_verifier() {
int len = Math.abs(rI) % 42;
test53(MyValue1[].class, MyValue1.ref[].class, len, 1);
test53(MyValue1[].class, MyValue1.ref[].class, len, 2);
@@ -1016,7 +1039,6 @@ public void test54_callee(MyValue1.ref v) { // Use .ref here to make sure the ar
}
@Test()
- @Warmup(10000) // Fill up the TLAB to trigger slow path allocation
public MyValue1 test54(MyValue1 v) {
v = U.makePrivateBuffer(v);
test54_callee(v);
@@ -1024,8 +1046,9 @@ public MyValue1 test54(MyValue1 v) {
return v;
}
- @DontCompile
- public void test54_verifier(boolean warmup) {
+ @Run(test = "test54")
+ @Warmup(10000) // Fill up the TLAB to trigger slow path allocation
+ public void test54_verifier() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
MyValue1 res = test54(v.setX(v, 0));
Asserts.assertEQ(res.hash(), v.hash());
@@ -1034,7 +1057,8 @@ public void test54_verifier(boolean warmup) {
static final MyValue1 test55_vt = MyValue1.createWithFieldsInline(rI, rL);
// Same as test30 but with constant field holder
- @Test(failOn=CALL_Unsafe)
+ @Test
+ @IR(failOn = {CALL_Unsafe})
public MyValue2 test55() {
if (V1_FLATTENED) {
return U.getValue(test55_vt, V1_OFFSET, MyValue2.val.class);
@@ -1042,8 +1066,8 @@ public MyValue2 test55() {
return (MyValue2)U.getReference(test55_vt, V1_OFFSET);
}
- @DontCompile
- public void test55_verifier(boolean warmup) {
+ @Run(test = "test55")
+ public void test55_verifier() {
MyValue2 res = test55();
Asserts.assertEQ(res.hash(), test55_vt.v1.hash());
}
@@ -1057,8 +1081,8 @@ public void test56(int idx) {
}
}
- @DontCompile
- public void test56_verifier(boolean warmup) {
+ @Run(test = "test56")
+ public void test56_verifier() {
test56(0);
}
@@ -1071,8 +1095,8 @@ public void test57() {
}
}
- @DontCompile
- public void test57_verifier(boolean warmup) {
+ @Run(test = "test57")
+ public void test57_verifier() {
test57();
}
@@ -1084,8 +1108,8 @@ public boolean test58(Class> c1, Class> c2) throws Exception {
return obj1 == obj2;
}
- @DontCompile
- public void test58_verifier(boolean warmup) throws Exception {
+ @Run(test = "test58")
+ public void test58_verifier() throws Exception {
boolean res = test58(MyValue1.class, MyValue1.class);
Asserts.assertTrue(res);
res = test58(Object.class, MyValue1.class);
@@ -1103,8 +1127,8 @@ public void test59(Class> c) throws Exception {
}
}
- @DontCompile
- public void test59_verifier(boolean warmup) throws Exception {
+ @Run(test = "test59")
+ public void test59_verifier() throws Exception {
test59(Integer.class);
try {
test59(MyValue1.class);
@@ -1122,8 +1146,8 @@ public boolean test60(Class> c1, Class> c2, boolean b1, boolean b2) throws E
return obj1 == obj2;
}
- @DontCompile
- public void test60_verifier(boolean warmup) throws Exception {
+ @Run(test = "test60")
+ public void test60_verifier() throws Exception {
Asserts.assertTrue(test60(MyValue1.class, MyValue1.class, false, false));
Asserts.assertFalse(test60(MyValue1.class, MyValue2.class, false, false));
Asserts.assertFalse(test60(MyValue1.class, MyValue1.class, false, true));
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestJNICalls.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestJNICalls.java
index bf3662817f2..7e39353ebab 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestJNICalls.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestJNICalls.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2021, 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
@@ -24,32 +24,30 @@
package compiler.valhalla.inlinetypes;
import jdk.test.lib.Asserts;
+import compiler.lib.ir_framework.*;
-import java.lang.reflect.Method;
+import static compiler.valhalla.inlinetypes.InlineTypes.rI;
+import static compiler.valhalla.inlinetypes.InlineTypes.rL;
/*
* @test
* @key randomness
* @summary Test calling native methods with inline type arguments from compiled code.
- * @library /testlibrary /test/lib /compiler/whitebox /
+ * @library /test/lib /
* @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
- * @compile TestJNICalls.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestJNICalls
+ * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestJNICalls
*/
-public class TestJNICalls extends InlineTypeTest {
- // Extra VM parameters for some test scenarios. See InlineTypeTest.getVMParameters()
- @Override
- public String[] getExtraVMParameters(int scenario) {
- return null;
- }
- public static void main(String[] args) throws Throwable {
- TestJNICalls test = new TestJNICalls();
- test.run(args, MyValue1.class);
+@ForceCompileClassInitializer
+public class TestJNICalls {
+
+ public static void main(String[] args) {
+ Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS;
+
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .addHelperClasses(MyValue1.class)
+ .start();
}
static {
@@ -61,7 +59,6 @@ public static void main(String[] args) throws Throwable {
// Pass an inline type to a native method that calls back into Java code and returns an inline type
@Test
- @Warmup(10000) // Make sure native method is compiled
public MyValue1 test1(MyValue1 vt, boolean callback) {
if (!callback) {
return (MyValue1)testMethod1(vt);
@@ -70,8 +67,9 @@ public MyValue1 test1(MyValue1 vt, boolean callback) {
}
}
- @DontCompile
- public void test1_verifier(boolean warmup) {
+ @Run(test = "test1")
+ @Warmup(10000) // Make sure native method is compiled
+ public void test1_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
MyValue1 result = test1(vt, false);
Asserts.assertEQ(result.hash(), vt.hash());
@@ -81,13 +79,13 @@ public void test1_verifier(boolean warmup) {
// Pass an inline type to a native method that calls the hash method and returns the result
@Test
- @Warmup(10000) // Make sure native method is compiled
public long test2(MyValue1 vt) {
return testMethod2(vt);
}
- @DontCompile
- public void test2_verifier(boolean warmup) {
+ @Run(test = "test2")
+ @Warmup(10000) // Make sure native method is compiled
+ public void test2_verifier() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
long result = test2(vt);
Asserts.assertEQ(result, vt.hash());
@@ -105,13 +103,13 @@ private MyValueWithNative(int x) {
// Call a native method with an inline type receiver
@Test
- @Warmup(10000) // Make sure native method is compiled
public int test3(MyValueWithNative vt) {
return vt.testMethod3();
}
- @DontCompile
- public void test3_verifier(boolean warmup) {
+ @Run(test = "test3")
+ @Warmup(10000) // Make sure native method is compiled
+ public void test3_verifier() {
MyValueWithNative vt = new MyValueWithNative(rI);
int result = test3(vt);
Asserts.assertEQ(result, rI);
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java
index 5f2718030ad..4d1deef5078 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java
@@ -23,49 +23,52 @@
package compiler.valhalla.inlinetypes;
-import java.lang.invoke.*;
+import compiler.lib.ir_framework.*;
+import jdk.test.lib.Asserts;
+import test.java.lang.invoke.lib.InstructionHelper;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.util.Arrays;
-import jdk.test.lib.Asserts;
-import test.java.lang.invoke.lib.InstructionHelper;
+import static compiler.valhalla.inlinetypes.InlineTypes.IRNode.*;
+import static compiler.valhalla.inlinetypes.InlineTypes.*;
/*
* @test
* @key randomness
* @summary Test inline types in LWorld.
- * @library /test/lib /test/jdk/lib/testlibrary/bytecode /test/jdk/java/lang/invoke/common /testlibrary /compiler/whitebox /
- * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper
+ * @library /test/lib /test/jdk/lib/testlibrary/bytecode /test/jdk/java/lang/invoke/common /
* @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
- * @compile TestLWorld.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestLWorld
+ * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper
+ * @run driver/timeout=450 compiler.valhalla.inlinetypes.TestLWorld
*/
-public class TestLWorld extends InlineTypeTest {
- // Extra VM parameters for some test scenarios. See InlineTypeTest.getVMParameters()
- @Override
- public String[] getExtraVMParameters(int scenario) {
- switch (scenario) {
- case 2: return new String[] {"-DVerifyIR=false"};
- case 3: return new String[] {"-XX:-MonomorphicArrayCheck", "-XX:FlatArrayElementMaxSize=-1"};
- case 4: return new String[] {"-XX:-MonomorphicArrayCheck"};
- }
- return null;
- }
- public static void main(String[] args) throws Throwable {
+@ForceCompileClassInitializer
+public class TestLWorld {
+
+ public static void main(String[] args) {
// Make sure Test140Value is loaded but not linked
Class> class1 = Test140Value.class;
// Make sure Test141Value is linked but not initialized
Class> class2 = Test141Value.class;
class2.getDeclaredFields();
- TestLWorld test = new TestLWorld();
- test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class, MyValue3.class,
- MyValue3Inline.class, Test51Value.class);
+ Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS;
+ scenarios[2].addFlags("-DVerifyIR=false");
+ scenarios[3].addFlags("-XX:-MonomorphicArrayCheck", "-XX:FlatArrayElementMaxSize=-1");
+ scenarios[4].addFlags("-XX:-MonomorphicArrayCheck");
+
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .addHelperClasses(MyValue1.class,
+ MyValue2.class,
+ MyValue2Inline.class,
+ MyValue3.class,
+ MyValue3Inline.class)
+ .start();
}
// Helper methods
@@ -98,7 +101,7 @@ public MyValue1 test1_inline2(Object o) {
return (MyValue1)o;
}
- @Test()
+ @Test
public MyValue1 test1() {
MyValue1 vt = testValue1;
vt = (MyValue1)test1_dontinline1(vt);
@@ -108,8 +111,8 @@ public MyValue1 test1() {
return vt;
}
- @DontCompile
- public void test1_verifier(boolean warmup) {
+ @Run(test = "test1")
+ public void test1_verifier() {
Asserts.assertEQ(test1().hash(), hash());
}
@@ -142,7 +145,7 @@ public Object readStaticValueField4() {
return (Object)staticValueField4;
}
- @Test()
+ @Test
public long test2(MyValue1 vt1, Object vt2) {
objectField1 = vt1;
objectField2 = (MyValue1)vt2;
@@ -166,8 +169,8 @@ public long test2(MyValue1 vt1, Object vt2) {
staticValueField1.hash() + staticValueField2.hash() + staticValueField3.hashPrimitive();
}
- @DontCompile
- public void test2_verifier(boolean warmup) {
+ @Run(test = "test2")
+ public void test2_verifier() {
MyValue1 vt = testValue1;
MyValue1 def = MyValue1.createDefaultDontInline();
long result = test2(vt, vt);
@@ -175,7 +178,7 @@ public void test2_verifier(boolean warmup) {
}
// Test merging inline types and objects
- @Test()
+ @Test
public Object test3(int state) {
Object res = null;
if (state == 0) {
@@ -198,8 +201,8 @@ public Object test3(int state) {
return res;
}
- @DontCompile
- public void test3_verifier(boolean warmup) {
+ @Run(test = "test3")
+ public void test3_verifier() {
objectField1 = valueField1;
Object result = null;
result = test3(0);
@@ -221,7 +224,7 @@ public void test3_verifier(boolean warmup) {
}
// Test merging inline types and objects in loops
- @Test()
+ @Test
public Object test4(int iters) {
Object res = Integer.valueOf(rI);
for (int i = 0; i < iters; ++i) {
@@ -234,8 +237,8 @@ public Object test4(int iters) {
return res;
}
- @DontCompile
- public void test4_verifier(boolean warmup) {
+ @Run(test = "test4")
+ public void test4_verifier() {
Integer result1 = (Integer)test4(0);
Asserts.assertEQ(result1, rI);
int iters = (Math.abs(rI) % 10) + 1;
@@ -245,28 +248,30 @@ public void test4_verifier(boolean warmup) {
}
// Test inline types in object variables that are live at safepoint
- @Test(failOn = ALLOC + STORE + LOOP)
- public long test5(MyValue1 arg, boolean deopt) {
+ @Test
+ @IR(failOn = {ALLOC, STORE, LOOP})
+ public long test5(MyValue1 arg, boolean deopt, Method m) {
Object vt1 = MyValue1.createWithFieldsInline(rI, rL);
Object vt2 = MyValue1.createWithFieldsDontInline(rI, rL);
Object vt3 = arg;
Object vt4 = valueField1;
if (deopt) {
// uncommon trap
- WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test5"));
+ TestFramework.deoptimize(m);
}
return ((MyValue1)vt1).hash() + ((MyValue1)vt2).hash() +
((MyValue1)vt3).hash() + ((MyValue1)vt4).hash();
}
- @DontCompile
- public void test5_verifier(boolean warmup) {
- long result = test5(valueField1, !warmup);
+ @Run(test = "test5")
+ public void test5_verifier(RunInfo info) {
+ long result = test5(valueField1, !info.isWarmUp(), info.getTest());
Asserts.assertEQ(result, 4*hash());
}
// Test comparing inline types with objects
- @Test(failOn = LOAD + LOOP)
+ @Test
+ @IR(failOn = {LOAD, LOOP})
public boolean test6(Object arg) {
Object vt = MyValue1.createWithFieldsInline(rI, rL);
if (vt == arg || vt == (Object)valueField1 || vt == objectField1 || vt == null ||
@@ -276,8 +281,8 @@ public boolean test6(Object arg) {
return false;
}
- @DontCompile
- public void test6_verifier(boolean warmup) {
+ @Run(test = "test6")
+ public void test6_verifier() {
boolean result = test6(null);
Asserts.assertFalse(result);
}
@@ -294,8 +299,8 @@ public Object test7(boolean flag) {
return res;
}
- @DontCompile
- public void test7_verifier(boolean warmup) {
+ @Run(test = "test7")
+ public void test7_verifier() {
test7(true);
test7(false);
}
@@ -311,8 +316,8 @@ public Object test8(boolean flag) {
return res;
}
- @DontCompile
- public void test8_verifier(boolean warmup) {
+ @Run(test = "test8")
+ public void test8_verifier() {
test8(true);
test8(false);
}
@@ -328,8 +333,8 @@ public Object test9() {
return o;
}
- @DontCompile
- public void test9_verifier(boolean warmup) {
+ @Run(test = "test9")
+ public void test9_verifier() {
test9();
}
@@ -339,7 +344,8 @@ public Object test10_helper() {
return valueField1;
}
- @Test(failOn = ALLOC + LOAD + STORE)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE})
public void test10(boolean flag) {
Object o = null;
if (flag) {
@@ -350,8 +356,8 @@ public void test10(boolean flag) {
valueField1 = (MyValue1)o;
}
- @DontCompile
- public void test10_verifier(boolean warmup) {
+ @Run(test = "test10")
+ public void test10_verifier() {
test10(true);
test10(false);
}
@@ -378,7 +384,7 @@ public MyValue1 test11_inline2(MyInterface o) {
return (MyValue1)o;
}
- @Test()
+ @Test
public MyValue1 test11() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
vt = (MyValue1)test11_dontinline1(vt);
@@ -388,8 +394,8 @@ public MyValue1 test11() {
return vt;
}
- @DontCompile
- public void test11_verifier(boolean warmup) {
+ @Run(test = "test11")
+ public void test11_verifier() {
Asserts.assertEQ(test11().hash(), hash());
}
@@ -411,7 +417,7 @@ public MyInterface readStaticValueField4AsInterface() {
return (MyInterface)staticValueField4;
}
- @Test()
+ @Test
public long test12(MyValue1 vt1, MyInterface vt2) {
interfaceField1 = vt1;
interfaceField2 = (MyValue1)vt2;
@@ -435,8 +441,8 @@ public long test12(MyValue1 vt1, MyInterface vt2) {
staticValueField1.hash() + staticValueField2.hash() + staticValueField3.hashPrimitive();
}
- @DontCompile
- public void test12_verifier(boolean warmup) {
+ @Run(test = "test12")
+ public void test12_verifier() {
MyValue1 vt = testValue1;
MyValue1 def = MyValue1.createDefaultDontInline();
long result = test12(vt, vt);
@@ -457,7 +463,7 @@ public long hash() {
}
// Test merging inline types and interfaces
- @Test()
+ @Test
public MyInterface test13(int state) {
MyInterface res = null;
if (state == 0) {
@@ -476,8 +482,8 @@ public MyInterface test13(int state) {
return res;
}
- @DontCompile
- public void test13_verifier(boolean warmup) {
+ @Run(test = "test13")
+ public void test13_verifier() {
objectField1 = valueField1;
MyInterface result = null;
result = test13(0);
@@ -495,7 +501,7 @@ public void test13_verifier(boolean warmup) {
}
// Test merging inline types and interfaces in loops
- @Test()
+ @Test
public MyInterface test14(int iters) {
MyInterface res = new MyObject1(rI);
for (int i = 0; i < iters; ++i) {
@@ -508,8 +514,8 @@ public MyInterface test14(int iters) {
return res;
}
- @DontCompile
- public void test14_verifier(boolean warmup) {
+ @Run(test = "test14")
+ public void test14_verifier() {
MyObject1 result1 = (MyObject1)test14(0);
Asserts.assertEQ(result1.x, rI);
int iters = (Math.abs(rI) % 10) + 1;
@@ -519,28 +525,30 @@ public void test14_verifier(boolean warmup) {
}
// Test inline types in interface variables that are live at safepoint
- @Test(failOn = ALLOC + STORE + LOOP)
- public long test15(MyValue1 arg, boolean deopt) {
+ @Test
+ @IR(failOn = {ALLOC, STORE, LOOP})
+ public long test15(MyValue1 arg, boolean deopt, Method m) {
MyInterface vt1 = MyValue1.createWithFieldsInline(rI, rL);
MyInterface vt2 = MyValue1.createWithFieldsDontInline(rI, rL);
MyInterface vt3 = arg;
MyInterface vt4 = valueField1;
if (deopt) {
// uncommon trap
- WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test15"));
+ TestFramework.deoptimize(m);
}
return ((MyValue1)vt1).hash() + ((MyValue1)vt2).hash() +
((MyValue1)vt3).hash() + ((MyValue1)vt4).hash();
}
- @DontCompile
- public void test15_verifier(boolean warmup) {
- long result = test15(valueField1, !warmup);
+ @Run(test = "test15")
+ public void test15_verifier(RunInfo info) {
+ long result = test15(valueField1, !info.isWarmUp(), info.getTest());
Asserts.assertEQ(result, 4*hash());
}
// Test comparing inline types with interfaces
- @Test(failOn = LOAD + LOOP)
+ @Test
+ @IR(failOn = {LOAD, LOOP})
public boolean test16(Object arg) {
MyInterface vt = MyValue1.createWithFieldsInline(rI, rL);
if (vt == arg || vt == (MyInterface)valueField1 || vt == interfaceField1 || vt == null ||
@@ -550,8 +558,8 @@ public boolean test16(Object arg) {
return false;
}
- @DontCompile
- public void test16_verifier(boolean warmup) {
+ @Run(test = "test16")
+ public void test16_verifier() {
boolean result = test16(null);
Asserts.assertFalse(result);
}
@@ -568,8 +576,8 @@ public MyValue1 test17(MyValue1 vt, Object obj) {
return vt;
}
- @DontCompile
- public void test17_verifier(boolean warmup) {
+ @Run(test = "test17")
+ public void test17_verifier() {
MyValue1 vt = testValue1;
MyValue1 result = test17(vt, Integer.valueOf(rI));
Asserts.assertEquals(result.hash(), vt.hash());
@@ -582,8 +590,8 @@ public MyValue1 test18(MyValue1 vt) {
return vt;
}
- @DontCompile
- public void test18_verifier(boolean warmup) {
+ @Run(test = "test18")
+ public void test18_verifier() {
MyValue1 vt = testValue1;
MyValue1 result = test18(vt);
Asserts.assertEquals(result.hash(), vt.hash());
@@ -600,8 +608,8 @@ public void test19(MyValue1 vt) {
}
}
- @DontCompile
- public void test19_verifier(boolean warmup) {
+ @Run(test = "test19")
+ public void test19_verifier() {
test19(valueField1);
}
@@ -616,8 +624,8 @@ public void test20(MyValue1 vt) {
}
}
- @DontCompile
- public void test20_verifier(boolean warmup) {
+ @Run(test = "test20")
+ public void test20_verifier() {
test20(valueField1);
}
@@ -638,37 +646,37 @@ public void test20_verifier(boolean warmup) {
private static final Integer[] testIntegerArray = new Integer[42];
// Test load from (flattened) inline type array disguised as object array
- @Test()
+ @Test
public Object test21(Object[] oa, int index) {
return oa[index];
}
- @DontCompile
- public void test21_verifier(boolean warmup) {
+ @Run(test = "test21")
+ public void test21_verifier() {
MyValue1 result = (MyValue1)test21(testValue1Array, Math.abs(rI) % 3);
Asserts.assertEQ(result.hash(), hash());
}
// Test load from (flattened) inline type array disguised as interface array
- @Test()
+ @Test
public Object test22Interface(MyInterface[] ia, int index) {
return ia[index];
}
- @DontCompile
- public void test22Interface_verifier(boolean warmup) {
+ @Run(test = "test22Interface")
+ public void test22Interface_verifier() {
MyValue1 result = (MyValue1)test22Interface(testValue1Array, Math.abs(rI) % 3);
Asserts.assertEQ(result.hash(), hash());
}
// Test load from (flattened) inline type array disguised as abstract array
- @Test()
+ @Test
public Object test22Abstract(MyAbstract[] ia, int index) {
return ia[index];
}
- @DontCompile
- public void test22Abstract_verifier(boolean warmup) {
+ @Run(test = "test22Abstract")
+ public void test22Abstract_verifier() {
MyValue1 result = (MyValue1)test22Abstract(testValue1Array, Math.abs(rI) % 3);
Asserts.assertEQ(result.hash(), hash());
}
@@ -679,13 +687,13 @@ public void test23_inline(Object[] oa, Object o, int index) {
oa[index] = o;
}
- @Test()
+ @Test
public void test23(Object[] oa, MyValue1 vt, int index) {
test23_inline(oa, vt, index);
}
- @DontCompile
- public void test23_verifier(boolean warmup) {
+ @Run(test = "test23")
+ public void test23_verifier() {
int index = Math.abs(rI) % 3;
MyValue1 vt = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
test23(testValue1Array, vt, index);
@@ -705,13 +713,13 @@ public void test24_inline(Object[] oa, Object o, int index) {
oa[index] = o;
}
- @Test()
+ @Test
public void test24(Object[] oa, MyValue1 vt, int index) {
test24_inline(oa, vt, index);
}
- @DontCompile
- public void test24_verifier(boolean warmup) {
+ @Run(test = "test24")
+ public void test24_verifier() {
int index = Math.abs(rI) % 3;
try {
test24(testIntegerArray, testValue1, index);
@@ -726,13 +734,13 @@ public void test25_inline(Object[] oa, Object o, int index) {
oa[index] = o;
}
- @Test()
+ @Test
public void test25(Object[] oa, MyValue1 vt, int index) {
test25_inline(oa, vt, index);
}
- @DontCompile
- public void test25_verifier(boolean warmup) {
+ @Run(test = "test25")
+ public void test25_verifier() {
int index = Math.abs(rI) % 3;
try {
test25(null, testValue1, index);
@@ -748,13 +756,13 @@ public void test26Interface_inline(MyInterface[] ia, MyInterface i, int index) {
ia[index] = i;
}
- @Test()
+ @Test
public void test26Interface(MyInterface[] ia, MyValue1 vt, int index) {
test26Interface_inline(ia, vt, index);
}
- @DontCompile
- public void test26Interface_verifier(boolean warmup) {
+ @Run(test = "test26Interface")
+ public void test26Interface_verifier() {
int index = Math.abs(rI) % 3;
MyValue1 vt = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
test26Interface(testValue1Array, vt, index);
@@ -774,13 +782,13 @@ public void test27Interface_inline(MyInterface[] ia, MyInterface i, int index) {
ia[index] = i;
}
- @Test()
+ @Test
public void test27Interface(MyInterface[] ia, MyValue1 vt, int index) {
test27Interface_inline(ia, vt, index);
}
- @DontCompile
- public void test27Interface_verifier(boolean warmup) {
+ @Run(test = "test27Interface")
+ public void test27Interface_verifier() {
int index = Math.abs(rI) % 3;
try {
test27Interface(null, testValue1, index);
@@ -796,13 +804,13 @@ public void test26Abstract_inline(MyAbstract[] ia, MyAbstract i, int index) {
ia[index] = i;
}
- @Test()
+ @Test
public void test26Abstract(MyAbstract[] ia, MyValue1 vt, int index) {
test26Abstract_inline(ia, vt, index);
}
- @DontCompile
- public void test26Abstract_verifier(boolean warmup) {
+ @Run(test = "test26Abstract")
+ public void test26Abstract_verifier() {
int index = Math.abs(rI) % 3;
MyValue1 vt = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
test26Abstract(testValue1Array, vt, index);
@@ -822,13 +830,13 @@ public void test27Abstract_inline(MyAbstract[] ia, MyAbstract i, int index) {
ia[index] = i;
}
- @Test()
+ @Test
public void test27Abstract(MyAbstract[] ia, MyValue1 vt, int index) {
test27Abstract_inline(ia, vt, index);
}
- @DontCompile
- public void test27Abstract_verifier(boolean warmup) {
+ @Run(test = "test27Abstract")
+ public void test27Abstract_verifier() {
int index = Math.abs(rI) % 3;
try {
test27Abstract(null, testValue1, index);
@@ -844,13 +852,13 @@ public void test28_inline(Object[] oa, Object o, int index) {
oa[index] = o;
}
- @Test()
+ @Test
public void test28(Object[] oa, Object o, int index) {
test28_inline(oa, o, index);
}
- @DontCompile
- public void test28_verifier(boolean warmup) {
+ @Run(test = "test28")
+ public void test28_verifier() {
int index = Math.abs(rI) % 3;
MyValue1 vt1 = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
test28(testValue1Array, vt1, index);
@@ -870,13 +878,13 @@ public void test29_inline(Object[] oa, Object o, int index) {
oa[index] = o;
}
- @Test()
+ @Test
public void test29(Object[] oa, Object o, int index) {
test29_inline(oa, o, index);
}
- @DontCompile
- public void test29_verifier(boolean warmup) {
+ @Run(test = "test29")
+ public void test29_verifier() {
int index = Math.abs(rI) % 3;
try {
test29(testValue2Array, testValue1, index);
@@ -892,13 +900,13 @@ public void test30_inline(Object[] oa, Object o, int index) {
oa[index] = o;
}
- @Test()
+ @Test
public void test30(Object[] oa, Object o, int index) {
test30_inline(oa, o, index);
}
- @DontCompile
- public void test30_verifier(boolean warmup) {
+ @Run(test = "test30")
+ public void test30_verifier() {
int index = Math.abs(rI) % 3;
try {
test30(testIntegerArray, testValue1, index);
@@ -914,13 +922,13 @@ public void test31Interface_inline(MyInterface[] ia, MyInterface i, int index) {
ia[index] = i;
}
- @Test()
+ @Test
public void test31Interface(MyInterface[] ia, MyInterface i, int index) {
test31Interface_inline(ia, i, index);
}
- @DontCompile
- public void test31Interface_verifier(boolean warmup) {
+ @Run(test = "test31Interface")
+ public void test31Interface_verifier() {
int index = Math.abs(rI) % 3;
MyValue1 vt1 = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
test31Interface(testValue1Array, vt1, index);
@@ -940,13 +948,13 @@ public void test32Interface_inline(MyInterface[] ia, MyInterface i, int index) {
ia[index] = i;
}
- @Test()
+ @Test
public void test32Interface(MyInterface[] ia, MyInterface i, int index) {
test32Interface_inline(ia, i, index);
}
- @DontCompile
- public void test32Interface_verifier(boolean warmup) {
+ @Run(test = "test32Interface")
+ public void test32Interface_verifier() {
int index = Math.abs(rI) % 3;
try {
test32Interface(testValue2Array, testValue1, index);
@@ -962,13 +970,13 @@ public void test31Abstract_inline(MyAbstract[] ia, MyAbstract i, int index) {
ia[index] = i;
}
- @Test()
+ @Test
public void test31Abstract(MyAbstract[] ia, MyAbstract i, int index) {
test31Abstract_inline(ia, i, index);
}
- @DontCompile
- public void test31Abstract_verifier(boolean warmup) {
+ @Run(test = "test31Abstract")
+ public void test31Abstract_verifier() {
int index = Math.abs(rI) % 3;
MyValue1 vt1 = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
test31Abstract(testValue1Array, vt1, index);
@@ -988,13 +996,13 @@ public void test32Abstract_inline(MyAbstract[] ia, MyAbstract i, int index) {
ia[index] = i;
}
- @Test()
+ @Test
public void test32Abstract(MyAbstract[] ia, MyAbstract i, int index) {
test32Abstract_inline(ia, i, index);
}
- @DontCompile
- public void test32Abstract_verifier(boolean warmup) {
+ @Run(test = "test32Abstract")
+ public void test32Abstract_verifier() {
int index = Math.abs(rI) % 3;
try {
test32Abstract(testValue2Array, testValue1, index);
@@ -1010,13 +1018,13 @@ public void test33_inline(Object[] oa, Object o, int index) {
oa[index] = o;
}
- @Test()
+ @Test
public void test33(Object[] oa, Object o, int index) {
test33_inline(oa, o, index);
}
- @DontCompile
- public void test33_verifier(boolean warmup) {
+ @Run(test = "test33")
+ public void test33_verifier() {
int index = Math.abs(rI) % 3;
try {
test33(testValue1Array, null, index);
@@ -1034,13 +1042,13 @@ public void test34_inline(Object[] oa, Object o, int index) {
oa[index] = o;
}
- @Test()
+ @Test
public void test34(Object[] oa, int index) {
test34_inline(oa, null, index);
}
- @DontCompile
- public void test34_verifier(boolean warmup) {
+ @Run(test = "test34")
+ public void test34_verifier() {
int index = Math.abs(rI) % 3;
try {
test34(testValue1Array, index);
@@ -1065,13 +1073,13 @@ public void test34_verifier(boolean warmup) {
return_();
});
- @Test()
+ @Test
public void test35(MyValue1[] va, int index) throws Throwable {
setArrayElementNull.invoke(this, va, index);
}
- @DontCompile
- public void test35_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test35")
+ public void test35_verifier() throws Throwable {
int index = Math.abs(rI) % 3;
try {
test35(testValue1Array, index);
@@ -1083,13 +1091,13 @@ public void test35_verifier(boolean warmup) throws Throwable {
}
// Test writing an inline type to a null inline type array
- @Test()
+ @Test
public void test36(MyValue1[] va, MyValue1 vt, int index) {
va[index] = vt;
}
- @DontCompile
- public void test36_verifier(boolean warmup) {
+ @Run(test = "test36")
+ public void test36_verifier() {
int index = Math.abs(rI) % 3;
try {
test36(null, testValue1Array[index], index);
@@ -1105,13 +1113,13 @@ public void test37_inline(Object[] oa, Object o, int index) {
oa[index] = o;
}
- @Test()
+ @Test
public void test37(MyValue1[] va, Object o, int index) {
test37_inline(va, o, index);
}
- @DontCompile
- public void test37_verifier(boolean warmup) {
+ @Run(test = "test37")
+ public void test37_verifier() {
int index = Math.abs(rI) % 3;
MyValue1 vt1 = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
test37(testValue1Array, vt1, index);
@@ -1133,7 +1141,7 @@ public Object[] test38_inline() {
return new MyValue1[42];
}
- @Test()
+ @Test
public Object[] test38(Object[] oa, Object o, int i1, int i2, int num) {
Object[] result = null;
switch (num) {
@@ -1164,8 +1172,8 @@ public Object[] test38(Object[] oa, Object o, int i1, int i2, int num) {
return result;
}
- @DontCompile
- public void test38_verifier(boolean warmup) {
+ @Run(test = "test38")
+ public void test38_verifier() {
int index = Math.abs(rI) % 3;
MyValue1[] va = new MyValue1[42];
Object[] result = test38(null, testValue1, index, index, 0);
@@ -1205,7 +1213,7 @@ public Object test39_inline() {
}
// Same as above but merging into Object instead of Object[]
- @Test()
+ @Test
public Object test39(Object oa, Object o, int i1, int i2, int num) {
Object result = null;
switch (num) {
@@ -1250,8 +1258,8 @@ public Object test39(Object oa, Object o, int i1, int i2, int num) {
return result;
}
- @DontCompile
- public void test39_verifier(boolean warmup) {
+ @Run(test = "test39")
+ public void test39_verifier() {
int index = Math.abs(rI) % 3;
MyValue1[] va = new MyValue1[42];
Object result = test39(null, testValue1, index, index, 0);
@@ -1290,7 +1298,7 @@ public void test39_verifier(boolean warmup) {
}
// Test instanceof with inline types and arrays
- @Test()
+ @Test
public long test40(Object o, int index) {
if (o instanceof MyValue1) {
return ((MyValue1)o).hashInterpreted();
@@ -1308,8 +1316,8 @@ public long test40(Object o, int index) {
return 0;
}
- @DontCompile
- public void test40_verifier(boolean warmup) {
+ @Run(test = "test40")
+ public void test40_verifier() {
int index = Math.abs(rI) % 3;
long result = test40(testValue1, 0);
Asserts.assertEQ(result, testValue1.hash());
@@ -1331,15 +1339,15 @@ public void test41_dontinline(Object o) {
Asserts.assertEQ(o, rI);
}
- @Test()
+ @Test
public void test41() {
MyValue1[] vals = new MyValue1[] {testValue1};
test41_dontinline(vals[0].oa[0]);
test41_dontinline(vals[0].oa[0]);
}
- @DontCompile
- public void test41_verifier(boolean warmup) {
+ @Run(test = "test41")
+ public void test41_verifier() {
test41();
}
@@ -1347,26 +1355,26 @@ public void test41_verifier(boolean warmup) {
private static final MyValue1.ref test42VT1 = MyValue1.createWithFieldsInline(rI, rL);
private static final MyValue1.ref test42VT2 = MyValue1.createWithFieldsInline(rI + 1, rL + 1);
- @Test()
+ @Test
public void test42() {
MyValue1[] vals = new MyValue1[] {(MyValue1) test42VT1, (MyValue1) test42VT2};
Asserts.assertEQ(vals[0].hash(), test42VT1.hash());
Asserts.assertEQ(vals[1].hash(), test42VT2.hash());
}
- @DontCompile
- public void test42_verifier(boolean warmup) {
- if (!warmup) test42(); // We need -Xcomp behavior
+ @Run(test = "test42")
+ public void test42_verifier(RunInfo info) {
+ if (!info.isWarmUp()) test42(); // We need -Xcomp behavior
}
// Test for bug in Escape Analysis
- @Test()
- public long test43(boolean deopt) {
+ @Test
+ public long test43(boolean deopt, Method m) {
MyValue1[] vals = new MyValue1[] {(MyValue1) test42VT1, (MyValue1) test42VT2};
if (deopt) {
// uncommon trap
- WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test43"));
+ TestFramework.deoptimize(m);
Asserts.assertEQ(vals[0].hash(), test42VT1.hash());
Asserts.assertEQ(vals[1].hash(), test42VT2.hash());
}
@@ -1374,9 +1382,9 @@ public long test43(boolean deopt) {
return vals[0].hash();
}
- @DontCompile
- public void test43_verifier(boolean warmup) {
- test43(!warmup);
+ @Run(test = "test43")
+ public void test43_verifier(RunInfo info) {
+ test43(!info.isWarmUp(), info.getTest());
}
// Tests writing an array element with a (statically known) incompatible type
@@ -1392,13 +1400,13 @@ public void test43_verifier(boolean warmup) {
return_();
});
- @Test()
+ @Test
public void test44(MyValue1[] va, int index, MyValue2 v) throws Throwable {
setArrayElementIncompatible.invoke(this, va, index, v);
}
- @DontCompile
- public void test44_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test44")
+ public void test44_verifier() throws Throwable {
int index = Math.abs(rI) % 3;
try {
test44(testValue1Array, index, testValue2);
@@ -1415,13 +1423,13 @@ public void test45_inline(Object[] oa, Object o, int index) {
oa[index] = o;
}
- @Test()
+ @Test
public void test45(MyValue1[] va, int index, MyValue2 v) throws Throwable {
test45_inline(va, v, index);
}
- @DontCompile
- public void test45_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test45")
+ public void test45_verifier() throws Throwable {
int index = Math.abs(rI) % 3;
try {
test45(testValue1Array, index, testValue2);
@@ -1439,8 +1447,8 @@ public boolean test46(MyValue1 vt) {
return obj instanceof MyValue1;
}
- @DontCompile
- public void test46_verifier(boolean warmup) {
+ @Run(test = "test46")
+ public void test46_verifier() {
MyValue1 vt = testValue1;
boolean result = test46(vt);
Asserts.assertTrue(result);
@@ -1452,8 +1460,8 @@ public boolean test47(MyValue1 vt) {
return obj instanceof MyValue2;
}
- @DontCompile
- public void test47_verifier(boolean warmup) {
+ @Run(test = "test47")
+ public void test47_verifier() {
MyValue1 vt = testValue1;
boolean result = test47(vt);
Asserts.assertFalse(result);
@@ -1464,8 +1472,8 @@ public boolean test48(Object obj) {
return obj instanceof MyValue1;
}
- @DontCompile
- public void test48_verifier(boolean warmup) {
+ @Run(test = "test48")
+ public void test48_verifier() {
MyValue1 vt = testValue1;
boolean result = test48(vt);
Asserts.assertTrue(result);
@@ -1476,8 +1484,8 @@ public boolean test49(Object obj) {
return obj instanceof MyValue2;
}
- @DontCompile
- public void test49_verifier(boolean warmup) {
+ @Run(test = "test49")
+ public void test49_verifier() {
MyValue1 vt = testValue1;
boolean result = test49(vt);
Asserts.assertFalse(result);
@@ -1488,8 +1496,8 @@ public boolean test50(Object obj) {
return obj instanceof MyValue1;
}
- @DontCompile
- public void test50_verifier(boolean warmup) {
+ @Run(test = "test50")
+ public void test50_verifier() {
boolean result = test49(Integer.valueOf(42));
Asserts.assertFalse(result);
}
@@ -1573,13 +1581,13 @@ public long test(Test51Value holder, MyValue1 vt1, Object vt2) {
}
// Same as test2 but with field holder being an inline type
- @Test()
+ @Test
public long test51(Test51Value holder, MyValue1 vt1, Object vt2) {
return holder.test(holder, vt1, vt2);
}
- @DontCompile
- public void test51_verifier(boolean warmup) {
+ @Run(test = "test51")
+ public void test51_verifier() {
MyValue1 vt = testValue1;
MyValue1 def = MyValue1.createDefaultDontInline();
Test51Value holder = new Test51Value();
@@ -1590,56 +1598,56 @@ public void test51_verifier(boolean warmup) {
}
// Access non-flattened, uninitialized inline type field with inline type holder
- @Test()
+ @Test
public void test52(Test51Value holder) {
if ((Object)holder.valueField5 != null) {
throw new RuntimeException("Should be null");
}
}
- @DontCompile
- public void test52_verifier(boolean warmup) {
+ @Run(test = "test52")
+ public void test52_verifier() {
Test51Value vt = Test51Value.default;
test52(vt);
}
// Merging inline types of different types
- @Test()
+ @Test
public Object test53(Object o, boolean b) {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
return b ? vt : o;
}
- @DontCompile
- public void test53_verifier(boolean warmup) {
+ @Run(test = "test53")
+ public void test53_verifier() {
test53(new Object(), false);
MyValue1 result = (MyValue1)test53(new Object(), true);
Asserts.assertEQ(result.hash(), hash());
}
- @Test()
+ @Test
public Object test54(boolean b) {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
return b ? vt : testValue2;
}
- @DontCompile
- public void test54_verifier(boolean warmup) {
+ @Run(test = "test54")
+ public void test54_verifier() {
MyValue1 result1 = (MyValue1)test54(true);
Asserts.assertEQ(result1.hash(), hash());
MyValue2 result2 = (MyValue2)test54(false);
Asserts.assertEQ(result2.hash(), testValue2.hash());
}
- @Test()
+ @Test
public Object test55(boolean b) {
MyValue1 vt1 = MyValue1.createWithFieldsInline(rI, rL);
MyValue2 vt2 = MyValue2.createWithFieldsInline(rI, rD);
return b ? vt1 : vt2;
}
- @DontCompile
- public void test55_verifier(boolean warmup) {
+ @Run(test = "test55")
+ public void test55_verifier() {
MyValue1 result1 = (MyValue1)test55(true);
Asserts.assertEQ(result1.hash(), hash());
MyValue2 result2 = (MyValue2)test55(false);
@@ -1647,15 +1655,15 @@ public void test55_verifier(boolean warmup) {
}
// Test synchronization on inline types
- @Test()
+ @Test
public void test56(Object vt) {
synchronized (vt) {
throw new RuntimeException("test56 failed: synchronization on inline type should not succeed");
}
}
- @DontCompile
- public void test56_verifier(boolean warmup) {
+ @Run(test = "test56")
+ public void test56_verifier() {
try {
test56(testValue1);
throw new RuntimeException("test56 failed: no exception thrown");
@@ -1671,13 +1679,13 @@ public void test57_inline(Object vt) {
}
}
- @Test()
+ @Test
public void test57(MyValue1 vt) {
test57_inline(vt);
}
- @DontCompile
- public void test57_verifier(boolean warmup) {
+ @Run(test = "test57")
+ public void test57_verifier() {
try {
test57(testValue1);
throw new RuntimeException("test57 failed: no exception thrown");
@@ -1693,14 +1701,14 @@ public void test58_inline(Object vt) {
}
}
- @Test()
+ @Test
public void test58() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
test58_inline(vt);
}
- @DontCompile
- public void test58_verifier(boolean warmup) {
+ @Run(test = "test58")
+ public void test58_verifier() {
try {
test58();
throw new RuntimeException("test58 failed: no exception thrown");
@@ -1709,7 +1717,7 @@ public void test58_verifier(boolean warmup) {
}
}
- @Test()
+ @Test
public void test59(Object o, boolean b) {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
Object sync = b ? vt : o;
@@ -1720,8 +1728,8 @@ public void test59(Object o, boolean b) {
}
}
- @DontCompile
- public void test59_verifier(boolean warmup) {
+ @Run(test = "test59")
+ public void test59_verifier() {
test59(new Object(), false);
try {
test59(new Object(), true);
@@ -1731,7 +1739,7 @@ public void test59_verifier(boolean warmup) {
}
}
- @Test()
+ @Test
public void test60(boolean b) {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
Object sync = b ? vt : testValue2;
@@ -1740,8 +1748,8 @@ public void test60(boolean b) {
}
}
- @DontCompile
- public void test60_verifier(boolean warmup) {
+ @Run(test = "test60")
+ public void test60_verifier() {
try {
test60(false);
throw new RuntimeException("test60 failed: no exception thrown");
@@ -1757,7 +1765,7 @@ public void test60_verifier(boolean warmup) {
}
// Test catching the IllegalMonitorStateException in compiled code
- @Test()
+ @Test
public void test61(Object vt) {
boolean thrown = false;
try {
@@ -1772,12 +1780,12 @@ public void test61(Object vt) {
}
}
- @DontCompile
- public void test61_verifier(boolean warmup) {
+ @Run(test = "test61")
+ public void test61_verifier() {
test61(testValue1);
}
- @Test()
+ @Test
public void test62(Object o) {
try {
synchronized (o) { }
@@ -1788,19 +1796,19 @@ public void test62(Object o) {
throw new RuntimeException("test62 failed: no exception thrown");
}
- @DontCompile
- public void test62_verifier(boolean warmup) {
+ @Run(test = "test62")
+ public void test62_verifier() {
test62(testValue1);
}
// Test synchronization without any instructions in the synchronized block
- @Test()
+ @Test
public void test63(Object o) {
synchronized (o) { }
}
- @DontCompile
- public void test63_verifier(boolean warmup) {
+ @Run(test = "test63")
+ public void test63_verifier() {
try {
test63(testValue1);
} catch (IllegalMonitorStateException ex) {
@@ -1816,13 +1824,13 @@ public MyInterface test64Interface_helper(MyValue1 vt) {
return vt;
}
- @Test()
+ @Test
public MyInterface test64Interface(MyValue1 vt) {
return test64Interface_helper(vt);
}
- @DontCompile
- public void test64Interface_verifier(boolean warmup) {
+ @Run(test = "test64Interface")
+ public void test64Interface_verifier() {
test64Interface(testValue1);
}
@@ -1832,60 +1840,60 @@ public MyAbstract test64Abstract_helper(MyValue1 vt) {
return vt;
}
- @Test()
+ @Test
public MyAbstract test64Abstract(MyValue1 vt) {
return test64Abstract_helper(vt);
}
- @DontCompile
- public void test64Abstract_verifier(boolean warmup) {
+ @Run(test = "test64Abstract")
+ public void test64Abstract_verifier() {
test64Abstract(testValue1);
}
// Array store tests
- @Test()
+ @Test
public void test65(Object[] array, MyValue1 vt) {
array[0] = vt;
}
- @DontCompile
- public void test65_verifier(boolean warmup) {
+ @Run(test = "test65")
+ public void test65_verifier() {
Object[] array = new Object[1];
test65(array, testValue1);
Asserts.assertEQ(((MyValue1)array[0]).hash(), testValue1.hash());
}
- @Test()
+ @Test
public void test66(Object[] array, MyValue1 vt) {
array[0] = vt;
}
- @DontCompile
- public void test66_verifier(boolean warmup) {
+ @Run(test = "test66")
+ public void test66_verifier() {
MyValue1[] array = new MyValue1[1];
test66(array, testValue1);
Asserts.assertEQ(array[0].hash(), testValue1.hash());
}
- @Test()
+ @Test
public void test67(Object[] array, Object vt) {
array[0] = vt;
}
- @DontCompile
- public void test67_verifier(boolean warmup) {
+ @Run(test = "test67")
+ public void test67_verifier() {
MyValue1[] array = new MyValue1[1];
test67(array, testValue1);
Asserts.assertEQ(array[0].hash(), testValue1.hash());
}
- @Test()
+ @Test
public void test68(Object[] array, Integer o) {
array[0] = o;
}
- @DontCompile
- public void test68_verifier(boolean warmup) {
+ @Run(test = "test68")
+ public void test68_verifier() {
Integer[] array = new Integer[1];
test68(array, 1);
Asserts.assertEQ(array[0], Integer.valueOf(1));
@@ -1898,7 +1906,8 @@ public Object test69_sum(Object a, Object b) {
return MyValue1.setX(((MyValue1)a), sum);
}
- @Test(failOn = ALLOC + STORE)
+ @Test
+ @IR(failOn = {ALLOC, STORE})
public int test69(MyValue1[] array) {
MyValue1 result = MyValue1.createDefaultInline();
for (int i = 0; i < array.length; ++i) {
@@ -1907,8 +1916,8 @@ public int test69(MyValue1[] array) {
return result.x;
}
- @DontCompile
- public void test69_verifier(boolean warmup) {
+ @Run(test = "test69")
+ public void test69_verifier() {
int result = test69(testValue1Array);
Asserts.assertEQ(result, rI * testValue1Array.length);
}
@@ -1920,7 +1929,8 @@ public MyInterface test70Interface_sum(MyInterface a, MyInterface b) {
return MyValue1.setX(((MyValue1)a), sum);
}
- @Test(failOn = ALLOC + STORE)
+ @Test
+ @IR(failOn = {ALLOC, STORE})
public int test70Interface(MyValue1[] array) {
MyValue1 result = MyValue1.createDefaultInline();
for (int i = 0; i < array.length; ++i) {
@@ -1929,8 +1939,8 @@ public int test70Interface(MyValue1[] array) {
return result.x;
}
- @DontCompile
- public void test70Interface_verifier(boolean warmup) {
+ @Run(test = "test70Interface")
+ public void test70Interface_verifier() {
int result = test70Interface(testValue1Array);
Asserts.assertEQ(result, rI * testValue1Array.length);
}
@@ -1942,7 +1952,8 @@ public MyAbstract test70Abstract_sum(MyAbstract a, MyAbstract b) {
return MyValue1.setX(((MyValue1)a), sum);
}
- @Test(failOn = ALLOC + STORE)
+ @Test
+ @IR(failOn = {ALLOC, STORE})
public int test70Abstract(MyValue1[] array) {
MyValue1 result = MyValue1.createDefaultInline();
for (int i = 0; i < array.length; ++i) {
@@ -1951,8 +1962,8 @@ public int test70Abstract(MyValue1[] array) {
return result.x;
}
- @DontCompile
- public void test70Abstract_verifier(boolean warmup) {
+ @Run(test = "test70Abstract")
+ public void test70Abstract_verifier() {
int result = test70Abstract(testValue1Array);
Asserts.assertEQ(result, rI * testValue1Array.length);
}
@@ -1974,8 +1985,8 @@ public MyValue1 test71() {
return test71_inline(null);
}
- @DontCompile
- public void test71_verifier(boolean warmup) {
+ @Run(test = "test71")
+ public void test71_verifier() {
MyValue1 vt = test71();
Asserts.assertEquals(vt.hash(), hash());
}
@@ -1992,14 +2003,14 @@ public int get() {
public void unused(Test72Value vt) { }
@Test
- @Warmup(0)
public int test72() {
Test72Value vt = Test72Value.default;
return vt.get();
}
- @DontCompile
- public void test72_verifier(boolean warmup) {
+ @Run(test = "test72")
+ @Warmup(0)
+ public void test72_verifier() {
int result = test72();
Asserts.assertEquals(result, 0);
}
@@ -2010,8 +2021,8 @@ public Object test73(Object[] va) {
return va[0];
}
- @DontCompile
- public void test73_verifier(boolean warmup) {
+ @Run(test = "test73")
+ public void test73_verifier() {
MyValue1 vt = (MyValue1)test73(testValue1Array);
Asserts.assertEquals(testValue1Array[0].hash(), vt.hash());
}
@@ -2021,8 +2032,8 @@ public void test74(Object[] va, Object vt) {
va[0] = vt;
}
- @DontCompile
- public void test74_verifier(boolean warmup) {
+ @Run(test = "test74")
+ public void test74_verifier() {
MyValue1[] va = new MyValue1[1];
test74(va, testValue1);
Asserts.assertEquals(va[0].hash(), testValue1.hash());
@@ -2042,8 +2053,8 @@ public Object test75(Object o) {
return arr[0];
}
- @DontCompile
- public void test75_verifier(boolean warmup) {
+ @Run(test = "test75")
+ public void test75_verifier() {
test75(42);
}
@@ -2058,8 +2069,8 @@ public MyValue1 test76(Integer i) throws Throwable {
return test76_helper(i);
}
- @DontCompile
- public void test76_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test76")
+ public void test76_verifier() throws Throwable {
try {
test76(null);
throw new RuntimeException("NullPointerException expected");
@@ -2081,8 +2092,8 @@ public MyValue1 test77(Integer i) throws Throwable {
return test77_helper(i);
}
- @DontCompile
- public void test77_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test77")
+ public void test77_verifier() throws Throwable {
try {
test77(Integer.valueOf(42));
throw new RuntimeException("ClassCastException expected");
@@ -2104,8 +2115,8 @@ public MyValue1.ref test78(Integer i) throws Throwable {
return test78_helper(i);
}
- @DontCompile
- public void test78_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test78")
+ public void test78_verifier() throws Throwable {
try {
test78(null); // Should not throw
} catch (Exception e) {
@@ -2124,8 +2135,8 @@ public MyValue1.ref test79(Integer i) throws Throwable {
return test79_helper(i);
}
- @DontCompile
- public void test79_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test79")
+ public void test79_verifier() throws Throwable {
try {
test79(Integer.valueOf(42));
throw new RuntimeException("ClassCastException expected");
@@ -2169,8 +2180,8 @@ public long test80() {
return small.i + small.big.l0 + smallDefault.i + smallDefault.big.l29 + big.l0 + bigDefault.l29;
}
- @DontCompile
- public void test80_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test80")
+ public void test80_verifier() throws Throwable {
long result = test80();
Asserts.assertEQ(result, rI + 2*rL);
}
@@ -2180,7 +2191,8 @@ public int test81Callee(MyValue1 vt) {
return vt.x;
}
- @Test(failOn = ALLOC + LOAD + STORE)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE})
public int test81() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
int result = 0;
@@ -2194,8 +2206,8 @@ public int test81() {
return result;
}
- @DontCompile
- public void test81_verifier(boolean warmup) {
+ @Run(test = "test81")
+ public void test81_verifier() {
int result = test81();
Asserts.assertEQ(result, 10*rI);
}
@@ -2206,11 +2218,11 @@ public void test82(Object[] dst, Object v) {
dst[0] = v;
}
- @DontCompile
- public void test82_verifier(boolean warmup) {
+ @Run(test = "test82")
+ public void test82_verifier(RunInfo info) {
MyValue2[] dst = new MyValue2[1];
test82(dst, testValue2);
- if (!warmup) {
+ if (!info.isWarmUp()) {
try {
test82(dst, null);
throw new RuntimeException("No ArrayStoreException thrown");
@@ -2221,7 +2233,6 @@ public void test82_verifier(boolean warmup) {
}
@Test
- @Warmup(10000)
public void test83(Object[] dst, Object v, boolean flag) {
if (dst == null) { // null check
}
@@ -2234,12 +2245,13 @@ public void test83(Object[] dst, Object v, boolean flag) {
dst[0] = v;
}
- @DontCompile
- public void test83_verifier(boolean warmup) {
+ @Run(test = "test83")
+ @Warmup(10000)
+ public void test83_verifier(RunInfo info) {
MyValue2[] dst = new MyValue2[1];
test83(dst, testValue2, false);
test83(dst, testValue2, true);
- if (!warmup) {
+ if (!info.isWarmUp()) {
try {
test83(dst, null, true);
throw new RuntimeException("No ArrayStoreException thrown");
@@ -2249,98 +2261,104 @@ public void test83_verifier(boolean warmup) {
}
}
- private void rerun_and_recompile_for(String name, int num, Runnable test) {
- Method m = tests.get(name);
-
+ private void rerun_and_recompile_for(Method m, int num, Runnable test) {
for (int i = 1; i < num; i++) {
test.run();
- if (!WHITE_BOX.isMethodCompiled(m, false)) {
- enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION);
+ if (!TestFramework.isCompiled(m)) {
+ TestFramework.compile(m, CompLevel.C2);
}
}
}
// Tests for the Loop Unswitching optimization
// Should make 2 copies of the loop, one for non flattened arrays, one for other cases.
- @Test(match = { COUNTEDLOOP_MAIN }, matchCount = { 2 } )
- @Warmup(0)
+ @Test
+ @IR(counts = {COUNTEDLOOP_MAIN, "= 2"})
public void test84(Object[] src, Object[] dst) {
for (int i = 0; i < src.length; i++) {
dst[i] = src[i];
}
}
- @DontCompile
- public void test84_verifier(boolean warmup) {
+ @Run(test = "test84")
+ @Warmup(0)
+ public void test84_verifier(RunInfo info) {
MyValue2[] src = new MyValue2[100];
Arrays.fill(src, testValue2);
MyValue2[] dst = new MyValue2[100];
- rerun_and_recompile_for("TestLWorld::test84", 10,
+ rerun_and_recompile_for(info.getTest(), 10,
() -> { test84(src, dst);
Asserts.assertTrue(Arrays.equals(src, dst)); });
}
- @Test(valid = G1GCOn, match = { COUNTEDLOOP, LOAD_UNKNOWN_INLINE }, matchCount = { 2, 1 } )
- @Test(valid = G1GCOff, match = { COUNTEDLOOP_MAIN, LOAD_UNKNOWN_INLINE }, matchCount = { 2, 4 } )
- @Warmup(0)
+ @Test
+ @IR(applyIf = {"UseG1GC", "true"},
+ counts = {COUNTEDLOOP, "= 2", LOAD_UNKNOWN_INLINE, "= 1"})
+ @IR(applyIf = {"UseG1GC", "false"},
+ counts = {COUNTEDLOOP_MAIN, "= 2", LOAD_UNKNOWN_INLINE, "= 4"})
public void test85(Object[] src, Object[] dst) {
for (int i = 0; i < src.length; i++) {
dst[i] = src[i];
}
}
- @DontCompile
- public void test85_verifier(boolean warmup) {
+ @Run(test = "test85")
+ @Warmup(0)
+ public void test85_verifier(RunInfo info) {
Object[] src = new Object[100];
Arrays.fill(src, new Object());
src[0] = null;
Object[] dst = new Object[100];
- rerun_and_recompile_for("TestLWorld::test85", 10,
+ rerun_and_recompile_for(info.getTest(), 10,
() -> { test85(src, dst);
Asserts.assertTrue(Arrays.equals(src, dst)); });
}
- @Test(valid = G1GCOn, match = { COUNTEDLOOP }, matchCount = { 2 } )
- @Test(valid = G1GCOff, match = { COUNTEDLOOP_MAIN }, matchCount = { 2 } )
- @Warmup(0)
+ @Test
+ @IR(applyIf = {"UseG1GC", "true"},
+ counts = {COUNTEDLOOP, "= 2"})
+ @IR(applyIf = {"UseG1GC", "false"},
+ counts = {COUNTEDLOOP_MAIN, "= 2"})
public void test86(Object[] src, Object[] dst) {
for (int i = 0; i < src.length; i++) {
dst[i] = src[i];
}
}
- @DontCompile
- public void test86_verifier(boolean warmup) {
+ @Run(test = "test86")
+ @Warmup(0)
+ public void test86_verifier(RunInfo info) {
MyValue2[] src = new MyValue2[100];
Arrays.fill(src, testValue2);
Object[] dst = new Object[100];
- rerun_and_recompile_for("TestLWorld::test86", 10,
+ rerun_and_recompile_for(info.getTest(), 10,
() -> { test86(src, dst);
Asserts.assertTrue(Arrays.equals(src, dst)); });
}
- @Test(match = { COUNTEDLOOP_MAIN }, matchCount = { 2 } )
- @Warmup(0)
+ @Test
+ @IR(counts = {COUNTEDLOOP_MAIN, "= 2"})
public void test87(Object[] src, Object[] dst) {
for (int i = 0; i < src.length; i++) {
dst[i] = src[i];
}
}
- @DontCompile
- public void test87_verifier(boolean warmup) {
+ @Run(test = "test87")
+ @Warmup(0)
+ public void test87_verifier(RunInfo info) {
Object[] src = new Object[100];
Arrays.fill(src, testValue2);
MyValue2[] dst = new MyValue2[100];
- rerun_and_recompile_for("TestLWorld::test87", 10,
+ rerun_and_recompile_for(info.getTest(), 10,
() -> { test87(src, dst);
Asserts.assertTrue(Arrays.equals(src, dst)); });
}
- @Test(match = { COUNTEDLOOP_MAIN }, matchCount = { 2 } )
- @Warmup(0)
+ @Test
+ @IR(counts = {COUNTEDLOOP_MAIN, "= 2"})
public void test88(Object[] src1, Object[] dst1, Object[] src2, Object[] dst2) {
for (int i = 0; i < src1.length; i++) {
dst1[i] = src1[i];
@@ -2348,8 +2366,9 @@ public void test88(Object[] src1, Object[] dst1, Object[] src2, Object[] dst2) {
}
}
- @DontCompile
- public void test88_verifier(boolean warmup) {
+ @Run(test = "test88")
+ @Warmup(0)
+ public void test88_verifier(RunInfo info) {
MyValue2[] src1 = new MyValue2[100];
Arrays.fill(src1, testValue2);
MyValue2[] dst1 = new MyValue2[100];
@@ -2357,7 +2376,7 @@ public void test88_verifier(boolean warmup) {
Arrays.fill(src2, new Object());
Object[] dst2 = new Object[100];
- rerun_and_recompile_for("TestLWorld::test88", 10,
+ rerun_and_recompile_for(info.getTest(), 10,
() -> { test88(src1, dst1, src2, dst2);
Asserts.assertTrue(Arrays.equals(src1, dst1));
Asserts.assertTrue(Arrays.equals(src2, dst2)); });
@@ -2368,8 +2387,8 @@ public boolean test89(Object obj) {
return obj.getClass() == Integer.class;
}
- @DontCompile
- public void test89_verifier(boolean warmup) {
+ @Run(test = "test89")
+ public void test89_verifier() {
Asserts.assertTrue(test89(Integer.valueOf(42)));
Asserts.assertFalse(test89(new Object()));
}
@@ -2379,8 +2398,8 @@ public Integer test90(Object obj) {
return (Integer)obj;
}
- @DontCompile
- public void test90_verifier(boolean warmup) {
+ @Run(test = "test90")
+ public void test90_verifier() {
test90(Integer.valueOf(42));
try {
test90(new Object());
@@ -2395,8 +2414,8 @@ public boolean test91(Object obj) {
return obj.getClass() == MyValue2[].class;
}
- @DontCompile
- public void test91_verifier(boolean warmup) {
+ @Run(test = "test91")
+ public void test91_verifier() {
Asserts.assertTrue(test91(new MyValue2[1]));
Asserts.assertFalse(test91(new Object()));
}
@@ -2408,8 +2427,9 @@ public Test92Value() {
}
}
- @Warmup(10000)
- @Test(match = { CLASS_CHECK_TRAP }, matchCount = { 2 }, failOn = LOAD_UNKNOWN_INLINE + ALLOC_G + MEMBAR)
+ @Test
+ @IR(counts = {CLASS_CHECK_TRAP, "= 2"},
+ failOn = {LOAD_UNKNOWN_INLINE, ALLOC_G, MEMBAR})
public Object test92(Object[] array) {
// Dummy loops to ensure we run enough passes of split if
for (int i = 0; i < 2; i++) {
@@ -2422,8 +2442,9 @@ public Object test92(Object[] array) {
return (Integer)array[0];
}
- @DontCompile
- public void test92_verifier(boolean warmup) {
+ @Run(test = "test92")
+ @Warmup(10000)
+ public void test92_verifier() {
Object[] array = new Object[1];
array[0] = 0x42;
Object result = test92(array);
@@ -2434,7 +2455,6 @@ public void test92_verifier(boolean warmup) {
// precedes will never succeed and the flat array branch should
// trigger an uncommon trap.
@Test
- @Warmup(10000)
public Object test93(Object[] array) {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
@@ -2445,16 +2465,17 @@ public Object test93(Object[] array) {
return v;
}
- @DontCompile
- public void test93_verifier(boolean warmup) {
- if (warmup) {
+ @Run(test = "test93")
+ @Warmup(10000)
+ public void test93_verifier(RunInfo info) {
+ if (info.isWarmUp()) {
Object[] array = new Object[1];
array[0] = 0x42;
Object result = test93(array);
Asserts.assertEquals(result, 0x42);
} else {
Object[] array = new Test92Value[1];
- Method m = tests.get("TestLWorld::test93");
+ Method m = info.getTest();
int extra = 3;
for (int j = 0; j < extra; j++) {
for (int i = 0; i < 10; i++) {
@@ -2463,17 +2484,19 @@ public void test93_verifier(boolean warmup) {
} catch (ClassCastException cce) {
}
}
- boolean compiled = isCompiledByC2(m);
- Asserts.assertTrue(!USE_COMPILER || XCOMP || STRESS_CC || TEST_C1 || !ProfileInterpreter || compiled || (j != extra-1));
- if (!compiled) {
- enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION);
+ boolean compiled = TestFramework.isCompiled(m);
+ boolean compilationSkipped = info.isCompilationSkipped();
+ Asserts.assertTrue(compilationSkipped || compiled || (j != extra-1));
+ if (!compilationSkipped && !compiled) {
+ TestFramework.compile(m, CompLevel.ANY);
}
}
}
}
- @Warmup(10000)
- @Test(match = { CLASS_CHECK_TRAP, LOOP }, matchCount = { 2, 1 }, failOn = LOAD_UNKNOWN_INLINE + ALLOC_G + MEMBAR)
+ @Test
+ @IR(counts = {CLASS_CHECK_TRAP, "= 2", LOOP, "= 1"},
+ failOn = {LOAD_UNKNOWN_INLINE, ALLOC_G, MEMBAR})
public int test94(Object[] array) {
int res = 0;
for (int i = 1; i < 4; i *= 2) {
@@ -2483,8 +2506,9 @@ public int test94(Object[] array) {
return res;
}
- @DontCompile
- public void test94_verifier(boolean warmup) {
+ @Run(test = "test94")
+ @Warmup(10000)
+ public void test94_verifier() {
Object[] array = new Object[4];
array[0] = 0x42;
array[1] = 0x42;
@@ -2494,14 +2518,14 @@ public void test94_verifier(boolean warmup) {
Asserts.assertEquals(result, 0x42 * 2);
}
- @Warmup(10000)
@Test
public boolean test95(Object o1, Object o2) {
return o1 == o2;
}
- @DontCompile
- public void test95_verifier(boolean warmup) {
+ @Run(test = "test95")
+ @Warmup(10000)
+ public void test95_verifier() {
Object o1 = new Object();
Object o2 = new Object();
Asserts.assertTrue(test95(o1, o1));
@@ -2510,19 +2534,19 @@ public void test95_verifier(boolean warmup) {
Asserts.assertFalse(test95(o1, o2));
}
- @Warmup(10000)
@Test
public boolean test96(Object o1, Object o2) {
return o1 == o2;
}
- @DontCompile
- public void test96_verifier(boolean warmup) {
+ @Run(test = "test96")
+ @Warmup(10000)
+ public void test96_verifier(RunInfo info) {
Object o1 = new Object();
Object o2 = new Object();
Asserts.assertTrue(test96(o1, o1));
Asserts.assertFalse(test96(o1, o2));
- if (!warmup) {
+ if (!info.isWarmUp()) {
Asserts.assertTrue(test96(null, null));
Asserts.assertFalse(test96(o1, null));
}
@@ -2550,7 +2574,7 @@ public MyValue1 test97_inline2(MyAbstract o) {
return (MyValue1)o;
}
- @Test()
+ @Test
public MyValue1 test97() {
MyValue1 vt = MyValue1.createWithFieldsInline(rI, rL);
vt = (MyValue1)test97_dontinline1(vt);
@@ -2560,8 +2584,8 @@ public MyValue1 test97() {
return vt;
}
- @DontCompile
- public void test97_verifier(boolean warmup) {
+ @Run(test = "test97")
+ public void test97_verifier() {
Asserts.assertEQ(test97().hash(), hash());
}
@@ -2583,7 +2607,7 @@ public MyAbstract readStaticValueField4AsAbstract() {
return (MyAbstract)staticValueField4;
}
- @Test()
+ @Test
public long test98(MyValue1 vt1, MyAbstract vt2) {
abstractField1 = vt1;
abstractField2 = (MyValue1)vt2;
@@ -2607,8 +2631,8 @@ public long test98(MyValue1 vt1, MyAbstract vt2) {
staticValueField1.hash() + staticValueField2.hash() + staticValueField3.hashPrimitive();
}
- @DontCompile
- public void test98_verifier(boolean warmup) {
+ @Run(test = "test98")
+ public void test98_verifier() {
MyValue1 vt = testValue1;
MyValue1 def = MyValue1.createDefaultDontInline();
long result = test98(vt, vt);
@@ -2629,7 +2653,7 @@ public long hash() {
}
// Test merging inline types and abstract classes
- @Test()
+ @Test
public MyAbstract test99(int state) {
MyAbstract res = null;
if (state == 0) {
@@ -2648,8 +2672,8 @@ public MyAbstract test99(int state) {
return res;
}
- @DontCompile
- public void test99_verifier(boolean warmup) {
+ @Run(test = "test99")
+ public void test99_verifier() {
objectField1 = valueField1;
MyAbstract result = null;
result = test99(0);
@@ -2667,7 +2691,7 @@ public void test99_verifier(boolean warmup) {
}
// Test merging inline types and abstract classes in loops
- @Test()
+ @Test
public MyAbstract test100(int iters) {
MyAbstract res = new MyObject2(rI);
for (int i = 0; i < iters; ++i) {
@@ -2680,8 +2704,8 @@ public MyAbstract test100(int iters) {
return res;
}
- @DontCompile
- public void test100_verifier(boolean warmup) {
+ @Run(test = "test100")
+ public void test100_verifier() {
MyObject2 result1 = (MyObject2)test100(0);
Asserts.assertEQ(result1.x, rI);
int iters = (Math.abs(rI) % 10) + 1;
@@ -2691,28 +2715,30 @@ public void test100_verifier(boolean warmup) {
}
// Test inline types in abstract class variables that are live at safepoint
- @Test(failOn = ALLOC + STORE + LOOP)
- public long test101(MyValue1 arg, boolean deopt) {
+ @Test
+ @IR(failOn = {ALLOC, STORE, LOOP})
+ public long test101(MyValue1 arg, boolean deopt, Method m) {
MyAbstract vt1 = MyValue1.createWithFieldsInline(rI, rL);
MyAbstract vt2 = MyValue1.createWithFieldsDontInline(rI, rL);
MyAbstract vt3 = arg;
MyAbstract vt4 = valueField1;
if (deopt) {
// uncommon trap
- WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test101"));
+ TestFramework.deoptimize(m);
}
return ((MyValue1)vt1).hash() + ((MyValue1)vt2).hash() +
((MyValue1)vt3).hash() + ((MyValue1)vt4).hash();
}
- @DontCompile
- public void test101_verifier(boolean warmup) {
- long result = test101(valueField1, !warmup);
+ @Run(test = "test101")
+ public void test101_verifier(RunInfo info) {
+ long result = test101(valueField1, !info.isWarmUp(), info.getTest());
Asserts.assertEQ(result, 4*hash());
}
// Test comparing inline types with abstract classes
- @Test(failOn = LOAD + LOOP)
+ @Test
+ @IR(failOn = {LOAD, LOOP})
public boolean test102(Object arg) {
MyAbstract vt = MyValue1.createWithFieldsInline(rI, rL);
if (vt == arg || vt == (MyAbstract)valueField1 || vt == abstractField1 || vt == null ||
@@ -2722,8 +2748,8 @@ public boolean test102(Object arg) {
return false;
}
- @DontCompile
- public void test102_verifier(boolean warmup) {
+ @Run(test = "test102")
+ public void test102_verifier() {
boolean result = test102(null);
Asserts.assertFalse(result);
}
@@ -2742,13 +2768,15 @@ class MyObject4 extends NoValueImplementors1 {
}
// Loading from an abstract class array does not require a flatness check if the abstract class has a non-static field
- @Test(failOn = ALLOC_G + MEMBAR + ALLOCA_G + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD)
+ @Test
+ @IR(failOn = {ALLOC_G, MEMBAR, ALLOCA_G,
+ LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
public NoValueImplementors1 test103(NoValueImplementors1[] array, int i) {
return array[i];
}
- @DontCompile
- public void test103_verifier(boolean warmup) {
+ @Run(test = "test103")
+ public void test103_verifier() {
NoValueImplementors1[] array1 = new NoValueImplementors1[3];
MyObject3[] array2 = new MyObject3[3];
MyObject4[] array3 = new MyObject4[3];
@@ -2763,7 +2791,9 @@ public void test103_verifier(boolean warmup) {
}
// Storing to an abstract class array does not require a flatness/null check if the abstract class has a non-static field
- @Test(failOn = ALLOC_G + ALLOCA_G + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD)
+ @Test
+ @IR(failOn = {ALLOC_G, ALLOCA_G,
+ LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
public NoValueImplementors1 test104(NoValueImplementors1[] array, NoValueImplementors1 v, MyObject3 o, int i) {
array[0] = v;
array[1] = array[0];
@@ -2771,8 +2801,8 @@ public NoValueImplementors1 test104(NoValueImplementors1[] array, NoValueImpleme
return array[i];
}
- @DontCompile
- public void test104_verifier(boolean warmup) {
+ @Run(test = "test104")
+ public void test104_verifier() {
MyObject4 v = new MyObject4();
MyObject3 o = new MyObject3();
NoValueImplementors1[] array1 = new NoValueImplementors1[3];
@@ -2807,13 +2837,15 @@ class MyObject5 extends NoValueImplementors2 {
}
// Loading from an abstract class array does not require a flatness check if the abstract class has no inline implementor
- @Test(failOn = ALLOC_G + MEMBAR + ALLOCA_G + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD)
+ @Test
+ @IR(failOn = {ALLOC_G, MEMBAR, ALLOCA_G,
+ LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
public NoValueImplementors2 test105(NoValueImplementors2[] array, int i) {
return array[i];
}
- @DontCompile
- public void test105_verifier(boolean warmup) {
+ @Run(test = "test105")
+ public void test105_verifier() {
NoValueImplementors2[] array1 = new NoValueImplementors2[3];
MyObject5[] array2 = new MyObject5[3];
NoValueImplementors2 result = test105(array1, 0);
@@ -2824,7 +2856,9 @@ public void test105_verifier(boolean warmup) {
}
// Storing to an abstract class array does not require a flatness/null check if the abstract class has no inline implementor
- @Test(failOn = ALLOC_G + ALLOCA_G + LOAD_UNKNOWN_INLINE + STORE_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD)
+ @Test
+ @IR(failOn = {ALLOC_G, ALLOCA_G,
+ LOAD_UNKNOWN_INLINE, STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD})
public NoValueImplementors2 test106(NoValueImplementors2[] array, NoValueImplementors2 v, MyObject5 o, int i) {
array[0] = v;
array[1] = array[0];
@@ -2832,8 +2866,8 @@ public NoValueImplementors2 test106(NoValueImplementors2[] array, NoValueImpleme
return array[i];
}
- @DontCompile
- public void test106_verifier(boolean warmup) {
+ @Run(test = "test106")
+ public void test106_verifier() {
MyObject5 v = new MyObject5();
NoValueImplementors2[] array1 = new NoValueImplementors2[3];
MyObject5[] array2 = new MyObject5[3];
@@ -2853,9 +2887,13 @@ public void test106_verifier(boolean warmup) {
// More tests for the Loop Unswitching optimization (similar to test84 and following)
Object oFld1, oFld2;
- @Test(valid = G1GCOn, failOn = STORE_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD, match = { COUNTEDLOOP, LOAD_UNKNOWN_INLINE }, matchCount = { 2, 2 } )
- @Test(valid = G1GCOff, failOn = STORE_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD, match = { COUNTEDLOOP, LOAD_UNKNOWN_INLINE }, matchCount = { 3, 2 } )
- @Warmup(0)
+ @Test
+ @IR(applyIf = {"UseG1GC", "true"},
+ failOn = {STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD},
+ counts = {COUNTEDLOOP, "= 2", LOAD_UNKNOWN_INLINE, "= 2"})
+ @IR(applyIf = {"UseG1GC", "false"},
+ failOn = {STORE_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD},
+ counts = {COUNTEDLOOP, "= 3", LOAD_UNKNOWN_INLINE, "= 2"})
public void test107(Object[] src1, Object[] src2) {
for (int i = 0; i < src1.length; i++) {
oFld1 = src1[i];
@@ -2863,14 +2901,15 @@ public void test107(Object[] src1, Object[] src2) {
}
}
- @DontCompile
- public void test107_verifier(boolean warmup) {
+ @Run(test = "test107")
+ @Warmup(0)
+ public void test107_verifier(RunInfo info) {
MyValue2[] src1 = new MyValue2[100];
Arrays.fill(src1, testValue2);
Object[] src2 = new Object[100];
Object obj = new Object();
Arrays.fill(src2, obj);
- rerun_and_recompile_for("TestLWorld::test107", 10,
+ rerun_and_recompile_for(info.getTest(), 10,
() -> { test107(src1, src2);
Asserts.assertEquals(oFld1, testValue2);
Asserts.assertEquals(oFld2, obj);
@@ -2879,9 +2918,13 @@ public void test107_verifier(boolean warmup) {
Asserts.assertEquals(oFld2, testValue2); });
}
- @Test(valid = G1GCOn, failOn = LOAD_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD, match = { COUNTEDLOOP, STORE_UNKNOWN_INLINE }, matchCount = { 4, 9 } )
- @Test(valid = G1GCOff, failOn = LOAD_UNKNOWN_INLINE + INLINE_ARRAY_NULL_GUARD, match = { COUNTEDLOOP, STORE_UNKNOWN_INLINE }, matchCount = { 4, 12 } )
- @Warmup(0)
+ @Test
+ @IR(applyIf = {"UseG1GC", "true"},
+ failOn = {LOAD_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD},
+ counts = {COUNTEDLOOP, "= 4", STORE_UNKNOWN_INLINE, "= 9"})
+ @IR(applyIf = {"UseG1GC", "false"},
+ failOn = {LOAD_UNKNOWN_INLINE, INLINE_ARRAY_NULL_GUARD},
+ counts = {COUNTEDLOOP, "= 4", STORE_UNKNOWN_INLINE, "= 12"})
public void test108(Object[] dst1, Object[] dst2, Object o1, Object o2) {
for (int i = 0; i < dst1.length; i++) {
dst1[i] = o1;
@@ -2889,12 +2932,13 @@ public void test108(Object[] dst1, Object[] dst2, Object o1, Object o2) {
}
}
- @DontCompile
- public void test108_verifier(boolean warmup) {
+ @Run(test = "test108")
+ @Warmup(0)
+ public void test108_verifier(RunInfo info) {
MyValue2[] dst1 = new MyValue2[100];
Object[] dst2 = new Object[100];
Object o1 = new Object();
- rerun_and_recompile_for("TestLWorld::test108", 10,
+ rerun_and_recompile_for(info.getTest(), 10,
() -> { test108(dst1, dst2, testValue2, o1);
for (int i = 0; i < dst1.length; i++) {
Asserts.assertEquals(dst1[i], testValue2);
@@ -2919,6 +2963,7 @@ static WrapperInterface wrap(long val) {
}
}
+ @ForceCompileClassInitializer
static primitive class LongWrapper implements WrapperInterface {
final static LongWrapper ZERO = new LongWrapper(0);
private long val;
@@ -3015,8 +3060,9 @@ static GenericBox box(long val) {
long[] lArr = {0L, rL, 0L, rL, 0L, rL, 0L, rL, 0L, rL};
// Test removal of allocations when inline type instance is wrapped into box object
- @Warmup(10000) // Make sure interface calls are inlined
- @Test(failOn = ALLOC_G + MEMBAR, match = { PREDICATE_TRAP }, matchCount = { 1 })
+ @Test
+ @IR(failOn = {ALLOC_G, MEMBAR},
+ counts = {PREDICATE_TRAP, "= 1"})
public long test109() {
long res = 0;
for (int i = 0 ; i < lArr.length; i++) {
@@ -3025,14 +3071,16 @@ public long test109() {
return res;
}
- @DontCompile
- public void test109_verifier(boolean warmup) {
+ @Run(test = "test109")
+ @Warmup(10000) // Make sure interface calls are inlined
+ public void test109_verifier() {
long res = test109();
Asserts.assertEquals(res, 5*rL);
}
- @Warmup(10000) // Make sure interface calls are inlined
- @Test(failOn = ALLOC_G + MEMBAR, match = { PREDICATE_TRAP }, matchCount = { 1 })
+ @Test
+ @IR(failOn = {ALLOC_G, MEMBAR},
+ counts = {PREDICATE_TRAP, "= 1"})
public long test109_sharp() {
long res = 0;
for (int i = 0 ; i < lArr.length; i++) {
@@ -3041,15 +3089,17 @@ public long test109_sharp() {
return res;
}
- @DontCompile
- public void test109_sharp_verifier(boolean warmup) {
+ @Run(test = "test109_sharp")
+ @Warmup(10000) // Make sure interface calls are inlined
+ public void test109_sharp_verifier() {
long res = test109_sharp();
Asserts.assertEquals(res, 5*rL);
}
// Same as test109 but with ObjectBox
- @Test(failOn = ALLOC_G + MEMBAR, match = { PREDICATE_TRAP }, matchCount = { 1 })
- @Warmup(10000) // Make sure interface calls are inlined
+ @Test
+ @IR(failOn = {ALLOC_G, MEMBAR},
+ counts = {PREDICATE_TRAP, "= 1"})
public long test110() {
long res = 0;
for (int i = 0 ; i < lArr.length; i++) {
@@ -3058,14 +3108,16 @@ public long test110() {
return res;
}
- @DontCompile
- public void test110_verifier(boolean warmup) {
+ @Run(test = "test110")
+ @Warmup(10000) // Make sure interface calls are inlined
+ public void test110_verifier() {
long res = test110();
Asserts.assertEquals(res, 5*rL);
}
- @Test(failOn = ALLOC_G + MEMBAR, match = { PREDICATE_TRAP }, matchCount = { 1 })
- @Warmup(10000) // Make sure interface calls are inlined
+ @Test
+ @IR(failOn = {ALLOC_G, MEMBAR},
+ counts = {PREDICATE_TRAP, "= 1"})
public long test110_sharp() {
long res = 0;
for (int i = 0 ; i < lArr.length; i++) {
@@ -3074,14 +3126,17 @@ public long test110_sharp() {
return res;
}
- @DontCompile
- public void test110_sharp_verifier(boolean warmup) {
+ @Run(test = "test110_sharp")
+ @Warmup(10000) // Make sure interface calls are inlined
+ public void test110_sharp_verifier() {
long res = test110_sharp();
Asserts.assertEquals(res, 5*rL);
}
// Same as test109 but with RefBox
- @Test(failOn = ALLOC_G + MEMBAR, match = { PREDICATE_TRAP }, matchCount = { 1 })
+ @Test
+ @IR(failOn = {ALLOC_G, MEMBAR},
+ counts = {PREDICATE_TRAP, "= 1"})
public long test111() {
long res = 0;
for (int i = 0 ; i < lArr.length; i++) {
@@ -3090,13 +3145,15 @@ public long test111() {
return res;
}
- @DontCompile
- public void test111_verifier(boolean warmup) {
+ @Run(test = "test111")
+ public void test111_verifier() {
long res = test111();
Asserts.assertEquals(res, 5*rL);
}
- @Test(failOn = ALLOC_G + MEMBAR, match = { PREDICATE_TRAP }, matchCount = { 1 })
+ @Test
+ @IR(failOn = {ALLOC_G, MEMBAR},
+ counts = {PREDICATE_TRAP, "= 1"})
public long test111_sharp() {
long res = 0;
for (int i = 0 ; i < lArr.length; i++) {
@@ -3105,14 +3162,16 @@ public long test111_sharp() {
return res;
}
- @DontCompile
- public void test111_sharp_verifier(boolean warmup) {
+ @Run(test = "test111_sharp")
+ public void test111_sharp_verifier() {
long res = test111_sharp();
Asserts.assertEquals(res, 5*rL);
}
// Same as test109 but with InlineBox
- @Test(failOn = ALLOC_G + MEMBAR, match = { PREDICATE_TRAP }, matchCount = { 1 })
+ @Test
+ @IR(failOn = {ALLOC_G, MEMBAR},
+ counts = {PREDICATE_TRAP, "= 1"})
public long test112() {
long res = 0;
for (int i = 0 ; i < lArr.length; i++) {
@@ -3121,15 +3180,16 @@ public long test112() {
return res;
}
- @DontCompile
- public void test112_verifier(boolean warmup) {
+ @Run(test = "test112")
+ public void test112_verifier() {
long res = test112();
Asserts.assertEquals(res, 5*rL);
}
// Same as test109 but with GenericBox
- @Test(failOn = ALLOC_G + MEMBAR, match = { PREDICATE_TRAP }, matchCount = { 1 })
- @Warmup(10000) // Make sure interface calls are inlined
+ @Test
+ @IR(failOn = {ALLOC_G, MEMBAR},
+ counts = {PREDICATE_TRAP, "= 1"})
public long test113() {
long res = 0;
for (int i = 0 ; i < lArr.length; i++) {
@@ -3138,14 +3198,16 @@ public long test113() {
return res;
}
- @DontCompile
- public void test113_verifier(boolean warmup) {
+ @Run(test = "test113")
+ @Warmup(10000) // Make sure interface calls are inlined
+ public void test113_verifier() {
long res = test113();
Asserts.assertEquals(res, 5*rL);
}
- @Test(failOn = ALLOC_G + MEMBAR, match = { PREDICATE_TRAP }, matchCount = { 1 })
- @Warmup(10000) // Make sure interface calls are inlined
+ @Test
+ @IR(failOn = {ALLOC_G, MEMBAR},
+ counts = {PREDICATE_TRAP, "= 1"})
public long test113_sharp() {
long res = 0;
for (int i = 0 ; i < lArr.length; i++) {
@@ -3154,8 +3216,9 @@ public long test113_sharp() {
return res;
}
- @DontCompile
- public void test113_sharp_verifier(boolean warmup) {
+ @Run(test = "test113_sharp")
+ @Warmup(10000) // Make sure interface calls are inlined
+ public void test113_sharp_verifier() {
long res = test113_sharp();
Asserts.assertEquals(res, 5*rL);
}
@@ -3211,8 +3274,9 @@ static InterfaceBox2 box_default(long val) {
}
// Same as tests above but with ZERO hidden in field of another inline type
- @Test(failOn = ALLOC_G + MEMBAR, match = { PREDICATE_TRAP }, matchCount = { 1 })
- @Warmup(10000)
+ @Test
+ @IR(failOn = {ALLOC_G, MEMBAR},
+ counts = {PREDICATE_TRAP, "= 1"})
public long test114() {
long res = 0;
for (int i = 0; i < lArr.length; i++) {
@@ -3221,15 +3285,17 @@ public long test114() {
return res;
}
- @DontCompile
- public void test114_verifier(boolean warmup) {
+ @Run(test = "test114")
+ @Warmup(10000)
+ public void test114_verifier() {
long res = test114();
Asserts.assertEquals(res, 5*rL);
}
// Same as test114 but with .default instead of ZERO field
- @Test(failOn = ALLOC_G + MEMBAR, match = { PREDICATE_TRAP }, matchCount = { 1 })
- @Warmup(10000)
+ @Test
+ @IR(failOn = {ALLOC_G, MEMBAR},
+ counts = {PREDICATE_TRAP, "= 1"})
public long test115() {
long res = 0;
for (int i = 0; i < lArr.length; i++) {
@@ -3238,8 +3304,9 @@ public long test115() {
return res;
}
- @DontCompile
- public void test115_verifier(boolean warmup) {
+ @Run(test = "test115")
+ @Warmup(10000)
+ public void test115_verifier() {
long res = test115();
Asserts.assertEquals(res, 5*rL);
}
@@ -3250,7 +3317,8 @@ public void test115_verifier(boolean warmup) {
MyValueEmpty.ref fEmpty4 = MyValueEmpty.default;
// Test fields loads/stores with empty inline types
- @Test(failOn = ALLOC + ALLOC_G + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOC_G, LOAD, STORE, TRAP})
public void test116() {
fEmpty1 = fEmpty4;
fEmpty2 = fEmpty1;
@@ -3258,8 +3326,8 @@ public void test116() {
fEmpty4 = fEmpty3;
}
- @DontCompile
- public void test116_verifier(boolean warmup) {
+ @Run(test = "test116")
+ public void test116_verifier() {
test116();
Asserts.assertEquals(fEmpty1, fEmpty2);
Asserts.assertEquals(fEmpty2, fEmpty3);
@@ -3267,15 +3335,16 @@ public void test116_verifier(boolean warmup) {
}
// Test array loads/stores with empty inline types
- @Test(failOn = ALLOC + ALLOC_G)
+ @Test
+ @IR(failOn = {ALLOC, ALLOC_G})
public MyValueEmpty test117(MyValueEmpty[] arr1, MyValueEmpty.ref[] arr2) {
arr1[0] = arr2[0];
arr2[0] = new MyValueEmpty();
return arr1[0];
}
- @DontCompile
- public void test117_verifier(boolean warmup) {
+ @Run(test = "test117")
+ public void test117_verifier() {
MyValueEmpty[] arr1 = new MyValueEmpty[]{MyValueEmpty.default};
MyValueEmpty res = test117(arr1, arr1);
Asserts.assertEquals(res, MyValueEmpty.default);
@@ -3283,13 +3352,14 @@ public void test117_verifier(boolean warmup) {
}
// Test acmp with empty inline types
- @Test(failOn = ALLOC + ALLOC_G)
+ @Test
+ @IR(failOn = {ALLOC, ALLOC_G})
public boolean test118(MyValueEmpty v1, MyValueEmpty.ref v2, Object o1) {
return (v1 == v2) && (v2 == o1);
}
- @DontCompile
- public void test118_verifier(boolean warmup) {
+ @Run(test = "test118")
+ public void test118_verifier() {
boolean res = test118(MyValueEmpty.default, MyValueEmpty.default, new MyValueEmpty());
Asserts.assertTrue(res);
}
@@ -3305,60 +3375,62 @@ static primitive class MixedContainer {
// Test re-allocation of empty inline type array during deoptimization
@Test
- public void test119(boolean deopt) {
+ public void test119(boolean deopt, Method m) {
MyValueEmpty[] array1 = new MyValueEmpty[]{MyValueEmpty.default};
EmptyContainer[] array2 = new EmptyContainer[]{EmptyContainer.default};
MixedContainer[] array3 = new MixedContainer[]{MixedContainer.default};
if (deopt) {
// uncommon trap
- WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test119"));
+ TestFramework.deoptimize(m);
}
Asserts.assertEquals(array1[0], MyValueEmpty.default);
Asserts.assertEquals(array2[0], EmptyContainer.default);
Asserts.assertEquals(array3[0], MixedContainer.default);
}
- @DontCompile
- public void test119_verifier(boolean warmup) {
- test119(!warmup);
+ @Run(test = "test119")
+ public void test119_verifier(RunInfo info) {
+ test119(!info.isWarmUp(), info.getTest());
}
// Test removal of empty inline type field stores
- @Test(failOn = ALLOC + ALLOC_G + LOAD + STORE + FIELD_ACCESS + NULL_CHECK_TRAP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOC_G, LOAD, STORE, FIELD_ACCESS, NULL_CHECK_TRAP, TRAP})
public void test120(MyValueEmpty empty) {
fEmpty1 = empty;
fEmpty3 = empty;
// fEmpty2 and fEmpty4 could be null, store can't be removed
}
- @DontCompile
- public void test120_verifier(boolean warmup) {
+ @Run(test = "test120")
+ public void test120_verifier() {
test120(MyValueEmpty.default);
Asserts.assertEquals(fEmpty1, MyValueEmpty.default);
Asserts.assertEquals(fEmpty2, MyValueEmpty.default);
}
// Test removal of empty inline type field loads
- @Test(failOn = ALLOC + ALLOC_G + LOAD + STORE + FIELD_ACCESS + NULL_CHECK_TRAP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOC_G, LOAD, STORE, FIELD_ACCESS, NULL_CHECK_TRAP, TRAP})
public boolean test121() {
return fEmpty1.equals(fEmpty3);
// fEmpty2 and fEmpty4 could be null, load can't be removed
}
- @DontCompile
- public void test121_verifier(boolean warmup) {
+ @Run(test = "test121")
+ public void test121_verifier() {
boolean res = test121();
Asserts.assertTrue(res);
}
// Verify that empty inline type field loads check for null holder
- @Test()
+ @Test
public MyValueEmpty test122(TestLWorld t) {
return t.fEmpty3;
}
- @DontCompile
- public void test122_verifier(boolean warmup) {
+ @Run(test = "test122")
+ public void test122_verifier() {
MyValueEmpty res = test122(this);
Asserts.assertEquals(res, MyValueEmpty.default);
try {
@@ -3370,13 +3442,13 @@ public void test122_verifier(boolean warmup) {
}
// Verify that empty inline type field stores check for null holder
- @Test()
+ @Test
public void test123(TestLWorld t) {
t.fEmpty3 = MyValueEmpty.default;
}
- @DontCompile
- public void test123_verifier(boolean warmup) {
+ @Run(test = "test123")
+ public void test123_verifier() {
test123(this);
Asserts.assertEquals(fEmpty3, MyValueEmpty.default);
try {
@@ -3389,33 +3461,35 @@ public void test123_verifier(boolean warmup) {
// acmp doesn't need substitutability test when one input is known
// not to be a value type
- @Test(failOn = SUBSTITUTABILITY_TEST)
+ @Test
+ @IR(failOn = SUBSTITUTABILITY_TEST)
public boolean test124(Integer o1, Object o2) {
return o1 == o2;
}
- @DontCompile
- public void test124_verifier(boolean warmup) {
+ @Run(test = "test124")
+ public void test124_verifier() {
test124(42, 42);
test124(42, testValue1);
}
// acmp doesn't need substitutability test when one input null
- @Test(failOn = SUBSTITUTABILITY_TEST)
+ @Test
+ @IR(failOn = {SUBSTITUTABILITY_TEST})
public boolean test125(Object o1) {
Object o2 = null;
return o1 == o2;
}
- @DontCompile
- public void test125_verifier(boolean warmup) {
+ @Run(test = "test125")
+ public void test125_verifier() {
test125(testValue1);
test125(null);
}
// Test inline type that can only be scalarized after loop opts
- @Test(failOn = ALLOC + LOAD + STORE)
- @Warmup(10000)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE})
public long test126(boolean trap) {
MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD);
MyValue2.ref val = null;
@@ -3433,19 +3507,20 @@ public long test126(boolean trap) {
return 0;
}
- @DontCompile
- public void test126_verifier(boolean warmup) {
+ @Run(test = "test126")
+ @Warmup(10000)
+ public void test126_verifier(RunInfo info) {
long res = test126(false);
Asserts.assertEquals(res, 0L);
- if (!warmup) {
+ if (!info.isWarmUp()) {
res = test126(true);
Asserts.assertEquals(res, testValue2.hash());
}
}
// Same as test126 but with interface type
- @Test(failOn = ALLOC + LOAD + STORE)
- @Warmup(10000)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE})
public long test127(boolean trap) {
MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD);
MyInterface val = null;
@@ -3463,19 +3538,20 @@ public long test127(boolean trap) {
return 0;
}
- @DontCompile
- public void test127_verifier(boolean warmup) {
+ @Run(test = "test127")
+ @Warmup(10000)
+ public void test127_verifier(RunInfo info) {
long res = test127(false);
Asserts.assertEquals(res, 0L);
- if (!warmup) {
+ if (!info.isWarmUp()) {
res = test127(true);
Asserts.assertEquals(res, testValue2.hash());
}
}
// Test inline type that can only be scalarized after CCP
- @Test(failOn = ALLOC + LOAD + STORE)
- @Warmup(10000)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE})
public long test128(boolean trap) {
MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD);
MyValue2.ref val = null;
@@ -3493,19 +3569,20 @@ public long test128(boolean trap) {
return 0;
}
- @DontCompile
- public void test128_verifier(boolean warmup) {
+ @Run(test = "test128")
+ @Warmup(10000)
+ public void test128_verifier(RunInfo info) {
long res = test128(false);
Asserts.assertEquals(res, 0L);
- if (!warmup) {
+ if (!info.isWarmUp()) {
res = test128(true);
Asserts.assertEquals(res, testValue2.hash());
}
}
// Same as test128 but with interface type
- @Test(failOn = ALLOC + LOAD + STORE)
- @Warmup(10000)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE})
public long test129(boolean trap) {
MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD);
MyInterface val = null;
@@ -3523,11 +3600,12 @@ public long test129(boolean trap) {
return 0;
}
- @DontCompile
- public void test129_verifier(boolean warmup) {
+ @Run(test = "test129")
+ @Warmup(10000)
+ public void test129_verifier(RunInfo info) {
long res = test129(false);
Asserts.assertEquals(res, 0L);
- if (!warmup) {
+ if (!info.isWarmUp()) {
res = test129(true);
Asserts.assertEquals(res, testValue2.hash());
}
@@ -3539,7 +3617,7 @@ public Object test130_inlinee() {
return MyValue1.createWithFieldsInline(rI, rL);
}
- @Test()
+ @Test
public void test130() {
Object obj = test130_inlinee();
synchronized (obj) {
@@ -3547,8 +3625,8 @@ public void test130() {
}
}
- @DontCompile
- public void test130_verifier(boolean warmup) {
+ @Run(test = "test130")
+ public void test130_verifier() {
try {
test130();
throw new RuntimeException("test130 failed: no exception thrown");
@@ -3563,7 +3641,7 @@ public Object test131_inlinee() {
return testValue1;
}
- @Test()
+ @Test
public void test131() {
Object obj = test131_inlinee();
synchronized (obj) {
@@ -3571,8 +3649,8 @@ public void test131() {
}
}
- @DontCompile
- public void test131_verifier(boolean warmup) {
+ @Run(test = "test131")
+ public void test131_verifier() {
try {
test131();
throw new RuntimeException("test131 failed: no exception thrown");
@@ -3582,8 +3660,7 @@ public void test131_verifier(boolean warmup) {
}
// Test locking on object that is known to be an inline type only after CCP
- @Test()
- @Warmup(10000)
+ @Test
public void test132() {
MyValue2 vt = MyValue2.createWithFieldsInline(rI, rD);
Object obj = Integer.valueOf(42);
@@ -3598,8 +3675,9 @@ public void test132() {
}
}
- @DontCompile
- public void test132_verifier(boolean warmup) {
+ @Run(test = "test132")
+ @Warmup(10000)
+ public void test132_verifier() {
try {
test132();
throw new RuntimeException("test132 failed: no exception thrown");
@@ -3609,7 +3687,7 @@ public void test132_verifier(boolean warmup) {
}
// Test conditional locking on inline type and non-escaping object
- @Test()
+ @Test
public void test133(boolean b) {
Object obj = b ? Integer.valueOf(42) : MyValue2.createWithFieldsInline(rI, rD);
synchronized (obj) {
@@ -3619,8 +3697,8 @@ public void test133(boolean b) {
}
}
- @DontCompile
- public void test133_verifier(boolean warmup) {
+ @Run(test = "test133")
+ public void test133_verifier() {
test133(true);
try {
test133(false);
@@ -3631,7 +3709,7 @@ public void test133_verifier(boolean warmup) {
}
// Variant with non-scalarized inline type
- @Test()
+ @Test
public static void test134(boolean b) {
Object obj = null;
if (b) {
@@ -3642,8 +3720,8 @@ public static void test134(boolean b) {
}
}
- @DontCompile
- public void test134_verifier(boolean warmup) {
+ @Run(test = "test134")
+ public void test134_verifier() {
try {
test134(true);
throw new RuntimeException("test134 failed: no exception thrown");
@@ -3653,19 +3731,21 @@ public void test134_verifier(boolean warmup) {
}
// Test that acmp of the same inline object is removed
- @Test(failOn = ALLOC + LOAD + STORE + NULL_CHECK_TRAP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, NULL_CHECK_TRAP, TRAP})
public static boolean test135() {
MyValue1 val = MyValue1.createWithFieldsInline(rI, rL);
return val == val;
}
- @DontCompile
- public void test135_verifier(boolean warmup) {
+ @Run(test = "test135")
+ public void test135_verifier() {
Asserts.assertTrue(test135());
}
// Same as test135 but with .ref
- @Test(failOn = ALLOC + LOAD + STORE + NULL_CHECK_TRAP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, NULL_CHECK_TRAP, TRAP})
public static boolean test136(boolean b) {
MyValue1.ref val = MyValue1.createWithFieldsInline(rI, rL);
if (b) {
@@ -3674,8 +3754,8 @@ public static boolean test136(boolean b) {
return val == val;
}
- @DontCompile
- public void test136_verifier(boolean warmup) {
+ @Run(test = "test136")
+ public void test136_verifier() {
Asserts.assertTrue(test136(false));
Asserts.assertTrue(test136(true));
}
@@ -3688,20 +3768,22 @@ public SimpleInlineType(int x) {
}
// Test that acmp of different inline objects with same content is removed
- @Test(failOn = ALLOC + LOAD + STORE + NULL_CHECK_TRAP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, NULL_CHECK_TRAP, TRAP})
public static boolean test137(int i) {
SimpleInlineType val1 = new SimpleInlineType(i);
SimpleInlineType val2 = new SimpleInlineType(i);
return val1 == val2;
}
- @DontCompile
- public void test137_verifier(boolean warmup) {
+ @Run(test = "test137")
+ public void test137_verifier() {
Asserts.assertTrue(test137(rI));
}
// Same as test137 but with .ref
- @Test(failOn = ALLOC + LOAD + STORE + NULL_CHECK_TRAP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, NULL_CHECK_TRAP, TRAP})
public static boolean test138(int i, boolean b) {
SimpleInlineType.ref val1 = new SimpleInlineType(i);
SimpleInlineType.ref val2 = new SimpleInlineType(i);
@@ -3712,8 +3794,8 @@ public static boolean test138(int i, boolean b) {
return val1 == val2;
}
- @DontCompile
- public void test138_verifier(boolean warmup) {
+ @Run(test = "test138")
+ public void test138_verifier() {
Asserts.assertTrue(test138(rI, false));
Asserts.assertTrue(test138(rI, true));
}
@@ -3727,14 +3809,15 @@ static primitive class Test139Wrapper {
Test139Value value = Test139Value.default;
}
- @Test(failOn = ALLOC + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, TRAP})
public MyValueEmpty test139() {
Test139Wrapper w = new Test139Wrapper();
return w.value.empty;
}
- @DontCompile
- public void test139_verifier(boolean warmup) {
+ @Run(test = "test139")
+ public void test139_verifier() {
MyValueEmpty empty = test139();
Asserts.assertEquals(empty, MyValueEmpty.default);
}
@@ -3748,14 +3831,14 @@ public int get() {
}
@Test
- @Warmup(0)
public int test140() {
Test140Value vt = Test140Value.default;
return vt.get();
}
- @DontCompile
- public void test140_verifier(boolean warmup) {
+ @Run(test = "test140")
+ @Warmup(0)
+ public void test140_verifier() {
int result = test140();
Asserts.assertEquals(result, 0);
}
@@ -3769,14 +3852,14 @@ public int get() {
}
@Test
- @Warmup(0)
public int test141() {
Test141Value vt = Test141Value.default;
return vt.get();
}
- @DontCompile
- public void test141_verifier(boolean warmup) {
+ @Run(test = "test141")
+ @Warmup(0)
+ public void test141_verifier() {
int result = test141();
Asserts.assertEquals(result, 0);
}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorldProfiling.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorldProfiling.java
index 12232c26655..2349a0587ad 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorldProfiling.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorldProfiling.java
@@ -23,66 +23,77 @@
package compiler.valhalla.inlinetypes;
+import compiler.lib.ir_framework.*;
import jdk.test.lib.Asserts;
+import sun.hotspot.WhiteBox;
+
import java.lang.reflect.Method;
+import static compiler.valhalla.inlinetypes.InlineTypes.IRNode.*;
+import static compiler.valhalla.inlinetypes.InlineTypes.*;
+
/*
* @test
* @key randomness
* @summary Test inline type specific profiling
- * @library /testlibrary /test/lib /compiler/whitebox /
+ * @library /test/lib /
* @requires (os.simpleArch == "x64")
- * @compile TestLWorldProfiling.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:FlatArrayElementMaxSize=-1
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestLWorldProfiling
+ * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestLWorldProfiling
*/
-public class TestLWorldProfiling extends InlineTypeTest {
-
- static final String[][] scenarios = {
- {"-XX:-UseArrayLoadStoreProfile",
- "-XX:-UseACmpProfile",
- "-XX:TypeProfileLevel=0",
- "-XX:-MonomorphicArrayCheck" },
- { "-XX:+UseArrayLoadStoreProfile",
- "-XX:+UseACmpProfile",
- "-XX:TypeProfileLevel=0" },
- { "-XX:-UseArrayLoadStoreProfile",
- "-XX:-UseACmpProfile",
- "-XX:TypeProfileLevel=222",
- "-XX:-MonomorphicArrayCheck" },
- { "-XX:-UseArrayLoadStoreProfile",
- "-XX:-UseACmpProfile",
- "-XX:TypeProfileLevel=0",
- "-XX:-MonomorphicArrayCheck",
- "-XX:TieredStopAtLevel=4",
- "-XX:-TieredCompilation" },
- { "-XX:+UseArrayLoadStoreProfile",
- "-XX:+UseACmpProfile",
- "-XX:TypeProfileLevel=0",
- "-XX:TieredStopAtLevel=4",
- "-XX:-TieredCompilation" },
- { "-XX:-UseArrayLoadStoreProfile",
- "-XX:-UseACmpProfile",
- "-XX:TypeProfileLevel=222",
- "-XX:-MonomorphicArrayCheck",
- "-XX:TieredStopAtLevel=4",
- "-XX:-TieredCompilation" }
- };
-
- public int getNumScenarios() {
- return scenarios.length;
- }
-
- public String[] getVMParameters(int scenario) {
- return scenarios[scenario];
- }
-
- public static void main(String[] args) throws Throwable {
- TestLWorldProfiling test = new TestLWorldProfiling();
- test.run(args, MyValue1.class, MyValue2.class);
+
+@ForceCompileClassInitializer
+public class TestLWorldProfiling {
+
+ public static void main(String[] args) {
+ final Scenario[] scenarios = {
+ new Scenario(0,
+ "-XX:FlatArrayElementMaxSize=-1",
+ "-XX:-UseArrayLoadStoreProfile",
+ "-XX:-UseACmpProfile",
+ "-XX:TypeProfileLevel=0",
+ "-XX:-MonomorphicArrayCheck"),
+ new Scenario(1,
+ "-XX:FlatArrayElementMaxSize=-1",
+ "-XX:+UseArrayLoadStoreProfile",
+ "-XX:+UseACmpProfile",
+ "-XX:TypeProfileLevel=0"),
+ new Scenario(2,
+ "-XX:FlatArrayElementMaxSize=-1",
+ "-XX:-UseArrayLoadStoreProfile",
+ "-XX:-UseACmpProfile",
+ "-XX:TypeProfileLevel=222",
+ "-XX:-MonomorphicArrayCheck"),
+ new Scenario(3,
+ "-XX:FlatArrayElementMaxSize=-1",
+ "-XX:-UseArrayLoadStoreProfile",
+ "-XX:-UseACmpProfile",
+ "-XX:TypeProfileLevel=0",
+ "-XX:-MonomorphicArrayCheck",
+ "-XX:TieredStopAtLevel=4",
+ "-XX:-TieredCompilation"),
+ new Scenario(4,
+ "-XX:FlatArrayElementMaxSize=-1",
+ "-XX:+UseArrayLoadStoreProfile",
+ "-XX:+UseACmpProfile",
+ "-XX:TypeProfileLevel=0",
+ "-XX:TieredStopAtLevel=4",
+ "-XX:-TieredCompilation"),
+ new Scenario(5,
+ "-XX:FlatArrayElementMaxSize=-1",
+ "-XX:-UseArrayLoadStoreProfile",
+ "-XX:-UseACmpProfile",
+ "-XX:TypeProfileLevel=222",
+ "-XX:-MonomorphicArrayCheck",
+ "-XX:TieredStopAtLevel=4",
+ "-XX:-TieredCompilation")
+ };
+
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .addFlags("-XX:+IgnoreUnrecognizedVMOptions")
+ .addHelperClasses(MyValue1.class,
+ MyValue2.class)
+ .start();
}
private static final MyValue1 testValue1 = MyValue1.createWithFieldsInline(rI, rL);
@@ -95,19 +106,31 @@ public static void main(String[] args) throws Throwable {
private static final MyValue1.ref[] testValue1NotFlatArray = new MyValue1.ref[] {testValue1};
private static final MyValue1[][] testValue1ArrayArray = new MyValue1[][] {testValue1Array};
+ // Wrap these variables into helper class because
+ // WhiteBox API needs to be initialized by TestFramework first.
+ static class WBFlags {
+ static final boolean UseACmpProfile = (Boolean) WhiteBox.getWhiteBox().getVMFlag("UseACmpProfile");
+ static final boolean TieredCompilation = (Boolean) WhiteBox.getWhiteBox().getVMFlag("TieredCompilation");
+ static final boolean ProfileInterpreter = (Boolean) WhiteBox.getWhiteBox().getVMFlag("ProfileInterpreter");
+ static final boolean UseArrayLoadStoreProfile = (Boolean) WhiteBox.getWhiteBox().getVMFlag("UseArrayLoadStoreProfile");
+ static final long TypeProfileLevel = (Long) WhiteBox.getWhiteBox().getVMFlag("TypeProfileLevel");
+ }
+
// aaload
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, failOn = LOAD_UNKNOWN_INLINE)
- @Test(valid = TypeProfileOn, failOn = LOAD_UNKNOWN_INLINE)
- @Test(match = { LOAD_UNKNOWN_INLINE }, matchCount = { 1 })
+ @Test
+ @IR(applyIfOr = {"UseArrayLoadStoreProfile", "true", "TypeProfileLevel", "= 222"},
+ failOn = {LOAD_UNKNOWN_INLINE})
+ @IR(applyIfAnd={"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"},
+ counts = {LOAD_UNKNOWN_INLINE, "= 1"})
public Object test1(Object[] array) {
return array[0];
}
- @DontCompile
- public void test1_verifier(boolean warmup) {
- if (warmup) {
+ @Run(test = "test1")
+ @Warmup(10000)
+ public void test1_verifier(RunInfo info) {
+ if (info.isWarmUp()) {
Object o = test1(testValue1Array);
Asserts.assertEQ(((MyValue1)o).hash(), testValue1.hash());
} else {
@@ -116,17 +139,19 @@ public void test1_verifier(boolean warmup) {
}
}
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, failOn = LOAD_UNKNOWN_INLINE)
- @Test(valid = TypeProfileOn, failOn = LOAD_UNKNOWN_INLINE)
- @Test(match = { LOAD_UNKNOWN_INLINE }, matchCount = { 1 })
+ @Test
+ @IR(applyIfOr = {"UseArrayLoadStoreProfile", "true", "TypeProfileLevel", "= 222"},
+ failOn = {LOAD_UNKNOWN_INLINE})
+ @IR(applyIfAnd = {"UseArrayLoadStoreProfile", "false", "TypeProfileLevel", "!= 222"},
+ counts = {LOAD_UNKNOWN_INLINE, "= 1"})
public Object test2(Object[] array) {
return array[0];
}
- @DontCompile
- public void test2_verifier(boolean warmup) {
- if (warmup) {
+ @Run(test = "test2")
+ @Warmup(10000)
+ public void test2_verifier(RunInfo info) {
+ if (info.isWarmUp()) {
Object o = test2(testIntegerArray);
Asserts.assertEQ(o, 42);
} else {
@@ -135,30 +160,34 @@ public void test2_verifier(boolean warmup) {
}
}
- @Warmup(10000)
- @Test(match = { LOAD_UNKNOWN_INLINE }, matchCount = { 1 })
+ @Test
+ @IR(counts = {LOAD_UNKNOWN_INLINE, "= 1"})
public Object test3(Object[] array) {
return array[0];
}
- @DontCompile
- public void test3_verifier(boolean warmup) {
+ @Run(test = "test3")
+ @Warmup(10000)
+ public void test3_verifier() {
Object o = test3(testValue1Array);
Asserts.assertEQ(((MyValue1)o).hash(), testValue1.hash());
o = test3(testValue2Array);
Asserts.assertEQ(((MyValue2)o).hash(), testValue2.hash());
}
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, failOn = LOAD_UNKNOWN_INLINE)
- @Test(match = { LOAD_UNKNOWN_INLINE }, matchCount = { 1 })
+ @Test
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "true"},
+ failOn = {LOAD_UNKNOWN_INLINE})
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "false"},
+ counts = {LOAD_UNKNOWN_INLINE, "= 1"})
public Object test4(Object[] array) {
return array[0];
}
- @DontCompile
- public void test4_verifier(boolean warmup) {
- if (warmup) {
+ @Run(test = "test4")
+ @Warmup(10000)
+ public void test4_verifier(RunInfo info) {
+ if (info.isWarmUp()) {
Object o = test4(testIntegerArray);
Asserts.assertEQ(o, 42);
o = test4(testLongArray);
@@ -169,14 +198,15 @@ public void test4_verifier(boolean warmup) {
}
}
- @Warmup(10000)
- @Test(match = { LOAD_UNKNOWN_INLINE }, matchCount = { 1 })
+ @Test
+ @IR(counts = {LOAD_UNKNOWN_INLINE, "= 1"})
public Object test5(Object[] array) {
return array[0];
}
- @DontCompile
- public void test5_verifier(boolean warmup) {
+ @Run(test = "test5")
+ @Warmup(10000)
+ public void test5_verifier() {
Object o = test5(testValue1Array);
Asserts.assertEQ(((MyValue1)o).hash(), testValue1.hash());
o = test5(testValue1NotFlatArray);
@@ -196,19 +226,21 @@ public void test6_helper(Number[] arg) {
}
}
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, match = { CALL, CLASS_CHECK_TRAP, NULL_CHECK_TRAP, RANGE_CHECK_TRAP }, matchCount = { 3, 1, 1, 1 })
- @Test(valid = TypeProfileOn, match = { CALL, CLASS_CHECK_TRAP, NULL_CHECK_TRAP, RANGE_CHECK_TRAP }, matchCount = { 3, 1, 1, 1 })
- @Test(match = { CALL, RANGE_CHECK_TRAP, NULL_CHECK_TRAP }, matchCount = { 5, 1, 1 })
+ @Test
+ @IR(applyIfOr = {"UseArrayLoadStoreProfile", "true", "TypeProfileLevel", "= 222"},
+ counts = {CALL, "= 3", CLASS_CHECK_TRAP, "= 1", NULL_CHECK_TRAP, "= 1", RANGE_CHECK_TRAP, "= 1"})
+ @IR(applyIfAnd = {"UseArrayLoadStoreProfile", "false", "TypeProfileLevel", "!= 222"},
+ counts = {CALL, "= 5", RANGE_CHECK_TRAP, "= 1", NULL_CHECK_TRAP, "= 1"})
public Object test6(Number[] array) {
Number v = array[0];
test6_helper(array);
return v;
}
- @DontCompile
- public void test6_verifier(boolean warmup) {
- if (warmup) {
+ @Run(test = "test6")
+ @Warmup(10000)
+ public void test6_verifier(RunInfo info) {
+ if (info.isWarmUp()) {
// pollute profile
test6_helper(testLongArray);
test6_helper(testDoubleArray);
@@ -227,19 +259,21 @@ public void test7_helper(Number arg) {
}
}
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, match = { CALL, CLASS_CHECK_TRAP, NULL_CHECK_TRAP, RANGE_CHECK_TRAP }, matchCount = { 4, 1, 2, 1 })
- @Test(valid = TypeProfileOn, match = { CALL, CLASS_CHECK_TRAP, NULL_CHECK_TRAP, RANGE_CHECK_TRAP }, matchCount = { 4, 1, 2, 1 })
- @Test(match = { CALL, RANGE_CHECK_TRAP, NULL_CHECK_TRAP }, matchCount = { 6, 1, 2 })
+ @Test
+ @IR(applyIfOr = {"UseArrayLoadStoreProfile", "true", "TypeProfileLevel", "= 222"},
+ counts = {CALL, "= 4", CLASS_CHECK_TRAP, "= 1", NULL_CHECK_TRAP, "= 2", RANGE_CHECK_TRAP, "= 1"})
+ @IR(applyIfAnd = {"UseArrayLoadStoreProfile", "false", "TypeProfileLevel", "!= 222"},
+ counts = {CALL, "= 6", RANGE_CHECK_TRAP, "= 1", NULL_CHECK_TRAP, "= 2"})
public Object test7(Number[] array) {
Number v = array[0];
test7_helper(v);
return v;
}
- @DontCompile
- public void test7_verifier(boolean warmup) {
- if (warmup) {
+ @Run(test = "test7")
+ @Warmup(10000)
+ public void test7_verifier(RunInfo info) {
+ if (info.isWarmUp()) {
// pollute profile
test7_helper(42L);
test7_helper(42.0D);
@@ -258,18 +292,23 @@ public void test8_helper(Object arg) {
}
}
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, match = { CALL, CLASS_CHECK_TRAP, NULL_CHECK_TRAP, RANGE_CHECK_TRAP, UNHANDLED_TRAP, ALLOC_G }, matchCount = { 6, 1, 2, 1, 1, 1 })
- @Test(match = { CALL, RANGE_CHECK_TRAP, NULL_CHECK_TRAP, UNHANDLED_TRAP, ALLOC_G }, matchCount = { 6, 1, 2, 1, 1 })
+ @Test
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "true"},
+ counts = {CALL, "= 6", CLASS_CHECK_TRAP, "= 1", NULL_CHECK_TRAP, "= 2",
+ RANGE_CHECK_TRAP, "= 1", UNHANDLED_TRAP, "= 1", ALLOC_G, "= 1"})
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "false"},
+ counts = {CALL, "= 6", RANGE_CHECK_TRAP, "= 1", NULL_CHECK_TRAP, "= 2",
+ UNHANDLED_TRAP, "= 1", ALLOC_G, "= 1"})
public Object test8(Object[] array) {
Object v = array[0];
test8_helper(v);
return v;
}
- @DontCompile
- public void test8_verifier(boolean warmup) {
- if (warmup) {
+ @Run(test = "test8")
+ @Warmup(10000)
+ public void test8_verifier(RunInfo info) {
+ if (info.isWarmUp()) {
// pollute profile
test8_helper(42L);
test8_helper(42.0D);
@@ -280,91 +319,104 @@ public void test8_verifier(boolean warmup) {
// aastore
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, failOn = STORE_UNKNOWN_INLINE)
- @Test(valid = TypeProfileOn, failOn = STORE_UNKNOWN_INLINE)
- @Test(match = { STORE_UNKNOWN_INLINE }, matchCount = { 1 })
+ @Test
+ @IR(applyIfOr = {"UseArrayLoadStoreProfile", "true", "TypeProfileLevel", "= 222"},
+ failOn = {STORE_UNKNOWN_INLINE})
+ @IR(applyIfAnd = {"UseArrayLoadStoreProfile", "false", "TypeProfileLevel", "!= 222"},
+ counts = {STORE_UNKNOWN_INLINE, "= 1"})
public void test9(Object[] array, Object v) {
array[0] = v;
}
- @DontCompile
- public void test9_verifier(boolean warmup) {
+ @Run(test = "test9")
+ @Warmup(10000)
+ public void test9_verifier() {
test9(testValue1Array, testValue1);
Asserts.assertEQ(testValue1Array[0].hash(), testValue1.hash());
}
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, failOn = STORE_UNKNOWN_INLINE)
- @Test(valid = TypeProfileOn, failOn = STORE_UNKNOWN_INLINE)
- @Test(match = { STORE_UNKNOWN_INLINE }, matchCount = { 1 })
+
+ @Test
+ @IR(applyIfOr = {"UseArrayLoadStoreProfile", "true", "TypeProfileLevel", "= 222"},
+ failOn = {STORE_UNKNOWN_INLINE})
+ @IR(applyIfAnd = {"UseArrayLoadStoreProfile", "false", "TypeProfileLevel", "!= 222"},
+ counts = {STORE_UNKNOWN_INLINE, "= 1"})
public void test10(Object[] array, Object v) {
array[0] = v;
}
- @DontCompile
- public void test10_verifier(boolean warmup) {
+ @Run(test = "test10")
+ @Warmup(10000)
+ public void test10_verifier() {
test10(testIntegerArray, 42);
}
- @Warmup(10000)
- @Test(match = { STORE_UNKNOWN_INLINE }, matchCount = { 1 })
+ @Test
+ @IR(counts = {STORE_UNKNOWN_INLINE, "= 1"})
public void test11(Object[] array, Object v) {
array[0] = v;
}
- @DontCompile
- public void test11_verifier(boolean warmup) {
+ @Run(test = "test11")
+ @Warmup(10000)
+ public void test11_verifier() {
test11(testValue1Array, testValue1);
test11(testValue2Array, testValue2);
}
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, failOn = STORE_UNKNOWN_INLINE)
- @Test(match = { STORE_UNKNOWN_INLINE }, matchCount = { 1 })
+ @Test
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "true"},
+ failOn = {STORE_UNKNOWN_INLINE})
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "false"},
+ counts = {STORE_UNKNOWN_INLINE, "= 1"})
public void test12(Object[] array, Object v) {
array[0] = v;
}
- @DontCompile
- public void test12_verifier(boolean warmup) {
+ @Run(test = "test12")
+ @Warmup(10000)
+ public void test12_verifier() {
test12(testIntegerArray, 42);
test12(testLongArray, 42L);
}
- @Warmup(10000)
- @Test(match = { STORE_UNKNOWN_INLINE }, matchCount = { 1 })
+ @Test
+ @IR(counts = {STORE_UNKNOWN_INLINE, "= 1"})
public void test13(Object[] array, Object v) {
array[0] = v;
}
- @DontCompile
- public void test13_verifier(boolean warmup) {
+ @Run(test = "test13")
+ @Warmup(10000)
+ public void test13_verifier() {
test13(testValue1Array, testValue1);
test13(testValue1NotFlatArray, testValue1);
}
+
// MonomorphicArrayCheck
- @Warmup(10000)
@Test
public void test14(Number[] array, Number v) {
array[0] = v;
}
- @DontCompile
- public void test14_verifier(boolean warmup) {
- if (warmup) {
+ @Run(test = "test14")
+ @Warmup(10000)
+ public void test14_verifier(RunInfo info) {
+ if (info.isWarmUp()) {
test14(testIntegerArray, 42);
} else {
- Method m = tests.get("TestLWorldProfiling::test14");
+ Method m = info.getTest();
boolean deopt = false;
for (int i = 0; i < 100; i++) {
test14(testIntegerArray, 42);
- if (!WHITE_BOX.isMethodCompiled(m, false)) {
+ if (!info.isCompilationSkipped() && !TestFramework.isCompiled(m)) {
deopt = true;
}
}
- if (deopt && !TieredCompilation && !STRESS_CC && ProfileInterpreter && (UseArrayLoadStoreProfile || TypeProfileLevel == 222)) {
+
+ if (deopt && !WBFlags.TieredCompilation && WBFlags.ProfileInterpreter &&
+ (WBFlags.UseArrayLoadStoreProfile || WBFlags.TypeProfileLevel == 222)) {
throw new RuntimeException("Monomorphic array check should rely on profiling and be accurate");
}
}
@@ -384,16 +436,19 @@ primitive static class NotFlattenable {
private static final NotFlattenable notFlattenable = new NotFlattenable();
private static final NotFlattenable[] testNotFlattenableArray = new NotFlattenable[] { notFlattenable };
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, match = { NULL_CHECK_TRAP }, matchCount = { 2 }, failOn = STORE_UNKNOWN_INLINE)
- @Test(valid = TypeProfileOn, match = { NULL_CHECK_TRAP }, matchCount = { 2 }, failOn = STORE_UNKNOWN_INLINE)
- @Test(match = { NULL_CHECK_TRAP, STORE_UNKNOWN_INLINE }, matchCount = { 3, 1 })
+ @Test
+ @IR(applyIfOr = {"UseArrayLoadStoreProfile", "true", "TypeProfileLevel", "= 222"},
+ counts = {NULL_CHECK_TRAP, "= 2"},
+ failOn = {STORE_UNKNOWN_INLINE})
+ @IR(applyIfAnd = {"UseArrayLoadStoreProfile", "false", "TypeProfileLevel", "!= 222"},
+ counts = {NULL_CHECK_TRAP, "= 3", STORE_UNKNOWN_INLINE, "= 1"})
public void test15(Object[] array, Object v) {
array[0] = v;
}
- @DontCompile
- public void test15_verifier(boolean warmup) {
+ @Run(test = "test15")
+ @Warmup(10000)
+ public void test15_verifier() {
test15(testNotFlattenableArray, notFlattenable);
try {
test15(testNotFlattenableArray, null);
@@ -403,15 +458,19 @@ public void test15_verifier(boolean warmup) {
}
}
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, match = { NULL_CHECK_TRAP }, matchCount = { 2 }, failOn = STORE_UNKNOWN_INLINE)
- @Test(match = { NULL_CHECK_TRAP, STORE_UNKNOWN_INLINE }, matchCount = { 3, 1 })
+ @Test
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "true"},
+ counts = {NULL_CHECK_TRAP, "= 2"},
+ failOn = {STORE_UNKNOWN_INLINE})
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "false"},
+ counts = {NULL_CHECK_TRAP, "= 3", STORE_UNKNOWN_INLINE, "= 1"})
public void test16(Object[] array, Object v) {
array[0] = v;
}
- @DontCompile
- public void test16_verifier(boolean warmup) {
+ @Run(test = "test16")
+ @Warmup(10000)
+ public void test16_verifier() {
test16(testNotFlattenableArray, notFlattenable);
try {
test16(testNotFlattenableArray, null);
@@ -422,15 +481,19 @@ public void test16_verifier(boolean warmup) {
test16(testIntegerArray, 42);
}
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, match = { NULL_CHECK_TRAP }, matchCount = { 1 }, failOn = STORE_UNKNOWN_INLINE)
- @Test(match = { NULL_CHECK_TRAP, STORE_UNKNOWN_INLINE }, matchCount = { 3, 1 })
+ @Test
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "true"},
+ counts = {NULL_CHECK_TRAP, "= 1"},
+ failOn = {STORE_UNKNOWN_INLINE})
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "false"},
+ counts = {NULL_CHECK_TRAP, "= 3", STORE_UNKNOWN_INLINE, "= 1"})
public void test17(Object[] array, Object v) {
array[0] = v;
}
- @DontCompile
- public void test17_verifier(boolean warmup) {
+ @Run(test = "test17")
+ @Warmup(10000)
+ public void test17_verifier() {
test17(testIntegerArray, 42);
test17(testIntegerArray, null);
testIntegerArray[0] = 42;
@@ -441,17 +504,21 @@ public void test18_helper(Object[] array, Object v) {
array[0] = v;
}
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, match = { NULL_CHECK_TRAP }, matchCount = { 1 }, failOn = STORE_UNKNOWN_INLINE)
- @Test(match = { NULL_CHECK_TRAP, STORE_UNKNOWN_INLINE }, matchCount = { 3, 1 })
+ @Test
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "true"},
+ counts = {NULL_CHECK_TRAP, "= 1"},
+ failOn = {STORE_UNKNOWN_INLINE})
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "false"},
+ counts = {NULL_CHECK_TRAP, "= 3", STORE_UNKNOWN_INLINE, "= 1"})
public Object test18(Object[] array, Object v1) {
Object v2 = array[0];
test18_helper(array, v1);
return v2;
}
- @DontCompile
- public void test18_verifier(boolean warmup) {
+ @Run(test = "test18")
+ @Warmup(10000)
+ public void test18_verifier() {
test18_helper(testValue1Array, testValue1); // pollute profile
test18(testIntegerArray, 42);
test18(testIntegerArray, null);
@@ -461,30 +528,36 @@ public void test18_verifier(boolean warmup) {
// maybe null free, not flat
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, failOn = LOAD_UNKNOWN_INLINE)
- @Test(match = { LOAD_UNKNOWN_INLINE }, matchCount = { 1 })
+ @Test
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "true"},
+ failOn = {LOAD_UNKNOWN_INLINE})
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "false"},
+ counts = {LOAD_UNKNOWN_INLINE, "= 1"})
public Object test19(Object[] array) {
return array[0];
}
- @DontCompile
- public void test19_verifier(boolean warmup) {
+ @Run(test = "test19")
+ @Warmup(10000)
+ public void test19_verifier() {
Object o = test19(testIntegerArray);
Asserts.assertEQ(o, 42);
o = test19(testNotFlattenableArray);
Asserts.assertEQ(o, notFlattenable);
}
- @Warmup(10000)
- @Test(valid = ArrayLoadStoreProfileOn, failOn = STORE_UNKNOWN_INLINE)
- @Test(match = { STORE_UNKNOWN_INLINE }, matchCount = { 1 })
+ @Test
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "true"},
+ failOn = {STORE_UNKNOWN_INLINE})
+ @IR(applyIf = {"UseArrayLoadStoreProfile", "false"},
+ counts = {STORE_UNKNOWN_INLINE, "= 1"})
public void test20(Object[] array, Object o) {
array[0] = o;
}
- @DontCompile
- public void test20_verifier(boolean warmup) {
+ @Run(test = "test20")
+ @Warmup(10000)
+ public void test20_verifier() {
test20(testIntegerArray, 42);
test20(testNotFlattenableArray, notFlattenable);
}
@@ -492,384 +565,460 @@ public void test20_verifier(boolean warmup) {
// acmp tests
// branch frequency profiling causes not equal branch to be optimized out
- @Warmup(10000)
- @Test(failOn = SUBSTITUTABILITY_TEST)
+ @Test
+ @IR(failOn = {SUBSTITUTABILITY_TEST})
public boolean test21(Object o1, Object o2) {
return o1 == o2;
}
- @DontCompile
- public void test21_verifier(boolean warmup) {
+ @Run(test = "test21")
+ @Warmup(10000)
+ public void test21_verifier() {
test21(42, 42);
test21(testValue1, testValue1);
}
// Input profiled non null
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_ASSERT_TRAP }, matchCount = { 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIf = {"UseACmpProfile", "true"},
+ failOn = {SUBSTITUTABILITY_TEST},
+ counts = {NULL_ASSERT_TRAP, "= 1"})
+ @IR(applyIf = {"UseACmpProfile", "false"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test22(Object o1, Object o2) {
return o1 == o2;
}
- @DontCompile
- public void test22_verifier(boolean warmup) {
+ @Run(test = "test22")
+ @Warmup(10000)
+ public void test22_verifier(RunInfo info) {
test22(42, null);
test22(42.0, null);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test22"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
test22(42, 42.0);
- if (UseACmpProfile) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test22"));
+ if (WBFlags.UseACmpProfile) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_ASSERT_TRAP }, matchCount = { 1})
- @Test(valid = TypeProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_ASSERT_TRAP }, matchCount = { 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIfOr = {"UseACmpProfile", "true", "TypeProfileLevel", "= 222"},
+ failOn = {SUBSTITUTABILITY_TEST},
+ counts = {NULL_ASSERT_TRAP, "= 1"})
+ @IR(applyIfAnd = {"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test23(Object o1, Object o2) {
return o1 == o2;
}
- @DontCompile
- public void test23_verifier(boolean warmup) {
+ @Run(test = "test23")
+ @Warmup(10000)
+ public void test23_verifier(RunInfo info) {
test23(null, 42);
test23(null, 42.0);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test23"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
test23(42, 42.0);
- if (UseACmpProfile || TypeProfileLevel != 0) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test23"));
+ if (WBFlags.UseACmpProfile || WBFlags.TypeProfileLevel != 0) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_ASSERT_TRAP }, matchCount = { 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIf = {"UseACmpProfile", "true"},
+ failOn = {SUBSTITUTABILITY_TEST},
+ counts = {NULL_ASSERT_TRAP, "= 1"})
+ @IR(applyIf = {"UseACmpProfile", "false"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test24(Object o1, Object o2) {
return o1 != o2;
}
- @DontCompile
- public void test24_verifier(boolean warmup) {
+ @Run(test = "test24")
+ @Warmup(10000)
+ public void test24_verifier(RunInfo info) {
test24(42, null);
test24(42.0, null);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test24"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
test24(42, 42.0);
- if (UseACmpProfile) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test24"));
+ if (WBFlags.UseACmpProfile) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_ASSERT_TRAP }, matchCount = { 1})
- @Test(valid = TypeProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_ASSERT_TRAP }, matchCount = { 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIfOr = {"UseACmpProfile", "true", "TypeProfileLevel", "= 222"},
+ failOn = {SUBSTITUTABILITY_TEST},
+ counts = {NULL_ASSERT_TRAP, "= 1"})
+ @IR(applyIfAnd = {"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test25(Object o1, Object o2) {
return o1 != o2;
}
- @DontCompile
- public void test25_verifier(boolean warmup) {
+ @Run(test = "test25")
+ @Warmup(10000)
+ public void test25_verifier(RunInfo info) {
test25(null, 42);
test25(null, 42.0);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test25"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
test25(42, 42.0);
- if (UseACmpProfile || TypeProfileLevel != 0) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test25"));
+ if (WBFlags.UseACmpProfile || WBFlags.TypeProfileLevel != 0) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
// Input profiled not inline type with known type
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_CHECK_TRAP, CLASS_CHECK_TRAP }, matchCount = { 1, 1})
- @Test(valid = TypeProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_CHECK_TRAP, CLASS_CHECK_TRAP }, matchCount = { 1, 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIfOr = {"UseACmpProfile", "true", "TypeProfileLevel", "= 222"},
+ failOn = {SUBSTITUTABILITY_TEST},
+ counts = {NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"})
+ @IR(applyIfAnd = {"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test26(Object o1, Object o2) {
return o1 == o2;
}
- @DontCompile
- public void test26_verifier(boolean warmup) {
+ @Run(test = "test26")
+ @Warmup(10000)
+ public void test26_verifier(RunInfo info) {
test26(42, 42);
test26(42, 42.0);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test26"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
for (int i = 0; i < 10; i++) {
test26(42.0, 42);
}
- if (UseACmpProfile || TypeProfileLevel != 0) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test26"));
+ if (WBFlags.UseACmpProfile || WBFlags.TypeProfileLevel != 0) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_CHECK_TRAP, CLASS_CHECK_TRAP }, matchCount = { 1, 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIf = {"UseACmpProfile", "true"},
+ failOn = {SUBSTITUTABILITY_TEST},
+ counts = { NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"})
+ @IR(applyIf = {"UseACmpProfile", "false"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test27(Object o1, Object o2) {
return o1 == o2;
}
- @DontCompile
- public void test27_verifier(boolean warmup) {
+ @Run(test = "test27")
+ @Warmup(10000)
+ public void test27_verifier(RunInfo info) {
test27(42, 42);
test27(42.0, 42);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test27"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
for (int i = 0; i < 10; i++) {
test27(42, 42.0);
}
- if (UseACmpProfile) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test27"));
+ if (WBFlags.UseACmpProfile) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_CHECK_TRAP, CLASS_CHECK_TRAP }, matchCount = { 1, 1})
- @Test(valid = TypeProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_CHECK_TRAP, CLASS_CHECK_TRAP }, matchCount = { 1, 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIfOr = {"UseACmpProfile", "true", "TypeProfileLevel", "= 222"},
+ failOn = {SUBSTITUTABILITY_TEST},
+ counts = {NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"})
+ @IR(applyIfAnd = {"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test28(Object o1, Object o2) {
return o1 != o2;
}
- @DontCompile
- public void test28_verifier(boolean warmup) {
+ @Run(test = "test28")
+ @Warmup(10000)
+ public void test28_verifier(RunInfo info) {
test28(42, 42);
test28(42, 42.0);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test28"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
for (int i = 0; i < 10; i++) {
test28(42.0, 42);
}
- if (UseACmpProfile || TypeProfileLevel != 0) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test28"));
+ if (WBFlags.UseACmpProfile || WBFlags.TypeProfileLevel != 0) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_CHECK_TRAP, CLASS_CHECK_TRAP }, matchCount = { 1, 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIf = {"UseACmpProfile", "true"},
+ failOn = {SUBSTITUTABILITY_TEST},
+ counts = {NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"})
+ @IR(applyIf = {"UseACmpProfile", "false"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test29(Object o1, Object o2) {
return o1 != o2;
}
- @DontCompile
- public void test29_verifier(boolean warmup) {
+ @Run(test = "test29")
+ @Warmup(10000)
+ public void test29_verifier(RunInfo info) {
test29(42, 42);
test29(42.0, 42);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test29"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
for (int i = 0; i < 10; i++) {
test29(42, 42.0);
}
- if (UseACmpProfile) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test29"));
+ if (WBFlags.UseACmpProfile) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST + NULL_CHECK_TRAP, match = { CLASS_CHECK_TRAP }, matchCount = { 1})
- @Test(valid = TypeProfileOn, failOn = SUBSTITUTABILITY_TEST + NULL_CHECK_TRAP, match = { CLASS_CHECK_TRAP }, matchCount = { 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIfOr = {"UseACmpProfile", "true", "TypeProfileLevel", "= 222"},
+ failOn = {SUBSTITUTABILITY_TEST, NULL_CHECK_TRAP},
+ counts = {CLASS_CHECK_TRAP, "= 1"})
+ @IR(applyIfAnd = {"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test30(Object o1, Object o2) {
return o1 == o2;
}
- @DontCompile
- public void test30_verifier(boolean warmup) {
+ @Run(test = "test30")
+ @Warmup(10000)
+ public void test30_verifier(RunInfo info) {
test30(42, 42);
test30(42, 42.0);
test30(null, 42);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test30"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
for (int i = 0; i < 10; i++) {
test30(42.0, 42);
}
- if (UseACmpProfile || TypeProfileLevel != 0) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test30"));
+ if (WBFlags.UseACmpProfile || WBFlags.TypeProfileLevel != 0) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST + NULL_CHECK_TRAP)
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIf = {"UseACmpProfile", "true"},
+ failOn = {SUBSTITUTABILITY_TEST, NULL_CHECK_TRAP})
+ @IR(applyIf = {"UseACmpProfile", "false"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test31(Object o1, Object o2) {
return o1 == o2;
}
- @DontCompile
- public void test31_verifier(boolean warmup) {
+ @Run(test = "test31")
+ @Warmup(10000)
+ public void test31_verifier(RunInfo info) {
test31(42, 42);
test31(42.0, 42);
test31(42, null);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test31"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
for (int i = 0; i < 10; i++) {
test31(42, 42.0);
}
- if (UseACmpProfile) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test31"));
+ if (WBFlags.UseACmpProfile) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
// Input profiled not inline type with unknown type
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_CHECK_TRAP, CLASS_CHECK_TRAP }, matchCount = { 1, 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIf = {"UseACmpProfile", "true"},
+ failOn = {SUBSTITUTABILITY_TEST},
+ counts = {NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"})
+ @IR(applyIf = {"UseACmpProfile", "false"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test32(Object o1, Object o2) {
return o1 == o2;
}
- @DontCompile
- public void test32_verifier(boolean warmup) {
+ @Run(test = "test32")
+ @Warmup(10000)
+ public void test32_verifier(RunInfo info) {
test32(42, 42);
test32(42, testValue1);
test32(42.0, 42);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test32"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
for (int i = 0; i < 10; i++) {
test32(testValue1, 42);
}
- if (UseACmpProfile) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test32"));
+ if (WBFlags.UseACmpProfile) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_CHECK_TRAP, CLASS_CHECK_TRAP }, matchCount = { 1, 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIf = {"UseACmpProfile", "true"},
+ failOn = {SUBSTITUTABILITY_TEST},
+ counts = {NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"})
+ @IR(applyIf = {"UseACmpProfile", "false"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test33(Object o1, Object o2) {
return o1 == o2;
}
- @DontCompile
- public void test33_verifier(boolean warmup) {
+ @Run(test = "test33")
+ @Warmup(10000)
+ public void test33_verifier(RunInfo info) {
test33(42, 42);
test33(testValue1, 42);
test33(42, 42.0);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test33"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
for (int i = 0; i < 10; i++) {
test33(42, testValue1);
}
- if (UseACmpProfile) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test33"));
+ if (WBFlags.UseACmpProfile) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_CHECK_TRAP, CLASS_CHECK_TRAP }, matchCount = { 1, 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIf = {"UseACmpProfile", "true"},
+ failOn = {SUBSTITUTABILITY_TEST},
+ counts = {NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"})
+ @IR(applyIf = {"UseACmpProfile", "false"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test34(Object o1, Object o2) {
return o1 != o2;
}
- @DontCompile
- public void test34_verifier(boolean warmup) {
+ @Run(test = "test34")
+ @Warmup(10000)
+ public void test34_verifier(RunInfo info) {
test34(42, 42);
test34(42, testValue1);
test34(42.0, 42);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test34"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
for (int i = 0; i < 10; i++) {
test34(testValue1, 42);
}
- if (UseACmpProfile) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test34"));
+ if (WBFlags.UseACmpProfile) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { NULL_CHECK_TRAP, CLASS_CHECK_TRAP }, matchCount = { 1, 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIf = {"UseACmpProfile", "true"},
+ failOn = {SUBSTITUTABILITY_TEST},
+ counts = {NULL_CHECK_TRAP, "= 1", CLASS_CHECK_TRAP, "= 1"})
+ @IR(applyIf = {"UseACmpProfile", "false"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test35(Object o1, Object o2) {
return o1 != o2;
}
- @DontCompile
- public void test35_verifier(boolean warmup) {
+ @Run(test = "test35")
+ @Warmup(10000)
+ public void test35_verifier(RunInfo info) {
test35(42, 42);
test35(testValue1, 42);
test35(42, 42.0);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test35"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
for (int i = 0; i < 10; i++) {
test35(42, testValue1);
}
- if (UseACmpProfile) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test35"));
+ if (WBFlags.UseACmpProfile) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST + NULL_CHECK_TRAP, match = { CLASS_CHECK_TRAP }, matchCount = { 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIf = {"UseACmpProfile", "true"},
+ failOn = {SUBSTITUTABILITY_TEST, NULL_CHECK_TRAP},
+ counts = {CLASS_CHECK_TRAP, "= 1"})
+ @IR(applyIf = {"UseACmpProfile", "false"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test36(Object o1, Object o2) {
return o1 == o2;
}
- @DontCompile
- public void test36_verifier(boolean warmup) {
+ @Run(test = "test36")
+ @Warmup(10000)
+ public void test36_verifier(RunInfo info) {
test36(42, 42.0);
test36(42.0, testValue1);
test36(null, 42);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test36"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
for (int i = 0; i < 10; i++) {
test36(testValue1, 42);
}
- if (UseACmpProfile) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test36"));
+ if (WBFlags.UseACmpProfile) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST + NULL_CHECK_TRAP)
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1})
+ @Test
+ @IR(applyIf = {"UseACmpProfile", "true"},
+ failOn = {SUBSTITUTABILITY_TEST, NULL_CHECK_TRAP})
+ @IR(applyIf = {"UseACmpProfile", "false"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public boolean test37(Object o1, Object o2) {
return o1 == o2;
}
- @DontCompile
- public void test37_verifier(boolean warmup) {
+ @Run(test = "test37")
+ @Warmup(10000)
+ public void test37_verifier(RunInfo info) {
test37(42.0, 42);
test37(testValue1, 42.0);
test37(42, null);
- if (!warmup) {
- assertCompiledByC2(tests.get("TestLWorldProfiling::test37"));
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiledByC2(m);
for (int i = 0; i < 10; i++) {
test37(42, testValue1);
}
- if (UseACmpProfile) {
- assertDeoptimizedByC2(tests.get("TestLWorldProfiling::test37"));
+ if (WBFlags.UseACmpProfile) {
+ TestFramework.assertDeoptimizedByC2(m);
}
}
}
// Test that acmp profile data that's unused at the acmp is fed to
// speculation and leverage later
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { CLASS_CHECK_TRAP }, matchCount = { 1})
- @Test(valid = TypeProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { CLASS_CHECK_TRAP }, matchCount = { 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1 })
+ @Test
+ @IR(applyIfOr = {"UseACmpProfile", "true", "TypeProfileLevel", "= 222"},
+ failOn = {SUBSTITUTABILITY_TEST},
+ counts = {CLASS_CHECK_TRAP, "= 1"})
+ @IR(applyIfAnd = {"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public void test38(Object o1, Object o2, Object o3) {
if (o1 == o2) {
test38_helper2();
@@ -885,16 +1034,20 @@ public void test38_helper(Object o1, Object o2) {
public void test38_helper2() {
}
- @DontCompile
- public void test38_verifier(boolean warmup) {
+ @Run(test = "test38")
+ @Warmup(10000)
+ public void test38_verifier() {
test38(42, 42, 42);
test38_helper(testValue1, testValue2);
}
- @Warmup(10000)
- @Test(valid = ACmpProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { CLASS_CHECK_TRAP }, matchCount = { 1})
- @Test(valid = TypeProfileOn, failOn = SUBSTITUTABILITY_TEST, match = { CLASS_CHECK_TRAP }, matchCount = { 1})
- @Test(match = { SUBSTITUTABILITY_TEST }, matchCount = { 1 })
+
+ @Test
+ @IR(applyIfOr = {"UseACmpProfile", "true", "TypeProfileLevel", "= 222"},
+ failOn = {SUBSTITUTABILITY_TEST},
+ counts = {CLASS_CHECK_TRAP, "= 1"})
+ @IR(applyIfAnd = {"UseACmpProfile", "false", "TypeProfileLevel", "!= 222"},
+ counts = {SUBSTITUTABILITY_TEST, "= 1"})
public void test39(Object o1, Object o2, Object o3) {
if (o1 == o2) {
test39_helper2();
@@ -910,8 +1063,9 @@ public void test39_helper(Object o1, Object o2) {
public void test39_helper2() {
}
- @DontCompile
- public void test39_verifier(boolean warmup) {
+ @Run(test = "test39")
+ @Warmup(10000)
+ public void test39_verifier() {
test39(42, 42, 42);
test39_helper(testValue1, testValue2);
}
@@ -926,18 +1080,18 @@ public Object test40_access(Object[] array) {
return array[0];
}
- @Warmup(10000)
- @Test()
+ @Test
public Object test40(Test40Abstract[] array) {
return test40_access(array);
}
- @DontCompile
- public void test40_verifier(boolean warmup) {
+ @Run(test = "test40")
+ @Warmup(10000)
+ public void test40_verifier(RunInfo info) {
// Make sure multiple implementors of Test40Abstract are loaded
Test40Inline tmp1 = new Test40Inline();
Test40Class tmp2 = new Test40Class();
- if (warmup) {
+ if (info.isWarmUp()) {
// Pollute profile with Object[] (exact)
test40_access(new Object[1]);
} else {
@@ -952,18 +1106,18 @@ public void test41_access(Object[] array, Object val) {
array[0] = val;
}
- @Warmup(10000)
- @Test()
+ @Test
public void test41(Test40Inline[] array, Object val) {
test41_access(array, val);
}
- @DontCompile
- public void test41_verifier(boolean warmup) {
+ @Run(test = "test41")
+ @Warmup(10000)
+ public void test41_verifier(RunInfo info) {
// Make sure multiple implementors of Test40Abstract are loaded
Test40Inline tmp1 = new Test40Inline();
Test40Class tmp2 = new Test40Class();
- if (warmup) {
+ if (info.isWarmUp()) {
// Pollute profile with exact Object[]
test41_access(new Object[1], new Object());
} else {
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMethodHandles.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMethodHandles.java
index 6e093b45ff9..3263c9936a8 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMethodHandles.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMethodHandles.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2021, 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,35 +23,29 @@
package compiler.valhalla.inlinetypes;
-import java.lang.invoke.*;
+import compiler.lib.ir_framework.*;
+import jdk.test.lib.Asserts;
+import sun.hotspot.WhiteBox;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
-import jdk.test.lib.Asserts;
+import static compiler.valhalla.inlinetypes.InlineTypes.IRNode.*;
+import static compiler.valhalla.inlinetypes.InlineTypes.*;
/*
* @test
* @key randomness
* @summary Test method handle support for inline types
- * @library /testlibrary /test/lib /compiler/whitebox /
+ * @library /test/lib /
* @requires os.simpleArch == "x64"
- * @compile TestMethodHandles.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestMethodHandles
+ * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestMethodHandles
*/
-public class TestMethodHandles extends InlineTypeTest {
- // Extra VM parameters for some test scenarios. See InlineTypeTest.getVMParameters()
- @Override
- public String[] getExtraVMParameters(int scenario) {
- switch (scenario) {
- // Prevent inlining through MethodHandle linkTo adapters to stress the calling convention
- case 2: return new String[] {"-DVerifyIR=false", "-XX:CompileCommand=dontinline,java.lang.invoke.DirectMethodHandle::internalMemberName"};
- case 4: return new String[] {"-XX:CompileCommand=dontinline,java.lang.invoke.DirectMethodHandle::internalMemberName"};
- }
- return null;
- }
+
+@ForceCompileClassInitializer
+public class TestMethodHandles {
static {
try {
@@ -132,9 +126,22 @@ public String[] getExtraVMParameters(int scenario) {
}
}
- public static void main(String[] args) throws Throwable {
- TestMethodHandles test = new TestMethodHandles();
- test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class, MyValue3.class, MyValue3Inline.class);
+ public static void main(String[] args) {
+ Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS;
+
+ // Prevent inlining through MethodHandle linkTo adapters to stress the calling convention
+ scenarios[2].addFlags("-DVerifyIR=false",
+ "-XX:CompileCommand=dontinline,java.lang.invoke.DirectMethodHandle::internalMemberName");
+ scenarios[4].addFlags("-XX:CompileCommand=dontinline,java.lang.invoke.DirectMethodHandle::internalMemberName");
+
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .addHelperClasses(MyValue1.class,
+ MyValue2.class,
+ MyValue2Inline.class,
+ MyValue3.class,
+ MyValue3Inline.class)
+ .start();
}
// Everything inlined
@@ -147,14 +154,17 @@ MyValue3 test1_target() {
static final MethodHandle test1_mh;
- @Test(valid = InlineTypeReturnedAsFieldsOn, failOn = ALLOC + STORE + CALL)
- @Test(valid = InlineTypeReturnedAsFieldsOff, match = { ALLOC, STORE }, matchCount = { 1, 14 })
+ @Test
+ @IR(applyIf = {"InlineTypeReturnedAsFields", "true"},
+ failOn = {ALLOC, STORE, CALL})
+ @IR(applyIf = {"InlineTypeReturnedAsFields", "false"},
+ counts = {ALLOC, "= 1", STORE, "= 14"})
public MyValue3 test1() throws Throwable {
return (MyValue3)test1_mh.invokeExact(this);
}
- @DontCompile
- public void test1_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test1")
+ public void test1_verifier() throws Throwable {
MyValue3 vt = test1();
test1_vt.verify(vt);
}
@@ -173,12 +183,13 @@ public MyValue3 test2() throws Throwable {
return (MyValue3)test2_mh.invokeExact(this);
}
- @DontCompile
- public void test2_verifier(boolean warmup) throws Throwable {
- Method helper_m = getClass().getDeclaredMethod("test2_target");
- if (!warmup && USE_COMPILER && !WHITE_BOX.isMethodCompiled(helper_m, false)) {
- enqueueMethodForCompilation(helper_m, COMP_LEVEL_FULL_OPTIMIZATION);
- Asserts.assertTrue(WHITE_BOX.isMethodCompiled(helper_m, false), "test2_target not compiled");
+ @Run(test = "test2")
+ public void test2_verifier(RunInfo info) throws Throwable {
+ if (!info.isWarmUp()) {
+ Method helper_m = getClass().getDeclaredMethod("test2_target");
+ if (!TestFramework.isCompiled(helper_m)) {
+ TestFramework.compile(helper_m, CompLevel.C2);
+ }
}
MyValue3 vt = test2();
test2_vt.verify(vt);
@@ -198,12 +209,12 @@ public MyValue3 test3() throws Throwable {
return (MyValue3)test3_mh.invokeExact(this);
}
- @DontCompile
- public void test3_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test3")
+ public void test3_verifier(RunInfo info) throws Throwable {
// hack so C2 doesn't know the target of the invoke call
Class c = Class.forName("java.lang.invoke.DirectMethodHandle");
Method m = c.getDeclaredMethod("internalMemberName", Object.class);
- WHITE_BOX.testSetDontInlineMethod(m, warmup);
+ WhiteBox.getWhiteBox().testSetDontInlineMethod(m, info.isWarmUp());
MyValue3 vt = test3();
test3_vt.verify(vt);
}
@@ -228,8 +239,8 @@ public int test4() throws Throwable {
return (int)test4_mh.invokeExact();
}
- @DontCompile
- public void test4_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test4")
+ public void test4_verifier() throws Throwable {
int i = test4();
Asserts.assertEQ(i, test4_vt.x);
}
@@ -247,8 +258,8 @@ public int test5() throws Throwable {
return (int)test5_mh.invokeExact(this, test5_vt);
}
- @DontCompile
- public void test5_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test5")
+ public void test5_verifier() throws Throwable {
int i = test5();
Asserts.assertEQ(i, test5_vt.x);
}
@@ -275,14 +286,15 @@ boolean test6_test() {
static final MethodHandle test6_mh;
- @Test(valid = InlineTypeReturnedAsFieldsOn, failOn = ALLOC + ALLOCA + STORE + STORE_INLINE_FIELDS)
- @Test(valid = InlineTypeReturnedAsFieldsOff)
+ @Test
+ @IR(applyIf = {"InlineTypeReturnedAsFields", "true"},
+ failOn = {ALLOC, ALLOCA, STORE, STORE_INLINE_FIELDS})
public MyValue3 test6() throws Throwable {
return (MyValue3)test6_mh.invokeExact(this);
}
- @DontCompile
- public void test6_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test6")
+ public void test6_verifier() throws Throwable {
test6_bool = !test6_bool;
MyValue3 vt = test6();
vt.verify(test6_bool ? test6_vt1 : test6_vt2);
@@ -314,8 +326,8 @@ public long test7() throws Throwable {
return ((MyValue2)test7_mh.invokeExact(test7_mh1)).hash();
}
- @DontCompile
- public void test7_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test7")
+ public void test7_verifier() throws Throwable {
test7_bool = !test7_bool;
long hash = test7();
Asserts.assertEQ(hash, MyValue2.createWithFieldsInline(rI+(test7_bool ? 0 : 1), rD+(test7_bool ? 0 : 1)).hash());
@@ -347,8 +359,8 @@ public long test8() throws Throwable {
return ((MyValue2)test8_mh.invokeExact(test8_mh2)).hash();
}
- @DontCompile
- public void test8_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test8")
+ public void test8_verifier() throws Throwable {
test8_bool = !test8_bool;
long hash = test8();
Asserts.assertEQ(hash, MyValue2.createWithFieldsInline(rI+(test8_bool ? 0 : 1), rD+(test8_bool ? 0 : 1)).hash());
@@ -388,15 +400,16 @@ boolean test9_test2() {
static final MethodHandle test9_mh;
- @Test(valid = InlineTypeReturnedAsFieldsOn, failOn = ALLOC + ALLOCA + STORE + STORE_INLINE_FIELDS)
- @Test(valid = InlineTypeReturnedAsFieldsOff)
- public MyValue3 test9() throws Throwable {
+ @Test
+ @IR(applyIf = {"InlineTypeReturnedAsFields", "true"},
+ failOn = {ALLOC, ALLOCA, STORE, STORE_INLINE_FIELDS})
+ public MyValue3 test9() throws Throwable {
return (MyValue3)test9_mh.invokeExact(this);
}
static int test9_i = 0;
- @DontCompile
- public void test9_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test9")
+ public void test9_verifier() throws Throwable {
test9_i++;
test9_bool1 = (test9_i % 2) == 0;
test9_bool2 = (test9_i % 3) == 0;
@@ -443,8 +456,8 @@ public long test10() throws Throwable {
static int test10_i = 0;
- @DontCompile
- public void test10_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test10")
+ public void test10_verifier() throws Throwable {
test10_i++;
test10_bool1 = (test10_i % 2) == 0;
test10_bool2 = (test10_i % 3) == 0;
@@ -477,13 +490,13 @@ static boolean test11_test() {
// Check that a buffered inline type returned by a compiled lambda form
// is properly handled by the caller.
@Test
- @Warmup(11000)
public long test11() throws Throwable {
return ((MyValue2)test11_mh.invokeExact(test11_mh2)).hash();
}
- @DontCompile
- public void test11_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test11")
+ @Warmup(11000)
+ public void test11_verifier() throws Throwable {
test11_i++;
long hash = test11();
boolean b = (test11_i % 100) == 0;
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNewAcmp.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNewAcmp.java
index d77e17b00bf..2575dc65511 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNewAcmp.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNewAcmp.java
@@ -33,6 +33,8 @@
package compiler.valhalla.inlinetypes;
+import compiler.lib.ir_framework.CompLevel;
+import compiler.lib.ir_framework.TestFramework;
import jdk.test.lib.Asserts;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
@@ -1804,7 +1806,7 @@ public void run(int nullMode) throws Exception {
// Do some warmup runs
runTest(m, args, 1000, nullMode, equalities);
// Make sure method is compiled
- InlineTypeTest.enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION);
+ TestFramework.compile(m, CompLevel.ANY);
Asserts.assertTrue(WHITE_BOX.isMethodCompiled(m, false), m + " not compiled");
// Run again to verify correctness of compiled code
runTest(m, args, 1, nullMode, equalities);
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableArrays.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableArrays.java
index c3be6cb6d79..2b00bcbdec2 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableArrays.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableArrays.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2021, 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
@@ -24,6 +24,12 @@
package compiler.valhalla.inlinetypes;
import jdk.test.lib.Asserts;
+import compiler.lib.ir_framework.*;
+import static compiler.valhalla.inlinetypes.InlineTypes.rI;
+import static compiler.valhalla.inlinetypes.InlineTypes.rL;
+import static compiler.valhalla.inlinetypes.InlineTypes.rD;
+import static compiler.valhalla.inlinetypes.InlineTypes.IRNode.*;
+
import java.lang.reflect.Method;
import java.util.Arrays;
@@ -31,31 +37,28 @@
* @test
* @key randomness
* @summary Test nullable inline type arrays
- * @library /testlibrary /test/lib /compiler/whitebox /
+ * @library /test/lib /
* @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
- * @compile TestNullableArrays.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestNullableArrays
+ * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestNullableArrays
*/
-public class TestNullableArrays extends InlineTypeTest {
- // Extra VM parameters for some test scenarios. See InlineTypeTest.getVMParameters()
- @Override
- public String[] getExtraVMParameters(int scenario) {
- switch (scenario) {
- case 2: return new String[] {"-XX:-MonomorphicArrayCheck", "-XX:-UncommonNullCast", "-XX:+StressArrayCopyMacroNode"};
- case 3: return new String[] {"-XX:-MonomorphicArrayCheck", "-XX:-UncommonNullCast"};
- case 4: return new String[] {"-XX:-MonomorphicArrayCheck", "-XX:-UncommonNullCast"};
- case 5: return new String[] {"-XX:-MonomorphicArrayCheck", "-XX:-UncommonNullCast", "-XX:+StressArrayCopyMacroNode"};
- }
- return null;
- }
- public static void main(String[] args) throws Throwable {
- TestNullableArrays test = new TestNullableArrays();
- test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class);
+@ForceCompileClassInitializer
+public class TestNullableArrays {
+
+ public static void main(String[] args) {
+
+ Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS;
+ scenarios[2].addFlags("-XX:-MonomorphicArrayCheck", "-XX:-UncommonNullCast", "-XX:+StressArrayCopyMacroNode");
+ scenarios[3].addFlags("-XX:-MonomorphicArrayCheck", "-XX:-UncommonNullCast");
+ scenarios[4].addFlags("-XX:-MonomorphicArrayCheck", "-XX:-UncommonNullCast");
+ scenarios[5].addFlags("-XX:-MonomorphicArrayCheck", "-XX:-UncommonNullCast", "-XX:+StressArrayCopyMacroNode");
+
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .addHelperClasses(MyValue1.class,
+ MyValue2.class,
+ MyValue2Inline.class)
+ .start();
}
// Helper methods
@@ -71,8 +74,12 @@ protected long hash(int x, long y) {
private static final MyValue1 testValue1 = MyValue1.createWithFieldsInline(rI, rL);
// Test nullable inline type array creation and initialization
- @Test(valid = InlineTypeArrayFlattenOn, match = { ALLOCA }, matchCount = { 1 })
- @Test(valid = InlineTypeArrayFlattenOff, match = { ALLOCA }, matchCount = { 1 }, failOn = LOAD)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ counts = {ALLOCA, "= 1"})
+ @IR(applyIf = {"FlatArrayElementMaxSize", "!= -1"},
+ counts = {ALLOCA, "= 1"},
+ failOn = LOAD)
public MyValue1.ref[] test1(int len) {
MyValue1.ref[] va = new MyValue1.ref[len];
if (len > 0) {
@@ -84,8 +91,8 @@ public MyValue1.ref[] test1(int len) {
return va;
}
- @DontCompile
- public void test1_verifier(boolean warmup) {
+ @Run(test = "test1")
+ public void test1_verifier() {
int len = Math.abs(rI % 10);
MyValue1.ref[] va = test1(len);
if (len > 0) {
@@ -97,22 +104,24 @@ public void test1_verifier(boolean warmup) {
}
// Test creation of an inline type array and element access
- @Test(failOn = ALLOC + ALLOCA + LOOP + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOOP, LOAD, STORE, TRAP})
public long test2() {
MyValue1.ref[] va = new MyValue1.ref[1];
va[0] = MyValue1.createWithFieldsInline(rI, rL);
return va[0].hash();
}
- @DontCompile
- public void test2_verifier(boolean warmup) {
+ @Run(test = "test2")
+ public void test2_verifier() {
long result = test2();
Asserts.assertEQ(result, hash());
}
// Test receiving an inline type array from the interpreter,
// updating its elements in a loop and computing a hash.
- @Test(failOn = ALLOCA)
+ @Test
+ @IR(failOn = {ALLOCA})
public long test3(MyValue1.ref[] va) {
long result = 0;
for (int i = 0; i < 10; ++i) {
@@ -125,8 +134,8 @@ public long test3(MyValue1.ref[] va) {
return result;
}
- @DontCompile
- public void test3_verifier(boolean warmup) {
+ @Run(test = "test3")
+ public void test3_verifier() {
MyValue1.ref[] va = new MyValue1.ref[10];
long expected = 0;
for (int i = 1; i < 10; ++i) {
@@ -144,13 +153,14 @@ public void test3_verifier(boolean warmup) {
}
// Test returning an inline type array received from the interpreter
- @Test(failOn = ALLOC + ALLOCA + LOAD + STORE + LOOP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOAD, STORE, LOOP, TRAP})
public MyValue1.ref[] test4(MyValue1.ref[] va) {
return va;
}
- @DontCompile
- public void test4_verifier(boolean warmup) {
+ @Run(test = "test4")
+ public void test4_verifier() {
MyValue1.ref[] va = new MyValue1.ref[10];
for (int i = 0; i < 10; ++i) {
va[i] = MyValue1.createWithFieldsDontInline(rI + i, rL + i);
@@ -187,8 +197,8 @@ public MyValue1.ref[] test5(boolean b) {
return va;
}
- @DontCompile
- public void test5_verifier(boolean warmup) {
+ @Run(test = "test5")
+ public void test5_verifier() {
MyValue1.ref[] va = test5(true);
Asserts.assertEQ(va.length, 5);
Asserts.assertEQ(va[0].hash(), hash(rI, hash()));
@@ -206,27 +216,29 @@ public void test5_verifier(boolean warmup) {
}
// Test creation of inline type array with single element
- @Test(failOn = ALLOC + ALLOCA + LOOP + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOOP, LOAD, STORE, TRAP})
public MyValue1.ref test6() {
MyValue1.ref[] va = new MyValue1.ref[1];
return va[0];
}
- @DontCompile
- public void test6_verifier(boolean warmup) {
+ @Run(test = "test6")
+ public void test6_verifier() {
MyValue1.ref[] va = new MyValue1.ref[1];
MyValue1.ref v = test6();
Asserts.assertEQ(v, null);
}
// Test default initialization of inline type arrays
- @Test(failOn = LOAD)
+ @Test
+ @IR(failOn = LOAD)
public MyValue1.ref[] test7(int len) {
return new MyValue1.ref[len];
}
- @DontCompile
- public void test7_verifier(boolean warmup) {
+ @Run(test = "test7")
+ public void test7_verifier() {
int len = Math.abs(rI % 10);
MyValue1.ref[] va = test7(len);
for (int i = 0; i < len; ++i) {
@@ -236,13 +248,14 @@ public void test7_verifier(boolean warmup) {
}
// Test creation of inline type array with zero length
- @Test(failOn = ALLOC + LOAD + STORE + LOOP + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, LOAD, STORE, LOOP, TRAP})
public MyValue1.ref[] test8() {
return new MyValue1.ref[0];
}
- @DontCompile
- public void test8_verifier(boolean warmup) {
+ @Run(test = "test8")
+ public void test8_verifier() {
MyValue1.ref[] va = test8();
Asserts.assertEQ(va.length, 0);
}
@@ -250,13 +263,14 @@ public void test8_verifier(boolean warmup) {
static MyValue1.ref[] test9_va;
// Test that inline type array loaded from field has correct type
- @Test(failOn = LOOP)
+ @Test
+ @IR(failOn = LOOP)
public long test9() {
return test9_va[0].hash();
}
- @DontCompile
- public void test9_verifier(boolean warmup) {
+ @Run(test = "test9")
+ public void test9_verifier() {
test9_va = new MyValue1.ref[1];
test9_va[0] = testValue1;
long result = test9();
@@ -280,8 +294,8 @@ public MyValue1.ref[][][] test10(int len1, int len2, int len3) {
return arr;
}
- @DontCompile
- public void test10_verifier(boolean warmup) {
+ @Run(test = "test10")
+ public void test10_verifier() {
MyValue1.ref[][][] arr = test10(2, 3, 4);
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
@@ -313,8 +327,8 @@ public void test11(MyValue1.ref[][][] arr, long[] res) {
}
}
- @DontCompile
- public void test11_verifier(boolean warmup) {
+ @Run(test = "test11")
+ public void test11_verifier() {
MyValue1.ref[][][] arr = new MyValue1.ref[2][3][4];
long[] res = new long[2*3*4];
long[] verif = new long[2*3*4];
@@ -353,8 +367,8 @@ public int test12() {
}
}
- @DontCompile
- public void test12_verifier(boolean warmup) {
+ @Run(test = "test12")
+ public void test12_verifier() {
Asserts.assertEQ(test12(), rI);
}
@@ -375,8 +389,8 @@ public int test13() {
}
}
- @DontCompile
- public void test13_verifier(boolean warmup) {
+ @Run(test = "test13")
+ public void test13_verifier() {
Asserts.assertEQ(test13(), rI);
}
@@ -386,8 +400,8 @@ public int test14(MyValue1.ref[] va, int index) {
return va[index].x;
}
- @DontCompile
- public void test14_verifier(boolean warmup) {
+ @Run(test = "test14")
+ public void test14_verifier() {
int arraySize = Math.abs(rI) % 10;
MyValue1.ref[] va = new MyValue1.ref[arraySize];
@@ -422,8 +436,8 @@ public int test15() {
}
}
- @DontCompile
- public void test15_verifier(boolean warmup) {
+ @Run(test = "test15")
+ public void test15_verifier() {
Asserts.assertEQ(test15(), rI);
}
@@ -443,8 +457,8 @@ public int test16() {
}
}
- @DontCompile
- public void test16_verifier(boolean warmup) {
+ @Run(test = "test16")
+ public void test16_verifier() {
Asserts.assertEQ(test16(), rI);
}
@@ -455,8 +469,8 @@ public int test17(MyValue1.ref[] va, int index, MyValue1 vt) {
return va[index].x;
}
- @DontCompile
- public void test17_verifier(boolean warmup) {
+ @Run(test = "test17")
+ public void test17_verifier() {
int arraySize = Math.abs(rI) % 10;
MyValue1.ref[] va = new MyValue1.ref[arraySize];
@@ -486,8 +500,8 @@ public MyValue1.ref[] test18(MyValue1.ref[] va) {
return va.clone();
}
- @DontCompile
- public void test18_verifier(boolean warmup) {
+ @Run(test = "test18")
+ public void test18_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
MyValue1.ref[] va1 = new MyValue1.ref[len];
MyValue1[] va2 = new MyValue1[len];
@@ -511,7 +525,7 @@ public void test18_verifier(boolean warmup) {
Asserts.assertEQ(result2[i].hash(), va2[i].hash());
}
}
- if (compile_and_run_again_if_deoptimized(warmup, "TestNullableArrays::test18")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
MyValue1.ref[] result2 = test18(va2);
for (int i = 0; i < len; ++i) {
Asserts.assertEQ(result2[i].hash(), va2[i].hash());
@@ -533,8 +547,8 @@ public MyValue1.ref[] test19() {
return va.clone();
}
- @DontCompile
- public void test19_verifier(boolean warmup) {
+ @Run(test = "test19")
+ public void test19_verifier() {
MyValue1.ref[] result = test19();
Asserts.assertEQ(result[0], null);
for (int i = 1; i < test19_orig.length; ++i) {
@@ -548,8 +562,8 @@ public void test20(MyValue1.ref[] src, MyValue1.ref[] dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test20_verifier(boolean warmup) {
+ @Run(test = "test20")
+ public void test20_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] src1 = new MyValue1.ref[len];
MyValue1.ref[] src2 = new MyValue1.ref[len];
@@ -592,8 +606,8 @@ public void test21(MyValue2.ref[] src, MyValue2.ref[] dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test21_verifier(boolean warmup) {
+ @Run(test = "test21")
+ public void test21_verifier() {
int len = Math.abs(rI) % 10;
MyValue2.ref[] src1 = new MyValue2.ref[len];
MyValue2.ref[] src2 = new MyValue2.ref[len];
@@ -639,8 +653,8 @@ public MyValue1.ref[] test22(MyValue1.ref[] src) {
return dst;
}
- @DontCompile
- public void test22_verifier(boolean warmup) {
+ @Run(test = "test22")
+ public void test22_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] src1 = new MyValue1.ref[len];
MyValue1[] src2 = new MyValue1[len];
@@ -669,8 +683,8 @@ public MyValue1.ref[] test23(MyValue1.ref[] src) {
return dst;
}
- @DontCompile
- public void test23_verifier(boolean warmup) {
+ @Run(test = "test23")
+ public void test23_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] src1 = new MyValue1.ref[len];
MyValue1[] src2 = new MyValue1[len];
@@ -696,8 +710,8 @@ public void test24(MyValue1.ref[] src, Object dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test24_verifier(boolean warmup) {
+ @Run(test = "test24")
+ public void test24_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] src1 = new MyValue1.ref[len];
MyValue1.ref[] src2 = new MyValue1.ref[len];
@@ -740,8 +754,8 @@ public void test25(MyValue2.ref[] src, MyValue2.ref[] dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test25_verifier(boolean warmup) {
+ @Run(test = "test25")
+ public void test25_verifier() {
MyValue2.ref[] src1 = new MyValue2.ref[8];
MyValue2.ref[] src2 = new MyValue2.ref[8];
MyValue2[] src3 = new MyValue2[8];
@@ -779,8 +793,8 @@ public void test26(MyValue1.ref[] src, MyValue1.ref[] dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test26_verifier(boolean warmup) {
+ @Run(test = "test26")
+ public void test26_verifier() {
MyValue1.ref[] src1 = new MyValue1.ref[8];
MyValue1.ref[] src2 = new MyValue1.ref[8];
MyValue1[] src3 = new MyValue1[8];
@@ -818,8 +832,8 @@ public void test27(MyValue1.ref[] src, MyValue1.ref[] dst) {
System.arraycopy(src, 1, dst, 2, 6);
}
- @DontCompile
- public void test27_verifier(boolean warmup) {
+ @Run(test = "test27")
+ public void test27_verifier() {
MyValue1.ref[] src1 = new MyValue1.ref[8];
MyValue1.ref[] src2 = new MyValue1.ref[8];
MyValue1[] src3 = new MyValue1[8];
@@ -854,8 +868,9 @@ public void test27_verifier(boolean warmup) {
// non escaping allocations
// TODO 8252027: Make sure this is optimized with ZGC
- @Test(valid = ZGCOff, failOn = ALLOC + ALLOCA + LOOP + LOAD + STORE + TRAP)
- @Test(valid = ZGCOn)
+ @Test
+ @IR(applyIf = {"UseZGC", "false"},
+ failOn = {ALLOC, ALLOCA, LOOP, LOAD, STORE, TRAP})
public MyValue2.ref test28() {
MyValue2.ref[] src = new MyValue2.ref[10];
src[0] = null;
@@ -863,8 +878,8 @@ public MyValue2.ref test28() {
return dst[0];
}
- @DontCompile
- public void test28_verifier(boolean warmup) {
+ @Run(test = "test28")
+ public void test28_verifier() {
MyValue2 v = MyValue2.createWithFieldsInline(rI, rD);
MyValue2.ref result = test28();
Asserts.assertEQ(result, null);
@@ -872,15 +887,16 @@ public void test28_verifier(boolean warmup) {
// non escaping allocations
// TODO 8227588: shouldn't this have the same IR matching rules as test6?
- @Test(failOn = ALLOCA + LOOP + TRAP)
+ @Test
+ @IR(failOn = {ALLOCA, LOOP, TRAP})
public MyValue2.ref test29(MyValue2.ref[] src) {
MyValue2.ref[] dst = new MyValue2.ref[10];
System.arraycopy(src, 0, dst, 0, 10);
return dst[0];
}
- @DontCompile
- public void test29_verifier(boolean warmup) {
+ @Run(test = "test29")
+ public void test29_verifier(RunInfo info) {
MyValue2.ref[] src1 = new MyValue2.ref[10];
MyValue2.val[] src2 = new MyValue2.val[10];
for (int i = 0; i < 10; ++i) {
@@ -889,7 +905,7 @@ public void test29_verifier(boolean warmup) {
}
MyValue2.ref v = test29(src1);
Asserts.assertEQ(src1[0].hash(), v.hash());
- if (!warmup) {
+ if (!info.isWarmUp()) {
v = test29(src2);
Asserts.assertEQ(src2[0].hash(), v.hash());
}
@@ -898,7 +914,6 @@ public void test29_verifier(boolean warmup) {
// non escaping allocation with uncommon trap that needs
// eliminated inline type array element as debug info
@Test
- @Warmup(10000)
public MyValue2.ref test30(MyValue2.ref[] src, boolean flag) {
MyValue2.ref[] dst = new MyValue2.ref[10];
System.arraycopy(src, 0, dst, 0, 10);
@@ -906,17 +921,18 @@ public MyValue2.ref test30(MyValue2.ref[] src, boolean flag) {
return dst[0];
}
- @DontCompile
- public void test30_verifier(boolean warmup) {
+ @Run(test = "test30")
+ @Warmup(10000)
+ public void test30_verifier(RunInfo info) {
MyValue2.ref[] src1 = new MyValue2.ref[10];
MyValue2.val[] src2 = new MyValue2.val[10];
for (int i = 0; i < 10; ++i) {
src1[i] = MyValue2.createWithFieldsInline(rI+i, rD+i);
src2[i] = MyValue2.createWithFieldsInline(rI+i, rD+i);
}
- MyValue2.ref v = test30(src1, !warmup);
+ MyValue2.ref v = test30(src1, !info.isWarmUp());
Asserts.assertEQ(src1[0].hash(), v.hash());
- if (!warmup) {
+ if (!info.isWarmUp()) {
v = test30(src2, true);
Asserts.assertEQ(src2[0].hash(), v.hash());
}
@@ -926,7 +942,7 @@ public void test30_verifier(boolean warmup) {
@Test()
// TODO 8227588
// @Test(failOn = ALLOC + ALLOCA + LOOP + LOAD + STORE + TRAP)
- public long test31(boolean b, boolean deopt) {
+ public long test31(boolean b, boolean deopt, Method m) {
MyValue2.ref[] src = new MyValue2.ref[1];
if (b) {
src[0] = MyValue2.createWithFieldsInline(rI, rD);
@@ -935,18 +951,18 @@ public long test31(boolean b, boolean deopt) {
}
if (deopt) {
// uncommon trap
- WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test31"));
+ TestFramework.deoptimize(m);
}
return src[0].hash();
}
- @DontCompile
- public void test31_verifier(boolean warmup) {
+ @Run(test = "test31")
+ public void test31_verifier(RunInfo info) {
MyValue2 v1 = MyValue2.createWithFieldsInline(rI, rD);
- long result1 = test31(true, !warmup);
+ long result1 = test31(true, !info.isWarmUp(), info.getTest());
Asserts.assertEQ(result1, v1.hash());
MyValue2 v2 = MyValue2.createWithFieldsInline(rI+1, rD+1);
- long result2 = test31(false, !warmup);
+ long result2 = test31(false, !info.isWarmUp(), info.getTest());
Asserts.assertEQ(result2, v2.hash());
}
@@ -957,8 +973,8 @@ public Object[] test32(Object[] va) {
return va.clone();
}
- @DontCompile
- public void test32_verifier(boolean warmup) {
+ @Run(test = "test32")
+ public void test32_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] va1 = new MyValue1.ref[len];
MyValue1[] va2 = new MyValue1[len];
@@ -983,8 +999,8 @@ public Object[] test33(Object[] va) {
return va.clone();
}
- @DontCompile
- public void test33_verifier(boolean warmup) {
+ @Run(test = "test33")
+ public void test33_verifier() {
int len = Math.abs(rI) % 10;
Object[] va = new Object[len];
for (int i = 0; i < len; ++i) {
@@ -1020,14 +1036,14 @@ public Object[] test34(boolean flag) {
return va.clone();
}
- @DontCompile
- public void test34_verifier(boolean warmup) {
+ @Run(test = "test34")
+ public void test34_verifier(RunInfo info) {
test34(false);
for (int i = 0; i < 10; i++) { // make sure we do deopt
Object[] result = test34(true);
verify(test34_orig, result);
}
- if (compile_and_run_again_if_deoptimized(warmup, "TestNullableArrays::test34")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
Object[] result = test34(true);
verify(test34_orig, result);
}
@@ -1083,15 +1099,11 @@ static void verify(MyValue2.ref[] src, Object[] dst) {
}
}
- static boolean compile_and_run_again_if_deoptimized(boolean warmup, String test) {
- if (!warmup) {
- Method m = tests.get(test);
- if (USE_COMPILER && !WHITE_BOX.isMethodCompiled(m, false)) {
- if (!InlineTypeArrayFlatten && !XCOMP && !STRESS_CC) {
- throw new RuntimeException("Unexpected deoptimization");
- }
- enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION);
- return true;
+ static boolean compile_and_run_again_if_deoptimized(RunInfo info) {
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ if (TestFramework.isCompiled(m)) {
+ TestFramework.compile(m, CompLevel.C2);
}
}
return false;
@@ -1103,8 +1115,8 @@ public void test35(Object src, Object dst, int len) {
System.arraycopy(src, 0, dst, 0, len);
}
- @DontCompile
- public void test35_verifier(boolean warmup) {
+ @Run(test = "test35")
+ public void test35_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
MyValue1.ref[] src = new MyValue1.ref[len];
MyValue1.ref[] dst = new MyValue1.ref[len];
@@ -1113,7 +1125,7 @@ public void test35_verifier(boolean warmup) {
}
test35(src, dst, src.length);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestNullableArrays::test35")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test35(src, dst, src.length);
verify(src, dst);
}
@@ -1124,8 +1136,8 @@ public void test36(Object src, MyValue2.ref[] dst) {
System.arraycopy(src, 0, dst, 0, dst.length);
}
- @DontCompile
- public void test36_verifier(boolean warmup) {
+ @Run(test = "test36")
+ public void test36_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
MyValue2.ref[] src = new MyValue2.ref[len];
MyValue2.ref[] dst = new MyValue2.ref[len];
@@ -1134,7 +1146,7 @@ public void test36_verifier(boolean warmup) {
}
test36(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestNullableArrays::test36")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test36(src, dst);
verify(src, dst);
}
@@ -1145,8 +1157,8 @@ public void test37(MyValue2.ref[] src, Object dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test37_verifier(boolean warmup) {
+ @Run(test = "test37")
+ public void test37_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
MyValue2.ref[] src = new MyValue2.ref[len];
MyValue2.ref[] dst = new MyValue2.ref[len];
@@ -1155,20 +1167,20 @@ public void test37_verifier(boolean warmup) {
}
test37(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestNullableArrays::test37")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test37(src, dst);
verify(src, dst);
}
}
@Test
- @Warmup(1) // Avoid early compilation
public void test38(Object src, MyValue2.ref[] dst) {
System.arraycopy(src, 0, dst, 0, dst.length);
}
- @DontCompile
- public void test38_verifier(boolean warmup) {
+ @Run(test = "test38")
+ @Warmup(1) // Avoid early compilation
+ public void test38_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
Object[] src = new Object[len];
MyValue2.ref[] dst = new MyValue2.ref[len];
@@ -1177,15 +1189,13 @@ public void test38_verifier(boolean warmup) {
}
test38(src, dst);
verify(dst, src);
- if (!warmup) {
- Method m = tests.get("TestNullableArrays::test38");
- assertDeoptimizedByC2(m);
- enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION);
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertDeoptimizedByC2(m);
+ TestFramework.compile(m, CompLevel.C2);
test38(src, dst);
verify(dst, src);
- if (USE_COMPILER && !WHITE_BOX.isMethodCompiled(m, false) && !XCOMP && !STRESS_CC) {
- throw new RuntimeException("unexpected deoptimization");
- }
+ TestFramework.assertCompiled(m);
}
}
@@ -1194,8 +1204,8 @@ public void test39(MyValue2.ref[] src, Object dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test39_verifier(boolean warmup) {
+ @Run(test = "test39")
+ public void test39_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
MyValue2.ref[] src = new MyValue2.ref[len];
Object[] dst = new Object[len];
@@ -1204,20 +1214,20 @@ public void test39_verifier(boolean warmup) {
}
test39(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestNullableArrays::test39")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test39(src, dst);
verify(src, dst);
}
}
@Test
- @Warmup(1) // Avoid early compilation
public void test40(Object[] src, Object dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test40_verifier(boolean warmup) {
+ @Run(test = "test40")
+ @Warmup(1) // Avoid early compilation
+ public void test40_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
Object[] src = new Object[len];
MyValue2.ref[] dst = new MyValue2.ref[len];
@@ -1226,15 +1236,13 @@ public void test40_verifier(boolean warmup) {
}
test40(src, dst);
verify(dst, src);
- if (!warmup) {
- Method m = tests.get("TestNullableArrays::test40");
- assertDeoptimizedByC2(m);
- enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION);
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertDeoptimizedByC2(m);
+ TestFramework.compile(m, CompLevel.C2);
test40(src, dst);
verify(dst, src);
- if (USE_COMPILER && !WHITE_BOX.isMethodCompiled(m, false) && !XCOMP && !STRESS_CC) {
- throw new RuntimeException("unexpected deoptimization");
- }
+ TestFramework.assertCompiled(m);
}
}
@@ -1243,8 +1251,8 @@ public void test41(Object src, Object[] dst) {
System.arraycopy(src, 0, dst, 0, dst.length);
}
- @DontCompile
- public void test41_verifier(boolean warmup) {
+ @Run(test = "test41")
+ public void test41_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
MyValue2.ref[] src = new MyValue2.ref[len];
Object[] dst = new Object[len];
@@ -1253,7 +1261,7 @@ public void test41_verifier(boolean warmup) {
}
test41(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestNullableArrays::test41")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test41(src, dst);
verify(src, dst);
}
@@ -1264,8 +1272,8 @@ public void test42(Object[] src, Object[] dst) {
System.arraycopy(src, 0, dst, 0, src.length);
}
- @DontCompile
- public void test42_verifier(boolean warmup) {
+ @Run(test = "test42")
+ public void test42_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
Object[] src = new Object[len];
Object[] dst = new Object[len];
@@ -1274,11 +1282,9 @@ public void test42_verifier(boolean warmup) {
}
test42(src, dst);
verify(src, dst);
- if (!warmup) {
- Method m = tests.get("TestNullableArrays::test42");
- if (USE_COMPILER && !WHITE_BOX.isMethodCompiled(m, false) && !XCOMP && !STRESS_CC) {
- throw new RuntimeException("unexpected deoptimization");
- }
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiled(m);
}
}
@@ -1288,8 +1294,8 @@ public void test43(Object src, Object dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test43_verifier(boolean warmup) {
+ @Run(test = "test43")
+ public void test43_verifier(RunInfo info) {
MyValue1.ref[] src = new MyValue1.ref[8];
MyValue1.ref[] dst = new MyValue1.ref[8];
for (int i = 1; i < 8; ++i) {
@@ -1297,7 +1303,7 @@ public void test43_verifier(boolean warmup) {
}
test43(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestNullableArrays::test43")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test43(src, dst);
verify(src, dst);
}
@@ -1308,8 +1314,8 @@ public void test44(Object src, MyValue2.ref[] dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test44_verifier(boolean warmup) {
+ @Run(test = "test44")
+ public void test44_verifier(RunInfo info) {
MyValue2.ref[] src = new MyValue2.ref[8];
MyValue2.ref[] dst = new MyValue2.ref[8];
for (int i = 1; i < 8; ++i) {
@@ -1317,7 +1323,7 @@ public void test44_verifier(boolean warmup) {
}
test44(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestNullableArrays::test44")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test44(src, dst);
verify(src, dst);
}
@@ -1328,8 +1334,8 @@ public void test45(MyValue2.ref[] src, Object dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test45_verifier(boolean warmup) {
+ @Run(test = "test45")
+ public void test45_verifier(RunInfo info) {
MyValue2.ref[] src = new MyValue2.ref[8];
MyValue2.ref[] dst = new MyValue2.ref[8];
for (int i = 1; i < 8; ++i) {
@@ -1337,20 +1343,20 @@ public void test45_verifier(boolean warmup) {
}
test45(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestNullableArrays::test45")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test45(src, dst);
verify(src, dst);
}
}
@Test
- @Warmup(1) // Avoid early compilation
public void test46(Object[] src, MyValue2.ref[] dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test46_verifier(boolean warmup) {
+ @Run(test = "test46")
+ @Warmup(1) // Avoid early compilation
+ public void test46_verifier(RunInfo info) {
Object[] src = new Object[8];
MyValue2.ref[] dst = new MyValue2.ref[8];
for (int i = 1; i < 8; ++i) {
@@ -1358,15 +1364,13 @@ public void test46_verifier(boolean warmup) {
}
test46(src, dst);
verify(dst, src);
- if (!warmup) {
- Method m = tests.get("TestNullableArrays::test46");
- assertDeoptimizedByC2(m);
- enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION);
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertDeoptimizedByC2(m);
+ TestFramework.compile(m, CompLevel.C2);
test46(src, dst);
verify(dst, src);
- if (USE_COMPILER && !WHITE_BOX.isMethodCompiled(m, false) && !XCOMP && !STRESS_CC) {
- throw new RuntimeException("unexpected deoptimization");
- }
+ TestFramework.assertCompiled(m);
}
}
@@ -1375,8 +1379,8 @@ public void test47(MyValue2.ref[] src, Object[] dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test47_verifier(boolean warmup) {
+ @Run(test = "test47")
+ public void test47_verifier(RunInfo info) {
MyValue2.ref[] src = new MyValue2.ref[8];
Object[] dst = new Object[8];
for (int i = 1; i < 8; ++i) {
@@ -1384,20 +1388,20 @@ public void test47_verifier(boolean warmup) {
}
test47(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestNullableArrays::test47")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test47(src, dst);
verify(src, dst);
}
}
@Test
- @Warmup(1) // Avoid early compilation
public void test48(Object[] src, Object dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test48_verifier(boolean warmup) {
+ @Run(test = "test48")
+ @Warmup(1) // Avoid early compilation
+ public void test48_verifier(RunInfo info) {
Object[] src = new Object[8];
MyValue2.ref[] dst = new MyValue2.ref[8];
for (int i = 1; i < 8; ++i) {
@@ -1405,15 +1409,13 @@ public void test48_verifier(boolean warmup) {
}
test48(src, dst);
verify(dst, src);
- if (!warmup) {
- Method m = tests.get("TestNullableArrays::test48");
- assertDeoptimizedByC2(m);
- enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION);
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertDeoptimizedByC2(m);
+ TestFramework.compile(m, CompLevel.C2);
test48(src, dst);
verify(dst, src);
- if (USE_COMPILER && !WHITE_BOX.isMethodCompiled(m, false) && !XCOMP && !STRESS_CC) {
- throw new RuntimeException("unexpected deoptimization");
- }
+ TestFramework.assertCompiled(m);
}
}
@@ -1422,8 +1424,8 @@ public void test49(Object src, Object[] dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test49_verifier(boolean warmup) {
+ @Run(test = "test49")
+ public void test49_verifier(RunInfo info) {
MyValue2.ref[] src = new MyValue2.ref[8];
Object[] dst = new Object[8];
for (int i = 1; i < 8; ++i) {
@@ -1431,7 +1433,7 @@ public void test49_verifier(boolean warmup) {
}
test49(src, dst);
verify(src, dst);
- if (compile_and_run_again_if_deoptimized(warmup, "TestNullableArrays::test49")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
test49(src, dst);
verify(src, dst);
}
@@ -1442,8 +1444,8 @@ public void test50(Object[] src, Object[] dst) {
System.arraycopy(src, 0, dst, 0, 8);
}
- @DontCompile
- public void test50_verifier(boolean warmup) {
+ @Run(test = "test50")
+ public void test50_verifier(RunInfo info) {
Object[] src = new Object[8];
Object[] dst = new Object[8];
for (int i = 1; i < 8; ++i) {
@@ -1451,11 +1453,9 @@ public void test50_verifier(boolean warmup) {
}
test50(src, dst);
verify(src, dst);
- if (!warmup) {
- Method m = tests.get("TestNullableArrays::test50");
- if (USE_COMPILER && !WHITE_BOX.isMethodCompiled(m, false) && !XCOMP && !STRESS_CC) {
- throw new RuntimeException("unexpected deoptimization");
- }
+ if (!info.isWarmUp()) {
+ Method m = info.getTest();
+ TestFramework.assertCompiled(m);
}
}
@@ -1464,8 +1464,8 @@ public MyValue1.ref[] test51(MyValue1.ref[] va) {
return Arrays.copyOf(va, va.length, MyValue1.ref[].class);
}
- @DontCompile
- public void test51_verifier(boolean warmup) {
+ @Run(test = "test51")
+ public void test51_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] va = new MyValue1.ref[len];
for (int i = 1; i < len; ++i) {
@@ -1482,8 +1482,8 @@ public MyValue1.ref[] test52() {
return Arrays.copyOf(test52_va, 8, MyValue1.ref[].class);
}
- @DontCompile
- public void test52_verifier(boolean warmup) {
+ @Run(test = "test52")
+ public void test52_verifier() {
for (int i = 1; i < 8; ++i) {
test52_va[i] = testValue1;
}
@@ -1496,8 +1496,8 @@ public MyValue1.ref[] test53(Object[] va) {
return Arrays.copyOf(va, va.length, MyValue1.ref[].class);
}
- @DontCompile
- public void test53_verifier(boolean warmup) {
+ @Run(test = "test53")
+ public void test53_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] va = new MyValue1.ref[len];
for (int i = 1; i < len; ++i) {
@@ -1512,8 +1512,8 @@ public Object[] test54(MyValue1.ref[] va) {
return Arrays.copyOf(va, va.length, Object[].class);
}
- @DontCompile
- public void test54_verifier(boolean warmup) {
+ @Run(test = "test54")
+ public void test54_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] va = new MyValue1.ref[len];
for (int i = 1; i < len; ++i) {
@@ -1528,8 +1528,8 @@ public Object[] test55(Object[] va) {
return Arrays.copyOf(va, va.length, Object[].class);
}
- @DontCompile
- public void test55_verifier(boolean warmup) {
+ @Run(test = "test55")
+ public void test55_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] va = new MyValue1.ref[len];
for (int i = 1; i < len; ++i) {
@@ -1544,8 +1544,8 @@ public MyValue1.ref[] test56(Object[] va) {
return Arrays.copyOf(va, va.length, MyValue1.ref[].class);
}
- @DontCompile
- public void test56_verifier(boolean warmup) {
+ @Run(test = "test56")
+ public void test56_verifier() {
int len = Math.abs(rI) % 10;
Object[] va = new Object[len];
for (int i = 1; i < len; ++i) {
@@ -1560,8 +1560,8 @@ public Object[] test57(Object[] va, Class klass) {
return Arrays.copyOf(va, va.length, klass);
}
- @DontCompile
- public void test57_verifier(boolean warmup) {
+ @Run(test = "test57")
+ public void test57_verifier() {
int len = Math.abs(rI) % 10;
Object[] va = new MyValue1.ref[len];
for (int i = 1; i < len; ++i) {
@@ -1576,8 +1576,8 @@ public Object[] test58(MyValue1.ref[] va, Class klass) {
return Arrays.copyOf(va, va.length, klass);
}
- @DontCompile
- public void test58_verifier(boolean warmup) {
+ @Run(test = "test58")
+ public void test58_verifier(RunInfo info) {
int len = Math.abs(rI) % 10;
MyValue1.ref[] va = new MyValue1.ref[len];
for (int i = 1; i < len; ++i) {
@@ -1587,7 +1587,7 @@ public void test58_verifier(boolean warmup) {
Object[] result = test58(va, MyValue1.ref[].class);
verify(va, result);
}
- if (compile_and_run_again_if_deoptimized(warmup, "TestNullableArrays::test58")) {
+ if (compile_and_run_again_if_deoptimized(info)) {
Object[] result = test58(va, MyValue1.ref[].class);
verify(va, result);
}
@@ -1598,8 +1598,8 @@ public Object[] test59(MyValue1.ref[] va) {
return Arrays.copyOf(va, va.length+1, MyValue1.ref[].class);
}
- @DontCompile
- public void test59_verifier(boolean warmup) {
+ @Run(test = "test59")
+ public void test59_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] va = new MyValue1.ref[len];
MyValue1.ref[] verif = new MyValue1.ref[len+1];
@@ -1616,8 +1616,8 @@ public Object[] test60(Object[] va, Class klass) {
return Arrays.copyOf(va, va.length+1, klass);
}
- @DontCompile
- public void test60_verifier(boolean warmup) {
+ @Run(test = "test60")
+ public void test60_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] va = new MyValue1.ref[len];
MyValue1.ref[] verif = new MyValue1.ref[len+1];
@@ -1634,8 +1634,8 @@ public Object[] test61(Object[] va, Class klass) {
return Arrays.copyOf(va, va.length+1, klass);
}
- @DontCompile
- public void test61_verifier(boolean warmup) {
+ @Run(test = "test61")
+ public void test61_verifier() {
int len = Math.abs(rI) % 10;
Object[] va = new Integer[len];
for (int i = 1; i < len; ++i) {
@@ -1668,8 +1668,8 @@ public Object[] test62(MyValue1.ref[] va, Integer[] oa) {
return Arrays.copyOf(arr, arr.length+1, arr.getClass());
}
- @DontCompile
- public void test62_verifier(boolean warmup) {
+ @Run(test = "test62")
+ public void test62_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] va = new MyValue1.ref[len];
Integer[] oa = new Integer[len];
@@ -1704,8 +1704,8 @@ public Object[] test63(MyValue1.ref[] va, Integer[] oa) {
return Arrays.copyOf(arr, arr.length+1, arr.getClass());
}
- @DontCompile
- public void test63_verifier(boolean warmup) {
+ @Run(test = "test63")
+ public void test63_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] va = new MyValue1.ref[len];
MyValue1.ref[] verif = new MyValue1.ref[len+1];
@@ -1725,8 +1725,8 @@ public MyValue1.ref[] test64() {
return new MyValue1.ref[8];
}
- @DontCompile
- public void test64_verifier(boolean warmup) {
+ @Run(test = "test64")
+ public void test64_verifier() {
MyValue1.ref[] va = test64();
for (int i = 0; i < 8; ++i) {
Asserts.assertEQ(va[i], null);
@@ -1739,8 +1739,8 @@ public MyValue1.ref[] test65() {
return new MyValue1.ref[32];
}
- @DontCompile
- public void test65_verifier(boolean warmup) {
+ @Run(test = "test65")
+ public void test65_verifier() {
MyValue1.ref[] va = test65();
for (int i = 0; i < 32; ++i) {
Asserts.assertEQ(va[i], null);
@@ -1748,15 +1748,16 @@ public void test65_verifier(boolean warmup) {
}
// Check init store elimination
- @Test(match = { ALLOCA }, matchCount = { 1 })
+ @Test
+ @IR(counts = {ALLOCA, "= 1"})
public MyValue1.ref[] test66(MyValue1.ref vt) {
MyValue1.ref[] va = new MyValue1.ref[1];
va[0] = vt;
return va;
}
- @DontCompile
- public void test66_verifier(boolean warmup) {
+ @Run(test = "test66")
+ public void test66_verifier() {
MyValue1.ref vt = MyValue1.createWithFieldsDontInline(rI, rL);
MyValue1.ref[] va = test66(vt);
Asserts.assertEQ(va[0].hashPrimitive(), vt.hashPrimitive());
@@ -1770,8 +1771,8 @@ public MyValue1.ref[] test67(MyValue1.ref[] src) {
return dst;
}
- @DontCompile
- public void test67_verifier(boolean warmup) {
+ @Run(test = "test67")
+ public void test67_verifier() {
MyValue1.ref[] va = new MyValue1.ref[16];
MyValue1.ref[] var = test67(va);
for (int i = 0; i < 16; ++i) {
@@ -1787,8 +1788,8 @@ public MyValue1.ref[] test68() {
return va;
}
- @DontCompile
- public void test68_verifier(boolean warmup) {
+ @Run(test = "test68")
+ public void test68_verifier() {
MyValue1.ref[] va = test68();
for (int i = 0; i < 2; ++i) {
Asserts.assertEQ(va[i], null);
@@ -1804,8 +1805,8 @@ public MyValue1.ref[] test69(MyValue1.ref vt) {
return va;
}
- @DontCompile
- public void test69_verifier(boolean warmup) {
+ @Run(test = "test69")
+ public void test69_verifier() {
MyValue1.ref vt = MyValue1.createWithFieldsDontInline(rI, rL);
MyValue1.ref[] va = new MyValue1.ref[4];
va[0] = vt;
@@ -1827,8 +1828,8 @@ public MyValue1.ref[] test70(MyValue1.ref[] other) {
return va;
}
- @DontCompile
- public void test70_verifier(boolean warmup) {
+ @Run(test = "test70")
+ public void test70_verifier() {
MyValue1.ref[] va = new MyValue1.ref[2];
MyValue1.ref[] var = test70(va);
for (int i = 0; i < 2; ++i) {
@@ -1855,8 +1856,8 @@ public void test71() {
}
}
- @DontCompile
- public void test71_verifier(boolean warmup) {
+ @Run(test = "test71")
+ public void test71_verifier() {
test71();
}
@@ -1872,8 +1873,8 @@ public void test72(Object[] o, boolean b, Object element) {
arr2[0] = element;
}
- @DontCompile
- public void test72_verifier(boolean warmup) {
+ @Run(test = "test72")
+ public void test72_verifier() {
Object[] arr = new Object[1];
Object elem = new Object();
test72(arr, true, elem);
@@ -1891,8 +1892,8 @@ public void test73(Object[] oa, MyValue1.ref v, Object o) {
oa[0] = oa; // The stored value is known to be not flattenable (an Object[])
}
- @DontCompile
- public void test73_verifier(boolean warmup) {
+ @Run(test = "test73")
+ public void test73_verifier() {
MyValue1.ref v0 = MyValue1.createWithFieldsDontInline(rI, rL);
MyValue1.ref v1 = MyValue1.createWithFieldsDontInline(rI+1, rL+1);
MyValue1.ref[] arr = new MyValue1.ref[3];
@@ -1928,8 +1929,8 @@ public Object[] test74(MyValue1.ref[] va, Integer[] oa) {
return arr.clone();
}
- @DontCompile
- public void test74_verifier(boolean warmup) {
+ @Run(test = "test74")
+ public void test74_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] va = new MyValue1.ref[len];
Integer[] oa = new Integer[len];
@@ -1966,8 +1967,8 @@ public Object[] test75(MyValue1.ref[] va, Integer[] oa) {
return arr.clone();
}
- @DontCompile
- public void test75_verifier(boolean warmup) {
+ @Run(test = "test75")
+ public void test75_verifier() {
int len = Math.abs(rI) % 10;
MyValue1.ref[] va = new MyValue1.ref[len];
MyValue1.ref[] verif = new MyValue1.ref[len];
@@ -2003,8 +2004,8 @@ public Object[] test76(MyValue1[] vva, MyValue1.ref[] vba, MyValue1 vt, Object[]
return result;
}
- @DontCompile
- public void test76_verifier(boolean warmup) {
+ @Run(test = "test76")
+ public void test76_verifier() {
MyValue1 vt = testValue1;
Object[] out = new Object[1];
MyValue1[] vva = new MyValue1[42];
@@ -2050,8 +2051,8 @@ public Object[] test77(boolean b) {
return va;
}
- @DontCompile
- public void test77_verifier(boolean warmup) {
+ @Run(test = "test77")
+ public void test77_verifier() {
Object[] va = test77(true);
Asserts.assertEQ(va.length, 5);
Asserts.assertEQ(((MyValue1)va[0]).hash(), hash(rI, hash()));
@@ -2086,8 +2087,8 @@ public Object[] test78(MyValue1[] vva, MyValue1.ref[] vba, Object val, Object[]
return result;
}
- @DontCompile
- public void test78_verifier(boolean warmup) {
+ @Run(test = "test78")
+ public void test78_verifier() {
MyValue1 vt = testValue1;
Integer i = Integer.valueOf(42);
Object[] out = new Object[1];
@@ -2115,13 +2116,14 @@ public void test78_verifier(boolean warmup) {
}
// Test widening conversions from [Q to [L
- @Test(failOn = ALLOC + ALLOCA + LOOP + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOOP, LOAD, STORE, TRAP})
public static MyValue1.ref[] test79(MyValue1[] va) {
return va;
}
- @DontCompile
- public void test79_verifier(boolean warmup) {
+ @Run(test = "test79")
+ public void test79_verifier() {
MyValue1[] va = new MyValue1[1];
va[0] = testValue1;
MyValue1.ref[] res = test79(va);
@@ -2137,13 +2139,14 @@ public void test79_verifier(boolean warmup) {
}
// Same as test79 but with explicit cast and Object return
- @Test(failOn = ALLOC + ALLOCA + LOOP + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOOP, LOAD, STORE, TRAP})
public static Object[] test80(MyValue1[] va) {
return (MyValue1.ref[])va;
}
- @DontCompile
- public void test80_verifier(boolean warmup) {
+ @Run(test = "test80")
+ public void test80_verifier() {
MyValue1[] va = new MyValue1[1];
va[0] = testValue1;
Object[] res = test80(va);
@@ -2170,8 +2173,8 @@ public static long test81(MyValue1[] va1, MyValue1.ref[] va2, MyValue1 vt, boole
return result[1].hash();
}
- @DontCompile
- public void test81_verifier(boolean warmup) {
+ @Run(test = "test81")
+ public void test81_verifier() {
MyValue1[] va = new MyValue1[2];
MyValue1.ref[] vaB = new MyValue1.ref[2];
va[1] = testValue1;
@@ -2214,8 +2217,8 @@ public static long test82(MyValue1[] va1, MyValue1.ref[] va2, MyValue1 vt1, MyVa
return result[1].hash();
}
- @DontCompile
- public void test82_verifier(boolean warmup) {
+ @Run(test = "test82")
+ public void test82_verifier() {
MyValue1[] va = new MyValue1[2];
MyValue1.ref[] vaB = new MyValue1.ref[2];
va[1] = testValue1;
@@ -2237,22 +2240,24 @@ public void test82_verifier(boolean warmup) {
Asserts.assertEquals(res, testValue1.hash());
}
- @Test(failOn = ALLOC + ALLOCA + STORE)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, STORE})
public static long test83(MyValue1[] va) {
MyValue1.ref[] result = va;
return result[0].hash();
}
- @DontCompile
- public void test83_verifier(boolean warmup) {
+ @Run(test = "test83")
+ public void test83_verifier() {
MyValue1[] va = new MyValue1[42];
va[0] = testValue1;
long res = test83(va);
Asserts.assertEquals(res, testValue1.hash());
}
- @Test(valid = InlineTypeArrayFlattenOn, failOn = ALLOC + LOOP + STORE + TRAP)
- @Test(valid = InlineTypeArrayFlattenOff)
+ @Test
+ @IR(applyIf = {"FlatArrayElementMaxSize", "= -1"},
+ failOn = {ALLOC, LOOP, STORE, TRAP})
public static MyValue1.ref[] test84(MyValue1 vt1, MyValue1.ref vt2) {
MyValue1.ref[] result = new MyValue1[2];
result[0] = vt1;
@@ -2260,8 +2265,8 @@ public static MyValue1.ref[] test84(MyValue1 vt1, MyValue1.ref vt2) {
return result;
}
- @DontCompile
- public void test84_verifier(boolean warmup) {
+ @Run(test = "test84")
+ public void test84_verifier() {
MyValue1.ref[] res = test84(testValue1, testValue1);
Asserts.assertEquals(res[0].hash(), testValue1.hash());
Asserts.assertEquals(res[1].hash(), testValue1.hash());
@@ -2279,8 +2284,8 @@ public static long test85(MyValue1.ref[] va, MyValue1 val) {
return va[1].hash();
}
- @DontCompile
- public void test85_verifier(boolean warmup) {
+ @Run(test = "test85")
+ public void test85_verifier() {
MyValue1[] va = new MyValue1[2];
MyValue1.ref[] vab = new MyValue1.ref[2];
va[1] = testValue1;
@@ -2300,8 +2305,8 @@ public static long test86(MyValue1.ref[] va, MyValue1.ref val) {
return va[1].hash();
}
- @DontCompile
- public void test86_verifier(boolean warmup) {
+ @Run(test = "test86")
+ public void test86_verifier() {
MyValue1[] va = new MyValue1[2];
MyValue1.ref[] vab = new MyValue1.ref[2];
va[1] = testValue1;
@@ -2331,20 +2336,21 @@ public long test87() {
return va[0].hash();
}
- @DontCompile
- public void test87_verifier(boolean warmup) {
+ @Run(test = "test87")
+ public void test87_verifier() {
long result = test87();
Asserts.assertEQ(result, hash());
}
// Test narrowing conversion from [L to [Q
- @Test(failOn = ALLOC + ALLOCA + LOOP + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOOP, LOAD, STORE, TRAP})
public static MyValue1[] test88(MyValue1.ref[] va) {
return (MyValue1[])va;
}
- @DontCompile
- public void test88_verifier(boolean warmup) {
+ @Run(test = "test88")
+ public void test88_verifier() {
MyValue1[] va = new MyValue1[1];
va[0] = testValue1;
MyValue1[] res = test88(va);
@@ -2360,13 +2366,14 @@ public void test88_verifier(boolean warmup) {
}
// Same as test88 but with explicit cast and Object argument
- @Test(failOn = ALLOC + ALLOCA + LOOP + LOAD + STORE + TRAP)
+ @Test
+ @IR(failOn = {ALLOC, ALLOCA, LOOP, LOAD, STORE, TRAP})
public static MyValue1[] test89(Object[] va) {
return (MyValue1[])va;
}
- @DontCompile
- public void test89_verifier(boolean warmup) {
+ @Run(test = "test89")
+ public void test89_verifier() {
MyValue1[] va = new MyValue1[1];
va[0] = testValue1;
MyValue1[] res = test89(va);
@@ -2387,8 +2394,8 @@ public static MyValue1.ref[] test90(Object va) {
return (MyValue1.ref[])va;
}
- @DontCompile
- public void test90_verifier(boolean warmup) {
+ @Run(test = "test90")
+ public void test90_verifier() {
MyValue1[] va = new MyValue1[1];
MyValue1.ref[] vab = new MyValue1.ref[1];
try {
@@ -2407,8 +2414,8 @@ public static MyValue1.ref[] test91(Object[] va) {
return (MyValue1.ref[])va;
}
- @DontCompile
- public void test91_verifier(boolean warmup) {
+ @Run(test = "test91")
+ public void test91_verifier() {
MyValue1[] va = new MyValue1[1];
MyValue1.ref[] vab = new MyValue1.ref[1];
try {
@@ -2428,8 +2435,8 @@ public static void test92(MyValue1.ref[] src, MyValue1.ref[] dst) {
System.arraycopy(src, 0, dst, 0, 2);
}
- @DontCompile
- public void test92_verifier(boolean warmup) {
+ @Run(test = "test92")
+ public void test92_verifier() {
MyValue1[] va = new MyValue1[2];
MyValue1.ref[] vab = new MyValue1.ref[2];
va[0] = testValue1;
@@ -2444,8 +2451,8 @@ public static void test93(Object src, MyValue1.ref[] dst) {
System.arraycopy(src, 0, dst, 0, 2);
}
- @DontCompile
- public void test93_verifier(boolean warmup) {
+ @Run(test = "test93")
+ public void test93_verifier() {
MyValue1[] va = new MyValue1[2];
MyValue1.ref[] vab = new MyValue1.ref[2];
va[0] = testValue1;
@@ -2468,8 +2475,8 @@ public static long test94() {
return dst[0].hash();
}
- @DontCompile
- public static void test94_verifier(boolean warmup) {
+ @Run(test = "test94")
+ public static void test94_verifier() {
long result = test94();
Asserts.assertEquals(result, MyValue1.default.hash());
}
@@ -2483,13 +2490,13 @@ public long test95_callee() {
}
@Test()
- @Warmup(0)
public long test95() {
return test95_callee();
}
- @DontCompile
- public void test95_verifier(boolean warmup) {
+ @Run(test = "test95")
+ @Warmup(0)
+ public void test95_verifier() {
long result = test95();
Asserts.assertEQ(result, hash());
}
@@ -2542,8 +2549,8 @@ public Complex.ref[][] test96(Complex.ref[][] A, Complex.ref[][] B) {
}
}
- @DontCompile
- public void test96_verifier(boolean warmup) {
+ @Run(test = "test96")
+ public void test96_verifier() {
Complex.ref[][] result = test96(test96_A, test96_B);
if (test96_R == null) {
test96_R = result;
@@ -2556,13 +2563,14 @@ public void test96_verifier(boolean warmup) {
}
// Test loads from vararg arrays
- @Test(failOn = LOAD_UNKNOWN_INLINE)
+ @Test
+ @IR(failOn = {LOAD_UNKNOWN_INLINE})
public static Object test97(Object... args) {
return args[0];
}
- @DontCompile
- public static void test97_verifier(boolean warmup) {
+ @Run(test = "test97")
+ public static void test97_verifier() {
Object obj = new Object();
Object result = test97(obj);
Asserts.assertEquals(result, obj);
@@ -2577,8 +2585,8 @@ public static Object test98(Object... args) {
return args[0];
}
- @DontCompile
- public static void test98_verifier(boolean warmup) {
+ @Run(test = "test98")
+ public static void test98_verifier(RunInfo info) {
Object obj = new Object();
Object result = test98(obj);
Asserts.assertEquals(result, obj);
@@ -2586,7 +2594,7 @@ public static void test98_verifier(boolean warmup) {
myInt[0] = rI;
result = test98((Object[])myInt);
Asserts.assertEquals(result, rI);
- if (!warmup) {
+ if (!info.isWarmUp()) {
MyValue1[] va = new MyValue1[1];
MyValue1.ref[] vab = new MyValue1.ref[1];
result = test98((Object[])va);
@@ -2601,8 +2609,8 @@ public static Object test99(Object... args) {
return args[0];
}
- @DontCompile
- public static void test99_verifier(boolean warmup) {
+ @Run(test = "test99")
+ public static void test99_verifier(RunInfo info) {
Object obj = new Object();
Object result = test99(obj);
Asserts.assertEquals(result, obj);
@@ -2610,7 +2618,7 @@ public static void test99_verifier(boolean warmup) {
myInt[0] = rI;
result = test99((Object[])myInt);
Asserts.assertEquals(result, rI);
- if (!warmup) {
+ if (!info.isWarmUp()) {
try {
test99((Object[])null);
throw new RuntimeException("No NPE thrown");
@@ -2625,8 +2633,8 @@ public static Object test100(Object... args) {
return args[0];
}
- @DontCompile
- public static void test100_verifier(boolean warmup) {
+ @Run(test = "test100")
+ public static void test100_verifier(RunInfo info) {
Object obj = new Object();
Object result = test100(obj);
Asserts.assertEquals(result, obj);
@@ -2634,7 +2642,7 @@ public static void test100_verifier(boolean warmup) {
myInt[0] = rI;
result = test100((Object[])myInt);
Asserts.assertEquals(result, rI);
- if (!warmup) {
+ if (!info.isWarmUp()) {
try {
test100();
throw new RuntimeException("No AIOOBE thrown");
@@ -2645,13 +2653,14 @@ public static void test100_verifier(boolean warmup) {
}
// Test stores to varag arrays
- @Test(failOn = STORE_UNKNOWN_INLINE)
+ @Test
+ @IR(failOn = STORE_UNKNOWN_INLINE)
public static void test101(Object val, Object... args) {
args[0] = val;
}
- @DontCompile
- public static void test101_verifier(boolean warmup) {
+ @Run(test = "test101")
+ public static void test101_verifier() {
Object obj = new Object();
test101(obj, obj);
Integer[] myInt = new Integer[1];
@@ -2666,8 +2675,8 @@ public static void test102(Object val, Object... args) {
args[0] = val;
}
- @DontCompile
- public static void test102_verifier(boolean warmup) {
+ @Run(test = "test102")
+ public static void test102_verifier(RunInfo info) {
Object obj = new Object();
test102(obj, obj);
Integer[] myInt = new Integer[1];
@@ -2675,7 +2684,7 @@ public static void test102_verifier(boolean warmup) {
Asserts.assertEquals(myInt[0], rI);
test102(null, (Object[])myInt);
Asserts.assertEquals(myInt[0], null);
- if (!warmup) {
+ if (!info.isWarmUp()) {
MyValue1[] va = new MyValue1[1];
MyValue1.ref[] vab = new MyValue1.ref[1];
test102(testValue1, (Object[])va);
@@ -2692,8 +2701,8 @@ public static void test103(Object val, Object... args) {
args[0] = val;
}
- @DontCompile
- public static void test103_verifier(boolean warmup) {
+ @Run(test = "test103")
+ public static void test103_verifier(RunInfo info) {
Object obj = new Object();
test103(obj, obj);
Integer[] myInt = new Integer[1];
@@ -2701,7 +2710,7 @@ public static void test103_verifier(boolean warmup) {
Asserts.assertEquals(myInt[0], rI);
test103(null, (Object[])myInt);
Asserts.assertEquals(myInt[0], null);
- if (!warmup) {
+ if (!info.isWarmUp()) {
MyValue1[] va = new MyValue1[1];
try {
test103(null, (Object[])va);
@@ -2717,8 +2726,8 @@ public static void test104(Object val, Object... args) {
args[0] = val;
}
- @DontCompile
- public static void test104_verifier(boolean warmup) {
+ @Run(test = "test104")
+ public static void test104_verifier(RunInfo info) {
Object obj = new Object();
test104(obj, obj);
Integer[] myInt = new Integer[1];
@@ -2726,7 +2735,7 @@ public static void test104_verifier(boolean warmup) {
Asserts.assertEquals(myInt[0], rI);
test104(null, (Object[])myInt);
Asserts.assertEquals(myInt[0], null);
- if (!warmup) {
+ if (!info.isWarmUp()) {
try {
test104(testValue1);
throw new RuntimeException("No AIOOBE thrown");
@@ -2741,8 +2750,8 @@ public static void test105(Object val, Object... args) {
args[0] = val;
}
- @DontCompile
- public static void test105_verifier(boolean warmup) {
+ @Run(test = "test105")
+ public static void test105_verifier(RunInfo info) {
Object obj = new Object();
test105(obj, obj);
Integer[] myInt = new Integer[1];
@@ -2750,7 +2759,7 @@ public static void test105_verifier(boolean warmup) {
Asserts.assertEquals(myInt[0], rI);
test105(null, (Object[])myInt);
Asserts.assertEquals(myInt[0], null);
- if (!warmup) {
+ if (!info.isWarmUp()) {
try {
test105(testValue1, (Object[])null);
throw new RuntimeException("No NPE thrown");
@@ -2775,8 +2784,8 @@ public static Object[] test106(Object[] dst, Object... args) {
return Arrays.copyOf(args, args.length, Object[].class);
}
- @DontCompile
- public static void test106_verifier(boolean warmup) {
+ @Run(test = "test106")
+ public static void test106_verifier(RunInfo info) {
Object[] dst = new Object[1];
Object obj = new Object();
Object[] result = test106(dst, obj);
@@ -2785,7 +2794,7 @@ public static void test106_verifier(boolean warmup) {
myInt[0] = rI;
result = test106(myInt, (Object[])myInt);
Asserts.assertEquals(result[0], rI);
- if (!warmup) {
+ if (!info.isWarmUp()) {
MyValue1[] va = new MyValue1[1];
MyValue1.ref[] vab = new MyValue1.ref[1];
result = test106(va, (Object[])va);
@@ -2814,13 +2823,12 @@ public void test107() {
Asserts.assertEquals(res2, MyValue1.default.hash());
}
- @DontCompile
- public void test107_verifier(boolean warmup) {
+ @Run(test = "test107")
+ public void test107_verifier() {
test107();
}
@Test
- @Warmup(10000)
public Object test108(MyValue1.ref[] src, boolean flag) {
MyValue1.ref[] dst = new MyValue1.ref[8];
System.arraycopy(src, 1, dst, 2, 6);
@@ -2828,10 +2836,11 @@ public Object test108(MyValue1.ref[] src, boolean flag) {
return dst[2];
}
- @DontCompile
- public void test108_verifier(boolean warmup) {
+ @Run(test = "test108")
+ @Warmup(10000)
+ public void test108_verifier(RunInfo info) {
MyValue1.ref[] src = new MyValue1.ref[8];
- test108(src, !warmup);
+ test108(src, !info.isWarmUp());
}
// Test LoadNode::can_see_arraycopy_value optimization
@@ -2844,8 +2853,8 @@ public static void test109() {
Asserts.assertEquals(src[0], dst[0]);
}
- @DontCompile
- public void test109_verifier(boolean warmup) {
+ @Run(test = "test109")
+ public void test109_verifier() {
test109();
}
@@ -2859,8 +2868,8 @@ public static void test110() {
Asserts.assertEquals(src[0], dst[0]);
}
- @DontCompile
- public void test110_verifier(boolean warmup) {
+ @Run(test = "test110")
+ public void test110_verifier() {
test110();
}
@@ -2873,8 +2882,8 @@ public static void test111() {
Asserts.assertEquals(src[0], dst[0]);
}
- @DontCompile
- public void test111_verifier(boolean warmup) {
+ @Run(test = "test111")
+ public void test111_verifier() {
test111();
}
}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java
index 7f235130fa6..3c124f28943 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2021, 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,38 +23,43 @@
package compiler.valhalla.inlinetypes;
-import java.lang.invoke.*;
+import compiler.lib.ir_framework.*;
+import jdk.test.lib.Asserts;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
-import jdk.test.lib.Asserts;
+import static compiler.valhalla.inlinetypes.InlineTypes.IRNode.ALLOC;
+import static compiler.valhalla.inlinetypes.InlineTypes.IRNode.STORE;
+import static compiler.valhalla.inlinetypes.InlineTypes.rI;
+import static compiler.valhalla.inlinetypes.InlineTypes.rL;
/*
* @test
* @key randomness
* @summary Test correct handling of nullable inline types.
- * @library /testlibrary /test/lib /compiler/whitebox /
+ * @library /test/lib /
* @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
- * @compile TestNullableInlineTypes.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestNullableInlineTypes
+ * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestNullableInlineTypes
*/
-public class TestNullableInlineTypes extends InlineTypeTest {
- // Extra VM parameters for some test scenarios. See InlineTypeTest.getVMParameters()
- @Override
- public String[] getExtraVMParameters(int scenario) {
- switch (scenario) {
- case 3: return new String[] {"-XX:-MonomorphicArrayCheck", "-XX:FlatArrayElementMaxSize=-1"};
- case 4: return new String[] {"-XX:-MonomorphicArrayCheck"};
- }
- return null;
- }
- public static void main(String[] args) throws Throwable {
- TestNullableInlineTypes test = new TestNullableInlineTypes();
- test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class, Test17Value.class, Test21Value.class);
+@ForceCompileClassInitializer
+public class TestNullableInlineTypes {
+
+ public static void main(String[] args) {
+
+ Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS;
+ scenarios[3].addFlags("-XX:-MonomorphicArrayCheck", "-XX:FlatArrayElementMaxSize=-1");
+ scenarios[4].addFlags("-XX:-MonomorphicArrayCheck");
+
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .addHelperClasses(MyValue1.class,
+ MyValue2.class,
+ MyValue2Inline.class)
+ .start();
}
static {
@@ -95,8 +100,8 @@ public long test1(MyValue1.ref vt) {
return result;
}
- @DontCompile
- public void test1_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test1")
+ public void test1_verifier() throws Throwable {
long result = test1(null);
Asserts.assertEquals(result, 0L);
}
@@ -113,8 +118,8 @@ public long test2(MyValue1.ref vt) {
return result;
}
- @DontCompile
- public void test2_verifier(boolean warmup) {
+ @Run(test = "test2")
+ public void test2_verifier() {
long result = test2(nullField);
Asserts.assertEquals(result, 0L);
}
@@ -134,8 +139,8 @@ public long test3() {
return result;
}
- @DontCompile
- public void test3_verifier(boolean warmup) {
+ @Run(test = "test3")
+ public void test3_verifier() {
long result = test3();
Asserts.assertEquals(result, 0L);
}
@@ -150,8 +155,8 @@ public void test4() {
}
}
- @DontCompile
- public void test4_verifier(boolean warmup) {
+ @Run(test = "test4")
+ public void test4_verifier() {
test4();
}
@@ -171,8 +176,8 @@ public MyValue1.ref test5(MyValue1.ref vt) {
return vt;
}
- @DontCompile
- public void test5_verifier(boolean warmup) {
+ @Run(test = "test5")
+ public void test5_verifier() {
MyValue1.ref vt = test5(nullField);
Asserts.assertEquals((Object)vt, null);
}
@@ -199,8 +204,8 @@ public MyValue1 test6(Object obj) {
return vt;
}
- @DontCompile
- public void test6_verifier(boolean warmup) {
+ @Run(test = "test6")
+ public void test6_verifier() {
MyValue1 vt = test6(null);
Asserts.assertEquals(vt.hash(), testValue1.hash());
}
@@ -233,8 +238,8 @@ public void test7() throws Throwable {
}
}
- @DontCompile
- public void test7_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test7")
+ public void test7_verifier() throws Throwable {
test7();
}
@@ -248,8 +253,8 @@ public void test8() throws Throwable {
}
}
- @DontCompile
- public void test8_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test8")
+ public void test8_verifier() throws Throwable {
test8();
}
@@ -265,8 +270,8 @@ public void test9(boolean flag1) {
valueField1 = v;
}
- @DontCompile
- public void test9_verifier(boolean warmup) {
+ @Run(test = "test9")
+ public void test9_verifier() {
test9(true);
try {
test9(false);
@@ -283,8 +288,8 @@ public void test10(boolean flag) throws Throwable {
valueField1 = (MyValue1) val;
}
- @DontCompile
- public void test10_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test10")
+ public void test10_verifier() throws Throwable {
test10(true);
try {
test10(false);
@@ -301,8 +306,8 @@ public void test11(boolean flag) throws Throwable {
valueField1 = (MyValue1) val;
}
- @DontCompile
- public void test11_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test11")
+ public void test11_verifier() throws Throwable {
test11(false);
try {
test11(true);
@@ -326,8 +331,8 @@ public void test12() {
valueField1 = (MyValue1) test12_helper();
}
- @DontCompile
- public void test12_verifier(boolean warmup) {
+ @Run(test = "test12")
+ public void test12_verifier() {
try {
test12_cnt = 0;
test12();
@@ -370,8 +375,8 @@ public void test13(A a) {
valueField1 = (MyValue1) a.test13_helper();
}
- @DontCompile
- public void test13_verifier(boolean warmup) {
+ @Run(test = "test13")
+ public void test13_verifier() {
A a = new A();
A b = new B();
A c = new C();
@@ -413,8 +418,8 @@ public void test14(MyValue1[] va, int index) {
test14_inline(va, nullField, index);
}
- @DontCompile
- public void test14_verifier(boolean warmup) {
+ @Run(test = "test14")
+ public void test14_verifier() {
int index = Math.abs(rI) % 3;
try {
test14(testValue1Array, index);
@@ -452,8 +457,8 @@ public void test15() {
}
}
- @DontCompile
- public void test15_verifier(boolean warmup) {
+ @Run(test = "test15")
+ public void test15_verifier() {
test15();
}
@@ -464,14 +469,14 @@ public boolean test16_dontinline(MyValue1.ref vt) {
// Test c2c call passing null for an inline type
@Test
- @Warmup(10000) // Warmup to make sure 'test17_dontinline' is compiled
public boolean test16(Object arg) throws Exception {
Method test16method = getClass().getMethod("test16_dontinline", MyValue1.ref.class);
return (boolean)test16method.invoke(this, arg);
}
- @DontCompile
- public void test16_verifier(boolean warmup) throws Exception {
+ @Run(test = "test16")
+ @Warmup(10000) // Warmup to make sure 'test17_dontinline' is compiled
+ public void test16_verifier() throws Exception {
boolean res = test16(null);
Asserts.assertTrue(res);
}
@@ -496,8 +501,8 @@ public Test17Value test17(boolean b) {
return b ? vt1 : vt2;
}
- @DontCompile
- public void test17_verifier(boolean warmup) {
+ @Run(test = "test17")
+ public void test17_verifier() {
test17(true);
test17(false);
}
@@ -519,14 +524,14 @@ static void test18_target2(MyValue1.ref vt) {
// Test passing null for an inline type
@Test
- @Warmup(11000) // Make sure lambda forms get compiled
public void test18() throws Throwable {
test18_mh1.invokeExact(nullValue);
test18_mh2.invokeExact(nullValue);
}
- @DontCompile
- public void test18_verifier(boolean warmup) {
+ @Run(test = "test18")
+ @Warmup(11000) // Make sure lambda forms get compiled
+ public void test18_verifier() {
try {
test18();
} catch (Throwable t) {
@@ -549,14 +554,14 @@ static void test19_target2(MyValue1.ref vt) {
// Same as test12 but with non-final mh
@Test
- @Warmup(11000) // Make sure lambda forms get compiled
public void test19() throws Throwable {
test19_mh1.invokeExact(nullValue);
test19_mh2.invokeExact(nullValue);
}
- @DontCompile
- public void test19_verifier(boolean warmup) {
+ @Run(test = "test19")
+ @Warmup(11000) // Make sure lambda forms get compiled
+ public void test19_verifier() {
try {
test19();
} catch (Throwable t) {
@@ -566,13 +571,13 @@ public void test19_verifier(boolean warmup) {
// Same as test12/13 but with constant null
@Test
- @Warmup(11000) // Make sure lambda forms get compiled
public void test20(MethodHandle mh) throws Throwable {
mh.invoke(null);
}
- @DontCompile
- public void test20_verifier(boolean warmup) {
+ @Run(test = "test20")
+ @Warmup(11000) // Make sure lambda forms get compiled
+ public void test20_verifier() {
try {
test20(test18_mh1);
test20(test18_mh2);
@@ -618,8 +623,8 @@ public Test21Value test21(Test21Value vt) {
return vt;
}
- @DontCompile
- public void test21_verifier(boolean warmup) {
+ @Run(test = "test21")
+ public void test21_verifier() {
test21(Test21Value.default);
}
@@ -633,8 +638,8 @@ public void test22() {
valueField1 = test22_helper();
}
- @DontCompile
- public void test22_verifier(boolean warmup) {
+ @Run(test = "test22")
+ public void test22_verifier() {
try {
test22();
throw new RuntimeException("NullPointerException expected");
@@ -648,8 +653,8 @@ public void test23(MyValue1[] arr, MyValue1.ref b) {
arr[0] = (MyValue1) b;
}
- @DontCompile
- public void test23_verifier(boolean warmup) {
+ @Run(test = "test23")
+ public void test23_verifier() {
MyValue1[] arr = new MyValue1[2];
MyValue1.ref b = null;
try {
@@ -667,8 +672,8 @@ public MyValue1 test24() {
return (MyValue1) nullBox;
}
- @DontCompile
- public void test24_verifier(boolean warmup) {
+ @Run(test = "test24")
+ public void test24_verifier() {
try {
test24();
throw new RuntimeException("NullPointerException expected");
@@ -682,7 +687,8 @@ public void test25_callee(MyValue1 val) { }
// Test that when checkcasting from null-ok to null-free and back to null-ok we
// keep track of the information that the inline type can never be null.
- @Test(failOn = ALLOC + STORE)
+ @Test
+ @IR(failOn = {ALLOC, STORE})
public int test25(boolean b, MyValue1.ref vt1, MyValue1 vt2) {
vt1 = (MyValue1)vt1;
Object obj = b ? vt1 : vt2; // We should not allocate here
@@ -690,8 +696,8 @@ public int test25(boolean b, MyValue1.ref vt1, MyValue1 vt2) {
return ((MyValue1)obj).x;
}
- @DontCompile
- public void test25_verifier(boolean warmup) {
+ @Run(test = "test25")
+ public void test25_verifier() {
int res = test25(true, testValue1, testValue1);
Asserts.assertEquals(res, testValue1.x);
res = test25(false, testValue1, testValue1);
@@ -699,25 +705,27 @@ public void test25_verifier(boolean warmup) {
}
// Test that chains of casts are folded and don't trigger an allocation
- @Test(failOn = ALLOC + STORE)
+ @Test
+ @IR(failOn = {ALLOC, STORE})
public MyValue3 test26(MyValue3 vt) {
return ((MyValue3)((Object)((MyValue3.ref)(MyValue3)((MyValue3.ref)((Object)vt)))));
}
- @DontCompile
- public void test26_verifier(boolean warmup) {
+ @Run(test = "test26")
+ public void test26_verifier() {
MyValue3 vt = MyValue3.create();
MyValue3 result = test26(vt);
Asserts.assertEquals(result, vt);
}
- @Test(failOn = ALLOC + STORE)
+ @Test
+ @IR(failOn = {ALLOC, STORE})
public MyValue3.ref test27(MyValue3.ref vt) {
return ((MyValue3.ref)((Object)((MyValue3)(MyValue3.ref)((MyValue3)((Object)vt)))));
}
- @DontCompile
- public void test27_verifier(boolean warmup) {
+ @Run(test = "test27")
+ public void test27_verifier() {
MyValue3 vt = MyValue3.create();
MyValue3 result = (MyValue3) test27(vt);
Asserts.assertEquals(result, vt);
@@ -738,8 +746,8 @@ public MyValue1.ref test28(MyValue1 vt, MyValue1.ref vtBox, int i) {
return result;
}
- @DontCompile
- public void test28_verifier(boolean warmup) {
+ @Run(test = "test28")
+ public void test28_verifier() {
MyValue1.ref result = test28(testValue1, null, 0);
Asserts.assertEquals(result, null);
result = test28(testValue1, testValue1, 1);
@@ -770,8 +778,8 @@ public long test29(MyValue1 vt, MyValue1.ref vtBox) {
return result;
}
- @DontCompile
- public void test29_verifier(boolean warmup) {
+ @Run(test = "test29")
+ public void test29_verifier() {
long result = test29(testValue1, null);
Asserts.assertEquals(result, testValue1.hash()*98);
result = test29(testValue1, testValue1);
@@ -795,8 +803,8 @@ public long test30() {
return test30_callee(nullField);
}
- @DontCompile
- public void test30_verifier(boolean warmup) {
+ @Run(test = "test30")
+ public void test30_verifier() {
long result = test30();
Asserts.assertEquals(result, 0L);
}
@@ -816,8 +824,8 @@ public void test31(Object o) {
}
}
- @DontCompile
- public void test31_verifier(boolean warmup) {
+ @Run(test = "test31")
+ public void test31_verifier() {
test31(null);
}
@@ -828,8 +836,8 @@ public MyValue1.ref test32() {
return constNullField;
}
- @DontCompile
- public void test32_verifier(boolean warmup) {
+ @Run(test = "test32")
+ public void test32_verifier() {
MyValue1.ref result = test32();
Asserts.assertEquals(result, null);
}
@@ -853,8 +861,8 @@ public Test33Value2 test33() {
return test33Val;
}
- @DontCompile
- public void test33_verifier(boolean warmup) {
+ @Run(test = "test33")
+ public void test33_verifier() {
Test33Value2 result = test33();
Asserts.assertEquals(result, test33Val);
}
@@ -870,10 +878,10 @@ public void test34(MyValue1 vt) {
}
}
- @DontCompile
- public void test34_verifier(boolean warmup) {
+ @Run(test = "test34")
+ public void test34_verifier(RunInfo info) {
test34(testValue1);
- if (!warmup) {
+ if (!info.isWarmUp()) {
test34Val = null;
test34(testValue1);
Asserts.assertEquals(test34Val, testValue1);
@@ -892,15 +900,16 @@ public Test17Value test35(boolean b) {
return b ? vt1 : vt2;
}
- @DontCompile
- public void test35_verifier(boolean warmup) {
+ @Run(test = "test35")
+ public void test35_verifier() {
test35(true);
test35(false);
}
// Test that when explicitly null checking an inline type, we keep
// track of the information that the inline type can never be null.
- @Test(failOn = ALLOC + STORE)
+ @Test
+ @IR(failOn = {ALLOC, STORE})
public int test37(boolean b, MyValue1.ref vt1, MyValue1.val vt2) {
if (vt1 == null) {
return 0;
@@ -911,8 +920,8 @@ public int test37(boolean b, MyValue1.ref vt1, MyValue1.val vt2) {
return ((MyValue1)obj).x;
}
- @DontCompile
- public void test37_verifier(boolean warmup) {
+ @Run(test = "test37")
+ public void test37_verifier() {
int res = test37(true, testValue1, testValue1);
Asserts.assertEquals(res, testValue1.x);
res = test37(false, testValue1, testValue1);
@@ -921,7 +930,8 @@ public void test37_verifier(boolean warmup) {
// Test that when explicitly null checking an inline type receiver,
// we keep track of the information that the inline type can never be null.
- @Test(failOn = ALLOC + STORE)
+ @Test
+ @IR(failOn = {ALLOC, STORE})
public int test38(boolean b, MyValue1.ref vt1, MyValue1.val vt2) {
vt1.hash(); // Inlined - Explicit null check
// vt1 should be scalarized because it's always non-null
@@ -930,8 +940,8 @@ public int test38(boolean b, MyValue1.ref vt1, MyValue1.val vt2) {
return ((MyValue1)obj).x;
}
- @DontCompile
- public void test38_verifier(boolean warmup) {
+ @Run(test = "test38")
+ public void test38_verifier() {
int res = test38(true, testValue1, testValue1);
Asserts.assertEquals(res, testValue1.x);
res = test38(false, testValue1, testValue1);
@@ -940,7 +950,8 @@ public void test38_verifier(boolean warmup) {
// Test that when implicitly null checking an inline type receiver,
// we keep track of the information that the inline type can never be null.
- @Test(failOn = ALLOC + STORE)
+ @Test
+ @IR(failOn = {ALLOC, STORE})
public int test39(boolean b, MyValue1.ref vt1, MyValue1.val vt2) {
vt1.hashInterpreted(); // Not inlined - Implicit null check
// vt1 should be scalarized because it's always non-null
@@ -949,8 +960,8 @@ public int test39(boolean b, MyValue1.ref vt1, MyValue1.val vt2) {
return ((MyValue1)obj).x;
}
- @DontCompile
- public void test39_verifier(boolean warmup) {
+ @Run(test = "test39")
+ public void test39_verifier() {
int res = test39(true, testValue1, testValue1);
Asserts.assertEquals(res, testValue1.x);
res = test39(false, testValue1, testValue1);
@@ -958,14 +969,14 @@ public void test39_verifier(boolean warmup) {
}
// Test NPE when casting constant null to inline type
- @Test()
+ @Test
public MyValue1 test40() throws Throwable {
Object NULL = null;
return (MyValue1)NULL;
}
- @DontCompile
- public void test40_verifier(boolean warmup) throws Throwable {
+ @Run(test = "test40")
+ public void test40_verifier() throws Throwable {
try {
test40();
throw new RuntimeException("NullPointerException expected");
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOnStackReplacement.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOnStackReplacement.java
index 7a1c8889c80..70264011080 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOnStackReplacement.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOnStackReplacement.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2021, 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,35 +23,37 @@
package compiler.valhalla.inlinetypes;
+import compiler.lib.ir_framework.*;
import jdk.test.lib.Asserts;
-import java.lang.reflect.Method;
+
+import static compiler.valhalla.inlinetypes.InlineTypes.IRNode.*;
+import static compiler.valhalla.inlinetypes.InlineTypes.rI;
+import static compiler.valhalla.inlinetypes.InlineTypes.rL;
/*
* @test
* @key randomness
* @summary Test on stack replacement (OSR) with inline types
- * @library /testlibrary /test/lib /compiler/whitebox /
+ * @library /test/lib /
* @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
- * @compile TestOnStackReplacement.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestOnStackReplacement
+ * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestOnStackReplacement
*/
-public class TestOnStackReplacement extends InlineTypeTest {
- // Extra VM parameters for some test scenarios. See InlineTypeTest.getVMParameters()
- @Override
- public String[] getExtraVMParameters(int scenario) {
- switch (scenario) {
- case 3: return new String[] {"-XX:FlatArrayElementMaxSize=0"};
- }
- return null;
- }
+
+public class TestOnStackReplacement {
+
public static void main(String[] args) throws Throwable {
- TestOnStackReplacement test = new TestOnStackReplacement();
- test.run(args, MyValue1.class, MyValue2.class, MyValue2Inline.class, MyValue3.class, MyValue3Inline.class);
+ Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS;
+ scenarios[3].addFlags("-XX:FlatArrayElementMaxSize=0");
+
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .addHelperClasses(MyValue1.class,
+ MyValue2.class,
+ MyValue2Inline.class,
+ MyValue3.class,
+ MyValue3Inline.class)
+ .start();
}
// Helper methods
@@ -65,7 +67,7 @@ protected long hash(int x, long y) {
}
// Test OSR compilation
- @Test() @Warmup(0) @OSRCompileOnly
+ @Test(compLevel = CompLevel.WAIT_FOR_COMPILATION)
public long test1() {
MyValue1 v = MyValue1.createWithFieldsInline(rI, rL);
MyValue1[] va = new MyValue1[Math.abs(rI) % 3];
@@ -84,14 +86,16 @@ public long test1() {
return result;
}
- @DontCompile
- public void test1_verifier(boolean warmup) {
+ @Run(test = "test1")
+ @Warmup(0)
+ public void test1_verifier() {
long result = test1();
Asserts.assertEQ(result, ((Math.abs(rI) % 3) + 1) * hash());
}
// Test loop peeling
- @Test(failOn = ALLOC + LOAD + STORE) @Warmup(0) @OSRCompileOnly
+ @Test(compLevel = CompLevel.WAIT_FOR_COMPILATION)
+ @IR(failOn = {ALLOC, LOAD, STORE})
public void test2() {
MyValue1 v = MyValue1.createWithFieldsInline(0, 1);
// Trigger OSR compilation and loop peeling
@@ -104,13 +108,14 @@ public void test2() {
}
}
- @DontCompile
- public void test2_verifier(boolean warmup) {
+ @Run(test = "test2")
+ @Warmup(0)
+ public void test2_verifier() {
test2();
}
// Test loop peeling and unrolling
- @Test() @Warmup(0) @OSRCompileOnly
+ @Test(compLevel = CompLevel.WAIT_FOR_COMPILATION)
public void test3() {
MyValue1 v1 = MyValue1.createWithFieldsInline(0, 0);
MyValue1 v2 = MyValue1.createWithFieldsInline(1, 1);
@@ -125,8 +130,9 @@ public void test3() {
}
}
- @DontCompile
- public void test3_verifier(boolean warmup) {
+ @Run(test = "test3")
+ @Warmup(0)
+ public void test3_verifier() {
test3();
}
@@ -141,7 +147,7 @@ public Object test4_body() {
return MyValue1.createWithFieldsInline(rI, rL);
}
- @Test() @Warmup(0) @OSRCompileOnly
+ @Test(compLevel = CompLevel.WAIT_FOR_COMPILATION)
public Object test4() {
Object vt = test4_init();
for (int i = 0; i < 50_000; i++) {
@@ -152,8 +158,9 @@ public Object test4() {
return vt;
}
- @DontCompile
- public void test4_verifier(boolean warmup) {
+ @Run(test = "test4")
+ @Warmup(0)
+ public void test4_verifier() {
test4();
}
@@ -161,7 +168,7 @@ public void test4_verifier(boolean warmup) {
MyValue1.ref nullField;
- @Test() @Warmup(0) @OSRCompileOnly
+ @Test(compLevel = CompLevel.WAIT_FOR_COMPILATION)
public void test5() {
MyValue1.ref vt = nullField;
for (int i = 0; i < 50_000; i++) {
@@ -171,8 +178,9 @@ public void test5() {
}
}
- @DontCompile
- public void test5_verifier(boolean warmup) {
+ @Run(test = "test5")
+ @Warmup(0)
+ public void test5_verifier() {
test5();
}
@@ -189,7 +197,7 @@ public int test() {
}
}
- @Test() @Warmup(0) @OSRCompileOnly
+ @Test(compLevel = CompLevel.WAIT_FOR_COMPILATION)
public void test6() {
Test6Value tmp = new Test6Value();
for (int i = 0; i < 100; ++i) {
@@ -197,8 +205,9 @@ public void test6() {
}
}
- @DontCompile
- public void test6_verifier(boolean warmup) {
+ @Run(test = "test6")
+ @Warmup(0)
+ public void test6_verifier() {
test6();
}
@@ -246,7 +255,7 @@ public int test(String[] args) {
}
}
- @Test() @Warmup(0) @OSRCompileOnly
+ @Test(compLevel = CompLevel.WAIT_FOR_COMPILATION)
public void test7() {
Test7Value2 tmp = new Test7Value2();
for (int i = 0; i < 10; ++i) {
@@ -254,8 +263,9 @@ public void test7() {
}
}
- @DontCompile
- public void test7_verifier(boolean warmup) {
+ @Run(test = "test7")
+ @Warmup(0)
+ public void test7_verifier() {
test7();
}
@@ -273,7 +283,7 @@ public MyValue3 test8_callee(int len) {
return test8_vt;
}
- @Test() @Warmup(2)
+ @Test
public int test8(int start) {
MyValue3 vt = test8_callee(start);
test8_vt.verify(vt);
@@ -284,8 +294,9 @@ public int test8(int start) {
return result;
}
- @DontCompile
- public void test8_verifier(boolean warmup) {
+ @Run(test = "test8")
+ @Warmup(2)
+ public void test8_verifier() {
test8(1);
test8(50_000);
}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeField.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeField.java
index 14fad35bc85..f58151b0eaa 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeField.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeField.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2021, 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
@@ -22,50 +22,46 @@
*/
package compiler.valhalla.inlinetypes;
+
+import compiler.lib.ir_framework.Run;
+import compiler.lib.ir_framework.RunInfo;
+import compiler.lib.ir_framework.Scenario;
+import compiler.lib.ir_framework.Test;
import jdk.test.lib.Asserts;
-/**
+import static compiler.valhalla.inlinetypes.InlineTypes.rI;
+
+/*
* @test
* @key randomness
- * @library /testlibrary /test/lib /compiler/whitebox /
* @summary Test the handling of fields of unloaded inline classes.
+ * @library /test/lib /
+ * @requires os.simpleArch == "x64"
* @compile hack/GetUnresolvedInlineFieldWrongSignature.java
* @compile TestUnloadedInlineTypeField.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=120 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * -XX:PerMethodRecompilationCutoff=-1 -XX:PerBytecodeRecompilationCutoff=-1
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestUnloadedInlineTypeField
+ * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestUnloadedInlineTypeField
*/
-public class TestUnloadedInlineTypeField extends InlineTypeTest {
- // Only prevent loading of classes when testing with C1. Load classes
+public class TestUnloadedInlineTypeField {
+ // The test only prevent loading of classes when testing with C1. Load classes
// early when executing with C2 to prevent uncommon traps. It's still
// beneficial to execute this test with C2 because it also checks handling
// of type mismatches.
- private static final boolean PREVENT_LOADING = TEST_C1;
- public static void main(String[] args) throws Throwable {
- TestUnloadedInlineTypeField test = new TestUnloadedInlineTypeField();
- test.run(args);
- }
-
- static final String[][] scenarios = {
- {},
- {"-XX:InlineFieldMaxFlatSize=0"},
- {"-XX:+PatchALot"},
- {"-XX:InlineFieldMaxFlatSize=0", "-XX:+PatchALot"}
- };
-
- @Override
- public int getNumScenarios() {
- return scenarios.length;
- }
+ public static void main(String[] args) {
+ final Scenario[] scenarios = {
+ new Scenario(0),
+ new Scenario(1, "-XX:InlineFieldMaxFlatSize=0"),
+ new Scenario(2, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-XX:+PatchALot"),
+ new Scenario(3,
+ "-XX:InlineFieldMaxFlatSize=0",
+ "-XX:+IgnoreUnrecognizedVMOptions",
+ "-XX:+PatchALot")
+ };
- @Override
- public String[] getVMParameters(int scenario) {
- return scenarios[scenario];
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .start();
}
// Test case 1:
@@ -107,9 +103,9 @@ public int test1(Object holder) {
}
}
- @DontCompile
- public void test1_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test1")
+ public void test1_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test1(null);
} else {
MyValue1Holder holder = new MyValue1Holder();
@@ -152,9 +148,9 @@ public int test2(Object holder) {
}
}
- @DontCompile
- public void test2_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test2")
+ public void test2_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test2(null);
} else {
MyValue2Holder holder = new MyValue2Holder();
@@ -201,9 +197,9 @@ public int test3(Object holder) {
return GetUnresolvedInlineFieldWrongSignature.test3(holder);
}
- @DontCompile
- public void test3_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test3")
+ public void test3_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test3(null);
} else {
// Make sure klass is resolved
@@ -245,10 +241,10 @@ public void test4(Object holder, MyValue4 v) {
}
}
- @DontCompile
- public void test4_verifier(boolean warmup) {
+ @Run(test = "test4")
+ public void test4_verifier(RunInfo info) {
MyValue4 v = new MyValue4(rI);
- if (warmup && PREVENT_LOADING) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test4(null, v);
} else {
MyValue4Holder holder = new MyValue4Holder();
@@ -288,9 +284,9 @@ public void test5(Object holder, Object o) {
}
}
- @DontCompile
- public void test5_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test5")
+ public void test5_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test5(null, null);
} else {
MyValue5Holder holder = new MyValue5Holder();
@@ -334,9 +330,9 @@ public int test6(int n) {
}
}
- @DontCompile
- public void test6_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test6")
+ public void test6_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test6(0);
} else {
Asserts.assertEQ(test6(rI), 2*rI);
@@ -373,9 +369,9 @@ public int test7(int n) {
}
}
- @DontCompile
- public void test7_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test7")
+ public void test7_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test7(0);
} else {
Asserts.assertEQ(test7(rI), 2*rI);
@@ -414,9 +410,9 @@ public int test8(boolean warmup) {
}
}
- @DontCompile
- public void test8_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test8")
+ public void test8_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test8(true);
} else {
Asserts.assertEQ(test8(false), rI);
@@ -451,9 +447,9 @@ public int test9(boolean warmup) {
}
}
- @DontCompile
- public void test9_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test9")
+ public void test9_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test9(true);
} else {
Asserts.assertEQ(test9(false), rI);
@@ -490,9 +486,9 @@ public void test10(Object holder) {
GetUnresolvedInlineFieldWrongSignature.test10(holder);
}
- @DontCompile
- public void test10_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test10")
+ public void test10_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test10(null);
} else {
// Make sure klass is resolved
@@ -537,10 +533,10 @@ public Object test11(boolean warmup, MyValue11 v) {
}
}
- @DontCompile
- public void test11_verifier(boolean warmup) {
+ @Run(test = "test11")
+ public void test11_verifier(RunInfo info) {
MyValue11 v = new MyValue11(rI);
- if (warmup && PREVENT_LOADING) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test11(true, v);
} else {
MyValue11Holder holder = (MyValue11Holder)test11(false, v);
@@ -578,9 +574,9 @@ public Object test12(boolean warmup, Object o) {
}
}
- @DontCompile
- public void test12_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test12")
+ public void test12_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test12(true, null);
} else {
MyValue12 v = new MyValue12(rI);
@@ -617,9 +613,9 @@ public void test13(Object holder) {
GetUnresolvedInlineFieldWrongSignature.test13(holder);
}
- @DontCompile
- public void test13_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test13")
+ public void test13_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test13(null);
} else {
// Make sure klass is resolved
@@ -663,9 +659,9 @@ public void test14(Object holder) {
GetUnresolvedInlineFieldWrongSignature.test14(holder);
}
- @DontCompile
- public void test14_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test14")
+ public void test14_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test14(null);
} else {
// Make sure klass is resolved
@@ -705,9 +701,9 @@ public void test15(Object holder) {
GetUnresolvedInlineFieldWrongSignature.test15(holder);
}
- @DontCompile
- public void test15_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test15")
+ public void test15_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test15(null);
} else {
// Make sure klass is resolved
@@ -742,9 +738,9 @@ public Object test16(boolean warmup) {
return GetUnresolvedInlineFieldWrongSignature.test16(warmup);
}
- @DontCompile
- public void test16_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test16")
+ public void test16_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test16(true);
} else {
// Make sure klass is resolved
@@ -774,9 +770,9 @@ public Object test17(boolean warmup) {
return GetUnresolvedInlineFieldWrongSignature.test17(warmup);
}
- @DontCompile
- public void test17_verifier(boolean warmup) {
- if (warmup && PREVENT_LOADING) {
+ @Run(test = "test17")
+ public void test17_verifier(RunInfo info) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test17(true);
} else {
// Make sure klass is resolved
@@ -814,11 +810,11 @@ public int test18(int n) {
}
}
- @DontCompile
- public void test18_verifier(boolean warmup) {
+ @Run(test = "test18")
+ public void test18_verifier(RunInfo info) {
// Make sure MyValue18Holder is loaded
MyValue18Holder holder = new MyValue18Holder();
- if (warmup && PREVENT_LOADING) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test18(0);
} else {
Asserts.assertEQ(test18(rI), 2*rI);
@@ -848,11 +844,11 @@ public int test19(int n) {
}
}
- @DontCompile
- public void test19_verifier(boolean warmup) {
+ @Run(test = "test19")
+ public void test19_verifier(RunInfo info) {
// Make sure MyValue19Holder is loaded
MyValue19Holder holder = new MyValue19Holder();
- if (warmup && PREVENT_LOADING) {
+ if (info.isWarmUp() && !info.isC2CompilationEnabled()) {
test19(0);
} else {
Asserts.assertEQ(test19(rI), rI);
@@ -878,8 +874,8 @@ public MyValue20 test20() {
return new MyValue20();
}
- @DontCompile
- public void test20_verifier(boolean warmup) {
+ @Run(test = "test20")
+ public void test20_verifier(RunInfo info) {
MyValue20 vt = test20();
Asserts.assertEQ(vt.obj, null);
}
diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestWithfieldC1.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestWithfieldC1.java
index 01be7861736..17b927ee1ce 100644
--- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestWithfieldC1.java
+++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestWithfieldC1.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2021, 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
@@ -21,70 +21,47 @@
* questions.
*/
-
package compiler.valhalla.inlinetypes;
-import java.lang.invoke.*;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-
import jdk.test.lib.Asserts;
+import compiler.lib.ir_framework.*;
/*
* @test
* @key randomness
* @summary Verify that C1 performs escape analysis before optimizing withfield bytecode to putfield.
- * @library /testlibrary /test/lib /compiler/whitebox /
+ * @library /test/lib /
* @requires os.simpleArch == "x64"
* @compile -XDallowWithFieldOperator TestWithfieldC1.java
- * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform
- * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
- * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI
- * compiler.valhalla.inlinetypes.InlineTypeTest
- * compiler.valhalla.inlinetypes.TestWithfieldC1
+ * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestWithfieldC1
*/
-public class TestWithfieldC1 extends InlineTypeTest {
- public static final int C1 = COMP_LEVEL_SIMPLE;
- public static final int C2 = COMP_LEVEL_FULL_OPTIMIZATION;
-
- public static void main(String[] args) throws Throwable {
- TestWithfieldC1 test = new TestWithfieldC1();
- test.run(args, FooValue.class);
- }
- @Override
- public int getNumScenarios() {
- return 5;
- }
-
- @Override
- public String[] getVMParameters(int scenario) {
- switch (scenario) {
- case 0: return new String[] { // C1 only
- "-XX:TieredStopAtLevel=1",
- "-XX:+TieredCompilation",
- };
- case 1: return new String[] { // C2 only. (Make sure the tests are correctly written)
- "-XX:TieredStopAtLevel=4",
- "-XX:-TieredCompilation",
- };
- case 2: return new String[] { // interpreter only
- "-Xint",
- };
- case 3: return new String[] {
- // Xcomp Only C1.
- "-XX:TieredStopAtLevel=1",
- "-XX:+TieredCompilation",
- "-Xcomp",
- };
- case 4: return new String[] {
- // Xcomp Only C2.
- "-XX:TieredStopAtLevel=4",
- "-XX:-TieredCompilation",
- "-Xcomp",
- };
- }
- return null;
+@ForceCompileClassInitializer
+public class TestWithfieldC1 {
+
+ public static void main(String[] args) {
+ final Scenario[] scenarios = {
+ new Scenario(0, // C1 only
+ "-XX:TieredStopAtLevel=1",
+ "-XX:+TieredCompilation"),
+ new Scenario(1, // C2 only. (Make sure the tests are correctly written)
+ "-XX:TieredStopAtLevel=4",
+ "-XX:-TieredCompilation"),
+ new Scenario(2, // interpreter only
+ "-Xint"),
+ new Scenario(3, // Xcomp Only C1.
+ "-XX:TieredStopAtLevel=1",
+ "-XX:+TieredCompilation",
+ "-Xcomp"),
+ new Scenario(4, // Xcomp Only C2.
+ "-XX:TieredStopAtLevel=4",
+ "-XX:-TieredCompilation",
+ "-Xcomp")
+ };
+
+ InlineTypes.getFramework()
+ .addScenarios(scenarios)
+ .start();
}
static FooValue.ref foo_static;
@@ -214,19 +191,19 @@ static void validate_foo_static_and(FooValue v) {
}
// escape with putstatic
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public FooValue test1() {
return FooValue.test1();
}
- @DontCompile
- public void test1_verifier(boolean warmup) {
+ @Run(test = "test1")
+ public void test1_verifier() {
FooValue v = test1();
validate_foo_static_and(v);
}
// escape with putfield
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public FooValue test2() {
FooValue v = FooValue.default;
@@ -239,8 +216,8 @@ public FooValue test2() {
return v;
}
- @DontCompile
- public void test2_verifier(boolean warmup) {
+ @Run(test = "test2")
+ public void test2_verifier() {
foo_instance = null;
FooValue v = test2();
Asserts.assertEQ(foo_instance.x, 1);
@@ -250,52 +227,52 @@ public void test2_verifier(boolean warmup) {
}
// escape with function call
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public FooValue test3() {
return FooValue.test3();
}
- @DontCompile
- public void test3_verifier(boolean warmup) {
+ @Run(test = "test3")
+ public void test3_verifier() {
foo_static = null;
FooValue v = test3();
validate_foo_static_and(v);
}
// escape and then branch backwards
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public FooValue test4() {
return FooValue.test4();
}
- @DontCompile
- public void test4_verifier(boolean warmup) {
+ @Run(test = "test4")
+ public void test4_verifier() {
foo_static = null;
FooValue v = test4();
validate_foo_static_and(v);
}
// escape using a different local variable
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public FooValue test5() {
return FooValue.test5();
}
- @DontCompile
- public void test5_verifier(boolean warmup) {
+ @Run(test = "test5")
+ public void test5_verifier() {
foo_static = null;
FooValue v = test5();
validate_foo_static_and(v);
}
// escape using aastore
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public FooValue test6() {
return FooValue.test6();
}
- @DontCompile
- public void test6_verifier(boolean warmup) {
+ @Run(test = "test6")
+ public void test6_verifier() {
foo_static_arr[0] = null;
FooValue v = test6();
Asserts.assertEQ(foo_static_arr[0].x, 1);
@@ -305,33 +282,33 @@ public void test6_verifier(boolean warmup) {
}
// Copying a value into different local slots -- disable withfield optimization
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public FooValue test7() {
return FooValue.test7();
}
- @DontCompile
- public void test7_verifier(boolean warmup) {
+ @Run(test = "test7")
+ public void test7_verifier() {
FooValue v = test7();
Asserts.assertEQ(v.x, 1);
Asserts.assertEQ(v.y, 1);
}
// escape by invoking non-static method
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public FooValue test8() {
return FooValue.test8();
}
- @DontCompile
- public void test8_verifier(boolean warmup) {
+ @Run(test = "test8")
+ public void test8_verifier() {
foo_static = null;
FooValue v = test8();
validate_foo_static_and(v);
}
// duplicate reference with local variables
- @Test(compLevel=C1)
+ @Test(compLevel = CompLevel.C1_SIMPLE)
public FooValue test9() {
FooValue v = FooValue.default;
@@ -350,8 +327,8 @@ public FooValue test9() {
return v;
}
- @DontCompile
- public void test9_verifier(boolean warmup) {
+ @Run(test = "test9")
+ public void test9_verifier() {
foo_instance = null;
FooValue v = test9();
Asserts.assertEQ(foo_instance.x, 3);
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/BaseTestExample.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/BaseTestExample.java
new file mode 100644
index 00000000000..5307cf5ed6b
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/BaseTestExample.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2021, 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.examples;
+
+import compiler.lib.ir_framework.*;
+import compiler.lib.ir_framework.test.TestVM; // Only used for Javadocs
+
+/*
+ * @test
+ * @summary Example test to use the new test framework.
+ * @library /test/lib /
+ * @run driver ir_framework.examples.BaseTestExample
+ */
+
+/**
+ * If there is no warm up specified the Test Framework will do the following:
+ *
+ * Invoke @Test method {@link TestVM#WARMUP_ITERATIONS} many times.
+ * Then do compilation of @Test method. (**)
+ * Invoke @Test method once again
+ *
+ *
+ *
+ * Configurable things for simple tests (no @Run or @Check) at @Test method:
+ *
+ * compLevel: Specify at which compilation level the test should be compiled by the framework at step (**).
+ * If {@link CompLevel#WAIT_FOR_COMPILATION} is specified, the framework will continue invoke the
+ * method until HotSpot compiles it. If it is not compiled after 10s, an exception is thrown.
+ * @Warmup: Change warm-up iterations of test (defined by default by TestVM.WARMUP_ITERATIONS)
+ * @Arguments: If a @Test method specifies arguments, you need to provide arguments by using @Arguments such
+ * that the framework knows how to call the method. If you need more complex values, use @Run.
+ * @IR: Arbitrary number of @IR rules.
+ *
+ *
+ * @see Test
+ * @see Arguments
+ * @see Warmup
+ * @see TestFramework
+ */
+public class BaseTestExample {
+ int iFld;
+
+ public static void main(String[] args) {
+ TestFramework.run(); // equivalent to TestFramework.run(BaseTestExample.class)
+ }
+
+ // Test without arguments.
+ @Test
+ public void mostBasicTest() {
+ iFld = 42;
+ }
+
+ // Test with arguments. Use Argument class to choose a value.
+ // Object arguments need to have an associated default constructor in its class.
+ @Test
+ @Arguments({Argument.DEFAULT, Argument.MAX})
+ public void basicTestWithArguments(int x, long y) {
+ iFld = x;
+ }
+
+ // @Warmup needs to be positive or zero. In case of zero, the method is directly compiled (simulated -Xcomp).
+ @Test
+ @Arguments({Argument.DEFAULT, Argument.MAX})
+ @Warmup(100)
+ public void basicTestWithDifferentWarmup(int x, long y) {
+ iFld = x;
+ }
+}
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/CheckedTestExample.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/CheckedTestExample.java
new file mode 100644
index 00000000000..206b7d9d185
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/CheckedTestExample.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2021, 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.examples;
+
+import compiler.lib.ir_framework.*;
+import compiler.lib.ir_framework.test.TestVM; // Only used for Javadocs
+
+/*
+ * @test
+ * @summary Example test to use the new test framework.
+ * @library /test/lib /
+ * @run driver ir_framework.examples.CheckedTestExample
+ */
+
+/**
+ * If there is no non-default warm-up specified, the Test Framework will do the following:
+ *
+ * Invoke @Test method {@link TestVM#WARMUP_ITERATIONS} many times.
+ * By default, after each invocation, the @Check method of the @Test method is invoked. This can be disabled
+ * by using {@link CheckAt#COMPILED}
+ * After the warm-up, the @Test method is compiled.
+ * Invoke @Test method once again and then always invoke the @Check method once again.
+ *
+ *
+ *
+ * Configurable things for checked tests:
+ *
+ * At @Test method:
+ *
+ * @Warmup: Change warm-up iterations of test (defined by default by TestVM.WARMUP_ITERATIONS)
+ * @Arguments: If a @Test method specifies arguments, you need to provide arguments by using @Arguments
+ * such that the framework knows how to call the method. If you need more complex values, use a
+ * custom run test with @Run.
+ * @IR: Arbitrary number of @IR rules.
+ *
+ * At @Check method:
+ *
+ *
+ *
+ * @see Check
+ * @see Test
+ * @see Arguments
+ * @see Warmup
+ * @see TestFramework
+ */
+public class CheckedTestExample {
+
+ public static void main(String[] args) {
+ TestFramework.run(); // equivalent to TestFramework.run(CheckedTestExample.class)
+ }
+
+ @Test
+ @Arguments(Argument.DEFAULT) // As with normal tests, you need to tell the framework what the argument is.
+ @Warmup(100) // As with normal tests, you can specify the warmup iterations.
+ public int test(int x) {
+ return 42;
+ }
+
+ // Check method for test(). Invoked directly after test() by the Test Framework.
+ @Check(test = "test") // Specify the @Test method for which this method is a check.
+ public void basicCheck() {
+ // Do some checks after an invocation.
+ }
+
+ @Test
+ public int test2() {
+ return 42;
+ }
+
+ // This version of @Check passes the return value from test2() as an argument.
+ // The return type and the parameter type must match.
+ @Check(test = "test2")
+ public void checkWithReturn(int returnValue) {
+ // Do some checks after an invocation.
+ if (returnValue != 42) {
+ throw new RuntimeException("Must match");
+ }
+ }
+
+ @Test
+ public int test3() {
+ return 42;
+ }
+
+ // This version of @Check passes a TestInfo object to the check which contains some additional information about the test.
+ @Check(test = "test3")
+ public void checkWithTestInfo(TestInfo info) {
+ // Do some checks after an invocation. Additional queries with TestInfo.
+ if (!info.isWarmUp()) {
+ // ...
+ }
+ }
+
+ @Test
+ public int test4() {
+ return 42;
+ }
+
+ // This version of @Check passes the return value and a TestInfo object to the check which contains some additional
+ // information about the test. The order of the arguments is important. The return value must come first and the
+ // the TestInfo parameter second. Any other combination or use of different arguments are forbidden for @Check methods.
+ @Check(test = "test4")
+ public void checkWithReturnAndTestInfo(int returnValue, TestInfo info) {
+ // Do some checks after an invocation. Additional queries with TestInfo.
+ if (returnValue != 42) {
+ throw new RuntimeException("Must match");
+ }
+ if (!info.isWarmUp()) {
+ // ...
+ }
+ }
+
+ @Test
+ public int test5() {
+ return 42;
+ }
+
+ // Check method for test5() is only invoked once warmup is finished and test() has been compiled by the Test Framework.
+ @Check(test = "test5", when = CheckAt.COMPILED) // Specify the @Test method for which this method is a check.
+ public void checkAfterCompiled(TestInfo info) {
+ // Do some checks after compilation.
+ TestFramework.assertCompiled(info.getTest()); // Test is compiled by framework after warm-up.
+ }
+
+}
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/CustomRunTestExample.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/CustomRunTestExample.java
new file mode 100644
index 00000000000..3565f3def3d
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/CustomRunTestExample.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2021, 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.examples;
+
+import compiler.lib.ir_framework.*;
+import compiler.lib.ir_framework.test.TestVM; // Only used for Javadocs
+
+/*
+ * @test
+ * @summary Example test to use the new test framework.
+ * @library /test/lib /
+ * @run driver ir_framework.examples.CustomRunTestExample
+ */
+
+/**
+ * If there is no warm-up specified, the Test Framework will do the following:
+ *
+ * Invoke @Run method {@link TestVM#WARMUP_ITERATIONS} many times. Note that the @Run method
+ * is responsible to invoke the @Test methods to warm it up properly. This is not done by the framework. Not
+ * invoking a @Test method will result in an -Xcomp like compilation of the method as there is no profile
+ * information for it. The @Run method can do any arbitrary argument setup and return value verification and
+ * can invoke the @Test methods multiple times in a single invocation of the @Run method or even skip some
+ * test invocations.
+ * After the warm-up, the @Test methods are compiled (there can be multiple @Test methods).
+ * Invoke the @Run method once again.
+ *
+ *
+ *
+ * Configurable things for custom run tests:
+ *
+ * At @Test methods:
+ *
+ * @IR: Arbitrary number of @IR rules.
+ * No @Warmup, this must be set at @Run method.
+ * No @Arguments, the arguments are set by @Run method.
+ *
+ * At @Run method:
+ *
+ * @Warmup: Change warm-up iterations of @Run method (defined by default by
+ * TestVM.WARMUP_ITERATIONS)
+ * {@link Run#test}: Specify any number of @Test methods. They cannot be shared with other @Check or @Run
+ * methods.
+ * {@link Run#mode}: Choose between normal invocation as described above or {@link RunMode#STANDALONE}.
+ * STANDALONE only invokes the @Run method once without warm-up or a compilation by the
+ * Test Framework. The only thing done by the framework is the verification of any @IR
+ * rules afterwards. The STANDALONE @Run method needs to make sure that a C2 compilation
+ * is reliably triggered if there are any @IR rules.
+ * No @IR annotations
+ *
+ *
+ *
+ * @see Run
+ * @see Test
+ * @see RunMode
+ * @see TestFramework
+ */
+public class CustomRunTestExample {
+
+ public static void main(String[] args) {
+ TestFramework.run(); // equivalent to TestFramework.run(CustomRunTestExample.class)
+ }
+
+ @Test
+ public int test(int x) {
+ return x;
+ }
+
+ // Run method for test(). Invoked directly by Test Framework instead of test().
+ // Can do anything you like. It's also possible to skip or do multiple invocations of test()
+ @Run(test = "test") // Specify the @Test method for which this method is a runner.
+ public void basicRun() {
+ int returnValue = test(34);
+ if (returnValue != 34) {
+ throw new RuntimeException("Must match");
+ }
+ }
+
+ @Test
+ public int test2(int x) {
+ return x;
+ }
+
+ // This version of @Run passes the RunInfo object as an argument. No other arguments and combiniations are allowed.
+ @Run(test = "test2")
+ public void runWithRunInfo(RunInfo info) {
+ // We could also skip some invocations. This might have an influence on possible @IR rules, need to be careful.
+ if (info.getRandom().nextBoolean()) {
+ int returnValue = test(34);
+ if (returnValue != 34) {
+ throw new RuntimeException("Must match");
+ }
+ }
+ }
+
+ @Test
+ public int test3(int x) {
+ return x;
+ }
+
+ // This version of @Run uses a user defined @Warmup.
+ @Run(test = "test3")
+ @Warmup(100)
+ public void runWithWarmUp() {
+ int returnValue = test3(34);
+ if (returnValue != 34) {
+ throw new RuntimeException("Must match");
+ }
+ }
+
+ @Test
+ public int test4(int x) {
+ return x;
+ }
+
+ // This version of @Run is only invoked once by the Test Framework. There is no warm-up and no compilation done
+ // by the Test Framework. The only thing done by the framework is @IR rule verification.
+ @Run(test = "test4", mode = RunMode.STANDALONE)
+ public void runOnlyOnce() {
+ int returnValue = test4(34);
+ if (returnValue != 34) {
+ throw new RuntimeException("Must match");
+ }
+ }
+
+ @Test
+ public int test5(int x) {
+ return x;
+ }
+
+ @Test
+ public int test6(int x) {
+ return x;
+ }
+
+ // This version of @Run can run multiple test methods and get them IR checked as part of this custom run test.
+ @Run(test = {"test5", "test6"})
+ public void runMultipleTests() {
+ int returnValue = test5(34);
+ if (returnValue != 34) {
+ throw new RuntimeException("Must match");
+ }
+ returnValue = test6(42);
+ if (returnValue != 42) {
+ throw new RuntimeException("Must match");
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/IRExample.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/IRExample.java
new file mode 100644
index 00000000000..8d8e5b31bc1
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/examples/IRExample.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2021, 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.examples;
+
+import compiler.lib.ir_framework.*;
+import compiler.lib.ir_framework.driver.IRViolationException;
+
+/*
+ * @test
+ * @summary Example test to use the new test framework.
+ * @library /test/lib /
+ * @run driver ir_framework.examples.IRExample
+ */
+
+/**
+ * Multiple @IR rules can be specified at @Test methods. The framework performs a regex based match on the PrintIdeal
+ * and PrintOptoAssembly of the run test VM. Some default string regexes for IR nodes are defined in the framework
+ * IRNode class. There are two kinds of checks:
+ *
+ * {@link IR#failOn}: One or more (IR node) regexes that are not allowed to occur in the IR (neither in
+ * PrintIdeal nor in PrintOptoAssembly)
+ * {@link IR#counts}: One or more regexes-count pairs specifies how often an (IR node) regex must be found in
+ * PrintIdeal and PrintOptoAssembly.
+ *
+ *
+ *
+ * One might also want to restrict the application of certain @IR rules depending on the used flags in the test VM.
+ * These could be flags defined by the user or by JTreg. In the latter case, the flags must be whitelisted (see
+ * {@link TestFramework}) most of them should not have an impact on the IR except for different GC flags which should
+ * be considered) to enable a verification by the framework (see below). The @IR rules thus have an option to restrict
+ * their application:
+ *
+ * {@link IR#applyIf}: Only apply a rule if a flag has a certain value
+ * {@link IR#applyIfNot}: Only apply a rule if a flag has NOT a certain value (inverse of applyIf)
+ * {@link IR#applyIfAnd}: Only apply a rule if all flags have the specified value
+ * {@link IR#applyIfOr}: Only apply a rule if at least one flag has the specified value
+ *
+ *
+ *
+ * The framework, however, does not perform the verification if:
+ *
+ * -DVerifyIR=false is used
+ * The test is run with a non-debug build
+ * -Xcomp, -Xint, -XX:-UseCompile, -XX:CompileThreshold, -DFlipC1C2=true, or -DExcludeRandom=true are used.
+ * JTreg specifies non-whitelisted flags as VM and/or Javaoptions (could change the IR in an unexpected way)
+ *
+ *
+ * @see IR
+ * @see Test
+ * @see TestFramework
+ */
+// This test is expected to fail when run with JTreg.
+public class IRExample {
+ int iFld, iFld2, iFld3;
+ public static void main(String[] args) {
+ TestFramework.run(); // First run tests from IRExample
+ try {
+ TestFramework.run(FailingExamples.class); // Secondly, run tests from FailingExamples
+ } catch (IRViolationException e) {
+ // Expected. Check stderr/stdout to see how IR failures are reported (always printed, regardless if
+ // exception is thrown or not). Uncomment the "throw" statement below to get a completely failing test.
+ //throw e;
+ }
+ }
+
+ // Rules with failOn constraint which all pass
+ @Test
+ @IR(failOn = IRNode.LOAD) // 1 default regex
+ @IR(failOn = {IRNode.LOAD, IRNode.LOOP}) // 2 default regexes
+ @IR(failOn = {IRNode.LOAD, "some regex that does not occur"}) // 1 default regex and a user-defined regex
+ // Rule with special configurable default regexes. All regexes with a "_OF" postfix in IR node expect a
+ // second string specifying an additional required information.
+ @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld2", IRNode.LOAD, IRNode.STORE_OF_CLASS, "Foo"})
+ // Only apply this rule if the VM flag UseZGC is true
+ @IR(applyIf = {"UseZGC", "true"}, failOn = IRNode.LOAD)
+ // We can also use comparators (<, <=, >, >=, !=, =) to restrict the rules.
+ // This rule is only applied if the loop unroll limit is 10 or greater.
+ @IR(applyIf = {"LoopUnrollLimit", ">= 10"}, failOn = IRNode.LOAD)
+ public void goodFailOn() {
+ iFld = 42; // No load, no loop, no store to iFld2, no store to class Foo
+ }
+
+ // Rules with counts constraint which all pass
+ @Test
+ @IR(counts = {IRNode.STORE, "2"}) // 1 default regex
+ @IR(counts = {IRNode.LOAD, "0"}) // equivalent to failOn = IRNode.LOAD
+ @IR(counts = {IRNode.STORE, "2",
+ IRNode.LOAD, "0"}) // 2 default regexes
+ @IR(counts = {IRNode.STORE, "2",
+ "some regex that does not occur", "0"}) // 1 default regex and a user-defined regex
+ // Rule with special configurable default regexes. All regexes with a "_OF" postfix in IR node expect a
+ // second string specifying an additional required information.
+ @IR(counts = {IRNode.STORE_OF_FIELD, "iFld", "1",
+ IRNode.STORE, "2",
+ IRNode.STORE_OF_CLASS, "IRExample", "2"})
+ public void goodCounts() {
+ iFld = 42; // No load, store to iFld in class IRExample
+ iFld2 = 42; // No load, store to iFld2 in class IRExample
+ }
+
+ // @IR rules can also specify both type of checks in the same rule
+ @Test
+ @IR(failOn = {IRNode.ALLOC,
+ IRNode.LOOP},
+ counts = {IRNode.LOAD, "2",
+ IRNode.LOAD_OF_FIELD, "iFld2", "1",
+ IRNode.LOAD_OF_CLASS, "IRExample", "2"})
+ public void mixFailOnAndCounts() {
+ iFld = iFld2;
+ iFld2 = iFld3;
+ }
+}
+
+class FailingExamples {
+ int iFld2, iFld3;
+ IRExample irExample = new IRExample();
+
+ // Rules with failOn constraint which all fail.
+ @Test
+ @IR(failOn = IRNode.STORE)
+ @IR(failOn = {IRNode.STORE, IRNode.LOOP}) // LOOP regex not found but STORE regex, letting the rule fail
+ @IR(failOn = {IRNode.LOOP, IRNode.STORE}) // Order does not matter
+ @IR(failOn = {IRNode.STORE, IRNode.LOAD}) // STORE and LOAD regex found, letting the rule fail
+ @IR(failOn = {"LoadI"}) // LoadI can be found in PrintIdeal letting the rule fail
+ // Store to iFld, store, and store to class IRExample, all 3 regexes found letting the rule fail
+ @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld", IRNode.STORE, IRNode.STORE_OF_CLASS, "IRExample"})
+ public void badFailOn() {
+ irExample.iFld = iFld2; // Store to iFld in class IRExample, load from iFld2
+ }
+
+
+ // Rules with counts constraint which all fail
+ @Test
+ @IR(counts = {IRNode.STORE, "1"}) // There are 2 stores
+ @IR(counts = {IRNode.LOAD, "0"}) // equivalent to failOn = IRNode.LOAD, there is 1 load
+ @IR(counts = {IRNode.STORE, "1",
+ IRNode.LOAD, "1"}) // first constraint holds (there is 1 load) but 2 stores, letting this rule fail
+ @IR(counts = {IRNode.LOAD, "1",
+ IRNode.STORE, "1"}) // order does not matter
+ @IR(counts = {"some regex that does not occur", "1"}) // user-defined regex does not occur once
+ // Rule with special configurable default regexes. All regexes with a "_OF" postfix in IR node expect a
+ // second string specifying an additional required information.
+ @IR(counts = {IRNode.STORE_OF_FIELD, "iFld", "2", // Only one store to iFld
+ IRNode.LOAD, "2", // Only 1 load
+ IRNode.STORE_OF_CLASS, "Foo", "1"}) // No store to class Foo
+ public void badCounts() {
+ irExample.iFld = iFld3; // No load, store to iFld in class IRExample
+ iFld2 = 42; // No load, store to iFld2 in class IRExample
+ }
+}
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/README.md b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/README.md
new file mode 100644
index 00000000000..9a1a2557bc1
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/README.md
@@ -0,0 +1,5 @@
+# Framework internal tests
+This folder contains tests which test the functionality of the framework. These are run with JTreg and are part of tier testing. All tests are run without additional VM and Javaopts flags. These tests must pass whenever the framework is updated.
+
+Additional testing should be performed with the converted Valhalla tests to make sure a changeset is correct (these are part of the Valhalla CI).
+
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestAccessModifiers.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestAccessModifiers.java
new file mode 100644
index 00000000000..47bc9741b60
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestAccessModifiers.java
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2021, 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.*;
+
+/*
+ * @test
+ * @requires vm.flagless
+ * @summary Test different access modifiers an make sure, the framework can access all methods.
+ * @library /test/lib /
+ * @run driver ir_framework.tests.TestAccessModifiers
+ */
+
+public class TestAccessModifiers {
+ public static void main(String[] args) {
+ TestFramework.run(PackagePrivate.class);
+ }
+}
+
+class PackagePrivate {
+ @Test
+ public void test() {
+ }
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void test2(int x) {
+ }
+
+ @Test
+ public static int staticPublicPrivate() {
+ return 42;
+ }
+
+ @Check(test = "staticPublicPrivate")
+ private void staticPublicPrivateCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ protected static int staticProtectedPrivate() {
+ return 42;
+ }
+
+ @Check(test = "staticProtectedPrivate")
+ private void staticProtectedPrivateCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ static int staticDefaultPrivate() {
+ return 42;
+ }
+
+ @Check(test = "staticDefaultPrivate")
+ private void staticDefaultPrivateCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ private static int staticPrivatePrivate() {
+ return 42;
+ }
+
+ @Check(test = "staticPrivatePrivate")
+ private void staticPrivatePrivateCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ public static int staticPublicDefault() {
+ return 42;
+ }
+
+ @Check(test = "staticPublicDefault")
+ void staticPublicDefaultCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ protected static int staticProtectedDefault() {
+ return 42;
+ }
+
+ @Check(test = "staticProtectedDefault")
+ void staticProtectedDefaultCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ static int staticDefaultDefault() {
+ return 42;
+ }
+
+ @Check(test = "staticDefaultDefault")
+ void staticDefaultDefaultCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ private static int staticPrivateDefault() {
+ return 42;
+ }
+
+ @Check(test = "staticPrivateDefault")
+ void staticPrivateDefaultCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ public static int staticPublicProtected() {
+ return 42;
+ }
+
+ @Check(test = "staticPublicProtected")
+ protected void staticPublicProtectedCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ protected static int staticProtectedProtected() {
+ return 42;
+ }
+
+ @Check(test = "staticProtectedProtected")
+ protected void staticProtectedProtectedCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ static int staticDefaultProtected() {
+ return 42;
+ }
+
+ @Check(test = "staticDefaultProtected")
+ protected void staticDefaultProtectedCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ private static int staticPrivateProtected() {
+ return 42;
+ }
+
+ @Check(test = "staticPrivateProtected")
+ protected void staticPrivateProtectedCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ public static int staticPublicPublic() {
+ return 42;
+ }
+
+ @Check(test = "staticPublicPublic")
+ public void staticPublicPublicCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ protected static int staticProtectedPublic() {
+ return 42;
+ }
+
+ @Check(test = "staticProtectedPublic")
+ public void staticProtectedPublicCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ static int staticDefaultPublic() {
+ return 42;
+ }
+
+ @Check(test = "staticDefaultPublic")
+ public void staticDefaultPublicCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ private static int staticPrivatePublic() {
+ return 42;
+ }
+
+ @Check(test = "staticPrivatePublic")
+ public void staticPrivatePublicCheck(int retValue) {
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ static int staticDefaultPrivate2() {
+ return 42;
+ }
+
+ @Run(test = "staticDefaultPrivate2")
+ private void staticDefaultPrivateRun() {
+ int retValue = staticDefaultPrivate2();
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ private static int staticPrivatePrivate2() {
+ return 42;
+ }
+
+ @Run(test = "staticPrivatePrivate2")
+ private void staticPrivatePrivateRun() {
+ int retValue = staticPrivatePrivate2();
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ public static int staticPublicDefault2() {
+ return 42;
+ }
+
+ @Run(test = "staticPublicDefault2")
+ void staticPublicDefaultRun() {
+ int retValue = staticPublicDefault2();
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ protected static int staticProtectedDefault2() {
+ return 42;
+ }
+
+ @Run(test = "staticProtectedDefault2")
+ void staticProtectedDefaultRun() {
+ int retValue = staticProtectedDefault2();
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ static int staticDefaultDefault2() {
+ return 42;
+ }
+
+ @Run(test = "staticDefaultDefault2")
+ void staticDefaultDefaultRun() {
+ int retValue = staticDefaultDefault2();
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ private static int staticPrivateDefault2() {
+ return 42;
+ }
+
+ @Run(test = "staticPrivateDefault2")
+ void staticPrivateDefaultRun() {
+ int retValue = staticPrivateDefault2();
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ public static int staticPublicProtected2() {
+ return 42;
+ }
+
+ @Run(test = "staticPublicProtected2")
+ protected void staticPublicProtectedRun() {
+ int retValue = staticPublicProtected2();
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ protected static int staticProtectedProtected2() {
+ return 42;
+ }
+
+ @Run(test = "staticProtectedProtected2")
+ protected void staticProtectedProtectedRun() {
+ int retValue = staticProtectedProtected2();
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ static int staticDefaultProtected2() {
+ return 42;
+ }
+
+ @Run(test = "staticDefaultProtected2")
+ protected void staticDefaultProtectedRun() {
+ int retValue = staticDefaultProtected2();
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ private static int staticPrivateProtected2() {
+ return 42;
+ }
+
+ @Run(test = "staticPrivateProtected2")
+ protected void staticPrivateProtectedRun() {
+ int retValue = staticPrivateProtected2();
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ public static int staticPublicPublic2() {
+ return 42;
+ }
+
+ @Run(test = "staticPublicPublic2")
+ public void staticPublicPublicRun() {
+ int retValue = staticPublicPublic2();
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ protected static int staticProtectedPublic2() {
+ return 42;
+ }
+
+ @Run(test = "staticProtectedPublic2")
+ public void staticProtectedPublicRun() {
+ int retValue = staticProtectedPublic2();
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ static int staticDefaultPublic2() {
+ return 42;
+ }
+
+ @Run(test = "staticDefaultPublic2")
+ public void staticDefaultPublicRun() {
+ int retValue = staticDefaultPublic2();
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+ @Test
+ private static int staticPrivatePublic2() {
+ return 42;
+ }
+
+ @Run(test = "staticPrivatePublic2")
+ public void staticPrivatePublicRun() {
+ int retValue = staticPrivatePublic2();
+ if (retValue != 42) {
+ throw new RuntimeException("Needs to be 42");
+ }
+ }
+
+
+}
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestBadFormat.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestBadFormat.java
new file mode 100644
index 00000000000..4eb0cba6f14
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestBadFormat.java
@@ -0,0 +1,1003 @@
+/*
+ * Copyright (c) 2021, 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.Compiler;
+import compiler.lib.ir_framework.shared.TestFormatException;
+import jdk.test.lib.Asserts;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/*
+ * @test
+ * @requires vm.debug == true & vm.compiler2.enabled & vm.flagless
+ * @summary Test test format violations.
+ * @library /test/lib /
+ * @run driver ir_framework.tests.TestBadFormat
+ */
+
+public class TestBadFormat {
+
+ public static void main(String[] args) {
+ expectTestFormatException(BadNoTests.class);
+ expectTestFormatException(BadArgumentsAnnotation.class);
+ expectTestFormatException(BadOverloadedMethod.class);
+ expectTestFormatException(BadCompilerControl.class);
+ expectTestFormatException(BadWarmup.class);
+ expectTestFormatException(BadBaseTests.class);
+ expectTestFormatException(BadRunTests.class);
+ expectTestFormatException(BadCheckTest.class);
+ expectTestFormatException(BadIRAnnotations.class);
+ expectTestFormatException(BadInnerClassTest.class);
+ expectTestFormatException(BadCompileClassInitializer.class, BadCompileClassInitializerHelper1.class,
+ BadCompileClassInitializerHelper2.class, BadCompileClassInitializerHelper3.class);
+ }
+
+ private static void expectTestFormatException(Class> clazz, Class>... helpers) {
+ try {
+ if (helpers == null) {
+ TestFramework.run(clazz);
+ } else {
+ new TestFramework(clazz).addHelperClasses(helpers).start();
+ }
+ } catch (Exception e) {
+ if (!(e instanceof TestFormatException)) {
+ e.printStackTrace();
+ Asserts.fail("Unexpected exception", e);
+ }
+ String msg = e.getMessage();
+ Violations violations = getViolations(clazz, helpers);
+ violations.getFailedMethods().forEach(
+ f -> Asserts.assertTrue(msg.contains(f),
+ "Could not find " + f + " in violations" + System.lineSeparator() + msg));
+ Pattern pattern = Pattern.compile("Violations \\((\\d+)\\)");
+ Matcher matcher = pattern.matcher(msg);
+ Asserts.assertTrue(matcher.find(), "Could not find violations in" + System.lineSeparator() + msg);
+ int violationCount = Integer.parseInt(matcher.group(1));
+ Asserts.assertEQ(violationCount, violations.getViolationCount(), msg);
+ return;
+ }
+ throw new RuntimeException("Should catch an exception");
+ }
+
+ private static Violations getViolations(Class> clazz, Class>... helpers) {
+ Violations violations = new Violations();
+ collectViolations(clazz, violations);
+ if (helpers != null) {
+ Arrays.stream(helpers).forEach(c -> collectViolations(c, violations));
+ }
+ return violations;
+ }
+
+ private static void collectViolations(Class> clazz, Violations violations) {
+ getViolationsOfClass(clazz, violations);
+ for (Class> c : clazz.getDeclaredClasses()) {
+ getViolationsOfClass(c, violations);
+ }
+ }
+
+ private static void getViolationsOfClass(Class> clazz, Violations violations) {
+ ClassFail classFail = clazz.getDeclaredAnnotation(ClassFail.class);
+ if (classFail != null) {
+ violations.addFail(clazz);
+ }
+ for (Method m : clazz.getDeclaredMethods()) {
+ NoFail noFail = m.getDeclaredAnnotation(NoFail.class);
+ if (noFail == null) {
+ FailCount failCount = m.getDeclaredAnnotation(FailCount.class);
+ if (failCount != null) {
+ violations.addFail(m, failCount.value());
+ } else {
+ violations.addFail(m, 1);
+ }
+ } else {
+ // Cannot define both annotation at the same method.
+ Asserts.assertEQ(m.getDeclaredAnnotation(FailCount.class), null);
+ }
+ }
+ }
+
+}
+
+// Specify at least one @Test
+@ClassFail
+class BadNoTests {
+
+}
+
+class BadArgumentsAnnotation {
+
+ @Test
+ public void noArgAnnotation(int a) {}
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void argNumberMismatch(int a, int b) {}
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void argNumberMismatch2() {}
+
+ @Test
+ @Arguments(Argument.NUMBER_42)
+ public void notBoolean(boolean a) {}
+
+ @Test
+ @Arguments(Argument.NUMBER_MINUS_42)
+ public void notBoolean2(boolean a) {}
+
+ @Test
+ @Arguments(Argument.TRUE)
+ public void notNumber(int a) {}
+
+ @Test
+ @Arguments(Argument.FALSE)
+ public void notNumber2(int a) {}
+
+ @Test
+ @Arguments(Argument.BOOLEAN_TOGGLE_FIRST_TRUE)
+ public void notNumber3(int a) {}
+
+ @Test
+ @Arguments(Argument.BOOLEAN_TOGGLE_FIRST_FALSE)
+ public void notNumber4(int a) {}
+
+ @Test
+ @Arguments({Argument.BOOLEAN_TOGGLE_FIRST_FALSE, Argument.TRUE})
+ public void notNumber5(boolean a, int b) {}
+
+ @FailCount(2)
+ @Test
+ @Arguments({Argument.BOOLEAN_TOGGLE_FIRST_FALSE, Argument.NUMBER_42})
+ public void notNumber6(int a, boolean b) {}
+
+ @FailCount(2)
+ @Test
+ @Arguments({Argument.MIN, Argument.MAX})
+ public void notNumber7(boolean a, boolean b) {}
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void missingDefaultConstructor(ClassNoDefaultConstructor a) {}
+
+ @Test
+ @Arguments(Argument.TRUE)
+ public void wrongArgumentNumberWithRun(Object o1, Object o2) {
+ }
+
+ // Also fails: Cannot use @Arguments together with @Run
+ @Run(test="wrongArgumentNumberWithRun")
+ public void forRun() {
+ }
+
+ @Test
+ @Arguments(Argument.TRUE)
+ public void wrongArgumentNumberWithCheck(Object o1, Object o2) {
+ }
+
+ @NoFail
+ @Check(test="wrongArgumentNumberWithCheck")
+ public void forCheck() {
+ }
+}
+
+class BadOverloadedMethod {
+
+ @FailCount(0) // Combined with both sameName() below
+ @Test
+ public void sameName() {}
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void sameName(boolean a) {}
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void sameName(double a) {}
+}
+
+class BadCompilerControl {
+
+ @Test
+ @DontCompile
+ public void test1() {}
+
+ @Test
+ @ForceCompile
+ public void test2() {}
+
+ @Test
+ @DontInline
+ public void test3() {}
+
+ @Test
+ @ForceInline
+ public void test4() {}
+
+ @Test
+ @ForceInline
+ @ForceCompile
+ @DontInline
+ @DontCompile
+ public void test5() {}
+
+ @DontInline
+ @ForceInline
+ public void mix1() {}
+
+ @DontCompile
+ @ForceCompile
+ public void mix2() {}
+
+ @NoFail
+ @Test
+ public void test6() {}
+
+ @Run(test = "test6")
+ @DontCompile
+ public void notAtRun() {}
+
+ @NoFail
+ @Test
+ public void test7() {}
+
+ @Run(test = "test7")
+ @ForceCompile
+ public void notAtRun2() {}
+
+ @NoFail
+ @Test
+ public void test8() {}
+
+ @Run(test = "test8")
+ @DontInline
+ public void notAtRun3() {}
+
+ @NoFail
+ @Test
+ public void test9() {}
+
+ @Run(test = "test9")
+ @ForceInline
+ public void notAtRun4() {}
+
+ @NoFail
+ @Test
+ public void test10() {}
+
+ @Run(test = "test10")
+ @ForceInline
+ @ForceCompile
+ @DontInline
+ @DontCompile
+ public void notAtRun5() {}
+
+ @NoFail
+ @Test
+ public void test11() {}
+
+ @Check(test = "test11")
+ @DontCompile
+ public void notAtCheck() {}
+
+ @NoFail
+ @Test
+ public void test12() {}
+
+ @Check(test = "test12")
+ @ForceCompile
+ public void notAtCheck2() {}
+
+ @NoFail
+ @Test
+ public void test13() {}
+
+ @Check(test = "test13")
+ @DontInline
+ public void notAtCheck3() {}
+
+ @NoFail
+ @Test
+ public void test14() {}
+
+ @Check(test = "test14")
+ @ForceInline
+ public void notAtCheck4() {}
+
+ @NoFail
+ @Test
+ public void test15() {}
+
+ @Check(test = "test15")
+ @ForceInline
+ @ForceCompile
+ @DontInline
+ @DontCompile
+ public void notAtCheck5() {}
+
+ @ForceCompile(CompLevel.SKIP)
+ public void invalidSkip1() {}
+
+ @ForceCompile(CompLevel.WAIT_FOR_COMPILATION)
+ public void invalidWaitForCompilation() {}
+
+ @ForceCompile(CompLevel.C1_SIMPLE)
+ @DontCompile(Compiler.C1)
+ public void overlappingCompile1() {}
+
+ @ForceCompile(CompLevel.C2)
+ @DontCompile(Compiler.C2)
+ public void overlappingCompile2() {}
+
+ @ForceCompile(CompLevel.ANY)
+ @DontCompile(Compiler.C1)
+ public void invalidMix1() {}
+
+ @ForceCompile(CompLevel.ANY)
+ @DontCompile(Compiler.C2)
+ public void invalidMix2() {}
+
+ @ForceCompile(CompLevel.ANY)
+ @DontCompile
+ public void invalidMix3() {}
+}
+
+class BadWarmup {
+
+ @Warmup(10000)
+ public void warmUpNonTest() {}
+
+ @Test
+ @Warmup(1)
+ public void someTest() {}
+
+ @FailCount(0) // Combined with someTest()
+ @Run(test = "someTest")
+ @Warmup(1)
+ public void twoWarmups() {}
+
+ @Test
+ @Warmup(-1)
+ public void negativeWarmup() {}
+
+ @NoFail
+ @Test
+ public void someTest2() {}
+
+ @Run(test = "someTest2")
+ @Warmup(-1)
+ public void negativeWarmup2() {}
+
+ @NoFail
+ @Test
+ public void someTest3() {}
+
+ @FailCount(2) // Negative warmup and invoke once
+ @Run(test = "someTest3", mode = RunMode.STANDALONE)
+ @Warmup(-1)
+ public void noWarmupAtStandalone() {}
+
+ @Test(compLevel = CompLevel.C1_SIMPLE)
+ public void testNoCompLevelStandalone() {}
+
+ @Test(compLevel = CompLevel.WAIT_FOR_COMPILATION)
+ public void testNoCompLevelStandalone2() {}
+
+ @NoFail
+ @Test
+ public void someTest4() {}
+
+ @FailCount(0) // Negative warmup and invoke once
+ @Run(test = {"someTest4", "testNoCompLevelStandalone", "testNoCompLevelStandalone2"}, mode = RunMode.STANDALONE)
+ public void runNoCompLevelStandalone() {}
+}
+
+class BadBaseTests {
+ @Test
+ @Arguments(Argument.DEFAULT)
+ @FailCount(3) // No default constructor + parameter + return
+ public TestInfo cannotUseTestInfoAsParameterOrReturn(TestInfo info) {
+ return null;
+ }
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ @FailCount(3) // No default constructor + parameter + return
+ public RunInfo cannotUseRunInfoAsParameterOrReturn(RunInfo info) {
+ return null;
+ }
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ @FailCount(3) // No default constructor + parameter + return
+ public AbstractInfo cannotUseAbstractInfoAsParameterOrReturn(AbstractInfo info) {
+ return null;
+ }
+}
+
+class BadRunTests {
+ @Run(test = "runForRun2")
+ public void runForRun() {}
+
+ @Run(test = "runForRun")
+ public void runForRun2() {}
+
+ @Test
+ public void sharedByTwo() {}
+
+ @FailCount(0) // Combined with sharedByTwo()
+ @Run(test = "sharedByTwo")
+ public void share1() {}
+
+ @FailCount(0) // Combined with sharedByTwo()
+ @Run(test = "sharedByTwo")
+ public void share2() {}
+
+ @Run(test = "doesNotExist")
+ public void noTestExists() {}
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void argTest(int x) {}
+
+ @FailCount(0) // Combined with argTest()
+ @Run(test = "argTest")
+ public void noArgumentAnnotationForRun() {}
+
+ @NoFail
+ @Test
+ public void test1() {}
+
+ @Run(test = "test1")
+ public void wrongParameters1(int x) {}
+
+ @NoFail
+ @Test
+ public void test2() {}
+
+ @Run(test = "test2")
+ public void wrongParameters(RunInfo info, int x) {}
+
+ @Test
+ public void invalidShare() {}
+
+ @FailCount(0) // Combined with invalidShare()
+ @Run(test = "invalidShare")
+ public void shareSameTestTwice1() {}
+
+ @FailCount(0) // Combined with invalidShare()
+ @Run(test = "invalidShare")
+ public void shareSameTestTwice2() {}
+
+ @Test
+ public void invalidShareCheckRun() {}
+
+ @FailCount(0) // Combined with invalidShare()
+ @Run(test = "invalidShareCheckRun")
+ public void invalidShareCheckRun1() {}
+
+ @FailCount(0) // Combined with invalidShare()
+ @Check(test = "invalidShareCheckRun")
+ public void invalidShareCheckRun2() {}
+
+ @NoFail
+ @Test
+ public void testInvalidRunWithArgAnnotation() {}
+
+ @Arguments(Argument.DEFAULT)
+ @Run(test = "testInvalidRunWithArgAnnotation")
+ public void invalidRunWithArgAnnotation(RunInfo info) {}
+
+ @NoFail
+ @Test
+ public void testRunWithTestInfo() {}
+
+ @Run(test = "testRunWithTestInfo")
+ public void invalidRunWithTestInfo(TestInfo info) {}
+
+ @Run(test = {})
+ public void invalidRunWithNoTest() {}
+
+ @Run(test = "")
+ public void invalidRunWithEmptyTestName() {}
+
+ @NoFail
+ @Test
+ public void someExistingTest() {}
+
+ @FailCount(2)
+ @Run(test = {"unknown1", "someExistingTest", "unknown2"})
+ public void invalidRunWithInvalidTests() {}
+
+ @NoFail
+ @Test
+ public void testInvalidReuse() {}
+
+ @Test
+ public void testInvalidReuse2() {}
+
+ @NoFail
+ @Test
+ public void testInvalidReuse3() {}
+
+ @FailCount(0)
+ @Run(test = {"testInvalidReuse", "testInvalidReuse2"})
+ public void runInvalidReuse1() {}
+
+ @FailCount(0)
+ @Run(test = {"testInvalidReuse2", "testInvalidReuse3"})
+ public void runInvalidReuse2() {}
+}
+
+class BadCheckTest {
+ @Check(test = "checkForCheck2")
+ public void checkForCheck() {}
+
+ @Check(test = "checkForCheck")
+ public void checkForCheck2() {}
+
+ @Test
+ public void sharedByTwo() {}
+
+ @FailCount(0) // Combined with sharedByTwo()
+ @Check(test = "sharedByTwo")
+ public void share1() {}
+
+ @FailCount(0) // Combined with sharedByTwo()
+ @Check(test = "sharedByTwo")
+ public void share2() {}
+
+ @Check(test = "doesNotExist")
+ public void noTestExists() {}
+
+ @NoFail
+ @Test
+ public void test1() {}
+
+ @Check(test = "test1")
+ public void wrongReturnParameter1(int x) {}
+
+ @NoFail
+ @Test
+ public short test2() {
+ return 3;
+ }
+
+ @Check(test = "test2")
+ public void wrongReturnParameter2(int x) {}
+
+ @NoFail
+ @Test
+ public short test3() {
+ return 3;
+ }
+
+ @Check(test = "test3")
+ public void wrongReturnParameter3(String x) {}
+
+ @NoFail
+ @Test
+ public short test4() {
+ return 3;
+ }
+
+ @Check(test = "test4")
+ public void wrongReturnParameter4(TestInfo info, int x) {} // Must flip parameters
+
+ @NoFail
+ @Test
+ public int test5() {
+ return 3;
+ }
+
+ @Check(test = "test5")
+ public void wrongReturnParameter5(short x, TestInfo info) {}
+
+ @Test
+ public void invalidShare() {}
+
+ @FailCount(0) // Combined with invalidShare()
+ @Check(test = "invalidShare")
+ public void shareSameTestTwice1() {}
+
+ @FailCount(0) // Combined with invalidShare()
+ @Check(test = "invalidShare")
+ public void shareSameTestTwice2() {}
+
+ @NoFail
+ @Test
+ public void testInvalidRunWithArgAnnotation() {}
+
+ @Arguments(Argument.DEFAULT)
+ @Check(test = "testInvalidRunWithArgAnnotation")
+ public void invalidRunWithArgAnnotation(TestInfo info) {}
+}
+
+class BadIRAnnotations {
+ @IR(failOn = IRNode.CALL)
+ public void noIRAtNonTest() {}
+
+ @NoFail
+ @Test
+ public void test() {}
+
+ @Run(test = "test")
+ @IR(failOn = IRNode.CALL)
+ public void noIRAtRun() {}
+
+ @NoFail
+ @Test
+ public void test2() {}
+
+ @Check(test = "test2")
+ @IR(failOn = IRNode.CALL)
+ public void noIRAtCheck() {}
+
+ @Test
+ @IR
+ public void mustSpecifyAtLeastOneConstraint() {
+ }
+
+ @FailCount(2)
+ @Test
+ @IR
+ @IR
+ public void mustSpecifyAtLeastOneConstraint2() {
+ }
+
+ @Test
+ @IR(applyIf = {"TLABRefillWasteFraction", "50"})
+ public void mustSpecifyAtLeastOneConstraint3() {
+ }
+
+ @FailCount(3)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "50"}, applyIfNot = {"UseTLAB", "true"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "50", "UseTLAB", "true"},
+ applyIfOr = {"TLABRefillWasteFraction", "50", "UseTLAB", "true"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "50"}, applyIfNot = {"TLABRefillWasteFraction", "50"},
+ applyIfAnd = {"TLABRefillWasteFraction", "50", "UseTLAB", "true"},
+ applyIfOr = {"TLABRefillWasteFraction", "50", "UseTLAB", "true"})
+ public void onlyOneApply() {}
+
+ @FailCount(3)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "50", "UseTLAB", "true"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "51", "UseTLAB"})
+ public void applyIfTooManyFlags() {}
+
+ @FailCount(2)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction"})
+ @IR(failOn = IRNode.CALL, applyIf = {"Bla"})
+ public void applyIfMissingValue() {}
+
+ @FailCount(2)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIf = {"PrintIdealGraphFilee", "true"})
+ @IR(failOn = IRNode.CALL, applyIf = {"Bla", "foo"})
+ public void applyIfUnknownFlag() {}
+
+ @FailCount(5)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIf = {"PrintIdealGraphFile", ""})
+ @IR(failOn = IRNode.CALL, applyIf = {"UseTLAB", ""})
+ @IR(failOn = IRNode.CALL, applyIf = {"", "true"})
+ @IR(failOn = IRNode.CALL, applyIf = {"", ""})
+ @IR(failOn = IRNode.CALL, applyIf = {" ", " "})
+ public void applyIfEmptyValue() {}
+
+ @FailCount(5)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "! 34"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!== 34"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<<= 34"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "=<34"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<"})
+ public void applyIfFaultyComparator() {}
+
+ @FailCount(3)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfNot = {"TLABRefillWasteFraction", "50", "UseTLAB", "true"})
+ @IR(failOn = IRNode.CALL, applyIfNot = {"TLABRefillWasteFraction", "50", "UseTLAB"})
+ public void applyIfNotTooManyFlags() {}
+
+ @FailCount(2)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfNot = {"TLABRefillWasteFraction"})
+ @IR(failOn = IRNode.CALL, applyIfNot = {"Bla"})
+ public void applyIfNotMissingValue() {}
+
+ @FailCount(2)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfNot = {"PrintIdealGraphFilee", "true"})
+ @IR(failOn = IRNode.CALL, applyIfNot = {"Bla", "foo"})
+ public void applyIfNotUnknownFlag() {}
+
+ @FailCount(5)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfNot = {"PrintIdealGraphFile", ""})
+ @IR(failOn = IRNode.CALL, applyIfNot = {"UseTLAB", ""})
+ @IR(failOn = IRNode.CALL, applyIfNot = {"", "true"})
+ @IR(failOn = IRNode.CALL, applyIfNot = {"", ""})
+ @IR(failOn = IRNode.CALL, applyIfNot = {" ", " "})
+ public void applyIfNotEmptyValue() {}
+
+ @FailCount(5)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfNot = {"TLABRefillWasteFraction", "! 34"})
+ @IR(failOn = IRNode.CALL, applyIfNot = {"TLABRefillWasteFraction", "!== 34"})
+ @IR(failOn = IRNode.CALL, applyIfNot = {"TLABRefillWasteFraction", "<<= 34"})
+ @IR(failOn = IRNode.CALL, applyIfNot = {"TLABRefillWasteFraction", "=<34"})
+ @IR(failOn = IRNode.CALL, applyIfNot = {"TLABRefillWasteFraction", "<"})
+ public void applyIfNotFaultyComparator() {}
+
+
+ @FailCount(2)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "50"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "51", "UseTLAB"})
+ public void applyIfAndNotEnoughFlags() {}
+
+ @FailCount(5)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "51", "UseTLAB"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"Bla"})
+ public void applyIfAndMissingValue() {}
+
+ @FailCount(3)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"PrintIdealGraphFilee", "true", "TLABRefillWasteFraction", "< 34"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "!= 50", "Bla", "bla", "Bla2", "bla2"})
+ public void applyIfAndUnknownFlag() {}
+
+ @FailCount(18)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"PrintIdealGraphFile", ""})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"PrintIdealGraphFile", "", "PrintIdealGraphFile", ""})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"UseTLAB", ""})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"UseTLAB", "", "UseTLAB", ""})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"", "true"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"", "true", "", "true"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"", ""})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"", "", "", ""})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {" ", " ", " ", " "})
+ public void applyIfAndEmptyValue() {}
+
+ @FailCount(20)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "! 34"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "! 34", "TLABRefillWasteFraction", "! 34"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "!== 34"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "!== 34", "TLABRefillWasteFraction", "=== 34"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "<<= 34"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "<<= 34", "TLABRefillWasteFraction", ">>= 34"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "=<34"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "=<34", "TLABRefillWasteFraction", "=<34"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "<"})
+ @IR(failOn = IRNode.CALL, applyIfAnd = {"TLABRefillWasteFraction", "<", "TLABRefillWasteFraction", "!="})
+ public void applyIfAndFaultyComparator() {}
+
+ @FailCount(2)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction", "50"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction", "51", "UseTLAB"})
+ public void applyIfOrNotEnoughFlags() {}
+
+ @FailCount(5)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction", "51", "UseTLAB"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"Bla"})
+ public void applyIfOrMissingValue() {}
+
+ @FailCount(3)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfOr = {"PrintIdealGraphFilee", "true", "TLABRefillWasteFraction", "< 34"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction", "!= 50", "Bla", "bla", "Bla2", "bla2"})
+ public void applyIfOrUnknownFlag() {}
+
+ @FailCount(18)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfOr = {"PrintIdealGraphFile", ""})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"PrintIdealGraphFile", "", "PrintIdealGraphFile", ""})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"UseTLAB", ""})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"UseTLAB", "", "UseTLAB", ""})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"", "true"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"", "true", "", "true"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"", ""})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"", "", "", ""})
+ @IR(failOn = IRNode.CALL, applyIfOr = {" ", " ", " ", " "})
+ public void applyIfOrEmptyValue() {}
+
+ @FailCount(20)
+ @Test
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction", "! 34"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction", "! 34", "TLABRefillWasteFraction", "! 34"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction", "!== 34"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction", "!== 34", "TLABRefillWasteFraction", "=== 34"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction", "<<= 34"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction", "<<= 34", "TLABRefillWasteFraction", ">>= 34"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction", "=<34"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction", "=<34", "TLABRefillWasteFraction", "=<34"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction", "<"})
+ @IR(failOn = IRNode.CALL, applyIfOr = {"TLABRefillWasteFraction", "<", "TLABRefillWasteFraction", "!="})
+ public void applyIfOrFaultyComparator() {}
+
+
+ @Test
+ @FailCount(3)
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "true"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "SomeString"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "48"}) // valid
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "48.5"})
+ public void wrongFlagValueLongFlag() {}
+
+ @Test
+ @FailCount(3)
+ @IR(failOn = IRNode.CALL, applyIf = {"UseTLAB", "true"}) // valid
+ @IR(failOn = IRNode.CALL, applyIf = {"UseTLAB", "SomeString"})
+ @IR(failOn = IRNode.CALL, applyIf = {"UseTLAB", "48"})
+ @IR(failOn = IRNode.CALL, applyIf = {"UseTLAB", "48.5"})
+ public void wrongFlagValueBooleanFlag() {}
+
+ @Test
+ @FailCount(2)
+ @IR(failOn = IRNode.CALL, applyIf = {"CompileThresholdScaling", "true"})
+ @IR(failOn = IRNode.CALL, applyIf = {"CompileThresholdScaling", "SomeString"})
+ @IR(failOn = IRNode.CALL, applyIf = {"CompileThresholdScaling", "48"}) // valid
+ @IR(failOn = IRNode.CALL, applyIf = {"CompileThresholdScaling", "48.5"}) // valid
+ public void wrongFlagValueDoubleFlag() {}
+
+ @Test
+ @NoFail
+ @IR(failOn = IRNode.CALL, applyIf = {"ErrorFile", "true"}) // valid
+ @IR(failOn = IRNode.CALL, applyIf = {"ErrorFile", "SomeString"}) // valid
+ @IR(failOn = IRNode.CALL, applyIf = {"ErrorFile", "48"}) // valid
+ @IR(failOn = IRNode.CALL, applyIf = {"ErrorFile", "48.5"}) // valid
+ public void anyValueForStringFlags() {}
+}
+
+@ClassFail
+class BadInnerClassTest {
+
+ class InnerClass {
+ @Test
+ public void noTestInInnerClass1() {}
+
+ @Test
+ public void noTestInInnerClass2() {}
+
+ @Check(test = "noTestInInnerClass2")
+ public void checkNoTestInInnerClass2() {}
+
+ @Test
+ public void noTestInInnerClass3() {}
+
+ @Run(test = "noTestInInnerClass3")
+ public void checkNoTestInInnerClass3() {}
+ }
+
+
+ static class StaticInnerClass {
+ @Test
+ public void noTestInInnerStaticClass1() {}
+
+ @Test
+ public void noTestInStaticInnerClass2() {}
+
+ @Check(test = "noTestInStaticInnerClass2")
+ public void checkNoTestInStaticInnerClass2() {}
+
+ @Test
+ public void noTestInStaticInnerClass3() {}
+
+ @Run(test = "noTestInStaticInnerClass3")
+ public void checkNoTestInStaticInnerClass3() {}
+ }
+}
+
+@ForceCompileClassInitializer
+class BadCompileClassInitializer {
+ static int iFld = 3;
+
+ @Test
+ @ForceCompileClassInitializer
+ public void test() {}
+
+ @ForceCompileClassInitializer
+ public void helper() {}
+}
+
+@ClassFail
+@ForceCompileClassInitializer(CompLevel.SKIP)
+class BadCompileClassInitializerHelper1 {
+
+}
+
+@ClassFail
+@ForceCompileClassInitializer(CompLevel.WAIT_FOR_COMPILATION)
+class BadCompileClassInitializerHelper2 {
+
+}
+
+@ClassFail
+@ForceCompileClassInitializer
+class BadCompileClassInitializerHelper3 {
+ // no
+}
+
+class ClassNoDefaultConstructor {
+ private ClassNoDefaultConstructor(int i) {
+ }
+}
+
+// Test specific annotation:
+// All methods without such an annotation must occur in the violation messages.
+@Retention(RetentionPolicy.RUNTIME)
+@interface NoFail {}
+
+// Test specific annotation:
+// Specify a fail count for a method without @NoFail. Use the value 0 if multiple methods are part of the same violation.
+@Retention(RetentionPolicy.RUNTIME)
+@interface FailCount {
+ int value();
+}
+
+// Class specific annotation:
+// All classes with such an annotation have exactly one violation with the clas name in it.
+@Retention(RetentionPolicy.RUNTIME)
+@interface ClassFail {}
+
+class Violations {
+ private final List failedMethods = new ArrayList<>();
+ private int violations;
+
+ public int getViolationCount() {
+ return violations;
+ }
+
+ public List getFailedMethods() {
+ return failedMethods;
+ }
+
+ public void addFail(Method m, int count) {
+ failedMethods.add(m.getName());
+ violations += count;
+ }
+
+ public void addFail(Class> c) {
+ failedMethods.add(c.getName());
+ violations += 1;
+ }
+}
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestBasics.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestBasics.java
new file mode 100644
index 00000000000..82b6f880f2d
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestBasics.java
@@ -0,0 +1,1086 @@
+/*
+ * Copyright (c) 2021, 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.test.TestVM;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.stream.Stream;
+
+/*
+ * @test
+ * @requires vm.compiler2.enabled & vm.flagless
+ * @summary Test basics of the framework. This test runs directly the test VM which normally does not happen.
+ * @library /test/lib /
+ * @build sun.hotspot.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -Xbatch ir_framework.tests.TestBasics
+ */
+
+public class TestBasics {
+ private static boolean wasExecuted = false;
+ private boolean lastToggleBoolean = true;
+ private final static int[] executed = new int[100];
+ private final static int[] executedOnce = new int[5];
+ private long[] nonFloatingRandomNumbers = new long[10];
+ private double[] floatingRandomNumbers = new double[10];
+ private Boolean[] randomBooleans = new Boolean[64];
+
+ public static void main(String[] args) throws Exception {
+ // Run on same VM to make this test easier as we are not interested in any output processing.
+ Class> c = TestFramework.class; // Enable JTreg test to compile TestFramework
+ Method runTestsOnSameVM = TestVM.class.getDeclaredMethod("runTestsOnSameVM", Class.class);
+ runTestsOnSameVM.setAccessible(true);
+ runTestsOnSameVM.invoke(null, new Object[]{ null });
+
+ if (wasExecuted) {
+ throw new RuntimeException("Executed non @Test method or a method that was not intended to be run");
+ }
+ for (int i = 0; i < executed.length; i++) {
+ int value = executed[i];
+ if (value != TestVM.WARMUP_ITERATIONS + 1) {
+ // Warmups + 1 C2 compiled invocation
+ throw new RuntimeException("Test " + i + " was executed " + value + " times instead stead of "
+ + (TestVM.WARMUP_ITERATIONS + 1) + " times." );
+ }
+ }
+
+ for (int value : executedOnce) {
+ if (value != 1) {
+ throw new RuntimeException("Check function should have been executed exactly once");
+ }
+ }
+ }
+
+ private void clearNonFloatingRandomNumbers() {
+ nonFloatingRandomNumbers = new long[10];
+ }
+
+ private void clearFloatingRandomNumbers() {
+ floatingRandomNumbers = new double[10];
+ }
+
+ private void clearRandomBooleans() {
+ randomBooleans = new Boolean[64];
+ }
+
+ // Base test, no arguments, directly invoked.
+ @Test
+ public void test() {
+ executed[0]++;
+ }
+
+ // Not a test
+ public void noTest() {
+ wasExecuted = true;
+ }
+
+ // Not a test
+ public void test2() {
+ wasExecuted = true;
+ }
+
+ // Can overload non- @Test
+ public static void test2(int i) {
+ wasExecuted = true;
+ }
+
+ // Can overload a @Test if it is not a @Test itself.
+ public static void test(double i) {
+ wasExecuted = true;
+ }
+
+ @Test
+ public static void staticTest() {
+ executed[1]++;
+ }
+
+ @Test
+ public final void finalTest() {
+ executed[2]++;
+ }
+
+ @Test
+ public int returnValueTest() {
+ executed[3]++;
+ return 4;
+ }
+
+ // Base test, with arguments, directly invoked.
+ // Specify the argument values with @Arguments
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void byteDefaultArgument(byte x) {
+ executed[4]++;
+ if (x != 0) {
+ throw new RuntimeException("Must be 0");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void shortDefaultArgument(short x) {
+ executed[5]++;
+ if (x != 0) {
+ throw new RuntimeException("Must be 0");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void intDefaultArgument(int x) {
+ executed[6]++;
+ if (x != 0) {
+ throw new RuntimeException("Must be 0");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void longDefaultArgument(long x) {
+ executed[7]++;
+ if (x != 0L) {
+ throw new RuntimeException("Must be 0");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void floatDefaultArgument(float x) {
+ executed[8]++;
+ if (x != 0.0f) {
+ throw new RuntimeException("Must be 0.0");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void doubleDefaultArgument(double x) {
+ executed[9]++;
+ if (x != 0.0f) {
+ throw new RuntimeException("Must be 0.0");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void charDefaultArgument(char x) {
+ executed[10]++;
+ if (x != '\u0000') {
+ throw new RuntimeException("Must be \u0000");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void booleanDefaultArgument(boolean x) {
+ executed[11]++;
+ if (x) {
+ throw new RuntimeException("Must be false");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void stringObjectDefaultArgument(String x) {
+ executed[12]++;
+ if (x == null || x.length() != 0) {
+ throw new RuntimeException("Default string object must be non-null and having a length of zero");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.DEFAULT)
+ public void defaultObjectDefaultArgument(DefaultObject x) {
+ executed[13]++;
+ if (x == null || x.i != 4) {
+ throw new RuntimeException("Default object must not be null and its i field must be 4");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.NUMBER_42)
+ public void byte42(byte x) {
+ executed[14]++;
+ if (x != 42) {
+ throw new RuntimeException("Must be 42");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.NUMBER_42)
+ public void short42(short x) {
+ executed[15]++;
+ if (x != 42) {
+ throw new RuntimeException("Must be 42");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.NUMBER_42)
+ public void int42(int x) {
+ executed[16]++;
+ if (x != 42) {
+ throw new RuntimeException("Must be 42");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.NUMBER_42)
+ public void long42(long x) {
+ executed[17]++;
+ if (x != 42) {
+ throw new RuntimeException("Must be 42");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.NUMBER_42)
+ public void float42(float x) {
+ executed[18]++;
+ if (x != 42.0) {
+ throw new RuntimeException("Must be 42");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.NUMBER_42)
+ public void double42(double x) {
+ executed[19]++;
+ if (x != 42.0) {
+ throw new RuntimeException("Must be 42");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.FALSE)
+ public void booleanFalse(boolean x) {
+ executed[20]++;
+ if (x) {
+ throw new RuntimeException("Must be false");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.TRUE)
+ public void booleanTrue(boolean x) {
+ executed[21]++;
+ if (!x) {
+ throw new RuntimeException("Must be true");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_ONCE)
+ public void randomByte(byte x) {
+ executed[22]++;
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_ONCE)
+ public void randomShort(short x) {
+ executed[23]++;
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_ONCE)
+ public void randomInt(int x) {
+ executed[24]++;
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_ONCE)
+ public void randomLong(long x) {
+ executed[25]++;
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_ONCE)
+ public void randomFloat(float x) {
+ executed[26]++;
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_ONCE)
+ public void randomDouble(double x) {
+ executed[27]++;
+ }
+
+ // Not executed
+ public void randomNotExecutedTest(double x) {
+ wasExecuted = true;
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_ONCE)
+ public void randomBoolean(boolean x) {
+ executed[28]++;
+ }
+
+ @Test
+ @Arguments(Argument.BOOLEAN_TOGGLE_FIRST_FALSE)
+ public void booleanToggleFirstFalse(boolean x) {
+ if (executed[29] == 0) {
+ // First invocation
+ if (x) {
+ throw new RuntimeException("BOOLEAN_TOGGLE_FIRST_FALSE must be false on first invocation");
+ }
+ } else if (x == lastToggleBoolean) {
+ throw new RuntimeException("BOOLEAN_TOGGLE_FIRST_FALSE did not toggle");
+ }
+ lastToggleBoolean = x;
+ executed[29]++;
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_EACH)
+ public void randomEachByte(byte x) {
+ checkNonFloatingRandomNumber(x, executed[30]);
+ executed[30]++;
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_EACH)
+ public void randomEachShort(short x) {
+ checkNonFloatingRandomNumber(x, executed[31]);
+ executed[31]++;
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_EACH)
+ public void randomEachInt(int x) {
+ checkNonFloatingRandomNumber(x, executed[32]);
+ executed[32]++;
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_EACH)
+ public void randomEachLong(long x) {
+ checkNonFloatingRandomNumber(x, executed[33]);
+ executed[33]++;
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_EACH)
+ public void randomEachChar(char x) {
+ checkNonFloatingRandomNumber(x, executed[34]);
+ executed[34]++;
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_EACH)
+ public void randomEachFloat(float x) {
+ checkFloatingRandomNumber(x, executed[35]);
+ executed[35]++;
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_EACH)
+ public void randomEachDouble(double x) {
+ checkFloatingRandomNumber(x, executed[36]);
+ executed[36]++;
+ }
+
+ @Test
+ @Arguments(Argument.RANDOM_EACH)
+ public void randomEachBoolean(boolean x) {
+ checkRandomBoolean(x, executed[37]);
+ executed[37]++;
+ }
+
+ private void checkNonFloatingRandomNumber(long x, int invocationCount) {
+ int mod10 = invocationCount % 10;
+ if (invocationCount > 0 && mod10 == 0) {
+ // Not first invocation
+ // Check the last 10 numbers and ensure that there are at least 2 different ones.
+ // All numbers are equal? Very unlikely nd we should really consider to play the lottery...
+ long first = nonFloatingRandomNumbers[0];
+ if (Arrays.stream(nonFloatingRandomNumbers).allMatch(n -> n == first)) {
+ throw new RuntimeException("RANDOM_EACH does not generate random integer numbers");
+ }
+ clearNonFloatingRandomNumbers();
+ }
+ nonFloatingRandomNumbers[mod10] = x;
+ }
+
+ private void checkFloatingRandomNumber(double x, int invocationCount) {
+ int mod10 = invocationCount % 10;
+ if (invocationCount > 0 && mod10 == 0) {
+ // Not first invocation
+ // Check the last 10 numbers and ensure that there are at least 2 different ones.
+ // All numbers are equal? Very unlikely nd we should really consider to play the lottery...
+ double first = floatingRandomNumbers[0];
+ if (Arrays.stream(floatingRandomNumbers).allMatch(n -> n == first)) {
+ throw new RuntimeException("RANDOM_EACH does not generate random floating point numbers");
+ }
+ clearFloatingRandomNumbers();
+ }
+ floatingRandomNumbers[mod10] = x;
+ }
+
+ private void checkRandomBoolean(boolean x, int invocationCount) {
+ int mod64 = invocationCount % 64;
+ if (invocationCount > 0 && mod64 == 0) {
+ // Not first invocation
+ // Check the last 64 booleans and ensure that there are at least one true and one false.
+ // All booleans are equal? Very unlikely (chance of 2^64) and we should really consider
+ // to play the lottery...
+ if (Arrays.stream(randomBooleans).allMatch(b -> b == randomBooleans[0])) {
+ throw new RuntimeException("RANDOM_EACH does not generate random booleans");
+ }
+ clearRandomBooleans();
+ }
+ randomBooleans[mod64] = x;
+ }
+
+
+ @Test
+ @Arguments(Argument.NUMBER_MINUS_42)
+ public void byteMinus42(byte x) {
+ executed[38]++;
+ if (x != -42) {
+ throw new RuntimeException("Must be -42");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.NUMBER_MINUS_42)
+ public void shortMinus42(short x) {
+ executed[39]++;
+ if (x != -42) {
+ throw new RuntimeException("Must be -42");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.NUMBER_MINUS_42)
+ public void intMinus42(int x) {
+ executed[40]++;
+ if (x != -42) {
+ throw new RuntimeException("Must be -42");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.NUMBER_MINUS_42)
+ public void longMinus42(long x) {
+ executed[41]++;
+ if (x != -42) {
+ throw new RuntimeException("Must be -42");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.NUMBER_MINUS_42)
+ public void floatMinus42(float x) {
+ executed[42]++;
+ if (x != -42.0) {
+ throw new RuntimeException("Must be -42");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.NUMBER_MINUS_42)
+ public void doubleMinus42(double x) {
+ executed[43]++;
+ if (x != -42.0) {
+ throw new RuntimeException("Must be -42");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.MIN)
+ public void byteMin(byte x) {
+ executed[79]++;
+ if (x != Byte.MIN_VALUE) {
+ throw new RuntimeException("Must be MIN_VALUE");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.MIN)
+ public void charMin(char x) {
+ executed[80]++;
+ if (x != Character.MIN_VALUE) {
+ throw new RuntimeException("Must be MIN_VALUE");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.MIN)
+ public void shortMin(short x) {
+ executed[81]++;
+ if (x != Short.MIN_VALUE) {
+ throw new RuntimeException("Must be MIN_VALUE");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.MIN)
+ public void intMin(int x) {
+ executed[82]++;
+ if (x != Integer.MIN_VALUE) {
+ throw new RuntimeException("Must be MIN_VALUE");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.MIN)
+ public void longMin(long x) {
+ executed[83]++;
+ if (x != Long.MIN_VALUE) {
+ throw new RuntimeException("Must be MIN_VALUE");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.MIN)
+ public void floatMin(float x) {
+ executed[84]++;
+ if (x != Float.MIN_VALUE) {
+ throw new RuntimeException("Must be MIN_VALUE");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.MIN)
+ public void doubleMin(double x) {
+ executed[85]++;
+ if (x != Double.MIN_VALUE) {
+ throw new RuntimeException("Must be MIN_VALUE");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.MAX)
+ public void byteMax(byte x) {
+ executed[86]++;
+ if (x != Byte.MAX_VALUE) {
+ throw new RuntimeException("Must be MAX_VALUE");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.MAX)
+ public void charMax(char x) {
+ executed[87]++;
+ if (x != Character.MAX_VALUE) {
+ throw new RuntimeException("Must be MAX_VALUE");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.MAX)
+ public void shortMax(short x) {
+ executed[88]++;
+ if (x != Short.MAX_VALUE) {
+ throw new RuntimeException("Must be MAX_VALUE");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.MAX)
+ public void intMax(int x) {
+ executed[89]++;
+ if (x != Integer.MAX_VALUE) {
+ throw new RuntimeException("Must be MAX_VALUE");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.MAX)
+ public void longMax(long x) {
+ executed[90]++;
+ if (x != Long.MAX_VALUE) {
+ throw new RuntimeException("Must be MAX_VALUE");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.MAX)
+ public void floatMax(float x) {
+ executed[91]++;
+ if (x != Float.MAX_VALUE) {
+ throw new RuntimeException("Must be MAX_VALUE");
+ }
+ }
+
+ @Test
+ @Arguments(Argument.MAX)
+ public void doubleMax(double x) {
+ executed[78]++;
+ if (x != Double.MAX_VALUE) {
+ throw new RuntimeException("Must be MAX_VALUE");
+ }
+ }
+
+ @Test
+ @Arguments({Argument.DEFAULT, Argument.DEFAULT})
+ public void twoArgsDefault1(byte x, short y) {
+ executed[44]++;
+ if (x != 0 || y != 0) {
+ throw new RuntimeException("Both must be 0");
+ }
+ }
+
+ @Test
+ @Arguments({Argument.DEFAULT, Argument.DEFAULT})
+ public void twoArgsDefault2(int x, short y) {
+ executed[45]++;
+ if (x != 0 || y != 0) {
+ throw new RuntimeException("Both must be 0");
+ }
+ }
+
+ @Test
+ @Arguments({Argument.DEFAULT, Argument.DEFAULT})
+ public void twoArgsDefault3(short x, long y) {
+ executed[46]++;
+ if (x != 0 || y != 0) {
+ throw new RuntimeException("Both must be 0");
+ }
+ }
+
+ @Test
+ @Arguments({Argument.DEFAULT, Argument.DEFAULT})
+ public void twoArgsDefault4(float x, boolean y) {
+ executed[47]++;
+ if (x != 0.0 || y) {
+ throw new RuntimeException("Must be 0 and false");
+ }
+ }
+
+ @Test
+ @Arguments({Argument.DEFAULT, Argument.DEFAULT})
+ public void twoArgsDefault5(boolean x, char y) {
+ executed[48]++;
+ if (x || y != '\u0000') {
+ throw new RuntimeException("Must be false and \u0000");
+ }
+ }
+
+ @Test
+ @Arguments({Argument.DEFAULT, Argument.DEFAULT})
+ public void twoArgsDefault6(char x, byte y) {
+ executed[49]++;
+ if (x != '\u0000' || y != 0) {
+ throw new RuntimeException("Must be\u0000 and 0");
+ }
+ }
+
+ @Test
+ @Arguments({Argument.RANDOM_ONCE, Argument.RANDOM_ONCE})
+ public void twoArgsRandomOnce(char x, byte y) {
+ executed[50]++;
+ }
+
+ @Test
+ @Arguments({Argument.RANDOM_ONCE, Argument.RANDOM_ONCE,
+ Argument.RANDOM_ONCE, Argument.RANDOM_ONCE,
+ Argument.RANDOM_ONCE, Argument.RANDOM_ONCE,
+ Argument.RANDOM_ONCE, Argument.RANDOM_ONCE})
+ public void checkRandomOnceDifferentArgs(int a, int b, int c, int d, int e, int f, int g, int h) {
+ if (Stream.of(a, b, c, d, e, f, g, h).allMatch(i -> i == a)) {
+ throw new RuntimeException("RANDOM_ONCE does not produce random values for different arguments");
+ }
+ executed[51]++;
+ }
+
+ @Test
+ @Arguments({Argument.RANDOM_ONCE, Argument.RANDOM_ONCE,
+ Argument.RANDOM_ONCE, Argument.RANDOM_ONCE,
+ Argument.RANDOM_ONCE, Argument.RANDOM_ONCE,
+ Argument.RANDOM_ONCE, Argument.RANDOM_ONCE})
+ public void checkMixedRandoms1(byte a, short b, int c, long d, char e, boolean f, float g, double h) {
+ executed[52]++;
+ }
+
+ @Test
+ @Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH,
+ Argument.RANDOM_EACH, Argument.RANDOM_EACH,
+ Argument.RANDOM_EACH, Argument.RANDOM_EACH,
+ Argument.RANDOM_EACH, Argument.RANDOM_EACH})
+ public void checkMixedRandoms2(byte a, short b, int c, long d, char e, boolean f, float g, double h) {
+ executed[53]++;
+ }
+
+ @Test
+ @Arguments({Argument.RANDOM_ONCE, Argument.RANDOM_ONCE,
+ Argument.RANDOM_EACH, Argument.RANDOM_EACH,
+ Argument.RANDOM_ONCE, Argument.RANDOM_EACH,
+ Argument.RANDOM_EACH, Argument.RANDOM_ONCE})
+ public void checkMixedRandoms3(byte a, short b, int c, long d, char e, boolean f, float g, double h) {
+ executed[54]++;
+ }
+
+ @Test
+ @Arguments({Argument.NUMBER_42, Argument.NUMBER_42,
+ Argument.NUMBER_42, Argument.NUMBER_42,
+ Argument.NUMBER_42, Argument.NUMBER_42})
+ public void check42Mix1(byte a, short b, int c, long d, float e, double f) {
+ if (a != 42 || b != 42 || c != 42 || d != 42 || e != 42.0 || f != 42.0) {
+ throw new RuntimeException("Must all be 42");
+ }
+ executed[55]++;
+ }
+
+ @Test
+ @Arguments({Argument.NUMBER_MINUS_42, Argument.NUMBER_MINUS_42,
+ Argument.NUMBER_MINUS_42, Argument.NUMBER_MINUS_42,
+ Argument.NUMBER_MINUS_42, Argument.NUMBER_MINUS_42})
+ public void check42Mix2(byte a, short b, int c, long d, float e, double f) {
+ if (a != -42 || b != -42 || c != -42 || d != -42 || e != -42.0 || f != -42.0) {
+ throw new RuntimeException("Must all be -42");
+ }
+ executed[56]++;
+ }
+
+ @Test
+ @Arguments({Argument.NUMBER_MINUS_42, Argument.NUMBER_42,
+ Argument.NUMBER_MINUS_42, Argument.NUMBER_MINUS_42,
+ Argument.NUMBER_42, Argument.NUMBER_MINUS_42})
+ public void check42Mix3(byte a, short b, int c, long d, float e, double f) {
+ if (a != -42 || b != 42 || c != -42 || d != -42 || e != 42.0 || f != -42.0) {
+ throw new RuntimeException("Do not match the right 42 version");
+ }
+ executed[57]++;
+ }
+
+
+ @Test
+ @Arguments(Argument.BOOLEAN_TOGGLE_FIRST_TRUE)
+ public void booleanToggleFirstTrue(boolean x) {
+ if (executed[58] == 0) {
+ // First invocation
+ if (!x) {
+ throw new RuntimeException("BOOLEAN_TOGGLE_FIRST_FALSE must be false on first invocation");
+ }
+ } else if (x == lastToggleBoolean) {
+ throw new RuntimeException("BOOLEAN_TOGGLE_FIRST_FALSE did not toggle");
+ }
+ lastToggleBoolean = x;
+ executed[58]++;
+ }
+
+ @Test
+ @Arguments({Argument.BOOLEAN_TOGGLE_FIRST_FALSE, Argument.BOOLEAN_TOGGLE_FIRST_TRUE})
+ public void checkTwoToggles(boolean b1, boolean b2) {
+ if (executed[59] == 0) {
+ // First invocation
+ if (b1 || !b2) {
+ throw new RuntimeException("BOOLEAN_TOGGLES have wrong initial value");
+ }
+ } else if (b1 == b2) {
+ throw new RuntimeException("Boolean values must be different");
+ } else if (b1 == lastToggleBoolean) {
+ throw new RuntimeException("Booleans did not toggle");
+ }
+ lastToggleBoolean = b1;
+ executed[59]++;
+ }
+
+ @Test
+ @Arguments({Argument.BOOLEAN_TOGGLE_FIRST_FALSE, Argument.FALSE,
+ Argument.TRUE, Argument.BOOLEAN_TOGGLE_FIRST_TRUE})
+ public void booleanMix(boolean b1, boolean b2, boolean b3, boolean b4) {
+ if (executed[60] == 0) {
+ // First invocation
+ if (b1 || b2 || !b3 || !b4) {
+ throw new RuntimeException("BOOLEAN_TOGGLES have wrong initial value");
+ }
+ } else if (b1 == b4) {
+ throw new RuntimeException("Boolean values must be different");
+ } else if (b1 == lastToggleBoolean) {
+ throw new RuntimeException("Booleans did not toggle");
+ }
+ lastToggleBoolean = b1;
+ executed[60]++;
+ }
+
+ /*
+ * Checked tests.
+ */
+
+ @Test
+ public int testCheck() {
+ executed[63]++;
+ return 1;
+ }
+
+ // Checked test. Check invoked after invoking "testCheck". Perform some more things after invocation.
+ @Check(test = "testCheck")
+ public void checkTestCheck() {
+ executed[64]++; // Executed on each invocation
+ }
+
+ @Test
+ public int testCheckReturn() {
+ executed[65]++;
+ return 2;
+ }
+
+ // Checked test with return value. Perform checks on it.
+ @Check(test = "testCheckReturn")
+ public void checkTestCheckReturn(int returnValue) {
+ if (returnValue != 2) {
+ throw new RuntimeException("Must be 2");
+ }
+ executed[66]++; // Executed on each invocation
+ }
+
+ @Test
+ @Arguments(Argument.NUMBER_42)
+ public short testCheckWithArgs(short x) {
+ executed[94]++;
+ return x;
+ }
+
+ @Check(test = "testCheckWithArgs")
+ public void checkTestCheckWithArgs(short returnValue) {
+ if (returnValue != 42) {
+ throw new RuntimeException("Must be 42");
+ }
+ executed[95]++; // Executed on each invocation
+ }
+
+ @Test
+ public int testCheckTestInfo() {
+ executed[67]++;
+ return 3;
+ }
+
+ // Checked test with info object about test.
+ @Check(test = "testCheckTestInfo")
+ public void checkTestCheckTestInfo(TestInfo testInfo) {
+ executed[68]++; // Executed on each invocation
+ }
+
+
+ @Test
+ public int testCheckBoth() {
+ executed[69]++;
+ return 4;
+ }
+
+ // Checked test with return value and info object about test.
+ @Check(test = "testCheckBoth")
+ public void checkTestCheckTestInfo(int returnValue, TestInfo testInfo) {
+ if (returnValue != 4) {
+ throw new RuntimeException("Must be 4");
+ }
+ executed[70]++; // Executed on each invocation
+ }
+
+ @Test
+ public int testCheckOnce() {
+ executed[71]++;
+ return 1;
+ }
+
+ // Check method only invoked once after method is compiled after warm up.
+ @Check(test = "testCheckOnce", when = CheckAt.COMPILED)
+ public void checkTestCheckOnce() {
+ executedOnce[0]++; // Executed once
+ }
+
+ @Test
+ public int testCheckReturnOnce() {
+ executed[72]++;
+ return 2;
+ }
+
+ @Check(test = "testCheckReturnOnce", when = CheckAt.COMPILED)
+ public void checkTestCheckReturnOnce(int returnValue) {
+ if (returnValue != 2) {
+ throw new RuntimeException("Must be 2");
+ }
+ executedOnce[1]++; // Executed once
+ }
+
+ @Test
+ public int testCheckTestInfoOnce() {
+ executed[73]++;
+ return 3;
+ }
+
+ @Check(test = "testCheckTestInfoOnce", when = CheckAt.COMPILED)
+ public void checkTestCheckTestInfoOnce(TestInfo testInfo) {
+ executedOnce[2]++; // Executed once
+ }
+
+ @Test
+ public int testCheckBothOnce() {
+ executed[74]++;
+ return 4;
+ }
+
+ @Check(test = "testCheckBothOnce", when = CheckAt.COMPILED)
+ public void checkTestCheckBothOnce(int returnValue, TestInfo testInfo) {
+ if (returnValue != 4) {
+ throw new RuntimeException("Must be 4");
+ }
+ executedOnce[3]++; // Executed once
+ }
+
+ @Test
+ public void sameName() {
+ executed[76]++;
+ }
+
+ // Allowed to overload test method if not test method itself
+ public void sameName(boolean a) {
+ wasExecuted = true;
+ }
+
+ // Allowed to overload test method if not test method itself
+ @Check(test = "sameName")
+ public void sameName(TestInfo info) {
+ executed[77]++;
+ }
+
+
+ /*
+ * Custom run tests.
+ */
+
+ @Test
+ public void sameName2() {
+ executed[92]++;
+ }
+
+ // Allowed to overload test method if not test method itself
+ @Run(test = "sameName2")
+ public void sameName2(RunInfo info) {
+ executed[93]++;
+ sameName2();
+ }
+
+ @Test
+ public void testRun() {
+ executed[61]++;
+ }
+
+ // Custom run test. This method is invoked each time instead of @Test method. This method responsible for calling
+ // the @Test method. @Test method is compiled after warm up. This is similar to the verifiers in the old Valhalla framework.
+ @Run(test = "testRun")
+ public void runTestRun(RunInfo info) {
+ testRun();
+ }
+
+ @Test
+ public void testRunNoTestInfo(int i) { // Argument allowed when run by @Run
+ executed[62]++;
+ }
+
+ @Run(test = "testRunNoTestInfo")
+ public void runTestRunNoTestInfo() {
+ testRunNoTestInfo(3);
+ }
+
+ @Test
+ public void testNotRun() {
+ wasExecuted = true;
+ }
+
+ @Run(test = "testNotRun")
+ public void runTestNotRun() {
+ // Do not execute the test. Pointless but need to test that as well.
+ }
+
+ @Test
+ public void testRunOnce() {
+ executedOnce[4]++;
+ }
+
+ // Custom run test that is only invoked once. There is no warm up and no compilation. This method is responsible
+ // for triggering compilation.
+ @Run(test = "testRunOnce", mode = RunMode.STANDALONE)
+ public void runTestRunOnce(RunInfo info) {
+ testRunOnce();
+ }
+
+ @Test
+ public void testRunOnce2() {
+ executed[75]++;
+ }
+
+ @Run(test = "testRunOnce2", mode = RunMode.STANDALONE)
+ public void runTestRunOnce2(RunInfo info) {
+ for (int i = 0; i < TestVM.WARMUP_ITERATIONS + 1; i++) {
+ testRunOnce2();
+ }
+ }
+
+ @Test
+ public void testRunMultiple() {
+ executed[96]++;
+ }
+
+ @Test
+ public void testRunMultiple2() {
+ executed[97]++;
+ }
+
+ @Test
+ public void testRunMultipleNotExecuted() {
+ wasExecuted = true;
+ }
+
+ @Run(test = {"testRunMultiple", "testRunMultiple2", "testRunMultipleNotExecuted"})
+ public void runTestRunMultiple() {
+ testRunMultiple();
+ testRunMultiple2();
+ }
+
+
+ @Test
+ public void testRunMultiple3() {
+ executed[98]++;
+ }
+
+ @Test
+ public void testRunMultiple4() {
+ executed[99]++;
+ }
+
+ @Test
+ public void testRunMultipleNotExecuted2() {
+ wasExecuted = true;
+ }
+
+ @Run(test = {"testRunMultiple3", "testRunMultiple4", "testRunMultipleNotExecuted2"}, mode = RunMode.STANDALONE)
+ public void runTestRunMultipl2(RunInfo info) {
+ for (int i = 0; i < TestVM.WARMUP_ITERATIONS + 1; i++) {
+ testRunMultiple3();
+ testRunMultiple4();
+ }
+ }
+}
+
+class DefaultObject {
+ int i = 4;
+}
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestCompLevels.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestCompLevels.java
new file mode 100644
index 00000000000..4f373ca4027
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestCompLevels.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2021, 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.test.TestVM;
+
+import java.lang.reflect.Method;
+
+/*
+ * @test
+ * @requires vm.flagless
+ * @summary Test if compilation levels are used correctly in the framework.
+ * This test partly runs directly the test VM which normally does and should not happen in user tests.
+ * @library /test/lib /
+ * @build sun.hotspot.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -DSkipWhiteBoxInstall=true -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
+ * -Xbatch -XX:+WhiteBoxAPI ir_framework.tests.TestCompLevels
+ */
+
+public class TestCompLevels {
+ static int[] testExecuted = new int[5];
+
+ public static void main(String[] args) throws Exception {
+ Method runTestsOnSameVM = TestVM.class.getDeclaredMethod("runTestsOnSameVM", Class.class);
+ runTestsOnSameVM.setAccessible(true);
+ runTestsOnSameVM.invoke(null, new Object[]{null});
+
+ for (int i = 0; i < testExecuted.length; i++) {
+ int value = testExecuted[i];
+ if (value != TestVM.WARMUP_ITERATIONS + 1) {
+ // Warmups + 1 compiled invocation
+ throw new RuntimeException("Test " + i + " was executed " + value + " times stead of "
+ + TestVM.WARMUP_ITERATIONS + 1 + " times." );
+ }
+ }
+ TestFramework framework = new TestFramework(TestNoTiered.class);
+ framework.setDefaultWarmup(10).addFlags("-XX:-TieredCompilation").start();
+ framework = new TestFramework(TestNoTiered.class);
+ framework.setDefaultWarmup(10).addScenarios(new Scenario(0, "-XX:-TieredCompilation")).start();
+ framework = new TestFramework(TestStopAtLevel1.class);
+ framework.setDefaultWarmup(10).addFlags("-XX:TieredStopAtLevel=1").start();
+ framework = new TestFramework(TestStopAtLevel1.class);
+ framework.setDefaultWarmup(10).addScenarios(new Scenario(0, "-XX:TieredStopAtLevel=1")).start();
+ }
+
+ @Test(compLevel = CompLevel.C1_SIMPLE)
+ public void testC1() {
+ testExecuted[0]++;
+ }
+
+ @Check(test = "testC1", when = CheckAt.COMPILED)
+ public void checkTestC1(TestInfo info) {
+ TestFramework.assertCompiledAtLevel(info.getTest(), CompLevel.C1_SIMPLE);
+ }
+
+ @Test(compLevel = CompLevel.C1_LIMITED_PROFILE)
+ public void testC1Limited() {
+ testExecuted[1]++;
+ }
+
+ @Check(test = "testC1Limited", when = CheckAt.COMPILED)
+ public void checkTestLimited(TestInfo info) {
+ TestFramework.assertCompiledAtLevel(info.getTest(), CompLevel.C1_LIMITED_PROFILE);
+ }
+
+ @Test(compLevel = CompLevel.C1_FULL_PROFILE)
+ public void testC1Full() {
+ testExecuted[2]++;
+ }
+
+ @Check(test = "testC1Full", when = CheckAt.COMPILED)
+ public void checkTestC1Full(TestInfo info) {
+ TestFramework.assertCompiledAtLevel(info.getTest(), CompLevel.C1_FULL_PROFILE);
+ }
+
+ @Test(compLevel = CompLevel.C2)
+ public void testC2() {
+ testExecuted[3]++;
+ }
+
+ @Check(test = "testC2", when = CheckAt.COMPILED)
+ public void checkTestC2(TestInfo info) {
+ TestFramework.assertCompiledAtLevel(info.getTest(), CompLevel.C2);
+ }
+
+ @Test(compLevel = CompLevel.SKIP)
+ public void testSkip() {
+ testExecuted[4]++; // Executed by eventually not compiled by framework
+ }
+}
+
+class TestNoTiered {
+ @Test(compLevel = CompLevel.C1_SIMPLE)
+ public void level1() {
+ }
+
+ @Check(test = "level1")
+ public void check1(TestInfo info) {
+ TestFramework.assertNotCompiled(info.getTest()); // Never compiled without C1
+ }
+
+ @Test(compLevel = CompLevel.C1_LIMITED_PROFILE)
+ public void level2() {
+ }
+
+ @Check(test = "level2")
+ public void check2(TestInfo info) {
+ TestFramework.assertNotCompiled(info.getTest()); // Never compiled without C1
+ }
+
+ @Test(compLevel = CompLevel.C1_FULL_PROFILE)
+ public void level3() {
+ }
+
+ @Check(test = "level3")
+ public void check3(TestInfo info) {
+ TestFramework.assertNotCompiled(info.getTest()); // Never compiled without C1
+ }
+
+ @Test(compLevel = CompLevel.C2)
+ public void level4() {
+ }
+
+ @Check(test = "level4")
+ public void check4(TestInfo info) {
+ if (info.isWarmUp()) {
+ TestFramework.assertNotCompiled(info.getTest()); // Never compiled without C1
+ } else {
+ if (TestFramework.isC1Compiled(info.getTest())) {
+ throw new RuntimeException("Cannot be compiled with C1"); // Never compiled without C1
+ }
+ TestFramework.assertCompiledByC2(info.getTest());
+ }
+ }
+
+ @Test(compLevel = CompLevel.SKIP)
+ public void skip() {
+ }
+
+ @Check(test = "skip")
+ public void checkSkip(TestInfo info) {
+ TestFramework.assertNotCompiled(info.getTest()); // Never compiled
+ }
+}
+
+class TestStopAtLevel1 {
+ @Test(compLevel = CompLevel.C1_SIMPLE)
+ public int level1() {
+ return 34;
+ }
+
+ @Check(test = "level1")
+ public void check1(int result, TestInfo info) {
+ if (info.isWarmUp()) {
+ TestFramework.assertNotCompiled(info.getTest()); // Not compiled yet
+ } else {
+ TestFramework.assertCompiledByC1(info.getTest());
+ if (TestFramework.isC2Compiled(info.getTest())) {
+ throw new RuntimeException("Cannot be compiled by C2");
+ }
+ System.out.println("TestStopAtLevel1=" + result);
+ }
+ }
+
+ @Test(compLevel = CompLevel.C1_LIMITED_PROFILE)
+ public void level2() {
+ }
+
+ @Check(test = "level2")
+ public void check2(TestInfo info) {
+ TestFramework.assertNotCompiled(info.getTest()); // Never with level 2
+ }
+
+ @Test(compLevel = CompLevel.C1_FULL_PROFILE)
+ public void level3() {
+ }
+
+ @Check(test = "level3")
+ public void check3(TestInfo info) {
+ TestFramework.assertNotCompiled(info.getTest()); // Never with level 3
+ }
+
+ @Test(compLevel = CompLevel.C2)
+ public void level4() {
+ }
+
+ @Check(test = "level4")
+ public void check4(TestInfo info) {
+ TestFramework.assertNotCompiled(info.getTest()); // Never with level 4
+ }
+
+ @Test(compLevel = CompLevel.SKIP)
+ public void skip() {
+ }
+
+ @Check(test = "skip")
+ public void checkSkip(TestInfo info) {
+ TestFramework.assertNotCompiled(info.getTest()); // Never compiled
+ }
+}
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestControls.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestControls.java
new file mode 100644
index 00000000000..8dad488740a
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestControls.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2021, 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.Compiler;
+import compiler.lib.ir_framework.test.TestVM;
+import jdk.test.lib.Asserts;
+import sun.hotspot.WhiteBox;
+
+import java.lang.reflect.Method;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/*
+ * @test
+ * @requires vm.debug == true & vm.compMode != "Xint" & vm.compiler2.enabled & vm.flagless
+ * @summary Test if compilation control annotaions are handled correctly in the framework.
+ * This test partly runs directly the test VM which normally does and should not happen in user tests.
+ * @library /test/lib /
+ * @build sun.hotspot.WhiteBox
+ * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -DSkipWhiteBoxInstall=true -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
+ * -Xbatch -XX:+WhiteBoxAPI ir_framework.tests.TestControls
+ */
+
+public class TestControls {
+ static int[] executed = new int[15];
+ static boolean wasExecuted = false;
+ static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+ public int iFld;
+
+ public static void main(String[] args) throws Exception {
+ Method runTestsOnSameVM = TestVM.class.getDeclaredMethod("runTestsOnSameVM", Class.class);
+ runTestsOnSameVM.setAccessible(true);
+ runTestsOnSameVM.invoke(null, new Object[]{ null });
+ final int defaultIterations = TestVM.WARMUP_ITERATIONS + 1;
+ Asserts.assertEQ(executed[0], 1001);
+ Asserts.assertEQ(executed[1], 101);
+ Asserts.assertEQ(executed[2], 10000);
+ Asserts.assertEQ(executed[3], 10000);
+ Asserts.assertEQ(executed[4], defaultIterations);
+ Asserts.assertEQ(executed[5], defaultIterations);
+ Asserts.assertEQ(executed[6], 5001);
+ Asserts.assertEQ(executed[7], 5001);
+ Asserts.assertEQ(executed[8], 1);
+ Asserts.assertEQ(executed[9], 5000);
+ Asserts.assertEQ(executed[10], 1);
+ Asserts.assertEQ(executed[11], 2);
+ Asserts.assertEQ(executed[12], 1);
+ Asserts.assertEQ(executed[13], 1);
+ Asserts.assertFalse(wasExecuted);
+ final long started = System.currentTimeMillis();
+ long elapsed = 0;
+ Method overloadDouble = TestControls.class.getDeclaredMethod("overload", double.class);
+ Method overloadInt = TestControls.class.getDeclaredMethod("overload", int.class);
+ while (!(TestFramework.isC2Compiled(overloadInt) && TestFramework.isCompiledAtLevel(overloadDouble, CompLevel.C1_LIMITED_PROFILE)) && elapsed < 5000) {
+ elapsed = System.currentTimeMillis() - started;
+ }
+ TestFramework.assertCompiledAtLevel(TestControls.class.getDeclaredMethod("overload", double.class), CompLevel.C1_LIMITED_PROFILE);
+ TestFramework.assertCompiledByC2(TestControls.class.getDeclaredMethod("overload", int.class));
+
+ TestFramework framework = new TestFramework(ClassInitializerTest.class);
+ framework.addFlags("-XX:+PrintCompilation").addHelperClasses(ClassInitializerHelper.class).start();
+ String output = TestFramework.getLastTestVMOutput();
+ Pattern p = Pattern.compile("4.*ClassInitializerTest::");
+ Matcher m = p.matcher(output);
+ Asserts.assertTrue(m.find());
+ p = Pattern.compile("2.*ClassInitializerHelper::");
+ m = p.matcher(output);
+ Asserts.assertTrue(m.find());
+
+ new TestFramework(TestWarmup.class).setDefaultWarmup(500).start();
+ TestFramework.run(ExplicitSkip.class);
+ }
+
+ @Test
+ @Warmup(1000)
+ public void test1() {
+ executed[0]++;
+ }
+
+ @Check(test = "test1")
+ public void check1(TestInfo info) {
+ if (executed[0] <= 1000) {
+ Asserts.assertTrue(info.isWarmUp());
+ } else {
+ Asserts.assertTrue(!info.isWarmUp() && executed[0] == 1001);
+ TestFramework.assertCompiledByC2(info.getTest());
+ }
+ }
+
+ @Test
+ @Warmup(100)
+ public void test2() {
+ executed[1]++;
+ }
+
+ @Check(test = "test2", when = CheckAt.COMPILED)
+ public void check2(TestInfo info) {
+ Asserts.assertTrue(!info.isWarmUp() && executed[1] == 101);
+ TestFramework.assertCompiledByC2(info.getTest());
+ }
+
+ @Test
+ public void overload() {
+ executed[4]++;
+ }
+
+ @ForceCompile
+ @DontInline
+ public static void overload(int i) {
+ wasExecuted = true;
+ }
+
+ @ForceCompile(CompLevel.C1_LIMITED_PROFILE)
+ @ForceInline
+ public static void overload(double i) {
+ wasExecuted = true;
+ }
+
+ @Check(test = "overload")
+ public void checkOverload() {
+ executed[5]++;
+ }
+
+ @Test
+ public void testDontCompile() {
+ executed[2]++;
+ }
+
+ @DontCompile
+ public static void dontCompile() {
+ executed[3]++;
+ }
+
+ @Run(test = "testDontCompile", mode = RunMode.STANDALONE)
+ public void runTestDontCompile() throws NoSuchMethodException {
+ for (int i = 0; i < 10000; i++) {
+ dontCompile(); // Should not compile this method
+ testDontCompile();
+ }
+ TestFramework.assertNotCompiled(TestControls.class.getDeclaredMethod("dontCompile"));
+ }
+
+ @Test
+ public void testCompileAtLevel1() {
+ executed[6]++;
+ }
+
+ @DontCompile(Compiler.ANY)
+ public static void dontCompile2() {
+ executed[7]++;
+ }
+
+ @Run(test = "testCompileAtLevel1")
+ @Warmup(5000)
+ public void runTestDontCompile2(RunInfo info) throws NoSuchMethodException {
+ dontCompile2();
+ testCompileAtLevel1();
+ if (!info.isWarmUp()) {
+ executed[8]++;
+ int compLevel = WHITE_BOX.getMethodCompilationLevel(TestControls.class.getDeclaredMethod("dontCompile2"), false);
+ Asserts.assertLessThan(compLevel, CompLevel.C1_LIMITED_PROFILE.getValue());
+ } else {
+ executed[9]++;
+ }
+ }
+
+ @Test
+ @Warmup(0)
+ public void noWarmup() {
+ executed[10]++;
+ }
+
+ @Test
+ public void noWarmup2() {
+ executed[11]++;
+ }
+
+ @Run(test = "noWarmup2")
+ @Warmup(0)
+ public void runNoWarmup2(RunInfo info) {
+ noWarmup2();
+ noWarmup2();
+ Asserts.assertTrue(!info.isWarmUp());
+ executed[12]++;
+ }
+
+ @Test
+ public void testCompilation() {
+ wasExecuted = true;
+ }
+
+ @DontCompile(Compiler.ANY)
+ public void dontCompileAny() {
+ for (int i = 0; i < 10; i++) {
+ iFld = i;
+ }
+ }
+
+ @DontCompile(Compiler.C1)
+ public void dontCompileC1() {
+ for (int i = 0; i < 10; i++) {
+ iFld = 3;
+ }
+ }
+
+ @DontCompile(Compiler.C2)
+ public void dontCompileC2(int x, boolean b) {
+ for (int i = 0; i < 10; i++) {
+ iFld = x;
+ }
+ }
+
+ // Default is C2.
+ @ForceCompile
+ public void forceCompileDefault() {
+ wasExecuted = true;
+ }
+
+ // ANY maps to C2.
+ @ForceCompile
+ public void forceCompileAny() {
+ wasExecuted = true;
+ }
+
+ @ForceCompile(CompLevel.C1_SIMPLE)
+ public void forceCompileC1() {
+ wasExecuted = true;
+ }
+
+ @ForceCompile(CompLevel.C1_LIMITED_PROFILE)
+ public void forceCompileC1Limited() {
+ wasExecuted = true;
+ }
+
+ @ForceCompile(CompLevel.C1_FULL_PROFILE)
+ public void forceCompileC1Full() {
+ wasExecuted = true;
+ }
+
+ @ForceCompile(CompLevel.C2)
+ public void forceCompileC2() {
+ wasExecuted = true;
+ }
+
+ @ForceCompile(CompLevel.C1_SIMPLE)
+ @DontCompile(Compiler.C2)
+ public void forceC1DontC2() {
+ wasExecuted = true;
+ }
+
+ @ForceCompile(CompLevel.C2)
+ @DontCompile(Compiler.C1)
+ public void forceC2DontC1() {
+ wasExecuted = true;
+ }
+
+ @Run(test = "testCompilation")
+ @Warmup(0)
+ public void runTestCompilation(RunInfo info) {
+ for (int i = 0; i < 100000; i++) {
+ dontCompileAny();
+ dontCompileC1();
+ dontCompileC2(i, i % 2 == 0);
+ }
+ TestFramework.assertCompiledByC2(info.getTest());
+ TestFramework.assertNotCompiled(info.getTestClassMethod("dontCompileAny"));
+ TestFramework.assertCompiledByC2(info.getTestClassMethod("dontCompileC1"));
+ TestFramework.assertCompiledByC1(info.getTestClassMethod("dontCompileC2", int.class, boolean.class));
+
+ TestFramework.assertCompiledAtLevel(info.getTestClassMethod("forceCompileDefault"), CompLevel.C2);
+ TestFramework.assertCompiledAtLevel(info.getTestClassMethod("forceCompileAny"), CompLevel.C2);
+ TestFramework.assertCompiledAtLevel(info.getTestClassMethod("forceCompileC2"), CompLevel.C2);
+ TestFramework.assertCompiledAtLevel(info.getTestClassMethod("forceCompileC1"), CompLevel.C1_SIMPLE);
+ TestFramework.assertCompiledAtLevel(info.getTestClassMethod("forceCompileC1Limited"), CompLevel.C1_LIMITED_PROFILE);
+ TestFramework.assertCompiledAtLevel(info.getTestClassMethod("forceCompileC1Full"), CompLevel.C1_FULL_PROFILE);
+
+ TestFramework.assertCompiledAtLevel(info.getTestClassMethod("forceC1DontC2"), CompLevel.C1_SIMPLE);
+ TestFramework.assertCompiledAtLevel(info.getTestClassMethod("forceC2DontC1"), CompLevel.C2);
+ executed[13]++;
+ }
+}
+
+@ForceCompileClassInitializer
+class ClassInitializerTest {
+
+ static int i;
+ static Object o;
+ static {
+ i = 3;
+ o = new Object();
+ }
+ @Test
+ public void test() {}
+}
+
+@ForceCompileClassInitializer(CompLevel.C1_LIMITED_PROFILE)
+class ClassInitializerHelper {
+ static int i;
+ static {
+ i = 3;
+ }
+}
+
+class TestWarmup {
+ int iFld;
+ int iFld2;
+ int iFldCheck;
+ int iFldCheck2;
+
+ @Test
+ @Warmup(200)
+ public void test() {
+ iFld++;
+ }
+
+ @Test
+ public void test2() {
+ iFld2++;
+ }
+
+ @Check(test = "test")
+ public void checkTest(TestInfo info) {
+ iFldCheck++;
+ if (iFldCheck != iFld) {
+ throw new RuntimeException(iFld + " must be equal " + iFldCheck);
+ }
+ if (!info.isWarmUp()) {
+ if (iFld != 201) {
+ throw new RuntimeException("Must be 201 but was " + iFld);
+ }
+ }
+ }
+
+ @Check(test = "test2")
+ public void checkTest2(TestInfo info) {
+ iFldCheck2++;
+ if (iFldCheck2 != iFld2) {
+ throw new RuntimeException(iFld2 + " must be equal " + iFldCheck2);
+ }
+ if (!info.isWarmUp()) {
+ if (iFld2 != 501) {
+ throw new RuntimeException("Must be 501 but was " + iFld2);
+ }
+ }
+ }
+}
+
+
+class ExplicitSkip {
+ int iFld;
+
+ // Test skipped and thus also no IR verification should be done.
+ @Test(compLevel = CompLevel.SKIP)
+ @IR(counts = {IRNode.STORE_I, "1"})
+ public int test(int x) {
+ iFld = x;
+ return x;
+ }
+
+ @Run(test = "test")
+ public void run(RunInfo info) {
+ test(34);
+ }
+}
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDFlags.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDFlags.java
new file mode 100644
index 00000000000..752ba5c0e44
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDFlags.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2021, 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.Test;
+import compiler.lib.ir_framework.TestFramework;
+/*
+ * @test
+ * @requires vm.debug == true & vm.compMode != "Xint" & vm.compiler2.enabled & vm.flagless
+ * @summary Sanity test remaining framework property flags.
+ * @library /test/lib /
+ * @run main/othervm -DFlipC1C2=true ir_framework.tests.TestDFlags
+ * @run main/othervm -DExcludeRandom=true ir_framework.tests.TestDFlags
+ * @run main/othervm -DVerifyVM=true ir_framework.tests.TestDFlags
+ * @run main/othervm -DDumpReplay=true ir_framework.tests.TestDFlags
+ * @run main/othervm -DVerbose=true ir_framework.tests.TestDFlags
+ * @run main/othervm -DShuffleTests=false ir_framework.tests.TestDFlags
+ * @run main/othervm -DReproduce=true ir_framework.tests.TestDFlags
+ * @run main/othervm -DReportStdout=true ir_framework.tests.TestDFlags
+ * @run main/othervm -DGCAfter=true ir_framework.tests.TestDFlags
+ * @run main/othervm -DPrintTimes=true ir_framework.tests.TestDFlags
+ * @run main/othervm -DVerifyIR=false ir_framework.tests.TestDFlags
+ */
+
+public class TestDFlags {
+ public static void main(String[] args) {
+ TestFramework.run();
+ }
+
+ @Test
+ public int c1() {
+ return 34;
+ }
+
+
+ @Test
+ public void c2() {
+ for (int i = 0; i < 100; i++) {
+ }
+ }
+
+ @Test
+ public void c2_2() {
+ for (int i = 0; i < 100; i++) {
+ }
+ }
+
+ @Test
+ public void c2_3() {
+ for (int i = 0; i < 100; i++) {
+ }
+ }
+}
+
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDIgnoreCompilerControls.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDIgnoreCompilerControls.java
new file mode 100644
index 00000000000..47a6ae6e310
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDIgnoreCompilerControls.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2021, 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 jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import sun.hotspot.WhiteBox;
+
+/*
+ * @test
+ * @requires vm.debug == true & vm.flagless
+ * @summary Test -DIgnoreCompilerControls property flag.
+ * @library /test/lib /
+ * @run driver ir_framework.tests.TestDIgnoreCompilerControls
+ */
+
+public class TestDIgnoreCompilerControls {
+ public static void main(String[] args) throws Exception {
+ if (args.length != 0) {
+ TestFramework.run();
+ } else {
+ OutputAnalyzer oa = run("true");
+ oa.shouldHaveExitValue(0);
+ oa = run("false");
+ oa.shouldNotHaveExitValue(0);
+ Asserts.assertTrue(oa.getOutput().contains("fail run"), "did not find run: " + oa.getOutput());
+ Asserts.assertTrue(oa.getOutput().contains("fail check"), "did not find check" + oa.getOutput());
+ }
+ }
+
+ private static OutputAnalyzer run(String flagValue) throws Exception {
+ OutputAnalyzer oa;
+ ProcessBuilder process = ProcessTools.createJavaProcessBuilder(
+ "-Dtest.class.path=" + Utils.TEST_CLASS_PATH, "-Dtest.jdk=" + Utils.TEST_JDK,
+ "-Dtest.vm.opts=-DIgnoreCompilerControls=" + flagValue,
+ "ir_framework.tests.TestDIgnoreCompilerControls", flagValue);
+ oa = ProcessTools.executeProcess(process);
+ return oa;
+ }
+
+ @Test
+ public void test() { }
+
+ @Run(test = "test")
+ @Warmup(10000)
+ public void run(RunInfo info) throws NoSuchMethodException {
+ if (!info.isWarmUp()) {
+ // Should be compiled with -DIgnoreCompilerControls=true
+ Asserts.assertTrue(WhiteBox.getWhiteBox().isMethodCompiled(getClass().getDeclaredMethod("run", RunInfo.class)), "fail run");
+ }
+ }
+
+ @Test
+ @Warmup(10000)
+ public void test2() {}
+
+
+ @Check(test = "test2")
+ public void check(TestInfo info) throws NoSuchMethodException {
+ if (!info.isWarmUp()) {
+ // Should be compiled with -DIgnoreCompilerControls=true
+ Asserts.assertTrue(WhiteBox.getWhiteBox().isMethodCompiled(getClass().getDeclaredMethod("check", TestInfo.class)), "fail check");
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDScenarios.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDScenarios.java
new file mode 100644
index 00000000000..10a49f9a3c7
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDScenarios.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021, 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.Scenario;
+import compiler.lib.ir_framework.Test;
+import compiler.lib.ir_framework.TestFramework;
+import compiler.lib.ir_framework.driver.TestVMException;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+/*
+ * @test
+ * @requires vm.debug == true & vm.flagless
+ * @summary Test -DScenarios property flag. Run with othervm which should not be done when writing tests using the framework.
+ * @library /test/lib /
+ * @run main/othervm -DScenarios=1,5,10 ir_framework.tests.TestDScenarios test
+ * @run main/othervm -DScenarios=1,4 ir_framework.tests.TestDScenarios test
+ * @run main/othervm -DScenarios=3,4,9 ir_framework.tests.TestDScenarios test
+ * @run driver ir_framework.tests.TestDScenarios test2
+ * @run driver ir_framework.tests.TestDScenarios
+ */
+
+public class TestDScenarios {
+ public static void main(String[] args) throws Exception {
+ if (args.length > 0) {
+ switch (args[0]) {
+ case "test" -> {
+ Scenario s1 = new Scenario(1);
+ Scenario s2 = new Scenario(5);
+ Scenario s3 = new Scenario(10);
+ Scenario bad = new Scenario(0, "-Flagdoesnotexist"); // not executed
+ new TestFramework().addScenarios(bad, s1, s2, s3).start();
+ }
+ case "test2" -> {
+ try {
+ TestFramework.run(DScenariosBad.class);
+ throw new RuntimeException("should not reach");
+ } catch (TestVMException e) {
+ System.out.println(e.getExceptionInfo());
+ Asserts.assertTrue(e.getExceptionInfo().contains("Expected DScenariosBad exception"));
+ }
+ }
+ default -> {
+ // Invalid -DScenarios set and thus exception thrown when Scenario class is statically initialized.
+ Scenario s = new Scenario(3);
+ throw new RuntimeException("should not reach");
+ }
+ }
+ } else {
+ // Test invalid -DScenario flag.
+ OutputAnalyzer oa;
+ ProcessBuilder process = ProcessTools.createJavaProcessBuilder(
+ "-Dtest.jdk=" + Utils.TEST_JDK, "-DScenarios=a,1,b,10",
+ "ir_framework.tests.TestDScenarios", " test3");
+ oa = ProcessTools.executeProcess(process);
+ oa.shouldNotHaveExitValue(0);
+ System.out.println(oa.getOutput());
+ Asserts.assertTrue(oa.getOutput().contains("TestRunException: Provided a scenario index"));
+ }
+ }
+
+ @Test
+ public void test() {
+ }
+}
+
+class DScenariosBad {
+ @Test
+ public void test() {
+ throw new RuntimeException("Expected DScenariosBad exception");
+ }
+}
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDTestAndExclude.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDTestAndExclude.java
new file mode 100644
index 00000000000..b74012fd54a
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestDTestAndExclude.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2021, 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.Check;
+import compiler.lib.ir_framework.Run;
+import compiler.lib.ir_framework.Test;
+import compiler.lib.ir_framework.TestFramework;
+import compiler.lib.ir_framework.driver.TestVMException;
+import compiler.lib.ir_framework.shared.NoTestsRunException;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.Utils;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+/*
+ * @test
+ * @requires vm.flagless
+ * @summary Test -DTest and -DExclude property flag.
+ * @library /test/lib /
+ * @run driver ir_framework.tests.TestDTestAndExclude
+ */
+
+public class TestDTestAndExclude {
+ public static void main(String[] args) throws Exception {
+ if (args.length == 0) {
+ run("good1,good2", "", "good");
+ run("good1,good2", "bad1", "good");
+ run("good1,bad1", "bad1", "good");
+ run("good1,bad1", "bad1,good", "good");
+ run("good3,bad2", "bad1,bad2", "good");
+ run("goodMulti1,goodMulti2", "", "good");
+ run("bad1,good1", "", "bad1");
+ run("bad1,good1", "good1", "bad1");
+ run("bad1,good1", "asdf", "bad1");
+ run("bad2,good1", "", "runBadSingle");
+ run("bad2", "runBadSingle", "runBadSingle");
+ run("badMulti1,badMulti2", "", "runBadMulti");
+ run("badMulti1", "", "runBadMulti");
+ run("badMulti1", "badMulti2", "runBadMulti");
+ run("badMulti2", "badMulti1", "runBadMulti");
+ run("runBadSingle", "", "empty");
+ run("runBadMulti", "", "empty");
+ run("asdf", "", "empty");
+ run("", "good1,good2,good3,bad1,bad2,goodMulti1,goodMulti2,badMulti1,badMulti2", "empty");
+ run("asdf", "good1,good2,good3,bad1,bad2,goodMulti1,goodMulti2,badMulti1,badMulti2", "empty");
+ run("bad1", "bad1", "empty");
+ run("good1", "asdf,good,good1", "empty");
+ } else {
+ switch (args[0]) {
+ case "good" -> TestFramework.run();
+ case "bad1", "runBadMulti", "runBadSingle" -> {
+ try {
+ TestFramework.run();
+ throw new RuntimeException("should not reach");
+ } catch (TestVMException e) {
+ Asserts.assertTrue(e.getExceptionInfo().contains("expected " + args[0] + " exception"));
+ }
+ }
+ case "empty" -> {
+ try {
+ TestFramework.run();
+ throw new RuntimeException("should not reach");
+ } catch (NoTestsRunException e) {
+ // Expected
+ }
+ }
+ default -> throw new RuntimeException("should not reach");
+ }
+ }
+ }
+
+ /**
+ * Create a VM and simulate as if it was a driver VM spawned by JTreg that has -DTest/DExclude set as VM or Javaopts
+ */
+ protected static void run(String dTest, String dExclude, String arg) throws Exception {
+ System.out.println("Run -DTest=" + dTest + " -DExclude=" + dExclude + " arg=" + arg);
+ OutputAnalyzer oa;
+ ProcessBuilder process = ProcessTools.createJavaProcessBuilder(
+ "-Dtest.class.path=" + Utils.TEST_CLASS_PATH, "-Dtest.jdk=" + Utils.TEST_JDK,
+ "-Dtest.vm.opts=-DTest=" + dTest + " -DExclude=" + dExclude,
+ "ir_framework.tests.TestDTestAndExclude", arg);
+ oa = ProcessTools.executeProcess(process);
+ oa.shouldHaveExitValue(0);
+ }
+
+ @Test
+ public void good1() { }
+
+ @Test
+ public void good2() { }
+
+ @Check(test = "good2")
+ public void check2() {}
+
+ @Test
+ public void bad1() {
+ throw new RuntimeException("expected bad1 exception");
+ }
+
+ @Test
+ public void good3() {}
+
+ @Test
+ public void goodMulti1() {}
+
+ @Test
+ public void goodMulti2() {}
+
+ @Run(test = "good3")
+ public void runGoodSingle() {
+ good3();
+ }
+
+ @Run(test = {"goodMulti1", "goodMulti2"})
+ public void runGoodMulti() {
+ goodMulti1();
+ goodMulti2();
+ }
+
+ @Test
+ public void bad2() {
+ }
+
+ @Test
+ public void badMulti1() {
+ }
+
+ @Test
+ public void badMulti2() {
+ }
+
+ @Run(test = "bad2")
+ public void runBadSingle() {
+ throw new RuntimeException("expected runBadSingle exception");
+ }
+
+ @Run(test = {"badMulti1", "badMulti2"})
+ public void runBadMulti() {
+ throw new RuntimeException("expected runBadMulti exception");
+ }
+}
+
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java
new file mode 100644
index 00000000000..344ff1213a9
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java
@@ -0,0 +1,1628 @@
+/*
+ * Copyright (c) 2021, 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.driver.IRViolationException;
+import jdk.test.lib.Asserts;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/*
+ * @test
+ * @requires vm.debug == true & vm.compMode != "Xint" & vm.compiler2.enabled & vm.flagless
+ * @summary Test IR matcher with different default IR node regexes. Use -DPrintIREncoding.
+ * Normally, the framework should be called with driver.
+ * @library /test/lib /
+ * @run main/othervm -DPrintIREncoding=true ir_framework.tests.TestIRMatching
+ */
+
+public class TestIRMatching {
+
+ public static void main(String[] args) {
+ runFailOnTestsArgs(BadFailOnConstraint.create(AndOr1.class, "test1(int)", 1, "CallStaticJava"), "-XX:TLABRefillWasteFraction=50", "-XX:+UsePerfData", "-XX:+UseTLAB");
+ runFailOnTestsArgs(BadFailOnConstraint.create(AndOr1.class, "test2()", 1, "CallStaticJava"), "-XX:TLABRefillWasteFraction=50", "-XX:-UsePerfData", "-XX:+UseTLAB");
+
+ runWithArguments(AndOr1.class, "-XX:TLABRefillWasteFraction=52", "-XX:+UsePerfData", "-XX:+UseTLAB");
+ runWithArguments(CountComparisons.class, "-XX:TLABRefillWasteFraction=50");
+ runWithArguments(GoodCount.class, "-XX:TLABRefillWasteFraction=50");
+ runWithArguments(MultipleFailOnGood.class, "-XX:TLABRefillWasteFraction=50");
+
+ String[] allocMatches = { "MyClass", "call,static wrapper for: _new_instance_Java" };
+ runCheck(BadFailOnConstraint.create(MultipleFailOnBad.class, "fail1()", 1, 1, "Store"),
+ BadFailOnConstraint.create(MultipleFailOnBad.class, "fail1()", 1, 3, "Store"),
+ GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail1()", 1, 2, 4),
+ GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail2()", 1, 1),
+ BadFailOnConstraint.create(MultipleFailOnBad.class, "fail2()", 1, 2, "CallStaticJava"),
+ BadFailOnConstraint.create(MultipleFailOnBad.class, "fail3()", 1, 2, "Store"),
+ GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail3()", 1, 1, 3),
+ BadFailOnConstraint.create(MultipleFailOnBad.class, "fail4()", 1, 1, "Store"),
+ GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail4()", 1, 2, 3),
+ BadFailOnConstraint.create(MultipleFailOnBad.class, "fail5()", 1, 1, "Store"),
+ GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail5()", 1, 2, 3),
+ GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail6()", 1, 1),
+ BadFailOnConstraint.create(MultipleFailOnBad.class, "fail6()", 1, 2, allocMatches),
+ BadFailOnConstraint.create(MultipleFailOnBad.class, "fail6()", 1, 3, "CallStaticJava"),
+ GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail7()", 1, 1),
+ BadFailOnConstraint.create(MultipleFailOnBad.class, "fail7()", 1, 2, allocMatches),
+ GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail8()", 1, 1),
+ BadFailOnConstraint.create(MultipleFailOnBad.class, "fail8()", 1, 2, allocMatches),
+ BadFailOnConstraint.create(MultipleFailOnBad.class, "fail9()", 1, 1, "Store"),
+ BadFailOnConstraint.create(MultipleFailOnBad.class, "fail9()", 1, 2, "CallStaticJava"),
+ BadFailOnConstraint.create(MultipleFailOnBad.class, "fail10()", 1, 1, "Store", "iFld"),
+ GoodFailOnRegexConstraint.create(MultipleFailOnBad.class, "fail10()", 1, 2, 3)
+ );
+
+ runCheck(BadCountsConstraint.create(BadCount.class, "bad1()", 1, 1, "Load"),
+ GoodCountsConstraint.create(BadCount.class, "bad1()", 2),
+ GoodCountsConstraint.create(BadCount.class, "bad2()", 1),
+ BadCountsConstraint.create(BadCount.class, "bad2()", 2, 1, "Store"),
+ BadCountsConstraint.create(BadCount.class, "bad3()", 1, 1, "Load"),
+ BadCountsConstraint.create(BadCount.class, "bad3()", 2, 1, "Store")
+ );
+
+ String[] allocArrayMatches = { "MyClass", "call,static wrapper for: _new_array_Java"};
+ runCheck(BadFailOnConstraint.create(AllocArray.class, "allocArray()", 1, allocArrayMatches),
+ BadFailOnConstraint.create(AllocArray.class, "allocArray()", 2, allocArrayMatches),
+ GoodFailOnConstraint.create(AllocArray.class, "allocArray()", 3),
+ GoodFailOnConstraint.create(AllocArray.class, "allocArray()", 4),
+ BadFailOnConstraint.create(AllocArray.class, "allocArray()", 5, allocArrayMatches)
+ );
+
+ runCheck(GoodRuleConstraint.create(RunTests.class, "good1()", 1),
+ GoodRuleConstraint.create(RunTests.class, "good1()", 2),
+ GoodRuleConstraint.create(RunTests.class, "good2()", 1),
+ GoodRuleConstraint.create(RunTests.class, "good2()", 2),
+ GoodRuleConstraint.create(RunTests.class, "good3(int)", 1),
+ BadCountsConstraint.create(RunTests.class, "bad1(int)", 1, 0),
+ BadFailOnConstraint.create(RunTests.class, "bad1(int)", 2, "Load")
+ );
+
+ runCheck(new String[] {"-XX:-UseCompressedClassPointers"},
+ BadFailOnConstraint.create(Loads.class, "load()", 1, 1, "Load"),
+ BadFailOnConstraint.create(Loads.class, "load()", 1, 3, "LoadI"),
+ BadCountsConstraint.create(Loads.class, "load()", 1, 1, 0),
+ BadCountsConstraint.create(Loads.class, "load()", 1, 2, 1,"Load"),
+ GoodRuleConstraint.create(Loads.class, "load()", 2),
+ GoodFailOnConstraint.create(Loads.class, "load()", 3),
+ BadCountsConstraint.create(Loads.class, "load()", 3, 2, 2,"Store"),
+ BadFailOnConstraint.create(Loads.class, "load()", 4, 2, "Store"),
+ BadFailOnConstraint.create(Loads.class, "load()", 5, "Load"),
+ BadFailOnConstraint.create(Loads.class, "load()", 6, "Load"),
+ BadFailOnConstraint.create(Loads.class, "load()", 7, "Load"),
+ GoodRuleConstraint.create(Loads.class, "load()", 8),
+ GoodRuleConstraint.create(Loads.class, "load()", 9),
+ GoodRuleConstraint.create(Loads.class, "load()", 10),
+ BadFailOnConstraint.create(Loads.class, "loadKlass()", 1),
+ BadCountsConstraint.create(Loads.class, "loadKlass()", 2, 2,"Field")
+ );
+
+ // Loops
+ runCheck(BadFailOnConstraint.create(Loops.class, "loop()", 1, "Loop"),
+ GoodRuleConstraint.create(Loops.class, "loop()", 2),
+ GoodRuleConstraint.create(Loops.class, "loop()", 3),
+ GoodRuleConstraint.create(Loops.class, "countedLoop()", 1),
+ BadFailOnConstraint.create(Loops.class, "countedLoop()", 2, "CountedLoop"),
+ GoodRuleConstraint.create(Loops.class, "countedLoop()", 3),
+ BadFailOnConstraint.create(Loops.class, "loopAndCountedLoop()", 1, "Loop"),
+ BadFailOnConstraint.create(Loops.class, "loopAndCountedLoop()", 2, "CountedLoop"),
+ GoodRuleConstraint.create(Loops.class, "loopAndCountedLoop()", 3),
+ GoodRuleConstraint.create(Loops.class, "countedLoopMain()", 1),
+ BadFailOnConstraint.create(Loops.class, "countedLoopMain()", 2, "CountedLoop"),
+ BadFailOnConstraint.create(Loops.class, "countedLoopMain()", 3, "CountedLoop", "main"),
+ GoodRuleConstraint.create(Loops.class, "countedLoopUnrolled()", 1),
+ GoodRuleConstraint.create(Loops.class, "countedLoopUnrolled()", 2),
+ GoodRuleConstraint.create(Loops.class, "countedLoopUnrolled()", 3)
+ );
+
+ // Traps
+ runCheck(GoodRuleConstraint.create(Traps.class, "noTraps()", 1),
+ BadFailOnConstraint.create(Traps.class, "noTraps()", 2, "Store", "iFld"),
+ GoodRuleConstraint.create(Traps.class, "noTraps()", 3),
+ BadFailOnConstraint.create(Traps.class, "predicateTrap()", 1, "CallStaticJava", "uncommon_trap"),
+ BadFailOnConstraint.create(Traps.class, "predicateTrap()", 2, "CallStaticJava", "uncommon_trap", "predicate"),
+ GoodRuleConstraint.create(Traps.class, "predicateTrap()", 3),
+ GoodRuleConstraint.create(Traps.class, "predicateTrap()", 4),
+ BadFailOnConstraint.create(Traps.class, "nullCheck()", 1, "CallStaticJava", "uncommon_trap"),
+ BadFailOnConstraint.create(Traps.class, "nullCheck()", 2, "CallStaticJava", "uncommon_trap", "null_check"),
+ BadFailOnConstraint.create(Traps.class, "nullCheck()", 3, "uncommon_trap", "unstable_if"),
+ GoodRuleConstraint.create(Traps.class, "nullCheck()", 4),
+ BadFailOnConstraint.create(Traps.class, "nullAssert()", 1, "CallStaticJava", "uncommon_trap"),
+ BadFailOnConstraint.create(Traps.class, "nullAssert()", 2, "CallStaticJava", "uncommon_trap", "null_assert"),
+ BadFailOnConstraint.create(Traps.class, "nullAssert()", 3, "CallStaticJava", "uncommon_trap", "null_check"),
+ GoodRuleConstraint.create(Traps.class, "nullAssert()", 4),
+ BadFailOnConstraint.create(Traps.class, "unstableIf(boolean)", 1, "CallStaticJava", "uncommon_trap"),
+ BadFailOnConstraint.create(Traps.class, "unstableIf(boolean)", 2, "CallStaticJava", "uncommon_trap", "unstable_if"),
+ GoodRuleConstraint.create(Traps.class, "unstableIf(boolean)", 3),
+ BadFailOnConstraint.create(Traps.class, "classCheck()", 1, "CallStaticJava", "uncommon_trap"),
+ BadFailOnConstraint.create(Traps.class, "classCheck()", 2, "CallStaticJava", "uncommon_trap", "class_check"),
+ BadFailOnConstraint.create(Traps.class, "classCheck()", 3, "CallStaticJava", "uncommon_trap", "null_check"),
+ GoodRuleConstraint.create(Traps.class, "classCheck()", 4),
+ BadFailOnConstraint.create(Traps.class, "rangeCheck()", 1, "CallStaticJava", "uncommon_trap"),
+ BadFailOnConstraint.create(Traps.class, "rangeCheck()", 2, "CallStaticJava", "uncommon_trap", "range_check"),
+ BadFailOnConstraint.create(Traps.class, "rangeCheck()", 3, "CallStaticJava", "uncommon_trap", "null_check"),
+ GoodRuleConstraint.create(Traps.class, "rangeCheck()", 4),
+ BadFailOnConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 1, "CallStaticJava", "uncommon_trap"),
+ BadFailOnConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 2, "CallStaticJava", "uncommon_trap", "intrinsic_or_type_checked_inlining"),
+ BadFailOnConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 3, "CallStaticJava", "uncommon_trap", "null_check"),
+ GoodRuleConstraint.create(Traps.class, "instrinsicOrTypeCheckedInlining()", 4)
+ );
+
+
+ runCheck(new String[] {"-XX:+BailoutToInterpreterForThrows"},
+ BadFailOnConstraint.create(UnhandledTrap.class, "unhandled()", 1, "CallStaticJava", "uncommon_trap"),
+ BadFailOnConstraint.create(UnhandledTrap.class, "unhandled()", 2, "CallStaticJava", "uncommon_trap", "unhandled"),
+ GoodRuleConstraint.create(UnhandledTrap.class, "unhandled()", 3)
+ );
+
+ runCheck(BadFailOnConstraint.create(ScopeObj.class, "scopeObject()", 1, "ScObj"));
+ runCheck(BadFailOnConstraint.create(Membar.class, "membar()", 1, "MemBar"));
+ runCheck(BadFailOnConstraint.create(CheckCastArray.class, "array()", 1, "cmp", "precise klass"),
+ BadFailOnConstraint.create(CheckCastArray.class, "array()", 2, 1,"cmp", "precise klass", "MyClass"),
+ BadFailOnConstraint.create(CheckCastArray.class, "array()", 2, 2,"cmp", "precise klass", "ir_framework/tests/MyClass"),
+ GoodFailOnConstraint.create(CheckCastArray.class, "array()", 3),
+ BadFailOnConstraint.create(CheckCastArray.class, "arrayCopy(java.lang.Object[],java.lang.Class)", 1, "checkcast_arraycopy")
+ );
+
+ // Redirect stdout to stream and then check if we find required IR encoding read from socket.
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ PrintStream old = System.out;
+ System.setOut(ps);
+
+ try {
+ runWithArguments(CompilationOutputOfFails.class);
+ shouldNotReach();
+ } catch (IRViolationException e) {
+ System.out.flush();
+ String output = baos.toString();
+ baos.reset();
+ Pattern pattern = Pattern.compile(">>> Compilation.*both\\d.*\\RPrintIdeal:(?:(?!PrintOpto|>>> Compilation)[\\S\\s])+PrintOptoAssembly");
+ Matcher matcher = pattern.matcher(output);
+ Asserts.assertEQ(matcher.results().count(), (long)7, "Could not find all both methods: " + output);
+ pattern = Pattern.compile(">>> Compilation.*ideal\\d.*\\RPrintIdeal:(?:(?!>>> Compilation)[\\S\\s])+");
+ matcher = pattern.matcher(output);
+ int count = 0;
+ while (matcher.find()) {
+ String match = matcher.group();
+ Asserts.assertFalse(match.contains("PrintOptoAssembly"), "Cannot contain opto assembly: " + output);
+ count++;
+ }
+ Asserts.assertEQ(count, 7, "Could not find all ideal methods: " + output);
+ pattern = Pattern.compile(">>> Compilation.*opto\\d.*\\RPrintOptoAssembly:(?:(?!>>> Compilation)[\\S\\s])+");
+ matcher = pattern.matcher(output);
+ count = 0;
+ while (matcher.find()) {
+ String match = matcher.group();
+ Asserts.assertFalse(match.contains("PrintIdeal"), "Cannot contain opto assembly: " + output);
+ count++;
+ }
+ Asserts.assertEQ(count, 7, "Could not find all opto methods");
+ }
+
+ runWithArguments(FlagComparisons.class, "-XX:TLABRefillWasteFraction=50");
+ System.out.flush();
+ String output = baos.toString();
+ baos.reset();
+ findIrIds(output, "testMatchAllIf50", 0, 21);
+ findIrIds(output, "testMatchNoneIf50", -1, -1);
+
+ runWithArguments(FlagComparisons.class, "-XX:TLABRefillWasteFraction=49");
+ System.out.flush();
+ output = baos.toString();
+ baos.reset();
+ findIrIds(output, "testMatchAllIf50", 4, 6, 13, 18);
+ findIrIds(output, "testMatchNoneIf50", 0, 3, 8, 10, 17, 22);
+
+ runWithArguments(FlagComparisons.class, "-XX:TLABRefillWasteFraction=51");
+ System.out.flush();
+ output = baos.toString();
+ baos.reset();
+ findIrIds(output, "testMatchAllIf50", 7, 12, 19, 21);
+ findIrIds(output, "testMatchNoneIf50", 4, 7, 11, 16, 20, 22);
+ System.setOut(old);
+ }
+
+ private static void runWithArguments(Class> clazz, String... args) {
+ new TestFramework(clazz).addFlags(args).start();
+ }
+
+ private static void runCheck(String[] args , Constraint... constraints) {
+ try {
+ new TestFramework(constraints[0].getKlass()).addFlags(args).start(); // All constraints have the same class.
+ shouldNotReach();
+ } catch (IRViolationException e) {
+ checkConstraints(e, constraints);
+ }
+ }
+
+ private static void runCheck(Constraint... constraints) {
+ try {
+ TestFramework.run(constraints[0].getKlass()); // All constraints have the same class.
+ shouldNotReach();
+ } catch (IRViolationException e) {
+ checkConstraints(e, constraints);
+ }
+ }
+
+ private static void checkConstraints(IRViolationException e, Constraint[] constraints) {
+ String message = e.getExceptionInfo();
+ try {
+ for (Constraint constraint : constraints) {
+ constraint.checkConstraint(e);
+ }
+ } catch (Exception e1) {
+ System.out.println(TestFramework.getLastTestVMOutput());
+ System.out.println(message);
+ throw e1;
+ }
+ }
+
+ // Single constraint
+ private static void runFailOnTestsArgs(Constraint constraint, String... args) {
+ try {
+ new TestFramework(constraint.getKlass()).addFlags(args).start(); // All constraints have the same class.
+ shouldNotReach();
+ } catch (IRViolationException e) {
+ constraint.checkConstraint(e);
+ }
+ }
+
+ public static void shouldNotReach() {
+ throw new ShouldNotReachException("Framework did not fail but it should have!");
+ }
+
+ public static void findIrIds(String output, String method, int... numbers) {
+ StringBuilder builder = new StringBuilder();
+ builder.append(method);
+ 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(",");
+ builder.append(j);
+ }
+ }
+ Asserts.assertTrue(output.contains(builder.toString()), "Could not find encoding: \"" + builder.toString()
+ + System.lineSeparator());
+ }
+}
+
+class AndOr1 {
+ @Test
+ @Arguments(Argument.DEFAULT)
+ @IR(applyIfAnd = {"UsePerfData", "true", "TLABRefillWasteFraction", "50", "UseTLAB", "true"}, failOn = {IRNode.CALL})
+ public void test1(int i) {
+ dontInline();
+ }
+
+ @Test
+ @IR(applyIfOr = {"UsePerfData", "false", "TLABRefillWasteFraction", "51", "UseTLAB", "false"}, failOn = {IRNode.CALL})
+ public void test2() {
+ dontInline();
+ }
+
+ @DontInline
+ private void dontInline() {
+ }
+}
+
+class MultipleFailOnGood {
+ private int iFld;
+ private MyClassSub myClassSub = new MyClassSub();
+
+ @Test
+ @IR(applyIf = {"TLABRefillWasteFraction", "50"}, failOn = {IRNode.STORE, IRNode.CALL})
+ @IR(failOn = {IRNode.STORE, IRNode.CALL})
+ @IR(applyIfOr = {"TLABRefillWasteFraction", "99", "TLABRefillWasteFraction", "100"}, failOn = {IRNode.LOOP, IRNode.CALL}) // Not applied
+ public void good1() {
+ forceInline();
+ }
+
+ @Test
+ @IR(failOn = {IRNode.STORE, IRNode.CALL})
+ @IR(applyIfNot = {"TLABRefillWasteFraction", "20"}, failOn = {IRNode.ALLOC})
+ @IR(applyIfNot = {"TLABRefillWasteFraction", "< 100"}, failOn = {IRNode.ALLOC_OF, "Test"})
+ public void good2() {
+ forceInline();
+ }
+
+ @Test
+ @IR(failOn = {IRNode.STORE_OF_CLASS, "Test", IRNode.CALL})
+ @IR(applyIfNot = {"TLABRefillWasteFraction", "20"}, failOn = {IRNode.ALLOC})
+ @IR(applyIfNot = {"TLABRefillWasteFraction", "< 100"}, failOn = {IRNode.ALLOC_OF, "Test"})
+ public void good3() {
+ forceInline();
+ }
+
+ @Test
+ @IR(failOn = {IRNode.CALL, IRNode.STORE_OF_CLASS, "UnknownClass"})
+ public void good4() {
+ iFld = 42;
+ }
+
+ @Test
+ @IR(failOn = {IRNode.STORE_OF_FIELD, "xFld", IRNode.CALL})
+ public void good5() {
+ iFld = 42;
+ }
+
+ @Test
+ @IR(failOn = {IRNode.STORE_OF_CLASS, "MyClass"}) // Needs exact match to fail
+ public void good6() {
+ myClassSub.iFld = 42;
+ }
+
+ @Test
+ @IR(failOn = {IRNode.STORE_OF_CLASS, "MyClassSub"}) // Static write is with Class and not MySubClass
+ public void good7() {
+ MyClassSub.iFldStatic = 42;
+ }
+
+ @ForceInline
+ private void forceInline() {}
+}
+
+class MultipleFailOnBad {
+ private int iFld;
+ private int myInt;
+ private MyClass myClass;
+
+ @Test
+ @IR(failOn = {IRNode.STORE, IRNode.CALL, IRNode.STORE_I, IRNode.LOOP})
+ public void fail1() {
+ iFld = 42;
+ }
+
+ @Test
+ @IR(failOn = {IRNode.STORE, IRNode.CALL})
+ public void fail2() {
+ dontInline();
+ }
+
+ @Test
+ @IR(failOn = {IRNode.CALL, IRNode.STORE_OF_CLASS, "MultipleFailOnBad", IRNode.ALLOC})
+ public void fail3() {
+ iFld = 42;
+ }
+
+ @Test
+ @IR(failOn = {IRNode.STORE_OF_CLASS, "ir_framework/tests/MultipleFailOnBad", IRNode.CALL, IRNode.ALLOC})
+ public void fail4() {
+ iFld = 42;
+ }
+
+ @Test
+ @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld", IRNode.CALL, IRNode.ALLOC})
+ public void fail5() {
+ iFld = 42;
+ }
+
+ @Test
+ @IR(failOn = {IRNode.STORE_OF_CLASS, "MyClass", IRNode.ALLOC, IRNode.CALL})
+ public void fail6() {
+ myClass = new MyClass();
+ }
+
+ @Test
+ @IR(failOn = {IRNode.STORE_OF_CLASS, "UnknownClass", IRNode.ALLOC_OF, "MyClass"})
+ public void fail7() {
+ myClass = new MyClass();
+ }
+
+ @Test
+ @IR(failOn = {IRNode.STORE_OF_CLASS, "UnknownClass", IRNode.ALLOC_OF, "ir_framework/tests/MyClassSub"})
+ public void fail8() {
+ myClass = new MyClassSub();
+ }
+
+ @Test
+ @IR(failOn = {IRNode.STORE, IRNode.CALL})
+ public void fail9() {
+ iFld = 42;
+ dontInline();
+ }
+
+ @Test
+ @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld", IRNode.CALL, IRNode.ALLOC})
+ public void fail10() {
+ myInt = 34;
+ iFld = 42;
+ }
+
+ @DontInline
+ private void dontInline() {}
+}
+
+// Called with -XX:TLABRefillWasteFraction=X.
+class FlagComparisons {
+ // Applies all IR rules if TLABRefillWasteFraction=50
+ @Test
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "50"}) // Index 0
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "=50"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "= 50"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " = 50"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<=50"}) // Index 4
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<= 50"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " <= 50"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">=50"}) // Index 7
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">= 50"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " >= 50"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">49"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "> 49"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " > 49"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<51"}) // Index 13
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "< 51"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " < 51"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!=51"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!= 51"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " != 51"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!=49"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!= 49"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " != 49"}) // Index 21
+ public void testMatchAllIf50() {}
+
+ // Applies no IR rules if TLABRefillWasteFraction=50
+ @Test
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "49"}) // Index 0
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "=49"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "= 49"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " = 49"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "51"}) // Index 4
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "=51"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "= 51"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " = 51"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<=49"}) // Index 8
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<= 49"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " <= 49"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">=51"}) // Index 11
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">= 51"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " >= 51"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", ">50"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "> 50"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " > 50"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "<50"}) // Index 17
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "< 50"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " < 50"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!=50"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", "!= 50"})
+ @IR(failOn = IRNode.CALL, applyIf = {"TLABRefillWasteFraction", " != 50"}) // Index 22
+ public void testMatchNoneIf50() {}
+}
+
+class CountComparisons {
+ int iFld;
+
+ @Test
+ @IR(counts = {IRNode.STORE, "= 1",
+ IRNode.STORE, "=1",
+ IRNode.STORE, " = 1",
+ IRNode.STORE, " = 1",
+ IRNode.STORE, ">= 1",
+ IRNode.STORE, ">=1",
+ IRNode.STORE, " >= 1",
+ IRNode.STORE, " >= 1",
+ IRNode.STORE, "<= 1",
+ IRNode.STORE, "<=1",
+ IRNode.STORE, " <= 1",
+ IRNode.STORE, " <= 1",
+ IRNode.STORE, "!= 0",
+ IRNode.STORE, "!=0",
+ IRNode.STORE, " != 0",
+ IRNode.STORE, " != 0",
+ IRNode.STORE, "> 0",
+ IRNode.STORE, ">0",
+ IRNode.STORE, " > 0",
+ IRNode.STORE, " > 0",
+ IRNode.STORE, "< 2",
+ IRNode.STORE, "<2",
+ IRNode.STORE, " < 2",
+ IRNode.STORE, " < 2",
+ })
+ public void countComparison() {
+ iFld = 3;
+ }
+}
+
+class GoodCount {
+ boolean flag;
+ char cFld;
+ byte bFld;
+ short sFld;
+ int iFld;
+ long lFld;
+ float fFld;
+ double dFld;
+ long x;
+
+ long result;
+ MyClass myClass = new MyClass();
+ MyClass myClassSubPoly = new MyClassSub();
+ MyClassSub myClassSub = new MyClassSub();
+
+ @Test
+ @IR(counts = {IRNode.STORE, "1", IRNode.STORE_I, "1"},
+ failOn = {IRNode.STORE_B, IRNode.STORE_C, IRNode.STORE_D,
+ IRNode.STORE_F, IRNode.STORE_L})
+ public void good1() {
+ iFld = 3;
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE, "8",
+ IRNode.STORE_B, "2", // bFld + flag
+ IRNode.STORE_C, "2", // cFld + sFld
+ IRNode.STORE_I, "1",
+ IRNode.STORE_L, "1",
+ IRNode.STORE_F, "1",
+ IRNode.STORE_D, "1"})
+ public void good2() {
+ flag = true;
+ cFld = 'a';
+ bFld = 1;
+ sFld = 2;
+ iFld = 3;
+ lFld = 4L;
+ fFld = 5.0f;
+ dFld = 6.0;
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE, "8", IRNode.STORE_OF_CLASS, "GoodCount", "8",
+ IRNode.STORE_B, "2", IRNode.STORE_B_OF_CLASS, "GoodCount", "2",
+ IRNode.STORE_C, "2", IRNode.STORE_C_OF_CLASS, "GoodCount", "2",
+ IRNode.STORE_I, "1", IRNode.STORE_I_OF_CLASS, "GoodCount", "1",
+ IRNode.STORE_L, "1", IRNode.STORE_L_OF_CLASS, "GoodCount", "1",
+ IRNode.STORE_F, "1", IRNode.STORE_F_OF_CLASS, "GoodCount", "1",
+ IRNode.STORE_D, "1", IRNode.STORE_D_OF_CLASS, "GoodCount", "1"})
+ public void good3() {
+ flag = true;
+ cFld = 'a';
+ bFld = 1;
+ sFld = 2;
+ iFld = 3;
+ lFld = 4L;
+ fFld = 5.0f;
+ dFld = 6.0;
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE, "8", IRNode.STORE_OF_CLASS, "GoodCount", "8",
+ IRNode.STORE_B, "2", IRNode.STORE_B_OF_CLASS, "GoodCount", "2",
+ IRNode.STORE_C, "2", IRNode.STORE_C_OF_CLASS, "GoodCount", "2",
+ IRNode.STORE_I, "1", IRNode.STORE_I_OF_CLASS, "GoodCount", "1",
+ IRNode.STORE_L, "1", IRNode.STORE_L_OF_CLASS, "GoodCount", "1",
+ IRNode.STORE_F, "1", IRNode.STORE_F_OF_CLASS, "GoodCount", "1",
+ IRNode.STORE_D, "1", IRNode.STORE_D_OF_CLASS, "GoodCount", "1",
+ IRNode.STORE_OF_FIELD, "lFld", "1"})
+ public void good4() {
+ flag = true;
+ cFld = 'a';
+ bFld = 1;
+ sFld = 2;
+ iFld = 3;
+ lFld = 4L;
+ fFld = 5.0f;
+ dFld = 6.0;
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE, "2", IRNode.STORE_I, "1", IRNode.STORE_L, "1",
+ IRNode.STORE_OF_CLASS, "GoodCount", "1", IRNode.STORE_L_OF_CLASS, "GoodCount", "1",
+ IRNode.STORE_OF_CLASS, "ir_framework/tests/MyClass", "1",
+ IRNode.STORE_I_OF_CLASS, "ir_framework/tests/MyClass", "1",
+ IRNode.STORE_OF_CLASS, "ir_framework/tests/GoodCount", "1",
+ IRNode.STORE_L_OF_CLASS, "ir_framework/tests/GoodCount", "1",
+ IRNode.STORE_OF_FIELD, "x", "2"})
+ public void good5() {
+ x = 3; // long
+ myClass.x = 4; // int
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE_OF_FIELD, "myClass", "1", IRNode.STORE_OF_CLASS, "GoodCount", "1",
+ IRNode.STORE_OF_CLASS, "/GoodCount", "1", IRNode.STORE_OF_CLASS, "MyClass", "0"},
+ failOn = {IRNode.STORE_OF_CLASS, "MyClass"})
+ public void good6() {
+ myClass = new MyClass();
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE_OF_FIELD, "iFld", "3", IRNode.STORE_OF_CLASS, "GoodCount", "0",
+ IRNode.STORE_OF_CLASS, "MyClass", "2", IRNode.STORE_OF_CLASS, "MyClassSub", "1",
+ IRNode.STORE, "3"},
+ failOn = {IRNode.STORE_OF_CLASS, "GoodCount"})
+ public void good7() {
+ myClass.iFld = 1;
+ myClassSubPoly.iFld = 2;
+ myClassSub.iFld = 3;
+ }
+
+ @Test
+ @IR(counts = {IRNode.LOAD, "1", IRNode.STORE, "1"})
+ public void good8() {
+ result = iFld;
+ }
+
+
+ @Test
+ @IR(counts = {IRNode.LOAD, "4", IRNode.STORE, "1", IRNode.LOAD_OF_FIELD, "iFld", "2", IRNode.LOAD_OF_FIELD, "iFld2", "0",
+ IRNode.LOAD_OF_FIELD, "lFldStatic", "1", IRNode.LOAD_OF_CLASS, "GoodCount", "2", IRNode.LOAD_OF_CLASS, "MyClass", "1",
+ IRNode.STORE_OF_CLASS, "GoodCount", "1", IRNode.STORE_OF_FIELD, "result", "1",
+ IRNode.LOAD_OF_FIELD, "myClass", "1"})
+ public void good9() {
+ result = iFld + MyClass.lFldStatic + myClass.iFld; // 1 + 1 + 2 loads (myClass is LoadN of GoodCount and myClass.iFld a LoadI of MyClass)
+ }
+
+ @Test
+ @IR(counts = {IRNode.LOAD, "8",
+ IRNode.LOAD_B, "1",
+ IRNode.LOAD_UB, "1",
+ IRNode.LOAD_S, "1",
+ IRNode.LOAD_US, "1",
+ IRNode.LOAD_I, "1",
+ IRNode.LOAD_L, "1",
+ IRNode.LOAD_F, "1",
+ IRNode.LOAD_D, "1"})
+ public void good10() {
+ bFld++;
+ cFld++;
+ sFld++;
+ iFld++;
+ lFld++;
+ fFld++;
+ dFld++;
+ flag = !flag;
+ }
+
+ @Test
+ @IR(counts = {IRNode.LOAD, "8", IRNode.LOAD_OF_CLASS, "GoodCount", "8",
+ IRNode.LOAD_B, "1", IRNode.LOAD_B_OF_CLASS, "GoodCount", "1",
+ IRNode.LOAD_UB, "1", IRNode.LOAD_UB_OF_CLASS, "GoodCount", "1",
+ IRNode.LOAD_S, "1", IRNode.LOAD_S_OF_CLASS, "GoodCount", "1",
+ IRNode.LOAD_US, "1", IRNode.LOAD_US_OF_CLASS, "GoodCount", "1",
+ IRNode.LOAD_I, "1", IRNode.LOAD_I_OF_CLASS, "GoodCount", "1",
+ IRNode.LOAD_L, "1", IRNode.LOAD_L_OF_CLASS, "GoodCount", "1",
+ IRNode.LOAD_F, "1", IRNode.LOAD_F_OF_CLASS, "GoodCount", "1",
+ IRNode.LOAD_D, "1", IRNode.LOAD_D_OF_CLASS, "GoodCount", "1"})
+ public void good11() {
+ bFld++;
+ cFld++;
+ sFld++;
+ iFld++;
+ lFld++;
+ fFld++;
+ dFld++;
+ flag = !flag;
+ }
+}
+
+class BadCount {
+ int iFld;
+ int result;
+ @Test
+ @IR(counts = {IRNode.LOAD, "!= 1"})
+ @IR(counts = {IRNode.STORE, "> 0"})
+ public void bad1() {
+ result = iFld;
+ }
+
+ @Test
+ @IR(counts = {IRNode.LOAD, "1"})
+ @IR(counts = {IRNode.STORE, "< 1"})
+ public void bad2() {
+ result = iFld;
+ }
+
+
+ @Test
+ @IR(counts = {IRNode.LOAD, "0"})
+ @IR(counts = {IRNode.STORE, " <= 0"})
+ public void bad3() {
+ result = iFld;
+ }
+}
+
+
+class RunTests {
+ public int iFld;
+
+ @Test
+ @IR(counts = {IRNode.STORE, "1"})
+ @IR(failOn = IRNode.LOAD)
+ public void good1() {
+ iFld = 42;
+ }
+
+ @Test
+ @IR(counts = {IRNode.LOAD, "1"})
+ @IR(failOn = IRNode.STORE)
+ public int good2() {
+ return iFld;
+ }
+
+ @Run(test = {"good1", "good2"})
+ public void runGood1() {
+ good1();
+ good2();
+ }
+
+
+ @Test
+ @IR(counts = {IRNode.STORE, "1"})
+ @IR(failOn = IRNode.LOAD)
+ public void good3(int x) {
+ iFld = x;
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE, "1"})
+ @IR(failOn = IRNode.LOAD)
+ public int bad1(int x) {
+ return iFld + x;
+ }
+
+ @Run(test = {"bad1", "good3"})
+ public void run() {
+ bad1(2);
+ good3(4);
+ }
+}
+
+
+class AllocArray {
+ MyClass[] myClassArray;
+
+ @Test
+ @IR(failOn = {IRNode.ALLOC_ARRAY})
+ @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "MyClass"})
+ @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "MyClasss"}) // Does not fail
+ @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ir_framework/tests/MySubClass"}) // Does not fail
+ @IR(failOn = {IRNode.ALLOC_ARRAY_OF, "ir_framework/tests/MyClass"})
+ public void allocArray() {
+ myClassArray = new MyClass[2];
+ }
+}
+
+class Loads {
+ int iFld = 34;
+ int result = 0;
+ Object myClass = new MyClass();
+
+ @Test
+ @IR(failOn = {IRNode.LOAD, IRNode.LOOP, IRNode.LOAD_I}, counts = {IRNode.LOOP, "2", IRNode.LOAD, "2", IRNode.STORE, "2"})
+ @IR(failOn = {IRNode.LOOP, IRNode.LOOP}, counts = {IRNode.LOOP, "0", IRNode.LOAD, "1"}) // Does not fail
+ @IR(failOn = {IRNode.LOOP, IRNode.LOOP}, counts = {IRNode.LOOP, "0", IRNode.STORE, "1"})
+ @IR(failOn = {IRNode.LOOP, IRNode.STORE}, counts = {IRNode.LOOP, "0", IRNode.LOAD, "1"})
+ @IR(failOn = {IRNode.LOAD_OF_CLASS, "ir_framework/tests/Loads"})
+ @IR(failOn = {IRNode.LOAD_OF_CLASS, "Loads"})
+ @IR(failOn = {IRNode.LOAD_OF_FIELD, "iFld"})
+ @IR(failOn = {IRNode.LOAD_OF_FIELD, "iFld2", IRNode.LOAD_OF_CLASS, "Load"}) // Does not fail
+ @IR(failOn = {IRNode.LOAD_KLASS}) // Does not fail
+ @IR(counts = {IRNode.FIELD_ACCESS, "3"}) // Does not fail
+ public void load() {
+ result = iFld;
+ iFld = 3;
+ }
+
+ @Test
+ @IR(failOn = {IRNode.LOAD_KLASS})
+ @IR(counts = {IRNode.FIELD_ACCESS, "3"})
+ public void loadKlass() {
+ if (myClass instanceof MyClass) {
+ result = 3;
+ }
+ }
+}
+
+class Loops {
+ int limit = 1024;
+ int[] iArr = new int[100];
+
+ @DontInline
+ public void dontInline() {}
+
+ @Test
+ @IR(failOn = IRNode.LOOP) // fails
+ @IR(failOn = IRNode.COUNTEDLOOP)
+ @IR(failOn = IRNode.COUNTEDLOOP_MAIN)
+ public void loop() {
+ for (int i = 0; i < limit; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.LOOP)
+ @IR(failOn = IRNode.COUNTEDLOOP) // fails
+ @IR(failOn = IRNode.COUNTEDLOOP_MAIN)
+ public void countedLoop() {
+ for (int i = 0; i < 2000; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.LOOP) // fails
+ @IR(failOn = IRNode.COUNTEDLOOP) // fails
+ @IR(failOn = IRNode.COUNTEDLOOP_MAIN)
+ public void loopAndCountedLoop() {
+ for (int i = 0; i < 2000; i++) {
+ for (int j = 0; j < limit; j++) {
+ dontInline();
+ }
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.LOOP)
+ @IR(failOn = IRNode.COUNTEDLOOP) // fails
+ @IR(failOn = IRNode.COUNTEDLOOP_MAIN) // fails
+ public void countedLoopMain() {
+ // Cannot unroll completely -> create pre/main/post
+ for (int i = 0; i < 100; i++) {
+ iArr[i] = i;
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.LOOP)
+ @IR(failOn = IRNode.COUNTEDLOOP)
+ @IR(failOn = IRNode.COUNTEDLOOP_MAIN)
+ public void countedLoopUnrolled() {
+ // Completely unrolled -> no pre/main/post
+ for (int i = 0; i < 8; i++) {
+ iArr[i] = i;
+ }
+ }
+}
+
+class Traps {
+ int number42 = 42;
+ int iFld = 10;
+ int[] iArr = new int[2];
+ MyClass myClass = new MyClass();
+ MyClassSub myClassSub = new MyClassSub();
+ NotLoaded notLoaded = new NotLoaded();
+ Object[] oArr = new Object[10];
+ MyClass[] mArr = new MyClass[10];
+
+ @Test
+ @IR(failOn = IRNode.TRAP)
+ @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld"}) // fails
+ @IR(failOn = {IRNode.PREDICATE_TRAP,
+ IRNode.UNSTABLE_IF_TRAP,
+ IRNode.NULL_CHECK_TRAP,
+ IRNode.NULL_ASSERT_TRAP,
+ IRNode.RANGE_CHECK_TRAP,
+ IRNode.CLASS_CHECK_TRAP,
+ IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
+ IRNode.UNHANDLED_TRAP})
+ public void noTraps() {
+ for (int i = 0; i < 100; i++) {
+ if (i < 42) {
+ // Reached, no uncommon trap
+ iFld = i;
+ }
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.TRAP) // fails
+ @IR(failOn = IRNode.PREDICATE_TRAP) // fails
+ @IR(failOn = {IRNode.STORE_OF_FIELD, "iFld"})
+ @IR(failOn = {IRNode.UNSTABLE_IF_TRAP,
+ IRNode.NULL_CHECK_TRAP,
+ IRNode.NULL_ASSERT_TRAP,
+ IRNode.RANGE_CHECK_TRAP,
+ IRNode.CLASS_CHECK_TRAP,
+ IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
+ IRNode.UNHANDLED_TRAP})
+ public void predicateTrap() {
+ for (int i = 0; i < 100; i++) {
+ if (number42 != 42) {
+ // Never reached
+ iFld = i;
+ }
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.TRAP) // fails
+ @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
+ @IR(failOn = IRNode.UNSTABLE_IF_TRAP) // fails
+ @IR(failOn = {IRNode.PREDICATE_TRAP,
+ IRNode.NULL_ASSERT_TRAP,
+ IRNode.RANGE_CHECK_TRAP,
+ IRNode.CLASS_CHECK_TRAP,
+ IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
+ IRNode.UNHANDLED_TRAP})
+ public void nullCheck() {
+ if (myClass instanceof MyClassSub) {
+ iFld = 4;
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.TRAP) // fails
+ @IR(failOn = IRNode.NULL_ASSERT_TRAP) // fails
+ @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
+ @IR(failOn = {IRNode.PREDICATE_TRAP,
+ IRNode.UNSTABLE_IF_TRAP,
+ IRNode.RANGE_CHECK_TRAP,
+ IRNode.CLASS_CHECK_TRAP,
+ IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
+ IRNode.UNHANDLED_TRAP})
+ public Object nullAssert() {
+ return notLoaded.notLoadedFld;
+ }
+
+ @Test
+ @Arguments(Argument.TRUE)
+ @IR(failOn = IRNode.TRAP) // fails
+ @IR(failOn = IRNode.UNSTABLE_IF_TRAP) // fails
+ @IR(failOn = {IRNode.PREDICATE_TRAP,
+ IRNode.NULL_CHECK_TRAP,
+ IRNode.NULL_ASSERT_TRAP,
+ IRNode.RANGE_CHECK_TRAP,
+ IRNode.CLASS_CHECK_TRAP,
+ IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
+ IRNode.UNHANDLED_TRAP})
+ public void unstableIf(boolean flag) {
+ if (flag) {
+ iFld++;
+ } else {
+ iFld--;
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.TRAP) // fails
+ @IR(failOn = IRNode.CLASS_CHECK_TRAP) // fails
+ @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
+ @IR(failOn = {IRNode.PREDICATE_TRAP,
+ IRNode.UNSTABLE_IF_TRAP,
+ IRNode.NULL_ASSERT_TRAP,
+ IRNode.RANGE_CHECK_TRAP,
+ IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
+ IRNode.UNHANDLED_TRAP})
+ public void classCheck() {
+ try {
+ myClassSub = (MyClassSub) myClass;
+ } catch (ClassCastException e) {
+ // Expected
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.TRAP) // fails
+ @IR(failOn = IRNode.RANGE_CHECK_TRAP) // fails
+ @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
+ @IR(failOn = {IRNode.PREDICATE_TRAP,
+ IRNode.UNSTABLE_IF_TRAP,
+ IRNode.NULL_ASSERT_TRAP,
+ IRNode.CLASS_CHECK_TRAP,
+ IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP,
+ IRNode.UNHANDLED_TRAP})
+ public void rangeCheck() {
+ iArr[1] = 3;
+ }
+
+
+ @Test
+ @IR(failOn = IRNode.TRAP) // fails
+ @IR(failOn = IRNode.INTRINSIC_OR_TYPE_CHECKED_INLINING_TRAP) // fails
+ @IR(failOn = IRNode.NULL_CHECK_TRAP) // fails
+ @IR(failOn = {IRNode.PREDICATE_TRAP,
+ IRNode.UNSTABLE_IF_TRAP,
+ IRNode.NULL_ASSERT_TRAP,
+ IRNode.CLASS_CHECK_TRAP,
+ IRNode.RANGE_CHECK_TRAP,
+ IRNode.UNHANDLED_TRAP})
+ public void instrinsicOrTypeCheckedInlining() {
+ System.arraycopy(oArr, 0, mArr, 0, 8);
+ }
+}
+
+class UnhandledTrap {
+ int iFld = 34;
+
+ @Test
+ @IR(failOn = IRNode.TRAP) // fails
+ @IR(failOn = IRNode.UNHANDLED_TRAP) // fails
+ @IR(failOn = {IRNode.PREDICATE_TRAP,
+ IRNode.UNSTABLE_IF_TRAP,
+ IRNode.NULL_CHECK_TRAP,
+ IRNode.NULL_ASSERT_TRAP,
+ IRNode.RANGE_CHECK_TRAP,
+ IRNode.CLASS_CHECK_TRAP})
+ public void unhandled() {
+ try {
+ throw new RuntimeException();
+ } catch (RuntimeException e) {
+ // Expected
+ }
+ }
+}
+
+class ScopeObj {
+
+ @DontInline
+ public void dontInline(int i) {}
+
+ @Test
+ @IR(failOn = IRNode.SCOPE_OBJECT) // fails
+ public int scopeObject() {
+ MyClass myClass = new MyClass();
+ for (int i = 0; i < 100; i++) {
+ dontInline(myClass.iFld);
+ }
+ return 3;
+ }
+}
+
+class Membar {
+ volatile MyClass myClass;
+
+ @Test
+ @IR(failOn = IRNode.MEMBAR) // fails
+ public int membar() {
+ myClass = new MyClass();
+ return myClass.x;
+ }
+}
+
+class CheckCastArray {
+ Object[] oArr = new Object[10];
+ MyClass[] mArr = new MyClass[10];
+
+ @Test
+ @IR(failOn = IRNode.CHECKCAST_ARRAY) // fails
+ @IR(failOn = {IRNode.CHECKCAST_ARRAY_OF, "MyClass", // fails
+ IRNode.CHECKCAST_ARRAY_OF, "ir_framework/tests/MyClass"}) // fails
+ @IR(failOn = {IRNode.CHECKCAST_ARRAY_OF, "MyClasss", IRNode.CHECKCAST_ARRAY_OF, "Object"})
+ public boolean array() {
+ return oArr instanceof MyClass[];
+ }
+
+ @Test
+ @IR(failOn = IRNode.CHECKCAST_ARRAYCOPY) // fails
+ public Object[] arrayCopy(Object[] src, Class klass) {
+ return Arrays.copyOf(src, 8, klass);
+ }
+
+ @Run(test = "arrayCopy")
+ public void testArrayCopy() {
+ arrayCopy(mArr, MyClass[].class);
+ arrayCopy(mArr, Object[].class);
+ arrayCopy(mArr, MyClass2[].class);
+ }
+}
+
+class CompilationOutputOfFails {
+
+ @Test
+ @IR(failOn = IRNode.COUNTEDLOOP + "[\\s\\S]*" + "call")
+ public void both1() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.COUNTEDLOOP + "|" + "call")
+ public void both2() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.COUNTEDLOOP)
+ @IR(failOn = "call")
+ public void both3() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.COUNTEDLOOP + "[\\s\\S]*" + "call", "0"})
+ public void both4() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.COUNTEDLOOP + "|" + "call", "1"})
+ public void both5() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.COUNTEDLOOP, "0"})
+ @IR(counts = {"call", "1"})
+ public void both6() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.COUNTEDLOOP)
+ @IR(counts = {"call", "1"})
+ public void both7() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.COUNTEDLOOP)
+ public void ideal1() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.COUNTEDLOOP)
+ @IR(failOn = IRNode.ALLOC) // not fail
+ public void ideal2() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.COUNTEDLOOP)
+ @IR(counts = {IRNode.ALLOC, "0"}) // not fail
+ public void ideal3() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.COUNTEDLOOP, "2"})
+ public void ideal4() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.ALLOC) // not fail
+ @IR(counts = {IRNode.COUNTEDLOOP, "2"})
+ public void ideal5() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.ALLOC, "0"}) // not fail
+ @IR(counts = {IRNode.COUNTEDLOOP, "2"})
+ public void ideal6() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.COUNTEDLOOP, "5"})
+ @IR(counts = {IRNode.COUNTEDLOOP, "2"})
+ public void ideal7() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(failOn = "call")
+ public void opto1() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(failOn = "call")
+ @IR(failOn = IRNode.STORE) // not fail
+ public void opto2() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(failOn = "call")
+ @IR(counts = {IRNode.COUNTEDLOOP, "1"}) // not fail
+ public void opto3() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(counts = {"call", "1"})
+ public void opto4() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(failOn = IRNode.STORE) // not fail
+ @IR(counts = {"call", "1"})
+ public void opto5() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE, "0"}) // not fail
+ @IR(counts = {"call", "1"})
+ public void opto6() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @Test
+ @IR(counts = {"call", "10"})
+ @IR(counts = {"call", "1"})
+ public void opto7() {
+ for (int i = 0; i < 100; i++) {
+ dontInline();
+ }
+ }
+
+ @DontInline
+ private void dontInline() {}
+}
+
+
+// Used only by class Traps
+class NotLoaded {
+ NotLoadedHelper notLoadedFld;
+}
+
+// Used only by class Traps
+class NotLoadedHelper {}
+
+class MyClass {
+ int iFld = 3;
+ int x = 5;
+ static long lFldStatic;
+}
+
+class MyClass2 {}
+
+class MyClassSub extends MyClass {
+ int iFld;
+ static int iFldStatic;
+}
+
+class ShouldNotReachException extends RuntimeException {
+ ShouldNotReachException(String s) {
+ super(s);
+ }
+}
+
+
+// Base class for any kind of constraint that is used to verify if the framework reports the correct IR failures.
+abstract class Constraint {
+ private final Class> klass;
+ protected final int ruleIdx;
+ private final Pattern methodPattern;
+ private final String classAndMethod;
+ protected final Pattern irPattern;
+ private final String methodName;
+ protected boolean matched;
+
+ Constraint(Class> klass, String methodName, int ruleIdx, Pattern irPattern) {
+ this.klass = klass;
+ classAndMethod = klass.getSimpleName() + "." + methodName;
+ this.ruleIdx = ruleIdx;
+ this.methodPattern = Pattern.compile(Pattern.quote(classAndMethod));
+ this.irPattern = irPattern;
+ this.methodName = methodName;
+ this.matched = false;
+ }
+
+ // For good constraints only
+ Constraint(Class> klass, String methodName, int ruleIdx) {
+ this.klass = klass;
+ classAndMethod = klass.getSimpleName() + "." + methodName;
+ this.ruleIdx = ruleIdx;
+ this.methodPattern = Pattern.compile(Pattern.quote(classAndMethod));
+ this.irPattern = null;
+ this.methodName = methodName;
+ this.matched = false;
+ }
+
+ @Override
+ public String toString() {
+ return "Constraint " + getClass().getSimpleName() + ", method: " + methodName + ", rule: " + ruleIdx;
+ }
+
+ public Class> getKlass() {
+ return klass;
+ }
+
+ protected String errorPrefix() {
+ return "Method " + methodName + ", Rule " + ruleIdx;
+ }
+
+ public void checkConstraint(IRViolationException e) {
+ String message = e.getExceptionInfo();
+ String[] splitMethods = message.split("Method");
+ for (int i = 1; i < splitMethods.length; i++) {
+ String method = splitMethods[i];
+ if (methodPattern.matcher(method).find()) {
+ String[] splitIrRules = method.split("@IR ");
+ for (int j = 1; j < splitIrRules.length; j++) {
+ String irRule = splitIrRules[j];
+ if (irRule.startsWith("rule " + ruleIdx)) {
+ checkIRRule(irRule);
+ }
+ }
+ }
+ }
+ Asserts.assertTrue(matched, toString() + " should have been matched");
+ }
+
+ abstract protected void checkIRRule(String irRule);
+
+ protected void checkOnMethod(String method) {}
+}
+
+// Constraint for rule that does not fail.
+class GoodRuleConstraint extends Constraint {
+
+ GoodRuleConstraint(Class> klass, String methodName, int ruleIdx) {
+ super(klass, methodName, ruleIdx);
+ matched = true;
+ }
+
+ public static GoodRuleConstraint create(Class> klass, String methodName, int ruleIdx) {
+ return new GoodRuleConstraint(klass, methodName, ruleIdx);
+ }
+
+ @Override
+ protected void checkIRRule(String irRule) {
+ Asserts.fail(errorPrefix() + " should not fail:" + System.lineSeparator() + irRule);
+ }
+}
+
+// Constraint for rule that might fail but not with "failOn".
+class GoodFailOnConstraint extends GoodRuleConstraint {
+
+ private GoodFailOnConstraint(Class> klass, String methodName, int ruleIdx) {
+ super(klass, methodName, ruleIdx);
+ }
+
+ public static GoodFailOnConstraint create(Class> klass, String methodName, int ruleIdx) {
+ return new GoodFailOnConstraint(klass, methodName, ruleIdx);
+ }
+
+ @Override
+ protected void checkIRRule(String irRule) {
+ Asserts.assertFalse(irRule.contains("- failOn"), errorPrefix() + " should not have failed:" + System.lineSeparator() + irRule);
+ }
+}
+
+// Constraint for rule that might fail but not with "counts".
+class GoodCountsConstraint extends GoodRuleConstraint {
+
+ private GoodCountsConstraint(Class> klass, String methodName, int ruleIdx) {
+ super(klass, methodName, ruleIdx);
+ }
+
+ public static GoodCountsConstraint create(Class> klass, String methodName, int ruleIdx) {
+ return new GoodCountsConstraint(klass, methodName, ruleIdx);
+ }
+
+ @Override
+ protected void checkIRRule(String irRule) {
+ Asserts.assertFalse(irRule.contains("- counts"), errorPrefix() + " should not have failed with counts:"
+ + System.lineSeparator() + irRule);
+ }
+}
+
+// Base class for all Regex based constraint.
+abstract class RegexConstraint extends Constraint {
+ final String category;
+ final String otherCategory;
+ final int[] regexIndexes;
+ final boolean isGood;
+ final List matches;
+
+ RegexConstraint(Class> klass, String methodName, String category, boolean isGood, List matches, int ruleIdx, int... regexIndexes) {
+ super(klass, methodName, ruleIdx, initIRPattern(category, ruleIdx));
+ this.category = category;
+ this.regexIndexes = regexIndexes;
+ if (category.equals("failOn")) {
+ this.otherCategory = "counts";
+ } else {
+ Asserts.assertTrue(category.equals("counts"));
+ this.otherCategory = "failOn";
+ }
+ this.isGood = isGood;
+ this.matches = matches;
+ }
+
+ @Override
+ public String toString() {
+ String msg = super.toString() + ", ";
+ if (regexIndexes.length > 1) {
+ msg += "regexes: [" + String.join(", ", Arrays.stream(regexIndexes).mapToObj(String::valueOf).toArray(String[]::new)) + "]";
+ } else {
+ msg += "regex: " + regexIndexes[0];
+ }
+ return msg;
+ }
+
+ @Override
+ protected String errorPrefix() {
+ return super.errorPrefix() + " with \"" + category + "\"";
+ }
+
+ private static Pattern initIRPattern(String category, int ruleIdx) {
+ if (category.equals("failOn")) {
+ return Pattern.compile("rule " + ruleIdx + ":.*\\R.*- failOn: Graph contains forbidden nodes.*\\R" +
+ ".*Regex \\d+:.*\\R.*Matched forbidden node.*");
+ } else {
+ return Pattern.compile("rule " + ruleIdx + ":.*\\R.*- counts: Graph contains wrong number of nodes:\\R" +
+ ".*Regex \\d+:.*\\R.*Expected.*");
+ }
+ }
+
+ @Override
+ protected void checkIRRule(String irRule) {
+ int categoryIndex = irRule.indexOf("- " + category);
+ Asserts.assertTrue(categoryIndex != -1, errorPrefix() + " should have failed");
+
+ int endIndex;
+ int otherCategoryIndex = irRule.indexOf("- " + otherCategory);
+ if (otherCategoryIndex == -1 || categoryIndex > otherCategoryIndex) {
+ endIndex = irRule.length();
+ } else {
+ endIndex = otherCategoryIndex;
+ }
+ String categoryString = irRule.substring(irRule.indexOf("- " + category), endIndex);
+ Pattern pattern;
+ Matcher matcher;
+ for (int regexIndex : this.regexIndexes) {
+ pattern = Pattern.compile("Regex " + regexIndex + ":.*");
+ matcher = pattern.matcher(categoryString);
+ if (isGood) {
+ Asserts.assertFalse(matcher.find(), errorPrefix() + " failed with Regex " + regexIndex);
+ matched = true;
+ } else {
+ Asserts.assertTrue(matcher.find(), errorPrefix() + " should have failed at Regex " + regexIndex);
+ String[] splitRegex = categoryString.split("Regex ");
+ if (matches != null) {
+ for (int i = 1; i < splitRegex.length; i++) {
+ String regexString = splitRegex[i];
+ if (regexString.startsWith(String.valueOf(regexIndex))) {
+ Asserts.assertTrue(matches.stream().allMatch(regexString::contains),
+ errorPrefix() + " could not find all matches at Regex " + regexIndex);
+ matched = true;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// Base class for all good regex based constraints.
+abstract class GoodRegexConstraint extends RegexConstraint {
+
+ GoodRegexConstraint(Class> klass, String methodName, String category, int ruleIdx, int... regexIndexes) {
+ super(klass, methodName, category, true, null, ruleIdx, regexIndexes);
+ }
+}
+
+// Constraint for rule that might fail with "counts" or "failOn", but the specified regex in "failOn" does not fail.
+class GoodFailOnRegexConstraint extends GoodRegexConstraint {
+
+ private GoodFailOnRegexConstraint(Class> klass, String methodName, int ruleIdx, int... regexIndexes) {
+ super(klass, methodName, "failOn", ruleIdx, regexIndexes);
+ }
+
+
+ public static GoodFailOnRegexConstraint create(Class> klass, String methodName, int ruleIdx, int... regexIndexes) {
+ return new GoodFailOnRegexConstraint(klass, methodName, ruleIdx, regexIndexes);
+ }
+}
+
+
+// Constraint for rule that might fail with "counts" or "failOn", but the specified regex in "counts" does not fail.
+class GoodCountsRegexConstraint extends GoodRegexConstraint {
+
+ private GoodCountsRegexConstraint(Class> klass, String methodName, int ruleIdx, int... regexIndexes) {
+ super(klass, methodName, "counts", ruleIdx, regexIndexes);
+ }
+
+
+ public static GoodCountsRegexConstraint create(Class> klass, String methodName, int ruleIdx, int... regexIndexes) {
+ return new GoodCountsRegexConstraint(klass, methodName, ruleIdx, regexIndexes);
+ }
+}
+
+// Constraint for rule that fails with "failOn" and the specified regex must also fail.
+class BadFailOnConstraint extends RegexConstraint {
+
+ BadFailOnConstraint(Class> klass, String methodName, int ruleIdx, List matches, int... regexIndexes) {
+ super(klass, methodName, "failOn", false, matches, ruleIdx, regexIndexes);
+ }
+
+ public static BadFailOnConstraint create(Class> klass, String methodName, int ruleIdx, int regexId, String... matches) {
+ return new BadFailOnConstraint(klass, methodName, ruleIdx, new ArrayList<>(Arrays.asList(matches)), regexId);
+ }
+
+ public static BadFailOnConstraint create(Class> klass, String methodName, int ruleIdx, String... matches) {
+ return new BadFailOnConstraint(klass, methodName, ruleIdx, new ArrayList<>(Arrays.asList(matches)), 1);
+ }
+}
+
+// Constraint for rule that fails with "counts" and the specified regex must also fail.
+class BadCountsConstraint extends RegexConstraint {
+
+ BadCountsConstraint(Class> klass, String methodName, int ruleIdx, List matches, int... regexIndexes) {
+ super(klass, methodName, "counts", false, matches, ruleIdx, regexIndexes);
+ }
+
+ public static BadCountsConstraint create(Class> klass, String methodName, int ruleIdx, int regexId, int foundCount, String... matches) {
+ List matchesList = getMatchesList(foundCount, matches, Arrays.asList(matches));
+ return new BadCountsConstraint(klass, methodName, ruleIdx, matchesList, regexId);
+ }
+
+ public static BadCountsConstraint create(Class> klass, String methodName, int ruleIdx, int foundCount, String... matches) {
+ List matchesList = getMatchesList(foundCount, matches, Arrays.asList(matches));
+ return new BadCountsConstraint(klass, methodName, ruleIdx, matchesList, 1);
+ }
+
+ private static List getMatchesList(int foundCount, String[] matches, List strings) {
+ List matchesList = new ArrayList<>();
+ matchesList.add("but found " + foundCount);
+ if (matches != null) {
+ matchesList.addAll(strings);
+ }
+ return matchesList;
+ }
+}
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestRunTests.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestRunTests.java
new file mode 100644
index 00000000000..7f7cb1830dc
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestRunTests.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2021, 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.driver.IRViolationException;
+import compiler.lib.ir_framework.shared.TestRunException;
+import jdk.test.lib.Asserts;
+
+import java.util.Arrays;
+
+/*
+ * @test
+ * @requires vm.debug == true & vm.compMode != "Xint" & vm.compiler2.enabled & vm.flagless
+ * @summary Test different custom run tests.
+ * @library /test/lib /
+ * @run driver ir_framework.tests.TestRunTests
+ */
+
+public class TestRunTests {
+
+ public static void main(String[] args) {
+ TestFramework.run();
+ try {
+ TestFramework.run(BadStandalone.class);
+ throw new RuntimeException("Should not reach");
+ } catch (IRViolationException e) {
+ String[] matches = { "test(int)", "test2(int)", "Failed IR Rules (2)"};
+ Arrays.stream(matches).forEach(m -> Asserts.assertTrue(e.getExceptionInfo().contains(m)));
+ Asserts.assertEQ(e.getExceptionInfo().split("STANDALONE mode", -1).length - 1, 2);
+ }
+ new TestFramework(SkipCompilation.class).addFlags("-XX:-UseCompiler").start();
+ new TestFramework(SkipCompilation.class).addFlags("-Xint").start();
+ new TestFramework(SkipC2Compilation.class).addFlags("-XX:TieredStopAtLevel=1").start();
+ new TestFramework(SkipC2Compilation.class).addFlags("-XX:TieredStopAtLevel=2").start();
+ new TestFramework(SkipC2Compilation.class).addFlags("-XX:TieredStopAtLevel=3").start();
+ }
+ public int iFld;
+
+ @Test
+ @IR(counts = {IRNode.STORE_I, "1"})
+ public int test1(int x) {
+ iFld = x;
+ return x;
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE_I, "1"})
+ public int test2(int y) {
+ iFld = y;
+ return y;
+ }
+
+ @Run(test = {"test1", "test2"})
+ public void run(RunInfo info) {
+ test1(23);
+ test2(42);
+ Asserts.assertTrue(info.isC2CompilationEnabled());
+ if (!info.isWarmUp()) {
+ TestFramework.assertCompiledByC2(info.getTest("test1"));
+ TestFramework.assertCompiledByC2(info.getTest("test2"));
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE_I, "1"})
+ public int test3(int x) {
+ iFld = x;
+ return x;
+ }
+
+ @Run(test = "test3")
+ public void run2(RunInfo info) {
+ Asserts.assertTrue(info.isC2CompilationEnabled());
+ test3(42);
+ if (!info.isWarmUp()) {
+ TestFramework.assertCompiledByC2(info.getTest());
+ try {
+ info.getTest("test2");
+ throw new RuntimeException("should not reach");
+ } catch (TestRunException e) {
+ // Excepted, do not call this method for single associated test.
+ }
+ try {
+ info.isTestC1Compiled("test2");
+ throw new RuntimeException("should not reach");
+ } catch (TestRunException e) {
+ // Excepted, do not call this method for single associated test.
+ }
+ try {
+ info.isTestC2Compiled("test2");
+ throw new RuntimeException("should not reach");
+ } catch (TestRunException e) {
+ // Excepted, do not call this method for single associated test.
+ }
+ try {
+ info.isTestCompiledAtLevel("test2", CompLevel.C2);
+ throw new RuntimeException("should not reach");
+ } catch (TestRunException e) {
+ // Excepted, do not call this method for single associated test.
+ }
+ }
+ }
+
+
+ @Test
+ @IR(counts = {IRNode.STORE_I, "1"})
+ public int test4(int x) {
+ iFld = x;
+ return x;
+ }
+
+ @Run(test = "test4", mode = RunMode.STANDALONE)
+ public void run3(RunInfo info) {
+ for (int i = 0; i < 2000; i++) {
+ test4(i);
+ }
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE_I, "1"})
+ public int test5(int x) {
+ iFld = x;
+ return x;
+ }
+
+ @Test(compLevel = CompLevel.WAIT_FOR_COMPILATION)
+ @IR(counts = {IRNode.STORE_I, "1"})
+ public int test6(int y) {
+ iFld = y;
+ return y;
+ }
+
+ @Run(test = {"test5", "test6"})
+ public void run4(RunInfo info) {
+ test5(23);
+ test6(42);
+ if (!info.isWarmUp()) {
+ TestFramework.assertCompiledByC2(info.getTest("test5"));
+ TestFramework.assertCompiledByC2(info.getTest("test6"));
+ try {
+ info.getTest();
+ throw new RuntimeException("should not reach");
+ } catch (TestRunException e) {
+ // Excepted, do not call this method for single associated test.
+ }
+ try {
+ info.isTestC1Compiled();
+ throw new RuntimeException("should not reach");
+ } catch (TestRunException e) {
+ // Excepted, do not call this method for single associated test.
+ }
+ try {
+ info.isTestC2Compiled();
+ throw new RuntimeException("should not reach");
+ } catch (TestRunException e) {
+ // Excepted, do not call this method for single associated test.
+ }
+ try {
+ info.isTestCompiledAtLevel(CompLevel.C2);
+ throw new RuntimeException("should not reach");
+ } catch (TestRunException e) {
+ // Excepted, do not call this method for single associated test.
+ }
+ }
+ }
+
+
+ @Test
+ @IR(counts = {IRNode.STORE_I, "1"})
+ public int test7(int x) {
+ for (int i = 0; i < 100; i++) {}
+ iFld = x;
+ return x;
+ }
+
+
+ @Test
+ @IR(counts = {IRNode.STORE_I, "1"})
+ public int test8(int x) {
+ for (int i = 0; i < 100; i++) {}
+ iFld = x;
+ return x;
+ }
+
+ @Run(test = {"test7", "test8"}, mode = RunMode.STANDALONE)
+ public void run5() {
+ for (int i = 0; i < 10000; i++) {
+ test7(23);
+ test8(42);
+ }
+ }
+
+ @Test(compLevel = CompLevel.WAIT_FOR_COMPILATION)
+ @Warmup(0)
+ public void test9() {
+ TestClass tmp = new TestClass();
+ for (int i = 0; i < 100; ++i) {
+ tmp.test();
+ }
+ }
+
+ static class TestClass {
+ public int test() {
+ int res = 0;
+ for (int i = 1; i < 20_000; ++i) {
+ res -= i;
+ }
+ return res;
+ }
+ }
+}
+
+class BadStandalone {
+ int iFld;
+
+ @Test
+ @IR(counts = {IRNode.STORE_I, "1"})
+ public int test(int x) {
+ iFld = x;
+ return x;
+ }
+
+ @Run(test = "test", mode = RunMode.STANDALONE)
+ public void run(RunInfo info) {
+ test(42);
+ }
+
+ @Test
+ @IR(counts = {IRNode.STORE_I, "1"})
+ public int test2(int x) {
+ iFld = x;
+ return x;
+ }
+
+ @Run(test = "test2", mode = RunMode.STANDALONE)
+ public void run2(RunInfo info) {
+ }
+}
+
+// Run with TieredStopAt=[1,3]. IR verification is skipped.
+class SkipC2Compilation {
+
+ int iFld;
+ @Test(compLevel = CompLevel.C2)
+ @IR(failOn = IRNode.STORE) // Would fail but not evaluated.
+ public void testC2() {
+ iFld = 34;
+ }
+
+ @Check(test = "testC2")
+ public void checkC2(TestInfo info) {
+ Asserts.assertFalse(info.isC2CompilationEnabled());
+ Asserts.assertTrue(info.isCompilationSkipped());
+ }
+
+ @Test(compLevel = CompLevel.C2)
+ @IR(failOn = IRNode.STORE) // Would fail but not evaluated.
+ public void test2C2() {
+ iFld = 34;
+ }
+
+
+ @Run(test = "test2C2")
+ public void run2C2(RunInfo info) {
+ Asserts.assertFalse(info.isC2CompilationEnabled());
+ Asserts.assertTrue(info.isCompilationSkipped());
+ test2C2();
+ Asserts.assertTrue(info.isCompilationSkipped());
+ try {
+ info.isCompilationSkipped("test2C2");
+ throw new RuntimeException("should not reach");
+ } catch (TestRunException e) {
+ // Excepted, do not call this method for single associated test.
+ }
+ }
+
+ @Test(compLevel = CompLevel.C2)
+ @IR(failOn = IRNode.STORE) // Would fail but not evaluated.
+ public void test3C2() {
+ iFld = 34;
+ }
+
+ @Test(compLevel = CompLevel.C2)
+ @IR(failOn = IRNode.STORE) // Would fail but not evaluated.
+ public void test4C2() {
+ iFld = 34;
+ }
+
+
+ @Test // Level any
+ @IR(failOn = IRNode.STORE) // Would fail but not evaluated.
+ public void testAny() {
+ iFld = 34;
+ }
+
+ @Run(test = {"test3C2", "test4C2", "testAny"})
+ public void runMulti(RunInfo info) {
+ Asserts.assertFalse(info.isC2CompilationEnabled());
+ if (!info.isWarmUp()) {
+ TestFramework.assertCompiledByC1(info.getTest("testAny"));
+ }
+ Asserts.assertTrue(info.isCompilationSkipped("test3C2"));
+ Asserts.assertTrue(info.isCompilationSkipped("test4C2"));
+ Asserts.assertFalse(info.isCompilationSkipped("testAny"));
+ test2C2();
+ Asserts.assertTrue(info.isCompilationSkipped("test3C2"));
+ Asserts.assertTrue(info.isCompilationSkipped("test4C2"));
+ Asserts.assertFalse(info.isCompilationSkipped("testAny"));
+ try {
+ info.isCompilationSkipped();
+ throw new RuntimeException("should not reach");
+ } catch (TestRunException e) {
+ // Excepted, do not call this method for multiple associated tests.
+ }
+ }
+}
+
+// Run with -Xint and -XX:-Compiler. IR verification is skipped.
+class SkipCompilation {
+ int iFld;
+ @Test(compLevel = CompLevel.C2)
+ @IR(failOn = IRNode.STORE) // Would fail but not evaluated.
+ public void testC2() {
+ iFld = 34;
+ }
+
+ @Check(test = "testC2")
+ public void checkC2(TestInfo info) {
+ Asserts.assertTrue(info.isCompilationSkipped());
+ Asserts.assertFalse(info.isC2CompilationEnabled());
+ }
+
+ @Test(compLevel = CompLevel.C2)
+ @IR(failOn = IRNode.STORE) // Would fail but not evaluated.
+ public void test2C2() {
+ iFld = 34;
+ }
+
+
+ @Run(test = "test2C2")
+ public void run2C2(RunInfo info) {
+ Asserts.assertFalse(info.isC2CompilationEnabled());
+ Asserts.assertTrue(info.isCompilationSkipped());
+ test2C2();
+ Asserts.assertTrue(info.isCompilationSkipped());
+ }
+
+ @Test(compLevel = CompLevel.C2)
+ @IR(failOn = IRNode.STORE) // Would fail but not evaluated.
+ public void test3C2() {
+ iFld = 34;
+ }
+
+ @Test(compLevel = CompLevel.C2)
+ @IR(failOn = IRNode.STORE) // Would fail but not evaluated.
+ public void test4C2() {
+ iFld = 34;
+ }
+
+
+ @Test // Level any
+ @IR(failOn = IRNode.STORE) // Would fail but not evaluated.
+ public void testAny() {
+ iFld = 34;
+ }
+
+ @Run(test = {"test3C2", "test4C2", "testAny"})
+ public void runMulti(RunInfo info) {
+ Asserts.assertFalse(info.isC2CompilationEnabled());
+ if (!info.isWarmUp()) {
+ TestFramework.assertNotCompiled(info.getTest("testAny"));
+ TestFramework.assertNotCompiled(info.getTest("test3C2"));
+ TestFramework.assertNotCompiled(info.getTest("test4C2"));
+ }
+ Asserts.assertTrue(info.isCompilationSkipped("test3C2"));
+ Asserts.assertTrue(info.isCompilationSkipped("test4C2"));
+ Asserts.assertTrue(info.isCompilationSkipped("testAny"));
+ test2C2();
+ Asserts.assertTrue(info.isCompilationSkipped("test3C2"));
+ Asserts.assertTrue(info.isCompilationSkipped("test4C2"));
+ Asserts.assertTrue(info.isCompilationSkipped("testAny"));
+ }
+}
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestSanity.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestSanity.java
new file mode 100644
index 00000000000..77f8a157363
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestSanity.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2021, 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.Scenario;
+import compiler.lib.ir_framework.Test;
+import compiler.lib.ir_framework.TestFramework;
+
+/*
+ * @test
+ * @requires vm.flagless
+ * @summary Sanity test the different ways to start the test framework.
+ * @library /test/lib /
+ * @run driver ir_framework.tests.TestSanity
+ */
+
+public class TestSanity {
+
+ public static void main(String[] args) {
+ TestFramework.run();
+ TestFramework.run(TestSanity.class);
+ TestFramework.runWithFlags("-XX:+TieredCompilation");
+ new TestFramework().addFlags("-XX:TLABRefillWasteFraction=51", "-XX:+UseTLAB").start();
+ new TestFramework(TestSanity.class).addFlags("-XX:TLABRefillWasteFraction=51", "-XX:+UseTLAB").start();
+ new TestFramework().addHelperClasses(HelperA.class).start();
+ new TestFramework(TestSanity.class).addHelperClasses(HelperA.class, HelperB.class).start();
+ Scenario sDefault = new Scenario(0);
+ Scenario s1 = new Scenario(1, "-XX:TLABRefillWasteFraction=52", "-XX:+UseTLAB");
+ Scenario s2 = new Scenario(2, "-XX:TLABRefillWasteFraction=53", "-XX:+UseTLAB");
+ new TestFramework(TestSanity.class).addScenarios(s1).start();
+ new TestFramework().addScenarios(s1, s2).start();
+ new TestFramework(TestSanity.class).addScenarios(s1, s2).start();
+ new TestFramework().addScenarios(sDefault, s1).start();
+ new TestFramework().addScenarios(sDefault, s1, s2).start();
+ new TestFramework(TestSanity.class).addScenarios(sDefault, s1).start();
+ new TestFramework(TestSanity.class).addScenarios(sDefault, s1, s2).start();
+ TestFramework testFramework = new TestFramework();
+ testFramework.start();
+ testFramework.addFlags("-XX:TLABRefillWasteFraction=54").start();
+ testFramework = new TestFramework();
+ testFramework.addFlags("-XX:TLABRefillWasteFraction=55").addFlags("-XX:+UseTLAB").start();
+ testFramework = new TestFramework();
+ testFramework.addHelperClasses(HelperA.class, HelperB.class).start();
+ testFramework = new TestFramework();
+ testFramework.addHelperClasses(HelperA.class, HelperB.class).addHelperClasses(HelperC.class).start();
+ testFramework = new TestFramework();
+ testFramework.addScenarios(sDefault).addScenarios(s1, s2).start();
+ testFramework = new TestFramework();
+ testFramework.addHelperClasses(HelperA.class).addScenarios(sDefault).addFlags("-XX:+UseSuperWord").start();
+ testFramework = new TestFramework();
+ testFramework.addHelperClasses(HelperA.class).addFlags("-XX:+UseSuperWord", "-XX:+UseCompiler").addScenarios(sDefault)
+ .addHelperClasses(HelperB.class, HelperC.class).addScenarios(s1, s2).addFlags("-XX:+TieredCompilation").start();
+ testFramework = new TestFramework();
+ testFramework.addHelperClasses(HelperA.class).addFlags("-XX:+UseSuperWord", "-XX:+UseCompiler").addScenarios(sDefault)
+ .addHelperClasses(HelperB.class, HelperC.class).addScenarios(s1, s2).setDefaultWarmup(200)
+ .addFlags("-XX:+TieredCompilation").start();
+ }
+
+ @Test
+ public void test() {}
+}
+
+class HelperA { }
+class HelperB { }
+class HelperC { }
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestScenarios.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestScenarios.java
new file mode 100644
index 00000000000..64edcbc82e2
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestScenarios.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2021, 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 jdk.test.lib.Asserts;
+
+/*
+ * @test
+ * @requires vm.debug == true & vm.compMode != "Xint" & vm.compiler2.enabled & vm.flagless
+ * @summary Test scenarios with the framework.
+ * @library /test/lib /
+ * @run driver ir_framework.tests.TestScenarios
+ */
+
+public class TestScenarios {
+ public static void main(String[] args) {
+ Scenario sDefault = new Scenario(0);
+ Scenario s1 = new Scenario(1, "-XX:TLABRefillWasteFraction=51");
+ Scenario s2 = new Scenario(2, "-XX:TLABRefillWasteFraction=52");
+ Scenario s3 = new Scenario(3, "-XX:TLABRefillWasteFraction=53");
+ Scenario s3dup = new Scenario(3, "-XX:TLABRefillWasteFraction=53");
+ try {
+ new TestFramework().addScenarios(sDefault, s1, s2, s3).start();
+ Asserts.fail("Should not reach");
+ } catch (TestRunException e) {
+ Asserts.assertTrue(e.getMessage().contains("The following scenarios have failed: #0, #1, #3"), e.getMessage());
+ }
+ try {
+ new TestFramework().addScenarios(s1, s2, s3).start();
+ Asserts.fail("Should not reach");
+ } catch (TestRunException e) {
+ Asserts.assertTrue(e.getMessage().contains("The following scenarios have failed: #1, #3"), e.getMessage());
+ }
+ new TestFramework(ScenarioTest.class).addScenarios(s1, s2, s3).start();
+ try {
+ new TestFramework().addScenarios(s1, s3dup, s2, s3).start();
+ Asserts.fail("Should not reach");
+ } catch (RuntimeException e) {
+ Asserts.assertTrue(e.getMessage().contains("Cannot define two scenarios with the same index 3"), e.getMessage());
+ }
+ try {
+ new TestFramework(MyExceptionTest.class).addScenarios(s1, s2, s3).start();
+ Asserts.fail("Should not reach");
+ } catch (TestRunException e) {
+ Asserts.assertTrue(s1.getTestVMOutput().contains("Caused by: ir_framework.tests.MyScenarioException"));
+ Asserts.assertTrue(s2.getTestVMOutput().contains("Caused by: ir_framework.tests.MyScenarioException"));
+ Asserts.assertTrue(s3.getTestVMOutput().contains("Caused by: ir_framework.tests.MyScenarioException"));
+ } catch (Exception e) {
+ Asserts.fail("Should not catch other exceptions");
+ }
+
+ }
+
+ @Test
+ @IR(applyIf = {"TLABRefillWasteFraction", "64"}, counts = {IRNode.CALL, "1"})
+ public void failDefault() {
+ }
+
+ @Test
+ @IR(applyIf = {"TLABRefillWasteFraction", "51"}, counts = {IRNode.CALL, "1"})
+ @IR(applyIf = {"TLABRefillWasteFraction", "53"}, counts = {IRNode.CALL, "1"})
+ public void failS3() {
+ }
+}
+
+class ScenarioTest {
+ @Test
+ @IR(applyIf = {"TLABRefillWasteFraction", "54"}, counts = {IRNode.CALL, "1"})
+ public void doesNotFail() {
+ }
+}
+
+class MyExceptionTest {
+ int iFld;
+ @Test
+ @IR(failOn = IRNode.STORE) // Not evaluated due to MyScenarioException
+ public void test() {
+ iFld = 42;
+ throw new MyScenarioException();
+ }
+}
+
+class MyScenarioException extends RuntimeException {}
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestWithHelperClasses.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestWithHelperClasses.java
new file mode 100644
index 00000000000..f2359bf5900
--- /dev/null
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestWithHelperClasses.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2021, 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.driver.TestVMException;
+import compiler.lib.ir_framework.shared.TestFormatException;
+import jdk.test.lib.Asserts;
+
+/*
+ * @test
+ * @requires vm.flagless
+ * @summary Test the framework with helper classes.
+ * @library /test/lib /
+ * @run driver ir_framework.tests.TestWithHelperClasses
+ */
+
+public class TestWithHelperClasses {
+
+ public static void main(String[] args) {
+ new TestFramework().addHelperClasses(Helper1.class, Helper2.class).start();
+ try {
+ new TestFramework().addHelperClasses(Helper1.class).start();
+ shouldNotReach();
+ } catch (TestVMException e) {
+ Asserts.assertFalse(e.getExceptionInfo().contains("public static void ir_framework.tests.Helper1.foo() should have been C2 compiled"));
+ Asserts.assertFalse(TestFramework.getLastTestVMOutput().contains("public static void ir_framework.tests.Helper1.foo() should have been C2 compiled"));
+ Asserts.assertTrue(TestFramework.getLastTestVMOutput().contains("public static void ir_framework.tests.Helper2.foo() should have been C2 compiled"));
+ Asserts.assertTrue(e.getExceptionInfo().contains("public static void ir_framework.tests.Helper2.foo() should have been C2 compiled"));
+ Asserts.assertFalse(TestFramework.getLastTestVMOutput().contains("Should not be executed"));
+ Asserts.assertFalse(e.getExceptionInfo().contains("Should not be executed"));
+ }
+
+ try {
+ new TestFramework(BadHelperClass.class).addHelperClasses(BadHelper.class).start();
+ shouldNotReach();
+ } catch (TestFormatException e) {
+ Asserts.assertTrue(e.getMessage().contains("Cannot use @Test annotation in helper class"));
+ Asserts.assertTrue(e.getMessage().contains("Cannot use @Check annotation in helper class"));
+ Asserts.assertTrue(e.getMessage().contains("Cannot use @Run annotation in helper class"));
+ Asserts.assertTrue(e.getMessage().contains("noTestInHelper"));
+ Asserts.assertTrue(e.getMessage().contains("test2"));
+ Asserts.assertTrue(e.getMessage().contains("check2"));
+ Asserts.assertTrue(e.getMessage().contains("test3"));
+ Asserts.assertTrue(e.getMessage().contains("run3"));
+ }
+
+ try {
+ new TestFramework(TestAsHelper.class).addHelperClasses(TestAsHelper.class).start();
+ shouldNotReach();
+ } catch (TestFormatException e) {
+ Asserts.assertTrue(e.getMessage().contains("Cannot specify test class ir_framework.tests." +
+ "TestAsHelper as helper class, too"));
+ }
+
+ try {
+ new TestFramework().addHelperClasses(NestedHelper.class).start();
+ shouldNotReach();
+ } catch (TestFormatException e) {
+ Asserts.assertTrue(e.getMessage().contains("Nested class"));
+ Asserts.assertTrue(e.getMessage().contains("TestWithHelperClasses$NestedHelper inside test class"));
+ }
+ }
+
+ public static void shouldNotReach() {
+ throw new RuntimeException("should not reach");
+ }
+
+ @Test
+ public void test() throws NoSuchMethodException {
+ TestFramework.assertCompiledByC2(Helper1.class.getMethod("foo"));
+ TestFramework.assertCompiledByC2(Helper2.class.getMethod("foo"));
+ TestFramework.assertCompiledByC2(NestedHelper.class.getMethod("foo"));
+ TestFramework.assertCompiledByC2(StaticNestedHelper.class.getMethod("foo"));
+ }
+
+ class NestedHelper {
+ @ForceCompile(CompLevel.C2)
+ public void foo() {
+ throw new RuntimeException("Should not be executed");
+ }
+ }
+
+
+ static class StaticNestedHelper {
+ @ForceCompile(CompLevel.C2)
+ public void foo() {
+ throw new RuntimeException("Should not be executed");
+ }
+ }
+}
+
+class TestAsHelper {
+
+ @Test
+ public void foo() {}
+}
+
+class Helper1 {
+
+ @ForceCompile(CompLevel.C2)
+ public static void foo() {
+ throw new RuntimeException("Should not be executed");
+ }
+}
+
+class Helper2 {
+
+ @ForceCompile(CompLevel.C2)
+ public static void foo() {
+ throw new RuntimeException("Should not be executed");
+ }
+}
+
+class BadHelperClass {
+ @Test
+ public void test1() {}
+ }
+
+
+class BadHelper {
+ @Test
+ public void noTestInHelper() {}
+
+ @Test
+ public void test2() {}
+
+ @Check(test = "test2")
+ public void check2() {}
+
+ @Test
+ public void test3() {}
+
+ @Run(test = "test3")
+ public void run3() {}
+}
diff --git a/test/lib/jdk/test/lib/util/ClassFileInstaller.java b/test/lib/jdk/test/lib/util/ClassFileInstaller.java
new file mode 100644
index 00000000000..96f0db0989a
--- /dev/null
+++ b/test/lib/jdk/test/lib/util/ClassFileInstaller.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2016, 2021, 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 jdk.test.lib.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * Dump a class file for a class on the class path in the current directory, or
+ * in the specified JAR file. This class is usually used when you build a class
+ * from a test library, but want to use this class in a sub-process.
+ *
+ * For example, to build the following library class:
+ * test/lib/sun/hotspot/WhiteBox.java
+ *
+ * You would use the following tags:
+ *
+ * @library /test/lib
+ * @build sun.hotspot.WhiteBox
+ *
+ * JTREG would build the class file under
+ * ${JTWork}/classes/test/lib/sun/hotspot/WhiteBox.class
+ *
+ * With you run your main test class using "@run main MyMainClass", JTREG would setup the
+ * -classpath to include "${JTWork}/classes/test/lib/", so MyMainClass would be able to
+ * load the WhiteBox class.
+ *
+ * However, if you run a sub process, and do not wish to use the exact same -classpath,
+ * You can use ClassFileInstaller to ensure that WhiteBox is available in the current
+ * directory of your test:
+ *
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ *
+ * Or, you can use the -jar option to store the class in the specified JAR file. If a relative
+ * path name is given, the JAR file would be relative to the current directory of
+ *
+ * @run driver ClassFileInstaller -jar myjar.jar sun.hotspot.WhiteBox
+ */
+public class ClassFileInstaller {
+ /**
+ * You can enable debug tracing of ClassFileInstaller by running JTREG with
+ * jtreg -DClassFileInstaller.debug=true ...
+ */
+ public static boolean DEBUG = Boolean.getBoolean("ClassFileInstaller.debug");
+
+ /**
+ * @param args The names of the classes to dump
+ * @throws Exception
+ */
+ public static void main(String... args) throws Exception {
+ if (args.length > 1 && args[0].equals("-jar")) {
+ if (args.length < 2) {
+ throw new RuntimeException("Usage: ClassFileInstaller \n" +
+ "where possible options include:\n" +
+ " -jar Write to the JAR file ");
+ }
+ String jarFile = args[1];
+ String[] classes = addInnerClasses(args, 2);
+ writeJar_impl(jarFile, null, classes);
+ } else {
+ if (DEBUG) {
+ System.out.println("ClassFileInstaller: Writing to " + System.getProperty("user.dir"));
+ }
+ String[] classes = addInnerClasses(args, 0);
+ for (String cls : classes) {
+ writeClassToDisk(cls);
+ }
+ }
+ }
+
+ // Add commonly used inner classes that are often omitted by mistake. Currently
+ // we support only sun.hotspot.WhiteBox$WhiteBoxPermission. See JDK-8199290
+ private static String[] addInnerClasses(String[] classes, int startIdx) {
+ boolean seenWB = false;
+ boolean seenWBInner = false;
+ final String wb = "sun.hotspot.WhiteBox";
+ final String wbInner = "sun.hotspot.WhiteBox$WhiteBoxPermission";
+
+ ArrayList list = new ArrayList<>();
+
+ for (int i = startIdx; i < classes.length; i++) {
+ String cls = classes[i];
+ list.add(cls);
+ switch (cls) {
+ case wb: seenWB = true; break;
+ case wbInner: seenWBInner = true; break;
+ }
+ }
+ if (seenWB && !seenWBInner) {
+ list.add(wbInner);
+ }
+
+ String[] array = new String[list.size()];
+ list.toArray(array);
+ return array;
+ }
+
+ public static class Manifest {
+ private InputStream in;
+
+ private Manifest(InputStream in) {
+ this.in = in;
+ }
+
+ static Manifest fromSourceFile(String fileName) throws Exception {
+ String pathName = System.getProperty("test.src") + File.separator + fileName;
+ return new Manifest(new FileInputStream(pathName));
+ }
+
+ // Example:
+ // String manifest = "Premain-Class: RedefineClassHelper\n" +
+ // "Can-Redefine-Classes: true\n";
+ // ClassFileInstaller.writeJar("redefineagent.jar",
+ // ClassFileInstaller.Manifest.fromString(manifest),
+ // "RedefineClassHelper");
+ static Manifest fromString(String manifest) throws Exception {
+ return new Manifest(new ByteArrayInputStream(manifest.getBytes()));
+ }
+
+ public InputStream getInputStream() {
+ return in;
+ }
+ }
+
+ private static void writeJar_impl(String jarFile, Manifest manifest, String classes[]) throws Exception {
+ if (DEBUG) {
+ System.out.println("ClassFileInstaller: Writing to " + getJarPath(jarFile));
+ }
+
+ (new File(jarFile)).delete();
+ FileOutputStream fos = new FileOutputStream(jarFile);
+ ZipOutputStream zos = new ZipOutputStream(fos);
+
+ // The manifest must be the first or second entry. See comments in JarInputStream
+ // constructor and JDK-5046178.
+ if (manifest != null) {
+ writeToDisk(zos, "META-INF/MANIFEST.MF", manifest.getInputStream());
+ }
+
+ for (String cls : classes) {
+ writeClassToDisk(zos, cls);
+ }
+
+ zos.close();
+ fos.close();
+ }
+
+ /*
+ * You can call ClassFileInstaller.writeJar() from your main test class instead of
+ * using "@run ClassFileInstaller -jar ...". E.g.,
+ *
+ * String jarPath = ClassFileInstaller.getJarPath("myjar.jar", "sun.hotspot.WhiteBox")
+ *
+ * If you call this API, make sure you build ClassFileInstaller with the following tags:
+ *
+ * @library testlibrary
+ * @build ClassFileInstaller
+ */
+ public static String writeJar(String jarFile, String... classes) throws Exception {
+ classes = addInnerClasses(classes, 0);
+ writeJar_impl(jarFile, null, classes);
+ return getJarPath(jarFile);
+ }
+
+ public static String writeJar(String jarFile, Manifest manifest, String... classes) throws Exception {
+ classes = addInnerClasses(classes, 0);
+ writeJar_impl(jarFile, manifest, classes);
+ return getJarPath(jarFile);
+ }
+
+ /**
+ * This returns the absolute path to the file specified in "@ClassFileInstaller -jar myjar.jar",
+ * In your test program, instead of using the JAR file name directly:
+ *
+ * String jarPath = "myjar.jar";
+ *
+ * you should call this function, like:
+ *
+ * String jarPath = ClassFileInstaller.getJarPath("myjar.jar")
+ *
+ * The reasons are:
+ * (1) Using absolute path makes it easy to cut-and-paste from the JTR file and rerun your
+ * test in any directory.
+ * (2) In the future, we may make the JAR file name unique to avoid clobbering
+ * during parallel JTREG execution.
+ *
+ */
+ public static String getJarPath(String jarFileName) {
+ return new File(jarFileName).getAbsolutePath();
+ }
+
+ public static void writeClassToDisk(String className) throws Exception {
+ writeClassToDisk((ZipOutputStream)null, className);
+ }
+ private static void writeClassToDisk(ZipOutputStream zos, String className) throws Exception {
+ writeClassToDisk(zos, className, "");
+ }
+
+ public static void writeClassToDisk(String className, String prependPath) throws Exception {
+ writeClassToDisk(null, className, prependPath);
+ }
+ private static void writeClassToDisk(ZipOutputStream zos, String className, String prependPath) throws Exception {
+ ClassLoader cl = ClassFileInstaller.class.getClassLoader();
+
+ // Convert dotted class name to a path to a class file
+ String pathName = className.replace('.', '/').concat(".class");
+ InputStream is = cl.getResourceAsStream(pathName);
+ if (is == null) {
+ throw new RuntimeException("Failed to find " + pathName);
+ }
+ if (prependPath.length() > 0) {
+ pathName = prependPath + "/" + pathName;
+ }
+ writeToDisk(zos, pathName, is);
+ }
+
+ public static void writeClassToDisk(String className, byte[] bytecode) throws Exception {
+ writeClassToDisk(null, className, bytecode);
+ }
+ private static void writeClassToDisk(ZipOutputStream zos, String className, byte[] bytecode) throws Exception {
+ writeClassToDisk(zos, className, bytecode, "");
+ }
+
+ public static void writeClassToDisk(String className, byte[] bytecode, String prependPath) throws Exception {
+ writeClassToDisk(null, className, bytecode, prependPath);
+ }
+ private static void writeClassToDisk(ZipOutputStream zos, String className, byte[] bytecode, String prependPath) throws Exception {
+ // Convert dotted class name to a path to a class file
+ String pathName = className.replace('.', '/').concat(".class");
+ if (prependPath.length() > 0) {
+ pathName = prependPath + "/" + pathName;
+ }
+ writeToDisk(zos, pathName, new ByteArrayInputStream(bytecode));
+ }
+
+ private static void writeToDisk(ZipOutputStream zos, String pathName, InputStream is) throws Exception {
+ if (DEBUG) {
+ System.out.println("ClassFileInstaller: Writing " + pathName);
+ }
+ if (zos != null) {
+ ZipEntry ze = new ZipEntry(pathName);
+ zos.putNextEntry(ze);
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = is.read(buf))>0){
+ zos.write(buf, 0, len);
+ }
+ } else {
+ // Create the class file's package directory
+ Path p = Paths.get(pathName);
+ if (pathName.contains("/")) {
+ Files.createDirectories(p.getParent());
+ }
+ // Create the class file
+ Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING);
+ }
+ is.close();
+ }
+}