# HG changeset patch # User acorn # Date 1270135381 14400 # Node ID 7c358fbb6a848047218dd8708a62708db7fd982b # Parent 4a9cc99938e3daea8d25b31b2c87fadf9a2e4676# Parent d4197f8d516a4ddcbc2d61dfb44cd02885375a5d Merge diff -r d4197f8d516a -r 7c358fbb6a84 make/windows/build.bat --- a/make/windows/build.bat Thu Mar 18 12:14:59 2010 -0400 +++ b/make/windows/build.bat Thu Apr 01 11:23:01 2010 -0400 @@ -28,6 +28,9 @@ REM Since we don't have uname and we could be cross-compiling, REM Use the compiler to determine which ARCH we are building REM +REM Note: Running this batch file from the Windows command shell requires +REM that "grep" be accessible on the PATH. An MKS install does this. +REM cl 2>&1 | grep "IA-64" >NUL if %errorlevel% == 0 goto isia64 cl 2>&1 | grep "AMD64" >NUL @@ -57,11 +60,12 @@ if "%1" == "product" goto test1 if "%1" == "debug" goto test1 if "%1" == "fastdebug" goto test1 +if "%1" == "tree" goto test1 goto usage :test1 if "%2" == "core" goto test2 -if "%2" == "kernel" goto test2 +if "%2" == "kernel" goto test2 if "%2" == "compiler1" goto test2 if "%2" == "compiler2" goto test2 if "%2" == "tiered" goto test2 @@ -70,6 +74,7 @@ goto usage :test2 +if "%1" == "tree" goto build_tree REM check_j2se_version REM jvmti.make requires J2SE 1.4.x or newer. REM If not found then fail fast. @@ -93,6 +98,10 @@ nmake -f %3/make/windows/build.make Variant=compiler2 WorkSpace=%3 BootStrapDir=%4 BuildUser="%USERNAME%" HOTSPOT_BUILD_VERSION=%5 ADLC_ONLY=1 %1 goto end +:build_tree +nmake -f %3/make/windows/build.make Variant=%2 WorkSpace=%3 BootStrapDir=%4 BuildUser="%USERNAME%" HOTSPOT_BUILD_VERSION="%5" %1 +goto end + :usage echo Usage: build flavor version workspace bootstrap_dir [build_id] [windbg_home] echo. @@ -100,8 +109,10 @@ echo flavor is "product", "debug" or "fastdebug", echo version is "core", "kernel", "compiler1", "compiler2", or "tiered", echo workspace is source directory without trailing slash, -echo bootstrap_dir is a full path to echo a JDK in which bin/java -echo and bin/javac are present and working, and echo build_id is an +echo bootstrap_dir is a full path to a JDK in which bin/java +echo and bin/javac are present and working, and build_id is an echo optional build identifier displayed by java -version +exit /b 1 :end +exit /b %errorlevel% diff -r d4197f8d516a -r 7c358fbb6a84 make/windows/build.make --- a/make/windows/build.make Thu Mar 18 12:14:59 2010 -0400 +++ b/make/windows/build.make Thu Apr 01 11:23:01 2010 -0400 @@ -27,6 +27,9 @@ # environment variables (Variant, WorkSpace, BootStrapDir, BuildUser, HOTSPOT_BUILD_VERSION) # are passed in as command line arguments. +# Note: Running nmake or build.bat from the Windows command shell requires +# that "sh" be accessible on the PATH. An MKS install does this. + # SA components are built if BUILD_WIN_SA=1 is specified. # See notes in README. This produces files: # 1. sa-jdi.jar - This is built before building jvm.dll @@ -233,6 +236,12 @@ cd $(variantDir) nmake -nologo -f $(WorkSpace)\make\windows\makefiles\top.make BUILD_FLAVOR=product DEVELOP=1 ARCH=$(ARCH) +# target to create just the directory structure +tree: checks $(variantDir) $(variantDir)\local.make sanity + mkdir $(variantDir)\product + mkdir $(variantDir)\debug + mkdir $(variantDir)\fastdebug + sanity: @ echo; @ cd $(variantDir) diff -r d4197f8d516a -r 7c358fbb6a84 make/windows/create.bat --- a/make/windows/create.bat Thu Mar 18 12:14:59 2010 -0400 +++ b/make/windows/create.bat Thu Apr 01 11:23:01 2010 -0400 @@ -36,6 +36,9 @@ REM Since we don't have uname and we could be cross-compiling, REM Use the compiler to determine which ARCH we are building REM +REM Note: Running this batch file from the Windows command shell requires +REM that "grep" be accessible on the PATH. An MKS install does this. +REM cl 2>&1 | grep "IA-64" >NUL if %errorlevel% == 0 goto isia64 cl 2>&1 | grep "AMD64" >NUL diff -r d4197f8d516a -r 7c358fbb6a84 make/windows/get_msc_ver.sh --- a/make/windows/get_msc_ver.sh Thu Mar 18 12:14:59 2010 -0400 +++ b/make/windows/get_msc_ver.sh Thu Apr 01 11:23:01 2010 -0400 @@ -22,6 +22,8 @@ # # +set -e + # This shell script echoes "MSC_VER=" # It ignores the micro version component. # Examples: @@ -38,17 +40,20 @@ # sh, and it has been found that sometimes `which sh` fails. if [ "x$HotSpotMksHome" != "x" ]; then - MKS_HOME="$HotSpotMksHome" + TOOL_DIR="$HotSpotMksHome" else - SH=`which sh` - MKS_HOME=`dirname "$SH"` + # HotSpotMksHome is not set so use the directory that contains "sh". + # This works with both MKS and Cygwin. + SH=`which sh` + TOOL_DIR=`dirname "$SH"` fi -HEAD="$MKS_HOME/head" -ECHO="$MKS_HOME/echo" -EXPR="$MKS_HOME/expr" -CUT="$MKS_HOME/cut" -SED="$MKS_HOME/sed" +DIRNAME="$TOOL_DIR/dirname" +HEAD="$TOOL_DIR/head" +ECHO="$TOOL_DIR/echo" +EXPR="$TOOL_DIR/expr" +CUT="$TOOL_DIR/cut" +SED="$TOOL_DIR/sed" if [ "x$FORCE_MSC_VER" != "x" ]; then echo "MSC_VER=$FORCE_MSC_VER" @@ -70,7 +75,15 @@ if [ "x$FORCE_LINK_VER" != "x" ]; then echo "LINK_VER=$FORCE_LINK_VER" else - LINK_VER_RAW=`link 2>&1 | "$HEAD" -n 1 | "$SED" 's/.*Version[\ ]*\([0-9][0-9.]*\).*/\1/'` + # use the "link" command that is co-located with the "cl" command + cl_cmd=`which cl` + if [ "x$cl_cmd" != "x" ]; then + link_cmd=`$DIRNAME "$cl_cmd"`/link + else + # which can't find "cl" so just use which ever "link" we find + link_cmd="link" + fi + LINK_VER_RAW=`"$link_cmd" 2>&1 | "$HEAD" -n 1 | "$SED" 's/.*Version[\ ]*\([0-9][0-9.]*\).*/\1/'` LINK_VER_MAJOR=`"$ECHO" $LINK_VER_RAW | "$CUT" -d'.' -f1` LINK_VER_MINOR=`"$ECHO" $LINK_VER_RAW | "$CUT" -d'.' -f2` LINK_VER_MICRO=`"$ECHO" $LINK_VER_RAW | "$CUT" -d'.' -f3` diff -r d4197f8d516a -r 7c358fbb6a84 src/cpu/x86/vm/methodHandles_x86.cpp --- a/src/cpu/x86/vm/methodHandles_x86.cpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Thu Apr 01 11:23:01 2010 -0400 @@ -1065,7 +1065,7 @@ __ movptr(rbx_temp, Address(rsi_array, elem_offset)); __ movptr(Address(rax_argslot, slot_offset), rbx_temp); elem_offset += type2aelembytes(elem_type); - slot_offset += Interpreter::stackElementSize(); + slot_offset += Interpreter::stackElementSize(); } } diff -r d4197f8d516a -r 7c358fbb6a84 src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/os/linux/vm/os_linux.cpp Thu Apr 01 11:23:01 2010 -0400 @@ -22,6 +22,8 @@ * */ +# define __STDC_FORMAT_MACROS + // do not include precompiled header file # include "incls/_os_linux.cpp.incl" @@ -53,6 +55,8 @@ # include # include # include +# include +# include #define MAX_PATH (2 * K) @@ -2492,6 +2496,91 @@ != MAP_FAILED; } +// Linux uses a growable mapping for the stack, and if the mapping for +// the stack guard pages is not removed when we detach a thread the +// stack cannot grow beyond the pages where the stack guard was +// mapped. If at some point later in the process the stack expands to +// that point, the Linux kernel cannot expand the stack any further +// because the guard pages are in the way, and a segfault occurs. +// +// However, it's essential not to split the stack region by unmapping +// a region (leaving a hole) that's already part of the stack mapping, +// so if the stack mapping has already grown beyond the guard pages at +// the time we create them, we have to truncate the stack mapping. +// So, we need to know the extent of the stack mapping when +// create_stack_guard_pages() is called. + +// Find the bounds of the stack mapping. Return true for success. +// +// We only need this for stacks that are growable: at the time of +// writing thread stacks don't use growable mappings (i.e. those +// creeated with MAP_GROWSDOWN), and aren't marked "[stack]", so this +// only applies to the main thread. +static bool +get_stack_bounds(uintptr_t *bottom, uintptr_t *top) +{ + FILE *f = fopen("/proc/self/maps", "r"); + if (f == NULL) + return false; + + while (!feof(f)) { + size_t dummy; + char *str = NULL; + ssize_t len = getline(&str, &dummy, f); + if (len == -1) { + fclose(f); + return false; + } + + if (len > 0 && str[len-1] == '\n') { + str[len-1] = 0; + len--; + } + + static const char *stack_str = "[stack]"; + if (len > (ssize_t)strlen(stack_str) + && (strcmp(str + len - strlen(stack_str), stack_str) == 0)) { + if (sscanf(str, "%" SCNxPTR "-%" SCNxPTR, bottom, top) == 2) { + uintptr_t sp = (uintptr_t)__builtin_frame_address(0); + if (sp >= *bottom && sp <= *top) { + free(str); + fclose(f); + return true; + } + } + } + free(str); + } + fclose(f); + return false; +} + +// If the (growable) stack mapping already extends beyond the point +// where we're going to put our guard pages, truncate the mapping at +// that point by munmap()ping it. This ensures that when we later +// munmap() the guard pages we don't leave a hole in the stack +// mapping. +bool os::create_stack_guard_pages(char* addr, size_t size) { + uintptr_t stack_extent, stack_base; + if (get_stack_bounds(&stack_extent, &stack_base)) { + if (stack_extent < (uintptr_t)addr) + ::munmap((void*)stack_extent, (uintptr_t)addr - stack_extent); + } + + return os::commit_memory(addr, size); +} + +// If this is a growable mapping, remove the guard pages entirely by +// munmap()ping them. If not, just call uncommit_memory(). +bool os::remove_stack_guard_pages(char* addr, size_t size) { + uintptr_t stack_extent, stack_base; + if (get_stack_bounds(&stack_extent, &stack_base)) { + return ::munmap(addr, size) == 0; + } + + return os::uncommit_memory(addr, size); +} + static address _highest_vm_reserved_address = NULL; // If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory diff -r d4197f8d516a -r 7c358fbb6a84 src/os/solaris/dtrace/hotspot.d --- a/src/os/solaris/dtrace/hotspot.d Thu Mar 18 12:14:59 2010 -0400 +++ b/src/os/solaris/dtrace/hotspot.d Thu Apr 01 11:23:01 2010 -0400 @@ -25,9 +25,20 @@ provider hotspot { probe class__loaded(char*, uintptr_t, void*, uintptr_t); probe class__unloaded(char*, uintptr_t, void*, uintptr_t); + probe class__initialization__required(char*, uintptr_t, void*, intptr_t,int); + probe class__initialization__recursive(char*, uintptr_t, void*, intptr_t,int); + probe class__initialization__concurrent(char*, uintptr_t, void*, intptr_t,int); + probe class__initialization__erroneous(char*, uintptr_t, void*, intptr_t, int); + probe class__initialization__super__failed(char*, uintptr_t, void*, intptr_t,int); + probe class__initialization__clinit(char*, uintptr_t, void*, intptr_t,int); + probe class__initialization__error(char*, uintptr_t, void*, intptr_t,int); + probe class__initialization__end(char*, uintptr_t, void*, intptr_t,int); probe vm__init__begin(); probe vm__init__end(); probe vm__shutdown(); + probe vmops__request(char*, uintptr_t, int); + probe vmops__begin(char*, uintptr_t, int); + probe vmops__end(char*, uintptr_t, int); probe gc__begin(uintptr_t); probe gc__end(); probe mem__pool__gc__begin( @@ -38,6 +49,12 @@ uintptr_t, uintptr_t, uintptr_t, uintptr_t); probe thread__start(char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t); probe thread__stop(char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t); + probe thread__sleep__begin(long long); + probe thread__sleep__end(int); + probe thread__yield(); + probe thread__park__begin(uintptr_t, int, long long); + probe thread__park__end(uintptr_t); + probe thread__unpark(uintptr_t); probe method__compile__begin( char*, uintptr_t, char*, uintptr_t, char*, uintptr_t, char*, uintptr_t); probe method__compile__end( diff -r d4197f8d516a -r 7c358fbb6a84 src/os/solaris/vm/attachListener_solaris.cpp --- a/src/os/solaris/vm/attachListener_solaris.cpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/os/solaris/vm/attachListener_solaris.cpp Thu Apr 01 11:23:01 2010 -0400 @@ -668,13 +668,18 @@ } } - if (strcmp(name, "ExtendedDTraceProbes") != 0) { - out->print_cr("flag '%s' cannot be changed", name); - return JNI_ERR; + if (strcmp(name, "ExtendedDTraceProbes") == 0) { + DTrace::set_extended_dprobes(flag); + return JNI_OK; } - DTrace::set_extended_dprobes(flag); - return JNI_OK; + if (strcmp(name, "DTraceMonitorProbes") == 0) { + DTrace::set_monitor_dprobes(flag); + return JNI_OK; + } + + out->print_cr("flag '%s' cannot be changed", name); + return JNI_ERR; } void AttachListener::pd_detachall() { diff -r d4197f8d516a -r 7c358fbb6a84 src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/os/solaris/vm/os_solaris.cpp Thu Apr 01 11:23:01 2010 -0400 @@ -2698,6 +2698,14 @@ } } +bool os::create_stack_guard_pages(char* addr, size_t size) { + return os::commit_memory(addr, size); +} + +bool os::remove_stack_guard_pages(char* addr, size_t size) { + return os::uncommit_memory(addr, size); +} + // Change the page size in a given range. void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { assert((intptr_t)addr % alignment_hint == 0, "Address should be aligned."); diff -r d4197f8d516a -r 7c358fbb6a84 src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/os/windows/vm/os_windows.cpp Thu Apr 01 11:23:01 2010 -0400 @@ -2803,6 +2803,14 @@ return VirtualFree(addr, 0, MEM_RELEASE) != 0; } +bool os::create_stack_guard_pages(char* addr, size_t size) { + return os::commit_memory(addr, size); +} + +bool os::remove_stack_guard_pages(char* addr, size_t size) { + return os::uncommit_memory(addr, size); +} + // Set protections specified bool os::protect_memory(char* addr, size_t bytes, ProtType prot, bool is_committed) { diff -r d4197f8d516a -r 7c358fbb6a84 src/share/vm/includeDB_core --- a/src/share/vm/includeDB_core Thu Mar 18 12:14:59 2010 -0400 +++ b/src/share/vm/includeDB_core Thu Apr 01 11:23:01 2010 -0400 @@ -2026,6 +2026,7 @@ instanceKlass.cpp collectedHeap.inline.hpp instanceKlass.cpp compileBroker.hpp +instanceKlass.cpp dtrace.hpp instanceKlass.cpp fieldDescriptor.hpp instanceKlass.cpp genOopClosures.inline.hpp instanceKlass.cpp handles.inline.hpp @@ -2485,6 +2486,7 @@ jvm.cpp collectedHeap.inline.hpp jvm.cpp copy.hpp jvm.cpp defaultStream.hpp +jvm.cpp dtrace.hpp jvm.cpp dtraceJSDT.hpp jvm.cpp events.hpp jvm.cpp handles.inline.hpp @@ -4458,6 +4460,7 @@ unsafe.cpp allocation.inline.hpp unsafe.cpp copy.hpp +unsafe.cpp dtrace.hpp unsafe.cpp globals.hpp unsafe.cpp interfaceSupport.hpp unsafe.cpp jni.h @@ -4629,6 +4632,7 @@ vmThread.cpp collectedHeap.hpp vmThread.cpp compileBroker.hpp +vmThread.cpp dtrace.hpp vmThread.cpp events.hpp vmThread.cpp interfaceSupport.hpp vmThread.cpp methodOop.hpp diff -r d4197f8d516a -r 7c358fbb6a84 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/share/vm/oops/instanceKlass.cpp Thu Apr 01 11:23:01 2010 -0400 @@ -25,6 +25,58 @@ # include "incls/_precompiled.incl" # include "incls/_instanceKlass.cpp.incl" +#ifdef DTRACE_ENABLED + +HS_DTRACE_PROBE_DECL4(hotspot, class__initialization__required, + char*, intptr_t, oop, intptr_t); +HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__recursive, + char*, intptr_t, oop, intptr_t, int); +HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__concurrent, + char*, intptr_t, oop, intptr_t, int); +HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__erroneous, + char*, intptr_t, oop, intptr_t, int); +HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__super__failed, + char*, intptr_t, oop, intptr_t, int); +HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__clinit, + char*, intptr_t, oop, intptr_t, int); +HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__error, + char*, intptr_t, oop, intptr_t, int); +HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end, + char*, intptr_t, oop, intptr_t, int); + +#define DTRACE_CLASSINIT_PROBE(type, clss, thread_type) \ + { \ + char* data = NULL; \ + int len = 0; \ + symbolOop name = (clss)->name(); \ + if (name != NULL) { \ + data = (char*)name->bytes(); \ + len = name->utf8_length(); \ + } \ + HS_DTRACE_PROBE4(hotspot, class__initialization__##type, \ + data, len, (clss)->class_loader(), thread_type); \ + } + +#define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait) \ + { \ + char* data = NULL; \ + int len = 0; \ + symbolOop name = (clss)->name(); \ + if (name != NULL) { \ + data = (char*)name->bytes(); \ + len = name->utf8_length(); \ + } \ + HS_DTRACE_PROBE5(hotspot, class__initialization__##type, \ + data, len, (clss)->class_loader(), thread_type, wait); \ + } + +#else // ndef DTRACE_ENABLED + +#define DTRACE_CLASSINIT_PROBE(type, clss, thread_type) +#define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait) + +#endif // ndef DTRACE_ENABLED + bool instanceKlass::should_be_initialized() const { return !is_initialized(); } @@ -292,6 +344,10 @@ // A class could already be verified, since it has been reflected upon. this_oop->link_class(CHECK); + DTRACE_CLASSINIT_PROBE(required, instanceKlass::cast(this_oop()), -1); + + bool wait = false; + // refer to the JVM book page 47 for description of steps // Step 1 { ObjectLocker ol(this_oop, THREAD); @@ -303,19 +359,25 @@ // we might end up throwing IE from link/symbol resolution sites // that aren't expected to throw. This would wreak havoc. See 6320309. while(this_oop->is_being_initialized() && !this_oop->is_reentrant_initialization(self)) { + wait = true; ol.waitUninterruptibly(CHECK); } // Step 3 - if (this_oop->is_being_initialized() && this_oop->is_reentrant_initialization(self)) + if (this_oop->is_being_initialized() && this_oop->is_reentrant_initialization(self)) { + DTRACE_CLASSINIT_PROBE_WAIT(recursive, instanceKlass::cast(this_oop()), -1,wait); return; + } // Step 4 - if (this_oop->is_initialized()) + if (this_oop->is_initialized()) { + DTRACE_CLASSINIT_PROBE_WAIT(concurrent, instanceKlass::cast(this_oop()), -1,wait); return; + } // Step 5 if (this_oop->is_in_error_state()) { + DTRACE_CLASSINIT_PROBE_WAIT(erroneous, instanceKlass::cast(this_oop()), -1,wait); ResourceMark rm(THREAD); const char* desc = "Could not initialize class "; const char* className = this_oop->external_name(); @@ -348,6 +410,7 @@ this_oop->set_initialization_state_and_notify(initialization_error, THREAD); // Locks object, set state, and notify all waiting threads CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, superclass initialization error is thrown below } + DTRACE_CLASSINIT_PROBE_WAIT(super__failed, instanceKlass::cast(this_oop()), -1,wait); THROW_OOP(e()); } } @@ -356,6 +419,7 @@ { assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl"); JavaThread* jt = (JavaThread*)THREAD; + DTRACE_CLASSINIT_PROBE_WAIT(clinit, instanceKlass::cast(this_oop()), -1,wait); // Timer includes any side effects of class initialization (resolution, // etc), but not recursive entry into call_class_initializer(). PerfClassTraceTime timer(ClassLoader::perf_class_init_time(), @@ -383,6 +447,7 @@ this_oop->set_initialization_state_and_notify(initialization_error, THREAD); CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below } + DTRACE_CLASSINIT_PROBE_WAIT(error, instanceKlass::cast(this_oop()), -1,wait); if (e->is_a(SystemDictionary::Error_klass())) { THROW_OOP(e()); } else { @@ -392,6 +457,7 @@ &args); } } + DTRACE_CLASSINIT_PROBE_WAIT(end, instanceKlass::cast(this_oop()), -1,wait); } diff -r d4197f8d516a -r 7c358fbb6a84 src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/share/vm/prims/jvm.cpp Thu Apr 01 11:23:01 2010 -0400 @@ -26,6 +26,10 @@ #include "incls/_jvm.cpp.incl" #include +HS_DTRACE_PROBE_DECL1(hotspot, thread__sleep__begin, long long); +HS_DTRACE_PROBE_DECL1(hotspot, thread__sleep__end, int); +HS_DTRACE_PROBE_DECL0(hotspot, thread__yield); + /* NOTE about use of any ctor or function call that can trigger a safepoint/GC: such ctors and calls MUST NOT come between an oop declaration/init and its @@ -2762,6 +2766,7 @@ JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass)) JVMWrapper("JVM_Yield"); if (os::dont_yield()) return; + HS_DTRACE_PROBE0(hotspot, thread__yield); // When ConvertYieldToSleep is off (default), this matches the classic VM use of yield. // Critical for similar threading behaviour if (ConvertYieldToSleep) { @@ -2787,6 +2792,8 @@ // And set new thread state to SLEEPING. JavaThreadSleepState jtss(thread); + HS_DTRACE_PROBE1(hotspot, thread__sleep__begin, millis); + if (millis == 0) { // When ConvertSleepToYield is on, this matches the classic VM implementation of // JVM_Sleep. Critical for similar threading behaviour (Win32) @@ -2807,6 +2814,7 @@ // An asynchronous exception (e.g., ThreadDeathException) could have been thrown on // us while we were sleeping. We do not overwrite those. if (!HAS_PENDING_EXCEPTION) { + HS_DTRACE_PROBE1(hotspot, thread__sleep__end,1); // TODO-FIXME: THROW_MSG returns which means we will not call set_state() // to properly restore the thread state. That's likely wrong. THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted"); @@ -2814,6 +2822,7 @@ } thread->osthread()->set_state(old_state); } + HS_DTRACE_PROBE1(hotspot, thread__sleep__end,0); JVM_END JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass)) diff -r d4197f8d516a -r 7c358fbb6a84 src/share/vm/prims/unsafe.cpp --- a/src/share/vm/prims/unsafe.cpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/share/vm/prims/unsafe.cpp Thu Apr 01 11:23:01 2010 -0400 @@ -29,6 +29,10 @@ #include "incls/_precompiled.incl" #include "incls/_unsafe.cpp.incl" +HS_DTRACE_PROBE_DECL3(hotspot, thread__park__begin, uintptr_t, int, long long); +HS_DTRACE_PROBE_DECL1(hotspot, thread__park__end, uintptr_t); +HS_DTRACE_PROBE_DECL1(hotspot, thread__unpark, uintptr_t); + #define MAX_OBJECT_SIZE \ ( arrayOopDesc::header_size(T_DOUBLE) * HeapWordSize \ + ((julong)max_jint * sizeof(double)) ) @@ -1083,8 +1087,10 @@ UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) UnsafeWrapper("Unsafe_Park"); + HS_DTRACE_PROBE3(hotspot, thread__park__begin, thread->parker(), (int) isAbsolute, time); JavaThreadParkedState jtps(thread, time != 0); thread->parker()->park(isAbsolute != 0, time); + HS_DTRACE_PROBE1(hotspot, thread__park__end, thread->parker()); UNSAFE_END UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) @@ -1116,6 +1122,7 @@ } } if (p != NULL) { + HS_DTRACE_PROBE1(hotspot, thread__unpark, p); p->unpark(); } UNSAFE_END diff -r d4197f8d516a -r 7c358fbb6a84 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/share/vm/runtime/globals.hpp Thu Apr 01 11:23:01 2010 -0400 @@ -2293,6 +2293,10 @@ "print safepoint statistics only when safepoint takes" \ " more than PrintSafepointSatisticsTimeout in millis") \ \ + product(bool, TraceSafepointCleanupTime, false, \ + "print the break down of clean up tasks performed during" \ + " safepoint") \ + \ develop(bool, InlineAccessors, true, \ "inline accessor methods (get/set)") \ \ diff -r d4197f8d516a -r 7c358fbb6a84 src/share/vm/runtime/os.hpp --- a/src/share/vm/runtime/os.hpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/share/vm/runtime/os.hpp Thu Apr 01 11:23:01 2010 -0400 @@ -218,6 +218,9 @@ static bool guard_memory(char* addr, size_t bytes); static bool unguard_memory(char* addr, size_t bytes); + static bool create_stack_guard_pages(char* addr, size_t bytes); + static bool remove_stack_guard_pages(char* addr, size_t bytes); + static char* map_memory(int fd, const char* file_name, size_t file_offset, char *addr, size_t bytes, bool read_only = false, bool allow_exec = false); diff -r d4197f8d516a -r 7c358fbb6a84 src/share/vm/runtime/safepoint.cpp --- a/src/share/vm/runtime/safepoint.cpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/share/vm/runtime/safepoint.cpp Thu Apr 01 11:23:01 2010 -0400 @@ -457,21 +457,21 @@ // Various cleaning tasks that should be done periodically at safepoints void SafepointSynchronize::do_cleanup_tasks() { { - TraceTime t1("deflating idle monitors", TraceSafepoint); + TraceTime t1("deflating idle monitors", TraceSafepointCleanupTime); ObjectSynchronizer::deflate_idle_monitors(); } { - TraceTime t2("updating inline caches", TraceSafepoint); + TraceTime t2("updating inline caches", TraceSafepointCleanupTime); InlineCacheBuffer::update_inline_caches(); } if(UseCounterDecay && CounterDecay::is_decay_needed()) { - TraceTime t3("decaying counter", TraceSafepoint); + TraceTime t3("decaying counter", TraceSafepointCleanupTime); CounterDecay::decay(); } - TraceTime t4("sweeping nmethods", TraceSafepoint); + TraceTime t4("sweeping nmethods", TraceSafepointCleanupTime); NMethodSweeper::sweep(); } diff -r d4197f8d516a -r 7c358fbb6a84 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/share/vm/runtime/thread.cpp Thu Apr 01 11:23:01 2010 -0400 @@ -2137,7 +2137,7 @@ int allocate = os::allocate_stack_guard_pages(); // warning("Guarding at " PTR_FORMAT " for len " SIZE_FORMAT "\n", low_addr, len); - if (allocate && !os::commit_memory((char *) low_addr, len)) { + if (allocate && !os::create_stack_guard_pages((char *) low_addr, len)) { warning("Attempt to allocate stack guard pages failed."); return; } @@ -2158,7 +2158,7 @@ size_t len = (StackYellowPages + StackRedPages) * os::vm_page_size(); if (os::allocate_stack_guard_pages()) { - if (os::uncommit_memory((char *) low_addr, len)) { + if (os::remove_stack_guard_pages((char *) low_addr, len)) { _stack_guard_state = stack_guard_unused; } else { warning("Attempt to deallocate stack guard pages failed."); diff -r d4197f8d516a -r 7c358fbb6a84 src/share/vm/runtime/vmThread.cpp --- a/src/share/vm/runtime/vmThread.cpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/share/vm/runtime/vmThread.cpp Thu Apr 01 11:23:01 2010 -0400 @@ -25,6 +25,10 @@ # include "incls/_precompiled.incl" # include "incls/_vmThread.cpp.incl" +HS_DTRACE_PROBE_DECL3(hotspot, vmops__request, char *, uintptr_t, int); +HS_DTRACE_PROBE_DECL3(hotspot, vmops__begin, char *, uintptr_t, int); +HS_DTRACE_PROBE_DECL3(hotspot, vmops__end, char *, uintptr_t, int); + // Dummy VM operation to act as first element in our circular double-linked list class VM_Dummy: public VM_Operation { VMOp_Type type() const { return VMOp_Dummy; } @@ -132,6 +136,10 @@ //----------------------------------------------------------------- // High-level interface bool VMOperationQueue::add(VM_Operation *op) { + + HS_DTRACE_PROBE3(hotspot, vmops__request, op->name(), strlen(op->name()), + op->evaluation_mode()); + // Encapsulates VM queue policy. Currently, that // only involves putting them on the right list if (op->evaluate_at_safepoint()) { @@ -325,7 +333,11 @@ { PerfTraceTime vm_op_timer(perf_accumulated_vm_operation_time()); + HS_DTRACE_PROBE3(hotspot, vmops__begin, op->name(), strlen(op->name()), + op->evaluation_mode()); op->evaluate(); + HS_DTRACE_PROBE3(hotspot, vmops__end, op->name(), strlen(op->name()), + op->evaluation_mode()); } // Last access of info in _cur_vm_operation! diff -r d4197f8d516a -r 7c358fbb6a84 src/share/vm/services/dtraceAttacher.cpp --- a/src/share/vm/services/dtraceAttacher.cpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/share/vm/services/dtraceAttacher.cpp Thu Apr 01 11:23:01 2010 -0400 @@ -135,4 +135,9 @@ } } +void DTrace::set_monitor_dprobes(bool flag) { + // explicit setting of DTraceMonitorProbes flag + set_bool_flag("DTraceMonitorProbes", flag); +} + #endif /* SOLARIS */ diff -r d4197f8d516a -r 7c358fbb6a84 src/share/vm/services/dtraceAttacher.hpp --- a/src/share/vm/services/dtraceAttacher.hpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/share/vm/services/dtraceAttacher.hpp Thu Apr 01 11:23:01 2010 -0400 @@ -41,4 +41,6 @@ static void detach_all_clients(); // set ExtendedDTraceProbes flag static void set_extended_dprobes(bool value); + // set DTraceMonitorProbes flag + static void set_monitor_dprobes(bool value); }; diff -r d4197f8d516a -r 7c358fbb6a84 src/share/vm/services/management.cpp --- a/src/share/vm/services/management.cpp Thu Mar 18 12:14:59 2010 -0400 +++ b/src/share/vm/services/management.cpp Thu Apr 01 11:23:01 2010 -0400 @@ -1537,7 +1537,6 @@ global->type = JMM_VMGLOBAL_TYPE_JSTRING; } else { global->type = JMM_VMGLOBAL_TYPE_UNKNOWN; - assert(false, "Unsupported VMGlobal Type"); return false; } diff -r d4197f8d516a -r 7c358fbb6a84 test/runtime/6929067/T.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/6929067/T.java Thu Apr 01 11:23:01 2010 -0400 @@ -0,0 +1,12 @@ +public class T +{ + public static boolean foo(boolean bar) + { + return bar; + } + + public static void printIt() + { + System.out.println("Hello"); + } +} diff -r d4197f8d516a -r 7c358fbb6a84 test/runtime/6929067/Test6929067.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/6929067/Test6929067.sh Thu Apr 01 11:23:01 2010 -0400 @@ -0,0 +1,60 @@ +#!/bin/sh + +## +## @test Test6929067.sh +## @bug 6929067 +## @summary Stack guard pages should be removed when thread is detached +## @run shell Test6929067.sh +## + +if [ "${TESTSRC}" = "" ] +then TESTSRC=. +fi + +if [ "${TESTJAVA}" = "" ] +then + PARENT=`dirname \`which java\`` + TESTJAVA=`dirname ${PARENT}` + echo "TESTJAVA not set, selecting " ${TESTJAVA} + echo "If this is incorrect, try setting the variable manually." +fi + +BIT_FLAG="" + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + Linux) + NULL=/dev/null + PS=":" + FS="/" + ;; + SunOS | Windows_* ) + NULL=NUL + PS=";" + FS="\\" + echo "Test passed; only valid for Linux" + exit 0; + ;; + * ) + echo "Unrecognized system!" + exit 1; + ;; +esac + +LD_LIBRARY_PATH=.:${TESTJAVA}/jre/lib/i386/client:/usr/openwin/lib:/usr/dt/lib:/usr/lib:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH + +THIS_DIR=`pwd` + +cp ${TESTSRC}${FS}invoke.c ${THIS_DIR} +cp ${TESTSRC}${FS}T.java ${THIS_DIR} + + +${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -fullversion + +${TESTJAVA}${FS}bin${FS}javac T.java + +gcc -o invoke -I${TESTJAVA}/include -I${TESTJAVA}/include/linux invoke.c ${TESTJAVA}/jre/lib/i386/client/libjvm.so +./invoke +exit $? diff -r d4197f8d516a -r 7c358fbb6a84 test/runtime/6929067/invoke.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/6929067/invoke.c Thu Apr 01 11:23:01 2010 -0400 @@ -0,0 +1,90 @@ +#include +#include +#include + +#include + +union env_union +{ + void *void_env; + JNIEnv *jni_env; +}; + +union env_union tmp; +JNIEnv* env; +JavaVM* jvm; +JavaVMInitArgs vm_args; +JavaVMOption options[1]; +jclass class_id; +jmethodID method_id; +jint result; + +long product(unsigned long n, unsigned long m) { + if (m == 1) { + return n; + } else { + int *p = alloca(sizeof (int)); + *p = n; + return product (n, m-1) + *p; + } +} + +void * +floobydust (void *p) +{ + (*jvm)->AttachCurrentThread(jvm, &tmp.void_env, NULL); + env = tmp.jni_env; + + class_id = (*env)->FindClass (env, "T"); + assert (class_id); + + method_id = (*env)->GetStaticMethodID (env, class_id, "printIt", "()V"); + assert (method_id); + + (*env)->CallStaticVoidMethod (env, class_id, method_id, NULL); + + (*jvm)->DetachCurrentThread(jvm); + + printf("%ld\n", product(5000,5000)); + + (*jvm)->AttachCurrentThread(jvm, &tmp.void_env, NULL); + env = tmp.jni_env; + + class_id = (*env)->FindClass (env, "T"); + assert (class_id); + + method_id = (*env)->GetStaticMethodID (env, class_id, "printIt", "()V"); + assert (method_id); + + (*env)->CallStaticVoidMethod (env, class_id, method_id, NULL); + + (*jvm)->DetachCurrentThread(jvm); + + printf("%ld\n", product(5000,5000)); + + return NULL; +} + +int +main (int argc, const char** argv) +{ + options[0].optionString = "-Xss320k"; + + vm_args.version = JNI_VERSION_1_2; + vm_args.ignoreUnrecognized = JNI_TRUE; + vm_args.options = options; + vm_args.nOptions = 1; + + result = JNI_CreateJavaVM (&jvm, &tmp.void_env, &vm_args); + assert (result >= 0); + + env = tmp.jni_env; + + floobydust (NULL); + + pthread_t thr; + pthread_create (&thr, NULL, floobydust, NULL); + pthread_join (thr, NULL); + + return 0; +}