Mercurial > hg > truffle
diff src/share/vm/runtime/thread.cpp @ 6275:957c266d8bc5
Merge with http://hg.openjdk.java.net/hsx/hsx24/hotspot/
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Tue, 21 Aug 2012 10:39:19 +0200 |
parents | 120820e30baa 24b9c7f4cae6 |
children | e522a00b91aa |
line wrap: on
line diff
--- a/src/share/vm/runtime/thread.cpp Mon Aug 20 15:21:31 2012 +0200 +++ b/src/share/vm/runtime/thread.cpp Tue Aug 21 10:39:19 2012 +0200 @@ -76,6 +76,7 @@ #include "runtime/vm_operations.hpp" #include "services/attachListener.hpp" #include "services/management.hpp" +#include "services/memTracker.hpp" #include "services/threadService.hpp" #include "trace/traceEventTypes.hpp" #include "utilities/defaultStream.hpp" @@ -162,6 +163,7 @@ #endif // ndef DTRACE_ENABLED + // Class hierarchy // - Thread // - VMThread @@ -171,13 +173,13 @@ // - CompilerThread // ======= Thread ======== - // Support for forcing alignment of thread objects for biased locking -void* Thread::operator new(size_t size) { +void* Thread::allocate(size_t size, bool throw_excpt, MEMFLAGS flags) { if (UseBiasedLocking) { const int alignment = markOopDesc::biased_lock_alignment; size_t aligned_size = size + (alignment - sizeof(intptr_t)); - void* real_malloc_addr = CHeapObj::operator new(aligned_size); + void* real_malloc_addr = throw_excpt? AllocateHeap(aligned_size, flags, CURRENT_PC) + : os::malloc(aligned_size, flags, CURRENT_PC); void* aligned_addr = (void*) align_size_up((intptr_t) real_malloc_addr, alignment); assert(((uintptr_t) aligned_addr + (uintptr_t) size) <= ((uintptr_t) real_malloc_addr + (uintptr_t) aligned_size), @@ -190,16 +192,17 @@ ((Thread*) aligned_addr)->_real_malloc_address = real_malloc_addr; return aligned_addr; } else { - return CHeapObj::operator new(size); + return throw_excpt? AllocateHeap(size, flags, CURRENT_PC) + : os::malloc(size, flags, CURRENT_PC); } } void Thread::operator delete(void* p) { if (UseBiasedLocking) { void* real_malloc_addr = ((Thread*) p)->_real_malloc_address; - CHeapObj::operator delete(real_malloc_addr); + FreeHeap(real_malloc_addr, mtThread); } else { - CHeapObj::operator delete(p); + FreeHeap(p, mtThread); } } @@ -217,8 +220,8 @@ // allocated data structures set_osthread(NULL); - set_resource_area(new ResourceArea()); - set_handle_area(new HandleArea(NULL)); + set_resource_area(new (mtThread)ResourceArea()); + set_handle_area(new (mtThread) HandleArea(NULL)); set_active_handles(NULL); set_free_handle_block(NULL); set_last_handle_mark(NULL); @@ -250,6 +253,10 @@ omInUseList = NULL ; omInUseCount = 0 ; +#ifdef ASSERT + _visited_for_critical_count = false; +#endif + _SR_lock = new Monitor(Mutex::suspend_resume, "SR_lock", true); _suspend_flags = 0; @@ -305,12 +312,17 @@ // set up any platform-specific state. os::initialize_thread(); - } void Thread::record_stack_base_and_size() { set_stack_base(os::current_stack_base()); set_stack_size(os::current_stack_size()); + + // record thread's native stack, stack grows downward + address vm_base = _stack_base - _stack_size; + MemTracker::record_virtual_memory_reserve(vm_base, _stack_size, + CURRENT_PC, this); + MemTracker::record_virtual_memory_type(vm_base, mtThreadStack); } @@ -318,6 +330,9 @@ // Reclaim the objectmonitors from the omFreeList of the moribund thread. ObjectSynchronizer::omFlush (this) ; + MemTracker::record_virtual_memory_release((_stack_base - _stack_size), + _stack_size, this); + // deallocate data structures delete resource_area(); // since the handle marks are using the handle area, we have to deallocated the root @@ -995,6 +1010,29 @@ vmSymbols::void_method_signature(), CHECK); } +char java_runtime_name[128] = ""; + +// extract the JRE name from sun.misc.Version.java_runtime_name +static const char* get_java_runtime_name(TRAPS) { + klassOop k = SystemDictionary::find(vmSymbols::sun_misc_Version(), + Handle(), Handle(), CHECK_AND_CLEAR_NULL); + fieldDescriptor fd; + bool found = k != NULL && + instanceKlass::cast(k)->find_local_field(vmSymbols::java_runtime_name_name(), + vmSymbols::string_signature(), &fd); + if (found) { + oop name_oop = k->java_mirror()->obj_field(fd.offset()); + if (name_oop == NULL) + return NULL; + const char* name = java_lang_String::as_utf8_string(name_oop, + java_runtime_name, + sizeof(java_runtime_name)); + return name; + } else { + return NULL; + } +} + // General purpose hook into Java code, run once when the VM is initialized. // The Java library method itself may be changed independently from the VM. static void call_postVMInitHook(TRAPS) { @@ -1104,14 +1142,14 @@ NamedThread::~NamedThread() { if (_name != NULL) { - FREE_C_HEAP_ARRAY(char, _name); + FREE_C_HEAP_ARRAY(char, _name, mtThread); _name = NULL; } } void NamedThread::set_name(const char* format, ...) { guarantee(_name == NULL, "Only get to set name once."); - _name = NEW_C_HEAP_ARRAY(char, max_name_len); + _name = NEW_C_HEAP_ARRAY(char, max_name_len, mtThread); guarantee(_name != NULL, "alloc failure"); va_list ap; va_start(ap, format); @@ -1296,6 +1334,7 @@ set_monitor_chunks(NULL); set_next(NULL); set_thread_state(_thread_new); + set_recorder(NULL); _terminated = _not_terminated; _privileged_stack_top = NULL; _array_for_gc = NULL; @@ -1379,6 +1418,7 @@ _jni_attach_state = _not_attaching_via_jni; } assert(_deferred_card_mark.is_empty(), "Default MemRegion ctor"); + _safepoint_visible = false; } bool JavaThread::reguard_stack(address cur_sp) { @@ -1441,7 +1481,7 @@ thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread : os::java_thread; os::create_thread(this, thr_type, stack_sz); - + _safepoint_visible = false; // The _osthread may be NULL here because we ran out of memory (too many threads active). // We need to throw and OutOfMemoryError - however we cannot do this here because the caller // may hold a lock and all locks must be unlocked before throwing the exception (throwing @@ -1459,6 +1499,11 @@ tty->print_cr("terminate thread %p", this); } + // Info NMT that this JavaThread is exiting, its memory + // recorder should be collected + assert(!is_safepoint_visible(), "wrong state"); + MemTracker::thread_exiting(this); + // JSR166 -- return the parker to the free list Parker::Release(_parker); _parker = NULL ; @@ -2913,7 +2958,7 @@ void JavaThread::popframe_preserve_args(ByteSize size_in_bytes, void* start) { assert(_popframe_preserved_args == NULL, "should not wipe out old PopFrame preserved arguments"); if (in_bytes(size_in_bytes) != 0) { - _popframe_preserved_args = NEW_C_HEAP_ARRAY(char, in_bytes(size_in_bytes)); + _popframe_preserved_args = NEW_C_HEAP_ARRAY(char, in_bytes(size_in_bytes), mtThread); _popframe_preserved_args_size = in_bytes(size_in_bytes); Copy::conjoint_jbytes(start, _popframe_preserved_args, _popframe_preserved_args_size); } @@ -2935,7 +2980,7 @@ void JavaThread::popframe_free_preserved_args() { assert(_popframe_preserved_args != NULL, "should not free PopFrame preserved arguments twice"); - FREE_C_HEAP_ARRAY(char, (char*) _popframe_preserved_args); + FREE_C_HEAP_ARRAY(char, (char*) _popframe_preserved_args, mtThread); _popframe_preserved_args = NULL; _popframe_preserved_args_size = 0; } @@ -3171,6 +3216,14 @@ jint os_init_2_result = os::init_2(); if (os_init_2_result != JNI_OK) return os_init_2_result; + // intialize TLS + ThreadLocalStorage::init(); + + // Bootstrap native memory tracking, so it can start recording memory + // activities before worker thread is started. This is the first phase + // of bootstrapping, VM is currently running in single-thread mode. + MemTracker::bootstrap_single_thread(); + // Initialize output stream logging ostream_init_log(); @@ -3190,9 +3243,6 @@ _number_of_threads = 0; _number_of_non_daemon_threads = 0; - // Initialize TLS - ThreadLocalStorage::init(); - // Initialize global data structures and create system classes in heap vm_init_globals(); @@ -3224,6 +3274,9 @@ // Initialize Java-Level synchronization subsystem ObjectMonitor::Initialize() ; + // Second phase of bootstrapping, VM is about entering multi-thread mode + MemTracker::bootstrap_multi_thread(); + // Initialize global modules jint status = init_globals(); if (status != JNI_OK) { @@ -3251,6 +3304,9 @@ Universe::verify(); // make sure we're starting with a clean slate } + // Fully start NMT + MemTracker::start(); + // Create the VMThread { TraceTime timer("Start VMThread", TraceStartupTime); VMThread::create(); @@ -3360,6 +3416,9 @@ // The VM creates & returns objects of this class. Make sure it's initialized. initialize_class(vmSymbols::java_lang_Class(), CHECK_0); call_initializeSystemClass(CHECK_0); + + // get the Java runtime name after java.lang.System is initialized + JDK_Version::set_runtime_name(get_java_runtime_name(THREAD)); } else { warning("java.lang.System not initialized"); } @@ -3476,13 +3535,13 @@ create_vm_init_libraries(); } + // Notify JVMTI agents that VM initialization is complete - nop if no agents. + JvmtiExport::post_vm_initialized(); + if (!TRACE_START()) { vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); } - // Notify JVMTI agents that VM initialization is complete - nop if no agents. - JvmtiExport::post_vm_initialized(); - if (CleanChunkPoolAsync) { Chunk::start_chunk_pool_cleaner_task(); } @@ -3552,11 +3611,11 @@ if (library == NULL) { const char *sub_msg = " in absolute path, with error: "; size_t len = strlen(msg) + strlen(name) + strlen(sub_msg) + strlen(ebuf) + 1; - char *buf = NEW_C_HEAP_ARRAY(char, len); + char *buf = NEW_C_HEAP_ARRAY(char, len, mtThread); jio_snprintf(buf, len, "%s%s%s%s", msg, name, sub_msg, ebuf); // If we can't find the agent, exit. vm_exit_during_initialization(buf, NULL); - FREE_C_HEAP_ARRAY(char, buf); + FREE_C_HEAP_ARRAY(char, buf, mtThread); } } else { // Try to load the agent from the standard dll directory @@ -3570,7 +3629,7 @@ const char *fmt = "%s/bin/java %s -Dkernel.background.download=false" " sun.jkernel.DownloadManager -download client_jvm"; size_t length = strlen(props) + strlen(home) + strlen(fmt) + 1; - char *cmd = NEW_C_HEAP_ARRAY(char, length); + char *cmd = NEW_C_HEAP_ARRAY(char, length, mtThread); jio_snprintf(cmd, length, fmt, home, props); int status = os::fork_and_exec(cmd); FreeHeap(props); @@ -3579,7 +3638,7 @@ vm_exit_during_initialization("fork_and_exec failed: %s", strerror(errno)); } - FREE_C_HEAP_ARRAY(char, cmd); + FREE_C_HEAP_ARRAY(char, cmd, mtThread); // when this comes back the instrument.dll should be where it belongs. library = os::dll_load(buffer, ebuf, sizeof ebuf); } @@ -3591,11 +3650,11 @@ if (library == NULL) { const char *sub_msg = " on the library path, with error: "; size_t len = strlen(msg) + strlen(name) + strlen(sub_msg) + strlen(ebuf) + 1; - char *buf = NEW_C_HEAP_ARRAY(char, len); + char *buf = NEW_C_HEAP_ARRAY(char, len, mtThread); jio_snprintf(buf, len, "%s%s%s%s", msg, name, sub_msg, ebuf); // If we can't find the agent, exit. vm_exit_during_initialization(buf, NULL); - FREE_C_HEAP_ARRAY(char, buf); + FREE_C_HEAP_ARRAY(char, buf, mtThread); } } } @@ -3764,6 +3823,7 @@ // and VM_Exit op at VM level. // // Shutdown sequence: +// + Shutdown native memory tracking if it is on // + Wait until we are the last non-daemon thread to execute // <-- every thing is still working at this moment --> // + Call java.lang.Shutdown.shutdown(), which will invoke Java level @@ -3809,6 +3869,10 @@ Mutex::_as_suspend_equivalent_flag); } + // Shutdown NMT before exit. Otherwise, + // it will run into trouble when system destroys static variables. + MemTracker::shutdown(MemTracker::NMT_normal); + // Hang forever on exit if we are reporting an error. if (ShowMessageBoxOnError && is_error_reported()) { os::infinite_sleep(); @@ -3915,6 +3979,8 @@ daemon = false; } + p->set_safepoint_visible(true); + ThreadService::add_thread(p, daemon); // Possible GC point. @@ -3960,6 +4026,10 @@ // to do callbacks into the safepoint code. However, the safepoint code is not aware // of this thread since it is removed from the queue. p->set_terminated_value(); + + // Now, this thread is not visible to safepoint + p->set_safepoint_visible(false); + } // unlock Threads_lock // Since Events::log uses a lock, we grab it outside the Threads_lock