--- old/src/share/vm/prims/whitebox.cpp 2016-04-14 14:23:41.433762423 +0200 +++ new/src/share/vm/prims/whitebox.cpp 2016-04-14 14:23:41.293762417 +0200 @@ -646,7 +646,7 @@ return false; } methodHandle mh(THREAD, method); - nmethod* nm = CompileBroker::compile_method(mh, bci, comp_level, mh, mh->invocation_count(), "WhiteBox", THREAD); + 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); } --- old/src/share/vm/compiler/compileBroker.cpp 2016-04-14 14:23:41.473762424 +0200 +++ new/src/share/vm/compiler/compileBroker.cpp 2016-04-14 14:23:41.289762417 +0200 @@ -169,6 +169,8 @@ CompileQueue* CompileBroker::_c2_compile_queue = NULL; CompileQueue* CompileBroker::_c1_compile_queue = NULL; + + class CompilationLog : public StringEventLog { public: CompilationLog() : StringEventLog("Compilation events") { @@ -844,7 +846,7 @@ int comp_level, const methodHandle& hot_method, int hot_count, - const char* comment, + CompileTask::CompileReason compile_reason, bool blocking, Thread* thread) { guarantee(!method->is_abstract(), "cannot compile abstract methods"); @@ -860,7 +862,7 @@ if (osr_bci != InvocationEntryBci) { tty->print(" osr_bci: %d", osr_bci); } - tty->print(" level: %d comment: %s count: %d", comp_level, comment, hot_count); + tty->print(" level: %d comment: %s count: %d", comp_level, CompileTask::reason_name(compile_reason), hot_count); if (!hot_method.is_null()) { tty->print(" hot: "); if (hot_method() != method()) { @@ -1024,7 +1026,7 @@ task = create_compile_task(queue, compile_id, method, osr_bci, comp_level, - hot_method, hot_count, comment, + hot_method, hot_count, compile_reason, blocking); } @@ -1036,7 +1038,8 @@ 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) { + CompileTask::CompileReason compile_reason, + Thread* THREAD) { // do nothing if compilebroker is not available if (!_initialized) { return NULL; @@ -1044,7 +1047,7 @@ AbstractCompiler *comp = CompileBroker::compiler(comp_level); assert(comp != NULL, "Ensure we don't compile before compilebroker init"); DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp); - nmethod* nm = CompileBroker::compile_method(method, osr_bci, comp_level, hot_method, hot_count, comment, directive, THREAD); + nmethod* nm = CompileBroker::compile_method(method, osr_bci, comp_level, hot_method, hot_count, compile_reason, directive, THREAD); DirectivesStack::release(directive); return nm; } @@ -1052,7 +1055,8 @@ 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, + CompileTask::CompileReason compile_reason, + DirectiveSet* directive, Thread* THREAD) { // make sure arguments make sense @@ -1178,7 +1182,7 @@ return NULL; } bool is_blocking = !directive->BackgroundCompilationOption || CompileTheWorld || ReplayCompiles; - compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, is_blocking, THREAD); + compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, compile_reason, is_blocking, THREAD); } // return requested nmethod @@ -1337,11 +1341,11 @@ int comp_level, const methodHandle& hot_method, int hot_count, - const char* comment, + CompileTask::CompileReason compile_reason, bool blocking) { CompileTask* new_task = CompileTask::allocate(); new_task->initialize(compile_id, method, osr_bci, comp_level, - hot_method, hot_count, comment, + hot_method, hot_count, compile_reason, blocking); queue->add(new_task); return new_task; --- old/src/share/vm/ci/ciReplay.cpp 2016-04-14 14:23:41.481762425 +0200 +++ new/src/share/vm/ci/ciReplay.cpp 2016-04-14 14:23:41.293762417 +0200 @@ -552,7 +552,7 @@ } replay_state = this; CompileBroker::compile_method(method, entry_bci, comp_level, - methodHandle(), 0, "replay", THREAD); + methodHandle(), 0, CompileTask::Reason_Replay, THREAD); replay_state = NULL; reset(); } --- old/src/share/vm/compiler/compileTask.hpp 2016-04-14 14:23:41.489762425 +0200 +++ new/src/share/vm/compiler/compileTask.hpp 2016-04-14 14:23:41.309762417 +0200 @@ -40,6 +40,39 @@ friend class VMStructs; friend class JVMCIVMStructs; + public: + // Different reasons for a compilation + // The order is important - Reason_Whitebox and higher can not become + // stale, see CompileTask::can_become_stale() + // Also mapped to reason_names[] + enum CompileReason { + Reason_None, + Reason_InvocationCount, // Simple/StackWalk-policy + Reason_BackedgeCount, // Simple/StackWalk-policy + Reason_Tiered, // Tiered-policy + Reason_CTW, // Compile the world + Reason_Replay, // ciReplay + Reason_Whitebox, // Whitebox API + Reason_MustBeCompiled, // Java callHelper, LinkResolver + Reason_Bootstrap, // JVMCI bootstrap + Reason_Count + }; + + static const char* reason_name(CompileTask::CompileReason compile_reason) { + static const char* reason_names[] = { + "no_reason", + "count", + "backedge_count", + "tiered", + "CTW", + "replay", + "whitebox", + "must_be_compiled", + "bootstrap" + }; + return reason_names[compile_reason]; + } + private: static CompileTask* _task_free_list; #ifdef ASSERT @@ -69,7 +102,7 @@ Method* _hot_method; // which method actually triggered this task jobject _hot_method_holder; int _hot_count; // information about its invocation counter - const char* _comment; // more info about the task + CompileReason _compile_reason; // more info about the task const char* _failure_reason; public: @@ -78,8 +111,8 @@ } void initialize(int compile_id, const methodHandle& method, int osr_bci, int comp_level, - const methodHandle& hot_method, int hot_count, const char* comment, - bool is_blocking); + const methodHandle& hot_method, int hot_count, + CompileTask::CompileReason compile_reason, bool is_blocking); static CompileTask* allocate(); static void free(CompileTask* task); @@ -91,6 +124,9 @@ bool is_complete() const { return _is_complete; } bool is_blocking() const { return _is_blocking; } bool is_success() const { return _is_success; } + bool can_become_stale() const { + return !_is_blocking && (_compile_reason < Reason_Whitebox); + } #if INCLUDE_JVMCI bool has_waiter() const { return _has_waiter; } void clear_waiter() { _has_waiter = false; } --- old/src/share/vm/interpreter/linkResolver.cpp 2016-04-14 14:23:41.525762427 +0200 +++ new/src/share/vm/interpreter/linkResolver.cpp 2016-04-14 14:23:41.333762418 +0200 @@ -149,7 +149,7 @@ } CompileBroker::compile_method(selected_method, InvocationEntryBci, CompilationPolicy::policy()->initial_compile_level(), - methodHandle(), 0, "must_be_compiled", CHECK); + methodHandle(), 0, CompileTask::Reason_MustBeCompiled, CHECK); } } --- old/src/share/vm/runtime/advancedThresholdPolicy.cpp 2016-04-14 14:23:41.529762427 +0200 +++ new/src/share/vm/runtime/advancedThresholdPolicy.cpp 2016-04-14 14:23:41.369762420 +0200 @@ -191,8 +191,8 @@ max_method = method; } else { // If a method has been stale for some time, remove it from the queue. - // Blocking tasks don't become stale - if (!task->is_blocking() && is_stale(t, TieredCompileTaskTimeout, method) && !is_old(method)) { + // Blocking tasks and tasks submitted from whitebox API don't become stale + if (task->can_become_stale() && is_stale(t, TieredCompileTaskTimeout, method) && !is_old(method)) { if (PrintTieredEvents) { print_event(REMOVE_FROM_QUEUE, method, method, task->osr_bci(), (CompLevel)task->comp_level()); } @@ -491,7 +491,7 @@ void AdvancedThresholdPolicy::submit_compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread) { int hot_count = (bci == InvocationEntryBci) ? mh->invocation_count() : mh->backedge_count(); update_rate(os::javaTimeMillis(), mh()); - CompileBroker::compile_method(mh, bci, level, mh, hot_count, "tiered", thread); + CompileBroker::compile_method(mh, bci, level, mh, hot_count, CompileTask::Reason_Tiered, thread); } // Handle the invocation event. --- old/src/share/vm/jvmci/jvmciCompiler.cpp 2016-04-14 14:23:41.541762427 +0200 +++ new/src/share/vm/jvmci/jvmciCompiler.cpp 2016-04-14 14:23:41.361762420 +0200 @@ -85,7 +85,7 @@ if (!mh->is_native() && !mh->is_static() && !mh->is_initializer()) { ResourceMark rm; int hot_count = 10; // TODO: what's the appropriate value? - CompileBroker::compile_method(mh, InvocationEntryBci, CompLevel_full_optimization, mh, hot_count, "bootstrap", THREAD); + CompileBroker::compile_method(mh, InvocationEntryBci, CompLevel_full_optimization, mh, hot_count, CompileTask::Reason_Bootstrap, THREAD); } } --- old/src/share/vm/runtime/compilationPolicy.cpp 2016-04-14 14:23:41.549762428 +0200 +++ new/src/share/vm/runtime/compilationPolicy.cpp 2016-04-14 14:23:41.365762420 +0200 @@ -481,12 +481,11 @@ const int comp_level = CompLevel_highest_tier; const int hot_count = m->invocation_count(); reset_counter_for_invocation_event(m); - const char* comment = "count"; if (is_compilation_enabled() && can_be_compiled(m, comp_level)) { nmethod* nm = m->code(); if (nm == NULL ) { - CompileBroker::compile_method(m, InvocationEntryBci, comp_level, m, hot_count, comment, thread); + CompileBroker::compile_method(m, InvocationEntryBci, comp_level, m, hot_count, CompileTask::Reason_InvocationCount, thread); } } } @@ -494,10 +493,9 @@ void SimpleCompPolicy::method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread) { const int comp_level = CompLevel_highest_tier; const int hot_count = m->backedge_count(); - const char* comment = "backedge_count"; if (is_compilation_enabled() && can_be_osr_compiled(m, comp_level)) { - CompileBroker::compile_method(m, bci, comp_level, m, hot_count, comment, thread); + CompileBroker::compile_method(m, bci, comp_level, m, hot_count, CompileTask::Reason_BackedgeCount, thread); NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, comp_level, true));) } } @@ -512,7 +510,6 @@ const int comp_level = CompLevel_highest_tier; const int hot_count = m->invocation_count(); reset_counter_for_invocation_event(m); - const char* comment = "count"; if (is_compilation_enabled() && m->code() == NULL && can_be_compiled(m, comp_level)) { ResourceMark rm(thread); @@ -542,7 +539,7 @@ assert(top != NULL, "findTopInlinableFrame returned null"); if (TraceCompilationPolicy) top->print(); CompileBroker::compile_method(top->top_method(), InvocationEntryBci, comp_level, - m, hot_count, comment, thread); + m, hot_count, CompileTask::Reason_InvocationCount, thread); } } } @@ -550,10 +547,9 @@ void StackWalkCompPolicy::method_back_branch_event(const methodHandle& m, int bci, JavaThread* thread) { const int comp_level = CompLevel_highest_tier; const int hot_count = m->backedge_count(); - const char* comment = "backedge_count"; if (is_compilation_enabled() && can_be_osr_compiled(m, comp_level)) { - CompileBroker::compile_method(m, bci, comp_level, m, hot_count, comment, thread); + CompileBroker::compile_method(m, bci, comp_level, m, hot_count, CompileTask::Reason_BackedgeCount, thread); NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, comp_level, true));) } } --- old/src/share/vm/compiler/compileBroker.hpp 2016-04-14 14:23:41.549762428 +0200 +++ new/src/share/vm/compiler/compileBroker.hpp 2016-04-14 14:23:41.369762420 +0200 @@ -232,7 +232,7 @@ int comp_level, const methodHandle& hot_method, int hot_count, - const char* comment, + CompileTask::CompileReason compile_reason, bool blocking); static void wait_for_completion(CompileTask* task); #if INCLUDE_JVMCI @@ -251,7 +251,7 @@ int comp_level, const methodHandle& hot_method, int hot_count, - const char* comment, + CompileTask::CompileReason compile_reason, bool blocking, Thread* thread); @@ -289,14 +289,15 @@ int comp_level, const methodHandle& hot_method, int hot_count, - const char* comment, Thread* thread); + CompileTask::CompileReason compile_reason, + 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, + CompileTask::CompileReason compile_reason, DirectiveSet* directive, Thread* thread); --- old/src/share/vm/runtime/javaCalls.cpp 2016-04-14 14:23:41.561762428 +0200 +++ new/src/share/vm/runtime/javaCalls.cpp 2016-04-14 14:23:41.377762420 +0200 @@ -348,7 +348,7 @@ if (CompilationPolicy::must_be_compiled(method)) { CompileBroker::compile_method(method, InvocationEntryBci, CompilationPolicy::policy()->initial_compile_level(), - methodHandle(), 0, "must_be_compiled", CHECK); + methodHandle(), 0, CompileTask::Reason_MustBeCompiled, CHECK); } // Since the call stub sets up like the interpreter we call the from_interpreted_entry --- old/src/share/vm/compiler/compileTask.cpp 2016-04-14 14:23:41.565762428 +0200 +++ new/src/share/vm/compiler/compileTask.cpp 2016-04-14 14:23:41.381762420 +0200 @@ -82,7 +82,7 @@ int comp_level, const methodHandle& hot_method, int hot_count, - const char* comment, + CompileTask::CompileReason compile_reason, bool is_blocking) { assert(!_lock->is_locked(), "bad locking"); @@ -104,7 +104,7 @@ _hot_method_holder = NULL; _hot_count = hot_count; _time_queued = 0; // tidy - _comment = comment; + _compile_reason = compile_reason; _failure_reason = NULL; if (LogCompilation) { @@ -305,9 +305,9 @@ xtty->begin_elem("task_queued"); log_task(xtty); - if (_comment != NULL) { - xtty->print(" comment='%s'", _comment); - } + assert(_compile_reason > CompileTask::Reason_None && _compile_reason < CompileTask::Reason_Count, "Valid values"); + xtty->print(" comment='%s'", reason_name(_compile_reason)); + if (_hot_method != NULL) { methodHandle hot(thread, _hot_method); methodHandle method(thread, _method); @@ -436,3 +436,5 @@ } st->cr(); } + + --- old/src/share/vm/classfile/classLoader.cpp 2016-04-14 14:23:41.569762428 +0200 +++ new/src/share/vm/classfile/classLoader.cpp 2016-04-14 14:23:41.377762420 +0200 @@ -1634,7 +1634,7 @@ } // Force compilation CompileBroker::compile_method(m, InvocationEntryBci, comp_level, - methodHandle(), 0, "CTW", THREAD); + methodHandle(), 0, CompileTask::Reason_CTW, THREAD); if (HAS_PENDING_EXCEPTION) { clear_pending_exception_if_not_oom(CHECK); tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_class_counter, m->name_and_sig_as_C_string()); @@ -1650,7 +1650,7 @@ m->clear_code(); } CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_full_optimization, - methodHandle(), 0, "CTW", THREAD); + methodHandle(), 0, CompileTask::Reason_CTW, THREAD); if (HAS_PENDING_EXCEPTION) { clear_pending_exception_if_not_oom(CHECK); tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_class_counter, m->name_and_sig_as_C_string()); --- old/src/share/vm/runtime/simpleThresholdPolicy.cpp 2016-04-14 14:23:41.885762442 +0200 +++ new/src/share/vm/runtime/simpleThresholdPolicy.cpp 2016-04-14 14:23:41.765762437 +0200 @@ -265,7 +265,7 @@ // Tell the broker to compile the method void SimpleThresholdPolicy::submit_compile(const methodHandle& mh, int bci, CompLevel level, JavaThread* thread) { int hot_count = (bci == InvocationEntryBci) ? mh->invocation_count() : mh->backedge_count(); - CompileBroker::compile_method(mh, bci, level, mh, hot_count, "tiered", thread); + CompileBroker::compile_method(mh, bci, level, mh, hot_count, CompileTask::Reason_Tiered, thread); } // Call and loop predicates determine whether a transition to a higher --- old/test/compiler/whitebox/BlockingCompilation.java 2016-04-14 14:23:43.289762500 +0200 +++ new/test/compiler/whitebox/BlockingCompilation.java 2016-04-14 14:23:43.169762495 +0200 @@ -28,9 +28,8 @@ * @library /testlibrary /test/lib / * @build sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils - * @run main ClassFileInstaller sun.hotspot.WhiteBox - * sun.hotspot.WhiteBox$WhiteBoxPermission - * + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm/timeout=60 * -Xbootclasspath/a:. * -Xmixed @@ -40,11 +39,10 @@ * BlockingCompilation */ +import compiler.testlibrary.CompilerUtils; import java.lang.reflect.Method; import java.util.Random; - import sun.hotspot.WhiteBox; -import compiler.testlibrary.CompilerUtils; public class BlockingCompilation { private static final WhiteBox WB = WhiteBox.getWhiteBox(); @@ -77,7 +75,13 @@ // If the compiles are blocking, this call will block until the test time out, // Progress == success // (Don't run with -Xcomp since that can cause long timeouts due to many compiles) - WB.enqueueMethodForCompilation(m, highest_level); + if (!WB.enqueueMethodForCompilation(m, highest_level)) { + throw new Exception("Failed to enqueue method on level: " + highest_level); + } + + if (!WB.isMethodQueuedForCompilation(m)) { + throw new Exception("Must be enqueued because of locked compilation"); + } // restore state WB.unlockCompilation();