--- old/src/share/vm/runtime/advancedThresholdPolicy.cpp 2016-03-02 14:29:24.409648609 +0100 +++ new/src/share/vm/runtime/advancedThresholdPolicy.cpp 2016-03-02 14:29:24.305648605 +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)) { --- old/src/share/vm/compiler/compileBroker.hpp 2016-03-02 14:29:24.409648609 +0100 +++ new/src/share/vm/compiler/compileBroker.hpp 2016-03-02 14:29:24.309648605 +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/prims/whitebox.cpp 2016-03-02 14:29:24.409648609 +0100 +++ new/src/share/vm/prims/whitebox.cpp 2016-03-02 14:29:24.305648605 +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(jint, 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 (jint) DirectivesParser::parse_string(tmpstr, tty);; +WB_END + +WB_ENTRY(void, WB_RemoveCompilerDirective(JNIEnv* env, jobject o, jint count)) + DirectivesStack::pop(count); +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;)I", + (void*)&WB_AddCompilerDirective }, + {CC"removeCompilerDirective", CC"(I)V", (void*)&WB_RemoveCompilerDirective }, }; #undef CC --- old/src/share/vm/compiler/compileBroker.cpp 2016-03-02 14:29:24.409648609 +0100 +++ new/src/share/vm/compiler/compileBroker.cpp 2016-03-02 14:29:24.305648605 +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/services/diagnosticCommand.cpp 2016-03-02 14:29:24.413648609 +0100 +++ new/src/share/vm/services/diagnosticCommand.cpp 2016-03-02 14:29:24.309648605 +0100 @@ -931,7 +931,7 @@ } void CompilerDirectivesRemoveDCmd::execute(DCmdSource source, TRAPS) { - DirectivesStack::pop(); + DirectivesStack::pop(1); } void CompilerDirectivesClearDCmd::execute(DCmdSource source, TRAPS) { --- old/src/share/vm/compiler/directivesParser.cpp 2016-03-02 14:29:24.461648611 +0100 +++ new/src/share/vm/compiler/directivesParser.cpp 2016-03-02 14:29:24.301648605 +0100 @@ -55,7 +55,7 @@ assert(_tmp_depth == 0, "Consistency"); } -bool DirectivesParser::parse_string(const char* text, outputStream* st) { +int DirectivesParser::parse_string(const char* text, outputStream* st) { DirectivesParser cd(text, st); if (cd.valid()) { return cd.install_directives(); @@ -63,7 +63,7 @@ cd.clean_tmp(); st->flush(); st->print_cr("Parsing of compiler directives failed"); - return false; + return 0; } } @@ -103,11 +103,11 @@ return false; } -bool DirectivesParser::install_directives() { +int DirectivesParser::install_directives() { // Check limit if (!DirectivesStack::check_capacity(_tmp_depth, _st)) { clean_tmp(); - return false; + return 0; } // Pop from internal temporary stack and push to compileBroker. @@ -120,14 +120,14 @@ } if (i == 0) { _st->print_cr("No directives in file"); - return false; + return 0; } else { _st->print_cr("%i compiler directives added", i); if (CompilerDirectivesPrint) { // Print entire directives stack after new has been pushed. DirectivesStack::print(_st); } - return true; + return i; } } --- old/src/share/vm/compiler/compilerDirectives.cpp 2016-03-02 14:29:24.461648611 +0100 +++ new/src/share/vm/compiler/compilerDirectives.cpp 2016-03-02 14:29:24.305648605 +0100 @@ -472,9 +472,12 @@ _depth++; } -void DirectivesStack::pop() { +void DirectivesStack::pop(int count) { MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag); - pop_inner(); + assert(count > -1, "No negative values"); + for (int i = 0; i < count; i++) { + pop_inner(); + } } void DirectivesStack::pop_inner() { --- old/src/share/vm/compiler/directivesParser.hpp 2016-03-02 14:29:24.461648611 +0100 +++ new/src/share/vm/compiler/directivesParser.hpp 2016-03-02 14:29:24.301648605 +0100 @@ -51,8 +51,8 @@ static bool has_file(); static bool parse_from_flag(); static bool parse_from_file(const char* filename, outputStream* st); - static bool parse_string(const char* string, outputStream* st); - bool install_directives(); + static int parse_string(const char* string, outputStream* st); + int install_directives(); private: DirectivesParser(const char* text, outputStream* st); --- old/src/share/vm/compiler/compilerDirectives.hpp 2016-03-02 14:29:24.465648612 +0100 +++ new/src/share/vm/compiler/compilerDirectives.hpp 2016-03-02 14:29:24.305648605 +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) \ @@ -87,7 +88,7 @@ static DirectiveSet* getMatchingDirective(methodHandle mh, AbstractCompiler* comp); static DirectiveSet* getDefaultDirective(AbstractCompiler* comp); static void push(CompilerDirectives* directive); - static void pop(); + static void pop(int count); static bool check_capacity(int request_size, outputStream* st); static void clear(); static void print(outputStream* st);