--- old/src/share/vm/prims/whitebox.cpp 2015-03-26 13:31:23.723895112 +0100 +++ new/src/share/vm/prims/whitebox.cpp 2015-03-26 13:31:23.643895116 +0100 @@ -805,46 +805,9 @@ mo.notify_all(); WB_END -void WhiteBox::sweeper_thread_entry(JavaThread* thread, TRAPS) { - guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled"); - { - MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); - NMethodSweeper::_should_sweep = true; - } - NMethodSweeper::possibly_sweep(); -} - -JavaThread* WhiteBox::create_sweeper_thread(TRAPS) { - // create sweeper thread w/ custom entry -- one iteration instead of loop - CodeCacheSweeperThread* sweeper_thread = new CodeCacheSweeperThread(); - sweeper_thread->set_entry_point(&WhiteBox::sweeper_thread_entry); - - // create j.l.Thread object and associate it w/ sweeper thread - { - // inherit deamon property from current thread - bool is_daemon = java_lang_Thread::is_daemon(JavaThread::current()->threadObj()); - - HandleMark hm(THREAD); - Handle thread_group(THREAD, Universe::system_thread_group()); - const char* name = "WB Sweeper thread"; - sweeper_thread->allocate_threadObj(thread_group, name, is_daemon, THREAD); - } - - { - MutexLocker mu(Threads_lock, THREAD); - Threads::add(sweeper_thread); - } - return sweeper_thread; -} - -WB_ENTRY(jobject, WB_ForceNMethodSweep(JNIEnv* env, jobject o)) - JavaThread* sweeper_thread = WhiteBox::create_sweeper_thread(Thread::current()); - if (sweeper_thread == NULL) { - return NULL; - } - jobject result = JNIHandles::make_local(env, sweeper_thread->threadObj()); - Thread::start(sweeper_thread); - return result; +WB_ENTRY(void, WB_ForceNMethodSweep(JNIEnv* env, jobject o)) + // Force a code cache sweep and block until it finished + NMethodSweeper::force_sweep(); WB_END WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString)) @@ -1385,7 +1348,7 @@ {CC"getCPUFeatures", CC"()Ljava/lang/String;", (void*)&WB_GetCPUFeatures }, {CC"getNMethod", CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;", (void*)&WB_GetNMethod }, - {CC"forceNMethodSweep0", CC"()Ljava/lang/Thread;", (void*)&WB_ForceNMethodSweep }, + {CC"forceNMethodSweep", CC"()V", (void*)&WB_ForceNMethodSweep }, {CC"allocateCodeBlob", CC"(II)J", (void*)&WB_AllocateCodeBlob }, {CC"freeCodeBlob", CC"(J)V", (void*)&WB_FreeCodeBlob }, {CC"getCodeHeapEntries", CC"(I)[Ljava/lang/Object;",(void*)&WB_GetCodeHeapEntries }, --- old/src/share/vm/prims/whitebox.hpp 2015-03-26 13:31:24.027895098 +0100 +++ new/src/share/vm/prims/whitebox.hpp 2015-03-26 13:31:23.943895102 +0100 @@ -70,8 +70,6 @@ Symbol* signature_symbol); static const char* lookup_jstring(const char* field_name, oop object); static bool lookup_bool(const char* field_name, oop object); - static void sweeper_thread_entry(JavaThread* thread, TRAPS); - static JavaThread* create_sweeper_thread(TRAPS); static int get_blob_type(const CodeBlob* code); static CodeHeap* get_code_heap(int blob_type); static CodeBlob* allocate_code_blob(int size, int blob_type); --- old/src/share/vm/runtime/sweeper.cpp 2015-03-26 13:31:24.295895086 +0100 +++ new/src/share/vm/runtime/sweeper.cpp 2015-03-26 13:31:24.211895090 +0100 @@ -144,6 +144,7 @@ int NMethodSweeper::_seen = 0; // Nof. nmethod we have currently processed in current pass of CodeCache volatile bool NMethodSweeper::_should_sweep = true; // Indicates if we should invoke the sweeper +volatile bool NMethodSweeper::_force_sweep = false;// Indicates if we should force a sweep volatile int NMethodSweeper::_bytes_changed = 0; // Counts the total nmethod size if the nmethod changed from: // 1) alive -> not_entrant // 2) not_entrant -> zombie @@ -276,6 +277,23 @@ } /** + * Wakes up the sweeper thread and forces a sweep. Blocks until it finished. + */ +void NMethodSweeper::force_sweep() { + ThreadBlockInVM tbivm(JavaThread::current()); + MutexLockerEx waiter(CodeCache_lock, Mutex::_no_safepoint_check_flag); + // Request forced sweep + _force_sweep = true; + while (_force_sweep) { + // Notify sweeper that we want to force a sweep and wait for completion. + // In case a sweep currently takes place we timeout and try again because + // we want to enforce a full sweep. + CodeCache_lock->notify(); + CodeCache_lock->wait(Mutex::_no_safepoint_check_flag, 1000); + } +} + +/** * Handle a safepoint request */ void NMethodSweeper::handle_safepoint_request() { @@ -335,6 +353,9 @@ } } + // Remember if this was a forced sweep + bool forced = _force_sweep; + // Force stack scanning if there is only 10% free space in the code cache. // We force stack scanning only non-profiled code heap gets full, since critical // allocation go to the non-profiled heap and we must be make sure that there is @@ -344,7 +365,7 @@ do_stack_scanning(); } - if (_should_sweep) { + if (_should_sweep || forced) { init_sweeper_log(); sweep_code_cache(); } @@ -356,12 +377,20 @@ _should_sweep = false; // If there was enough state change, 'possibly_enable_sweeper()' // sets '_should_sweep' to true - possibly_enable_sweeper(); + possibly_enable_sweeper(); // Reset _bytes_changed only if there was enough state change. _bytes_changed // can further increase by calls to 'report_state_change'. if (_should_sweep) { _bytes_changed = 0; } + + if (forced) { + // Notify requester that forced sweep finished + assert(_force_sweep, "Should be a forced sweep"); + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + _force_sweep = false; + CodeCache_lock->notify(); + } } void NMethodSweeper::sweep_code_cache() { --- old/src/share/vm/runtime/sweeper.hpp 2015-03-26 13:31:24.583895072 +0100 +++ new/src/share/vm/runtime/sweeper.hpp 2015-03-26 13:31:24.503895076 +0100 @@ -54,7 +54,6 @@ // nmethod's space is freed. class NMethodSweeper : public AllStatic { - friend class WhiteBox; private: enum MethodStateChange { None, @@ -71,6 +70,7 @@ static volatile int _sweep_started; // Flag to control conc sweeper static volatile bool _should_sweep; // Indicates if we should invoke the sweeper + static volatile bool _force_sweep; // Indicates if we should force a sweep static volatile int _bytes_changed; // Counts the total nmethod size if the nmethod changed from: // 1) alive -> not_entrant // 2) not_entrant -> zombie @@ -117,6 +117,7 @@ static void mark_active_nmethods(); // Invoked at the end of each safepoint static void sweeper_loop(); static void notify(int code_blob_type); // Possibly start the sweeper thread. + static void force_sweep(); static int hotness_counter_reset_val(); static void report_state_change(nmethod* nm);