提交 fd6a5e93 编写于 作者: X xliu

8059575: JEP-JDK-8043304: Test task: Tiered Compilation level transition tests

Summary: Includes compile_id addition from JDK-8054492
Reviewed-by: andrew
上级 164f6e98
......@@ -848,19 +848,23 @@ WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jbo
ThreadToNativeFromVM ttn(thread);
jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
result = env->NewObjectArray(2, clazz, NULL);
result = env->NewObjectArray(3, clazz, NULL);
if (result == NULL) {
return result;
}
jobject obj = integerBox(thread, env, code->comp_level());
jobject level = integerBox(thread, env, code->comp_level());
CHECK_JNI_EXCEPTION_(env, NULL);
env->SetObjectArrayElement(result, 0, obj);
env->SetObjectArrayElement(result, 0, level);
jobject id = integerBox(thread, env, code->compile_id());
CHECK_JNI_EXCEPTION_(env, NULL);
env->SetObjectArrayElement(result, 1, id);
jbyteArray insts = env->NewByteArray(insts_size);
CHECK_JNI_EXCEPTION_(env, NULL);
env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
env->SetObjectArrayElement(result, 1, insts);
env->SetObjectArrayElement(result, 2, insts);
return result;
WB_END
......
/*
* Copyright (c) 2014, 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.
*/
import java.lang.reflect.Executable;
import java.util.concurrent.Callable;
/**
* @test ConstantGettersTransitionsTest
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
* @build TransitionsTestExecutor ConstantGettersTransitionsTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm/timeout=240 -Xmixed -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:+TieredCompilation
* -XX:CompileCommand=compileonly,ConstantGettersTestCase$TrivialMethods::*
* TransitionsTestExecutor ConstantGettersTransitionsTest
* @summary Test the correctness of compilation level transitions for constant getters methods
*/
public class ConstantGettersTransitionsTest extends LevelTransitionTest {
public static void main(String[] args) {
assert (!CompilerWhiteBoxTest.skipOnTieredCompilation(false));
// run test cases
for (TestCase testCase : ConstantGettersTestCase.values()) {
new ConstantGettersTransitionsTest(testCase).runTest();
}
}
@Override
protected boolean isTrivial() {
return true;
}
private ConstantGettersTransitionsTest(TestCase testCase) {
super(testCase);
}
}
enum ConstantGettersTestCase implements CompilerWhiteBoxTest.TestCase {
ICONST_M1,
ICONST_0,
ICONST_1,
ICONST_2,
ICONST_3,
ICONST_4,
ICONST_5,
LCONST_0,
LCONST_1,
FCONST_0,
FCONST_1,
FCONST_2,
DCONST_0,
DCONST_1,
DCONST_W,
BYTE,
SHORT,
CHAR;
private final Executable executable;
private final Callable<Integer> callable;
@Override
public Executable getExecutable() {
return executable;
}
@Override
public Callable<Integer> getCallable() {
return callable;
}
@Override
public boolean isOsr() {
return false;
}
private ConstantGettersTestCase() {
String name = "make" + this.name();
this.executable = LevelTransitionTest.Helper.getMethod(TrivialMethods.class, name);
this.callable = LevelTransitionTest.Helper.getCallable(new TrivialMethods(), name);
}
/**
* Contains methods that load constants with certain types of bytecodes
* See JVMS 2.11.2. Load and Store Instructions
* Note that it doesn't have a method for ldc_w instruction
*/
private static class TrivialMethods {
public static int makeICONST_M1() {
return -1;
}
public static int makeICONST_0() {
return 0;
}
public static int makeICONST_1() {
return 1;
}
public static int makeICONST_2() {
return 2;
}
public static int makeICONST_3() {
return 3;
}
public static int makeICONST_4() {
return 4;
}
public static int makeICONST_5() {
return 5;
}
public static long makeLCONST_0() {
return 0L;
}
public static long makeLCONST_1() {
return 1L;
}
public static float makeFCONST_0() {
return 0F;
}
public static float makeFCONST_1() {
return 1F;
}
public static float makeFCONST_2() {
return 2F;
}
public static double makeDCONST_0() {
return 0D;
}
public static double makeDCONST_1() {
return 1D;
}
public static double makeDCONST_W() {
// ldc2_w
return Double.MAX_VALUE;
}
public static Object makeOBJECT() {
// aconst_null
return null;
}
public static byte makeBYTE() {
// bipush
return (byte) 0x7F;
}
public static short makeSHORT() {
// sipush
return (short) 0x7FFF;
}
public static char makeCHAR() {
// ldc
return (char) 0xFFFF;
}
public static boolean makeBOOLEAN() {
return true;
}
}
}
/*
* Copyright (c) 2014, 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.
*/
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.Callable;
/**
* @test LevelTransitionTest
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
* @build TransitionsTestExecutor LevelTransitionTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm/timeout=240 -Xmixed -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:+TieredCompilation
* -XX:CompileCommand=compileonly,SimpleTestCase$Helper::*
* -XX:CompileCommand=compileonly,ExtendedTestCase$CompileMethodHolder::*
* TransitionsTestExecutor LevelTransitionTest
* @summary Test the correctness of compilation level transitions for different methods
*/
public class LevelTransitionTest extends TieredLevelsTest {
/** Shows if method was profiled by being executed on levels 2 or 3 */
protected boolean isMethodProfiled;
private int transitionCount;
public static void main(String[] args) throws Throwable {
assert (!CompilerWhiteBoxTest.skipOnTieredCompilation(false));
CompilerWhiteBoxTest.main(LevelTransitionTest::new, args);
// run extended test cases
for (TestCase testCase : ExtendedTestCase.values()) {
new LevelTransitionTest(testCase).runTest();
}
}
protected LevelTransitionTest(TestCase testCase) {
super(testCase);
isMethodProfiled = testCase.isOsr(); // OSR methods were already profiled by warmup
transitionCount = 0;
}
@Override
protected void test() throws Exception {
checkTransitions();
deoptimize();
printInfo();
if (testCase.isOsr()) {
// deoptimization makes the following transitions be unstable
// methods go to level 3 before 4 because of uncommon_trap and reprofile
return;
}
checkTransitions();
}
/**
* Makes and verifies transitions between compilation levels
*/
protected void checkTransitions() {
checkNotCompiled();
boolean finish = false;
while (!finish) {
System.out.printf("Level transition #%d%n", ++transitionCount);
int newLevel;
int current = getCompLevel();
int expected = getNextLevel(current);
if (current == expected) {
// if we are on expected level, just execute it more
// to ensure that the level won't change
System.out.printf("Method %s is already on expected level %d%n", method, expected);
compile();
newLevel = getCompLevel();
finish = true;
} else {
newLevel = changeCompLevel();
finish = false;
}
System.out.printf("Method %s is compiled on level %d. Expected level is %d%n", method, newLevel, expected);
checkLevel(expected, newLevel);
printInfo();
};
}
/**
* Gets next expected level for the test case on each transition.
*
* @param currentLevel a level the test case is compiled on
* @return expected compilation level
*/
protected int getNextLevel(int currentLevel) {
int nextLevel = currentLevel;
switch (currentLevel) {
case CompilerWhiteBoxTest.COMP_LEVEL_NONE:
nextLevel = isMethodProfiled ? CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION
: CompilerWhiteBoxTest.COMP_LEVEL_FULL_PROFILE;
break;
case CompilerWhiteBoxTest.COMP_LEVEL_LIMITED_PROFILE:
case CompilerWhiteBoxTest.COMP_LEVEL_FULL_PROFILE:
nextLevel = CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION;
isMethodProfiled = true;
break;
}
nextLevel = isTrivial() ? CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE : nextLevel;
return Math.min(nextLevel, CompilerWhiteBoxTest.TIERED_STOP_AT_LEVEL);
}
/**
* Determines if tested method should be handled as trivial
*
* @return {@code true} for trivial methods, {@code false} otherwise
*/
protected boolean isTrivial() {
return testCase == ExtendedTestCase.ACCESSOR_TEST
|| testCase == SimpleTestCase.METHOD_TEST
|| testCase == SimpleTestCase.STATIC_TEST
|| (testCase == ExtendedTestCase.TRIVIAL_CODE_TEST && isMethodProfiled);
}
/**
* Invokes {@linkplain #method} until its compilation level is changed.
* Note that if the level won't change, it will be an endless loop
*
* @return compilation level the {@linkplain #method} was compiled on
*/
protected int changeCompLevel() {
int currentLevel = getCompLevel();
int newLevel = currentLevel;
int result = 0;
while (currentLevel == newLevel) {
result = compile(1);
if (WHITE_BOX.isMethodCompiled(method, testCase.isOsr())) {
newLevel = getCompLevel();
}
}
return newLevel;
}
protected static class Helper {
/**
* Gets method from a specified class using its name
*
* @param aClass type method belongs to
* @param name the name of the method
* @return {@link Method} that represents corresponding class method
*/
public static Method getMethod(Class<?> aClass, String name) {
Method method;
try {
method = aClass.getDeclaredMethod(name);
} catch (NoSuchMethodException e) {
throw new Error("TESTBUG: Unable to get method " + name, e);
}
return method;
}
/**
* Gets {@link Callable} that invokes given method from the given object
*
* @param object the object the specified method is invoked from
* @param name the name of the method
*/
public static Callable<Integer> getCallable(Object object, String name) {
Method method = getMethod(object.getClass(), name);
return () -> {
try {
return Objects.hashCode(method.invoke(object));
} catch (ReflectiveOperationException e) {
throw new Error("TESTBUG: Invocation failure", e);
}
};
}
}
}
enum ExtendedTestCase implements CompilerWhiteBoxTest.TestCase {
ACCESSOR_TEST("accessor"),
NONTRIVIAL_METHOD_TEST("nonTrivialMethod"),
TRIVIAL_CODE_TEST("trivialCode");
private final Executable executable;
private final Callable<Integer> callable;
@Override
public Executable getExecutable() {
return executable;
}
@Override
public Callable<Integer> getCallable() {
return callable;
}
@Override
public boolean isOsr() {
return false;
}
private ExtendedTestCase(String methodName) {
this.executable = LevelTransitionTest.Helper.getMethod(CompileMethodHolder.class, methodName);
this.callable = LevelTransitionTest.Helper.getCallable(new CompileMethodHolder(), methodName);
}
private static class CompileMethodHolder {
private final int iter = 10;
private int field = 42;
/** Non-trivial method for threshold policy: contains loops */
public int nonTrivialMethod() {
int acc = 0;
for (int i = 0; i < iter; i++) {
acc += i;
}
return acc;
}
/** Field accessor method */
public int accessor() {
return field;
}
/** Method considered as trivial by amount of code */
public int trivialCode() {
int var = 0xBAAD_C0DE;
var *= field;
return var;
}
}
}
......@@ -54,9 +54,7 @@ public class NonTieredLevelsTest extends CompLevelsTest {
}
public static void main(String[] args) throws Exception {
if (TIERED_COMPILATION) {
System.err.println("Test isn't applicable w/ enabled "
+ "TieredCompilation. Skip test.");
if (CompilerWhiteBoxTest.skipOnTieredCompilation(true)) {
return;
}
CompilerWhiteBoxTest.main(NonTieredLevelsTest::new, args);
......
......@@ -34,16 +34,14 @@
* @author igor.ignatyev@oracle.com
*/
public class TieredLevelsTest extends CompLevelsTest {
public static void main(String[] args) throws Exception {
if (!TIERED_COMPILATION) {
System.err.println("Test isn't applicable w/ disabled "
+ "TieredCompilation. Skip test.");
public static void main(String[] args) throws Exception, Throwable {
if (CompilerWhiteBoxTest.skipOnTieredCompilation(false)) {
return;
}
CompilerWhiteBoxTest.main(TieredLevelsTest::new, args);
}
private TieredLevelsTest(TestCase testCase) {
protected TieredLevelsTest(TestCase testCase) {
super(testCase);
// to prevent inlining of #method
WHITE_BOX.testSetDontInlineMethod(method, true);
......@@ -76,14 +74,18 @@ public class TieredLevelsTest extends CompLevelsTest {
}
}
@Override
protected void checkLevel(int expected, int actual) {
if (expected == COMP_LEVEL_FULL_PROFILE
&& actual == COMP_LEVEL_LIMITED_PROFILE) {
// for simple method full_profile may be replaced by limited_profile
if (IS_VERBOSE) {
System.out.printf("Level check: full profiling was replaced "
+ "by limited profiling. Expected: %d, actual:%d",
expected, actual);
}
return;
}
super.checkLevel(expected, actual);
}
}
}
/*
* Copyright (c) 2014, 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.
*/
import com.oracle.java.testlibrary.OutputAnalyzer;
import com.oracle.java.testlibrary.ProcessTools;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Executes given test in a separate VM with enabled Tiered Compilation for
* CompilationPolicyChoice 2 and 3
*/
public class TransitionsTestExecutor {
public static void main(String[] args) throws Throwable {
if (CompilerWhiteBoxTest.skipOnTieredCompilation(false)) {
return;
}
if (args.length != 1) {
throw new Error("TESTBUG: Test name should be specified");
}
executeTestFor(2, args[0]);
executeTestFor(3, args[0]);
}
private static void executeTestFor(int compilationPolicy, String testName) throws Throwable {
String policy = "-XX:CompilationPolicyChoice=" + compilationPolicy;
// Get runtime arguments including VM options given to this executor
RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
List<String> vmArgs = runtime.getInputArguments();
// Construct execution command with compilation policy choice and test name
List<String> args = new ArrayList<>(vmArgs);
Collections.addAll(args, policy, testName);
OutputAnalyzer out = ProcessTools.executeTestJvm(args.toArray(new String[args.size()]));
int exitCode = out.getExitValue();
if (exitCode != 0) {
throw new Error("Test execution failed with exit code " + exitCode);
}
}
}
......@@ -41,19 +41,19 @@ import java.util.function.Function;
*/
public abstract class CompilerWhiteBoxTest {
/** {@code CompLevel::CompLevel_none} -- Interpreter */
protected static int COMP_LEVEL_NONE = 0;
protected static final int COMP_LEVEL_NONE = 0;
/** {@code CompLevel::CompLevel_any}, {@code CompLevel::CompLevel_all} */
protected static int COMP_LEVEL_ANY = -1;
protected static final int COMP_LEVEL_ANY = -1;
/** {@code CompLevel::CompLevel_simple} -- C1 */
protected static int COMP_LEVEL_SIMPLE = 1;
protected static final int COMP_LEVEL_SIMPLE = 1;
/** {@code CompLevel::CompLevel_limited_profile} -- C1, invocation &amp; backedge counters */
protected static int COMP_LEVEL_LIMITED_PROFILE = 2;
protected static final int COMP_LEVEL_LIMITED_PROFILE = 2;
/** {@code CompLevel::CompLevel_full_profile} -- C1, invocation &amp; backedge counters + mdo */
protected static int COMP_LEVEL_FULL_PROFILE = 3;
protected static final int COMP_LEVEL_FULL_PROFILE = 3;
/** {@code CompLevel::CompLevel_full_optimization} -- C2 or Shark */
protected static int COMP_LEVEL_FULL_OPTIMIZATION = 4;
protected static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
/** Maximal value for CompLevel */
protected static int COMP_LEVEL_MAX = COMP_LEVEL_FULL_OPTIMIZATION;
protected static final int COMP_LEVEL_MAX = COMP_LEVEL_FULL_OPTIMIZATION;
/** Instance of WhiteBox */
protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
......@@ -347,14 +347,22 @@ public abstract class CompilerWhiteBoxTest {
System.out.printf("%n%s:%n", method);
System.out.printf("\tcompilable:\t%b%n",
WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY, false));
System.out.printf("\tcompiled:\t%b%n",
WHITE_BOX.isMethodCompiled(method, false));
boolean isCompiled = WHITE_BOX.isMethodCompiled(method, false);
System.out.printf("\tcompiled:\t%b%n", isCompiled);
if (isCompiled) {
System.out.printf("\tcompile_id:\t%d%n",
NMethod.get(method, false).compile_id);
}
System.out.printf("\tcomp_level:\t%d%n",
WHITE_BOX.getMethodCompilationLevel(method, false));
System.out.printf("\tosr_compilable:\t%b%n",
WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY, true));
System.out.printf("\tosr_compiled:\t%b%n",
WHITE_BOX.isMethodCompiled(method, true));
isCompiled = WHITE_BOX.isMethodCompiled(method, true);
System.out.printf("\tosr_compiled:\t%b%n", isCompiled);
if (isCompiled) {
System.out.printf("\tosr_compile_id:\t%d%n",
NMethod.get(method, true).compile_id);
}
System.out.printf("\tosr_comp_level:\t%d%n",
WHITE_BOX.getMethodCompilationLevel(method, true));
System.out.printf("\tin_queue:\t%b%n",
......@@ -437,6 +445,22 @@ public abstract class CompilerWhiteBoxTest {
}
return result;
}
/**
* Skip the test for the specified value of Tiered Compilation
* @param value of TieredCompilation the test should not run with
* @return {@code true} if the test should be skipped,
* {@code false} otherwise
*/
protected static boolean skipOnTieredCompilation(boolean value) {
if (value == CompilerWhiteBoxTest.TIERED_COMPILATION) {
System.err.println("Test isn't applicable w/ "
+ (value ? "enabled" : "disabled")
+ "TieredCompilation. Skip test.");
return true;
}
return false;
}
}
enum SimpleTestCase implements CompilerWhiteBoxTest.TestCase {
......
......@@ -34,18 +34,21 @@ public class NMethod {
return obj == null ? null : new NMethod(obj);
}
private NMethod(Object[] obj) {
assert obj.length == 2;
assert obj.length == 3;
comp_level = (Integer) obj[0];
insts = (byte[]) obj[1];
compile_id = (Integer) obj[1];
insts = (byte[]) obj[2];
}
public byte[] insts;
public int comp_level;
public final byte[] insts;
public final int comp_level;
public final int compile_id;
@Override
public String toString() {
return "NMethod{" +
"insts=" + insts +
", comp_level=" + comp_level +
", compile_id=" + compile_id +
'}';
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册