Mercurial > hg > release > icedtea7-forest-2.4 > hotspot
changeset 4577:d90c913b8103 hs24-b41
Merge
author | amurillo |
---|---|
date | Thu, 18 Apr 2013 13:42:00 -0700 |
parents | 00144225e0dd (current diff) 0e9dba751d8b (diff) |
children | c11b058d4170 |
files | |
diffstat | 34 files changed, 492 insertions(+), 140 deletions(-) [+] |
line wrap: on
line diff
--- a/agent/src/os/bsd/MacosxDebuggerLocal.m Wed Apr 17 12:13:28 2013 -0700 +++ b/agent/src/os/bsd/MacosxDebuggerLocal.m Thu Apr 18 13:42:00 2013 -0700 @@ -90,7 +90,8 @@ * Method: init0 * Signature: ()V */ -JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) { +JNIEXPORT void JNICALL +Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) { symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J"); taskID = (*env)->GetFieldID(env, cls, "task", "J"); CHECK_EXCEPTION; @@ -101,7 +102,11 @@ * Method: lookupByName0 * Signature: (Ljava/lang/String;Ljava/lang/String;)J */ -JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) { +JNIEXPORT jlong JNICALL +Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0( + JNIEnv *env, jobject this_obj, + jstring objectName, jstring symbolName) +{ jlong address = 0; JNF_COCOA_ENTER(env); @@ -130,7 +135,11 @@ * Method: readBytesFromProcess0 * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult; */ -JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) { +JNIEXPORT jbyteArray JNICALL +Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0( + JNIEnv *env, jobject this_obj, + jlong addr, jlong numBytes) +{ if (debug) printf("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes); // must allocate storage instead of using former parameter buf @@ -202,12 +211,74 @@ return array; } + /* - * Class: sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal + * Lookup the thread_t that corresponds to the given thread_id. + * The thread_id should be the result from calling thread_info() with THREAD_IDENTIFIER_INFO + * and reading the m_ident_info.thread_id returned. + * The returned thread_t is the mach send right to the kernel port for the corresponding thread. + * + * We cannot simply use the OSThread._thread_id field in the JVM. This is set to ::mach_thread_self() + * in the VM, but that thread port is not valid for a remote debugger to access the thread. + */ +thread_t +lookupThreadFromThreadId(task_t task, jlong thread_id) { + if (debug) { + printf("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id); + } + + thread_array_t thread_list = NULL; + mach_msg_type_number_t thread_list_count = 0; + thread_t result_thread = 0; + int i; + + // get the list of all the send rights + kern_return_t result = task_threads(task, &thread_list, &thread_list_count); + if (result != KERN_SUCCESS) { + if (debug) { + printf("task_threads returned 0x%x\n", result); + } + return 0; + } + + for(i = 0 ; i < thread_list_count; i++) { + thread_identifier_info_data_t m_ident_info; + mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; + + // get the THREAD_IDENTIFIER_INFO for the send right + result = thread_info(thread_list[i], THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count); + if (result != KERN_SUCCESS) { + if (debug) { + printf("thread_info returned 0x%x\n", result); + } + break; + } + + // if this is the one we're looking for, return the send right + if (thread_id == m_ident_info.thread_id) + { + result_thread = thread_list[i]; + break; + } + } + + vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (thread_t)); + vm_deallocate(mach_task_self(), (vm_address_t) thread_list, thread_list_count); + + return result_thread; +} + + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal * Method: getThreadIntegerRegisterSet0 - * Signature: (I)[J + * Signature: (J)[J */ -JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(JNIEnv *env, jobject this_obj, jint lwp_id) { +JNIEXPORT jlongArray JNICALL +Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0( + JNIEnv *env, jobject this_obj, + jlong thread_id) +{ if (debug) printf("getThreadRegisterSet0 called\n"); @@ -219,8 +290,9 @@ int i; jlongArray registerArray; jlong *primitiveArray; + task_t gTask = getTask(env, this_obj); - tid = lwp_id; + tid = lookupThreadFromThreadId(gTask, thread_id); result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count); @@ -321,19 +393,21 @@ } /* - * Class: sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal * Method: translateTID0 * Signature: (I)I */ JNIEXPORT jint JNICALL -Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(JNIEnv *env, jobject this_obj, jint tid) { +Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0( + JNIEnv *env, jobject this_obj, jint tid) +{ if (debug) printf("translateTID0 called on tid = 0x%x\n", (int)tid); kern_return_t result; thread_t foreign_tid, usable_tid; mach_msg_type_name_t type; - + foreign_tid = tid; task_t gTask = getTask(env, this_obj); @@ -421,7 +495,10 @@ * Method: attach0 * Signature: (I)V */ -JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(JNIEnv *env, jobject this_obj, jint jpid) { +JNIEXPORT void JNICALL +Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I( + JNIEnv *env, jobject this_obj, jint jpid) +{ JNF_COCOA_ENTER(env); if (getenv("JAVA_SAPROC_DEBUG") != NULL) debug = JNI_TRUE; @@ -469,7 +546,10 @@ * Method: detach0 * Signature: ()V */ -JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(JNIEnv *env, jobject this_obj) { +JNIEXPORT void JNICALL +Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0( + JNIEnv *env, jobject this_obj) +{ JNF_COCOA_ENTER(env); if (debug) printf("detach0 called\n");
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java Wed Apr 17 12:13:28 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java Thu Apr 18 13:42:00 2013 -0700 @@ -48,7 +48,7 @@ public BsdAddress readCompOopAddress(long address) throws DebuggerException; public BsdOopHandle readOopHandle(long address) throws DebuggerException; public BsdOopHandle readCompOopHandle(long address) throws DebuggerException; - public long[] getThreadIntegerRegisterSet(int lwp_id) throws DebuggerException; + public long[] getThreadIntegerRegisterSet(long unique_thread_id) throws DebuggerException; public long getAddressValue(Address addr) throws DebuggerException; public Address newAddress(long value) throws DebuggerException;
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java Wed Apr 17 12:13:28 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java Thu Apr 18 13:42:00 2013 -0700 @@ -90,7 +90,7 @@ throws DebuggerException; private native ClosestSymbol lookupByAddress0(long address) throws DebuggerException; - private native long[] getThreadIntegerRegisterSet0(int lwp_id) + private native long[] getThreadIntegerRegisterSet0(long unique_thread_id) throws DebuggerException; private native byte[] readBytesFromProcess0(long address, long numBytes) throws DebuggerException; @@ -400,10 +400,15 @@ // /** From the ThreadAccess interface via Debugger and JVMDebugger */ + public ThreadProxy getThreadForIdentifierAddress(Address threadIdAddr, Address uniqueThreadIdAddr) { + return new BsdThread(this, threadIdAddr, uniqueThreadIdAddr); + } + @Override public ThreadProxy getThreadForIdentifierAddress(Address addr) { - return new BsdThread(this, addr); + throw new RuntimeException("unimplemented"); } + /** From the ThreadAccess interface via Debugger and JVMDebugger */ public ThreadProxy getThreadForThreadId(long id) { return new BsdThread(this, id); @@ -449,22 +454,22 @@ // Thread context access // - public synchronized long[] getThreadIntegerRegisterSet(int lwp_id) + public synchronized long[] getThreadIntegerRegisterSet(long unique_thread_id) throws DebuggerException { requireAttach(); if (isCore) { - return getThreadIntegerRegisterSet0(lwp_id); + return getThreadIntegerRegisterSet0(unique_thread_id); } else { class GetThreadIntegerRegisterSetTask implements WorkerThreadTask { - int lwp_id; + long unique_thread_id; long[] result; public void doit(BsdDebuggerLocal debugger) { - result = debugger.getThreadIntegerRegisterSet0(lwp_id); + result = debugger.getThreadIntegerRegisterSet0(unique_thread_id); } } GetThreadIntegerRegisterSetTask task = new GetThreadIntegerRegisterSetTask(); - task.lwp_id = lwp_id; + task.unique_thread_id = unique_thread_id; workerThread.execute(task); return task.result; }
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java Wed Apr 17 12:13:28 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java Thu Apr 18 13:42:00 2013 -0700 @@ -28,21 +28,23 @@ class BsdThread implements ThreadProxy { private BsdDebugger debugger; - private int lwp_id; + private int thread_id; + private long unique_thread_id; /** The address argument must be the address of the _thread_id in the OSThread. It's value is result ::gettid() call. */ - BsdThread(BsdDebugger debugger, Address addr) { + BsdThread(BsdDebugger debugger, Address threadIdAddr, Address uniqueThreadIdAddr) { this.debugger = debugger; // FIXME: size of data fetched here should be configurable. // However, making it so would produce a dependency on the "types" // package from the debugger package, which is not desired. - this.lwp_id = (int) addr.getCIntegerAt(0, 4, true); + this.thread_id = (int) threadIdAddr.getCIntegerAt(0, 4, true); + this.unique_thread_id = uniqueThreadIdAddr.getCIntegerAt(0, 8, true); } BsdThread(BsdDebugger debugger, long id) { this.debugger = debugger; - this.lwp_id = (int) id; + this.thread_id = (int) id; } public boolean equals(Object obj) { @@ -50,19 +52,19 @@ return false; } - return (((BsdThread) obj).lwp_id == lwp_id); + return (((BsdThread) obj).thread_id == thread_id); } public int hashCode() { - return lwp_id; + return thread_id; } public String toString() { - return Integer.toString(lwp_id); + return Integer.toString(thread_id); } public ThreadContext getContext() throws IllegalThreadStateException { - long[] data = debugger.getThreadIntegerRegisterSet(lwp_id); + long[] data = debugger.getThreadIntegerRegisterSet(unique_thread_id); ThreadContext context = BsdThreadContextFactory.createThreadContext(debugger); for (int i = 0; i < data.length; i++) { context.setRegister(i, data[i]);
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java Wed Apr 17 12:13:28 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java Thu Apr 18 13:42:00 2013 -0700 @@ -28,6 +28,8 @@ import java.util.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.amd64.*; +import sun.jvm.hotspot.debugger.bsd.BsdDebugger; +import sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.runtime.amd64.*; import sun.jvm.hotspot.runtime.x86.*; @@ -38,8 +40,9 @@ private static AddressField lastJavaFPField; private static AddressField osThreadField; - // Field from OSThread + // Fields from OSThread private static CIntegerField osThreadThreadIDField; + private static CIntegerField osThreadUniqueThreadIDField; // This is currently unneeded but is being kept in case we change // the currentFrameGuess algorithm @@ -61,7 +64,8 @@ lastJavaFPField = anchorType.getAddressField("_last_Java_fp"); Type osThreadType = db.lookupType("OSThread"); - osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id"); + osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id"); + osThreadUniqueThreadIDField = osThreadType.getCIntegerField("_unique_thread_id"); } public Address getLastJavaFP(Address addr) { @@ -125,8 +129,9 @@ Address osThreadAddr = osThreadField.getValue(addr); // Get the address of the _thread_id from the OSThread Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset()); + Address uniqueThreadIdAddr = osThreadAddr.addOffsetTo(osThreadUniqueThreadIDField.getOffset()); - JVMDebugger debugger = VM.getVM().getDebugger(); - return debugger.getThreadForIdentifierAddress(threadIdAddr); + BsdDebuggerLocal debugger = (BsdDebuggerLocal) VM.getVM().getDebugger(); + return debugger.getThreadForIdentifierAddress(threadIdAddr, uniqueThreadIdAddr); } }
--- a/make/hotspot_version Wed Apr 17 12:13:28 2013 -0700 +++ b/make/hotspot_version Thu Apr 18 13:42:00 2013 -0700 @@ -35,7 +35,7 @@ HS_MAJOR_VER=24 HS_MINOR_VER=0 -HS_BUILD_NUMBER=40 +HS_BUILD_NUMBER=41 JDK_MAJOR_VER=1 JDK_MINOR_VER=7
--- a/make/solaris/makefiles/vm.make Wed Apr 17 12:13:28 2013 -0700 +++ b/make/solaris/makefiles/vm.make Thu Apr 18 13:42:00 2013 -0700 @@ -135,9 +135,7 @@ LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle endif # sparcWorks -ifeq ("${Platform_arch}", "sparc") LIBS += -lkstat -endif # By default, link the *.o into the library, not the executable. LINK_INTO$(LINK_INTO) = LIBJVM
--- a/src/os/bsd/vm/osThread_bsd.hpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/os/bsd/vm/osThread_bsd.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -55,6 +55,11 @@ // (e.g. pthread_kill). pthread_t _pthread_id; + // This is the "thread_id" from struct thread_identifier_info. According to a + // comment in thread_info.h, this is a "system-wide unique 64-bit thread id". + // The value is used by SA to correlate threads. + uint64_t _unique_thread_id; + sigset_t _caller_sigmask; // Caller's signal mask public: @@ -83,6 +88,10 @@ _pthread_id = tid; } + void set_unique_thread_id(uint64_t id) { + _unique_thread_id = id; + } + // *************************************************************** // suspension support. // ***************************************************************
--- a/src/os/bsd/vm/os_bsd.cpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/os/bsd/vm/os_bsd.cpp Thu Apr 18 13:42:00 2013 -0700 @@ -970,6 +970,18 @@ objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFunction = NULL; #endif +#ifdef __APPLE__ +static uint64_t locate_unique_thread_id() { + // Additional thread_id used to correlate threads in SA + thread_identifier_info_data_t m_ident_info; + mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; + + thread_info(::mach_thread_self(), THREAD_IDENTIFIER_INFO, + (thread_info_t) &m_ident_info, &count); + return m_ident_info.thread_id; +} +#endif + // Thread start routine for all newly created threads static void *java_start(Thread *thread) { // Try to randomize the cache line index of hot stack frames. @@ -999,6 +1011,7 @@ #ifdef __APPLE__ // thread_id is mach thread on macos osthread->set_thread_id(::mach_thread_self()); + osthread->set_unique_thread_id(locate_unique_thread_id()); #else // thread_id is pthread_id on BSD osthread->set_thread_id(::pthread_self()); @@ -1195,6 +1208,7 @@ #ifdef _ALLBSD_SOURCE #ifdef __APPLE__ osthread->set_thread_id(::mach_thread_self()); + osthread->set_unique_thread_id(locate_unique_thread_id()); #else osthread->set_thread_id(::pthread_self()); #endif
--- a/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -35,7 +35,7 @@ /* Threads (NOTE: incomplete) */ \ /******************************/ \ nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ - nonstatic_field(OSThread, _pthread_id, pthread_t) \ + nonstatic_field(OSThread, _unique_thread_id, uint64_t) \ /* This must be the last entry, and must be present */ \ last_entry() @@ -43,11 +43,10 @@ #define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type, last_entry) \ \ /**********************/ \ - /* Posix Thread IDs */ \ + /* Thread IDs */ \ /**********************/ \ \ declare_unsigned_integer_type(OSThread::thread_id_t) \ - declare_unsigned_integer_type(pthread_t) \ \ /* This must be the last entry, and must be present */ \ last_entry()
--- a/src/share/vm/classfile/systemDictionary.cpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/classfile/systemDictionary.cpp Thu Apr 18 13:42:00 2013 -0700 @@ -54,7 +54,11 @@ #include "runtime/signature.hpp" #include "services/classLoadingService.hpp" #include "services/threadService.hpp" -#include "trace/traceMacros.hpp" + +#if INCLUDE_TRACE + #include "memory/iterator.hpp" + #include "trace/tracing.hpp" +#endif Dictionary* SystemDictionary::_dictionary = NULL; @@ -581,6 +585,8 @@ assert(name != NULL && !FieldType::is_array(name) && !FieldType::is_obj(name), "invalid class name"); + TracingTime class_load_start_time = Tracing::time(); + // UseNewReflection // Fix for 4474172; see evaluation for more details class_loader = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(class_loader())); @@ -820,6 +826,7 @@ } return NULL; } + post_class_load_event(class_load_start_time, k, class_loader); } } @@ -939,6 +946,8 @@ TRAPS) { TempNewSymbol parsed_name = NULL; + TracingTime class_load_start_time = Tracing::time(); + // Parse the stream. Note that we do this even though this klass might // already be present in the SystemDictionary, otherwise we would not // throw potential ClassFormatErrors. @@ -996,6 +1005,8 @@ assert(THREAD->is_Java_thread(), "thread->is_Java_thread()"); JvmtiExport::post_class_load((JavaThread *) THREAD, k()); } + + post_class_load_event(class_load_start_time, k, class_loader); } return k(); @@ -1012,7 +1023,6 @@ ClassFileStream* st, bool verify, TRAPS) { - // Classloaders that support parallelism, e.g. bootstrap classloader, // or all classloaders with UnsyncloadClass do not acquire lock here bool DoObjectLock = true; @@ -1655,6 +1665,7 @@ return newsize; } bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) { + post_class_unload_events(is_alive); bool result = dictionary()->do_unloading(is_alive); constraints()->purge_loader_constraints(is_alive); resolution_errors()->purge_resolution_errors(is_alive); @@ -2601,6 +2612,73 @@ "Loaded klasses should be in SystemDictionary"); } +// utility function for posting class load event +void SystemDictionary::post_class_load_event(TracingTime start_time, + instanceKlassHandle k, + Handle initiating_loader) { +#if INCLUDE_TRACE + EventClassLoad event(UNTIMED); + if (event.should_commit()) { + event.set_endtime(Tracing::time()); + event.set_starttime(start_time); + event.set_loadedClass(k()); + oop defining_class_loader = k->class_loader(); + event.set_definingClassLoader(defining_class_loader != NULL ? + defining_class_loader->klass() : (klassOop)NULL); + oop class_loader = initiating_loader.is_null() ? (oop)NULL : initiating_loader(); + event.set_initiatingClassLoader(class_loader != NULL ? + class_loader->klass() : (klassOop)NULL); + event.commit(); + } +#endif /* INCLUDE_TRACE */ +} + +void SystemDictionary::post_class_unload_events(BoolObjectClosure* is_alive) { +#if INCLUDE_TRACE + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); + if (Tracing::enabled()) { + _should_write_unload_events = Tracing::is_event_enabled(TraceClassUnloadEvent); + _class_unload_time = Tracing::time(); + _is_alive = is_alive; + classes_do(&class_unload_event); + + if (_no_of_classes_unloading > 0) { + Tracing::on_unloading_classes(is_alive, _no_of_classes_unloading); + _no_of_classes_unloading = 0; + } + _should_write_unload_events = false; + _is_alive = NULL; + } +#endif /* INCLUDE_TRACE */ +} + +#if INCLUDE_TRACE + +TracingTime SystemDictionary::_class_unload_time; +BoolObjectClosure* SystemDictionary::_is_alive = NULL; +int SystemDictionary::_no_of_classes_unloading = 0; +bool SystemDictionary::_should_write_unload_events = false; + +void SystemDictionary::class_unload_event(klassOop curklass) { + + Klass* myklass = curklass->klass_part(); + oop class_loader = myklass->class_loader(); + + if (class_loader != NULL && _is_alive != NULL && !_is_alive->do_object_b(class_loader)) { + _no_of_classes_unloading++; + if (_should_write_unload_events) { + // post class unload event + EventClassUnload event(UNTIMED); + event.set_endtime(_class_unload_time); + event.set_unloadedClass(curklass); + event.set_definingClassLoader(class_loader->klass()); + event.commit(); + } + } +} + +#endif /* INCLUDE_TRACE */ + #ifndef PRODUCT // statistics code
--- a/src/share/vm/classfile/systemDictionary.hpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/classfile/systemDictionary.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -33,6 +33,7 @@ #include "runtime/reflectionUtils.hpp" #include "utilities/hashtable.hpp" #include "utilities/hashtable.inline.hpp" +#include "trace/traceTime.hpp" // The system dictionary stores all loaded classes and maps: // @@ -76,6 +77,7 @@ template <MEMFLAGS F> class HashtableBucket; class ResolutionErrorTable; class SymbolPropertyTable; +class BoolObjectClosure; // Certain classes are preloaded, such as java.lang.Object and java.lang.String. // They are all "well-known", in the sense that no class loader is allowed @@ -613,6 +615,11 @@ // Setup link to hierarchy static void add_to_hierarchy(instanceKlassHandle k, TRAPS); + // event based tracing + static void post_class_load_event(TracingTime start_time, instanceKlassHandle k, + Handle initiating_loader); + static void post_class_unload_events(BoolObjectClosure* is_alive); + private: // We pass in the hashtable index so we can calculate it outside of // the SystemDictionary_lock. @@ -669,6 +676,14 @@ static bool _has_loadClassInternal; static bool _has_checkPackageAccess; + +#if INCLUDE_TRACE + static TracingTime _class_unload_time; + static BoolObjectClosure* _is_alive; + static int _no_of_classes_unloading; + static bool _should_write_unload_events; + static void class_unload_event(klassOop curklass); +#endif }; class SystemDictionaryHandles : AllStatic {
--- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -546,8 +546,6 @@ void clear_has_overflown() { _has_overflown = false; } bool restart_for_overflow() { return _restart_for_overflow; } - bool has_aborted() { return _has_aborted; } - // Methods to enter the two overflow sync barriers void enter_first_sync_barrier(int task_num); void enter_second_sync_barrier(int task_num); @@ -795,6 +793,8 @@ // Called to abort the marking cycle after a Full GC takes palce. void abort(); + bool has_aborted() { return _has_aborted; } + // This prints the global/local fingers. It is used for debugging. NOT_PRODUCT(void print_finger();)
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Apr 18 13:42:00 2013 -0700 @@ -1905,7 +1905,7 @@ _ref_processor_stw(NULL), _process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)), _bot_shared(NULL), - _evac_failure_scan_stack(NULL) , + _evac_failure_scan_stack(NULL), _mark_in_progress(false), _cg1r(NULL), _summary_bytes_used(0), _g1mm(NULL), @@ -1949,21 +1949,19 @@ int n_rem_sets = HeapRegionRemSet::num_par_rem_sets(); assert(n_rem_sets > 0, "Invariant."); - HeapRegionRemSetIterator** iter_arr = - NEW_C_HEAP_ARRAY(HeapRegionRemSetIterator*, n_queues, mtGC); - for (int i = 0; i < n_queues; i++) { - iter_arr[i] = new HeapRegionRemSetIterator(); - } - _rem_set_iterator = iter_arr; - + HeapRegionRemSetIterator** iter_arr = NEW_C_HEAP_ARRAY(HeapRegionRemSetIterator*, n_queues, mtGC); _worker_cset_start_region = NEW_C_HEAP_ARRAY(HeapRegion*, n_queues, mtGC); _worker_cset_start_region_time_stamp = NEW_C_HEAP_ARRAY(unsigned int, n_queues, mtGC); + _evacuation_failed_info_array = NEW_C_HEAP_ARRAY(EvacuationFailedInfo, n_queues, mtGC); for (int i = 0; i < n_queues; i++) { RefToScanQueue* q = new RefToScanQueue(); q->initialize(); _task_queues->register_queue(i, q); - } + iter_arr[i] = new HeapRegionRemSetIterator(); + ::new (&_evacuation_failed_info_array[i]) EvacuationFailedInfo(); + } + _rem_set_iterator = iter_arr; clear_cset_start_regions(); @@ -2518,6 +2516,9 @@ if (_concurrent_cycle_started) { _gc_timer_cm->register_gc_end(os::elapsed_counter()); + if (_cm->has_aborted()) { + _gc_tracer_cm->report_concurrent_mode_failure(); + } _gc_tracer_cm->report_gc_end(_gc_timer_cm->gc_end(), _gc_timer_cm->time_partitions()); _concurrent_cycle_started = false; @@ -4035,13 +4036,19 @@ #endif // YOUNG_LIST_VERBOSE g1_policy()->record_survivor_regions(_young_list->survivor_length(), - _young_list->first_survivor_region(), - _young_list->last_survivor_region()); + _young_list->first_survivor_region(), + _young_list->last_survivor_region()); _young_list->reset_auxilary_lists(); if (evacuation_failed()) { _summary_bytes_used = recalculate_used(); + uint n_queues = MAX2((int)ParallelGCThreads, 1); + for (uint i = 0; i < n_queues; i++) { + if (_evacuation_failed_info_array[i].has_failed()) { + _gc_tracer_stw->report_evacuation_failed(_evacuation_failed_info_array[i]); + } + } } else { // The "used" of the the collection set have already been subtracted // when they were freed. Add in the bytes evacuated. @@ -4355,7 +4362,7 @@ } oop -G1CollectedHeap::handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, +G1CollectedHeap::handle_evacuation_failure_par(G1ParScanThreadState* _par_scan_state, oop old) { assert(obj_in_cs(old), err_msg("obj: "PTR_FORMAT" should still be in the CSet", @@ -4364,7 +4371,12 @@ oop forward_ptr = old->forward_to_atomic(old); if (forward_ptr == NULL) { // Forward-to-self succeeded. - + assert(_par_scan_state != NULL, "par scan state"); + OopsInHeapRegionClosure* cl = _par_scan_state->evac_failure_closure(); + uint queue_num = _par_scan_state->queue_num(); + + _evacuation_failed = true; + _evacuation_failed_info_array[queue_num].register_copy_failure(old->size()); if (_evac_failure_closure != cl) { MutexLockerEx x(EvacFailureStack_lock, Mutex::_no_safepoint_check_flag); assert(!_drain_in_progress, @@ -4395,8 +4407,6 @@ } void G1CollectedHeap::handle_evacuation_failure_common(oop old, markOop m) { - set_evacuation_failed(true); - preserve_mark_if_necessary(old, m); HeapRegion* r = heap_region_containing(old); @@ -4646,8 +4656,7 @@ if (obj_ptr == NULL) { // This will either forward-to-self, or detect that someone else has // installed a forwarding pointer. - OopsInHeapRegionClosure* cl = _par_scan_state->evac_failure_closure(); - return _g1->handle_evacuation_failure_par(cl, old); + return _g1->handle_evacuation_failure_par(_par_scan_state, old); } oop obj = oop(obj_ptr); @@ -5660,7 +5669,7 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) { _expand_heap_after_alloc_failure = true; - set_evacuation_failed(false); + _evacuation_failed = false; // Should G1EvacuationFailureALot be in effect for this GC? NOT_PRODUCT(set_evacuation_failure_alot_for_current_gc();)
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -68,6 +68,7 @@ class STWGCTimer; class G1NewTracer; class G1OldTracer; +class EvacuationFailedInfo; typedef OverflowTaskQueue<StarTask, mtGC> RefToScanQueue; typedef GenericTaskQueueSet<RefToScanQueue, mtGC> RefToScanQueueSet; @@ -166,7 +167,7 @@ // An instance is embedded into the G1CH and used as the // (optional) _is_alive_non_header closure in the STW // reference processor. It is also extensively used during -// refence processing during STW evacuation pauses. +// reference processing during STW evacuation pauses. class G1STWIsAliveClosure: public BoolObjectClosure { G1CollectedHeap* _g1; public: @@ -885,9 +886,7 @@ // True iff a evacuation has failed in the current collection. bool _evacuation_failed; - // Set the attribute indicating whether evacuation has failed in the - // current collection. - void set_evacuation_failed(bool b) { _evacuation_failed = b; } + EvacuationFailedInfo* _evacuation_failed_info_array; // Failed evacuations cause some logical from-space objects to have // forwarding pointers to themselves. Reset them. @@ -929,7 +928,7 @@ void finalize_for_evac_failure(); // An attempt to evacuate "obj" has failed; take necessary steps. - oop handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop obj); + oop handle_evacuation_failure_par(G1ParScanThreadState* _par_scan_state, oop obj); void handle_evacuation_failure_common(oop obj, markOop m); #ifndef PRODUCT @@ -961,13 +960,13 @@ inline bool evacuation_should_fail(); // Reset the G1EvacuationFailureALot counters. Should be called at - // the end of an evacuation pause in which an evacuation failure ocurred. + // the end of an evacuation pause in which an evacuation failure occurred. inline void reset_evacuation_should_fail(); #endif // !PRODUCT // ("Weak") Reference processing support. // - // G1 has 2 instances of the referece processor class. One + // G1 has 2 instances of the reference processor class. One // (_ref_processor_cm) handles reference object discovery // and subsequent processing during concurrent marking cycles. // @@ -1238,7 +1237,7 @@ // verify_region_sets_optional() is planted in the code for // list verification in non-product builds (and it can be enabled in - // product builds by definning HEAP_REGION_SET_FORCE_VERIFY to be 1). + // product builds by defining HEAP_REGION_SET_FORCE_VERIFY to be 1). #if HEAP_REGION_SET_FORCE_VERIFY void verify_region_sets_optional() { verify_region_sets(); @@ -1310,7 +1309,7 @@ // the context of the vm thread. virtual void collect_as_vm_thread(GCCause::Cause cause); - // True iff a evacuation has failed in the most-recent collection. + // True iff an evacuation has failed in the most-recent collection. bool evacuation_failed() { return _evacuation_failed; } // It will free a region if it has allocated objects in it that are @@ -1816,7 +1815,7 @@ G1ParScanHeapEvacClosure* _evac_cl; G1ParScanPartialArrayClosure* _partial_scan_cl; - int _hash_seed; + int _hash_seed; uint _queue_num; size_t _term_attempts; @@ -2020,7 +2019,6 @@ } } -public: void trim_queue(); };
--- a/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -36,7 +36,7 @@ bool _print_sum; // We are caching the sum and average to only have to calculate them once. - // This is not done in an MT-safe way. It is intetened to allow single + // This is not done in an MT-safe way. It is intended to allow single // threaded code to call sum() and average() multiple times in any order // without having to worry about the cost. bool _has_new_data; @@ -135,7 +135,7 @@ double _min_clear_cc_time_ms; // min double _max_clear_cc_time_ms; // max double _cur_clear_cc_time_ms; // clearing time during current pause - double _cum_clear_cc_time_ms; // cummulative clearing time + double _cum_clear_cc_time_ms; // cumulative clearing time jlong _num_cc_clears; // number of times the card count cache has been cleared double _cur_collection_start_sec;
--- a/src/share/vm/gc_implementation/shared/copyFailedInfo.hpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/gc_implementation/shared/copyFailedInfo.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -28,35 +28,31 @@ #include "runtime/thread.hpp" #include "utilities/globalDefinitions.hpp" -class CopyFailedInfo VALUE_OBJ_CLASS_SPEC { +class CopyFailedInfo : public CHeapObj<mtGC> { size_t _first_size; size_t _smallest_size; size_t _total_size; uint _count; - OSThread* _thread; public: - CopyFailedInfo() : _first_size(0), _smallest_size(0), _total_size(0), _count(0), _thread(NULL) {} + CopyFailedInfo() : _first_size(0), _smallest_size(0), _total_size(0), _count(0) {} - void register_copy_failure(size_t size) { + virtual void register_copy_failure(size_t size) { if (_first_size == 0) { _first_size = size; _smallest_size = size; - _thread = Thread::current()->osthread(); } else if (size < _smallest_size) { _smallest_size = size; } _total_size += size; _count++; - assert(_thread == Thread::current()->osthread(), "The PromotionFailedInfo should be thread local."); } - void reset() { + virtual void reset() { _first_size = 0; _smallest_size = 0; _total_size = 0; _count = 0; - _thread = NULL; } bool has_failed() const { return _count != 0; } @@ -64,9 +60,31 @@ size_t smallest_size() const { return _smallest_size; } size_t total_size() const { return _total_size; } uint failed_count() const { return _count; } +}; + +class PromotionFailedInfo : public CopyFailedInfo { + OSThread* _thread; + + public: + PromotionFailedInfo() : CopyFailedInfo(), _thread(NULL) {} + + void register_copy_failure(size_t size) { + CopyFailedInfo::register_copy_failure(size); + if (_thread == NULL) { + _thread = Thread::current()->osthread(); + } else { + assert(_thread == Thread::current()->osthread(), "The PromotionFailedInfo should be thread local."); + } + } + + void reset() { + CopyFailedInfo::reset(); + _thread = NULL; + } + OSThread* thread() const { return _thread; } }; -class PromotionFailedInfo : public CopyFailedInfo {}; +class EvacuationFailedInfo : public CopyFailedInfo {}; #endif /* SHARE_VM_GC_IMPLEMENTATION_SHARED_COPYFAILEDINFO_HPP */
--- a/src/share/vm/gc_implementation/shared/gcTrace.cpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/gc_implementation/shared/gcTrace.cpp Thu Apr 18 13:42:00 2013 -0700 @@ -161,7 +161,7 @@ _parallel_old_gc_info.report_dense_prefix(dense_prefix); } -void CMSTracer::report_concurrent_mode_failure() { +void OldGCTracer::report_concurrent_mode_failure() { assert_set_gc_id(); send_concurrent_mode_failure_event(); @@ -186,4 +186,11 @@ send_evacuation_info_event(info); } + +void G1NewTracer::report_evacuation_failed(EvacuationFailedInfo& ef_info) { + assert_set_gc_id(); + + send_evacuation_failed_event(ef_info); + ef_info.reset(); +} #endif
--- a/src/share/vm/gc_implementation/shared/gcTrace.hpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/gc_implementation/shared/gcTrace.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -162,8 +162,12 @@ OldGCTracer(GCName name) : GCTracer(name) {} virtual void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions); + public: + void report_concurrent_mode_failure(); + private: void send_old_gc_event() const; + void send_concurrent_mode_failure_event(); }; class ParallelOldTracer : public OldGCTracer { @@ -210,21 +214,18 @@ void report_yc_type(G1YCType type); void report_gc_end_impl(jlong timestamp, TimePartitions* time_partitions); void report_evacuation_info(EvacuationInfo* info); + void report_evacuation_failed(EvacuationFailedInfo& ef_info); private: void send_g1_young_gc_event(); void send_evacuation_info_event(EvacuationInfo* info); + void send_evacuation_failed_event(const EvacuationFailedInfo& ef_info) const; }; #endif class CMSTracer : public OldGCTracer { public: CMSTracer() : OldGCTracer(ConcurrentMarkSweep) {} - - void report_concurrent_mode_failure(); - - private: - void send_concurrent_mode_failure_event(); }; class G1OldTracer : public OldGCTracer {
--- a/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Thu Apr 18 13:42:00 2013 -0700 @@ -101,7 +101,6 @@ failed_info.set_firstSize(cf_info.first_size()); failed_info.set_smallestSize(cf_info.smallest_size()); failed_info.set_totalSize(cf_info.total_size()); - failed_info.set_thread(cf_info.thread()->thread_id()); return failed_info; } @@ -110,11 +109,13 @@ if (e.should_commit()) { e.set_gcId(_shared_gc_info.id()); e.set_data(to_trace_struct(pf_info)); + e.set_thread(pf_info.thread()->thread_id()); e.commit(); } } -void CMSTracer::send_concurrent_mode_failure_event() { +// Common to CMS and G1 +void OldGCTracer::send_concurrent_mode_failure_event() { EventConcurrentModeFailure e; if (e.should_commit()) { e.set_gcId(_shared_gc_info.id()); @@ -135,7 +136,7 @@ bool GCTracer::should_send_object_count_after_gc_event() const { #if INCLUDE_TRACE - return Tracing::enabled(EventObjectCountAfterGC::eventId); + return Tracing::is_event_enabled(EventObjectCountAfterGC::eventId); #else return false; #endif @@ -168,6 +169,15 @@ e.commit(); } } + +void G1NewTracer::send_evacuation_failed_event(const EvacuationFailedInfo& ef_info) const { + EventEvacuationFailed e; + if (e.should_commit()) { + e.set_gcId(_shared_gc_info.id()); + e.set_data(to_trace_struct(ef_info)); + e.commit(); + } +} #endif static TraceStructVirtualSpace to_trace_struct(const VirtualSpaceSummary& summary) {
--- a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Thu Apr 18 13:42:00 2013 -0700 @@ -145,19 +145,18 @@ } bool VM_GC_HeapInspection::collect() { - CollectedHeap* ch = Universe::heap(); - ch->ensure_parsability(false); // must happen, even if collection does - // not happen (e.g. due to GC_locker) - if (GC_locker::is_active()) { return false; } - ch->collect_as_vm_thread(GCCause::_heap_inspection); + Universe::heap()->collect_as_vm_thread(GCCause::_heap_inspection); return true; } void VM_GC_HeapInspection::doit() { HandleMark hm; + Universe::heap()->ensure_parsability(false); // must happen, even if collection does + // not happen (e.g. due to GC_locker) + // or _full_gc being false if (_full_gc) { if (!collect()) { // The collection attempt was skipped because the gc locker is held.
--- a/src/share/vm/runtime/objectMonitor.cpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/runtime/objectMonitor.cpp Thu Apr 18 13:42:00 2013 -0700 @@ -973,7 +973,7 @@ #if INCLUDE_TRACE // get the owner's thread id for the MonitorEnter event // if it is enabled and the thread isn't suspended - if (not_suspended && Tracing::enabled(TraceJavaMonitorEnterEvent)) { + if (not_suspended && Tracing::is_event_enabled(TraceJavaMonitorEnterEvent)) { _previous_owner_tid = SharedRuntime::get_java_tid(Self); } #endif
--- a/src/share/vm/runtime/thread.hpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/runtime/thread.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -1042,11 +1042,11 @@ // native memory tracking inline MemRecorder* get_recorder() const { return (MemRecorder*)_recorder; } - inline void set_recorder(MemRecorder* rc) { _recorder = (volatile MemRecorder*)rc; } + inline void set_recorder(MemRecorder* rc) { _recorder = rc; } private: // per-thread memory recorder - volatile MemRecorder* _recorder; + MemRecorder* volatile _recorder; // Suspend/resume support for JavaThread private:
--- a/src/share/vm/services/memTrackWorker.cpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/services/memTrackWorker.cpp Thu Apr 18 13:42:00 2013 -0700 @@ -39,7 +39,7 @@ } } -MemTrackWorker::MemTrackWorker() { +MemTrackWorker::MemTrackWorker(MemSnapshot* snapshot): _snapshot(snapshot) { // create thread uses cgc thread type for now. We should revisit // the option, or create new thread type. _has_error = !os::create_thread(this, os::cgc_thread); @@ -88,8 +88,7 @@ assert(MemTracker::is_on(), "native memory tracking is off"); this->initialize_thread_local_storage(); this->record_stack_base_and_size(); - MemSnapshot* snapshot = MemTracker::get_snapshot(); - assert(snapshot != NULL, "Worker should not be started"); + assert(_snapshot != NULL, "Worker should not be started"); MemRecorder* rec; unsigned long processing_generation = 0; bool worker_idle = false; @@ -109,7 +108,7 @@ } // merge the recorder into staging area - if (!snapshot->merge(rec)) { + if (!_snapshot->merge(rec)) { MemTracker::shutdown(MemTracker::NMT_out_of_memory); } else { NOT_PRODUCT(_merge_count ++;) @@ -132,7 +131,7 @@ _head = (_head + 1) % MAX_GENERATIONS; } // promote this generation data to snapshot - if (!snapshot->promote(number_of_classes)) { + if (!_snapshot->promote(number_of_classes)) { // failed to promote, means out of memory MemTracker::shutdown(MemTracker::NMT_out_of_memory); } @@ -140,7 +139,7 @@ // worker thread is idle worker_idle = true; MemTracker::report_worker_idle(); - snapshot->wait(1000); + _snapshot->wait(1000); ThreadCritical tc; // check if more data arrived if (!_gen[_head].has_more_recorder()) {
--- a/src/share/vm/services/memTrackWorker.hpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/services/memTrackWorker.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -85,8 +85,10 @@ bool _has_error; + MemSnapshot* _snapshot; + public: - MemTrackWorker(); + MemTrackWorker(MemSnapshot* snapshot); ~MemTrackWorker(); _NOINLINE_ void* operator new(size_t size); _NOINLINE_ void* operator new(size_t size, const std::nothrow_t& nothrow_constant);
--- a/src/share/vm/services/memTracker.cpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/services/memTracker.cpp Thu Apr 18 13:42:00 2013 -0700 @@ -53,12 +53,12 @@ } -MemRecorder* MemTracker::_global_recorder = NULL; +MemRecorder* volatile MemTracker::_global_recorder = NULL; MemSnapshot* MemTracker::_snapshot = NULL; MemBaseline MemTracker::_baseline; Mutex* MemTracker::_query_lock = NULL; -volatile MemRecorder* MemTracker::_merge_pending_queue = NULL; -volatile MemRecorder* MemTracker::_pooled_recorders = NULL; +MemRecorder* volatile MemTracker::_merge_pending_queue = NULL; +MemRecorder* volatile MemTracker::_pooled_recorders = NULL; MemTrackWorker* MemTracker::_worker_thread = NULL; int MemTracker::_sync_point_skip_count = 0; MemTracker::NMTLevel MemTracker::_tracking_level = MemTracker::NMT_off; @@ -127,12 +127,15 @@ assert(_state == NMT_bootstrapping_multi_thread, "wrong state"); _snapshot = new (std::nothrow)MemSnapshot(); - if (_snapshot != NULL && !_snapshot->out_of_memory()) { - if (start_worker()) { + if (_snapshot != NULL) { + if (!_snapshot->out_of_memory() && start_worker(_snapshot)) { _state = NMT_started; NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack()); return; } + + delete _snapshot; + _snapshot = NULL; } // fail to start native memory tracking, shut it down @@ -206,7 +209,7 @@ // delete all pooled recorders void MemTracker::delete_all_pooled_recorders() { // free all pooled recorders - volatile MemRecorder* cur_head = _pooled_recorders; + MemRecorder* volatile cur_head = _pooled_recorders; if (cur_head != NULL) { MemRecorder* null_ptr = NULL; while (cur_head != NULL && (void*)cur_head != Atomic::cmpxchg_ptr((void*)null_ptr, @@ -540,11 +543,14 @@ /* * Start worker thread. */ -bool MemTracker::start_worker() { - assert(_worker_thread == NULL, "Just Check"); - _worker_thread = new (std::nothrow) MemTrackWorker(); - if (_worker_thread == NULL || _worker_thread->has_error()) { - shutdown(NMT_initialization); +bool MemTracker::start_worker(MemSnapshot* snapshot) { + assert(_worker_thread == NULL && _snapshot != NULL, "Just Check"); + _worker_thread = new (std::nothrow) MemTrackWorker(snapshot); + if (_worker_thread == NULL) { + return false; + } else if (_worker_thread->has_error()) { + delete _worker_thread; + _worker_thread = NULL; return false; } _worker_thread->start();
--- a/src/share/vm/services/memTracker.hpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/services/memTracker.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -349,7 +349,7 @@ private: // start native memory tracking worker thread - static bool start_worker(); + static bool start_worker(MemSnapshot* snapshot); // called by worker thread to complete shutdown process static void final_shutdown(); @@ -403,18 +403,18 @@ // a thread can start to allocate memory before it is attached // to VM 'Thread', those memory activities are recorded here. // ThreadCritical is required to guard this global recorder. - static MemRecorder* _global_recorder; + static MemRecorder* volatile _global_recorder; // main thread id debug_only(static intx _main_thread_tid;) // pending recorders to be merged - static volatile MemRecorder* _merge_pending_queue; + static MemRecorder* volatile _merge_pending_queue; NOT_PRODUCT(static volatile jint _pending_recorder_count;) // pooled memory recorders - static volatile MemRecorder* _pooled_recorders; + static MemRecorder* volatile _pooled_recorders; // memory recorder pool management, uses following // counter to determine if a released memory recorder
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/trace/noTraceBackend.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013, 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. + * + */ +#ifndef SHARE_VM_TRACE_NOTRACEBACKEND_HPP +#define SHARE_VM_TRACE_NOTRACEBACKEND_HPP + +#include "prims/jni.h" + +typedef jlong TracingTime; +typedef jlong RelativeTracingTime; + +class NoTraceBackend { +public: + static TracingTime time() { + return 0; + } +}; + +typedef NoTraceBackend Tracing; + +#endif + +
--- a/src/share/vm/trace/trace.xml Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/trace/trace.xml Thu Apr 18 13:42:00 2013 -0700 @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2012, 2013, 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 @@ -36,6 +36,7 @@ <relation_decl id="GC_ID" uri="vm/gc/id"/> <relation_decl id="COMP_ID" uri="vm/compiler/id"/> <relation_decl id="SWEEP_ID" uri="vm/code_sweeper/id"/> + <relation_decl id="JAVA_MONITOR_ADDRESS" uri="java/monitor/address"/> </relation_decls> <!-- @@ -89,14 +90,14 @@ has_thread="true" has_stacktrace="true" is_instant="false"> <value type="CLASS" field="klass" label="Class Parked On"/> <value type="MILLIS" field="timeout" label="Park Timeout"/> - <value type="ADDRESS" field="address" label="Address of Object Parked"/> + <value type="ADDRESS" field="address" label="Address of Object Parked" relation="JAVA_MONITOR_ADDRESS"/> </event> <event id="JavaMonitorEnter" path="java/monitor_enter" label="Java Monitor Blocked" has_thread="true" has_stacktrace="true" is_instant="false"> <value type="CLASS" field="klass" label="Monitor Class"/> <value type="JAVALANGTHREAD" field="previousOwner" label="Previous Monitor Owner"/> - <value type="ADDRESS" field="address" label="Monitor Address"/> + <value type="ADDRESS" field="address" label="Monitor Address" relation="JAVA_MONITOR_ADDRESS"/> </event> <event id="JavaMonitorWait" path="java/monitor_wait" label="Java Monitor Wait" description="Waiting on a Java monitor" @@ -105,7 +106,20 @@ <value type="OSTHREAD" field="notifier" label="Notifier Thread" description="Notifying Thread"/> <value type="MILLIS" field="timeout" label="Timeout" description="Maximum wait time"/> <value type="BOOLEAN" field="timedOut" label="Timed Out" description="Wait has been timed out"/> - <value type="ADDRESS" field="address" label="Monitor Address" description="Address of object waited on"/> + <value type="ADDRESS" field="address" label="Monitor Address" description="Address of object waited on" relation="JAVA_MONITOR_ADDRESS"/> + </event> + + <event id="ClassLoad" path="vm/class/load" label="Class Load" + has_thread="true" has_stacktrace="true" is_instant="false"> + <value type="CLASS" field="loadedClass" label="Loaded Class"/> + <value type="CLASS" field="definingClassLoader" label="Defining Class Loader"/> + <value type="CLASS" field="initiatingClassLoader" label="Initiating Class Loader"/> + </event> + + <event id="ClassUnload" path="vm/class/unload" label="Class Unload" + has_thread="true" is_instant="true"> + <value type="CLASS" field="unloadedClass" label="Unloaded Class"/> + <value type="CLASS" field="definingClassLoader" label="Defining Class Loader"/> </event> <struct id="VirtualSpace"> @@ -203,11 +217,10 @@ </event> <struct id="CopyFailed"> - <value type="BYTES64" field="objectCount" label="Object Count"/> + <value type="ULONG" field="objectCount" label="Object Count"/> <value type="BYTES64" field="firstSize" label="First Failed Object Size"/> <value type="BYTES64" field="smallestSize" label="Smallest Failed Object Size"/> <value type="BYTES64" field="totalSize" label="Total Object Size"/> - <value type="OSTHREAD" field="thread" label="Running thread"/> </struct> <event id="ObjectCountAfterGC" path="vm/gc/detailed/object_count_after_gc" is_instant="true" label="Object Count After GC"> @@ -221,6 +234,13 @@ description="Promotion of an object failed"> <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> <structvalue type="CopyFailed" field="data" label="data"/> + <value type="OSTHREAD" field="thread" label="Running thread"/> + </event> + + <event id="EvacuationFailed" path="vm/gc/detailed/evacuation_failed" label="Evacuation Failed" is_instant="true" + description="Evacuation of an object failed"> + <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <structvalue type="CopyFailed" field="data" label="data"/> </event> <event id="ConcurrentModeFailure" path="vm/gc/detailed/concurrent_mode_failure" label="Concurrent Mode Failure" @@ -313,7 +333,7 @@ <value type="VMOPERATIONTYPE" field="operation" label="Operation" /> <value type="BOOLEAN" field="safepoint" label="At Safepoint" description="If the operation occured at a safepoint."/> <value type="BOOLEAN" field="blocking" label="Caller Blocked" description="If the calling thread was blocked until the operation was complete."/> - <value type="OSTHREAD" field="caller" label="Caller" transition="TO" description="Thread requesting operation. If non-blocking, will be set to 0 indicating thread is unknown."/> + <value type="OSTHREAD" field="caller" label="Caller" transition="FROM" description="Thread requesting operation. If non-blocking, will be set to 0 indicating thread is unknown."/> </event> <!-- Allocation events -->
--- a/src/share/vm/trace/traceBackend.hpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/trace/traceBackend.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -32,10 +32,13 @@ #include "runtime/os.hpp" class TraceBackend { - public: - static bool enabled(TraceEventId id) { +public: + static bool enabled(void) { return EnableTracing; } + static bool is_event_enabled(TraceEventId id) { + return enabled(); + } static TracingTime time() { return os::elapsed_counter(); @@ -44,9 +47,16 @@ static TracingTime time_adjustment(jlong time) { return time; } + + static void on_unloading_classes(BoolObjectClosure* is_alive, int no_of_classes_unloading) { + } }; typedef TraceBackend Tracing; +#else /* INCLUDE_TRACE */ + +#include "trace/noTraceBackend.hpp" + #endif /* INCLUDE_TRACE */ #endif /* SHARE_VM_TRACE_TRACEBACKEND_HPP */
--- a/src/share/vm/trace/traceEvent.hpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/trace/traceEvent.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -73,7 +73,7 @@ } static bool is_enabled() { - return Tracing::enabled(T::eventId); + return Tracing::is_event_enabled(T::eventId); } bool should_commit() {
--- a/src/share/vm/trace/traceEventClasses.xsl Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/trace/traceEventClasses.xsl Thu Apr 18 13:42:00 2013 -0700 @@ -37,6 +37,7 @@ // INCLUDE_TRACE #include "memory/resourceArea.hpp" +#include "runtime/handles.inline.hpp" #include "tracefiles/traceTypes.hpp" #include "trace/traceEvent.hpp" @@ -130,6 +131,7 @@ <xsl:value-of select="concat(' Event', @id, '(EventStartTime timing=TIMED) : TraceEvent<Event', @id, '>(timing) {}', $newline)"/> void writeEvent(void) { ResourceMark rm; + HandleMark hm; TraceStream ts(*tty); ts.print("<xsl:value-of select="@label"/>: ["); <xsl:apply-templates select="value|structvalue" mode="write-data"/>
--- a/src/share/vm/trace/traceStream.hpp Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/trace/traceStream.hpp Thu Apr 18 13:42:00 2013 -0700 @@ -27,9 +27,11 @@ #if INCLUDE_TRACE -#include "utilities/ostream.hpp" +#include "oops/klass.hpp" +#include "oops/klassOop.hpp" #include "oops/methodOop.hpp" -#include "oops/klassOop.hpp" +#include "oops/symbol.hpp" +#include "utilities/ostream.hpp" class TraceStream : public StackObj { private: @@ -78,12 +80,32 @@ _st.print("%s = %f", label, val); } - void print_val(const char* label, klassOop& val) { - _st.print("%s = %s", label, val->print_string()); + // Caller is machine generated code located in traceEventClasses.hpp + // Event<TraceId>::writeEvent() (pseudocode) contains the + // necessary ResourceMark for the resource allocations below. + // See traceEventClasses.xsl for details. + void print_val(const char* label, const klassOop& val) { + const char* description = "NULL"; + if (val != NULL) { + Klass* myklass = val->klass_part(); + Symbol* name = myklass->name(); + if (name != NULL) { + description = name->as_C_string(); + } + } + _st.print("%s = %s", label, description); } - void print_val(const char* label, methodOop& val) { - _st.print("%s = %s", label, val->name_and_sig_as_C_string()); + // Caller is machine generated code located in traceEventClasses.hpp + // Event<TraceId>::writeEvent() (pseudocode) contains the + // necessary ResourceMark for the resource allocations below. + // See traceEventClasses.xsl for details. + void print_val(const char* label, const methodOop& val) { + const char* description = "NULL"; + if (val != NULL) { + description = val->name_and_sig_as_C_string(); + } + _st.print("%s = %s", label, description); } void print_val(const char* label, const char* val) { @@ -95,5 +117,5 @@ } }; -#endif -#endif +#endif /* INCLUDE_TRACE */ +#endif /* SHARE_VM_TRACE_TRACESTREAM_HPP */
--- a/src/share/vm/trace/tracetypes.xml Wed Apr 17 12:13:28 2013 -0700 +++ b/src/share/vm/trace/tracetypes.xml Thu Apr 18 13:42:00 2013 -0700 @@ -103,6 +103,7 @@ <content_type id="StackTrace" hr_name="Stacktrace" type="U8" builtin_type="STACKTRACE"> + <value type="BOOLEAN" field="truncated" label="Truncated"/> <structarray type="StackFrame" field="frames" label="Stack frames"/> </content_type>