--- old/src/share/vm/prims/whitebox.hpp 2014-11-26 20:49:54.616203410 +0300 +++ new/src/share/vm/prims/whitebox.hpp 2014-11-26 20:49:54.424203412 +0300 @@ -27,6 +27,7 @@ #include "prims/jni.h" +#include "utilities/exceptions.hpp" #include "memory/allocation.hpp" #include "oops/oopsHierarchy.hpp" #include "oops/symbol.hpp" @@ -56,6 +57,7 @@ class CodeBlob; class CodeHeap; +class JavaThread; class WhiteBox : public AllStatic { private: @@ -68,7 +70,8 @@ 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 force_sweep(); + 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 blob_type, int size); --- old/src/share/vm/runtime/thread.cpp 2014-11-26 20:49:54.696203409 +0300 +++ new/src/share/vm/runtime/thread.cpp 2014-11-26 20:49:54.424203412 +0300 @@ -1115,7 +1115,7 @@ } -void JavaThread::allocate_threadObj(Handle thread_group, char* thread_name, +void JavaThread::allocate_threadObj(Handle thread_group, const char* thread_name, bool daemon, TRAPS) { assert(thread_group.not_null(), "thread group should be specified"); assert(threadObj() == NULL, "should only create Java thread object once"); @@ -1162,8 +1162,8 @@ return; } - KlassHandle group(this, SystemDictionary::ThreadGroup_klass()); - Handle threadObj(this, this->threadObj()); + KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass()); + Handle threadObj(THREAD, this->threadObj()); JavaCalls::call_special(&result, thread_group, @@ -1172,8 +1172,6 @@ vmSymbols::thread_void_signature(), threadObj, // Arg 1 THREAD); - - } // NamedThread -- non-JavaThread subclasses with multiple --- old/src/share/vm/runtime/sweeper.cpp 2014-11-26 20:49:54.748203408 +0300 +++ new/src/share/vm/runtime/sweeper.cpp 2014-11-26 20:49:54.448203412 +0300 @@ -142,9 +142,6 @@ long NMethodSweeper::_time_counter = 0; // Virtual time used to periodically invoke sweeper long NMethodSweeper::_last_sweep = 0; // Value of _time_counter when the last sweep happened int NMethodSweeper::_seen = 0; // Nof. nmethod we have currently processed in current pass of CodeCache -int NMethodSweeper::_flushed_count = 0; // Nof. nmethods flushed in current sweep -int NMethodSweeper::_zombified_count = 0; // Nof. nmethods made zombie in current sweep -int NMethodSweeper::_marked_for_reclamation_count = 0; // Nof. nmethods marked for reclaim in current sweep volatile bool NMethodSweeper::_should_sweep = true; // Indicates if we should invoke the sweeper volatile int NMethodSweeper::_bytes_changed = 0; // Counts the total nmethod size if the nmethod changed from: @@ -161,6 +158,7 @@ Tickspan NMethodSweeper::_peak_sweep_time; // Peak time for a full sweep Tickspan NMethodSweeper::_peak_sweep_fraction_time; // Peak time sweeping one fraction +Monitor* NMethodSweeper::_stat_lock = new Monitor(Mutex::special, "Sweeper::Statistics", true); class MarkActivationClosure: public CodeBlobClosure { public: @@ -370,9 +368,10 @@ ResourceMark rm; Ticks sweep_start_counter = Ticks::now(); - _flushed_count = 0; - _zombified_count = 0; - _marked_for_reclamation_count = 0; + int flushed_count = 0; + int zombified_count = 0; + int marked_for_reclamation_count = 0; + int flushed_c2_count = 0; if (PrintMethodFlushing && Verbose) { tty->print_cr("### Sweep at %d out of %d", _seen, CodeCache::nof_nmethods()); @@ -386,10 +385,8 @@ { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); - // The last invocation iterates until there are no more nmethods while (!_current.end()) { swept_count++; - handle_safepoint_request(); // Since we will give up the CodeCache_lock, always skip ahead // to the next nmethod. Other blobs can be deleted by other // threads but nmethods are only reclaimed by the sweeper. @@ -399,9 +396,32 @@ // Now ready to process nmethod and give up CodeCache_lock { MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); - freed_memory += process_nmethod(nm); + int size = nm->total_size(); + bool is_c2_method = nm->is_compiled_by_c2(); + + MethodStateChange type = process_nmethod(nm); + switch (type) { + case Flushed: + freed_memory += size; + ++flushed_count; + if (is_c2_method) { + ++flushed_c2_count; + } + break; + case MarkedForReclamation: + ++marked_for_reclamation_count; + break; + case MadeZombie: + ++zombified_count; + break; + case None: + break; + default: + ShouldNotReachHere(); + } } _seen++; + handle_safepoint_request(); } } @@ -409,21 +429,25 @@ const Ticks sweep_end_counter = Ticks::now(); const Tickspan sweep_time = sweep_end_counter - sweep_start_counter; - _total_time_sweeping += sweep_time; - _total_time_this_sweep += sweep_time; - _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time); - _total_flushed_size += freed_memory; - _total_nof_methods_reclaimed += _flushed_count; - + { + MutexLockerEx mu(_stat_lock, Mutex::_no_safepoint_check_flag); + _total_time_sweeping += sweep_time; + _total_time_this_sweep += sweep_time; + _peak_sweep_fraction_time = MAX2(sweep_time, _peak_sweep_fraction_time); + _total_flushed_size += freed_memory; + _total_nof_methods_reclaimed += flushed_count; + _total_nof_c2_methods_reclaimed += flushed_c2_count; + _peak_sweep_time = MAX2(_peak_sweep_time, _total_time_this_sweep); + } EventSweepCodeCache event(UNTIMED); if (event.should_commit()) { event.set_starttime(sweep_start_counter); event.set_endtime(sweep_end_counter); event.set_sweepIndex(_traversals); event.set_sweptCount(swept_count); - event.set_flushedCount(_flushed_count); - event.set_markedCount(_marked_for_reclamation_count); - event.set_zombifiedCount(_zombified_count); + event.set_flushedCount(flushed_count); + event.set_markedCount(marked_for_reclamation_count); + event.set_zombifiedCount(zombified_count); event.commit(); } @@ -433,7 +457,6 @@ } #endif - _peak_sweep_time = MAX2(_peak_sweep_time, _total_time_this_sweep); log_sweep("finished"); // Sweeper is the only case where memory is released, check here if it @@ -511,10 +534,11 @@ nm->flush(); } -int NMethodSweeper::process_nmethod(nmethod* nm) { +NMethodSweeper::MethodStateChange NMethodSweeper::process_nmethod(nmethod* nm) { + assert(nm != NULL, "sanity"); assert(!CodeCache_lock->owned_by_self(), "just checking"); - int freed_memory = 0; + MethodStateChange result = None; // Make sure this nmethod doesn't get unloaded during the scan, // since safepoints may happen during acquired below locks. NMethodMarker nmm(nm); @@ -529,7 +553,7 @@ nm->cleanup_inline_caches(); SWEEP(nm); } - return freed_memory; + return result; } if (nm->is_zombie()) { @@ -541,12 +565,9 @@ if (PrintMethodFlushing && Verbose) { tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm); } - freed_memory = nm->total_size(); - if (nm->is_compiled_by_c2()) { - _total_nof_c2_methods_reclaimed++; - } release_nmethod(nm); - _flushed_count++; + assert(result == None, "sanity"); + result = Flushed; } else { if (PrintMethodFlushing && Verbose) { tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm); @@ -554,8 +575,9 @@ nm->mark_for_reclamation(); // Keep track of code cache state change _bytes_changed += nm->total_size(); - _marked_for_reclamation_count++; SWEEP(nm); + assert(result == None, "sanity"); + result = MarkedForReclamation; } } else if (nm->is_not_entrant()) { // If there are no current activations of this method on the @@ -576,8 +598,9 @@ } // Code cache state change is tracked in make_zombie() nm->make_zombie(); - _zombified_count++; SWEEP(nm); + assert(result == None, "sanity"); + result = MadeZombie; } assert(nm->is_zombie(), "nmethod must be zombie"); } else { @@ -594,17 +617,15 @@ if (nm->is_osr_method()) { SWEEP(nm); // No inline caches will ever point to osr methods, so we can just remove it - freed_memory = nm->total_size(); - if (nm->is_compiled_by_c2()) { - _total_nof_c2_methods_reclaimed++; - } release_nmethod(nm); - _flushed_count++; + assert(result == None, "sanity"); + result = Flushed; } else { // Code cache state change is tracked in make_zombie() nm->make_zombie(); - _zombified_count++; SWEEP(nm); + assert(result == None, "sanity"); + result = MadeZombie; } } else { possibly_flush(nm); @@ -613,7 +634,7 @@ nm->cleanup_inline_caches(); SWEEP(nm); } - return freed_memory; + return result; } --- old/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java 2014-11-26 20:49:54.716203408 +0300 +++ new/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java 2014-11-26 20:49:54.464203412 +0300 @@ -149,7 +149,14 @@ public native Object[] getNMethod(Executable method, boolean isOsr); public native long allocateCodeBlob(int size, int type); public native void freeCodeBlob(long addr); - public native void forceNMethodSweep(); + public void forceNMethodSweep() { + try { + forceNMethodSweep0().join(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + public native Thread forceNMethodSweep0(); public native Object[] getCodeHeapEntries(int type); public native int getCompilationActivityMode(); public native Object[] getCodeBlob(long addr); --- old/src/share/vm/prims/whitebox.cpp 2014-11-26 20:49:54.704203409 +0300 +++ new/src/share/vm/prims/whitebox.cpp 2014-11-26 20:49:54.416203412 +0300 @@ -44,6 +44,7 @@ #include "runtime/os.hpp" #include "runtime/vm_version.hpp" #include "runtime/sweeper.hpp" +#include "runtime/javaCalls.hpp" #include "utilities/array.hpp" #include "utilities/debug.hpp" @@ -742,8 +743,8 @@ mo.notify_all(); WB_END -void WhiteBox::force_sweep() { - guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to enabled"); +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; @@ -751,8 +752,37 @@ NMethodSweeper::possibly_sweep(); } -WB_ENTRY(void, WB_ForceNMethodSweep(JNIEnv* env, jobject o)) - WhiteBox::force_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_END WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString)) @@ -802,12 +832,12 @@ WB_END int WhiteBox::get_blob_type(const CodeBlob* code) { - guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to enabled"); + guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled"); return CodeCache::get_code_heap(code)->code_blob_type(); } CodeHeap* WhiteBox::get_code_heap(int blob_type) { - guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to enabled"); + guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled"); return CodeCache::get_code_heap(blob_type); } @@ -883,7 +913,7 @@ WB_END CodeBlob* WhiteBox::allocate_code_blob(int size, int blob_type) { - guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to enabled"); + guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled"); BufferBlob* blob; int full_size = CodeBlob::align_code_offset(sizeof(BufferBlob)); if (full_size < size) { @@ -892,10 +922,10 @@ { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); blob = (BufferBlob*) CodeCache::allocate(full_size, blob_type); + ::new (blob) BufferBlob("WB::DummyBlob", full_size); } // Track memory usage statistic after releasing CodeCache_lock MemoryService::track_code_cache_memory_usage(); - ::new (blob) BufferBlob("WB::DummyBlob", full_size); return blob; } @@ -1200,7 +1230,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"forceNMethodSweep", CC"()V", (void*)&WB_ForceNMethodSweep }, + {CC"forceNMethodSweep0", CC"()Ljava/lang/Thread;", (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 }, --- /dev/null 2014-11-18 17:23:07.628909932 +0300 +++ new/test/testlibrary/com/oracle/java/testlibrary/InfiniteLoop.java 2014-11-26 20:49:54.496203411 +0300 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary; + +import java.util.Objects; + +/** + * Class which runs another Runnable in infinite loop with certain pauses + * between cycles. + */ +public class InfiniteLoop implements Runnable { + private final Runnable target; + private final long mills; + + + /** + * @param target a target to run in a loop + * @param mills the length of pause time in milliseconds + * @throws NullPointerException if target is null + * @throws IllegalArgumentException if the value of millis is negative + */ + public InfiniteLoop(Runnable target, long mills) { + Objects.requireNonNull(target); + if (mills < 0) { + throw new IllegalArgumentException("mills < 0"); + } + this.target = target; + this.mills = mills; + } + + @Override + public void run() { + try { + while (true) { + target.run(); + Thread.sleep(mills); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new Error(e); + } + } +} --- old/test/compiler/whitebox/AllocationCodeBlobTest.java 2014-11-26 20:49:54.820203407 +0300 +++ new/test/compiler/whitebox/AllocationCodeBlobTest.java 2014-11-26 20:49:54.556203411 +0300 @@ -29,10 +29,11 @@ import sun.hotspot.WhiteBox; import sun.hotspot.code.BlobType; import com.oracle.java.testlibrary.Asserts; +import com.oracle.java.testlibrary.InfiniteLoop; /* * @test AllocationCodeBlobTest - * @bug 8059624 + * @bug 8059624 8064669 * @library /testlibrary /testlibrary/whitebox * @build AllocationCodeBlobTest * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -53,11 +54,32 @@ public static void main(String[] args) { // check that Sweeper handels dummy blobs correctly - new ForcedSweeper(500).start(); + Thread t = new Thread( + new InfiniteLoop(WHITE_BOX::forceNMethodSweep, 1L), + "ForcedSweeper"); + t.setDaemon(true); + System.out.println("Starting " + t.getName()); + t.start(); + EnumSet blobTypes = BlobType.getAvailable(); for (BlobType type : blobTypes) { new AllocationCodeBlobTest(type).test(); } + + // check that deoptimization works well w/ dummy blobs + t = new Thread( + new InfiniteLoop(WHITE_BOX::deoptimizeAll, 1L), + "Deoptimize Thread"); + t.setDaemon(true); + System.out.println("Starting " + t.getName()); + t.start(); + + for (int i = 0; i < 10_000; ++i) { + for (BlobType type : blobTypes) { + long addr = WHITE_BOX.allocateCodeBlob(SIZE, type.id); + } + } + } private final BlobType type; @@ -105,24 +127,4 @@ private long getUsage() { return bean.getUsage().getUsed(); } - - private static class ForcedSweeper extends Thread { - private final int millis; - public ForcedSweeper(int millis) { - super("ForcedSweeper"); - setDaemon(true); - this.millis = millis; - } - public void run() { - try { - while (true) { - WHITE_BOX.forceNMethodSweep(); - Thread.sleep(millis); - } - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new Error(e); - } - } - } } --- old/src/share/vm/runtime/thread.hpp 2014-11-26 20:49:54.836203407 +0300 +++ new/src/share/vm/runtime/thread.hpp 2014-11-26 20:49:54.552203411 +0300 @@ -752,6 +752,7 @@ class JavaThread: public Thread { friend class VMStructs; + friend class WhiteBox; private: JavaThread* _next; // The next thread in the Threads list oop _threadObj; // The Java level thread object @@ -1003,7 +1004,7 @@ ThreadFunction entry_point() const { return _entry_point; } // Allocates a new Java level thread object for this thread. thread_name may be NULL. - void allocate_threadObj(Handle thread_group, char* thread_name, bool daemon, TRAPS); + void allocate_threadObj(Handle thread_group, const char* thread_name, bool daemon, TRAPS); // Last frame anchor routines --- /dev/null 2014-11-18 17:23:07.628909932 +0300 +++ new/test/compiler/whitebox/ForceNMethodSweepTest.java 2014-11-26 20:49:54.548203411 +0300 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +import java.lang.reflect.Method; +import java.util.EnumSet; + +import sun.hotspot.WhiteBox; +import sun.hotspot.code.BlobType; + +import com.oracle.java.testlibrary.Asserts; +import com.oracle.java.testlibrary.InfiniteLoop; + +/* + * @test + * @bug 8059624 8064669 + * @library /testlibrary /testlibrary/whitebox + * @build ForceNMethodSweepTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:-TieredCompilation -XX:+WhiteBoxAPI + * -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* + * ForceNMethodSweepTest + * @summary testing of WB::forceNMethodSweep + */ +public class ForceNMethodSweepTest extends CompilerWhiteBoxTest { + public static void main(String[] args) throws Exception { + CompilerWhiteBoxTest.main(ForceNMethodSweepTest::new, args); + } + private final EnumSet blobTypes; + private ForceNMethodSweepTest(TestCase testCase) { + super(testCase); + // to prevent inlining of #method + WHITE_BOX.testSetDontInlineMethod(method, true); + blobTypes = BlobType.getAvailable(); + } + + @Override + protected void test() throws Exception { + checkNotCompiled(); + guaranteedSweep(); + int usage = getTotalUsage(); + + compile(); + checkCompiled(); + int afterCompilation = getTotalUsage(); + Asserts.assertGT(afterCompilation, usage, + "compilation should increase usage"); + + guaranteedSweep(); + int afterSweep = getTotalUsage(); + Asserts.assertLTE(afterSweep, afterCompilation, + "sweep shouldn't increase usage"); + + deoptimize(); + guaranteedSweep(); + int afterDeoptAndSweep = getTotalUsage(); + Asserts.assertLT(afterDeoptAndSweep, afterSweep, + "sweep after deoptimization should decrease usage"); + } + + private int getTotalUsage() { + int usage = 0; + for (BlobType type : blobTypes) { + usage += type.getMemoryPool().getUsage().getUsed(); + } + return usage; + } + private void guaranteedSweep() { + // not entrant -> ++stack_traversal_mark -> zombie -> reclamation -> flushed + for (int i = 0; i < 5; ++i) { + WHITE_BOX.fullGC(); + WHITE_BOX.forceNMethodSweep(); + } + } +} --- old/src/share/vm/runtime/sweeper.hpp 2014-11-26 20:49:54.868203406 +0300 +++ new/src/share/vm/runtime/sweeper.hpp 2014-11-26 20:49:54.620203410 +0300 @@ -56,15 +56,18 @@ class NMethodSweeper : public AllStatic { friend class WhiteBox; private: + enum MethodStateChange { + None, + MadeZombie, + MarkedForReclamation, + Flushed + }; static long _traversals; // Stack scan count, also sweep ID. static long _total_nof_code_cache_sweeps; // Total number of full sweeps of the code cache static long _time_counter; // Virtual time used to periodically invoke sweeper static long _last_sweep; // Value of _time_counter when the last sweep happened static NMethodIterator _current; // Current nmethod static int _seen; // Nof. nmethod we have currently processed in current pass of CodeCache - static int _flushed_count; // Nof. nmethods flushed in current sweep - static int _zombified_count; // Nof. nmethods made zombie in current sweep - static int _marked_for_reclamation_count; // Nof. nmethods marked for reclaim in current sweep static volatile int _sweep_started; // Flag to control conc sweeper static volatile bool _should_sweep; // Indicates if we should invoke the sweeper @@ -83,8 +86,10 @@ static Tickspan _peak_sweep_time; // Peak time for a full sweep static Tickspan _peak_sweep_fraction_time; // Peak time sweeping one fraction - static int process_nmethod(nmethod *nm); - static void release_nmethod(nmethod* nm); + static Monitor* _stat_lock; + + static MethodStateChange process_nmethod(nmethod *nm); + static void release_nmethod(nmethod* nm); static void init_sweeper_log() NOT_DEBUG_RETURN; static bool wait_for_stack_scanning();