提交 9cd6f543 编写于 作者: I iignatyev

8011971: WB API doesn't accept j.l.reflect.Constructor

Reviewed-by: kvn, vlivanov
上级 6ea208d0
...@@ -237,10 +237,10 @@ WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject meth ...@@ -237,10 +237,10 @@ WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject meth
WB_END WB_END
WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method)) WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level))
jmethodID jmid = reflected_method_to_jmid(thread, env, method); jmethodID jmid = reflected_method_to_jmid(thread, env, method);
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
mh->set_not_compilable(); mh->set_not_compilable(comp_level, true /* report */, "WhiteBox");
WB_END WB_END
WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value)) WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
...@@ -398,28 +398,28 @@ static JNINativeMethod methods[] = { ...@@ -398,28 +398,28 @@ static JNINativeMethod methods[] = {
{CC"NMTWaitForDataMerge", CC"()Z", (void*)&WB_NMTWaitForDataMerge}, {CC"NMTWaitForDataMerge", CC"()Z", (void*)&WB_NMTWaitForDataMerge},
#endif // INCLUDE_NMT #endif // INCLUDE_NMT
{CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll }, {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll },
{CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Method;)I", {CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Executable;)I",
(void*)&WB_DeoptimizeMethod }, (void*)&WB_DeoptimizeMethod },
{CC"isMethodCompiled", CC"(Ljava/lang/reflect/Method;)Z", {CC"isMethodCompiled", CC"(Ljava/lang/reflect/Executable;)Z",
(void*)&WB_IsMethodCompiled }, (void*)&WB_IsMethodCompiled },
{CC"isMethodCompilable", CC"(Ljava/lang/reflect/Method;I)Z", {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Executable;I)Z",
(void*)&WB_IsMethodCompilable}, (void*)&WB_IsMethodCompilable},
{CC"isMethodQueuedForCompilation", {CC"isMethodQueuedForCompilation",
CC"(Ljava/lang/reflect/Method;)Z", (void*)&WB_IsMethodQueuedForCompilation}, CC"(Ljava/lang/reflect/Executable;)Z", (void*)&WB_IsMethodQueuedForCompilation},
{CC"makeMethodNotCompilable", {CC"makeMethodNotCompilable",
CC"(Ljava/lang/reflect/Method;)V", (void*)&WB_MakeMethodNotCompilable}, CC"(Ljava/lang/reflect/Executable;I)V", (void*)&WB_MakeMethodNotCompilable},
{CC"testSetDontInlineMethod", {CC"testSetDontInlineMethod",
CC"(Ljava/lang/reflect/Method;Z)Z", (void*)&WB_TestSetDontInlineMethod}, CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetDontInlineMethod},
{CC"getMethodCompilationLevel", {CC"getMethodCompilationLevel",
CC"(Ljava/lang/reflect/Method;)I", (void*)&WB_GetMethodCompilationLevel}, CC"(Ljava/lang/reflect/Executable;)I", (void*)&WB_GetMethodCompilationLevel},
{CC"getCompileQueuesSize", {CC"getCompileQueuesSize",
CC"()I", (void*)&WB_GetCompileQueuesSize}, CC"()I", (void*)&WB_GetCompileQueuesSize},
{CC"testSetForceInlineMethod", {CC"testSetForceInlineMethod",
CC"(Ljava/lang/reflect/Method;Z)Z", (void*)&WB_TestSetForceInlineMethod}, CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetForceInlineMethod},
{CC"enqueueMethodForCompilation", {CC"enqueueMethodForCompilation",
CC"(Ljava/lang/reflect/Method;I)Z", (void*)&WB_EnqueueMethodForCompilation}, CC"(Ljava/lang/reflect/Executable;I)Z", (void*)&WB_EnqueueMethodForCompilation},
{CC"clearMethodState", {CC"clearMethodState",
CC"(Ljava/lang/reflect/Method;)V", (void*)&WB_ClearMethodState}, CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState},
{CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable }, {CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable },
{CC"fullGC", CC"()V", (void*)&WB_FullGC }, {CC"fullGC", CC"()V", (void*)&WB_FullGC },
}; };
......
...@@ -27,42 +27,61 @@ ...@@ -27,42 +27,61 @@
* @build ClearMethodStateTest * @build ClearMethodStateTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ClearMethodStateTest * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ClearMethodStateTest
* @summary testing of WB::clearMethodState()
* @author igor.ignatyev@oracle.com * @author igor.ignatyev@oracle.com
*/ */
public class ClearMethodStateTest extends CompilerWhiteBoxTest { public class ClearMethodStateTest extends CompilerWhiteBoxTest {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// to prevent inlining #method into #compile() and #test() for (TestCase test : TestCase.values()) {
WHITE_BOX.testSetDontInlineMethod(METHOD, true); new ClearMethodStateTest(test).runTest();
new ClearMethodStateTest().runTest(); }
}
public ClearMethodStateTest(TestCase testCase) {
super(testCase);
// to prevent inlining of #method
WHITE_BOX.testSetDontInlineMethod(method, true);
} }
/**
* Tests {@code WB::clearMethodState()} by calling it before/after
* compilation. For non-tiered, checks that counters will be rested after
* clearing of method state.
*
* @throws Exception if one of the checks fails.
*/
@Override
protected void test() throws Exception { protected void test() throws Exception {
checkNotCompiled(METHOD); checkNotCompiled();
compile(); compile();
checkCompiled(METHOD); WHITE_BOX.clearMethodState(method);
WHITE_BOX.clearMethodState(METHOD); checkCompiled();
WHITE_BOX.deoptimizeMethod(METHOD); WHITE_BOX.clearMethodState(method);
checkNotCompiled(METHOD); WHITE_BOX.deoptimizeMethod(method);
checkNotCompiled();
if (!TIERED_COMPILATION) { if (!TIERED_COMPILATION) {
WHITE_BOX.clearMethodState(METHOD); WHITE_BOX.clearMethodState(method);
compile(COMPILE_THRESHOLD); compile(COMPILE_THRESHOLD);
checkCompiled(METHOD); checkCompiled();
WHITE_BOX.deoptimizeMethod(METHOD); WHITE_BOX.deoptimizeMethod(method);
checkNotCompiled(METHOD); checkNotCompiled();
WHITE_BOX.clearMethodState(METHOD); WHITE_BOX.clearMethodState(method);
// invoke method one less time than needed to compile
if (COMPILE_THRESHOLD > 1) { if (COMPILE_THRESHOLD > 1) {
compile(COMPILE_THRESHOLD - 1); compile(COMPILE_THRESHOLD - 1);
checkNotCompiled(METHOD); checkNotCompiled();
} else { } else {
System.err.println("Warning: 'CompileThreshold' <= 1"); System.err.println("Warning: 'CompileThreshold' <= 1");
} }
method(); compile(1);
checkCompiled(METHOD); checkCompiled();
} else { } else {
System.err.println( System.err.println(
"Warning: part of test is not applicable in Tiered"); "Warning: part of test is not applicable in Tiered");
......
...@@ -21,68 +21,132 @@ ...@@ -21,68 +21,132 @@
* questions. * questions.
*/ */
import com.sun.management.HotSpotDiagnosticMXBean;
import com.sun.management.VMOption;
import sun.hotspot.WhiteBox; import sun.hotspot.WhiteBox;
import sun.management.ManagementFactoryHelper; import sun.management.ManagementFactoryHelper;
import com.sun.management.HotSpotDiagnosticMXBean;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.Callable;
/* /**
* Abstract class for WhiteBox testing of JIT.
*
* @author igor.ignatyev@oracle.com * @author igor.ignatyev@oracle.com
*/ */
public abstract class CompilerWhiteBoxTest { public abstract class CompilerWhiteBoxTest {
/** {@code CompLevel::CompLevel_none} -- Interpreter */
protected static int COMP_LEVEL_NONE = 0;
/** {@code CompLevel::CompLevel_any}, {@code CompLevel::CompLevel_all} */
protected static int COMP_LEVEL_ANY = -1;
/** Instance of WhiteBox */
protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
protected static final Method METHOD = getMethod("method"); /** Value of {@code -XX:CompileThreshold} */
protected static final int COMPILE_THRESHOLD protected static final int COMPILE_THRESHOLD
= Integer.parseInt(getVMOption("CompileThreshold", "10000")); = Integer.parseInt(getVMOption("CompileThreshold", "10000"));
/** Value of {@code -XX:BackgroundCompilation} */
protected static final boolean BACKGROUND_COMPILATION protected static final boolean BACKGROUND_COMPILATION
= Boolean.valueOf(getVMOption("BackgroundCompilation", "true")); = Boolean.valueOf(getVMOption("BackgroundCompilation", "true"));
/** Value of {@code -XX:TieredCompilation} */
protected static final boolean TIERED_COMPILATION protected static final boolean TIERED_COMPILATION
= Boolean.valueOf(getVMOption("TieredCompilation", "false")); = Boolean.valueOf(getVMOption("TieredCompilation", "false"));
/** Value of {@code -XX:TieredStopAtLevel} */
protected static final int TIERED_STOP_AT_LEVEL
= Integer.parseInt(getVMOption("TieredStopAtLevel", "0"));
protected static Method getMethod(String name) { /**
try { * Returns value of VM option.
return CompilerWhiteBoxTest.class.getDeclaredMethod(name); *
} catch (NoSuchMethodException | SecurityException e) { * @param name option's name
throw new RuntimeException( * @return value of option or {@code null}, if option doesn't exist
"exception on getting method " + name, e); * @throws NullPointerException if name is null
} */
}
protected static String getVMOption(String name) { protected static String getVMOption(String name) {
String result; Objects.requireNonNull(name);
HotSpotDiagnosticMXBean diagnostic HotSpotDiagnosticMXBean diagnostic
= ManagementFactoryHelper.getDiagnosticMXBean(); = ManagementFactoryHelper.getDiagnosticMXBean();
result = diagnostic.getVMOption(name).getValue(); VMOption tmp;
return result; try {
tmp = diagnostic.getVMOption(name);
} catch (IllegalArgumentException e) {
tmp = null;
}
return (tmp == null ? null : tmp.getValue());
} }
/**
* Returns value of VM option or default value.
*
* @param name option's name
* @param defaultValue default value
* @return value of option or {@code defaultValue}, if option doesn't exist
* @throws NullPointerException if name is null
* @see #getVMOption(String)
*/
protected static String getVMOption(String name, String defaultValue) { protected static String getVMOption(String name, String defaultValue) {
String result = getVMOption(name); String result = getVMOption(name);
return result == null ? defaultValue : result; return result == null ? defaultValue : result;
} }
protected final void runTest() throws RuntimeException { /** tested method */
protected final Executable method;
private final Callable<Integer> callable;
/**
* Constructor.
*
* @param testCase object, that contains tested method and way to invoke it.
*/
protected CompilerWhiteBoxTest(TestCase testCase) {
Objects.requireNonNull(testCase);
System.out.println("TEST CASE:" + testCase.name());
method = testCase.executable;
callable = testCase.callable;
}
/**
* Template method for testing. Prints tested method's info before
* {@linkplain #test()} and after {@linkplain #test()} or on thrown
* exception.
*
* @throws RuntimeException if method {@linkplain #test()} throws any
* exception
* @see #test()
*/
protected final void runTest() {
if (ManagementFactoryHelper.getCompilationMXBean() == null) { if (ManagementFactoryHelper.getCompilationMXBean() == null) {
System.err.println( System.err.println(
"Warning: test is not applicable in interpreted mode"); "Warning: test is not applicable in interpreted mode");
return; return;
} }
System.out.println("at test's start:"); System.out.println("at test's start:");
printInfo(METHOD); printInfo();
try { try {
test(); test();
} catch (Exception e) { } catch (Exception e) {
System.out.printf("on exception '%s':", e.getMessage()); System.out.printf("on exception '%s':", e.getMessage());
printInfo(METHOD); printInfo();
e.printStackTrace(); e.printStackTrace();
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw new RuntimeException(e); throw new RuntimeException(e);
} }
System.out.println("at test's end:"); System.out.println("at test's end:");
printInfo(METHOD); printInfo();
} }
protected static void checkNotCompiled(Method method) { /**
* Checks, that {@linkplain #method} is not compiled.
*
* @throws RuntimeException if {@linkplain #method} is in compiler queue or
* is compiled, or if {@linkplain #method} has zero
* compilation level.
*/
protected final void checkNotCompiled() {
if (WHITE_BOX.isMethodQueuedForCompilation(method)) { if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
throw new RuntimeException(method + " must not be in queue"); throw new RuntimeException(method + " must not be in queue");
} }
...@@ -94,10 +158,16 @@ public abstract class CompilerWhiteBoxTest { ...@@ -94,10 +158,16 @@ public abstract class CompilerWhiteBoxTest {
} }
} }
protected static void checkCompiled(Method method) /**
throws InterruptedException { * Checks, that {@linkplain #method} is compiled.
*
* @throws RuntimeException if {@linkplain #method} isn't in compiler queue
* and isn't compiled, or if {@linkplain #method}
* has nonzero compilation level
*/
protected final void checkCompiled() {
final long start = System.currentTimeMillis(); final long start = System.currentTimeMillis();
waitBackgroundCompilation(method); waitBackgroundCompilation();
if (WHITE_BOX.isMethodQueuedForCompilation(method)) { if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
System.err.printf("Warning: %s is still in queue after %dms%n", System.err.printf("Warning: %s is still in queue after %dms%n",
method, System.currentTimeMillis() - start); method, System.currentTimeMillis() - start);
...@@ -111,23 +181,30 @@ public abstract class CompilerWhiteBoxTest { ...@@ -111,23 +181,30 @@ public abstract class CompilerWhiteBoxTest {
} }
} }
protected static void waitBackgroundCompilation(Method method) /**
throws InterruptedException { * Waits for completion of background compilation of {@linkplain #method}.
*/
protected final void waitBackgroundCompilation() {
if (!BACKGROUND_COMPILATION) { if (!BACKGROUND_COMPILATION) {
return; return;
} }
final Object obj = new Object(); final Object obj = new Object();
for (int i = 0; i < 10
&& WHITE_BOX.isMethodQueuedForCompilation(method); ++i) {
synchronized (obj) { synchronized (obj) {
for (int i = 0; i < 10; ++i) { try {
if (!WHITE_BOX.isMethodQueuedForCompilation(method)) {
break;
}
obj.wait(1000); obj.wait(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
} }
} }
} }
protected static void printInfo(Method method) { /**
* Prints information about {@linkplain #method}.
*/
protected final void printInfo() {
System.out.printf("%n%s:%n", method); System.out.printf("%n%s:%n", method);
System.out.printf("\tcompilable:\t%b%n", System.out.printf("\tcompilable:\t%b%n",
WHITE_BOX.isMethodCompilable(method)); WHITE_BOX.isMethodCompilable(method));
...@@ -141,22 +218,139 @@ public abstract class CompilerWhiteBoxTest { ...@@ -141,22 +218,139 @@ public abstract class CompilerWhiteBoxTest {
WHITE_BOX.getCompileQueuesSize()); WHITE_BOX.getCompileQueuesSize());
} }
/**
* Executes testing.
*/
protected abstract void test() throws Exception; protected abstract void test() throws Exception;
/**
* Tries to trigger compilation of {@linkplain #method} by call
* {@linkplain #callable} enough times.
*
* @return accumulated result
* @see #compile(int)
*/
protected final int compile() { protected final int compile() {
return compile(Math.max(COMPILE_THRESHOLD, 150000)); return compile(Math.max(COMPILE_THRESHOLD, 150000));
} }
/**
* Tries to trigger compilation of {@linkplain #method} by call
* {@linkplain #callable} specified times.
*
* @param count invocation count
* @return accumulated result
*/
protected final int compile(int count) { protected final int compile(int count) {
int result = 0; int result = 0;
Integer tmp;
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
result += method(); try {
tmp = callable.call();
} catch (Exception e) {
tmp = null;
}
result += tmp == null ? 0 : tmp;
} }
System.out.println("method was invoked " + count + " times"); System.out.println("method was invoked " + count + " times");
return result; return result;
} }
}
/**
* Utility structure containing tested method and object to invoke it.
*/
enum TestCase {
/** constructor test case */
CONSTRUCTOR_TEST(Helper.CONSTRUCTOR, Helper.CONSTRUCTOR_CALLABLE),
/** method test case */
METOD_TEST(Helper.METHOD, Helper.METHOD_CALLABLE),
/** static method test case */
STATIC_TEST(Helper.STATIC, Helper.STATIC_CALLABLE);
/** tested method */
final Executable executable;
/** object to invoke {@linkplain #executable} */
final Callable<Integer> callable;
private TestCase(Executable executable, Callable<Integer> callable) {
this.executable = executable;
this.callable = callable;
}
private static class Helper {
private static final Callable<Integer> CONSTRUCTOR_CALLABLE
= new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return new Helper(1337).hashCode();
}
};
private static final Callable<Integer> METHOD_CALLABLE
= new Callable<Integer>() {
private final Helper helper = new Helper();
@Override
public Integer call() throws Exception {
return helper.method();
}
};
private static final Callable<Integer> STATIC_CALLABLE
= new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return staticMethod();
}
};
private static final Constructor CONSTRUCTOR;
private static final Method METHOD;
private static final Method STATIC;
static {
try {
CONSTRUCTOR = Helper.class.getDeclaredConstructor(int.class);
} catch (NoSuchMethodException | SecurityException e) {
throw new RuntimeException(
"exception on getting method Helper.<init>(int)", e);
}
try {
METHOD = Helper.class.getDeclaredMethod("method");
} catch (NoSuchMethodException | SecurityException e) {
throw new RuntimeException(
"exception on getting method Helper.method()", e);
}
try {
STATIC = Helper.class.getDeclaredMethod("staticMethod");
} catch (NoSuchMethodException | SecurityException e) {
throw new RuntimeException(
"exception on getting method Helper.staticMethod()", e);
}
}
protected int method() { private static int staticMethod() {
return 1138;
}
private int method() {
return 42; return 42;
} }
private final int x;
public Helper() {
x = 0;
}
private Helper(int x) {
this.x = x;
}
@Override
public int hashCode() {
return x;
}
}
} }
...@@ -27,20 +27,34 @@ ...@@ -27,20 +27,34 @@
* @build DeoptimizeAllTest * @build DeoptimizeAllTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI DeoptimizeAllTest * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI DeoptimizeAllTest
* @summary testing of WB::deoptimizeAll()
* @author igor.ignatyev@oracle.com * @author igor.ignatyev@oracle.com
*/ */
public class DeoptimizeAllTest extends CompilerWhiteBoxTest { public class DeoptimizeAllTest extends CompilerWhiteBoxTest {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// to prevent inlining #method into #compile() for (TestCase test : TestCase.values()) {
WHITE_BOX.testSetDontInlineMethod(METHOD, true); new DeoptimizeAllTest(test).runTest();
new DeoptimizeAllTest().runTest(); }
}
public DeoptimizeAllTest(TestCase testCase) {
super(testCase);
// to prevent inlining of #method
WHITE_BOX.testSetDontInlineMethod(method, true);
} }
/**
* Tests {@code WB::deoptimizeAll()} by calling it after
* compilation and checking that method isn't compiled.
*
* @throws Exception if one of the checks fails.
*/
@Override
protected void test() throws Exception { protected void test() throws Exception {
compile(); compile();
checkCompiled(METHOD); checkCompiled();
WHITE_BOX.deoptimizeAll(); WHITE_BOX.deoptimizeAll();
checkNotCompiled(METHOD); checkNotCompiled();
} }
} }
...@@ -27,20 +27,34 @@ ...@@ -27,20 +27,34 @@
* @build DeoptimizeMethodTest * @build DeoptimizeMethodTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI DeoptimizeMethodTest * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI DeoptimizeMethodTest
* @summary testing of WB::deoptimizeMethod()
* @author igor.ignatyev@oracle.com * @author igor.ignatyev@oracle.com
*/ */
public class DeoptimizeMethodTest extends CompilerWhiteBoxTest { public class DeoptimizeMethodTest extends CompilerWhiteBoxTest {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// to prevent inlining #method into #compile() for (TestCase test : TestCase.values()) {
WHITE_BOX.testSetDontInlineMethod(METHOD, true); new DeoptimizeMethodTest(test).runTest();
new DeoptimizeMethodTest().runTest(); }
}
public DeoptimizeMethodTest(TestCase testCase) {
super(testCase);
// to prevent inlining of #method
WHITE_BOX.testSetDontInlineMethod(method, true);
} }
/**
* Tests {@code WB::deoptimizeMethod()} by calling it after
* compilation and checking that method isn't compiled.
*
* @throws Exception if one of the checks fails.
*/
@Override
protected void test() throws Exception { protected void test() throws Exception {
compile(); compile();
checkCompiled(METHOD); checkCompiled();
WHITE_BOX.deoptimizeMethod(METHOD); WHITE_BOX.deoptimizeMethod(method);
checkNotCompiled(METHOD); checkNotCompiled();
} }
} }
...@@ -27,48 +27,60 @@ ...@@ -27,48 +27,60 @@
* @build EnqueueMethodForCompilationTest * @build EnqueueMethodForCompilationTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI EnqueueMethodForCompilationTest * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI EnqueueMethodForCompilationTest
* @summary testing of WB::enqueueMethodForCompilation()
* @author igor.ignatyev@oracle.com * @author igor.ignatyev@oracle.com
*/ */
public class EnqueueMethodForCompilationTest extends CompilerWhiteBoxTest { public class EnqueueMethodForCompilationTest extends CompilerWhiteBoxTest {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// to prevent inlining #method into #compile() for (TestCase test : TestCase.values()) {
WHITE_BOX.testSetDontInlineMethod(METHOD, true); new EnqueueMethodForCompilationTest(test).runTest();
new EnqueueMethodForCompilationTest().runTest(); }
}
public EnqueueMethodForCompilationTest(TestCase testCase) {
super(testCase);
// to prevent inlining of #method
WHITE_BOX.testSetDontInlineMethod(method, true);
} }
@Override
protected void test() throws Exception { protected void test() throws Exception {
checkNotCompiled(METHOD); checkNotCompiled();
WHITE_BOX.enqueueMethodForCompilation(METHOD, 0); // method can not be compiled on level 'none'
if (WHITE_BOX.isMethodCompilable(METHOD, 0)) { WHITE_BOX.enqueueMethodForCompilation(method, COMP_LEVEL_NONE);
throw new RuntimeException(METHOD + " is compilable at level 0"); if (WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_NONE)) {
throw new RuntimeException(method
+ " is compilable at level COMP_LEVEL_NONE");
} }
checkNotCompiled(METHOD); checkNotCompiled();
WHITE_BOX.enqueueMethodForCompilation(METHOD, -1); // COMP_LEVEL_ANY is inapplicable as level for compilation
checkNotCompiled(METHOD); WHITE_BOX.enqueueMethodForCompilation(method, COMP_LEVEL_ANY);
checkNotCompiled();
WHITE_BOX.enqueueMethodForCompilation(METHOD, 5); WHITE_BOX.enqueueMethodForCompilation(method, 5);
if (!WHITE_BOX.isMethodCompilable(METHOD, 5)) { if (!WHITE_BOX.isMethodCompilable(method, 5)) {
checkNotCompiled(METHOD); checkNotCompiled();
compile(); compile();
checkCompiled(METHOD); checkCompiled();
} else { } else {
checkCompiled(METHOD); checkCompiled();
} }
int compLevel = WHITE_BOX.getMethodCompilationLevel(METHOD); int compLevel = WHITE_BOX.getMethodCompilationLevel(method);
WHITE_BOX.deoptimizeMethod(METHOD); WHITE_BOX.deoptimizeMethod(method);
checkNotCompiled(METHOD); checkNotCompiled();
WHITE_BOX.enqueueMethodForCompilation(METHOD, compLevel); WHITE_BOX.enqueueMethodForCompilation(method, compLevel);
checkCompiled(METHOD); checkCompiled();
WHITE_BOX.deoptimizeMethod(METHOD); WHITE_BOX.deoptimizeMethod(method);
checkNotCompiled(METHOD); checkNotCompiled();
compile(); compile();
checkCompiled(METHOD); checkCompiled();
WHITE_BOX.deoptimizeMethod(METHOD); WHITE_BOX.deoptimizeMethod(method);
checkNotCompiled(METHOD); checkNotCompiled();
} }
} }
...@@ -28,9 +28,13 @@ ...@@ -28,9 +28,13 @@
* @build IsMethodCompilableTest * @build IsMethodCompilableTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI IsMethodCompilableTest * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI IsMethodCompilableTest
* @summary testing of WB::isMethodCompilable()
* @author igor.ignatyev@oracle.com * @author igor.ignatyev@oracle.com
*/ */
public class IsMethodCompilableTest extends CompilerWhiteBoxTest { public class IsMethodCompilableTest extends CompilerWhiteBoxTest {
/**
* Value of {@code -XX:PerMethodRecompilationCutoff}
*/
protected static final long PER_METHOD_RECOMPILATION_CUTOFF; protected static final long PER_METHOD_RECOMPILATION_CUTOFF;
static { static {
...@@ -44,14 +48,28 @@ public class IsMethodCompilableTest extends CompilerWhiteBoxTest { ...@@ -44,14 +48,28 @@ public class IsMethodCompilableTest extends CompilerWhiteBoxTest {
} }
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// to prevent inlining #method into #compile() for (TestCase test : TestCase.values()) {
WHITE_BOX.testSetDontInlineMethod(METHOD, true); new IsMethodCompilableTest(test).runTest();
new IsMethodCompilableTest().runTest(); }
}
public IsMethodCompilableTest(TestCase testCase) {
super(testCase);
// to prevent inlining of #method
WHITE_BOX.testSetDontInlineMethod(method, true);
} }
/**
* Tests {@code WB::isMethodCompilable()} by recompilation of tested method
* 'PerMethodRecompilationCutoff' times and checks compilation status. Also
* checks that WB::clearMethodState() clears no-compilable flags.
*
* @throws Exception if one of the checks fails.
*/
@Override
protected void test() throws Exception { protected void test() throws Exception {
if (!WHITE_BOX.isMethodCompilable(METHOD)) { if (!WHITE_BOX.isMethodCompilable(method)) {
throw new RuntimeException(METHOD + " must be compilable"); throw new RuntimeException(method + " must be compilable");
} }
System.out.println("PerMethodRecompilationCutoff = " System.out.println("PerMethodRecompilationCutoff = "
+ PER_METHOD_RECOMPILATION_CUTOFF); + PER_METHOD_RECOMPILATION_CUTOFF);
...@@ -61,46 +79,47 @@ public class IsMethodCompilableTest extends CompilerWhiteBoxTest { ...@@ -61,46 +79,47 @@ public class IsMethodCompilableTest extends CompilerWhiteBoxTest {
return; return;
} }
// deoptimze 'PerMethodRecompilationCutoff' times and clear state // deoptimize 'PerMethodRecompilationCutoff' times and clear state
for (long i = 0L, n = PER_METHOD_RECOMPILATION_CUTOFF - 1; i < n; ++i) { for (long i = 0L, n = PER_METHOD_RECOMPILATION_CUTOFF - 1; i < n; ++i) {
compileAndDeoptimaze(); compileAndDeoptimize();
} }
if (!WHITE_BOX.isMethodCompilable(METHOD)) { if (!WHITE_BOX.isMethodCompilable(method)) {
throw new RuntimeException(METHOD + " is not compilable after " throw new RuntimeException(method + " is not compilable after "
+ (PER_METHOD_RECOMPILATION_CUTOFF - 1) + " iterations"); + (PER_METHOD_RECOMPILATION_CUTOFF - 1) + " iterations");
} }
WHITE_BOX.clearMethodState(METHOD); WHITE_BOX.clearMethodState(method);
// deoptimze 'PerMethodRecompilationCutoff' + 1 times // deoptimize 'PerMethodRecompilationCutoff' + 1 times
long i; long i;
for (i = 0L; i < PER_METHOD_RECOMPILATION_CUTOFF for (i = 0L; i < PER_METHOD_RECOMPILATION_CUTOFF
&& WHITE_BOX.isMethodCompilable(METHOD); ++i) { && WHITE_BOX.isMethodCompilable(method); ++i) {
compileAndDeoptimaze(); compileAndDeoptimize();
} }
if (i != PER_METHOD_RECOMPILATION_CUTOFF) { if (i != PER_METHOD_RECOMPILATION_CUTOFF) {
throw new RuntimeException(METHOD + " is not compilable after " throw new RuntimeException(method + " is not compilable after "
+ i + " iterations, but must only after " + i + " iterations, but must only after "
+ PER_METHOD_RECOMPILATION_CUTOFF); + PER_METHOD_RECOMPILATION_CUTOFF);
} }
if (WHITE_BOX.isMethodCompilable(METHOD)) { if (WHITE_BOX.isMethodCompilable(method)) {
throw new RuntimeException(METHOD + " is still compilable after " throw new RuntimeException(method + " is still compilable after "
+ PER_METHOD_RECOMPILATION_CUTOFF + " iterations"); + PER_METHOD_RECOMPILATION_CUTOFF + " iterations");
} }
compile(); compile();
checkNotCompiled(METHOD); checkNotCompiled();
WHITE_BOX.clearMethodState(METHOD); // WB.clearMethodState() must reset no-compilable flags
if (!WHITE_BOX.isMethodCompilable(METHOD)) { WHITE_BOX.clearMethodState(method);
throw new RuntimeException(METHOD if (!WHITE_BOX.isMethodCompilable(method)) {
+ " is compilable after clearMethodState()"); throw new RuntimeException(method
+ " is not compilable after clearMethodState()");
} }
compile(); compile();
checkCompiled(METHOD); checkCompiled();
} }
private void compileAndDeoptimaze() throws Exception { private void compileAndDeoptimize() throws Exception {
compile(); compile();
waitBackgroundCompilation(METHOD); waitBackgroundCompilation();
WHITE_BOX.deoptimizeMethod(METHOD); WHITE_BOX.deoptimizeMethod(method);
} }
} }
...@@ -27,28 +27,85 @@ ...@@ -27,28 +27,85 @@
* @build MakeMethodNotCompilableTest * @build MakeMethodNotCompilableTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI MakeMethodNotCompilableTest * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI MakeMethodNotCompilableTest
* @summary testing of WB::makeMethodNotCompilable()
* @author igor.ignatyev@oracle.com * @author igor.ignatyev@oracle.com
*/ */
public class MakeMethodNotCompilableTest extends CompilerWhiteBoxTest { public class MakeMethodNotCompilableTest extends CompilerWhiteBoxTest {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// to prevent inlining #method into #compile() if (args.length == 0) {
WHITE_BOX.testSetDontInlineMethod(METHOD, true); for (TestCase test : TestCase.values()) {
new MakeMethodNotCompilableTest().runTest(); new MakeMethodNotCompilableTest(test).runTest();
}
} else {
for (String name : args) {
new MakeMethodNotCompilableTest(
TestCase.valueOf(name)).runTest();
}
}
}
public MakeMethodNotCompilableTest(TestCase testCase) {
super(testCase);
// to prevent inlining of #method
WHITE_BOX.testSetDontInlineMethod(method, true);
} }
/**
* Tests {@code WB::makeMethodNotCompilable()} by calling it before
* compilation and checking that method isn't compiled. Also
* checks that WB::clearMethodState() clears no-compilable flags. For
* tiered, additional checks for all available levels are conducted.
*
* @throws Exception if one of the checks fails.
*/
@Override
protected void test() throws Exception { protected void test() throws Exception {
if (!WHITE_BOX.isMethodCompilable(METHOD)) { checkNotCompiled();
throw new RuntimeException(METHOD + " must be compilable"); if (!WHITE_BOX.isMethodCompilable(method)) {
throw new RuntimeException(method + " must be compilable");
}
if (TIERED_COMPILATION) {
for (int i = 1, n = TIERED_STOP_AT_LEVEL + 1; i < n; ++i) {
WHITE_BOX.makeMethodNotCompilable(method, i);
if (WHITE_BOX.isMethodCompilable(method, i)) {
throw new RuntimeException(method
+ " must be not compilable at level" + i);
}
WHITE_BOX.enqueueMethodForCompilation(method, i);
checkNotCompiled();
if (!WHITE_BOX.isMethodCompilable(method)) {
System.out.println(method
+ " is not compilable after level " + i);
}
}
// WB.clearMethodState() must reset no-compilable flags
WHITE_BOX.clearMethodState(method);
if (!WHITE_BOX.isMethodCompilable(method)) {
throw new RuntimeException(method
+ " is not compilable after clearMethodState()");
} }
WHITE_BOX.makeMethodNotCompilable(METHOD);
if (WHITE_BOX.isMethodCompilable(METHOD)) {
throw new RuntimeException(METHOD + " must be not compilable");
} }
WHITE_BOX.makeMethodNotCompilable(method);
if (WHITE_BOX.isMethodCompilable(method)) {
throw new RuntimeException(method + " must be not compilable");
}
compile(); compile();
checkNotCompiled(METHOD); checkNotCompiled();
if (WHITE_BOX.isMethodCompilable(METHOD)) { if (WHITE_BOX.isMethodCompilable(method)) {
throw new RuntimeException(METHOD + " must be not compilable"); throw new RuntimeException(method + " must be not compilable");
} }
// WB.clearMethodState() must reset no-compilable flags
WHITE_BOX.clearMethodState(method);
if (!WHITE_BOX.isMethodCompilable(method)) {
throw new RuntimeException(method
+ " is not compilable after clearMethodState()");
}
compile();
checkCompiled();
} }
} }
...@@ -27,33 +27,47 @@ ...@@ -27,33 +27,47 @@
* @build SetDontInlineMethodTest * @build SetDontInlineMethodTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SetDontInlineMethodTest * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SetDontInlineMethodTest
* @summary testing of WB::testSetDontInlineMethod()
* @author igor.ignatyev@oracle.com * @author igor.ignatyev@oracle.com
*/ */
public class SetDontInlineMethodTest extends CompilerWhiteBoxTest { public class SetDontInlineMethodTest extends CompilerWhiteBoxTest {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
new SetDontInlineMethodTest().runTest(); for (TestCase test : TestCase.values()) {
new SetDontInlineMethodTest(test).runTest();
}
}
public SetDontInlineMethodTest(TestCase testCase) {
super(testCase);
} }
/**
* Tests {@code WB::testSetDontInlineMethod()} by sequential calling it and
* checking of return value.
*
* @throws Exception if one of the checks fails.
*/
@Override
protected void test() throws Exception { protected void test() throws Exception {
if (WHITE_BOX.testSetDontInlineMethod(METHOD, true)) { if (WHITE_BOX.testSetDontInlineMethod(method, true)) {
throw new RuntimeException("on start " + METHOD throw new RuntimeException("on start " + method
+ " must be inlineable"); + " must be inlineable");
} }
if (!WHITE_BOX.testSetDontInlineMethod(METHOD, true)) { if (!WHITE_BOX.testSetDontInlineMethod(method, true)) {
throw new RuntimeException("after first change to true " + METHOD throw new RuntimeException("after first change to true " + method
+ " must be not inlineable"); + " must be not inlineable");
} }
if (!WHITE_BOX.testSetDontInlineMethod(METHOD, false)) { if (!WHITE_BOX.testSetDontInlineMethod(method, false)) {
throw new RuntimeException("after second change to true " + METHOD throw new RuntimeException("after second change to true " + method
+ " must be still not inlineable"); + " must be still not inlineable");
} }
if (WHITE_BOX.testSetDontInlineMethod(METHOD, false)) { if (WHITE_BOX.testSetDontInlineMethod(method, false)) {
throw new RuntimeException("after first change to false" + METHOD throw new RuntimeException("after first change to false" + method
+ " must be inlineable"); + " must be inlineable");
} }
if (WHITE_BOX.testSetDontInlineMethod(METHOD, false)) { if (WHITE_BOX.testSetDontInlineMethod(method, false)) {
throw new RuntimeException("after second change to false " + METHOD throw new RuntimeException("after second change to false " + method
+ " must be inlineable"); + " must be inlineable");
} }
} }
......
...@@ -27,33 +27,47 @@ ...@@ -27,33 +27,47 @@
* @build SetForceInlineMethodTest * @build SetForceInlineMethodTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SetForceInlineMethodTest * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SetForceInlineMethodTest
* @summary testing of WB::testSetForceInlineMethod()
* @author igor.ignatyev@oracle.com * @author igor.ignatyev@oracle.com
*/ */
public class SetForceInlineMethodTest extends CompilerWhiteBoxTest { public class SetForceInlineMethodTest extends CompilerWhiteBoxTest {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
new SetForceInlineMethodTest().runTest(); for (TestCase test : TestCase.values()) {
new SetForceInlineMethodTest(test).runTest();
}
}
public SetForceInlineMethodTest(TestCase testCase) {
super(testCase);
} }
/**
* Tests {@code WB::testSetForceInlineMethod()} by sequential calling it and
* checking of return value.
*
* @throws Exception if one of the checks fails.
*/
@Override
protected void test() throws Exception { protected void test() throws Exception {
if (WHITE_BOX.testSetForceInlineMethod(METHOD, true)) { if (WHITE_BOX.testSetForceInlineMethod(method, true)) {
throw new RuntimeException("on start " + METHOD throw new RuntimeException("on start " + method
+ " must be not force inlineable"); + " must be not force inlineable");
} }
if (!WHITE_BOX.testSetForceInlineMethod(METHOD, true)) { if (!WHITE_BOX.testSetForceInlineMethod(method, true)) {
throw new RuntimeException("after first change to true " + METHOD throw new RuntimeException("after first change to true " + method
+ " must be force inlineable"); + " must be force inlineable");
} }
if (!WHITE_BOX.testSetForceInlineMethod(METHOD, false)) { if (!WHITE_BOX.testSetForceInlineMethod(method, false)) {
throw new RuntimeException("after second change to true " + METHOD throw new RuntimeException("after second change to true " + method
+ " must be still force inlineable"); + " must be still force inlineable");
} }
if (WHITE_BOX.testSetForceInlineMethod(METHOD, false)) { if (WHITE_BOX.testSetForceInlineMethod(method, false)) {
throw new RuntimeException("after first change to false" + METHOD throw new RuntimeException("after first change to false" + method
+ " must be not force inlineable"); + " must be not force inlineable");
} }
if (WHITE_BOX.testSetForceInlineMethod(METHOD, false)) { if (WHITE_BOX.testSetForceInlineMethod(method, false)) {
throw new RuntimeException("after second change to false " + METHOD throw new RuntimeException("after second change to false " + method
+ " must be not force inlineable"); + " must be not force inlineable");
} }
} }
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
package sun.hotspot; package sun.hotspot;
import java.lang.reflect.Method; import java.lang.reflect.Executable;
import java.security.BasicPermission; import java.security.BasicPermission;
import sun.hotspot.parser.DiagnosticCommand; import sun.hotspot.parser.DiagnosticCommand;
...@@ -90,22 +90,25 @@ public class WhiteBox { ...@@ -90,22 +90,25 @@ public class WhiteBox {
// Compiler // Compiler
public native void deoptimizeAll(); public native void deoptimizeAll();
public native boolean isMethodCompiled(Method method); public native boolean isMethodCompiled(Executable method);
public boolean isMethodCompilable(Method method) { public boolean isMethodCompilable(Executable method) {
return isMethodCompilable(method, -1 /*any*/); return isMethodCompilable(method, -1 /*any*/);
} }
public native boolean isMethodCompilable(Method method, int compLevel); public native boolean isMethodCompilable(Executable method, int compLevel);
public native boolean isMethodQueuedForCompilation(Method method); public native boolean isMethodQueuedForCompilation(Executable method);
public native int deoptimizeMethod(Method method); public native int deoptimizeMethod(Executable method);
public native void makeMethodNotCompilable(Method method); public void makeMethodNotCompilable(Executable method) {
public native int getMethodCompilationLevel(Method method); makeMethodNotCompilable(method, -1 /*any*/);
public native boolean testSetDontInlineMethod(Method method, boolean value); }
public native void makeMethodNotCompilable(Executable method, int compLevel);
public native int getMethodCompilationLevel(Executable method);
public native boolean testSetDontInlineMethod(Executable method, boolean value);
public native int getCompileQueuesSize(); public native int getCompileQueuesSize();
public native boolean testSetForceInlineMethod(Method method, boolean value); public native boolean testSetForceInlineMethod(Executable method, boolean value);
public native boolean enqueueMethodForCompilation(Method method, int compLevel); public native boolean enqueueMethodForCompilation(Executable method, int compLevel);
public native void clearMethodState(Method method); public native void clearMethodState(Executable method);
//Intered strings // Intered strings
public native boolean isInStringTable(String str); public native boolean isInStringTable(String str);
// force Full GC // force Full GC
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册