8199624: [Graal] Blocking jvmci compilations time out

Handle blocking jvmci compilations that time out.

Reviewed-by: kvn, dnsimon
This commit is contained in:
Tobias Hartmann 2018-03-21 08:18:54 +01:00
parent 68345b93ad
commit eda7916ce8
5 changed files with 104 additions and 100 deletions

View File

@ -1344,11 +1344,11 @@ CompileTask* CompileBroker::create_compile_task(CompileQueue* queue,
#if INCLUDE_JVMCI
// The number of milliseconds to wait before checking if
// JVMCI compilation has made progress.
static const long JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE = 500;
static const long JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE = 1000;
// The number of JVMCI compilation progress checks that must fail
// before unblocking a thread waiting for a blocking compilation.
static const int JVMCI_COMPILATION_PROGRESS_WAIT_ATTEMPTS = 5;
static const int JVMCI_COMPILATION_PROGRESS_WAIT_ATTEMPTS = 10;
/**
* Waits for a JVMCI compiler to complete a given task. This thread

View File

@ -865,14 +865,21 @@ WB_END
bool WhiteBox::compile_method(Method* method, int comp_level, int bci, Thread* THREAD) {
// Screen for unavailable/bad comp level or null method
if (method == NULL || comp_level > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier) ||
CompileBroker::compiler(comp_level) == NULL) {
AbstractCompiler* comp = CompileBroker::compiler(comp_level);
if (method == NULL || comp_level > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier) || comp == NULL) {
return false;
}
// Check if compilation is blocking
methodHandle mh(THREAD, method);
DirectiveSet* directive = DirectivesStack::getMatchingDirective(mh, comp);
bool is_blocking = !directive->BackgroundCompilationOption;
DirectivesStack::release(directive);
// Compile method and check result
nmethod* nm = CompileBroker::compile_method(mh, bci, comp_level, mh, mh->invocation_count(), CompileTask::Reason_Whitebox, THREAD);
MutexLockerEx mu(Compile_lock);
return (mh->queued_for_compilation() || nm != NULL);
return ((!is_blocking && mh->queued_for_compilation()) || nm != NULL);
}
WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci))

View File

@ -152,16 +152,18 @@ public abstract class CallsBase {
calleeVisited = false; // reset state
}
// compile with requested level if needed
if (compileCallee > 0) {
compileMethod(calleeMethod, compileCallee);
if (compileCallee > 0 && !compileMethod(calleeMethod, compileCallee)) {
System.out.println("WARNING: Blocking compilation failed for calleeMethod (timeout?). Skipping.");
return;
}
if (checkCalleeCompilationLevel) {
Asserts.assertEQ(expectedCalleeCompilationLevel,
wb.getMethodCompilationLevel(calleeMethod),
"Unexpected callee compilation level");
}
if (compileCaller > 0) {
compileMethod(callerMethod, compileCaller);
if (compileCaller > 0 && !compileMethod(callerMethod, compileCaller)) {
System.out.println("WARNING: Blocking compilation failed for callerMethod (timeout?). Skipping.");
return;
}
if (checkCallerCompilationLevel) {
Asserts.assertEQ(expectedCallerCompilationLevel,
@ -185,11 +187,12 @@ public abstract class CallsBase {
* A method to compile another method, searching it by name in current class
* @param method a method to compile
* @param compLevel a compilation level
* @return true if method was enqueued for compilation
*/
protected final void compileMethod(Method method, int compLevel) {
protected final boolean compileMethod(Method method, int compLevel) {
wb.deoptimizeMethod(method);
Asserts.assertTrue(wb.isMethodCompilable(method, compLevel));
wb.enqueueMethodForCompilation(method, compLevel);
return wb.enqueueMethodForCompilation(method, compLevel);
}
/*

View File

@ -54,7 +54,23 @@ public class AbstractMethodErrorTest {
private static boolean enableChecks = true;
public static void setup_test() {
private static boolean compile(Class<?> clazz, String name) {
try {
Method method = clazz.getMethod(name);
boolean enqueued = WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!enqueued) {
System.out.println("Warning: Blocking compilation failed for " + clazz.getName() + "." + name + " (timeout?)");
return false;
} else if (!WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException(clazz.getName() + "." + name + " is not compiled");
}
} catch (NoSuchMethodException e) {
throw new RuntimeException(clazz.getName() + "." + name + " not found", e);
}
return true;
}
public static boolean setup_test() {
// Assure all exceptions are loaded.
new AbstractMethodError();
new IncompatibleClassChangeError();
@ -67,48 +83,19 @@ public class AbstractMethodErrorTest {
enableChecks = true;
// Compile
try {
Method method = AbstractMethodErrorTest.class.getMethod("test_ame5_compiled_vtable_stub");
WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException(method.getName() + " is not compiled");
}
method = AbstractMethodErrorTest.class.getMethod("test_ame6_compiled_itable_stub");
WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException(method.getName() + " is not compiled");
}
method = AME5_C.class.getMethod("c");
WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException("AME5_C." + method.getName() + " is not compiled");
}
method = AME5_D.class.getMethod("c");
WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException("AME5_D." + method.getName() + " is not compiled");
}
method = AME5_E.class.getMethod("c");
WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException("AME5_E." + method.getName() + " is not compiled");
}
method = AME6_C.class.getMethod("c");
WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException("AME6_C." + method.getName() + " is not compiled");
}
method = AME6_D.class.getMethod("c");
WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException("AME6_D." + method.getName() + " is not compiled");
}
method = AME6_E.class.getMethod("c");
WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException("AME6_E." + method.getName() + " is not compiled");
}
} catch (NoSuchMethodException e) { }
if (!compile(AbstractMethodErrorTest.class, "test_ame5_compiled_vtable_stub") ||
!compile(AbstractMethodErrorTest.class, "test_ame6_compiled_itable_stub") ||
!compile(AME5_C.class, "mc") ||
!compile(AME5_D.class, "mc") ||
!compile(AME5_E.class, "mc") ||
!compile(AME6_C.class, "mc") ||
!compile(AME6_D.class, "mc") ||
!compile(AME6_E.class, "mc")) {
return false;
}
System.out.println("warmup done.");
return true;
}
private static String expectedErrorMessageAME1_1 =
@ -493,7 +480,9 @@ public class AbstractMethodErrorTest {
public static void main(String[] args) throws Exception {
setup_test();
if (!setup_test()) {
return;
}
test_ame1();
test_ame2();
test_ame3_1();
@ -756,66 +745,66 @@ class AME4_E extends AME4_B {
// - Call errorneous B.mc() in the end to raise the AbstraceMethodError
abstract class AME5_A {
abstract void ma();
abstract void mb();
abstract void mc();
public abstract void ma();
public abstract void mb();
public abstract void mc();
}
class AME5_B extends AME5_A {
void ma() {
public void ma() {
System.out.print("B.ma() ");
}
void mb() {
public void mb() {
System.out.print("B.mb() ");
}
// This method is missing in the .jasm implementation.
void mc() {
public void mc() {
System.out.print("B.mc() ");
}
}
class AME5_C extends AME5_A {
void ma() {
public void ma() {
System.out.print("C.ma() ");
}
void mb() {
public void mb() {
System.out.print("C.mb() ");
}
void mc() {
public void mc() {
System.out.print("C.mc() ");
}
}
class AME5_D extends AME5_A {
void ma() {
public void ma() {
System.out.print("D.ma() ");
}
void mb() {
public void mb() {
System.out.print("D.mb() ");
}
void mc() {
public void mc() {
System.out.print("D.mc() ");
}
}
class AME5_E extends AME5_A {
void ma() {
System.out.print("E.ma() ");
}
public void ma() {
System.out.print("E.ma() ");
}
void mb() {
System.out.print("E.mb() ");
}
public void mb() {
System.out.print("E.mb() ");
}
void mc() {
System.out.print("E.mc() ");
}
public void mc() {
System.out.print("E.mc() ");
}
}
//-------------------------------------------------------------------------

View File

@ -62,7 +62,24 @@ public class IncompatibleClassChangeErrorTest {
"Class ICC_B does not implement the requested interface ICC_iB";
// old message: "vtable stub"
public static void setup_test() {
private static boolean compile(Class<?> clazz, String name) {
try {
Method method = clazz.getMethod(name);
boolean enqueued = WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!enqueued) {
System.out.println("Warning: Blocking compilation failed for " + clazz.getName() + "." + name + " (timeout?)");
return false;
} else if (!WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException(clazz.getName() + "." + name + " is not compiled");
}
} catch (NoSuchMethodException e) {
throw new RuntimeException(clazz.getName() + "." + name + " not found", e);
}
return true;
}
public static boolean setup_test() {
// Assure all exceptions are loaded.
new AbstractMethodError();
new IncompatibleClassChangeError();
@ -75,29 +92,15 @@ public class IncompatibleClassChangeErrorTest {
enableChecks = true;
// Compile
try {
Method method = IncompatibleClassChangeErrorTest.class.getMethod("test_icc_compiled_itable_stub");
WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException(method.getName() + " is not compiled");
}
method = ICC_C.class.getMethod("b");
WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException("ICC_C." + method.getName() + " is not compiled");
}
method = ICC_D.class.getMethod("b");
WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException("ICC_D." + method.getName() + " is not compiled");
}
method = ICC_E.class.getMethod("b");
WHITE_BOX.enqueueMethodForCompilation(method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
if (!WHITE_BOX.isMethodCompiled(method)) {
throw new RuntimeException("ICC_E." + method.getName() + " is not compiled");
}
} catch (NoSuchMethodException e) { }
if (!compile(IncompatibleClassChangeErrorTest.class, "test_icc_compiled_itable_stub") ||
!compile(ICC_C.class, "b") ||
!compile(ICC_D.class, "b") ||
!compile(ICC_E.class, "b")) {
return false;
}
System.out.println("warmup done.");
return true;
}
// Should never be compiled.
@ -204,7 +207,9 @@ public class IncompatibleClassChangeErrorTest {
}
public static void main(String[] args) throws Exception {
setup_test();
if (!setup_test()) {
return;
}
test_iccInt();
test_icc_compiled_itable_stub();
}