--- old/src/share/vm/prims/whitebox.cpp 2016-03-02 13:19:44.893474136 +0100 +++ new/src/share/vm/prims/whitebox.cpp 2016-03-02 13:19:44.785474131 +0100 @@ -30,6 +30,7 @@ #include "classfile/stringTable.hpp" #include "code/codeCache.hpp" #include "compiler/methodMatcher.hpp" +#include "compiler/directivesParser.hpp" #include "jvmtifiles/jvmtiEnv.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceShared.hpp" @@ -1502,6 +1503,22 @@ } } +WB_ENTRY(jboolean, WB_AddCompilerDirective(JNIEnv* env, jobject o, jstring compDirect)) + char* tmpstr = NULL; + { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + const char* dirstr = env->GetStringUTFChars(compDirect, NULL); + tmpstr = strdup(dirstr); + env->ReleaseStringUTFChars(compDirect, dirstr); + } + return (jboolean) DirectivesParser::parse_string(tmpstr, tty);; +WB_END + +WB_ENTRY(void, WB_RemoveCompilerDirective(JNIEnv* env, jobject o)) + DirectivesStack::pop(); +WB_END + #define CC (char*) static JNINativeMethod methods[] = { @@ -1677,6 +1694,9 @@ {CC"isShared", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared }, {CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored }, {CC"clearInlineCaches", CC"()V", (void*)&WB_ClearInlineCaches }, + {CC"addCompilerDirective", CC"(Ljava/lang/String;)Z", + (void*)&WB_AddCompilerDirective }, + {CC"removeCompilerDirective", CC"()V", (void*)&WB_RemoveCompilerDirective }, }; #undef CC --- old/src/share/vm/compiler/compileBroker.hpp 2016-03-02 13:19:44.897474136 +0100 +++ new/src/share/vm/compiler/compileBroker.hpp 2016-03-02 13:19:44.785474131 +0100 @@ -222,7 +222,7 @@ static JavaThread* make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, bool compiler_thread, TRAPS); static void init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count); static bool compilation_is_complete (const methodHandle& method, int osr_bci, int comp_level); - static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level); + static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level, bool excluded); static bool is_compile_blocking(); static void preload_classes (const methodHandle& method, TRAPS); @@ -253,6 +253,7 @@ const methodHandle& hot_method, int hot_count, const char* comment, + bool blocking, Thread* thread); static CompileQueue* compile_queue(int comp_level); @@ -291,6 +292,15 @@ int hot_count, const char* comment, Thread* thread); + static nmethod* compile_method(const methodHandle& method, + int osr_bci, + int comp_level, + const methodHandle& hot_method, + int hot_count, + const char* comment, + DirectiveSet* directive, + Thread* thread); + // Acquire any needed locks and assign a compile id static uint assign_compile_id_unlocked(Thread* thread, const methodHandle& method, int osr_bci); --- old/src/share/vm/compiler/compilerDirectives.hpp 2016-03-02 13:19:44.897474136 +0100 +++ new/src/share/vm/compiler/compilerDirectives.hpp 2016-03-02 13:19:44.793474132 +0100 @@ -42,6 +42,7 @@ cflags(PrintAssembly, bool, PrintAssembly, PrintAssembly) \ cflags(PrintInlining, bool, PrintInlining, PrintInlining) \ cflags(PrintNMethods, bool, PrintNMethods, PrintNMethods) \ + cflags(BackgroundCompilation, bool, BackgroundCompilation, X) \ cflags(ReplayInline, bool, false, ReplayInline) \ cflags(DumpReplay, bool, false, DumpReplay) \ cflags(DumpInline, bool, false, DumpInline) \ --- old/src/share/vm/compiler/compileBroker.cpp 2016-03-02 13:19:44.901474136 +0100 +++ new/src/share/vm/compiler/compileBroker.cpp 2016-03-02 13:19:44.797474132 +0100 @@ -838,6 +838,7 @@ const methodHandle& hot_method, int hot_count, const char* comment, + bool blocking, Thread* thread) { // do nothing if compiler thread(s) is not available if (!_initialized) { @@ -916,7 +917,6 @@ // Outputs from the following MutexLocker block: CompileTask* task = NULL; - bool blocking = false; CompileQueue* queue = compile_queue(comp_level); // Acquire our lock. @@ -946,9 +946,6 @@ return; } - // Should this thread wait for completion of the compile? - blocking = is_compile_blocking(); - #if INCLUDE_JVMCI if (UseJVMCICompiler) { if (blocking) { @@ -1034,11 +1031,23 @@ } } - nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci, int comp_level, const methodHandle& hot_method, int hot_count, const char* comment, Thread* THREAD) { + AbstractCompiler *comp = CompileBroker::compiler(comp_level); + DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp); + nmethod* nm = CompileBroker::compile_method(method, osr_bci, comp_level, hot_method, hot_count, comment, directive, THREAD); + DirectivesStack::release(directive); + return nm; +} + +nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci, + int comp_level, + const methodHandle& hot_method, int hot_count, + const char* comment, DirectiveSet* directive, + Thread* THREAD) { + // make sure arguments make sense assert(method->method_holder()->is_instance_klass(), "not an instance method"); assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range"); @@ -1052,7 +1061,7 @@ // isn't prohibited in a straightforward way. AbstractCompiler *comp = CompileBroker::compiler(comp_level); if (comp == NULL || !comp->can_compile_method(method) || - compilation_is_prohibited(method, osr_bci, comp_level)) { + compilation_is_prohibited(method, osr_bci, comp_level, directive->ExcludeOption)) { return NULL; } @@ -1160,7 +1169,7 @@ CompilationPolicy::policy()->delay_compilation(method()); return NULL; } - compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, THREAD); + compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, !directive->BackgroundCompilationOption, THREAD); } // return requested nmethod @@ -1217,7 +1226,7 @@ // CompileBroker::compilation_is_prohibited // // See if this compilation is not allowed. -bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level) { +bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level, bool excluded) { bool is_native = method->is_native(); // Some compilers may not support the compilation of natives. AbstractCompiler *comp = compiler(comp_level); @@ -1235,11 +1244,6 @@ return true; } - // Breaking the abstraction - directives are only used inside a compilation otherwise. - DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp); - bool excluded = directive->ExcludeOption; - DirectivesStack::release(directive); - // The method may be explicitly excluded by the user. double scale; if (excluded || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) { --- old/src/share/vm/runtime/advancedThresholdPolicy.cpp 2016-03-02 13:19:44.901474136 +0100 +++ new/src/share/vm/runtime/advancedThresholdPolicy.cpp 2016-03-02 13:19:44.797474132 +0100 @@ -164,9 +164,7 @@ // Called with the queue locked and with at least one element CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) { -#if INCLUDE_JVMCI CompileTask *max_blocking_task = NULL; -#endif CompileTask *max_task = NULL; Method* max_method = NULL; jlong t = os::javaTimeMillis(); @@ -180,7 +178,8 @@ max_method = method; } else { // If a method has been stale for some time, remove it from the queue. - if (is_stale(t, TieredCompileTaskTimeout, method) && !is_old(method)) { + // Blocking tasks don't become stale + if (!task->is_blocking() && is_stale(t, TieredCompileTaskTimeout, method) && !is_old(method)) { if (PrintTieredEvents) { print_event(REMOVE_FROM_QUEUE, method, method, task->osr_bci(), (CompLevel)task->comp_level()); } @@ -197,29 +196,25 @@ max_method = method; } } -#if INCLUDE_JVMCI - if (UseJVMCICompiler && task->is_blocking()) { + + if (task->is_blocking()) { if (max_blocking_task == NULL || compare_methods(method, max_blocking_task->method())) { max_blocking_task = task; } } -#endif + task = next_task; } -#if INCLUDE_JVMCI - if (UseJVMCICompiler) { - if (max_blocking_task != NULL) { - // In blocking compilation mode, the CompileBroker will make - // compilations submitted by a JVMCI compiler thread non-blocking. These - // compilations should be scheduled after all blocking compilations - // to service non-compiler related compilations sooner and reduce the - // chance of such compilations timing out. - max_task = max_blocking_task; - max_method = max_task->method(); - } + if (max_blocking_task != NULL) { + // In blocking compilation mode, the CompileBroker will make + // compilations submitted by a JVMCI compiler thread non-blocking. These + // compilations should be scheduled after all blocking compilations + // to service non-compiler related compilations sooner and reduce the + // chance of such compilations timing out. + max_task = max_blocking_task; + max_method = max_task->method(); } -#endif if (max_task->comp_level() == CompLevel_full_profile && TieredStopAtLevel > CompLevel_full_profile && is_method_profiled(max_method)) {