# HG changeset patch # User amurillo # Date 1405063194 25200 # Node ID d952af8cf67dd1e7ab5fec9a299c6c6dafd1863e # Parent b67a3f81b6308414339842e3e58fb4ad216e2449# Parent 5fbeae2a02d3b708928f76cff49e9541549140c5 Merge diff -r b67a3f81b630 -r d952af8cf67d make/hotspot_version --- a/make/hotspot_version Fri Jun 27 11:07:23 2014 +0100 +++ b/make/hotspot_version Fri Jul 11 00:19:54 2014 -0700 @@ -34,8 +34,8 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2014 HS_MAJOR_VER=25 -HS_MINOR_VER=20 -HS_BUILD_NUMBER=20 +HS_MINOR_VER=40 +HS_BUILD_NUMBER=01 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r b67a3f81b630 -r d952af8cf67d src/cpu/zero/vm/cppInterpreter_zero.cpp --- a/src/cpu/zero/vm/cppInterpreter_zero.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -40,6 +40,7 @@ #include "runtime/deoptimization.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/os/aix/vm/os_aix.cpp --- a/src/os/aix/vm/os_aix.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/aix/vm/os_aix.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -55,6 +55,7 @@ #include "runtime/javaCalls.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/objectMonitor.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/osThread.hpp" #include "runtime/perfMemory.hpp" #include "runtime/sharedRuntime.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/os/aix/vm/os_aix.inline.hpp --- a/src/os/aix/vm/os_aix.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/aix/vm/os_aix.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -26,12 +26,9 @@ #ifndef OS_AIX_VM_OS_AIX_INLINE_HPP #define OS_AIX_VM_OS_AIX_INLINE_HPP -#include "runtime/atomic.hpp" +#include "runtime/atomic.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/os.hpp" -#ifdef TARGET_OS_ARCH_aix_ppc -# include "atomic_aix_ppc.inline.hpp" -# include "orderAccess_aix_ppc.inline.hpp" -#endif // System includes diff -r b67a3f81b630 -r d952af8cf67d src/os/aix/vm/thread_aix.inline.hpp --- a/src/os/aix/vm/thread_aix.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/aix/vm/thread_aix.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -26,15 +26,9 @@ #ifndef OS_AIX_VM_THREAD_AIX_INLINE_HPP #define OS_AIX_VM_THREAD_AIX_INLINE_HPP -#include "runtime/atomic.hpp" -#include "runtime/prefetch.hpp" #include "runtime/thread.hpp" #include "runtime/threadLocalStorage.hpp" -#include "atomic_aix_ppc.inline.hpp" -#include "orderAccess_aix_ppc.inline.hpp" -#include "prefetch_aix_ppc.inline.hpp" - // Contains inlined functions for class Thread and ThreadLocalStorage inline void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do diff -r b67a3f81b630 -r d952af8cf67d src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/bsd/vm/os_bsd.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -48,6 +48,7 @@ #include "runtime/javaCalls.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/objectMonitor.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/osThread.hpp" #include "runtime/perfMemory.hpp" #include "runtime/sharedRuntime.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/os/bsd/vm/os_bsd.inline.hpp --- a/src/os/bsd/vm/os_bsd.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/bsd/vm/os_bsd.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -26,15 +26,9 @@ #define OS_BSD_VM_OS_BSD_INLINE_HPP #include "runtime/atomic.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/os.hpp" -#ifdef TARGET_OS_ARCH_bsd_x86 -# include "orderAccess_bsd_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_bsd_zero -# include "orderAccess_bsd_zero.inline.hpp" -#endif - // System includes #include diff -r b67a3f81b630 -r d952af8cf67d src/os/bsd/vm/thread_bsd.inline.hpp --- a/src/os/bsd/vm/thread_bsd.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/bsd/vm/thread_bsd.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -29,20 +29,8 @@ #error "This file should only be included from thread.inline.hpp" #endif -#include "runtime/atomic.hpp" -#include "runtime/prefetch.hpp" #include "runtime/thread.hpp" #include "runtime/threadLocalStorage.hpp" -#ifdef TARGET_OS_ARCH_bsd_x86 -# include "atomic_bsd_x86.inline.hpp" -# include "orderAccess_bsd_x86.inline.hpp" -# include "prefetch_bsd_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_bsd_zero -# include "atomic_bsd_zero.inline.hpp" -# include "orderAccess_bsd_zero.inline.hpp" -# include "prefetch_bsd_zero.inline.hpp" -#endif // Contains inlined functions for class Thread and ThreadLocalStorage diff -r b67a3f81b630 -r d952af8cf67d src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/linux/vm/os_linux.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -49,6 +49,7 @@ #include "runtime/javaCalls.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/objectMonitor.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/osThread.hpp" #include "runtime/perfMemory.hpp" #include "runtime/sharedRuntime.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/os/linux/vm/os_linux.inline.hpp --- a/src/os/linux/vm/os_linux.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/linux/vm/os_linux.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -26,24 +26,9 @@ #define OS_LINUX_VM_OS_LINUX_INLINE_HPP #include "runtime/atomic.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/os.hpp" -#ifdef TARGET_OS_ARCH_linux_x86 -# include "orderAccess_linux_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_sparc -# include "orderAccess_linux_sparc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_zero -# include "orderAccess_linux_zero.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_arm -# include "orderAccess_linux_arm.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_ppc -# include "orderAccess_linux_ppc.inline.hpp" -#endif - // System includes #include diff -r b67a3f81b630 -r d952af8cf67d src/os/linux/vm/thread_linux.inline.hpp --- a/src/os/linux/vm/thread_linux.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/linux/vm/thread_linux.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -29,35 +29,8 @@ #error "This file should only be included from thread.inline.hpp" #endif -#include "runtime/atomic.hpp" -#include "runtime/prefetch.hpp" #include "runtime/thread.hpp" #include "runtime/threadLocalStorage.hpp" -#ifdef TARGET_OS_ARCH_linux_x86 -# include "atomic_linux_x86.inline.hpp" -# include "orderAccess_linux_x86.inline.hpp" -# include "prefetch_linux_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_sparc -# include "atomic_linux_sparc.inline.hpp" -# include "orderAccess_linux_sparc.inline.hpp" -# include "prefetch_linux_sparc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_zero -# include "atomic_linux_zero.inline.hpp" -# include "orderAccess_linux_zero.inline.hpp" -# include "prefetch_linux_zero.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_arm -# include "atomic_linux_arm.inline.hpp" -# include "orderAccess_linux_arm.inline.hpp" -# include "prefetch_linux_arm.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_ppc -# include "atomic_linux_ppc.inline.hpp" -# include "orderAccess_linux_ppc.inline.hpp" -# include "prefetch_linux_ppc.inline.hpp" -#endif // Contains inlined functions for class Thread and ThreadLocalStorage diff -r b67a3f81b630 -r d952af8cf67d src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/solaris/vm/os_solaris.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -48,6 +48,7 @@ #include "runtime/javaCalls.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/objectMonitor.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/osThread.hpp" #include "runtime/perfMemory.hpp" #include "runtime/sharedRuntime.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/os/solaris/vm/os_solaris.inline.hpp --- a/src/os/solaris/vm/os_solaris.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/solaris/vm/os_solaris.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -26,15 +26,9 @@ #define OS_SOLARIS_VM_OS_SOLARIS_INLINE_HPP #include "runtime/atomic.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/os.hpp" -#ifdef TARGET_OS_ARCH_solaris_x86 -# include "orderAccess_solaris_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_solaris_sparc -# include "orderAccess_solaris_sparc.inline.hpp" -#endif - // System includes #include #include diff -r b67a3f81b630 -r d952af8cf67d src/os/solaris/vm/thread_solaris.inline.hpp --- a/src/os/solaris/vm/thread_solaris.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/solaris/vm/thread_solaris.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -29,20 +29,9 @@ #error "This file should only be included from thread.inline.hpp" #endif -#include "runtime/atomic.hpp" -#include "runtime/prefetch.hpp" +#include "runtime/atomic.inline.hpp" #include "runtime/thread.hpp" #include "runtime/threadLocalStorage.hpp" -#ifdef TARGET_OS_ARCH_solaris_x86 -# include "atomic_solaris_x86.inline.hpp" -# include "orderAccess_solaris_x86.inline.hpp" -# include "prefetch_solaris_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_solaris_sparc -# include "atomic_solaris_sparc.inline.hpp" -# include "orderAccess_solaris_sparc.inline.hpp" -# include "prefetch_solaris_sparc.inline.hpp" -#endif // Thread::current is "hot" it's called > 128K times in the 1st 500 msecs of // startup. diff -r b67a3f81b630 -r d952af8cf67d src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/windows/vm/os_windows.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -51,6 +51,7 @@ #include "runtime/javaCalls.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/objectMonitor.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/osThread.hpp" #include "runtime/perfMemory.hpp" #include "runtime/sharedRuntime.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/os/windows/vm/os_windows.inline.hpp --- a/src/os/windows/vm/os_windows.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/windows/vm/os_windows.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -26,12 +26,9 @@ #define OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP #include "runtime/atomic.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/os.hpp" -#ifdef TARGET_OS_ARCH_windows_x86 -# include "orderAccess_windows_x86.inline.hpp" -#endif - inline const char* os::file_separator() { return "\\"; } inline const char* os::line_separator() { return "\r\n"; } inline const char* os::path_separator() { return ";"; } diff -r b67a3f81b630 -r d952af8cf67d src/os/windows/vm/thread_windows.inline.hpp --- a/src/os/windows/vm/thread_windows.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os/windows/vm/thread_windows.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -29,15 +29,8 @@ #error "This file should only be included from thread.inline.hpp" #endif -#include "runtime/atomic.hpp" -#include "runtime/prefetch.hpp" #include "runtime/thread.hpp" #include "runtime/threadLocalStorage.hpp" -#ifdef TARGET_OS_ARCH_windows_x86 -# include "atomic_windows_x86.inline.hpp" -# include "orderAccess_windows_x86.inline.hpp" -# include "prefetch_windows_x86.inline.hpp" -#endif // Contains inlined functions for class Thread and ThreadLocalStorage diff -r b67a3f81b630 -r d952af8cf67d src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp --- a/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -26,7 +26,6 @@ #ifndef OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_INLINE_HPP #define OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_INLINE_HPP -#include "orderAccess_aix_ppc.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" #include "vm_version_ppc.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp --- a/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -26,7 +26,6 @@ #ifndef OS_CPU_LINUX_PPC_VM_ATOMIC_LINUX_PPC_INLINE_HPP #define OS_CPU_LINUX_PPC_VM_ATOMIC_LINUX_PPC_INLINE_HPP -#include "orderAccess_linux_ppc.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" #include "vm_version_ppc.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp --- a/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -55,7 +55,7 @@ if (detect_niagara()) { NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Detected Linux on Niagara");) - features = niagara1_m; + features = niagara1_m | T_family_m; } return features; diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/c1/c1_GraphBuilder.cpp --- a/src/share/vm/c1/c1_GraphBuilder.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -1569,6 +1569,7 @@ default: constant = new Constant(as_ValueType(field_val)); } + // Stable static fields are checked for non-default values in ciField::initialize_from(). } if (constant != NULL) { push(type, append(constant)); @@ -1610,6 +1611,10 @@ default: constant = new Constant(as_ValueType(field_val)); } + if (FoldStableValues && field->is_stable() && field_val.is_null_or_zero()) { + // Stable field with default value can't be constant. + constant = NULL; + } } else { // For CallSite objects treat the target field as a compile time constant. if (const_oop->is_call_site()) { @@ -1993,7 +1998,13 @@ if (!UseInlineCaches && is_loaded && code == Bytecodes::_invokevirtual && !target->can_be_statically_bound()) { // Find a vtable index if one is available - vtable_index = target->resolve_vtable_index(calling_klass, callee_holder); + // For arrays, callee_holder is Object. Resolving the call with + // Object would allow an illegal call to finalize() on an + // array. We use holder instead: illegal calls to finalize() won't + // be compiled as vtable calls (IC call resolution will catch the + // illegal call) and the few legal calls on array types won't be + // either. + vtable_index = target->resolve_vtable_index(calling_klass, holder); } #endif diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/ci/ciEnv.cpp --- a/src/share/vm/ci/ciEnv.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/ci/ciEnv.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -51,6 +51,7 @@ #include "runtime/init.hpp" #include "runtime/reflection.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/thread.inline.hpp" #include "utilities/dtrace.hpp" #include "utilities/macros.hpp" #ifdef COMPILER1 diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/classfile/classFileParser.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -4022,6 +4022,11 @@ this_klass->set_major_version(major_version); this_klass->set_has_default_methods(has_default_methods); + if (!host_klass.is_null()) { + assert (this_klass->is_anonymous(), "should be the same"); + this_klass->set_host_klass(host_klass()); + } + // Set up Method*::intrinsic_id as soon as we know the names of methods. // (We used to do this lazily, but now we query it in Rewriter, // which is eagerly done for every method, so we might as well do it now, diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/classfile/classLoaderData.cpp --- a/src/share/vm/classfile/classLoaderData.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/classfile/classLoaderData.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -531,6 +531,7 @@ // GC root of class loader data created. ClassLoaderData* ClassLoaderDataGraph::_head = NULL; ClassLoaderData* ClassLoaderDataGraph::_unloading = NULL; +ClassLoaderData* ClassLoaderDataGraph::_saved_unloading = NULL; ClassLoaderData* ClassLoaderDataGraph::_saved_head = NULL; bool ClassLoaderDataGraph::_should_purge = false; @@ -628,7 +629,9 @@ void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); - for (ClassLoaderData* cld = _unloading; cld != NULL; cld = cld->next()) { + // Only walk the head until any clds not purged from prior unloading + // (CMS doesn't purge right away). + for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) { cld->classes_do(f); } } @@ -676,6 +679,11 @@ ClassLoaderData* data = _head; ClassLoaderData* prev = NULL; bool seen_dead_loader = false; + + // Save previous _unloading pointer for CMS which may add to unloading list before + // purging and we don't want to rewalk the previously unloaded class loader data. + _saved_unloading = _unloading; + // mark metadata seen on the stack and code cache so we can delete // unneeded entries. bool has_redefined_a_class = JvmtiExport::has_redefined_a_class(); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/classfile/classLoaderData.hpp --- a/src/share/vm/classfile/classLoaderData.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/classfile/classLoaderData.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -66,6 +66,7 @@ static ClassLoaderData* _unloading; // CMS support. static ClassLoaderData* _saved_head; + static ClassLoaderData* _saved_unloading; static bool _should_purge; static ClassLoaderData* add(Handle class_loader, bool anonymous, TRAPS); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/classfile/dictionary.cpp --- a/src/share/vm/classfile/dictionary.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/classfile/dictionary.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -28,6 +28,7 @@ #include "memory/iterator.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiRedefineClassesTrace.hpp" +#include "runtime/orderAccess.inline.hpp" #include "utilities/hashtable.inline.hpp" PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/classfile/systemDictionary.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -52,6 +52,7 @@ #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/signature.hpp" #include "services/classLoadingService.hpp" #include "services/threadService.hpp" @@ -997,7 +998,6 @@ if (host_klass.not_null() && k.not_null()) { assert(EnableInvokeDynamic, ""); - k->set_host_klass(host_klass()); // If it's anonymous, initialize it now, since nobody else will. { diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/classfile/verifier.cpp --- a/src/share/vm/classfile/verifier.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/classfile/verifier.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -43,7 +43,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/javaCalls.hpp" -#include "runtime/orderAccess.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/os.hpp" #ifdef TARGET_ARCH_x86 # include "bytes_x86.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/code/dependencies.cpp --- a/src/share/vm/code/dependencies.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/code/dependencies.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -32,6 +32,7 @@ #include "oops/oop.inline.hpp" #include "runtime/handles.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/thread.inline.hpp" #include "utilities/copy.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/code/nmethod.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -37,6 +37,7 @@ #include "oops/methodData.hpp" #include "prims/jvmtiRedefineClassesTrace.hpp" #include "prims/jvmtiImpl.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/sweeper.hpp" #include "utilities/dtrace.hpp" @@ -688,8 +689,10 @@ _hotness_counter = NMethodSweeper::hotness_counter_reset_val(); code_buffer->copy_values_to(this); - if (ScavengeRootsInCode && detect_scavenge_root_oops()) { - CodeCache::add_scavenge_root_nmethod(this); + if (ScavengeRootsInCode) { + if (detect_scavenge_root_oops()) { + CodeCache::add_scavenge_root_nmethod(this); + } Universe::heap()->register_nmethod(this); } debug_only(verify_scavenge_root_oops()); @@ -773,8 +776,10 @@ _hotness_counter = NMethodSweeper::hotness_counter_reset_val(); code_buffer->copy_values_to(this); - if (ScavengeRootsInCode && detect_scavenge_root_oops()) { - CodeCache::add_scavenge_root_nmethod(this); + if (ScavengeRootsInCode) { + if (detect_scavenge_root_oops()) { + CodeCache::add_scavenge_root_nmethod(this); + } Universe::heap()->register_nmethod(this); } DEBUG_ONLY(verify_scavenge_root_oops();) @@ -889,8 +894,10 @@ code_buffer->copy_values_to(this); debug_info->copy_to(this); dependencies->copy_to(this); - if (ScavengeRootsInCode && detect_scavenge_root_oops()) { - CodeCache::add_scavenge_root_nmethod(this); + if (ScavengeRootsInCode) { + if (detect_scavenge_root_oops()) { + CodeCache::add_scavenge_root_nmethod(this); + } Universe::heap()->register_nmethod(this); } debug_only(verify_scavenge_root_oops()); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -33,12 +33,14 @@ #include "memory/allocation.inline.hpp" #include "memory/blockOffsetTable.inline.hpp" #include "memory/resourceArea.hpp" +#include "memory/space.inline.hpp" #include "memory/universe.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/globals.hpp" #include "runtime/handles.inline.hpp" #include "runtime/init.hpp" #include "runtime/java.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/vmThread.hpp" #include "utilities/copy.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -59,6 +59,7 @@ #include "runtime/globals_extension.hpp" #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/vmThread.hpp" #include "services/memoryService.hpp" #include "services/runtimeService.hpp" @@ -1999,7 +2000,7 @@ SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer(); gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start()); - GCTraceTime t("CMS:MSC ", PrintGCDetails && Verbose, true, NULL); + GCTraceTime t("CMS:MSC ", PrintGCDetails && Verbose, true, NULL, gc_tracer->gc_id()); if (PrintGC && Verbose && !(GCCause::is_user_requested_gc(gch->gc_cause()))) { gclog_or_tty->print_cr("Compact ConcurrentMarkSweepGeneration after %d " "collections passed to foreground collector", _full_gcs_since_conc_gc); @@ -2509,8 +2510,10 @@ assert(ConcurrentMarkSweepThread::vm_thread_has_cms_token(), "VM thread should have CMS token"); + // The gc id is created in register_foreground_gc_start if this collection is synchronous + const GCId gc_id = _collectorState == InitialMarking ? GCId::peek() : _gc_tracer_cm->gc_id(); NOT_PRODUCT(GCTraceTime t("CMS:MS (foreground) ", PrintGCDetails && Verbose, - true, NULL);) + true, NULL, gc_id);) if (UseAdaptiveSizePolicy) { size_policy()->ms_collection_begin(); } @@ -3527,6 +3530,7 @@ public: CMSPhaseAccounting(CMSCollector *collector, const char *phase, + const GCId gc_id, bool print_cr = true); ~CMSPhaseAccounting(); @@ -3535,6 +3539,7 @@ const char *_phase; elapsedTimer _wallclock; bool _print_cr; + const GCId _gc_id; public: // Not MT-safe; so do not pass around these StackObj's @@ -3550,15 +3555,15 @@ CMSPhaseAccounting::CMSPhaseAccounting(CMSCollector *collector, const char *phase, + const GCId gc_id, bool print_cr) : - _collector(collector), _phase(phase), _print_cr(print_cr) { + _collector(collector), _phase(phase), _print_cr(print_cr), _gc_id(gc_id) { if (PrintCMSStatistics != 0) { _collector->resetYields(); } if (PrintGCDetails) { - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); + gclog_or_tty->gclog_stamp(_gc_id); gclog_or_tty->print_cr("[%s-concurrent-%s-start]", _collector->cmsGen()->short_name(), _phase); } @@ -3572,8 +3577,7 @@ _collector->stopTimer(); _wallclock.stop(); if (PrintGCDetails) { - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); + gclog_or_tty->gclog_stamp(_gc_id); gclog_or_tty->print("[%s-concurrent-%s: %3.3f/%3.3f secs]", _collector->cmsGen()->short_name(), _phase, _collector->timerValue(), _wallclock.seconds()); @@ -3671,7 +3675,7 @@ setup_cms_unloading_and_verification_state(); NOT_PRODUCT(GCTraceTime t("\ncheckpointRootsInitialWork", - PrintGCDetails && Verbose, true, _gc_timer_cm);) + PrintGCDetails && Verbose, true, _gc_timer_cm, _gc_tracer_cm->gc_id());) if (UseAdaptiveSizePolicy) { size_policy()->checkpoint_roots_initial_begin(); } @@ -3796,7 +3800,7 @@ CMSTokenSyncWithLocks ts(true, bitMapLock()); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - CMSPhaseAccounting pa(this, "mark", !PrintGCDetails); + CMSPhaseAccounting pa(this, "mark", _gc_tracer_cm->gc_id(), !PrintGCDetails); res = markFromRootsWork(asynch); if (res) { _collectorState = Precleaning; @@ -4519,7 +4523,7 @@ _start_sampling = false; } TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - CMSPhaseAccounting pa(this, "preclean", !PrintGCDetails); + CMSPhaseAccounting pa(this, "preclean", _gc_tracer_cm->gc_id(), !PrintGCDetails); preclean_work(CMSPrecleanRefLists1, CMSPrecleanSurvivors1); } CMSTokenSync x(true); // is cms thread @@ -4548,7 +4552,7 @@ // we will never do an actual abortable preclean cycle. if (get_eden_used() > CMSScheduleRemarkEdenSizeThreshold) { TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - CMSPhaseAccounting pa(this, "abortable-preclean", !PrintGCDetails); + CMSPhaseAccounting pa(this, "abortable-preclean", _gc_tracer_cm->gc_id(), !PrintGCDetails); // We need more smarts in the abortable preclean // loop below to deal with cases where allocation // in young gen is very very slow, and our precleaning @@ -4693,7 +4697,7 @@ GCTimer *gc_timer = NULL; // Currently not tracing concurrent phases rp->preclean_discovered_references( rp->is_alive_non_header(), &keep_alive, &complete_trace, &yield_cl, - gc_timer); + gc_timer, _gc_tracer_cm->gc_id()); } if (clean_survivor) { // preclean the active survivor space(s) @@ -5036,7 +5040,7 @@ // expect it to be false and set to true FlagSetting fl(gch->_is_gc_active, false); NOT_PRODUCT(GCTraceTime t("Scavenge-Before-Remark", - PrintGCDetails && Verbose, true, _gc_timer_cm);) + PrintGCDetails && Verbose, true, _gc_timer_cm, _gc_tracer_cm->gc_id());) int level = _cmsGen->level() - 1; if (level >= 0) { gch->do_collection(true, // full (i.e. force, see below) @@ -5065,7 +5069,7 @@ void CMSCollector::checkpointRootsFinalWork(bool asynch, bool clear_all_soft_refs, bool init_mark_was_synchronous) { - NOT_PRODUCT(GCTraceTime tr("checkpointRootsFinalWork", PrintGCDetails, false, _gc_timer_cm);) + NOT_PRODUCT(GCTraceTime tr("checkpointRootsFinalWork", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());) assert(haveFreelistLocks(), "must have free list locks"); assert_lock_strong(bitMapLock()); @@ -5120,11 +5124,11 @@ // the most recent young generation GC, minus those cleaned up by the // concurrent precleaning. if (CMSParallelRemarkEnabled && CollectedHeap::use_parallel_gc_threads()) { - GCTraceTime t("Rescan (parallel) ", PrintGCDetails, false, _gc_timer_cm); + GCTraceTime t("Rescan (parallel) ", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id()); do_remark_parallel(); } else { GCTraceTime t("Rescan (non-parallel) ", PrintGCDetails, false, - _gc_timer_cm); + _gc_timer_cm, _gc_tracer_cm->gc_id()); do_remark_non_parallel(); } } @@ -5137,7 +5141,7 @@ verify_overflow_empty(); { - NOT_PRODUCT(GCTraceTime ts("refProcessingWork", PrintGCDetails, false, _gc_timer_cm);) + NOT_PRODUCT(GCTraceTime ts("refProcessingWork", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());) refProcessingWork(asynch, clear_all_soft_refs); } verify_work_stacks_empty(); @@ -5922,7 +5926,7 @@ NULL, // space is set further below &_markBitMap, &_markStack, &mrias_cl); { - GCTraceTime t("grey object rescan", PrintGCDetails, false, _gc_timer_cm); + GCTraceTime t("grey object rescan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id()); // Iterate over the dirty cards, setting the corresponding bits in the // mod union table. { @@ -5959,7 +5963,7 @@ Universe::verify(); } { - GCTraceTime t("root rescan", PrintGCDetails, false, _gc_timer_cm); + GCTraceTime t("root rescan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id()); verify_work_stacks_empty(); @@ -5981,7 +5985,7 @@ } { - GCTraceTime t("visit unhandled CLDs", PrintGCDetails, false, _gc_timer_cm); + GCTraceTime t("visit unhandled CLDs", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id()); verify_work_stacks_empty(); @@ -6000,7 +6004,7 @@ } { - GCTraceTime t("dirty klass scan", PrintGCDetails, false, _gc_timer_cm); + GCTraceTime t("dirty klass scan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id()); verify_work_stacks_empty(); @@ -6202,7 +6206,7 @@ _span, &_markBitMap, &_markStack, &cmsKeepAliveClosure, false /* !preclean */); { - GCTraceTime t("weak refs processing", PrintGCDetails, false, _gc_timer_cm); + GCTraceTime t("weak refs processing", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id()); ReferenceProcessorStats stats; if (rp->processing_is_mt()) { @@ -6227,13 +6231,15 @@ &cmsKeepAliveClosure, &cmsDrainMarkingStackClosure, &task_executor, - _gc_timer_cm); + _gc_timer_cm, + _gc_tracer_cm->gc_id()); } else { stats = rp->process_discovered_references(&_is_alive_closure, &cmsKeepAliveClosure, &cmsDrainMarkingStackClosure, NULL, - _gc_timer_cm); + _gc_timer_cm, + _gc_tracer_cm->gc_id()); } _gc_tracer_cm->report_gc_reference_stats(stats); @@ -6244,7 +6250,7 @@ if (should_unload_classes()) { { - GCTraceTime t("class unloading", PrintGCDetails, false, _gc_timer_cm); + GCTraceTime t("class unloading", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id()); // Unload classes and purge the SystemDictionary. bool purged_class = SystemDictionary::do_unloading(&_is_alive_closure); @@ -6257,7 +6263,7 @@ } { - GCTraceTime t("scrub symbol table", PrintGCDetails, false, _gc_timer_cm); + GCTraceTime t("scrub symbol table", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id()); // Clean up unreferenced symbols in symbol table. SymbolTable::unlink(); } @@ -6266,7 +6272,7 @@ // CMS doesn't use the StringTable as hard roots when class unloading is turned off. // Need to check if we really scanned the StringTable. if ((roots_scanning_options() & SharedHeap::SO_Strings) == 0) { - GCTraceTime t("scrub string table", PrintGCDetails, false, _gc_timer_cm); + GCTraceTime t("scrub string table", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id()); // Delete entries for dead interned strings. StringTable::unlink(&_is_alive_closure); } @@ -6333,7 +6339,7 @@ _intra_sweep_timer.start(); if (asynch) { TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - CMSPhaseAccounting pa(this, "sweep", !PrintGCDetails); + CMSPhaseAccounting pa(this, "sweep", _gc_tracer_cm->gc_id(), !PrintGCDetails); // First sweep the old gen { CMSTokenSyncWithLocks ts(true, _cmsGen->freelistLock(), @@ -6554,7 +6560,7 @@ // Clear the mark bitmap (no grey objects to start with) // for the next cycle. TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - CMSPhaseAccounting cmspa(this, "reset", !PrintGCDetails); + CMSPhaseAccounting cmspa(this, "reset", _gc_tracer_cm->gc_id(), !PrintGCDetails); HeapWord* curAddr = _markBitMap.startWord(); while (curAddr < _markBitMap.endWord()) { @@ -6620,7 +6626,7 @@ void CMSCollector::do_CMS_operation(CMS_op_type op, GCCause::Cause gc_cause) { gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - GCTraceTime t(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL); + GCTraceTime t(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer_cm->gc_id()); TraceCollectorStats tcs(counters()); switch (op) { diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -64,7 +64,7 @@ void VM_CMS_Operation::verify_before_gc() { if (VerifyBeforeGC && GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) { - GCTraceTime tm("Verify Before", false, false, _collector->_gc_timer_cm); + GCTraceTime tm("Verify Before", false, false, _collector->_gc_timer_cm, _collector->_gc_tracer_cm->gc_id()); HandleMark hm; FreelistLocker x(_collector); MutexLockerEx y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag); @@ -76,7 +76,7 @@ void VM_CMS_Operation::verify_after_gc() { if (VerifyAfterGC && GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) { - GCTraceTime tm("Verify After", false, false, _collector->_gc_timer_cm); + GCTraceTime tm("Verify After", false, false, _collector->_gc_timer_cm, _collector->_gc_tracer_cm->gc_id()); HandleMark hm; FreelistLocker x(_collector); MutexLockerEx y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp --- a/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -71,6 +71,7 @@ } void ConcurrentG1RefineThread::sample_young_list_rs_lengths() { + SuspendibleThreadSetJoiner sts; G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1CollectorPolicy* g1p = g1h->g1_policy(); if (g1p->adaptive_young_list_length()) { @@ -82,8 +83,8 @@ // we try to yield every time we visit 10 regions if (regions_visited == 10) { - if (_sts.should_yield()) { - _sts.yield("G1 refine"); + if (sts.should_yield()) { + sts.yield(); // we just abandon the iteration break; } @@ -99,9 +100,7 @@ DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); _vtime_start = os::elapsedVTime(); while(!_should_terminate) { - _sts.join(); sample_young_list_rs_lengths(); - _sts.leave(); if (os::supports_vtime()) { _vtime_accum = (os::elapsedVTime() - _vtime_start); @@ -182,37 +181,37 @@ break; } - _sts.join(); + { + SuspendibleThreadSetJoiner sts; + + do { + int curr_buffer_num = (int)dcqs.completed_buffers_num(); + // If the number of the buffers falls down into the yellow zone, + // that means that the transition period after the evacuation pause has ended. + if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) { + dcqs.set_completed_queue_padding(0); + } - do { - int curr_buffer_num = (int)dcqs.completed_buffers_num(); - // If the number of the buffers falls down into the yellow zone, - // that means that the transition period after the evacuation pause has ended. - if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) { - dcqs.set_completed_queue_padding(0); - } + if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) { + // If the number of the buffer has fallen below our threshold + // we should deactivate. The predecessor will reactivate this + // thread should the number of the buffers cross the threshold again. + deactivate(); + break; + } - if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) { - // If the number of the buffer has fallen below our threshold - // we should deactivate. The predecessor will reactivate this - // thread should the number of the buffers cross the threshold again. + // Check if we need to activate the next thread. + if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) { + _next->activate(); + } + } while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, cg1r()->green_zone())); + + // We can exit the loop above while being active if there was a yield request. + if (is_active()) { deactivate(); - break; } - - // Check if we need to activate the next thread. - if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) { - _next->activate(); - } - } while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, cg1r()->green_zone())); - - // We can exit the loop above while being active if there was a yield request. - if (is_active()) { - deactivate(); } - _sts.leave(); - if (os::supports_vtime()) { _vtime_accum = (os::elapsedVTime() - _vtime_start); } else { @@ -223,17 +222,6 @@ terminate(); } - -void ConcurrentG1RefineThread::yield() { - if (G1TraceConcRefinement) { - gclog_or_tty->print_cr("G1-Refine-yield"); - } - _sts.yield("G1 refine"); - if (G1TraceConcRefinement) { - gclog_or_tty->print_cr("G1-Refine-yield-end"); - } -} - void ConcurrentG1RefineThread::stop() { // it is ok to take late safepoints here, if needed { diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp --- a/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -64,9 +64,6 @@ void activate(); void deactivate(); - // For use by G1CollectedHeap, which is a friend. - static SuspendibleThreadSet* sts() { return &_sts; } - public: virtual void run(); // Constructor @@ -84,8 +81,6 @@ ConcurrentG1Refine* cg1r() { return _cg1r; } - // Yield for GC - void yield(); // shutdown void stop(); }; diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -45,6 +45,7 @@ #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" +#include "runtime/prefetch.inline.hpp" #include "services/memTracker.hpp" // Concurrent marking bit map wrapper @@ -510,6 +511,7 @@ _has_overflown(false), _concurrent(false), _has_aborted(false), + _aborted_gc_id(GCId::undefined()), _restart_for_overflow(false), _concurrent_marking_in_progress(false), @@ -976,13 +978,13 @@ } if (concurrent()) { - ConcurrentGCThread::stsLeave(); + SuspendibleThreadSet::leave(); } bool barrier_aborted = !_first_overflow_barrier_sync.enter(); if (concurrent()) { - ConcurrentGCThread::stsJoin(); + SuspendibleThreadSet::join(); } // at this point everyone should have synced up and not be doing any // more work @@ -1019,8 +1021,7 @@ force_overflow()->update(); if (G1Log::fine()) { - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); + gclog_or_tty->gclog_stamp(concurrent_gc_id()); gclog_or_tty->print_cr("[GC concurrent-mark-reset-for-overflow]"); } } @@ -1036,13 +1037,13 @@ } if (concurrent()) { - ConcurrentGCThread::stsLeave(); + SuspendibleThreadSet::leave(); } bool barrier_aborted = !_second_overflow_barrier_sync.enter(); if (concurrent()) { - ConcurrentGCThread::stsJoin(); + SuspendibleThreadSet::join(); } // at this point everything should be re-initialized and ready to go @@ -1094,7 +1095,7 @@ double start_vtime = os::elapsedVTime(); - ConcurrentGCThread::stsJoin(); + SuspendibleThreadSet::join(); assert(worker_id < _cm->active_tasks(), "invariant"); CMTask* the_task = _cm->task(worker_id); @@ -1121,9 +1122,9 @@ if (!_cm->has_aborted() && the_task->has_aborted()) { sleep_time_ms = (jlong) (elapsed_vtime_sec * _cm->sleep_factor() * 1000.0); - ConcurrentGCThread::stsLeave(); + SuspendibleThreadSet::leave(); os::sleep(Thread::current(), sleep_time_ms, false); - ConcurrentGCThread::stsJoin(); + SuspendibleThreadSet::join(); } double end_time2_sec = os::elapsedTime(); double elapsed_time2_sec = end_time2_sec - start_time_sec; @@ -1141,7 +1142,7 @@ the_task->record_end_time(); guarantee(!the_task->has_aborted() || _cm->has_aborted(), "invariant"); - ConcurrentGCThread::stsLeave(); + SuspendibleThreadSet::leave(); double end_vtime = os::elapsedVTime(); _cm->update_accum_task_vtime(worker_id, end_vtime - start_vtime); @@ -2464,7 +2465,7 @@ if (G1Log::finer()) { gclog_or_tty->put(' '); } - GCTraceTime t("GC ref-proc", G1Log::finer(), false, g1h->gc_timer_cm()); + GCTraceTime t("GC ref-proc", G1Log::finer(), false, g1h->gc_timer_cm(), concurrent_gc_id()); ReferenceProcessor* rp = g1h->ref_processor_cm(); @@ -2521,7 +2522,8 @@ &g1_keep_alive, &g1_drain_mark_stack, executor, - g1h->gc_timer_cm()); + g1h->gc_timer_cm(), + concurrent_gc_id()); g1h->gc_tracer_cm()->report_gc_reference_stats(stats); // The do_oop work routines of the keep_alive and drain_marking_stack @@ -3252,6 +3254,12 @@ } _first_overflow_barrier_sync.abort(); _second_overflow_barrier_sync.abort(); + const GCId& gc_id = _g1h->gc_tracer_cm()->gc_id(); + if (!gc_id.is_undefined()) { + // We can do multiple full GCs before ConcurrentMarkThread::run() gets a chance + // to detect that it was aborted. Only keep track of the first GC id that we aborted. + _aborted_gc_id = gc_id; + } _has_aborted = true; SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); @@ -3266,6 +3274,13 @@ _g1h->register_concurrent_cycle_end(); } +const GCId& ConcurrentMark::concurrent_gc_id() { + if (has_aborted()) { + return _aborted_gc_id; + } + return _g1h->gc_tracer_cm()->gc_id(); +} + static void print_ms_time_info(const char* prefix, const char* name, NumberSeq& ns) { gclog_or_tty->print_cr("%s%5d %12s: total time = %8.2f s (avg = %8.2f ms).", @@ -3322,21 +3337,17 @@ // We take a break if someone is trying to stop the world. bool ConcurrentMark::do_yield_check(uint worker_id) { - if (should_yield()) { + if (SuspendibleThreadSet::should_yield()) { if (worker_id == 0) { _g1h->g1_policy()->record_concurrent_pause(); } - cmThread()->yield(); + SuspendibleThreadSet::yield(); return true; } else { return false; } } -bool ConcurrentMark::should_yield() { - return cmThread()->should_yield(); -} - bool ConcurrentMark::containing_card_is_marked(void* p) { size_t offset = pointer_delta(p, _g1h->reserved_region().start(), 1); return _card_bm.at(offset >> CardTableModRefBS::card_shift); @@ -3625,7 +3636,7 @@ #endif // _MARKING_STATS_ // (4) We check whether we should yield. If we have to, then we abort. - if (_cm->should_yield()) { + if (SuspendibleThreadSet::should_yield()) { // We should yield. To do this we abort the task. The caller is // responsible for yielding. set_has_aborted(); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/concurrentMark.hpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -26,6 +26,7 @@ #define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_HPP #include "gc_implementation/g1/heapRegionSet.hpp" +#include "gc_implementation/shared/gcId.hpp" #include "utilities/taskqueue.hpp" class G1CollectedHeap; @@ -444,6 +445,7 @@ volatile bool _concurrent; // set at the end of a Full GC so that marking aborts volatile bool _has_aborted; + GCId _aborted_gc_id; // used when remark aborts due to an overflow to indicate that // another concurrent marking phase should start @@ -818,13 +820,14 @@ } inline bool do_yield_check(uint worker_i = 0); - inline bool should_yield(); // Called to abort the marking cycle after a Full GC takes palce. void abort(); bool has_aborted() { return _has_aborted; } + const GCId& concurrent_gc_id(); + // This prints the global/local fingers. It is used for debugging. NOT_PRODUCT(void print_finger();) diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp --- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -1,4 +1,4 @@ -/* + /* * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -29,6 +29,7 @@ #include "gc_implementation/g1/g1Log.hpp" #include "gc_implementation/g1/g1MMUTracker.hpp" #include "gc_implementation/g1/vm_operations_g1.hpp" +#include "gc_implementation/shared/gcTrace.hpp" #include "memory/resourceArea.hpp" #include "runtime/vmThread.hpp" @@ -109,8 +110,7 @@ double scan_start = os::elapsedTime(); if (!cm()->has_aborted()) { if (G1Log::fine()) { - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); + gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id()); gclog_or_tty->print_cr("[GC concurrent-root-region-scan-start]"); } @@ -118,8 +118,7 @@ double scan_end = os::elapsedTime(); if (G1Log::fine()) { - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); + gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id()); gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf secs]", scan_end - scan_start); } @@ -127,8 +126,7 @@ double mark_start_sec = os::elapsedTime(); if (G1Log::fine()) { - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); + gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id()); gclog_or_tty->print_cr("[GC concurrent-mark-start]"); } @@ -151,8 +149,7 @@ } if (G1Log::fine()) { - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); + gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id()); gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf secs]", mark_end_sec - mark_start_sec); } @@ -167,8 +164,7 @@ "in remark (restart #%d).", iter); } if (G1Log::fine()) { - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); + gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id()); gclog_or_tty->print_cr("[GC concurrent-mark-restart-for-overflow]"); } } @@ -194,9 +190,8 @@ } else { // We don't want to update the marking status if a GC pause // is already underway. - _sts.join(); + SuspendibleThreadSetJoiner sts; g1h->set_marking_complete(); - _sts.leave(); } // Check if cleanup set the free_regions_coming flag. If it @@ -212,8 +207,7 @@ double cleanup_start_sec = os::elapsedTime(); if (G1Log::fine()) { - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); + gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id()); gclog_or_tty->print_cr("[GC concurrent-cleanup-start]"); } @@ -233,8 +227,7 @@ double cleanup_end_sec = os::elapsedTime(); if (G1Log::fine()) { - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); + gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id()); gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf secs]", cleanup_end_sec - cleanup_start_sec); } @@ -266,46 +259,43 @@ // record_concurrent_mark_cleanup_completed() (and, in fact, it's // not needed any more as the concurrent mark state has been // already reset). - _sts.join(); - if (!cm()->has_aborted()) { - g1_policy->record_concurrent_mark_cleanup_completed(); + { + SuspendibleThreadSetJoiner sts; + if (!cm()->has_aborted()) { + g1_policy->record_concurrent_mark_cleanup_completed(); + } } - _sts.leave(); if (cm()->has_aborted()) { if (G1Log::fine()) { - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); + gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id()); gclog_or_tty->print_cr("[GC concurrent-mark-abort]"); } } // We now want to allow clearing of the marking bitmap to be // suspended by a collection pause. - _sts.join(); - _cm->clearNextBitmap(); - _sts.leave(); + { + SuspendibleThreadSetJoiner sts; + _cm->clearNextBitmap(); + } } // Update the number of full collections that have been // completed. This will also notify the FullGCCount_lock in case a // Java thread is waiting for a full GC to happen (e.g., it // called System.gc() with +ExplicitGCInvokesConcurrent). - _sts.join(); - g1h->increment_old_marking_cycles_completed(true /* concurrent */); - g1h->register_concurrent_cycle_end(); - _sts.leave(); + { + SuspendibleThreadSetJoiner sts; + g1h->increment_old_marking_cycles_completed(true /* concurrent */); + g1h->register_concurrent_cycle_end(); + } } assert(_should_terminate, "just checking"); terminate(); } - -void ConcurrentMarkThread::yield() { - _sts.yield("Concurrent Mark"); -} - void ConcurrentMarkThread::stop() { { MutexLockerEx ml(Terminator_lock); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp --- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -89,9 +89,6 @@ // that started() is set and set in_progress(). bool during_cycle() { return started() || in_progress(); } - // Yield for GC - void yield(); - // shutdown void stop(); }; diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/g1AllocRegion.cpp --- a/src/share/vm/gc_implementation/g1/g1AllocRegion.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/g1AllocRegion.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "gc_implementation/g1/g1AllocRegion.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" +#include "runtime/orderAccess.inline.hpp" G1CollectedHeap* G1AllocRegion::_g1h = NULL; HeapRegion* G1AllocRegion::_dummy_region = NULL; diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -60,6 +60,8 @@ #include "memory/referenceProcessor.hpp" #include "oops/oop.inline.hpp" #include "oops/oop.pcgc.inline.hpp" +#include "runtime/prefetch.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/vmThread.hpp" #include "utilities/ticks.hpp" @@ -96,15 +98,13 @@ // Local to this file. class RefineCardTableEntryClosure: public CardTableEntryClosure { - SuspendibleThreadSet* _sts; G1RemSet* _g1rs; ConcurrentG1Refine* _cg1r; bool _concurrent; public: - RefineCardTableEntryClosure(SuspendibleThreadSet* sts, - G1RemSet* g1rs, + RefineCardTableEntryClosure(G1RemSet* g1rs, ConcurrentG1Refine* cg1r) : - _sts(sts), _g1rs(g1rs), _cg1r(cg1r), _concurrent(true) + _g1rs(g1rs), _cg1r(cg1r), _concurrent(true) {} bool do_card_ptr(jbyte* card_ptr, uint worker_i) { bool oops_into_cset = _g1rs->refine_card(card_ptr, worker_i, false); @@ -113,7 +113,7 @@ // that point into the collection set. assert(!oops_into_cset, "should be"); - if (_concurrent && _sts->should_yield()) { + if (_concurrent && SuspendibleThreadSet::should_yield()) { // Caller will actually yield. return false; } @@ -1305,7 +1305,7 @@ TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty); { - GCTraceTime t(GCCauseString("Full GC", gc_cause()), G1Log::fine(), true, NULL); + GCTraceTime t(GCCauseString("Full GC", gc_cause()), G1Log::fine(), true, NULL, gc_tracer->gc_id()); TraceCollectorStats tcs(g1mm()->full_collection_counters()); TraceMemoryManagerStats tms(true /* fullGC */, gc_cause()); @@ -2113,8 +2113,7 @@ g1_policy()->init(); _refine_cte_cl = - new RefineCardTableEntryClosure(ConcurrentG1RefineThread::sts(), - g1_rem_set(), + new RefineCardTableEntryClosure(g1_rem_set(), concurrent_g1_refine()); JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl); @@ -3893,8 +3892,7 @@ return; } - gclog_or_tty->date_stamp(PrintGCDateStamps); - gclog_or_tty->stamp(PrintGCTimeStamps); + gclog_or_tty->gclog_stamp(_gc_tracer_stw->gc_id()); GCCauseString gc_cause_str = GCCauseString("GC pause", gc_cause()) .append(g1_policy()->gcs_are_young() ? "(young)" : "(mixed)") @@ -4326,7 +4324,7 @@ // this point does not assume that we are the only GC thread // running. Note: of course, the actual marking work will // not start until the safepoint itself is released in - // ConcurrentGCThread::safepoint_desynchronize(). + // SuspendibleThreadSet::desynchronize(). doConcurrentMark(); } @@ -5781,7 +5779,8 @@ &keep_alive, &drain_queue, NULL, - _gc_timer_stw); + _gc_timer_stw, + _gc_tracer_stw->gc_id()); } else { // Parallel reference processing assert(rp->num_q() == no_of_gc_workers, "sanity"); @@ -5792,7 +5791,8 @@ &keep_alive, &drain_queue, &par_task_executor, - _gc_timer_stw); + _gc_timer_stw, + _gc_tracer_stw->gc_id()); } _gc_tracer_stw->report_gc_reference_stats(stats); @@ -6949,7 +6949,7 @@ return; } - if (ScavengeRootsInCode && nm->detect_scavenge_root_oops()) { + if (ScavengeRootsInCode) { _g1h->register_nmethod(nm); } } diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -1124,20 +1124,11 @@ return _gc_time_stamp; } - void reset_gc_time_stamp() { - _gc_time_stamp = 0; - OrderAccess::fence(); - // Clear the cached CSet starting regions and time stamps. - // Their validity is dependent on the GC timestamp. - clear_cset_start_regions(); - } + inline void reset_gc_time_stamp(); void check_gc_time_stamps() PRODUCT_RETURN; - void increment_gc_time_stamp() { - ++_gc_time_stamp; - OrderAccess::fence(); - } + inline void increment_gc_time_stamp(); // Reset the given region's GC timestamp. If it's starts humongous, // also reset the GC timestamp of its corresponding diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -33,6 +33,7 @@ #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/heapRegionSet.inline.hpp" #include "gc_implementation/g1/heapRegionSeq.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "utilities/taskqueue.hpp" // Inline functions for G1CollectedHeap @@ -59,6 +60,19 @@ return res; } +inline void G1CollectedHeap::reset_gc_time_stamp() { + _gc_time_stamp = 0; + OrderAccess::fence(); + // Clear the cached CSet starting regions and time stamps. + // Their validity is dependent on the GC timestamp. + clear_cset_start_regions(); +} + +inline void G1CollectedHeap::increment_gc_time_stamp() { + ++_gc_time_stamp; + OrderAccess::fence(); +} + inline void G1CollectedHeap::old_set_remove(HeapRegion* hr) { _old_set.remove(hr); } diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/g1MarkSweep.cpp --- a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -123,7 +123,7 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading, bool clear_all_softrefs) { // Recursively traverse all live objects and mark them - GCTraceTime tm("phase 1", G1Log::fine() && Verbose, true, gc_timer()); + GCTraceTime tm("phase 1", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id()); GenMarkSweep::trace(" 1"); SharedHeap* sh = SharedHeap::heap(); @@ -148,7 +148,8 @@ &GenMarkSweep::keep_alive, &GenMarkSweep::follow_stack_closure, NULL, - gc_timer()); + gc_timer(), + gc_tracer()->gc_id()); gc_tracer()->report_gc_reference_stats(stats); @@ -262,7 +263,7 @@ G1CollectedHeap* g1h = G1CollectedHeap::heap(); - GCTraceTime tm("phase 2", G1Log::fine() && Verbose, true, gc_timer()); + GCTraceTime tm("phase 2", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id()); GenMarkSweep::trace("2"); // find the first region @@ -299,7 +300,7 @@ G1CollectedHeap* g1h = G1CollectedHeap::heap(); // Adjust the pointers to reflect the new locations - GCTraceTime tm("phase 3", G1Log::fine() && Verbose, true, gc_timer()); + GCTraceTime tm("phase 3", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id()); GenMarkSweep::trace("3"); SharedHeap* sh = SharedHeap::heap(); @@ -362,7 +363,7 @@ // to use a higher index (saved from phase2) when verifying perm_gen. G1CollectedHeap* g1h = G1CollectedHeap::heap(); - GCTraceTime tm("phase 4", G1Log::fine() && Verbose, true, gc_timer()); + GCTraceTime tm("phase 4", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id()); GenMarkSweep::trace("4"); G1SpaceCompactClosure blk; diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp --- a/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -31,6 +31,7 @@ #include "gc_implementation/g1/g1RemSet.hpp" #include "gc_implementation/g1/g1RemSet.inline.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" +#include "runtime/prefetch.inline.hpp" /* * This really ought to be an inline function, but apparently the C++ diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp --- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -27,6 +27,7 @@ #include "gc_implementation/g1/heapRegion.hpp" #include "gc_implementation/g1/satbQueue.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/thread.inline.hpp" G1SATBCardTableModRefBS::G1SATBCardTableModRefBS(MemRegion whole_heap, diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp --- a/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -77,38 +77,37 @@ break; } - // Include this thread in safepoints - stsJoin(); + { + // Include thread in safepoints + SuspendibleThreadSetJoiner sts; - stat.mark_exec(); + stat.mark_exec(); - // Process the queue - for (;;) { - oop java_string = G1StringDedupQueue::pop(); - if (java_string == NULL) { - break; + // Process the queue + for (;;) { + oop java_string = G1StringDedupQueue::pop(); + if (java_string == NULL) { + break; + } + + G1StringDedupTable::deduplicate(java_string, stat); + + // Safepoint this thread if needed + if (sts.should_yield()) { + stat.mark_block(); + sts.yield(); + stat.mark_unblock(); + } } - G1StringDedupTable::deduplicate(java_string, stat); + G1StringDedupTable::trim_entry_cache(); - // Safepoint this thread if needed - if (stsShouldYield()) { - stat.mark_block(); - stsYield(NULL); - stat.mark_unblock(); - } - } + stat.mark_done(); - G1StringDedupTable::trim_entry_cache(); - - stat.mark_done(); - - // Print statistics - total_stat.add(stat); - print(gclog_or_tty, stat, total_stat); - - // Exclude this thread from safepoints - stsLeave(); + // Print statistics + total_stat.add(stat); + print(gclog_or_tty, stat, total_stat); + } } terminate(); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/heapRegion.cpp --- a/src/share/vm/gc_implementation/g1/heapRegion.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -32,7 +32,9 @@ #include "gc_implementation/g1/heapRegionSeq.inline.hpp" #include "memory/genOopClosures.inline.hpp" #include "memory/iterator.hpp" +#include "memory/space.inline.hpp" #include "oops/oop.inline.hpp" +#include "runtime/orderAccess.inline.hpp" PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/g1/vm_operations_g1.cpp --- a/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -226,7 +226,7 @@ void VM_CGC_Operation::doit() { gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps); TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty); - GCTraceTime t(_printGCMessage, G1Log::fine(), true, G1CollectedHeap::heap()->gc_timer_cm()); + GCTraceTime t(_printGCMessage, G1Log::fine(), true, G1CollectedHeap::heap()->gc_timer_cm(), G1CollectedHeap::heap()->concurrent_mark()->concurrent_gc_id()); SharedHeap* sh = SharedHeap::heap(); // This could go away if CollectedHeap gave access to _gc_is_active... if (sh != NULL) { diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp --- a/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -32,6 +32,7 @@ #include "oops/oop.inline.hpp" #include "runtime/java.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/virtualspace.hpp" #include "runtime/vmThread.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/parNew/parNewGeneration.cpp --- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -50,7 +50,7 @@ #include "runtime/handles.hpp" #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" -#include "runtime/thread.hpp" +#include "runtime/thread.inline.hpp" #include "utilities/copy.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/workgroup.hpp" @@ -957,7 +957,7 @@ size_policy->minor_collection_begin(); } - GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL); + GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL, gc_tracer.gc_id()); // Capture heap used before collection (for printing). size_t gch_prev_used = gch->used(); @@ -1015,14 +1015,14 @@ ParNewRefProcTaskExecutor task_executor(*this, thread_state_set); stats = rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers, &task_executor, - _gc_timer); + _gc_timer, gc_tracer.gc_id()); } else { thread_state_set.flush(); gch->set_par_threads(0); // 0 ==> non-parallel. gch->save_marks(); stats = rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers, NULL, - _gc_timer); + _gc_timer, gc_tracer.gc_id()); } gc_tracer.report_gc_reference_stats(stats); if (!promotion_failed()) { diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -30,6 +30,7 @@ #include "gc_implementation/parallelScavenge/psYoungGen.hpp" #include "oops/oop.inline.hpp" #include "oops/oop.psgc.inline.hpp" +#include "runtime/prefetch.inline.hpp" // Checks an individual oop for missing precise marks. Mark // may be either dirty or newgen. diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -30,6 +30,7 @@ #include "memory/allocation.inline.hpp" #include "runtime/mutex.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/orderAccess.inline.hpp" PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -53,7 +53,7 @@ ResourceMark rm; NOT_PRODUCT(GCTraceTime tm("ThreadRootsMarkingTask", - PrintGCDetails && TraceParallelOldGCTasks, true, NULL)); + PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id())); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); @@ -82,7 +82,7 @@ assert(Universe::heap()->is_gc_active(), "called outside gc"); NOT_PRODUCT(GCTraceTime tm("MarkFromRootsTask", - PrintGCDetails && TraceParallelOldGCTasks, true, NULL)); + PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id())); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm); @@ -153,7 +153,7 @@ assert(Universe::heap()->is_gc_active(), "called outside gc"); NOT_PRODUCT(GCTraceTime tm("RefProcTask", - PrintGCDetails && TraceParallelOldGCTasks, true, NULL)); + PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id())); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm); @@ -209,7 +209,7 @@ assert(Universe::heap()->is_gc_active(), "called outside gc"); NOT_PRODUCT(GCTraceTime tm("StealMarkingTask", - PrintGCDetails && TraceParallelOldGCTasks, true, NULL)); + PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id())); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); @@ -242,7 +242,7 @@ assert(Universe::heap()->is_gc_active(), "called outside gc"); NOT_PRODUCT(GCTraceTime tm("StealRegionCompactionTask", - PrintGCDetails && TraceParallelOldGCTasks, true, NULL)); + PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id())); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); @@ -309,7 +309,7 @@ void UpdateDensePrefixTask::do_it(GCTaskManager* manager, uint which) { NOT_PRODUCT(GCTraceTime tm("UpdateDensePrefixTask", - PrintGCDetails && TraceParallelOldGCTasks, true, NULL)); + PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id())); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); @@ -324,7 +324,7 @@ assert(Universe::heap()->is_gc_active(), "called outside gc"); NOT_PRODUCT(GCTraceTime tm("DrainStacksCompactionTask", - PrintGCDetails && TraceParallelOldGCTasks, true, NULL)); + PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id())); ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(which); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -169,7 +169,7 @@ gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL); + GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer->gc_id()); TraceCollectorStats tcs(counters()); TraceMemoryManagerStats tms(true /* Full GC */,gc_cause); @@ -513,7 +513,7 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) { // Recursively traverse all live objects and mark them - GCTraceTime tm("phase 1", PrintGCDetails && Verbose, true, _gc_timer); + GCTraceTime tm("phase 1", PrintGCDetails && Verbose, true, _gc_timer, _gc_tracer->gc_id()); trace(" 1"); ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); @@ -548,7 +548,7 @@ ref_processor()->setup_policy(clear_all_softrefs); const ReferenceProcessorStats& stats = ref_processor()->process_discovered_references( - is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL, _gc_timer); + is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL, _gc_timer, _gc_tracer->gc_id()); gc_tracer()->report_gc_reference_stats(stats); } @@ -574,7 +574,7 @@ void PSMarkSweep::mark_sweep_phase2() { - GCTraceTime tm("phase 2", PrintGCDetails && Verbose, true, _gc_timer); + GCTraceTime tm("phase 2", PrintGCDetails && Verbose, true, _gc_timer, _gc_tracer->gc_id()); trace("2"); // Now all live objects are marked, compute the new object addresses. @@ -604,7 +604,7 @@ void PSMarkSweep::mark_sweep_phase3() { // Adjust the pointers to reflect the new locations - GCTraceTime tm("phase 3", PrintGCDetails && Verbose, true, _gc_timer); + GCTraceTime tm("phase 3", PrintGCDetails && Verbose, true, _gc_timer, _gc_tracer->gc_id()); trace("3"); ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); @@ -647,7 +647,7 @@ void PSMarkSweep::mark_sweep_phase4() { EventMark m("4 compact heap"); - GCTraceTime tm("phase 4", PrintGCDetails && Verbose, true, _gc_timer); + GCTraceTime tm("phase 4", PrintGCDetails && Verbose, true, _gc_timer, _gc_tracer->gc_id()); trace("4"); // All pointers are now adjusted, move objects accordingly diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -32,6 +32,7 @@ #include "gc_implementation/shared/markSweep.inline.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" #include "oops/oop.inline.hpp" +#include "runtime/prefetch.inline.hpp" PSMarkSweepDecorator* PSMarkSweepDecorator::_destination_decorator = NULL; diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -978,7 +978,7 @@ // at each young gen gc. Do the update unconditionally (even though a // promotion failure does not swap spaces) because an unknown number of minor // collections will have swapped the spaces an unknown number of times. - GCTraceTime tm("pre compact", print_phases(), true, &_gc_timer); + GCTraceTime tm("pre compact", print_phases(), true, &_gc_timer, _gc_tracer.gc_id()); ParallelScavengeHeap* heap = gc_heap(); _space_info[from_space_id].set_space(heap->young_gen()->from_space()); _space_info[to_space_id].set_space(heap->young_gen()->to_space()); @@ -1021,7 +1021,7 @@ void PSParallelCompact::post_compact() { - GCTraceTime tm("post compact", print_phases(), true, &_gc_timer); + GCTraceTime tm("post compact", print_phases(), true, &_gc_timer, _gc_tracer.gc_id()); for (unsigned int id = old_space_id; id < last_space_id; ++id) { // Clear the marking bitmap, summary data and split info. @@ -1847,7 +1847,7 @@ void PSParallelCompact::summary_phase(ParCompactionManager* cm, bool maximum_compaction) { - GCTraceTime tm("summary phase", print_phases(), true, &_gc_timer); + GCTraceTime tm("summary phase", print_phases(), true, &_gc_timer, _gc_tracer.gc_id()); // trace("2"); #ifdef ASSERT @@ -2056,7 +2056,7 @@ gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL); + GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer.gc_id()); TraceCollectorStats tcs(counters()); TraceMemoryManagerStats tms(true /* Full GC */,gc_cause); @@ -2351,7 +2351,7 @@ bool maximum_heap_compaction, ParallelOldTracer *gc_tracer) { // Recursively traverse all live objects and mark them - GCTraceTime tm("marking phase", print_phases(), true, &_gc_timer); + GCTraceTime tm("marking phase", print_phases(), true, &_gc_timer, _gc_tracer.gc_id()); ParallelScavengeHeap* heap = gc_heap(); uint parallel_gc_threads = heap->gc_task_manager()->workers(); @@ -2366,7 +2366,7 @@ ClassLoaderDataGraph::clear_claimed_marks(); { - GCTraceTime tm_m("par mark", print_phases(), true, &_gc_timer); + GCTraceTime tm_m("par mark", print_phases(), true, &_gc_timer, _gc_tracer.gc_id()); ParallelScavengeHeap::ParStrongRootsScope psrs; @@ -2395,24 +2395,24 @@ // Process reference objects found during marking { - GCTraceTime tm_r("reference processing", print_phases(), true, &_gc_timer); + GCTraceTime tm_r("reference processing", print_phases(), true, &_gc_timer, _gc_tracer.gc_id()); ReferenceProcessorStats stats; if (ref_processor()->processing_is_mt()) { RefProcTaskExecutor task_executor; stats = ref_processor()->process_discovered_references( is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, - &task_executor, &_gc_timer); + &task_executor, &_gc_timer, _gc_tracer.gc_id()); } else { stats = ref_processor()->process_discovered_references( is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, NULL, - &_gc_timer); + &_gc_timer, _gc_tracer.gc_id()); } gc_tracer->report_gc_reference_stats(stats); } - GCTraceTime tm_c("class unloading", print_phases(), true, &_gc_timer); + GCTraceTime tm_c("class unloading", print_phases(), true, &_gc_timer, _gc_tracer.gc_id()); // This is the point where the entire marking should have completed. assert(cm->marking_stacks_empty(), "Marking should have completed"); @@ -2451,7 +2451,7 @@ void PSParallelCompact::adjust_roots() { // Adjust the pointers to reflect the new locations - GCTraceTime tm("adjust roots", print_phases(), true, &_gc_timer); + GCTraceTime tm("adjust roots", print_phases(), true, &_gc_timer, _gc_tracer.gc_id()); // Need new claim bits when tracing through and adjusting pointers. ClassLoaderDataGraph::clear_claimed_marks(); @@ -2487,7 +2487,7 @@ void PSParallelCompact::enqueue_region_draining_tasks(GCTaskQueue* q, uint parallel_gc_threads) { - GCTraceTime tm("drain task setup", print_phases(), true, &_gc_timer); + GCTraceTime tm("drain task setup", print_phases(), true, &_gc_timer, _gc_tracer.gc_id()); // Find the threads that are active unsigned int which = 0; @@ -2561,7 +2561,7 @@ void PSParallelCompact::enqueue_dense_prefix_tasks(GCTaskQueue* q, uint parallel_gc_threads) { - GCTraceTime tm("dense prefix task setup", print_phases(), true, &_gc_timer); + GCTraceTime tm("dense prefix task setup", print_phases(), true, &_gc_timer, _gc_tracer.gc_id()); ParallelCompactData& sd = PSParallelCompact::summary_data(); @@ -2643,7 +2643,7 @@ GCTaskQueue* q, ParallelTaskTerminator* terminator_ptr, uint parallel_gc_threads) { - GCTraceTime tm("steal task setup", print_phases(), true, &_gc_timer); + GCTraceTime tm("steal task setup", print_phases(), true, &_gc_timer, _gc_tracer.gc_id()); // Once a thread has drained it's stack, it should try to steal regions from // other threads. @@ -2691,7 +2691,7 @@ void PSParallelCompact::compact() { // trace("5"); - GCTraceTime tm("compaction phase", print_phases(), true, &_gc_timer); + GCTraceTime tm("compaction phase", print_phases(), true, &_gc_timer, _gc_tracer.gc_id()); ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); @@ -2708,7 +2708,7 @@ enqueue_region_stealing_tasks(q, &terminator, active_gc_threads); { - GCTraceTime tm_pc("par compact", print_phases(), true, &_gc_timer); + GCTraceTime tm_pc("par compact", print_phases(), true, &_gc_timer, _gc_tracer.gc_id()); gc_task_manager()->execute_and_wait(q); @@ -2722,7 +2722,7 @@ { // Update the deferred objects, if any. Any compaction manager can be used. - GCTraceTime tm_du("deferred updates", print_phases(), true, &_gc_timer); + GCTraceTime tm_du("deferred updates", print_phases(), true, &_gc_timer, _gc_tracer.gc_id()); ParCompactionManager* cm = ParCompactionManager::manager_array(0); for (unsigned int id = old_space_id; id < last_space_id; ++id) { update_deferred_objects(cm, SpaceId(id)); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -1004,6 +1004,10 @@ static bool _dwl_initialized; #endif // #ifdef ASSERT + + public: + static ParallelOldTracer* gc_tracer() { return &_gc_tracer; } + private: static void initialize_space_info(); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -331,7 +331,7 @@ gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - GCTraceTime t1(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL); + GCTraceTime t1(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer.gc_id()); TraceCollectorStats tcs(counters()); TraceMemoryManagerStats tms(false /* not full GC */,gc_cause); @@ -397,7 +397,7 @@ // We'll use the promotion manager again later. PSPromotionManager* promotion_manager = PSPromotionManager::vm_thread_promotion_manager(); { - GCTraceTime tm("Scavenge", false, false, &_gc_timer); + GCTraceTime tm("Scavenge", false, false, &_gc_timer, _gc_tracer.gc_id()); ParallelScavengeHeap::ParStrongRootsScope psrs; GCTaskQueue* q = GCTaskQueue::create(); @@ -439,7 +439,7 @@ // Process reference objects discovered during scavenge { - GCTraceTime tm("References", false, false, &_gc_timer); + GCTraceTime tm("References", false, false, &_gc_timer, _gc_tracer.gc_id()); reference_processor()->setup_policy(false); // not always_clear reference_processor()->set_active_mt_degree(active_workers); @@ -450,10 +450,10 @@ PSRefProcTaskExecutor task_executor; stats = reference_processor()->process_discovered_references( &_is_alive_closure, &keep_alive, &evac_followers, &task_executor, - &_gc_timer); + &_gc_timer, _gc_tracer.gc_id()); } else { stats = reference_processor()->process_discovered_references( - &_is_alive_closure, &keep_alive, &evac_followers, NULL, &_gc_timer); + &_is_alive_closure, &keep_alive, &evac_followers, NULL, &_gc_timer, _gc_tracer.gc_id()); } _gc_tracer.report_gc_reference_stats(stats); @@ -468,7 +468,7 @@ } { - GCTraceTime tm("StringTable", false, false, &_gc_timer); + GCTraceTime tm("StringTable", false, false, &_gc_timer, _gc_tracer.gc_id()); // Unlink any dead interned Strings and process the remaining live ones. PSScavengeRootsClosure root_closure(promotion_manager); StringTable::unlink_or_oops_do(&_is_alive_closure, &root_closure); @@ -638,7 +638,7 @@ NOT_PRODUCT(reference_processor()->verify_no_references_recorded()); { - GCTraceTime tm("Prune Scavenge Root Methods", false, false, &_gc_timer); + GCTraceTime tm("Prune Scavenge Root Methods", false, false, &_gc_timer, _gc_tracer.gc_id()); CodeCache::prune_scavenge_root_nmethods(); } diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/shared/concurrentGCThread.cpp --- a/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -36,21 +36,10 @@ int ConcurrentGCThread::_CGC_flag = CGC_nil; -SuspendibleThreadSet ConcurrentGCThread::_sts; - ConcurrentGCThread::ConcurrentGCThread() : _should_terminate(false), _has_terminated(false) { - _sts.initialize(); }; -void ConcurrentGCThread::safepoint_synchronize() { - _sts.suspend_all(); -} - -void ConcurrentGCThread::safepoint_desynchronize() { - _sts.resume_all(); -} - void ConcurrentGCThread::create_and_start() { if (os::create_thread(this, os::cgc_thread)) { // XXX: need to set this to low priority @@ -91,78 +80,6 @@ ThreadLocalStorage::set_thread(NULL); } - -void SuspendibleThreadSet::initialize_work() { - MutexLocker x(STS_init_lock); - if (!_initialized) { - _m = new Monitor(Mutex::leaf, - "SuspendibleThreadSetLock", true); - _async = 0; - _async_stop = false; - _async_stopped = 0; - _initialized = true; - } -} - -void SuspendibleThreadSet::join() { - initialize(); - MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); - while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag); - _async++; - assert(_async > 0, "Huh."); -} - -void SuspendibleThreadSet::leave() { - assert(_initialized, "Must be initialized."); - MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); - _async--; - assert(_async >= 0, "Huh."); - if (_async_stop) _m->notify_all(); -} - -void SuspendibleThreadSet::yield(const char* id) { - assert(_initialized, "Must be initialized."); - if (_async_stop) { - MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); - if (_async_stop) { - _async_stopped++; - assert(_async_stopped > 0, "Huh."); - if (_async_stopped == _async) { - if (ConcGCYieldTimeout > 0) { - double now = os::elapsedTime(); - guarantee((now - _suspend_all_start) * 1000.0 < - (double)ConcGCYieldTimeout, - "Long delay; whodunit?"); - } - } - _m->notify_all(); - while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag); - _async_stopped--; - assert(_async >= 0, "Huh"); - _m->notify_all(); - } - } -} - -void SuspendibleThreadSet::suspend_all() { - initialize(); // If necessary. - if (ConcGCYieldTimeout > 0) { - _suspend_all_start = os::elapsedTime(); - } - MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); - assert(!_async_stop, "Only one at a time."); - _async_stop = true; - while (_async_stopped < _async) _m->wait(Mutex::_no_safepoint_check_flag); -} - -void SuspendibleThreadSet::resume_all() { - assert(_initialized, "Must be initialized."); - MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); - assert(_async_stopped == _async, "Huh."); - _async_stop = false; - _m->notify_all(); -} - static void _sltLoop(JavaThread* thread, TRAPS) { SurrogateLockerThread* slt = (SurrogateLockerThread*)thread; slt->loop(); @@ -282,30 +199,3 @@ } assert(!_monitor.owned_by_self(), "Should unlock before exit."); } - - -// ===== STS Access From Outside CGCT ===== - -void ConcurrentGCThread::stsYield(const char* id) { - assert( Thread::current()->is_ConcurrentGC_thread(), - "only a conc GC thread can call this" ); - _sts.yield(id); -} - -bool ConcurrentGCThread::stsShouldYield() { - assert( Thread::current()->is_ConcurrentGC_thread(), - "only a conc GC thread can call this" ); - return _sts.should_yield(); -} - -void ConcurrentGCThread::stsJoin() { - assert( Thread::current()->is_ConcurrentGC_thread(), - "only a conc GC thread can call this" ); - _sts.join(); -} - -void ConcurrentGCThread::stsLeave() { - assert( Thread::current()->is_ConcurrentGC_thread(), - "only a conc GC thread can call this" ); - _sts.leave(); -} diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/shared/concurrentGCThread.hpp --- a/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -26,55 +26,8 @@ #define SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS +#include "gc_implementation/shared/suspendibleThreadSet.hpp" #include "runtime/thread.hpp" -#endif // INCLUDE_ALL_GCS - -class VoidClosure; - -// A SuspendibleThreadSet is (obviously) a set of threads that can be -// suspended. A thread can join and later leave the set, and periodically -// yield. If some thread (not in the set) requests, via suspend_all, that -// the threads be suspended, then the requesting thread is blocked until -// all the threads in the set have yielded or left the set. (Threads may -// not enter the set when an attempted suspension is in progress.) The -// suspending thread later calls resume_all, allowing the suspended threads -// to continue. - -class SuspendibleThreadSet { - Monitor* _m; - int _async; - bool _async_stop; - int _async_stopped; - bool _initialized; - double _suspend_all_start; - - void initialize_work(); - - public: - SuspendibleThreadSet() : _initialized(false) {} - - // Add the current thread to the set. May block if a suspension - // is in progress. - void join(); - // Removes the current thread from the set. - void leave(); - // Returns "true" iff an suspension is in progress. - bool should_yield() { return _async_stop; } - // Suspends the current thread if a suspension is in progress (for - // the duration of the suspension.) - void yield(const char* id); - // Return when all threads in the set are suspended. - void suspend_all(); - // Allow suspended threads to resume. - void resume_all(); - // Redundant initializations okay. - void initialize() { - // Double-check dirty read idiom. - if (!_initialized) initialize_work(); - } -}; - class ConcurrentGCThread: public NamedThread { friend class VMStructs; @@ -96,9 +49,6 @@ static int set_CGC_flag(int b) { return _CGC_flag |= b; } static int reset_CGC_flag(int b) { return _CGC_flag &= ~b; } - // All instances share this one set. - static SuspendibleThreadSet _sts; - // Create and start the thread (setting it's priority high.) void create_and_start(); @@ -121,25 +71,6 @@ // Tester bool is_ConcurrentGC_thread() const { return true; } - - static void safepoint_synchronize(); - static void safepoint_desynchronize(); - - // All overridings should probably do _sts::yield, but we allow - // overriding for distinguished debugging messages. Default is to do - // nothing. - virtual void yield() {} - - bool should_yield() { return _sts.should_yield(); } - - // they are prefixed by sts since there are already yield() and - // should_yield() (non-static) methods in this class and it was an - // easy way to differentiate them. - static void stsYield(const char* id); - static bool stsShouldYield(); - static void stsJoin(); - static void stsLeave(); - }; // The SurrogateLockerThread is used by concurrent GC threads for diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/shared/gcId.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_implementation/shared/gcId.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/shared/gcId.hpp" +#include "runtime/safepoint.hpp" + +uint GCId::_next_id = 0; + +const GCId GCId::create() { + return GCId(_next_id++); +} +const GCId GCId::peek() { + return GCId(_next_id); +} +const GCId GCId::undefined() { + return GCId(UNDEFINED); +} +bool GCId::is_undefined() const { + return _id == UNDEFINED; +} diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/shared/gcId.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_implementation/shared/gcId.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCID_HPP +#define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCID_HPP + +#include "memory/allocation.hpp" + +class GCId VALUE_OBJ_CLASS_SPEC { + private: + uint _id; + GCId(uint id) : _id(id) {} + GCId() { } // Unused + + static uint _next_id; + static const uint UNDEFINED = (uint)-1; + + public: + uint id() const { + assert(_id != UNDEFINED, "Using undefined GC ID"); + return _id; + } + bool is_undefined() const; + + static const GCId create(); + static const GCId peek(); + static const GCId undefined(); +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_GCID_HPP diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/shared/gcTrace.cpp --- a/src/share/vm/gc_implementation/shared/gcTrace.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/shared/gcTrace.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "gc_implementation/shared/copyFailedInfo.hpp" #include "gc_implementation/shared/gcHeapSummary.hpp" +#include "gc_implementation/shared/gcId.hpp" #include "gc_implementation/shared/gcTimer.hpp" #include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/objectCountEventSender.hpp" @@ -38,19 +39,14 @@ #include "gc_implementation/g1/evacuationInfo.hpp" #endif -#define assert_unset_gc_id() assert(_shared_gc_info.id() == SharedGCInfo::UNSET_GCID, "GC already started?") -#define assert_set_gc_id() assert(_shared_gc_info.id() != SharedGCInfo::UNSET_GCID, "GC not started?") - -static GCId GCTracer_next_gc_id = 0; -static GCId create_new_gc_id() { - return GCTracer_next_gc_id++; -} +#define assert_unset_gc_id() assert(_shared_gc_info.gc_id().is_undefined(), "GC already started?") +#define assert_set_gc_id() assert(!_shared_gc_info.gc_id().is_undefined(), "GC not started?") void GCTracer::report_gc_start_impl(GCCause::Cause cause, const Ticks& timestamp) { assert_unset_gc_id(); - GCId gc_id = create_new_gc_id(); - _shared_gc_info.set_id(gc_id); + GCId gc_id = GCId::create(); + _shared_gc_info.set_gc_id(gc_id); _shared_gc_info.set_cause(cause); _shared_gc_info.set_start_timestamp(timestamp); } @@ -62,7 +58,7 @@ } bool GCTracer::has_reported_gc_start() const { - return _shared_gc_info.id() != SharedGCInfo::UNSET_GCID; + return !_shared_gc_info.gc_id().is_undefined(); } void GCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) { @@ -81,7 +77,7 @@ report_gc_end_impl(timestamp, time_partitions); - _shared_gc_info.set_id(SharedGCInfo::UNSET_GCID); + _shared_gc_info.set_gc_id(GCId::undefined()); } void GCTracer::report_gc_reference_stats(const ReferenceProcessorStats& rps) const { @@ -132,7 +128,7 @@ if (!cit.allocation_failed()) { HeapInspection hi(false, false, false, NULL); hi.populate_table(&cit, is_alive_cl); - ObjectCountEventSenderClosure event_sender(_shared_gc_info.id(), cit.size_of_instances_in_words(), Ticks::now()); + ObjectCountEventSenderClosure event_sender(_shared_gc_info.gc_id(), cit.size_of_instances_in_words(), Ticks::now()); cit.iterate(&event_sender); } } diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/shared/gcTrace.hpp --- a/src/share/vm/gc_implementation/shared/gcTrace.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/shared/gcTrace.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -27,6 +27,7 @@ #include "gc_interface/gcCause.hpp" #include "gc_interface/gcName.hpp" +#include "gc_implementation/shared/gcId.hpp" #include "gc_implementation/shared/gcWhen.hpp" #include "gc_implementation/shared/copyFailedInfo.hpp" #include "memory/allocation.hpp" @@ -38,7 +39,6 @@ #include "utilities/macros.hpp" #include "utilities/ticks.hpp" -typedef uint GCId; class EvacuationInfo; class GCHeapSummary; @@ -50,11 +50,8 @@ class BoolObjectClosure; class SharedGCInfo VALUE_OBJ_CLASS_SPEC { - public: - static const GCId UNSET_GCID = (GCId)-1; - private: - GCId _id; + GCId _gc_id; GCName _name; GCCause::Cause _cause; Ticks _start_timestamp; @@ -64,7 +61,7 @@ public: SharedGCInfo(GCName name) : - _id(UNSET_GCID), + _gc_id(GCId::undefined()), _name(name), _cause(GCCause::_last_gc_cause), _start_timestamp(), @@ -73,8 +70,8 @@ _longest_pause() { } - void set_id(GCId id) { _id = id; } - GCId id() const { return _id; } + void set_gc_id(GCId gc_id) { _gc_id = gc_id; } + const GCId& gc_id() const { return _gc_id; } void set_start_timestamp(const Ticks& timestamp) { _start_timestamp = timestamp; } const Ticks start_timestamp() const { return _start_timestamp; } @@ -131,10 +128,11 @@ void report_gc_reference_stats(const ReferenceProcessorStats& rp) const; void report_object_count_after_gc(BoolObjectClosure* object_filter) NOT_SERVICES_RETURN; bool has_reported_gc_start() const; + const GCId& gc_id() { return _shared_gc_info.gc_id(); } protected: GCTracer(GCName name) : _shared_gc_info(name) {} - virtual void report_gc_start_impl(GCCause::Cause cause, const Ticks& timestamp); + void report_gc_start_impl(GCCause::Cause cause, const Ticks& timestamp); virtual void report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions); private: diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/shared/gcTraceSend.cpp --- a/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -43,7 +43,7 @@ void GCTracer::send_garbage_collection_event() const { EventGCGarbageCollection event(UNTIMED); if (event.should_commit()) { - event.set_gcId(_shared_gc_info.id()); + event.set_gcId(_shared_gc_info.gc_id().id()); event.set_name(_shared_gc_info.name()); event.set_cause((u2) _shared_gc_info.cause()); event.set_sumOfPauses(_shared_gc_info.sum_of_pauses()); @@ -57,7 +57,7 @@ void GCTracer::send_reference_stats_event(ReferenceType type, size_t count) const { EventGCReferenceStatistics e; if (e.should_commit()) { - e.set_gcId(_shared_gc_info.id()); + e.set_gcId(_shared_gc_info.gc_id().id()); e.set_type((u1)type); e.set_count(count); e.commit(); @@ -68,7 +68,7 @@ const MetaspaceChunkFreeListSummary& summary) const { EventMetaspaceChunkFreeListSummary e; if (e.should_commit()) { - e.set_gcId(_shared_gc_info.id()); + e.set_gcId(_shared_gc_info.gc_id().id()); e.set_when(when); e.set_metadataType(mdtype); @@ -91,7 +91,7 @@ void ParallelOldTracer::send_parallel_old_event() const { EventGCParallelOld e(UNTIMED); if (e.should_commit()) { - e.set_gcId(_shared_gc_info.id()); + e.set_gcId(_shared_gc_info.gc_id().id()); e.set_densePrefix((TraceAddress)_parallel_old_gc_info.dense_prefix()); e.set_starttime(_shared_gc_info.start_timestamp()); e.set_endtime(_shared_gc_info.end_timestamp()); @@ -102,7 +102,7 @@ void YoungGCTracer::send_young_gc_event() const { EventGCYoungGarbageCollection e(UNTIMED); if (e.should_commit()) { - e.set_gcId(_shared_gc_info.id()); + e.set_gcId(_shared_gc_info.gc_id().id()); e.set_tenuringThreshold(_tenuring_threshold); e.set_starttime(_shared_gc_info.start_timestamp()); e.set_endtime(_shared_gc_info.end_timestamp()); @@ -113,7 +113,7 @@ void OldGCTracer::send_old_gc_event() const { EventGCOldGarbageCollection e(UNTIMED); if (e.should_commit()) { - e.set_gcId(_shared_gc_info.id()); + e.set_gcId(_shared_gc_info.gc_id().id()); e.set_starttime(_shared_gc_info.start_timestamp()); e.set_endtime(_shared_gc_info.end_timestamp()); e.commit(); @@ -132,7 +132,7 @@ void YoungGCTracer::send_promotion_failed_event(const PromotionFailedInfo& pf_info) const { EventPromotionFailed e; if (e.should_commit()) { - e.set_gcId(_shared_gc_info.id()); + e.set_gcId(_shared_gc_info.gc_id().id()); e.set_data(to_trace_struct(pf_info)); e.set_thread(pf_info.thread()->thread_id()); e.commit(); @@ -143,7 +143,7 @@ void OldGCTracer::send_concurrent_mode_failure_event() { EventConcurrentModeFailure e; if (e.should_commit()) { - e.set_gcId(_shared_gc_info.id()); + e.set_gcId(_shared_gc_info.gc_id().id()); e.commit(); } } @@ -152,7 +152,7 @@ void G1NewTracer::send_g1_young_gc_event() { EventGCG1GarbageCollection e(UNTIMED); if (e.should_commit()) { - e.set_gcId(_shared_gc_info.id()); + e.set_gcId(_shared_gc_info.gc_id().id()); e.set_type(_g1_young_gc_info.type()); e.set_starttime(_shared_gc_info.start_timestamp()); e.set_endtime(_shared_gc_info.end_timestamp()); @@ -163,7 +163,7 @@ void G1NewTracer::send_evacuation_info_event(EvacuationInfo* info) { EventEvacuationInfo e; if (e.should_commit()) { - e.set_gcId(_shared_gc_info.id()); + e.set_gcId(_shared_gc_info.gc_id().id()); e.set_cSetRegions(info->collectionset_regions()); e.set_cSetUsedBefore(info->collectionset_used_before()); e.set_cSetUsedAfter(info->collectionset_used_after()); @@ -179,7 +179,7 @@ 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_gcId(_shared_gc_info.gc_id().id()); e.set_data(to_trace_struct(ef_info)); e.commit(); } @@ -206,17 +206,17 @@ } class GCHeapSummaryEventSender : public GCHeapSummaryVisitor { - GCId _id; + GCId _gc_id; GCWhen::Type _when; public: - GCHeapSummaryEventSender(GCId id, GCWhen::Type when) : _id(id), _when(when) {} + GCHeapSummaryEventSender(GCId gc_id, GCWhen::Type when) : _gc_id(gc_id), _when(when) {} void visit(const GCHeapSummary* heap_summary) const { const VirtualSpaceSummary& heap_space = heap_summary->heap(); EventGCHeapSummary e; if (e.should_commit()) { - e.set_gcId(_id); + e.set_gcId(_gc_id.id()); e.set_when((u1)_when); e.set_heapSpace(to_trace_struct(heap_space)); e.set_heapUsed(heap_summary->used()); @@ -236,7 +236,7 @@ EventPSHeapSummary e; if (e.should_commit()) { - e.set_gcId(_id); + e.set_gcId(_gc_id.id()); e.set_when((u1)_when); e.set_oldSpace(to_trace_struct(ps_heap_summary->old())); @@ -251,7 +251,7 @@ }; void GCTracer::send_gc_heap_summary_event(GCWhen::Type when, const GCHeapSummary& heap_summary) const { - GCHeapSummaryEventSender visitor(_shared_gc_info.id(), when); + GCHeapSummaryEventSender visitor(_shared_gc_info.gc_id(), when); heap_summary.accept(&visitor); } @@ -268,7 +268,7 @@ void GCTracer::send_meta_space_summary_event(GCWhen::Type when, const MetaspaceSummary& meta_space_summary) const { EventMetaspaceSummary e; if (e.should_commit()) { - e.set_gcId(_shared_gc_info.id()); + e.set_gcId(_shared_gc_info.gc_id().id()); e.set_when((u1) when); e.set_gcThreshold(meta_space_summary.capacity_until_GC()); e.set_metaspace(to_trace_struct(meta_space_summary.meta_space())); @@ -287,7 +287,7 @@ void send_phase(PausePhase* pause) { T event(UNTIMED); if (event.should_commit()) { - event.set_gcId(_gc_id); + event.set_gcId(_gc_id.id()); event.set_name(pause->name()); event.set_starttime(pause->start()); event.set_endtime(pause->end()); @@ -311,7 +311,7 @@ }; void GCTracer::send_phase_events(TimePartitions* time_partitions) const { - PhaseSender phase_reporter(_shared_gc_info.id()); + PhaseSender phase_reporter(_shared_gc_info.gc_id()); TimePartitionPhasesIterator iter(time_partitions); while (iter.has_next()) { diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/shared/gcTraceTime.cpp --- a/src/share/vm/gc_implementation/shared/gcTraceTime.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/shared/gcTraceTime.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc_implementation/shared/gcTimer.hpp" +#include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/gcTraceTime.hpp" #include "runtime/globals.hpp" #include "runtime/os.hpp" @@ -34,7 +35,7 @@ #include "utilities/ticks.inline.hpp" -GCTraceTime::GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer) : +GCTraceTime::GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer, GCId gc_id) : _title(title), _doit(doit), _print_cr(print_cr), _timer(timer), _start_counter() { if (_doit || _timer != NULL) { _start_counter.stamp(); @@ -52,6 +53,9 @@ gclog_or_tty->stamp(); gclog_or_tty->print(": "); } + if (PrintGCID) { + gclog_or_tty->print("#%u: ", gc_id.id()); + } gclog_or_tty->print("[%s", title); gclog_or_tty->flush(); } diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/shared/gcTraceTime.hpp --- a/src/share/vm/gc_implementation/shared/gcTraceTime.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/shared/gcTraceTime.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTRACETIME_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTRACETIME_HPP +#include "gc_implementation/shared/gcTrace.hpp" #include "prims/jni_md.h" #include "utilities/ticks.hpp" @@ -38,7 +39,7 @@ Ticks _start_counter; public: - GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer); + GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer, GCId gc_id); ~GCTraceTime(); }; diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/shared/objectCountEventSender.cpp --- a/src/share/vm/gc_implementation/shared/objectCountEventSender.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_implementation/shared/objectCountEventSender.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -24,6 +24,7 @@ #include "precompiled.hpp" +#include "gc_implementation/shared/gcId.hpp" #include "gc_implementation/shared/objectCountEventSender.hpp" #include "memory/heapInspection.hpp" #include "trace/tracing.hpp" @@ -38,7 +39,7 @@ "Only call this method if the event is enabled"); EventObjectCountAfterGC event(UNTIMED); - event.set_gcId(gc_id); + event.set_gcId(gc_id.id()); event.set_class(entry->klass()); event.set_count(entry->count()); event.set_totalSize(entry->words() * BytesPerWord); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/shared/suspendibleThreadSet.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_implementation/shared/suspendibleThreadSet.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/shared/suspendibleThreadSet.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/thread.inline.hpp" + +uint SuspendibleThreadSet::_nthreads = 0; +uint SuspendibleThreadSet::_nthreads_stopped = 0; +bool SuspendibleThreadSet::_suspend_all = false; +double SuspendibleThreadSet::_suspend_all_start = 0.0; + +void SuspendibleThreadSet::join() { + MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); + while (_suspend_all) { + ml.wait(Mutex::_no_safepoint_check_flag); + } + _nthreads++; +} + +void SuspendibleThreadSet::leave() { + MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); + assert(_nthreads > 0, "Invalid"); + _nthreads--; + if (_suspend_all) { + ml.notify_all(); + } +} + +void SuspendibleThreadSet::yield() { + if (_suspend_all) { + MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); + if (_suspend_all) { + _nthreads_stopped++; + if (_nthreads_stopped == _nthreads) { + if (ConcGCYieldTimeout > 0) { + double now = os::elapsedTime(); + guarantee((now - _suspend_all_start) * 1000.0 < (double)ConcGCYieldTimeout, "Long delay"); + } + } + ml.notify_all(); + while (_suspend_all) { + ml.wait(Mutex::_no_safepoint_check_flag); + } + assert(_nthreads_stopped > 0, "Invalid"); + _nthreads_stopped--; + ml.notify_all(); + } + } +} + +void SuspendibleThreadSet::synchronize() { + assert(Thread::current()->is_VM_thread(), "Must be the VM thread"); + if (ConcGCYieldTimeout > 0) { + _suspend_all_start = os::elapsedTime(); + } + MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); + assert(!_suspend_all, "Only one at a time"); + _suspend_all = true; + while (_nthreads_stopped < _nthreads) { + ml.wait(Mutex::_no_safepoint_check_flag); + } +} + +void SuspendibleThreadSet::desynchronize() { + assert(Thread::current()->is_VM_thread(), "Must be the VM thread"); + MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag); + assert(_nthreads_stopped == _nthreads, "Invalid"); + _suspend_all = false; + ml.notify_all(); +} diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_implementation/shared/suspendibleThreadSet.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_implementation/shared/suspendibleThreadSet.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP +#define SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP + +#include "memory/allocation.hpp" + +// A SuspendibleThreadSet is a set of threads that can be suspended. +// A thread can join and later leave the set, and periodically yield. +// If some thread (not in the set) requests, via synchronize(), that +// the threads be suspended, then the requesting thread is blocked +// until all the threads in the set have yielded or left the set. Threads +// may not enter the set when an attempted suspension is in progress. The +// suspending thread later calls desynchronize(), allowing the suspended +// threads to continue. +class SuspendibleThreadSet : public AllStatic { +private: + static uint _nthreads; + static uint _nthreads_stopped; + static bool _suspend_all; + static double _suspend_all_start; + +public: + // Add the current thread to the set. May block if a suspension is in progress. + static void join(); + + // Removes the current thread from the set. + static void leave(); + + // Returns true if an suspension is in progress. + static bool should_yield() { return _suspend_all; } + + // Suspends the current thread if a suspension is in progress. + static void yield(); + + // Returns when all threads in the set are suspended. + static void synchronize(); + + // Resumes all suspended threads in the set. + static void desynchronize(); +}; + +class SuspendibleThreadSetJoiner : public StackObj { +public: + SuspendibleThreadSetJoiner() { + SuspendibleThreadSet::join(); + } + + ~SuspendibleThreadSetJoiner() { + SuspendibleThreadSet::leave(); + } + + bool should_yield() { + return SuspendibleThreadSet::should_yield(); + } + + void yield() { + SuspendibleThreadSet::yield(); + } +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/gc_interface/collectedHeap.cpp --- a/src/share/vm/gc_interface/collectedHeap.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/gc_interface/collectedHeap.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -558,13 +558,13 @@ void CollectedHeap::pre_full_gc_dump(GCTimer* timer) { if (HeapDumpBeforeFullGC) { - GCTraceTime tt("Heap Dump (before full gc): ", PrintGCDetails, false, timer); + GCTraceTime tt("Heap Dump (before full gc): ", PrintGCDetails, false, timer, GCId::create()); // We are doing a "major" collection and a heap dump before // major collection has been requested. HeapDumper::dump_heap(); } if (PrintClassHistogramBeforeFullGC) { - GCTraceTime tt("Class Histogram (before full gc): ", PrintGCDetails, true, timer); + GCTraceTime tt("Class Histogram (before full gc): ", PrintGCDetails, true, timer, GCId::create()); VM_GC_HeapInspection inspector(gclog_or_tty, false /* ! full gc */); inspector.doit(); } @@ -572,11 +572,11 @@ void CollectedHeap::post_full_gc_dump(GCTimer* timer) { if (HeapDumpAfterFullGC) { - GCTraceTime tt("Heap Dump (after full gc): ", PrintGCDetails, false, timer); + GCTraceTime tt("Heap Dump (after full gc): ", PrintGCDetails, false, timer, GCId::create()); HeapDumper::dump_heap(); } if (PrintClassHistogramAfterFullGC) { - GCTraceTime tt("Class Histogram (after full gc): ", PrintGCDetails, true, timer); + GCTraceTime tt("Class Histogram (after full gc): ", PrintGCDetails, true, timer, GCId::create()); VM_GC_HeapInspection inspector(gclog_or_tty, false /* ! full gc */); inspector.doit(); } diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/interpreter/bytecodeInterpreter.cpp --- a/src/share/vm/interpreter/bytecodeInterpreter.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -41,43 +41,10 @@ #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/threadCritical.hpp" #include "utilities/exceptions.hpp" -#ifdef TARGET_OS_ARCH_linux_x86 -# include "orderAccess_linux_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_sparc -# include "orderAccess_linux_sparc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_zero -# include "orderAccess_linux_zero.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_solaris_x86 -# include "orderAccess_solaris_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_solaris_sparc -# include "orderAccess_solaris_sparc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_windows_x86 -# include "orderAccess_windows_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_arm -# include "orderAccess_linux_arm.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_ppc -# include "orderAccess_linux_ppc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_aix_ppc -# include "orderAccess_aix_ppc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_bsd_x86 -# include "orderAccess_bsd_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_bsd_zero -# include "orderAccess_bsd_zero.inline.hpp" -#endif - // no precompiled headers #ifdef CC_INTERP diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/memory/defNewGeneration.cpp --- a/src/share/vm/memory/defNewGeneration.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/memory/defNewGeneration.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -42,6 +42,7 @@ #include "oops/instanceRefKlass.hpp" #include "oops/oop.inline.hpp" #include "runtime/java.hpp" +#include "runtime/prefetch.inline.hpp" #include "runtime/thread.inline.hpp" #include "utilities/copy.hpp" #include "utilities/stack.inline.hpp" @@ -584,7 +585,7 @@ init_assuming_no_promotion_failure(); - GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL); + GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL, gc_tracer.gc_id()); // Capture heap used before collection (for printing). size_t gch_prev_used = gch->used(); @@ -642,7 +643,7 @@ rp->setup_policy(clear_all_soft_refs); const ReferenceProcessorStats& stats = rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers, - NULL, _gc_timer); + NULL, _gc_timer, gc_tracer.gc_id()); gc_tracer.report_gc_reference_stats(stats); if (!_promotion_failed) { diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/memory/gcLocker.cpp --- a/src/share/vm/memory/gcLocker.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/memory/gcLocker.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -26,6 +26,7 @@ #include "memory/gcLocker.inline.hpp" #include "memory/resourceArea.hpp" #include "memory/sharedHeap.hpp" +#include "runtime/thread.inline.hpp" volatile jint GC_locker::_jni_lock_count = 0; volatile bool GC_locker::_needs_gc = false; diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/memory/genCollectedHeap.cpp --- a/src/share/vm/memory/genCollectedHeap.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/memory/genCollectedHeap.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -28,6 +28,7 @@ #include "classfile/vmSymbols.hpp" #include "code/icBuffer.hpp" #include "gc_implementation/shared/collectorCounters.hpp" +#include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/gcTraceTime.hpp" #include "gc_implementation/shared/vmGCOperations.hpp" #include "gc_interface/collectedHeap.inline.hpp" @@ -385,7 +386,9 @@ const char* gc_cause_prefix = complete ? "Full GC" : "GC"; gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); - GCTraceTime t(GCCauseString(gc_cause_prefix, gc_cause()), PrintGCDetails, false, NULL); + // The PrintGCDetails logging starts before we have incremented the GC id. We will do that later + // so we can assume here that the next GC id is what we want. + GCTraceTime t(GCCauseString(gc_cause_prefix, gc_cause()), PrintGCDetails, false, NULL, GCId::peek()); gc_prologue(complete); increment_total_collections(complete); @@ -418,7 +421,9 @@ } // Timer for individual generations. Last argument is false: no CR // FIXME: We should try to start the timing earlier to cover more of the GC pause - GCTraceTime t1(_gens[i]->short_name(), PrintGCDetails, false, NULL); + // The PrintGCDetails logging starts before we have incremented the GC id. We will do that later + // so we can assume here that the next GC id is what we want. + GCTraceTime t1(_gens[i]->short_name(), PrintGCDetails, false, NULL, GCId::peek()); TraceCollectorStats tcs(_gens[i]->counters()); TraceMemoryManagerStats tmms(_gens[i]->kind(),gc_cause()); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/memory/genMarkSweep.cpp --- a/src/share/vm/memory/genMarkSweep.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/memory/genMarkSweep.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -69,7 +69,7 @@ _ref_processor = rp; rp->setup_policy(clear_all_softrefs); - GCTraceTime t1(GCCauseString("Full GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL); + GCTraceTime t1(GCCauseString("Full GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL, _gc_tracer->gc_id()); gch->trace_heap_before_gc(_gc_tracer); @@ -193,7 +193,7 @@ void GenMarkSweep::mark_sweep_phase1(int level, bool clear_all_softrefs) { // Recursively traverse all live objects and mark them - GCTraceTime tm("phase 1", PrintGC && Verbose, true, _gc_timer); + GCTraceTime tm("phase 1", PrintGC && Verbose, true, _gc_timer, _gc_tracer->gc_id()); trace(" 1"); GenCollectedHeap* gch = GenCollectedHeap::heap(); @@ -222,7 +222,7 @@ ref_processor()->setup_policy(clear_all_softrefs); const ReferenceProcessorStats& stats = ref_processor()->process_discovered_references( - &is_alive, &keep_alive, &follow_stack_closure, NULL, _gc_timer); + &is_alive, &keep_alive, &follow_stack_closure, NULL, _gc_timer, _gc_tracer->gc_id()); gc_tracer()->report_gc_reference_stats(stats); } @@ -264,7 +264,7 @@ GenCollectedHeap* gch = GenCollectedHeap::heap(); - GCTraceTime tm("phase 2", PrintGC && Verbose, true, _gc_timer); + GCTraceTime tm("phase 2", PrintGC && Verbose, true, _gc_timer, _gc_tracer->gc_id()); trace("2"); gch->prepare_for_compaction(); @@ -281,7 +281,7 @@ GenCollectedHeap* gch = GenCollectedHeap::heap(); // Adjust the pointers to reflect the new locations - GCTraceTime tm("phase 3", PrintGC && Verbose, true, _gc_timer); + GCTraceTime tm("phase 3", PrintGC && Verbose, true, _gc_timer, _gc_tracer->gc_id()); trace("3"); // Need new claim bits for the pointer adjustment tracing. @@ -336,7 +336,7 @@ // to use a higher index (saved from phase2) when verifying perm_gen. GenCollectedHeap* gch = GenCollectedHeap::heap(); - GCTraceTime tm("phase 4", PrintGC && Verbose, true, _gc_timer); + GCTraceTime tm("phase 4", PrintGC && Verbose, true, _gc_timer, _gc_tracer->gc_id()); trace("4"); GenCompactClosure blk; diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/memory/metaspace.cpp --- a/src/share/vm/memory/metaspace.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/memory/metaspace.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -42,7 +42,7 @@ #include "runtime/init.hpp" #include "runtime/java.hpp" #include "runtime/mutex.hpp" -#include "runtime/orderAccess.hpp" +#include "runtime/orderAccess.inline.hpp" #include "services/memTracker.hpp" #include "services/memoryService.hpp" #include "utilities/copy.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/memory/referenceProcessor.cpp --- a/src/share/vm/memory/referenceProcessor.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/memory/referenceProcessor.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -190,7 +190,8 @@ OopClosure* keep_alive, VoidClosure* complete_gc, AbstractRefProcTaskExecutor* task_executor, - GCTimer* gc_timer) { + GCTimer* gc_timer, + GCId gc_id) { NOT_PRODUCT(verify_ok_to_handle_reflists()); assert(!enqueuing_is_done(), "If here enqueuing should not be complete"); @@ -212,7 +213,7 @@ // Soft references size_t soft_count = 0; { - GCTraceTime tt("SoftReference", trace_time, false, gc_timer); + GCTraceTime tt("SoftReference", trace_time, false, gc_timer, gc_id); soft_count = process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true, is_alive, keep_alive, complete_gc, task_executor); @@ -223,7 +224,7 @@ // Weak references size_t weak_count = 0; { - GCTraceTime tt("WeakReference", trace_time, false, gc_timer); + GCTraceTime tt("WeakReference", trace_time, false, gc_timer, gc_id); weak_count = process_discovered_reflist(_discoveredWeakRefs, NULL, true, is_alive, keep_alive, complete_gc, task_executor); @@ -232,7 +233,7 @@ // Final references size_t final_count = 0; { - GCTraceTime tt("FinalReference", trace_time, false, gc_timer); + GCTraceTime tt("FinalReference", trace_time, false, gc_timer, gc_id); final_count = process_discovered_reflist(_discoveredFinalRefs, NULL, false, is_alive, keep_alive, complete_gc, task_executor); @@ -241,7 +242,7 @@ // Phantom references size_t phantom_count = 0; { - GCTraceTime tt("PhantomReference", trace_time, false, gc_timer); + GCTraceTime tt("PhantomReference", trace_time, false, gc_timer, gc_id); phantom_count = process_discovered_reflist(_discoveredPhantomRefs, NULL, false, is_alive, keep_alive, complete_gc, task_executor); @@ -253,7 +254,7 @@ // thus use JNI weak references to circumvent the phantom references and // resurrect a "post-mortem" object. { - GCTraceTime tt("JNI Weak Reference", trace_time, false, gc_timer); + GCTraceTime tt("JNI Weak Reference", trace_time, false, gc_timer, gc_id); if (task_executor != NULL) { task_executor->set_single_threaded_mode(); } @@ -1251,14 +1252,15 @@ OopClosure* keep_alive, VoidClosure* complete_gc, YieldClosure* yield, - GCTimer* gc_timer) { + GCTimer* gc_timer, + GCId gc_id) { NOT_PRODUCT(verify_ok_to_handle_reflists()); // Soft references { GCTraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC, - false, gc_timer); + false, gc_timer, gc_id); for (uint i = 0; i < _max_num_q; i++) { if (yield->should_return()) { return; @@ -1271,7 +1273,7 @@ // Weak references { GCTraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC, - false, gc_timer); + false, gc_timer, gc_id); for (uint i = 0; i < _max_num_q; i++) { if (yield->should_return()) { return; @@ -1284,7 +1286,7 @@ // Final references { GCTraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC, - false, gc_timer); + false, gc_timer, gc_id); for (uint i = 0; i < _max_num_q; i++) { if (yield->should_return()) { return; @@ -1297,7 +1299,7 @@ // Phantom references { GCTraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC, - false, gc_timer); + false, gc_timer, gc_id); for (uint i = 0; i < _max_num_q; i++) { if (yield->should_return()) { return; diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/memory/referenceProcessor.hpp --- a/src/share/vm/memory/referenceProcessor.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/memory/referenceProcessor.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_MEMORY_REFERENCEPROCESSOR_HPP #define SHARE_VM_MEMORY_REFERENCEPROCESSOR_HPP +#include "gc_implementation/shared/gcTrace.hpp" #include "memory/referencePolicy.hpp" #include "memory/referenceProcessorStats.hpp" #include "memory/referenceType.hpp" @@ -349,7 +350,8 @@ OopClosure* keep_alive, VoidClosure* complete_gc, YieldClosure* yield, - GCTimer* gc_timer); + GCTimer* gc_timer, + GCId gc_id); // Delete entries in the discovered lists that have // either a null referent or are not active. Such @@ -480,7 +482,8 @@ OopClosure* keep_alive, VoidClosure* complete_gc, AbstractRefProcTaskExecutor* task_executor, - GCTimer *gc_timer); + GCTimer *gc_timer, + GCId gc_id); // Enqueue references at end of GC (called by the garbage collector) bool enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor = NULL); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/memory/space.cpp --- a/src/share/vm/memory/space.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/memory/space.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -37,6 +37,8 @@ #include "oops/oop.inline.hpp" #include "oops/oop.inline2.hpp" #include "runtime/java.hpp" +#include "runtime/prefetch.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/safepoint.hpp" #include "utilities/copy.hpp" #include "utilities/globalDefinitions.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/memory/space.hpp --- a/src/share/vm/memory/space.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/memory/space.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -33,24 +33,8 @@ #include "memory/watermark.hpp" #include "oops/markOop.hpp" #include "runtime/mutexLocker.hpp" -#include "runtime/prefetch.hpp" #include "utilities/macros.hpp" #include "utilities/workgroup.hpp" -#ifdef TARGET_OS_FAMILY_linux -# include "os_linux.inline.hpp" -#endif -#ifdef TARGET_OS_FAMILY_solaris -# include "os_solaris.inline.hpp" -#endif -#ifdef TARGET_OS_FAMILY_windows -# include "os_windows.inline.hpp" -#endif -#ifdef TARGET_OS_FAMILY_aix -# include "os_aix.inline.hpp" -#endif -#ifdef TARGET_OS_FAMILY_bsd -# include "os_bsd.inline.hpp" -#endif // A space is an abstraction for the "storage units" backing // up the generation abstraction. It includes specific @@ -512,272 +496,6 @@ size_t word_len); }; -#define SCAN_AND_FORWARD(cp,scan_limit,block_is_obj,block_size) { \ - /* Compute the new addresses for the live objects and store it in the mark \ - * Used by universe::mark_sweep_phase2() \ - */ \ - HeapWord* compact_top; /* This is where we are currently compacting to. */ \ - \ - /* We're sure to be here before any objects are compacted into this \ - * space, so this is a good time to initialize this: \ - */ \ - set_compaction_top(bottom()); \ - \ - if (cp->space == NULL) { \ - assert(cp->gen != NULL, "need a generation"); \ - assert(cp->threshold == NULL, "just checking"); \ - assert(cp->gen->first_compaction_space() == this, "just checking"); \ - cp->space = cp->gen->first_compaction_space(); \ - compact_top = cp->space->bottom(); \ - cp->space->set_compaction_top(compact_top); \ - cp->threshold = cp->space->initialize_threshold(); \ - } else { \ - compact_top = cp->space->compaction_top(); \ - } \ - \ - /* We allow some amount of garbage towards the bottom of the space, so \ - * we don't start compacting before there is a significant gain to be made.\ - * Occasionally, we want to ensure a full compaction, which is determined \ - * by the MarkSweepAlwaysCompactCount parameter. \ - */ \ - uint invocations = MarkSweep::total_invocations(); \ - bool skip_dead = ((invocations % MarkSweepAlwaysCompactCount) != 0); \ - \ - size_t allowed_deadspace = 0; \ - if (skip_dead) { \ - const size_t ratio = allowed_dead_ratio(); \ - allowed_deadspace = (capacity() * ratio / 100) / HeapWordSize; \ - } \ - \ - HeapWord* q = bottom(); \ - HeapWord* t = scan_limit(); \ - \ - HeapWord* end_of_live= q; /* One byte beyond the last byte of the last \ - live object. */ \ - HeapWord* first_dead = end();/* The first dead object. */ \ - LiveRange* liveRange = NULL; /* The current live range, recorded in the \ - first header of preceding free area. */ \ - _first_dead = first_dead; \ - \ - const intx interval = PrefetchScanIntervalInBytes; \ - \ - while (q < t) { \ - assert(!block_is_obj(q) || \ - oop(q)->mark()->is_marked() || oop(q)->mark()->is_unlocked() || \ - oop(q)->mark()->has_bias_pattern(), \ - "these are the only valid states during a mark sweep"); \ - if (block_is_obj(q) && oop(q)->is_gc_marked()) { \ - /* prefetch beyond q */ \ - Prefetch::write(q, interval); \ - size_t size = block_size(q); \ - compact_top = cp->space->forward(oop(q), size, cp, compact_top); \ - q += size; \ - end_of_live = q; \ - } else { \ - /* run over all the contiguous dead objects */ \ - HeapWord* end = q; \ - do { \ - /* prefetch beyond end */ \ - Prefetch::write(end, interval); \ - end += block_size(end); \ - } while (end < t && (!block_is_obj(end) || !oop(end)->is_gc_marked()));\ - \ - /* see if we might want to pretend this object is alive so that \ - * we don't have to compact quite as often. \ - */ \ - if (allowed_deadspace > 0 && q == compact_top) { \ - size_t sz = pointer_delta(end, q); \ - if (insert_deadspace(allowed_deadspace, q, sz)) { \ - compact_top = cp->space->forward(oop(q), sz, cp, compact_top); \ - q = end; \ - end_of_live = end; \ - continue; \ - } \ - } \ - \ - /* otherwise, it really is a free region. */ \ - \ - /* for the previous LiveRange, record the end of the live objects. */ \ - if (liveRange) { \ - liveRange->set_end(q); \ - } \ - \ - /* record the current LiveRange object. \ - * liveRange->start() is overlaid on the mark word. \ - */ \ - liveRange = (LiveRange*)q; \ - liveRange->set_start(end); \ - liveRange->set_end(end); \ - \ - /* see if this is the first dead region. */ \ - if (q < first_dead) { \ - first_dead = q; \ - } \ - \ - /* move on to the next object */ \ - q = end; \ - } \ - } \ - \ - assert(q == t, "just checking"); \ - if (liveRange != NULL) { \ - liveRange->set_end(q); \ - } \ - _end_of_live = end_of_live; \ - if (end_of_live < first_dead) { \ - first_dead = end_of_live; \ - } \ - _first_dead = first_dead; \ - \ - /* save the compaction_top of the compaction space. */ \ - cp->space->set_compaction_top(compact_top); \ -} - -#define SCAN_AND_ADJUST_POINTERS(adjust_obj_size) { \ - /* adjust all the interior pointers to point at the new locations of objects \ - * Used by MarkSweep::mark_sweep_phase3() */ \ - \ - HeapWord* q = bottom(); \ - HeapWord* t = _end_of_live; /* Established by "prepare_for_compaction". */ \ - \ - assert(_first_dead <= _end_of_live, "Stands to reason, no?"); \ - \ - if (q < t && _first_dead > q && \ - !oop(q)->is_gc_marked()) { \ - /* we have a chunk of the space which hasn't moved and we've \ - * reinitialized the mark word during the previous pass, so we can't \ - * use is_gc_marked for the traversal. */ \ - HeapWord* end = _first_dead; \ - \ - while (q < end) { \ - /* I originally tried to conjoin "block_start(q) == q" to the \ - * assertion below, but that doesn't work, because you can't \ - * accurately traverse previous objects to get to the current one \ - * after their pointers have been \ - * updated, until the actual compaction is done. dld, 4/00 */ \ - assert(block_is_obj(q), \ - "should be at block boundaries, and should be looking at objs"); \ - \ - /* point all the oops to the new location */ \ - size_t size = oop(q)->adjust_pointers(); \ - size = adjust_obj_size(size); \ - \ - q += size; \ - } \ - \ - if (_first_dead == t) { \ - q = t; \ - } else { \ - /* $$$ This is funky. Using this to read the previously written \ - * LiveRange. See also use below. */ \ - q = (HeapWord*)oop(_first_dead)->mark()->decode_pointer(); \ - } \ - } \ - \ - const intx interval = PrefetchScanIntervalInBytes; \ - \ - debug_only(HeapWord* prev_q = NULL); \ - while (q < t) { \ - /* prefetch beyond q */ \ - Prefetch::write(q, interval); \ - if (oop(q)->is_gc_marked()) { \ - /* q is alive */ \ - /* point all the oops to the new location */ \ - size_t size = oop(q)->adjust_pointers(); \ - size = adjust_obj_size(size); \ - debug_only(prev_q = q); \ - q += size; \ - } else { \ - /* q is not a live object, so its mark should point at the next \ - * live object */ \ - debug_only(prev_q = q); \ - q = (HeapWord*) oop(q)->mark()->decode_pointer(); \ - assert(q > prev_q, "we should be moving forward through memory"); \ - } \ - } \ - \ - assert(q == t, "just checking"); \ -} - -#define SCAN_AND_COMPACT(obj_size) { \ - /* Copy all live objects to their new location \ - * Used by MarkSweep::mark_sweep_phase4() */ \ - \ - HeapWord* q = bottom(); \ - HeapWord* const t = _end_of_live; \ - debug_only(HeapWord* prev_q = NULL); \ - \ - if (q < t && _first_dead > q && \ - !oop(q)->is_gc_marked()) { \ - debug_only( \ - /* we have a chunk of the space which hasn't moved and we've reinitialized \ - * the mark word during the previous pass, so we can't use is_gc_marked for \ - * the traversal. */ \ - HeapWord* const end = _first_dead; \ - \ - while (q < end) { \ - size_t size = obj_size(q); \ - assert(!oop(q)->is_gc_marked(), \ - "should be unmarked (special dense prefix handling)"); \ - debug_only(prev_q = q); \ - q += size; \ - } \ - ) /* debug_only */ \ - \ - if (_first_dead == t) { \ - q = t; \ - } else { \ - /* $$$ Funky */ \ - q = (HeapWord*) oop(_first_dead)->mark()->decode_pointer(); \ - } \ - } \ - \ - const intx scan_interval = PrefetchScanIntervalInBytes; \ - const intx copy_interval = PrefetchCopyIntervalInBytes; \ - while (q < t) { \ - if (!oop(q)->is_gc_marked()) { \ - /* mark is pointer to next marked oop */ \ - debug_only(prev_q = q); \ - q = (HeapWord*) oop(q)->mark()->decode_pointer(); \ - assert(q > prev_q, "we should be moving forward through memory"); \ - } else { \ - /* prefetch beyond q */ \ - Prefetch::read(q, scan_interval); \ - \ - /* size and destination */ \ - size_t size = obj_size(q); \ - HeapWord* compaction_top = (HeapWord*)oop(q)->forwardee(); \ - \ - /* prefetch beyond compaction_top */ \ - Prefetch::write(compaction_top, copy_interval); \ - \ - /* copy object and reinit its mark */ \ - assert(q != compaction_top, "everything in this pass should be moving"); \ - Copy::aligned_conjoint_words(q, compaction_top, size); \ - oop(compaction_top)->init_mark(); \ - assert(oop(compaction_top)->klass() != NULL, "should have a class"); \ - \ - debug_only(prev_q = q); \ - q += size; \ - } \ - } \ - \ - /* Let's remember if we were empty before we did the compaction. */ \ - bool was_empty = used_region().is_empty(); \ - /* Reset space after compaction is complete */ \ - reset_after_compaction(); \ - /* We do this clear, below, since it has overloaded meanings for some */ \ - /* space subtypes. For example, OffsetTableContigSpace's that were */ \ - /* compacted into will have had their offset table thresholds updated */ \ - /* continuously, but those that weren't need to have their thresholds */ \ - /* re-initialized. Also mangles unused area for debugging. */ \ - if (used_region().is_empty()) { \ - if (!was_empty) clear(SpaceDecorator::Mangle); \ - } else { \ - if (ZapUnusedHeapArea) mangle_unused_area(); \ - } \ -} - class GenSpaceMangler; // A space in which the free area is contiguous. It therefore supports diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/memory/space.inline.hpp --- a/src/share/vm/memory/space.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/memory/space.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -28,12 +28,279 @@ #include "gc_interface/collectedHeap.hpp" #include "memory/space.hpp" #include "memory/universe.hpp" +#include "runtime/prefetch.inline.hpp" #include "runtime/safepoint.hpp" inline HeapWord* Space::block_start(const void* p) { return block_start_const(p); } +#define SCAN_AND_FORWARD(cp,scan_limit,block_is_obj,block_size) { \ + /* Compute the new addresses for the live objects and store it in the mark \ + * Used by universe::mark_sweep_phase2() \ + */ \ + HeapWord* compact_top; /* This is where we are currently compacting to. */ \ + \ + /* We're sure to be here before any objects are compacted into this \ + * space, so this is a good time to initialize this: \ + */ \ + set_compaction_top(bottom()); \ + \ + if (cp->space == NULL) { \ + assert(cp->gen != NULL, "need a generation"); \ + assert(cp->threshold == NULL, "just checking"); \ + assert(cp->gen->first_compaction_space() == this, "just checking"); \ + cp->space = cp->gen->first_compaction_space(); \ + compact_top = cp->space->bottom(); \ + cp->space->set_compaction_top(compact_top); \ + cp->threshold = cp->space->initialize_threshold(); \ + } else { \ + compact_top = cp->space->compaction_top(); \ + } \ + \ + /* We allow some amount of garbage towards the bottom of the space, so \ + * we don't start compacting before there is a significant gain to be made.\ + * Occasionally, we want to ensure a full compaction, which is determined \ + * by the MarkSweepAlwaysCompactCount parameter. \ + */ \ + uint invocations = MarkSweep::total_invocations(); \ + bool skip_dead = ((invocations % MarkSweepAlwaysCompactCount) != 0); \ + \ + size_t allowed_deadspace = 0; \ + if (skip_dead) { \ + const size_t ratio = allowed_dead_ratio(); \ + allowed_deadspace = (capacity() * ratio / 100) / HeapWordSize; \ + } \ + \ + HeapWord* q = bottom(); \ + HeapWord* t = scan_limit(); \ + \ + HeapWord* end_of_live= q; /* One byte beyond the last byte of the last \ + live object. */ \ + HeapWord* first_dead = end();/* The first dead object. */ \ + LiveRange* liveRange = NULL; /* The current live range, recorded in the \ + first header of preceding free area. */ \ + _first_dead = first_dead; \ + \ + const intx interval = PrefetchScanIntervalInBytes; \ + \ + while (q < t) { \ + assert(!block_is_obj(q) || \ + oop(q)->mark()->is_marked() || oop(q)->mark()->is_unlocked() || \ + oop(q)->mark()->has_bias_pattern(), \ + "these are the only valid states during a mark sweep"); \ + if (block_is_obj(q) && oop(q)->is_gc_marked()) { \ + /* prefetch beyond q */ \ + Prefetch::write(q, interval); \ + size_t size = block_size(q); \ + compact_top = cp->space->forward(oop(q), size, cp, compact_top); \ + q += size; \ + end_of_live = q; \ + } else { \ + /* run over all the contiguous dead objects */ \ + HeapWord* end = q; \ + do { \ + /* prefetch beyond end */ \ + Prefetch::write(end, interval); \ + end += block_size(end); \ + } while (end < t && (!block_is_obj(end) || !oop(end)->is_gc_marked()));\ + \ + /* see if we might want to pretend this object is alive so that \ + * we don't have to compact quite as often. \ + */ \ + if (allowed_deadspace > 0 && q == compact_top) { \ + size_t sz = pointer_delta(end, q); \ + if (insert_deadspace(allowed_deadspace, q, sz)) { \ + compact_top = cp->space->forward(oop(q), sz, cp, compact_top); \ + q = end; \ + end_of_live = end; \ + continue; \ + } \ + } \ + \ + /* otherwise, it really is a free region. */ \ + \ + /* for the previous LiveRange, record the end of the live objects. */ \ + if (liveRange) { \ + liveRange->set_end(q); \ + } \ + \ + /* record the current LiveRange object. \ + * liveRange->start() is overlaid on the mark word. \ + */ \ + liveRange = (LiveRange*)q; \ + liveRange->set_start(end); \ + liveRange->set_end(end); \ + \ + /* see if this is the first dead region. */ \ + if (q < first_dead) { \ + first_dead = q; \ + } \ + \ + /* move on to the next object */ \ + q = end; \ + } \ + } \ + \ + assert(q == t, "just checking"); \ + if (liveRange != NULL) { \ + liveRange->set_end(q); \ + } \ + _end_of_live = end_of_live; \ + if (end_of_live < first_dead) { \ + first_dead = end_of_live; \ + } \ + _first_dead = first_dead; \ + \ + /* save the compaction_top of the compaction space. */ \ + cp->space->set_compaction_top(compact_top); \ +} + +#define SCAN_AND_ADJUST_POINTERS(adjust_obj_size) { \ + /* adjust all the interior pointers to point at the new locations of objects \ + * Used by MarkSweep::mark_sweep_phase3() */ \ + \ + HeapWord* q = bottom(); \ + HeapWord* t = _end_of_live; /* Established by "prepare_for_compaction". */ \ + \ + assert(_first_dead <= _end_of_live, "Stands to reason, no?"); \ + \ + if (q < t && _first_dead > q && \ + !oop(q)->is_gc_marked()) { \ + /* we have a chunk of the space which hasn't moved and we've \ + * reinitialized the mark word during the previous pass, so we can't \ + * use is_gc_marked for the traversal. */ \ + HeapWord* end = _first_dead; \ + \ + while (q < end) { \ + /* I originally tried to conjoin "block_start(q) == q" to the \ + * assertion below, but that doesn't work, because you can't \ + * accurately traverse previous objects to get to the current one \ + * after their pointers have been \ + * updated, until the actual compaction is done. dld, 4/00 */ \ + assert(block_is_obj(q), \ + "should be at block boundaries, and should be looking at objs"); \ + \ + /* point all the oops to the new location */ \ + size_t size = oop(q)->adjust_pointers(); \ + size = adjust_obj_size(size); \ + \ + q += size; \ + } \ + \ + if (_first_dead == t) { \ + q = t; \ + } else { \ + /* $$$ This is funky. Using this to read the previously written \ + * LiveRange. See also use below. */ \ + q = (HeapWord*)oop(_first_dead)->mark()->decode_pointer(); \ + } \ + } \ + \ + const intx interval = PrefetchScanIntervalInBytes; \ + \ + debug_only(HeapWord* prev_q = NULL); \ + while (q < t) { \ + /* prefetch beyond q */ \ + Prefetch::write(q, interval); \ + if (oop(q)->is_gc_marked()) { \ + /* q is alive */ \ + /* point all the oops to the new location */ \ + size_t size = oop(q)->adjust_pointers(); \ + size = adjust_obj_size(size); \ + debug_only(prev_q = q); \ + q += size; \ + } else { \ + /* q is not a live object, so its mark should point at the next \ + * live object */ \ + debug_only(prev_q = q); \ + q = (HeapWord*) oop(q)->mark()->decode_pointer(); \ + assert(q > prev_q, "we should be moving forward through memory"); \ + } \ + } \ + \ + assert(q == t, "just checking"); \ +} + +#define SCAN_AND_COMPACT(obj_size) { \ + /* Copy all live objects to their new location \ + * Used by MarkSweep::mark_sweep_phase4() */ \ + \ + HeapWord* q = bottom(); \ + HeapWord* const t = _end_of_live; \ + debug_only(HeapWord* prev_q = NULL); \ + \ + if (q < t && _first_dead > q && \ + !oop(q)->is_gc_marked()) { \ + debug_only( \ + /* we have a chunk of the space which hasn't moved and we've reinitialized \ + * the mark word during the previous pass, so we can't use is_gc_marked for \ + * the traversal. */ \ + HeapWord* const end = _first_dead; \ + \ + while (q < end) { \ + size_t size = obj_size(q); \ + assert(!oop(q)->is_gc_marked(), \ + "should be unmarked (special dense prefix handling)"); \ + debug_only(prev_q = q); \ + q += size; \ + } \ + ) /* debug_only */ \ + \ + if (_first_dead == t) { \ + q = t; \ + } else { \ + /* $$$ Funky */ \ + q = (HeapWord*) oop(_first_dead)->mark()->decode_pointer(); \ + } \ + } \ + \ + const intx scan_interval = PrefetchScanIntervalInBytes; \ + const intx copy_interval = PrefetchCopyIntervalInBytes; \ + while (q < t) { \ + if (!oop(q)->is_gc_marked()) { \ + /* mark is pointer to next marked oop */ \ + debug_only(prev_q = q); \ + q = (HeapWord*) oop(q)->mark()->decode_pointer(); \ + assert(q > prev_q, "we should be moving forward through memory"); \ + } else { \ + /* prefetch beyond q */ \ + Prefetch::read(q, scan_interval); \ + \ + /* size and destination */ \ + size_t size = obj_size(q); \ + HeapWord* compaction_top = (HeapWord*)oop(q)->forwardee(); \ + \ + /* prefetch beyond compaction_top */ \ + Prefetch::write(compaction_top, copy_interval); \ + \ + /* copy object and reinit its mark */ \ + assert(q != compaction_top, "everything in this pass should be moving"); \ + Copy::aligned_conjoint_words(q, compaction_top, size); \ + oop(compaction_top)->init_mark(); \ + assert(oop(compaction_top)->klass() != NULL, "should have a class"); \ + \ + debug_only(prev_q = q); \ + q += size; \ + } \ + } \ + \ + /* Let's remember if we were empty before we did the compaction. */ \ + bool was_empty = used_region().is_empty(); \ + /* Reset space after compaction is complete */ \ + reset_after_compaction(); \ + /* We do this clear, below, since it has overloaded meanings for some */ \ + /* space subtypes. For example, OffsetTableContigSpace's that were */ \ + /* compacted into will have had their offset table thresholds updated */ \ + /* continuously, but those that weren't need to have their thresholds */ \ + /* re-initialized. Also mangles unused area for debugging. */ \ + if (used_region().is_empty()) { \ + if (!was_empty) clear(SpaceDecorator::Mangle); \ + } else { \ + if (ZapUnusedHeapArea) mangle_unused_area(); \ + } \ +} + inline HeapWord* OffsetTableContigSpace::allocate(size_t size) { HeapWord* res = ContiguousSpace::allocate(size); if (res != NULL) { diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/oops/cpCache.cpp --- a/src/share/vm/oops/cpCache.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/oops/cpCache.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -33,6 +33,7 @@ #include "prims/jvmtiRedefineClassesTrace.hpp" #include "prims/methodHandles.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "utilities/macros.hpp" #if INCLUDE_ALL_GCS # include "gc_implementation/parallelScavenge/psPromotionManager.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/oops/cpCache.hpp --- a/src/share/vm/oops/cpCache.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/oops/cpCache.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -27,6 +27,7 @@ #include "interpreter/bytecodes.hpp" #include "memory/allocation.hpp" +#include "runtime/orderAccess.hpp" #include "utilities/array.hpp" class PSPromotionManager; diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/oops/instanceKlass.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -54,6 +54,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/thread.inline.hpp" #include "services/classLoadingService.hpp" #include "services/threadService.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/oops/klass.cpp --- a/src/share/vm/oops/klass.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/oops/klass.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -36,7 +36,8 @@ #include "oops/instanceKlass.hpp" #include "oops/klass.inline.hpp" #include "oops/oop.inline2.hpp" -#include "runtime/atomic.hpp" +#include "runtime/atomic.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "trace/traceMacros.hpp" #include "utilities/stack.hpp" #include "utilities/macros.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/oops/klass.hpp --- a/src/share/vm/oops/klass.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/oops/klass.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -32,7 +32,6 @@ #include "oops/klassPS.hpp" #include "oops/metadata.hpp" #include "oops/oop.hpp" -#include "runtime/orderAccess.hpp" #include "trace/traceMacros.hpp" #include "utilities/accessFlags.hpp" #include "utilities/macros.hpp" @@ -585,36 +584,6 @@ static void clean_weak_klass_links(BoolObjectClosure* is_alive); - // Prefetch within oop iterators. This is a macro because we - // can't guarantee that the compiler will inline it. In 64-bit - // it generally doesn't. Signature is - // - // static void prefetch_beyond(oop* const start, - // oop* const end, - // const intx foffset, - // const Prefetch::style pstyle); -#define prefetch_beyond(start, end, foffset, pstyle) { \ - const intx foffset_ = (foffset); \ - const Prefetch::style pstyle_ = (pstyle); \ - assert(foffset_ > 0, "prefetch beyond, not behind"); \ - if (pstyle_ != Prefetch::do_none) { \ - oop* ref = (start); \ - if (ref < (end)) { \ - switch (pstyle_) { \ - case Prefetch::do_read: \ - Prefetch::read(*ref, foffset_); \ - break; \ - case Prefetch::do_write: \ - Prefetch::write(*ref, foffset_); \ - break; \ - default: \ - ShouldNotReachHere(); \ - break; \ - } \ - } \ - } \ - } - // iterators virtual int oop_oop_iterate(oop obj, ExtendedOopClosure* blk) = 0; virtual int oop_oop_iterate_v(oop obj, ExtendedOopClosure* blk) { diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/oops/method.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -49,6 +49,7 @@ #include "runtime/compilationPolicy.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/relocator.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/oops/methodData.cpp --- a/src/share/vm/oops/methodData.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/oops/methodData.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -34,6 +34,7 @@ #include "runtime/compilationPolicy.hpp" #include "runtime/deoptimization.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/orderAccess.inline.hpp" PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/oops/objArrayKlass.cpp --- a/src/share/vm/oops/objArrayKlass.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/oops/objArrayKlass.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -42,6 +42,7 @@ #include "oops/symbol.hpp" #include "runtime/handles.inline.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/orderAccess.inline.hpp" #include "utilities/copy.hpp" #include "utilities/macros.hpp" #if INCLUDE_ALL_GCS diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/oops/oop.inline.hpp --- a/src/share/vm/oops/oop.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/oops/oop.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -38,7 +38,8 @@ #include "oops/klass.inline.hpp" #include "oops/markOop.inline.hpp" #include "oops/oop.hpp" -#include "runtime/atomic.hpp" +#include "runtime/atomic.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/os.hpp" #include "utilities/macros.hpp" #ifdef TARGET_ARCH_x86 diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/oops/typeArrayKlass.cpp --- a/src/share/vm/oops/typeArrayKlass.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/oops/typeArrayKlass.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -39,6 +39,7 @@ #include "oops/typeArrayKlass.hpp" #include "oops/typeArrayOop.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "utilities/macros.hpp" bool TypeArrayKlass::compute_is_subtype_of(Klass* k) { diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/oops/typeArrayOop.hpp --- a/src/share/vm/oops/typeArrayOop.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/oops/typeArrayOop.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -27,39 +27,7 @@ #include "oops/arrayOop.hpp" #include "oops/typeArrayKlass.hpp" -#ifdef TARGET_OS_ARCH_linux_x86 -# include "orderAccess_linux_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_sparc -# include "orderAccess_linux_sparc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_zero -# include "orderAccess_linux_zero.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_solaris_x86 -# include "orderAccess_solaris_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_solaris_sparc -# include "orderAccess_solaris_sparc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_windows_x86 -# include "orderAccess_windows_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_arm -# include "orderAccess_linux_arm.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_ppc -# include "orderAccess_linux_ppc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_aix_ppc -# include "orderAccess_aix_ppc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_bsd_x86 -# include "orderAccess_bsd_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_bsd_zero -# include "orderAccess_bsd_zero.inline.hpp" -#endif +#include "runtime/orderAccess.inline.hpp" // A typeArrayOop is an array containing basic types (non oop elements). // It is used for arrays of {characters, singles, doubles, bytes, shorts, integers, longs} diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/opto/callGenerator.cpp --- a/src/share/vm/opto/callGenerator.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/opto/callGenerator.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -837,8 +837,11 @@ Node* receiver_node = kit.argument(0); const TypeOopPtr* receiver_type = gvn.type(receiver_node)->isa_oopptr(); // call_does_dispatch and vtable_index are out-parameters. They might be changed. - target = C->optimize_virtual_call(caller, jvms->bci(), klass, target, receiver_type, - is_virtual, + // optimize_virtual_call() takes 2 different holder + // arguments for a corner case that doesn't apply here (see + // Parse::do_call()) + target = C->optimize_virtual_call(caller, jvms->bci(), klass, klass, + target, receiver_type, is_virtual, call_does_dispatch, vtable_index); // out-parameters // We lack profiling at this call but type speculation may // provide us with a type diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/opto/compile.hpp --- a/src/share/vm/opto/compile.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/opto/compile.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -854,8 +854,8 @@ // Helper functions to identify inlining potential at call-site ciMethod* optimize_virtual_call(ciMethod* caller, int bci, ciInstanceKlass* klass, - ciMethod* callee, const TypeOopPtr* receiver_type, - bool is_virtual, + ciKlass* holder, ciMethod* callee, + const TypeOopPtr* receiver_type, bool is_virtual, bool &call_does_dispatch, int &vtable_index); ciMethod* optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass* klass, ciMethod* callee, const TypeOopPtr* receiver_type); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/opto/doCall.cpp --- a/src/share/vm/opto/doCall.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/opto/doCall.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -460,8 +460,14 @@ Node* receiver_node = stack(sp() - nargs); const TypeOopPtr* receiver_type = _gvn.type(receiver_node)->isa_oopptr(); // call_does_dispatch and vtable_index are out-parameters. They might be changed. - callee = C->optimize_virtual_call(method(), bci(), klass, orig_callee, receiver_type, - is_virtual, + // For arrays, klass below is Object. When vtable calls are used, + // resolving the call with Object would allow an illegal call to + // finalize() on an array. We use holder instead: illegal calls to + // finalize() won't be compiled as vtable calls (IC call + // resolution will catch the illegal call) and the few legal calls + // on array types won't be either. + callee = C->optimize_virtual_call(method(), bci(), klass, holder, orig_callee, + receiver_type, is_virtual, call_does_dispatch, vtable_index); // out-parameters speculative_receiver_type = receiver_type != NULL ? receiver_type->speculative_type() : NULL; } @@ -937,8 +943,8 @@ ciMethod* Compile::optimize_virtual_call(ciMethod* caller, int bci, ciInstanceKlass* klass, - ciMethod* callee, const TypeOopPtr* receiver_type, - bool is_virtual, + ciKlass* holder, ciMethod* callee, + const TypeOopPtr* receiver_type, bool is_virtual, bool& call_does_dispatch, int& vtable_index) { // Set default values for out-parameters. call_does_dispatch = true; @@ -953,7 +959,7 @@ call_does_dispatch = false; } else if (!UseInlineCaches && is_virtual && callee->is_loaded()) { // We can make a vtable call at this site - vtable_index = callee->resolve_vtable_index(caller->holder(), klass); + vtable_index = callee->resolve_vtable_index(caller->holder(), holder); } return callee; } @@ -976,8 +982,10 @@ ciInstanceKlass* actual_receiver = klass; if (receiver_type != NULL) { // Array methods are all inherited from Object, and are monomorphic. + // finalize() call on array is not allowed. if (receiver_type->isa_aryptr() && - callee->holder() == env()->Object_klass()) { + callee->holder() == env()->Object_klass() && + callee->name() != ciSymbol::finalize_method_name()) { return callee; } diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/precompiled/precompiled.hpp --- a/src/share/vm/precompiled/precompiled.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/precompiled/precompiled.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -193,11 +193,13 @@ # include "runtime/mutexLocker.hpp" # include "runtime/objectMonitor.hpp" # include "runtime/orderAccess.hpp" +# include "runtime/orderAccess.inline.hpp" # include "runtime/os.hpp" # include "runtime/osThread.hpp" # include "runtime/perfData.hpp" # include "runtime/perfMemory.hpp" # include "runtime/prefetch.hpp" +# include "runtime/prefetch.inline.hpp" # include "runtime/reflection.hpp" # include "runtime/reflectionUtils.hpp" # include "runtime/registerMap.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/prims/forte.cpp --- a/src/share/vm/prims/forte.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/prims/forte.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -32,7 +32,7 @@ #include "oops/oop.inline2.hpp" #include "prims/forte.hpp" #include "runtime/javaCalls.hpp" -#include "runtime/thread.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/vframe.hpp" #include "runtime/vframeArray.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/prims/jni.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -67,6 +67,7 @@ #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" #include "runtime/jfieldIDWorkaround.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/reflection.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/prims/jniCheck.cpp --- a/src/share/vm/prims/jniCheck.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/prims/jniCheck.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -35,7 +35,7 @@ #include "runtime/handles.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/jfieldIDWorkaround.hpp" -#include "runtime/thread.hpp" +#include "runtime/thread.inline.hpp" #ifdef TARGET_ARCH_x86 # include "jniTypes_x86.hpp" #endif diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/prims/jvm.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -51,6 +51,7 @@ #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" #include "runtime/jfieldIDWorkaround.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/os.hpp" #include "runtime/perfData.hpp" #include "runtime/reflection.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/prims/jvmtiEnvBase.cpp --- a/src/share/vm/prims/jvmtiEnvBase.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/prims/jvmtiEnvBase.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -41,6 +41,7 @@ #include "runtime/objectMonitor.hpp" #include "runtime/objectMonitor.inline.hpp" #include "runtime/signature.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/vframe.hpp" #include "runtime/vframe_hp.hpp" #include "runtime/vmThread.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/prims/jvmtiExport.cpp --- a/src/share/vm/prims/jvmtiExport.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/prims/jvmtiExport.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -47,7 +47,7 @@ #include "runtime/interfaceSupport.hpp" #include "runtime/objectMonitor.hpp" #include "runtime/objectMonitor.inline.hpp" -#include "runtime/thread.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/vframe.hpp" #include "services/attachListener.hpp" #include "services/serviceUtil.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/prims/jvmtiRawMonitor.cpp --- a/src/share/vm/prims/jvmtiRawMonitor.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/prims/jvmtiRawMonitor.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -25,7 +25,8 @@ #include "precompiled.hpp" #include "prims/jvmtiRawMonitor.hpp" #include "runtime/interfaceSupport.hpp" -#include "runtime/thread.hpp" +#include "runtime/orderAccess.inline.hpp" +#include "runtime/thread.inline.hpp" GrowableArray *JvmtiPendingMonitors::_monitors = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(1,true); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/prims/jvmtiThreadState.inline.hpp --- a/src/share/vm/prims/jvmtiThreadState.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/prims/jvmtiThreadState.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -27,6 +27,7 @@ #include "prims/jvmtiEnvThreadState.hpp" #include "prims/jvmtiThreadState.hpp" +#include "runtime/thread.inline.hpp" // JvmtiEnvThreadStateIterator implementation diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/prims/unsafe.cpp --- a/src/share/vm/prims/unsafe.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/prims/unsafe.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -33,6 +33,8 @@ #include "prims/jvm.h" #include "runtime/globals.hpp" #include "runtime/interfaceSupport.hpp" +#include "runtime/prefetch.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/reflection.hpp" #include "runtime/synchronizer.hpp" #include "services/threadService.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/fprofiler.cpp --- a/src/share/vm/runtime/fprofiler.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/runtime/fprofiler.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -38,6 +38,7 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/task.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/vframe.hpp" #include "utilities/macros.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/runtime/globals.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -2287,6 +2287,9 @@ manageable(bool, PrintGCTimeStamps, false, \ "Print timestamps at garbage collection") \ \ + manageable(bool, PrintGCID, false, \ + "Print an identifier for each garbage collection") \ + \ product(bool, PrintGCTaskTimeStamps, false, \ "Print timestamps for individual gc worker thread tasks") \ \ diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/interfaceSupport.cpp --- a/src/share/vm/runtime/interfaceSupport.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/runtime/interfaceSupport.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -30,6 +30,7 @@ #include "memory/resourceArea.hpp" #include "runtime/init.hpp" #include "runtime/interfaceSupport.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/threadLocalStorage.hpp" #include "runtime/vframe.hpp" #include "utilities/preserveException.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/javaFrameAnchor.hpp --- a/src/share/vm/runtime/javaFrameAnchor.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/runtime/javaFrameAnchor.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -26,39 +26,7 @@ #define SHARE_VM_RUNTIME_JAVAFRAMEANCHOR_HPP #include "utilities/globalDefinitions.hpp" -#ifdef TARGET_OS_ARCH_linux_x86 -# include "orderAccess_linux_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_sparc -# include "orderAccess_linux_sparc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_zero -# include "orderAccess_linux_zero.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_solaris_x86 -# include "orderAccess_solaris_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_solaris_sparc -# include "orderAccess_solaris_sparc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_windows_x86 -# include "orderAccess_windows_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_arm -# include "orderAccess_linux_arm.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_ppc -# include "orderAccess_linux_ppc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_aix_ppc -# include "orderAccess_aix_ppc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_bsd_x86 -# include "orderAccess_bsd_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_bsd_zero -# include "orderAccess_bsd_zero.inline.hpp" -#endif +#include "runtime/orderAccess.inline.hpp" // // An object for encapsulating the machine/os dependent part of a JavaThread frame state diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/mutex.cpp --- a/src/share/vm/runtime/mutex.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/runtime/mutex.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "runtime/mutex.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/osThread.hpp" #include "runtime/thread.inline.hpp" #include "utilities/events.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/mutexLocker.cpp --- a/src/share/vm/runtime/mutexLocker.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/runtime/mutexLocker.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -69,7 +69,7 @@ Monitor* SerializePage_lock = NULL; Monitor* Threads_lock = NULL; Monitor* CGC_lock = NULL; -Mutex* STS_init_lock = NULL; +Monitor* STS_lock = NULL; Monitor* SLT_lock = NULL; Monitor* iCMS_lock = NULL; Monitor* FullGCCount_lock = NULL; @@ -173,7 +173,7 @@ def(tty_lock , Mutex , event, true ); // allow to lock in VM def(CGC_lock , Monitor, special, true ); // coordinate between fore- and background GC - def(STS_init_lock , Mutex, leaf, true ); + def(STS_lock , Monitor, leaf, true ); if (UseConcMarkSweepGC) { def(iCMS_lock , Monitor, special, true ); // CMS incremental mode start/stop notification } diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/mutexLocker.hpp --- a/src/share/vm/runtime/mutexLocker.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/runtime/mutexLocker.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -79,7 +79,7 @@ // (also used by Safepoints too to block threads creation/destruction) extern Monitor* CGC_lock; // used for coordination between // fore- & background GC threads. -extern Mutex* STS_init_lock; // coordinate initialization of SuspendibleThreadSets. +extern Monitor* STS_lock; // used for joining/leaving SuspendibleThreadSet. extern Monitor* SLT_lock; // used in CMS GC for acquiring PLL extern Monitor* iCMS_lock; // CMS incremental mode start/stop notification extern Monitor* FullGCCount_lock; // in support of "concurrent" full gc diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/objectMonitor.cpp --- a/src/share/vm/runtime/objectMonitor.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/runtime/objectMonitor.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -32,6 +32,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/objectMonitor.hpp" #include "runtime/objectMonitor.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/osThread.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/orderAccess.inline.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/runtime/orderAccess.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright 2014 SAP AG. 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_RUNTIME_ORDERACCESS_INLINE_HPP +#define SHARE_VM_RUNTIME_ORDERACCESS_INLINE_HPP + +#include "runtime/orderAccess.hpp" + +// Linux +#ifdef TARGET_OS_ARCH_linux_x86 +# include "orderAccess_linux_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_linux_sparc +# include "orderAccess_linux_sparc.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_linux_zero +# include "orderAccess_linux_zero.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_linux_arm +# include "orderAccess_linux_arm.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_linux_ppc +# include "orderAccess_linux_ppc.inline.hpp" +#endif + +// Solaris +#ifdef TARGET_OS_ARCH_solaris_x86 +# include "orderAccess_solaris_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_solaris_sparc +# include "orderAccess_solaris_sparc.inline.hpp" +#endif + +// Windows +#ifdef TARGET_OS_ARCH_windows_x86 +# include "orderAccess_windows_x86.inline.hpp" +#endif + +// AIX +#ifdef TARGET_OS_ARCH_aix_ppc +# include "orderAccess_aix_ppc.inline.hpp" +#endif + +// BSD +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "orderAccess_bsd_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "orderAccess_bsd_zero.inline.hpp" +#endif + +#endif // SHARE_VM_RUNTIME_ORDERACCESS_INLINE_HPP diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/perfMemory.cpp --- a/src/share/vm/runtime/perfMemory.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/runtime/perfMemory.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -28,6 +28,7 @@ #include "runtime/java.hpp" #include "runtime/mutex.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/os.hpp" #include "runtime/perfData.hpp" #include "runtime/perfMemory.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/prefetch.inline.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/runtime/prefetch.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_RUNTIME_PREFETCH_INLINE_HPP +#define SHARE_VM_RUNTIME_PREFETCH_INLINE_HPP + +#include "runtime/prefetch.hpp" + +// Linux +#ifdef TARGET_OS_ARCH_linux_x86 +# include "prefetch_linux_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_linux_sparc +# include "prefetch_linux_sparc.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_linux_zero +# include "prefetch_linux_zero.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_linux_arm +# include "prefetch_linux_arm.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_linux_ppc +# include "prefetch_linux_ppc.inline.hpp" +#endif + +// Solaris +#ifdef TARGET_OS_ARCH_solaris_x86 +# include "prefetch_solaris_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_solaris_sparc +# include "prefetch_solaris_sparc.inline.hpp" +#endif + +// Windows +#ifdef TARGET_OS_ARCH_windows_x86 +# include "prefetch_windows_x86.inline.hpp" +#endif + +// AIX +#ifdef TARGET_OS_ARCH_aix_ppc +# include "prefetch_aix_ppc.inline.hpp" +#endif + +// BSD +#ifdef TARGET_OS_ARCH_bsd_x86 +# include "prefetch_bsd_x86.inline.hpp" +#endif +#ifdef TARGET_OS_ARCH_bsd_zero +# include "prefetch_bsd_zero.inline.hpp" +#endif + +#endif // SHARE_VM_RUNTIME_PREFETCH_INLINE_HPP diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/safepoint.cpp --- a/src/share/vm/runtime/safepoint.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/runtime/safepoint.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -41,6 +41,7 @@ #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/osThread.hpp" #include "runtime/safepoint.hpp" #include "runtime/signature.hpp" @@ -75,7 +76,7 @@ #endif #if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" -#include "gc_implementation/shared/concurrentGCThread.hpp" +#include "gc_implementation/shared/suspendibleThreadSet.hpp" #endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_globals.hpp" @@ -112,7 +113,7 @@ // more-general mechanism below. DLD (01/05). ConcurrentMarkSweepThread::synchronize(false); } else if (UseG1GC) { - ConcurrentGCThread::safepoint_synchronize(); + SuspendibleThreadSet::synchronize(); } #endif // INCLUDE_ALL_GCS @@ -488,7 +489,7 @@ if (UseConcMarkSweepGC) { ConcurrentMarkSweepThread::desynchronize(false); } else if (UseG1GC) { - ConcurrentGCThread::safepoint_desynchronize(); + SuspendibleThreadSet::desynchronize(); } #endif // INCLUDE_ALL_GCS // record this time so VMThread can keep track how much time has elasped diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/sweeper.cpp --- a/src/share/vm/runtime/sweeper.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/runtime/sweeper.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -33,8 +33,10 @@ #include "runtime/atomic.hpp" #include "runtime/compilationPolicy.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/os.hpp" #include "runtime/sweeper.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/vm_operations.hpp" #include "trace/tracing.hpp" #include "utilities/events.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/runtime/thread.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -58,6 +58,7 @@ #include "runtime/memprofiler.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/objectMonitor.hpp" +#include "runtime/orderAccess.inline.hpp" #include "runtime/osThread.hpp" #include "runtime/safepoint.hpp" #include "runtime/sharedRuntime.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/runtime/thread.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -436,18 +436,7 @@ jlong allocated_bytes() { return _allocated_bytes; } void set_allocated_bytes(jlong value) { _allocated_bytes = value; } void incr_allocated_bytes(jlong size) { _allocated_bytes += size; } - jlong cooked_allocated_bytes() { - jlong allocated_bytes = OrderAccess::load_acquire(&_allocated_bytes); - if (UseTLAB) { - size_t used_bytes = tlab().used_bytes(); - if ((ssize_t)used_bytes > 0) { - // More-or-less valid tlab. The load_acquire above should ensure - // that the result of the add is <= the instantaneous value - return allocated_bytes + used_bytes; - } - } - return allocated_bytes; - } + inline jlong cooked_allocated_bytes(); TRACE_DATA* trace_data() { return &_trace_data; } @@ -1046,12 +1035,8 @@ #else // Use membars when accessing volatile _thread_state. See // Threads::create_vm() for size checks. - JavaThreadState thread_state() const { - return (JavaThreadState) OrderAccess::load_acquire((volatile jint*)&_thread_state); - } - void set_thread_state(JavaThreadState s) { - OrderAccess::release_store((volatile jint*)&_thread_state, (jint)s); - } + inline JavaThreadState thread_state() const; + inline void set_thread_state(JavaThreadState s); #endif ThreadSafepointState *safepoint_state() const { return _safepoint_state; } void set_safepoint_state(ThreadSafepointState *state) { _safepoint_state = state; } @@ -1775,7 +1760,7 @@ // clearing/querying jni attach status bool is_attaching_via_jni() const { return _jni_attach_state == _attaching_via_jni; } bool has_attached_via_jni() const { return is_attaching_via_jni() || _jni_attach_state == _attached_via_jni; } - void set_done_attaching_via_jni() { _jni_attach_state = _attached_via_jni; OrderAccess::fence(); } + inline void set_done_attaching_via_jni(); private: // This field is used to determine if a thread has claimed // a par_id: it is UINT_MAX if the thread has not claimed a par_id; diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/runtime/thread.inline.hpp --- a/src/share/vm/runtime/thread.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/runtime/thread.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -46,4 +46,32 @@ #undef SHARE_VM_RUNTIME_THREAD_INLINE_HPP_SCOPE +inline jlong Thread::cooked_allocated_bytes() { + jlong allocated_bytes = OrderAccess::load_acquire(&_allocated_bytes); + if (UseTLAB) { + size_t used_bytes = tlab().used_bytes(); + if ((ssize_t)used_bytes > 0) { + // More-or-less valid tlab. The load_acquire above should ensure + // that the result of the add is <= the instantaneous value. + return allocated_bytes + used_bytes; + } + } + return allocated_bytes; +} + +#ifdef PPC64 +inline JavaThreadState JavaThread::thread_state() const { + return (JavaThreadState) OrderAccess::load_acquire((volatile jint*)&_thread_state); +} + +inline void JavaThread::set_thread_state(JavaThreadState s) { + OrderAccess::release_store((volatile jint*)&_thread_state, (jint)s); +} +#endif + +inline void JavaThread::set_done_attaching_via_jni() { + _jni_attach_state = _attached_via_jni; + OrderAccess::fence(); +} + #endif // SHARE_VM_RUNTIME_THREAD_INLINE_HPP diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/services/management.cpp --- a/src/share/vm/services/management.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/services/management.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -39,6 +39,7 @@ #include "runtime/jniHandles.hpp" #include "runtime/os.hpp" #include "runtime/serviceThread.hpp" +#include "runtime/thread.inline.hpp" #include "services/classLoadingService.hpp" #include "services/diagnosticCommand.hpp" #include "services/diagnosticFramework.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/services/memTracker.cpp --- a/src/share/vm/services/memTracker.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/services/memTracker.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -29,6 +29,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/safepoint.hpp" #include "runtime/threadCritical.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/vm_operations.hpp" #include "services/memPtr.hpp" #include "services/memReporter.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/services/memoryManager.cpp --- a/src/share/vm/services/memoryManager.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/services/memoryManager.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -28,6 +28,7 @@ #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/orderAccess.inline.hpp" #include "services/lowMemoryDetector.hpp" #include "services/management.hpp" #include "services/memoryManager.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/services/memoryPool.cpp --- a/src/share/vm/services/memoryPool.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/services/memoryPool.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -29,6 +29,7 @@ #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/orderAccess.inline.hpp" #include "services/lowMemoryDetector.hpp" #include "services/management.hpp" #include "services/memoryManager.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/services/threadService.cpp --- a/src/share/vm/services/threadService.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/services/threadService.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -33,6 +33,7 @@ #include "runtime/init.hpp" #include "runtime/thread.hpp" #include "runtime/vframe.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/vmThread.hpp" #include "runtime/vm_operations.hpp" #include "services/threadService.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/utilities/array.hpp --- a/src/share/vm/utilities/array.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/utilities/array.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -28,6 +28,7 @@ #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "memory/metaspace.hpp" +#include "runtime/orderAccess.hpp" // correct linkage required to compile w/o warnings // (must be on file level - cannot be local) diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/utilities/hashtable.inline.hpp --- a/src/share/vm/utilities/hashtable.inline.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/utilities/hashtable.inline.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -26,6 +26,7 @@ #define SHARE_VM_UTILITIES_HASHTABLE_INLINE_HPP #include "memory/allocation.inline.hpp" +#include "runtime/orderAccess.inline.hpp" #include "utilities/hashtable.hpp" #include "utilities/dtrace.hpp" diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/utilities/ostream.cpp --- a/src/share/vm/utilities/ostream.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/utilities/ostream.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "compiler/compileLog.hpp" +#include "gc_implementation/shared/gcId.hpp" #include "oops/oop.inline.hpp" #include "runtime/arguments.hpp" #include "utilities/defaultStream.hpp" @@ -240,6 +241,14 @@ return; } +void outputStream::gclog_stamp(const GCId& gc_id) { + date_stamp(PrintGCDateStamps); + stamp(PrintGCTimeStamps); + if (PrintGCID) { + print("#%u: ", gc_id.id()); + } +} + outputStream& outputStream::indent() { while (_position < _indentation) sp(); return *this; diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/utilities/ostream.hpp --- a/src/share/vm/utilities/ostream.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/utilities/ostream.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -28,6 +28,7 @@ #include "memory/allocation.hpp" #include "runtime/timer.hpp" +class GCId; DEBUG_ONLY(class ResourceMark;) // Output streams for printing @@ -107,6 +108,7 @@ void date_stamp(bool guard) { date_stamp(guard, "", ": "); } + void gclog_stamp(const GCId& gc_id); // portable printing of 64 bit integers void print_jlong(jlong value); diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/utilities/taskqueue.hpp --- a/src/share/vm/utilities/taskqueue.hpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/utilities/taskqueue.hpp Fri Jul 11 00:19:54 2014 -0700 @@ -28,40 +28,8 @@ #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "runtime/mutex.hpp" +#include "runtime/orderAccess.inline.hpp" #include "utilities/stack.hpp" -#ifdef TARGET_OS_ARCH_linux_x86 -# include "orderAccess_linux_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_sparc -# include "orderAccess_linux_sparc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_zero -# include "orderAccess_linux_zero.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_solaris_x86 -# include "orderAccess_solaris_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_solaris_sparc -# include "orderAccess_solaris_sparc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_windows_x86 -# include "orderAccess_windows_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_arm -# include "orderAccess_linux_arm.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_linux_ppc -# include "orderAccess_linux_ppc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_aix_ppc -# include "orderAccess_aix_ppc.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_bsd_x86 -# include "orderAccess_bsd_x86.inline.hpp" -#endif -#ifdef TARGET_OS_ARCH_bsd_zero -# include "orderAccess_bsd_zero.inline.hpp" -#endif // Simple TaskQueue stats that are collected by default in debug builds. diff -r b67a3f81b630 -r d952af8cf67d src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Fri Jun 27 11:07:23 2014 +0100 +++ b/src/share/vm/utilities/vmError.cpp Fri Jul 11 00:19:54 2014 -0700 @@ -30,7 +30,7 @@ #include "runtime/frame.inline.hpp" #include "runtime/init.hpp" #include "runtime/os.hpp" -#include "runtime/thread.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/vmThread.hpp" #include "runtime/vm_operations.hpp" #include "services/memTracker.hpp" diff -r b67a3f81b630 -r d952af8cf67d test/compiler/stable/StableConfiguration.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/stable/StableConfiguration.java Fri Jul 11 00:19:54 2014 -0700 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.lang.invoke; + +import java.lang.reflect.Method; +import java.util.Properties; +import sun.hotspot.WhiteBox; + +public class StableConfiguration { + static final WhiteBox WB = WhiteBox.getWhiteBox(); + static final boolean isStableEnabled; + static final boolean isServerWithStable; + + static { + Boolean value = WB.getBooleanVMFlag("FoldStableValues"); + isStableEnabled = (value == null ? false : value); + isServerWithStable = isStableEnabled && get(); + System.out.println("@Stable: " + (isStableEnabled ? "enabled" : "disabled")); + System.out.println("Server Compiler: " + get()); + } + + // ::get() is among immediately compiled methods. + static boolean get() { + try { + Method m = StableConfiguration.class.getDeclaredMethod("get"); + int level = WB.getMethodCompilationLevel(m); + if (level > 0) { + return (level == 4); + } else { + String javaVM = System.getProperty("java.vm.name", ""); + if (javaVM.contains("Server")) return true; + if (javaVM.contains("Client")) return false; + throw new Error("Unknown VM type: "+javaVM); + } + } catch (NoSuchMethodException e) { + throw new Error(e); + } + } + +} diff -r b67a3f81b630 -r d952af8cf67d test/compiler/stable/TestStableBoolean.java --- a/test/compiler/stable/TestStableBoolean.java Fri Jun 27 11:07:23 2014 +0100 +++ b/test/compiler/stable/TestStableBoolean.java Fri Jul 11 00:19:54 2014 -0700 @@ -26,9 +26,11 @@ /* * @test TestStableBoolean * @summary tests on stable fields and arrays - * @library /testlibrary - * @compile -XDignore.symbol.file TestStableBoolean.java + * @library /testlibrary /testlibrary/whitebox + * @build TestStableBoolean StableConfiguration sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller + * java/lang/invoke/StableConfiguration * java/lang/invoke/TestStableBoolean * java/lang/invoke/TestStableBoolean$BooleanStable * java/lang/invoke/TestStableBoolean$StaticBooleanStable @@ -48,46 +50,60 @@ * java/lang/invoke/TestStableBoolean$NestedStableField3 * java/lang/invoke/TestStableBoolean$NestedStableField3$A * java/lang/invoke/TestStableBoolean$DefaultValue + * java/lang/invoke/TestStableBoolean$DefaultStaticValue * java/lang/invoke/TestStableBoolean$ObjectArrayLowerDim2 * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableBoolean + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableBoolean * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableBoolean + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableBoolean * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableBoolean - * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableBoolean */ package java.lang.invoke; -import com.sun.management.HotSpotDiagnosticMXBean; -import com.sun.management.VMOption; -import sun.management.ManagementFactoryHelper; import java.lang.reflect.InvocationTargetException; public class TestStableBoolean { + static final boolean isStableEnabled = StableConfiguration.isStableEnabled; + static final boolean isServerWithStable = StableConfiguration.isServerWithStable; + public static void main(String[] args) throws Exception { - System.out.println("@Stable enabled: "+isStableEnabled); - System.out.println(); - run(DefaultValue.class); run(BooleanStable.class); + run(DefaultStaticValue.class); run(StaticBooleanStable.class); run(VolatileBooleanStable.class); @@ -145,6 +161,21 @@ /* ==================================================== */ + static class DefaultStaticValue { + public static @Stable boolean v; + + public static final DefaultStaticValue c = new DefaultStaticValue(); + public static boolean get() { return c.v; } + public static void test() throws Exception { + boolean val1 = get(); + c.v = true; boolean val2 = get(); + assertEquals(val1, false); + assertEquals(val2, true); + } + } + + /* ==================================================== */ + static class StaticBooleanStable { public static @Stable boolean v; @@ -188,14 +219,14 @@ c.v = new boolean[1]; c.v[0] = true; boolean val1 = get(); c.v[0] = false; boolean val2 = get(); assertEquals(val1, true); - assertEquals(val2, (isStableEnabled ? true : false)); + assertEquals(val2, (isServerWithStable ? true : false)); } { c.v = new boolean[20]; c.v[10] = true; boolean val1 = get1(); c.v[10] = false; boolean val2 = get1(); assertEquals(val1, true); - assertEquals(val2, (isStableEnabled ? true : false)); + assertEquals(val2, (isServerWithStable ? true : false)); } { @@ -220,19 +251,19 @@ c.v = new boolean[1][1]; c.v[0][0] = true; boolean val1 = get(); c.v[0][0] = false; boolean val2 = get(); assertEquals(val1, true); - assertEquals(val2, (isStableEnabled ? true : false)); + assertEquals(val2, (isServerWithStable ? true : false)); c.v = new boolean[1][1]; c.v[0][0] = false; boolean val3 = get(); - assertEquals(val3, (isStableEnabled ? true : false)); + assertEquals(val3, (isServerWithStable ? true : false)); c.v[0] = new boolean[1]; c.v[0][0] = false; boolean val4 = get(); - assertEquals(val4, (isStableEnabled ? true : false)); + assertEquals(val4, (isServerWithStable ? true : false)); } { c.v = new boolean[1][1]; boolean[] val1 = get1(); c.v[0] = new boolean[1]; boolean[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -258,28 +289,28 @@ c.v = new boolean[1][1][1]; c.v[0][0][0] = true; boolean val1 = get(); c.v[0][0][0] = false; boolean val2 = get(); assertEquals(val1, true); - assertEquals(val2, (isStableEnabled ? true : false)); + assertEquals(val2, (isServerWithStable ? true : false)); c.v = new boolean[1][1][1]; c.v[0][0][0] = false; boolean val3 = get(); - assertEquals(val3, (isStableEnabled ? true : false)); + assertEquals(val3, (isServerWithStable ? true : false)); c.v[0] = new boolean[1][1]; c.v[0][0][0] = false; boolean val4 = get(); - assertEquals(val4, (isStableEnabled ? true : false)); + assertEquals(val4, (isServerWithStable ? true : false)); c.v[0][0] = new boolean[1]; c.v[0][0][0] = false; boolean val5 = get(); - assertEquals(val5, (isStableEnabled ? true : false)); + assertEquals(val5, (isServerWithStable ? true : false)); } { c.v = new boolean[1][1][1]; boolean[] val1 = get1(); c.v[0][0] = new boolean[1]; boolean[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new boolean[1][1][1]; boolean[][] val1 = get2(); c.v[0] = new boolean[1][1]; boolean[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -306,37 +337,37 @@ c.v = new boolean[1][1][1][1]; c.v[0][0][0][0] = true; boolean val1 = get(); c.v[0][0][0][0] = false; boolean val2 = get(); assertEquals(val1, true); - assertEquals(val2, (isStableEnabled ? true : false)); + assertEquals(val2, (isServerWithStable ? true : false)); c.v = new boolean[1][1][1][1]; c.v[0][0][0][0] = false; boolean val3 = get(); - assertEquals(val3, (isStableEnabled ? true : false)); + assertEquals(val3, (isServerWithStable ? true : false)); c.v[0] = new boolean[1][1][1]; c.v[0][0][0][0] = false; boolean val4 = get(); - assertEquals(val4, (isStableEnabled ? true : false)); + assertEquals(val4, (isServerWithStable ? true : false)); c.v[0][0] = new boolean[1][1]; c.v[0][0][0][0] = false; boolean val5 = get(); - assertEquals(val5, (isStableEnabled ? true : false)); + assertEquals(val5, (isServerWithStable ? true : false)); c.v[0][0][0] = new boolean[1]; c.v[0][0][0][0] = false; boolean val6 = get(); - assertEquals(val6, (isStableEnabled ? true : false)); + assertEquals(val6, (isServerWithStable ? true : false)); } { c.v = new boolean[1][1][1][1]; boolean[] val1 = get1(); c.v[0][0][0] = new boolean[1]; boolean[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new boolean[1][1][1][1]; boolean[][] val1 = get2(); c.v[0][0] = new boolean[1][1]; boolean[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new boolean[1][1][1][1]; boolean[][][] val1 = get3(); c.v[0] = new boolean[1][1][1]; boolean[][][] val2 = get3(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -399,7 +430,7 @@ c.v = new boolean[1][1]; c.v[0] = new boolean[0]; boolean[] val1 = get1(); c.v[0] = new boolean[0]; boolean[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -435,14 +466,14 @@ c.v = new boolean[1][1][1]; c.v[0][0] = new boolean[0]; boolean[] val1 = get1(); c.v[0][0] = new boolean[0]; boolean[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new boolean[1][1][1]; c.v[0] = new boolean[0][0]; boolean[][] val1 = get2(); c.v[0] = new boolean[0][0]; boolean[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -577,7 +608,7 @@ elem.a = false; boolean val3 = get(); boolean val4 = get1(); assertEquals(val1, true); - assertEquals(val3, (isStableEnabled ? true : false)); + assertEquals(val3, (isServerWithStable ? true : false)); assertEquals(val2, true); assertEquals(val4, false); @@ -611,17 +642,4 @@ } } } - - static final boolean isStableEnabled; - static { - HotSpotDiagnosticMXBean diagnostic - = ManagementFactoryHelper.getDiagnosticMXBean(); - VMOption tmp; - try { - tmp = diagnostic.getVMOption("FoldStableValues"); - } catch (IllegalArgumentException e) { - tmp = null; - } - isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue())); - } } diff -r b67a3f81b630 -r d952af8cf67d test/compiler/stable/TestStableByte.java --- a/test/compiler/stable/TestStableByte.java Fri Jun 27 11:07:23 2014 +0100 +++ b/test/compiler/stable/TestStableByte.java Fri Jul 11 00:19:54 2014 -0700 @@ -26,9 +26,11 @@ /* * @test TestStableByte * @summary tests on stable fields and arrays - * @library /testlibrary - * @compile -XDignore.symbol.file TestStableByte.java + * @library /testlibrary /testlibrary/whitebox + * @build TestStableByte StableConfiguration sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller + * java/lang/invoke/StableConfiguration * java/lang/invoke/TestStableByte * java/lang/invoke/TestStableByte$ByteStable * java/lang/invoke/TestStableByte$StaticByteStable @@ -48,46 +50,60 @@ * java/lang/invoke/TestStableByte$NestedStableField3 * java/lang/invoke/TestStableByte$NestedStableField3$A * java/lang/invoke/TestStableByte$DefaultValue + * java/lang/invoke/TestStableByte$DefaultStaticValue * java/lang/invoke/TestStableByte$ObjectArrayLowerDim2 * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableByte + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableByte * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableByte + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableByte * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableByte - * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableByte */ package java.lang.invoke; -import com.sun.management.HotSpotDiagnosticMXBean; -import com.sun.management.VMOption; -import sun.management.ManagementFactoryHelper; import java.lang.reflect.InvocationTargetException; public class TestStableByte { + static final boolean isStableEnabled = StableConfiguration.isStableEnabled; + static final boolean isServerWithStable = StableConfiguration.isServerWithStable; + public static void main(String[] args) throws Exception { - System.out.println("@Stable enabled: "+isStableEnabled); - System.out.println(); - run(DefaultValue.class); run(ByteStable.class); + run(DefaultStaticValue.class); run(StaticByteStable.class); run(VolatileByteStable.class); @@ -145,6 +161,21 @@ /* ==================================================== */ + static class DefaultStaticValue { + public static @Stable byte v; + + public static final DefaultStaticValue c = new DefaultStaticValue(); + public static byte get() { return c.v; } + public static void test() throws Exception { + byte val1 = get(); + c.v = 1; byte val2 = get(); + assertEquals(val1, 0); + assertEquals(val2, 1); + } + } + + /* ==================================================== */ + static class StaticByteStable { public static @Stable byte v; @@ -188,20 +219,22 @@ c.v = new byte[1]; c.v[0] = 1; byte val1 = get(); c.v[0] = 2; byte val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new byte[1]; c.v[0] = 3; byte val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); } { c.v = new byte[20]; c.v[10] = 1; byte val1 = get1(); c.v[10] = 2; byte val2 = get1(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new byte[20]; c.v[10] = 3; byte val3 = get1(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); } { @@ -226,19 +259,21 @@ c.v = new byte[1][1]; c.v[0][0] = 1; byte val1 = get(); c.v[0][0] = 2; byte val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new byte[1][1]; c.v[0][0] = 3; byte val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); c.v[0] = new byte[1]; c.v[0][0] = 4; byte val4 = get(); - assertEquals(val4, (isStableEnabled ? 1 : 4)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 4)); } { c.v = new byte[1][1]; byte[] val1 = get1(); c.v[0] = new byte[1]; byte[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -264,28 +299,31 @@ c.v = new byte[1][1][1]; c.v[0][0][0] = 1; byte val1 = get(); c.v[0][0][0] = 2; byte val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new byte[1][1][1]; c.v[0][0][0] = 3; byte val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); c.v[0] = new byte[1][1]; c.v[0][0][0] = 4; byte val4 = get(); - assertEquals(val4, (isStableEnabled ? 1 : 4)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 4)); c.v[0][0] = new byte[1]; c.v[0][0][0] = 5; byte val5 = get(); - assertEquals(val5, (isStableEnabled ? 1 : 5)); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 5)); } { c.v = new byte[1][1][1]; byte[] val1 = get1(); c.v[0][0] = new byte[1]; byte[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new byte[1][1][1]; byte[][] val1 = get2(); c.v[0] = new byte[1][1]; byte[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -312,37 +350,41 @@ c.v = new byte[1][1][1][1]; c.v[0][0][0][0] = 1; byte val1 = get(); c.v[0][0][0][0] = 2; byte val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new byte[1][1][1][1]; c.v[0][0][0][0] = 3; byte val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); c.v[0] = new byte[1][1][1]; c.v[0][0][0][0] = 4; byte val4 = get(); - assertEquals(val4, (isStableEnabled ? 1 : 4)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 4)); c.v[0][0] = new byte[1][1]; c.v[0][0][0][0] = 5; byte val5 = get(); - assertEquals(val5, (isStableEnabled ? 1 : 5)); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 5)); c.v[0][0][0] = new byte[1]; c.v[0][0][0][0] = 6; byte val6 = get(); - assertEquals(val6, (isStableEnabled ? 1 : 6)); + assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 6)); } { c.v = new byte[1][1][1][1]; byte[] val1 = get1(); c.v[0][0][0] = new byte[1]; byte[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new byte[1][1][1][1]; byte[][] val1 = get2(); c.v[0][0] = new byte[1][1]; byte[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new byte[1][1][1][1]; byte[][][] val1 = get3(); c.v[0] = new byte[1][1][1]; byte[][][] val2 = get3(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -404,7 +446,7 @@ c.v = new byte[1][1]; c.v[0] = new byte[0]; byte[] val1 = get1(); c.v[0] = new byte[0]; byte[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -440,14 +482,14 @@ c.v = new byte[1][1][1]; c.v[0][0] = new byte[0]; byte[] val1 = get1(); c.v[0][0] = new byte[0]; byte[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new byte[1][1][1]; c.v[0] = new byte[0][0]; byte[][] val1 = get2(); c.v[0] = new byte[0][0]; byte[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -582,7 +624,7 @@ elem.a = 2; byte val3 = get(); byte val4 = get1(); assertEquals(val1, 1); - assertEquals(val3, (isStableEnabled ? 1 : 2)); + assertEquals(val3, (isServerWithStable ? 1 : 2)); assertEquals(val2, 1); assertEquals(val4, 2); @@ -616,17 +658,4 @@ } } } - - static final boolean isStableEnabled; - static { - HotSpotDiagnosticMXBean diagnostic - = ManagementFactoryHelper.getDiagnosticMXBean(); - VMOption tmp; - try { - tmp = diagnostic.getVMOption("FoldStableValues"); - } catch (IllegalArgumentException e) { - tmp = null; - } - isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue())); - } } diff -r b67a3f81b630 -r d952af8cf67d test/compiler/stable/TestStableChar.java --- a/test/compiler/stable/TestStableChar.java Fri Jun 27 11:07:23 2014 +0100 +++ b/test/compiler/stable/TestStableChar.java Fri Jul 11 00:19:54 2014 -0700 @@ -26,9 +26,11 @@ /* * @test TestStableChar * @summary tests on stable fields and arrays - * @library /testlibrary - * @compile -XDignore.symbol.file TestStableChar.java + * @library /testlibrary /testlibrary/whitebox + * @build TestStableChar StableConfiguration sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller + * java/lang/invoke/StableConfiguration * java/lang/invoke/TestStableChar * java/lang/invoke/TestStableChar$CharStable * java/lang/invoke/TestStableChar$StaticCharStable @@ -48,46 +50,60 @@ * java/lang/invoke/TestStableChar$NestedStableField3 * java/lang/invoke/TestStableChar$NestedStableField3$A * java/lang/invoke/TestStableChar$DefaultValue + * java/lang/invoke/TestStableChar$DefaultStaticValue * java/lang/invoke/TestStableChar$ObjectArrayLowerDim2 * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableChar + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableChar * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableChar + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableChar * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableChar - * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableChar */ package java.lang.invoke; -import com.sun.management.HotSpotDiagnosticMXBean; -import com.sun.management.VMOption; -import sun.management.ManagementFactoryHelper; import java.lang.reflect.InvocationTargetException; public class TestStableChar { + static final boolean isStableEnabled = StableConfiguration.isStableEnabled; + static final boolean isServerWithStable = StableConfiguration.isServerWithStable; + public static void main(String[] args) throws Exception { - System.out.println("@Stable enabled: "+isStableEnabled); - System.out.println(); - run(DefaultValue.class); run(CharStable.class); + run(DefaultStaticValue.class); run(StaticCharStable.class); run(VolatileCharStable.class); @@ -145,6 +161,21 @@ /* ==================================================== */ + static class DefaultStaticValue { + public static @Stable char v; + + public static final DefaultStaticValue c = new DefaultStaticValue(); + public static char get() { return c.v; } + public static void test() throws Exception { + char val1 = get(); + c.v = 'a'; char val2 = get(); + assertEquals(val1, 0); + assertEquals(val2, 'a'); + } + } + + /* ==================================================== */ + static class StaticCharStable { public @Stable char v; @@ -188,20 +219,22 @@ c.v = new char[1]; c.v[0] = 'a'; char val1 = get(); c.v[0] = 'b'; char val2 = get(); assertEquals(val1, 'a'); - assertEquals(val2, (isStableEnabled ? 'a' : 'b')); + assertEquals(val2, (isServerWithStable ? 'a' : 'b')); c.v = new char[1]; c.v[0] = 'c'; char val3 = get(); - assertEquals(val3, (isStableEnabled ? 'a' : 'c')); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + : 'c')); } { c.v = new char[20]; c.v[10] = 'a'; char val1 = get1(); c.v[10] = 'b'; char val2 = get1(); assertEquals(val1, 'a'); - assertEquals(val2, (isStableEnabled ? 'a' : 'b')); + assertEquals(val2, (isServerWithStable ? 'a' : 'b')); c.v = new char[20]; c.v[10] = 'c'; char val3 = get1(); - assertEquals(val3, (isStableEnabled ? 'a' : 'c')); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + : 'c')); } { @@ -226,19 +259,21 @@ c.v = new char[1][1]; c.v[0][0] = 'a'; char val1 = get(); c.v[0][0] = 'b'; char val2 = get(); assertEquals(val1, 'a'); - assertEquals(val2, (isStableEnabled ? 'a' : 'b')); + assertEquals(val2, (isServerWithStable ? 'a' : 'b')); c.v = new char[1][1]; c.v[0][0] = 'c'; char val3 = get(); - assertEquals(val3, (isStableEnabled ? 'a' : 'c')); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + : 'c')); c.v[0] = new char[1]; c.v[0][0] = 'd'; char val4 = get(); - assertEquals(val4, (isStableEnabled ? 'a' : 'd')); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + : 'd')); } { c.v = new char[1][1]; char[] val1 = get1(); c.v[0] = new char[1]; char[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -264,28 +299,31 @@ c.v = new char[1][1][1]; c.v[0][0][0] = 'a'; char val1 = get(); c.v[0][0][0] = 'b'; char val2 = get(); assertEquals(val1, 'a'); - assertEquals(val2, (isStableEnabled ? 'a' : 'b')); + assertEquals(val2, (isServerWithStable ? 'a' : 'b')); c.v = new char[1][1][1]; c.v[0][0][0] = 'c'; char val3 = get(); - assertEquals(val3, (isStableEnabled ? 'a' : 'c')); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + : 'c')); c.v[0] = new char[1][1]; c.v[0][0][0] = 'd'; char val4 = get(); - assertEquals(val4, (isStableEnabled ? 'a' : 'd')); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + : 'd')); c.v[0][0] = new char[1]; c.v[0][0][0] = 'e'; char val5 = get(); - assertEquals(val5, (isStableEnabled ? 'a' : 'e')); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + : 'e')); } { c.v = new char[1][1][1]; char[] val1 = get1(); c.v[0][0] = new char[1]; char[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new char[1][1][1]; char[][] val1 = get2(); c.v[0] = new char[1][1]; char[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -312,37 +350,41 @@ c.v = new char[1][1][1][1]; c.v[0][0][0][0] = 'a'; char val1 = get(); c.v[0][0][0][0] = 'b'; char val2 = get(); assertEquals(val1, 'a'); - assertEquals(val2, (isStableEnabled ? 'a' : 'b')); + assertEquals(val2, (isServerWithStable ? 'a' : 'b')); c.v = new char[1][1][1][1]; c.v[0][0][0][0] = 'c'; char val3 = get(); - assertEquals(val3, (isStableEnabled ? 'a' : 'c')); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + : 'c')); c.v[0] = new char[1][1][1]; c.v[0][0][0][0] = 'd'; char val4 = get(); - assertEquals(val4, (isStableEnabled ? 'a' : 'd')); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + : 'd')); c.v[0][0] = new char[1][1]; c.v[0][0][0][0] = 'e'; char val5 = get(); - assertEquals(val5, (isStableEnabled ? 'a' : 'e')); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + : 'e')); c.v[0][0][0] = new char[1]; c.v[0][0][0][0] = 'f'; char val6 = get(); - assertEquals(val6, (isStableEnabled ? 'a' : 'f')); + assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + : 'f')); } { c.v = new char[1][1][1][1]; char[] val1 = get1(); c.v[0][0][0] = new char[1]; char[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new char[1][1][1][1]; char[][] val1 = get2(); c.v[0][0] = new char[1][1]; char[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new char[1][1][1][1]; char[][][] val1 = get3(); c.v[0] = new char[1][1][1]; char[][][] val2 = get3(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -350,7 +392,6 @@ c.v = new char[1][1][1][1]; char[][][][] val2 = get4(); assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } - } } @@ -403,7 +444,7 @@ c.v = new char[1][1]; c.v[0] = new char[0]; char[] val1 = get1(); c.v[0] = new char[0]; char[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -439,14 +480,14 @@ c.v = new char[1][1][1]; c.v[0][0] = new char[0]; char[] val1 = get1(); c.v[0][0] = new char[0]; char[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new char[1][1][1]; c.v[0] = new char[0][0]; char[][] val1 = get2(); c.v[0] = new char[0][0]; char[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -581,7 +622,7 @@ elem.a = 'b'; char val3 = get(); char val4 = get1(); assertEquals(val1, 'a'); - assertEquals(val3, (isStableEnabled ? 'a' : 'b')); + assertEquals(val3, (isServerWithStable ? 'a' : 'b')); assertEquals(val2, 'a'); assertEquals(val4, 'b'); @@ -615,17 +656,4 @@ } } } - - static final boolean isStableEnabled; - static { - HotSpotDiagnosticMXBean diagnostic - = ManagementFactoryHelper.getDiagnosticMXBean(); - VMOption tmp; - try { - tmp = diagnostic.getVMOption("FoldStableValues"); - } catch (IllegalArgumentException e) { - tmp = null; - } - isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue())); - } } diff -r b67a3f81b630 -r d952af8cf67d test/compiler/stable/TestStableDouble.java --- a/test/compiler/stable/TestStableDouble.java Fri Jun 27 11:07:23 2014 +0100 +++ b/test/compiler/stable/TestStableDouble.java Fri Jul 11 00:19:54 2014 -0700 @@ -26,9 +26,11 @@ /* * @test TestStableDouble * @summary tests on stable fields and arrays - * @library /testlibrary - * @compile -XDignore.symbol.file TestStableDouble.java + * @library /testlibrary /testlibrary/whitebox + * @build TestStableDouble StableConfiguration sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller + * java/lang/invoke/StableConfiguration * java/lang/invoke/TestStableDouble * java/lang/invoke/TestStableDouble$DoubleStable * java/lang/invoke/TestStableDouble$StaticDoubleStable @@ -48,46 +50,60 @@ * java/lang/invoke/TestStableDouble$NestedStableField3 * java/lang/invoke/TestStableDouble$NestedStableField3$A * java/lang/invoke/TestStableDouble$DefaultValue + * java/lang/invoke/TestStableDouble$DefaultStaticValue * java/lang/invoke/TestStableDouble$ObjectArrayLowerDim2 * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableDouble + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableDouble * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableDouble + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableDouble * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableDouble - * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableDouble */ package java.lang.invoke; -import com.sun.management.HotSpotDiagnosticMXBean; -import com.sun.management.VMOption; -import sun.management.ManagementFactoryHelper; import java.lang.reflect.InvocationTargetException; public class TestStableDouble { + static final boolean isStableEnabled = StableConfiguration.isStableEnabled; + static final boolean isServerWithStable = StableConfiguration.isServerWithStable; + public static void main(String[] args) throws Exception { - System.out.println("@Stable enabled: "+isStableEnabled); - System.out.println(); - run(DefaultValue.class); run(DoubleStable.class); + run(DefaultStaticValue.class); run(StaticDoubleStable.class); run(VolatileDoubleStable.class); @@ -145,6 +161,21 @@ /* ==================================================== */ + static class DefaultStaticValue { + public static @Stable double v; + + public static final DefaultStaticValue c = new DefaultStaticValue(); + public static double get() { return c.v; } + public static void test() throws Exception { + double val1 = get(); + c.v = 1.0; double val2 = get(); + assertEquals(val1, 0); + assertEquals(val2, 1.0); + } + } + + /* ==================================================== */ + static class StaticDoubleStable { public static @Stable double v; @@ -188,20 +219,22 @@ c.v = new double[1]; c.v[0] = 1.0; double val1 = get(); c.v[0] = 2.0; double val2 = get(); assertEquals(val1, 1.0); - assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); + assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); c.v = new double[1]; c.v[0] = 3.0; double val3 = get(); - assertEquals(val3, (isStableEnabled ? 1.0 : 3.0)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + : 3.0)); } { c.v = new double[20]; c.v[10] = 1.0; double val1 = get1(); c.v[10] = 2.0; double val2 = get1(); assertEquals(val1, 1.0); - assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); + assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); c.v = new double[20]; c.v[10] = 3.0; double val3 = get1(); - assertEquals(val3, (isStableEnabled ? 1.0 : 3.0)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + : 3.0)); } { @@ -226,19 +259,21 @@ c.v = new double[1][1]; c.v[0][0] = 1.0; double val1 = get(); c.v[0][0] = 2.0; double val2 = get(); assertEquals(val1, 1.0); - assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); + assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); c.v = new double[1][1]; c.v[0][0] = 3.0; double val3 = get(); - assertEquals(val3, (isStableEnabled ? 1.0 : 3.0)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + : 3.0)); c.v[0] = new double[1]; c.v[0][0] = 4.0; double val4 = get(); - assertEquals(val4, (isStableEnabled ? 1.0 : 4.0)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + : 4.0)); } { c.v = new double[1][1]; double[] val1 = get1(); c.v[0] = new double[1]; double[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -264,28 +299,31 @@ c.v = new double[1][1][1]; c.v[0][0][0] = 1.0; double val1 = get(); c.v[0][0][0] = 2.0; double val2 = get(); assertEquals(val1, 1.0); - assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); + assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); c.v = new double[1][1][1]; c.v[0][0][0] = 3.0; double val3 = get(); - assertEquals(val3, (isStableEnabled ? 1.0 : 3.0)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + : 3.0)); c.v[0] = new double[1][1]; c.v[0][0][0] = 4.0; double val4 = get(); - assertEquals(val4, (isStableEnabled ? 1.0 : 4.0)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + : 4.0)); c.v[0][0] = new double[1]; c.v[0][0][0] = 5.0; double val5 = get(); - assertEquals(val5, (isStableEnabled ? 1.0 : 5.0)); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + : 5.0)); } { c.v = new double[1][1][1]; double[] val1 = get1(); c.v[0][0] = new double[1]; double[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new double[1][1][1]; double[][] val1 = get2(); c.v[0] = new double[1][1]; double[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -312,37 +350,41 @@ c.v = new double[1][1][1][1]; c.v[0][0][0][0] = 1.0; double val1 = get(); c.v[0][0][0][0] = 2.0; double val2 = get(); assertEquals(val1, 1.0); - assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); + assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); c.v = new double[1][1][1][1]; c.v[0][0][0][0] = 3.0; double val3 = get(); - assertEquals(val3, (isStableEnabled ? 1.0 : 3.0)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + : 3.0)); c.v[0] = new double[1][1][1]; c.v[0][0][0][0] = 4.0; double val4 = get(); - assertEquals(val4, (isStableEnabled ? 1.0 : 4.0)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + : 4.0)); c.v[0][0] = new double[1][1]; c.v[0][0][0][0] = 5.0; double val5 = get(); - assertEquals(val5, (isStableEnabled ? 1.0 : 5.0)); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + : 5.0)); c.v[0][0][0] = new double[1]; c.v[0][0][0][0] = 6.0; double val6 = get(); - assertEquals(val6, (isStableEnabled ? 1.0 : 6.0)); + assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + : 6.0)); } { c.v = new double[1][1][1][1]; double[] val1 = get1(); c.v[0][0][0] = new double[1]; double[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new double[1][1][1][1]; double[][] val1 = get2(); c.v[0][0] = new double[1][1]; double[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new double[1][1][1][1]; double[][][] val1 = get3(); c.v[0] = new double[1][1][1]; double[][][] val2 = get3(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -350,13 +392,11 @@ c.v = new double[1][1][1][1]; double[][][][] val2 = get4(); assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } - } } /* ==================================================== */ // Dynamic Dim is higher than static - static class ObjectArrayLowerDim0 { public @Stable Object v; @@ -404,7 +444,7 @@ c.v = new double[1][1]; c.v[0] = new double[0]; double[] val1 = get1(); c.v[0] = new double[0]; double[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -440,14 +480,14 @@ c.v = new double[1][1][1]; c.v[0][0] = new double[0]; double[] val1 = get1(); c.v[0][0] = new double[0]; double[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new double[1][1][1]; c.v[0] = new double[0][0]; double[][] val1 = get2(); c.v[0] = new double[0][0]; double[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -582,7 +622,7 @@ elem.a = 2.0; double val3 = get(); double val4 = get1(); assertEquals(val1, 1.0); - assertEquals(val3, (isStableEnabled ? 1.0 : 2.0)); + assertEquals(val3, (isServerWithStable ? 1.0 : 2.0)); assertEquals(val2, 1.0); assertEquals(val4, 2.0); @@ -616,17 +656,4 @@ } } } - - static final boolean isStableEnabled; - static { - HotSpotDiagnosticMXBean diagnostic - = ManagementFactoryHelper.getDiagnosticMXBean(); - VMOption tmp; - try { - tmp = diagnostic.getVMOption("FoldStableValues"); - } catch (IllegalArgumentException e) { - tmp = null; - } - isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue())); - } } diff -r b67a3f81b630 -r d952af8cf67d test/compiler/stable/TestStableFloat.java --- a/test/compiler/stable/TestStableFloat.java Fri Jun 27 11:07:23 2014 +0100 +++ b/test/compiler/stable/TestStableFloat.java Fri Jul 11 00:19:54 2014 -0700 @@ -26,9 +26,11 @@ /* * @test TestStableFloat * @summary tests on stable fields and arrays - * @library /testlibrary - * @compile -XDignore.symbol.file TestStableFloat.java + * @library /testlibrary /testlibrary/whitebox + * @build TestStableFloat StableConfiguration sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller + * java/lang/invoke/StableConfiguration * java/lang/invoke/TestStableFloat * java/lang/invoke/TestStableFloat$FloatStable * java/lang/invoke/TestStableFloat$StaticFloatStable @@ -48,46 +50,60 @@ * java/lang/invoke/TestStableFloat$NestedStableField3 * java/lang/invoke/TestStableFloat$NestedStableField3$A * java/lang/invoke/TestStableFloat$DefaultValue + * java/lang/invoke/TestStableFloat$DefaultStaticValue * java/lang/invoke/TestStableFloat$ObjectArrayLowerDim2 * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableFloat + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableFloat * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableFloat + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableFloat * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableFloat - * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableFloat */ package java.lang.invoke; -import com.sun.management.HotSpotDiagnosticMXBean; -import com.sun.management.VMOption; -import sun.management.ManagementFactoryHelper; import java.lang.reflect.InvocationTargetException; public class TestStableFloat { + static final boolean isStableEnabled = StableConfiguration.isStableEnabled; + static final boolean isServerWithStable = StableConfiguration.isServerWithStable; + public static void main(String[] args) throws Exception { - System.out.println("@Stable enabled: "+isStableEnabled); - System.out.println(); - run(DefaultValue.class); run(FloatStable.class); + run(DefaultStaticValue.class); run(StaticFloatStable.class); run(VolatileFloatStable.class); @@ -145,6 +161,21 @@ /* ==================================================== */ + static class DefaultStaticValue { + public static @Stable float v; + + public static final DefaultStaticValue c = new DefaultStaticValue(); + public static float get() { return c.v; } + public static void test() throws Exception { + float val1 = get(); + c.v = 1.0F; float val2 = get(); + assertEquals(val1, 0F); + assertEquals(val2, 1.0F); + } + } + + /* ==================================================== */ + static class StaticFloatStable { public static @Stable float v; @@ -188,20 +219,22 @@ c.v = new float[1]; c.v[0] = 1.0F; float val1 = get(); c.v[0] = 2.0F; float val2 = get(); assertEquals(val1, 1.0F); - assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); + assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); c.v = new float[1]; c.v[0] = 3.0F; float val3 = get(); - assertEquals(val3, (isStableEnabled ? 1.0F : 3.0F)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + : 3.0F)); } { c.v = new float[20]; c.v[10] = 1.0F; float val1 = get1(); c.v[10] = 2.0F; float val2 = get1(); assertEquals(val1, 1.0F); - assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); + assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); c.v = new float[20]; c.v[10] = 3.0F; float val3 = get1(); - assertEquals(val3, (isStableEnabled ? 1.0F : 3.0F)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + : 3.0F)); } { @@ -226,19 +259,21 @@ c.v = new float[1][1]; c.v[0][0] = 1.0F; float val1 = get(); c.v[0][0] = 2.0F; float val2 = get(); assertEquals(val1, 1.0F); - assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); + assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); c.v = new float[1][1]; c.v[0][0] = 3.0F; float val3 = get(); - assertEquals(val3, (isStableEnabled ? 1.0F : 3.0F)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + : 3.0F)); c.v[0] = new float[1]; c.v[0][0] = 4.0F; float val4 = get(); - assertEquals(val4, (isStableEnabled ? 1.0F : 4.0F)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + : 4.0F)); } { c.v = new float[1][1]; float[] val1 = get1(); c.v[0] = new float[1]; float[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -264,28 +299,31 @@ c.v = new float[1][1][1]; c.v[0][0][0] = 1.0F; float val1 = get(); c.v[0][0][0] = 2.0F; float val2 = get(); assertEquals(val1, 1.0F); - assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); + assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); c.v = new float[1][1][1]; c.v[0][0][0] = 3.0F; float val3 = get(); - assertEquals(val3, (isStableEnabled ? 1.0F : 3.0F)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + : 3.0F)); c.v[0] = new float[1][1]; c.v[0][0][0] = 4.0F; float val4 = get(); - assertEquals(val4, (isStableEnabled ? 1.0F : 4.0F)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + : 4.0F)); c.v[0][0] = new float[1]; c.v[0][0][0] = 5.0F; float val5 = get(); - assertEquals(val5, (isStableEnabled ? 1.0F : 5.0F)); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + : 5.0F)); } { c.v = new float[1][1][1]; float[] val1 = get1(); c.v[0][0] = new float[1]; float[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new float[1][1][1]; float[][] val1 = get2(); c.v[0] = new float[1][1]; float[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -312,37 +350,41 @@ c.v = new float[1][1][1][1]; c.v[0][0][0][0] = 1.0F; float val1 = get(); c.v[0][0][0][0] = 2.0F; float val2 = get(); assertEquals(val1, 1.0F); - assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); + assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); c.v = new float[1][1][1][1]; c.v[0][0][0][0] = 3.0F; float val3 = get(); - assertEquals(val3, (isStableEnabled ? 1.0F : 3.0F)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + : 3.0F)); c.v[0] = new float[1][1][1]; c.v[0][0][0][0] = 4.0F; float val4 = get(); - assertEquals(val4, (isStableEnabled ? 1.0F : 4.0F)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + : 4.0F)); c.v[0][0] = new float[1][1]; c.v[0][0][0][0] = 5.0F; float val5 = get(); - assertEquals(val5, (isStableEnabled ? 1.0F : 5.0F)); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + : 5.0F)); c.v[0][0][0] = new float[1]; c.v[0][0][0][0] = 6.0F; float val6 = get(); - assertEquals(val6, (isStableEnabled ? 1.0F : 6.0F)); + assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + : 6.0F)); } { c.v = new float[1][1][1][1]; float[] val1 = get1(); c.v[0][0][0] = new float[1]; float[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new float[1][1][1][1]; float[][] val1 = get2(); c.v[0][0] = new float[1][1]; float[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new float[1][1][1][1]; float[][][] val1 = get3(); c.v[0] = new float[1][1][1]; float[][][] val2 = get3(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -350,13 +392,11 @@ c.v = new float[1][1][1][1]; float[][][][] val2 = get4(); assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } - } } /* ==================================================== */ // Dynamic Dim is higher than static - static class ObjectArrayLowerDim0 { public @Stable Object v; @@ -404,7 +444,7 @@ c.v = new float[1][1]; c.v[0] = new float[0]; float[] val1 = get1(); c.v[0] = new float[0]; float[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -440,14 +480,14 @@ c.v = new float[1][1][1]; c.v[0][0] = new float[0]; float[] val1 = get1(); c.v[0][0] = new float[0]; float[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new float[1][1][1]; c.v[0] = new float[0][0]; float[][] val1 = get2(); c.v[0] = new float[0][0]; float[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -582,7 +622,7 @@ elem.a = 2.0F; float val3 = get(); float val4 = get1(); assertEquals(val1, 1.0F); - assertEquals(val3, (isStableEnabled ? 1.0F : 2.0F)); + assertEquals(val3, (isServerWithStable ? 1.0F : 2.0F)); assertEquals(val2, 1.0F); assertEquals(val4, 2.0F); @@ -616,17 +656,4 @@ } } } - - static final boolean isStableEnabled; - static { - HotSpotDiagnosticMXBean diagnostic - = ManagementFactoryHelper.getDiagnosticMXBean(); - VMOption tmp; - try { - tmp = diagnostic.getVMOption("FoldStableValues"); - } catch (IllegalArgumentException e) { - tmp = null; - } - isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue())); - } } diff -r b67a3f81b630 -r d952af8cf67d test/compiler/stable/TestStableInt.java --- a/test/compiler/stable/TestStableInt.java Fri Jun 27 11:07:23 2014 +0100 +++ b/test/compiler/stable/TestStableInt.java Fri Jul 11 00:19:54 2014 -0700 @@ -26,9 +26,11 @@ /* * @test TestStableInt * @summary tests on stable fields and arrays - * @library /testlibrary - * @compile -XDignore.symbol.file TestStableInt.java + * @library /testlibrary /testlibrary/whitebox + * @build TestStableInt StableConfiguration sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller + * java/lang/invoke/StableConfiguration * java/lang/invoke/TestStableInt * java/lang/invoke/TestStableInt$IntStable * java/lang/invoke/TestStableInt$StaticIntStable @@ -48,46 +50,60 @@ * java/lang/invoke/TestStableInt$NestedStableField3 * java/lang/invoke/TestStableInt$NestedStableField3$A * java/lang/invoke/TestStableInt$DefaultValue + * java/lang/invoke/TestStableInt$DefaultStaticValue * java/lang/invoke/TestStableInt$ObjectArrayLowerDim2 * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableInt + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableInt * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableInt + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableInt * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableInt - * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableInt */ package java.lang.invoke; -import com.sun.management.HotSpotDiagnosticMXBean; -import com.sun.management.VMOption; -import sun.management.ManagementFactoryHelper; import java.lang.reflect.InvocationTargetException; public class TestStableInt { + static final boolean isStableEnabled = StableConfiguration.isStableEnabled; + static final boolean isServerWithStable = StableConfiguration.isServerWithStable; + public static void main(String[] args) throws Exception { - System.out.println("@Stable enabled: "+isStableEnabled); - System.out.println(); - run(DefaultValue.class); run(IntStable.class); + run(DefaultStaticValue.class); run(StaticIntStable.class); run(VolatileIntStable.class); @@ -145,6 +161,21 @@ /* ==================================================== */ + static class DefaultStaticValue { + public static @Stable int v; + + public static final DefaultStaticValue c = new DefaultStaticValue(); + public static int get() { return c.v; } + public static void test() throws Exception { + int val1 = get(); + c.v = 1; int val2 = get(); + assertEquals(val1, 0); + assertEquals(val2, 1); + } + } + + /* ==================================================== */ + static class StaticIntStable { public static @Stable int v; @@ -188,20 +219,22 @@ c.v = new int[1]; c.v[0] = 1; int val1 = get(); c.v[0] = 2; int val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new int[1]; c.v[0] = 3; int val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); } { c.v = new int[20]; c.v[10] = 1; int val1 = get1(); c.v[10] = 2; int val2 = get1(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new int[20]; c.v[10] = 3; int val3 = get1(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); } { @@ -226,19 +259,21 @@ c.v = new int[1][1]; c.v[0][0] = 1; int val1 = get(); c.v[0][0] = 2; int val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new int[1][1]; c.v[0][0] = 3; int val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); c.v[0] = new int[1]; c.v[0][0] = 4; int val4 = get(); - assertEquals(val4, (isStableEnabled ? 1 : 4)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 4)); } { c.v = new int[1][1]; int[] val1 = get1(); c.v[0] = new int[1]; int[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -264,28 +299,31 @@ c.v = new int[1][1][1]; c.v[0][0][0] = 1; int val1 = get(); c.v[0][0][0] = 2; int val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new int[1][1][1]; c.v[0][0][0] = 3; int val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); c.v[0] = new int[1][1]; c.v[0][0][0] = 4; int val4 = get(); - assertEquals(val4, (isStableEnabled ? 1 : 4)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 4)); c.v[0][0] = new int[1]; c.v[0][0][0] = 5; int val5 = get(); - assertEquals(val5, (isStableEnabled ? 1 : 5)); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 5)); } { c.v = new int[1][1][1]; int[] val1 = get1(); c.v[0][0] = new int[1]; int[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new int[1][1][1]; int[][] val1 = get2(); c.v[0] = new int[1][1]; int[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -312,37 +350,41 @@ c.v = new int[1][1][1][1]; c.v[0][0][0][0] = 1; int val1 = get(); c.v[0][0][0][0] = 2; int val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new int[1][1][1][1]; c.v[0][0][0][0] = 3; int val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); c.v[0] = new int[1][1][1]; c.v[0][0][0][0] = 4; int val4 = get(); - assertEquals(val4, (isStableEnabled ? 1 : 4)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 4)); c.v[0][0] = new int[1][1]; c.v[0][0][0][0] = 5; int val5 = get(); - assertEquals(val5, (isStableEnabled ? 1 : 5)); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 5)); c.v[0][0][0] = new int[1]; c.v[0][0][0][0] = 6; int val6 = get(); - assertEquals(val6, (isStableEnabled ? 1 : 6)); + assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 6)); } { c.v = new int[1][1][1][1]; int[] val1 = get1(); c.v[0][0][0] = new int[1]; int[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new int[1][1][1][1]; int[][] val1 = get2(); c.v[0][0] = new int[1][1]; int[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new int[1][1][1][1]; int[][][] val1 = get3(); c.v[0] = new int[1][1][1]; int[][][] val2 = get3(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -350,13 +392,11 @@ c.v = new int[1][1][1][1]; int[][][][] val2 = get4(); assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } - } } /* ==================================================== */ // Dynamic Dim is higher than static - static class ObjectArrayLowerDim0 { public @Stable Object v; @@ -404,7 +444,7 @@ c.v = new int[1][1]; c.v[0] = new int[0]; int[] val1 = get1(); c.v[0] = new int[0]; int[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -440,14 +480,14 @@ c.v = new int[1][1][1]; c.v[0][0] = new int[0]; int[] val1 = get1(); c.v[0][0] = new int[0]; int[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new int[1][1][1]; c.v[0] = new int[0][0]; int[][] val1 = get2(); c.v[0] = new int[0][0]; int[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -582,7 +622,7 @@ elem.a = 2; int val3 = get(); int val4 = get1(); assertEquals(val1, 1); - assertEquals(val3, (isStableEnabled ? 1 : 2)); + assertEquals(val3, (isServerWithStable ? 1 : 2)); assertEquals(val2, 1); assertEquals(val4, 2); @@ -616,17 +656,4 @@ } } } - - static final boolean isStableEnabled; - static { - HotSpotDiagnosticMXBean diagnostic - = ManagementFactoryHelper.getDiagnosticMXBean(); - VMOption tmp; - try { - tmp = diagnostic.getVMOption("FoldStableValues"); - } catch (IllegalArgumentException e) { - tmp = null; - } - isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue())); - } } diff -r b67a3f81b630 -r d952af8cf67d test/compiler/stable/TestStableLong.java --- a/test/compiler/stable/TestStableLong.java Fri Jun 27 11:07:23 2014 +0100 +++ b/test/compiler/stable/TestStableLong.java Fri Jul 11 00:19:54 2014 -0700 @@ -26,9 +26,11 @@ /* * @test TestStableLong * @summary tests on stable fields and arrays - * @library /testlibrary - * @compile -XDignore.symbol.file TestStableLong.java + * @library /testlibrary /testlibrary/whitebox + * @build TestStableLong StableConfiguration sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller + * java/lang/invoke/StableConfiguration * java/lang/invoke/TestStableLong * java/lang/invoke/TestStableLong$LongStable * java/lang/invoke/TestStableLong$StaticLongStable @@ -48,46 +50,60 @@ * java/lang/invoke/TestStableLong$NestedStableField3 * java/lang/invoke/TestStableLong$NestedStableField3$A * java/lang/invoke/TestStableLong$DefaultValue + * java/lang/invoke/TestStableLong$DefaultStaticValue * java/lang/invoke/TestStableLong$ObjectArrayLowerDim2 * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableLong + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableLong * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableLong + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableLong * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableLong - * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableLong */ package java.lang.invoke; -import com.sun.management.HotSpotDiagnosticMXBean; -import com.sun.management.VMOption; -import sun.management.ManagementFactoryHelper; import java.lang.reflect.InvocationTargetException; public class TestStableLong { + static final boolean isStableEnabled = StableConfiguration.isStableEnabled; + static final boolean isServerWithStable = StableConfiguration.isServerWithStable; + public static void main(String[] args) throws Exception { - System.out.println("@Stable enabled: "+isStableEnabled); - System.out.println(); - run(DefaultValue.class); run(LongStable.class); + run(DefaultStaticValue.class); run(StaticLongStable.class); run(VolatileLongStable.class); @@ -145,6 +161,21 @@ /* ==================================================== */ + static class DefaultStaticValue { + public static @Stable long v; + + public static final DefaultStaticValue c = new DefaultStaticValue(); + public static long get() { return c.v; } + public static void test() throws Exception { + long val1 = get(); + c.v = 1L; long val2 = get(); + assertEquals(val1, 0); + assertEquals(val2, 1L); + } + } + + /* ==================================================== */ + static class StaticLongStable { public static @Stable long v; @@ -188,20 +219,22 @@ c.v = new long[1]; c.v[0] = 1; long val1 = get(); c.v[0] = 2; long val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new long[1]; c.v[0] = 3; long val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); } { c.v = new long[20]; c.v[10] = 1; long val1 = get1(); c.v[10] = 2; long val2 = get1(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new long[20]; c.v[10] = 3; long val3 = get1(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); } { @@ -226,19 +259,21 @@ c.v = new long[1][1]; c.v[0][0] = 1; long val1 = get(); c.v[0][0] = 2; long val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new long[1][1]; c.v[0][0] = 3; long val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); c.v[0] = new long[1]; c.v[0][0] = 4; long val4 = get(); - assertEquals(val4, (isStableEnabled ? 1 : 4)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 4)); } { c.v = new long[1][1]; long[] val1 = get1(); c.v[0] = new long[1]; long[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -264,28 +299,31 @@ c.v = new long[1][1][1]; c.v[0][0][0] = 1; long val1 = get(); c.v[0][0][0] = 2; long val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new long[1][1][1]; c.v[0][0][0] = 3; long val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); c.v[0] = new long[1][1]; c.v[0][0][0] = 4; long val4 = get(); - assertEquals(val4, (isStableEnabled ? 1 : 4)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 4)); c.v[0][0] = new long[1]; c.v[0][0][0] = 5; long val5 = get(); - assertEquals(val5, (isStableEnabled ? 1 : 5)); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 5)); } { c.v = new long[1][1][1]; long[] val1 = get1(); c.v[0][0] = new long[1]; long[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new long[1][1][1]; long[][] val1 = get2(); c.v[0] = new long[1][1]; long[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -312,37 +350,41 @@ c.v = new long[1][1][1][1]; c.v[0][0][0][0] = 1; long val1 = get(); c.v[0][0][0][0] = 2; long val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new long[1][1][1][1]; c.v[0][0][0][0] = 3; long val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); c.v[0] = new long[1][1][1]; c.v[0][0][0][0] = 4; long val4 = get(); - assertEquals(val4, (isStableEnabled ? 1 : 4)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 4)); c.v[0][0] = new long[1][1]; c.v[0][0][0][0] = 5; long val5 = get(); - assertEquals(val5, (isStableEnabled ? 1 : 5)); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 5)); c.v[0][0][0] = new long[1]; c.v[0][0][0][0] = 6; long val6 = get(); - assertEquals(val6, (isStableEnabled ? 1 : 6)); + assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 6)); } { c.v = new long[1][1][1][1]; long[] val1 = get1(); c.v[0][0][0] = new long[1]; long[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new long[1][1][1][1]; long[][] val1 = get2(); c.v[0][0] = new long[1][1]; long[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new long[1][1][1][1]; long[][][] val1 = get3(); c.v[0] = new long[1][1][1]; long[][][] val2 = get3(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -350,13 +392,11 @@ c.v = new long[1][1][1][1]; long[][][][] val2 = get4(); assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } - } } /* ==================================================== */ // Dynamic Dim is higher than static - static class ObjectArrayLowerDim0 { public @Stable Object v; @@ -404,7 +444,7 @@ c.v = new long[1][1]; c.v[0] = new long[0]; long[] val1 = get1(); c.v[0] = new long[0]; long[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -440,14 +480,14 @@ c.v = new long[1][1][1]; c.v[0][0] = new long[0]; long[] val1 = get1(); c.v[0][0] = new long[0]; long[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new long[1][1][1]; c.v[0] = new long[0][0]; long[][] val1 = get2(); c.v[0] = new long[0][0]; long[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -582,7 +622,7 @@ elem.a = 2; long val3 = get(); long val4 = get1(); assertEquals(val1, 1); - assertEquals(val3, (isStableEnabled ? 1 : 2)); + assertEquals(val3, (isServerWithStable ? 1 : 2)); assertEquals(val2, 1); assertEquals(val4, 2); @@ -616,17 +656,4 @@ } } } - - static final boolean isStableEnabled; - static { - HotSpotDiagnosticMXBean diagnostic - = ManagementFactoryHelper.getDiagnosticMXBean(); - VMOption tmp; - try { - tmp = diagnostic.getVMOption("FoldStableValues"); - } catch (IllegalArgumentException e) { - tmp = null; - } - isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue())); - } } diff -r b67a3f81b630 -r d952af8cf67d test/compiler/stable/TestStableObject.java --- a/test/compiler/stable/TestStableObject.java Fri Jun 27 11:07:23 2014 +0100 +++ b/test/compiler/stable/TestStableObject.java Fri Jul 11 00:19:54 2014 -0700 @@ -26,9 +26,11 @@ /* * @test TestStableObject * @summary tests on stable fields and arrays - * @library /testlibrary - * @compile -XDignore.symbol.file TestStableObject.java + * @library /testlibrary /testlibrary/whitebox + * @build TestStableObject StableConfiguration sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller + * java/lang/invoke/StableConfiguration * java/lang/invoke/TestStableObject * java/lang/invoke/TestStableObject$ObjectStable * java/lang/invoke/TestStableObject$StaticObjectStable @@ -49,46 +51,60 @@ * java/lang/invoke/TestStableObject$NestedStableField3$A * java/lang/invoke/TestStableObject$Values * java/lang/invoke/TestStableObject$DefaultValue + * java/lang/invoke/TestStableObject$DefaultStaticValue * java/lang/invoke/TestStableObject$ObjectArrayLowerDim2 * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableObject + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableObject * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableObject + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableObject * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableObject - * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableObject */ package java.lang.invoke; -import com.sun.management.HotSpotDiagnosticMXBean; -import com.sun.management.VMOption; -import sun.management.ManagementFactoryHelper; import java.lang.reflect.InvocationTargetException; public class TestStableObject { + static final boolean isStableEnabled = StableConfiguration.isStableEnabled; + static final boolean isServerWithStable = StableConfiguration.isServerWithStable; + public static void main(String[] args) throws Exception { - System.out.println("@Stable enabled: "+isStableEnabled); - System.out.println(); - run(DefaultValue.class); run(ObjectStable.class); + run(DefaultStaticValue.class); run(StaticObjectStable.class); run(VolatileObjectStable.class); @@ -148,6 +164,21 @@ /* ==================================================== */ + static class DefaultStaticValue { + public static @Stable Object v; + + public static final DefaultStaticValue c = new DefaultStaticValue(); + public static Object get() { return c.v; } + public static void test() throws Exception { + Object val1 = get(); + c.v = Values.A; Object val2 = get(); + assertEquals(val1, null); + assertEquals(val2, Values.A); + } + } + + /* ==================================================== */ + static class StaticObjectStable { public static @Stable Values v; @@ -191,20 +222,22 @@ c.v = new Object[1]; c.v[0] = Values.A; Object val1 = get(); c.v[0] = Values.B; Object val2 = get(); assertEquals(val1, Values.A); - assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); + assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); c.v = new Object[1]; c.v[0] = Values.C; Object val3 = get(); - assertEquals(val3, (isStableEnabled ? Values.A : Values.C)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + : Values.C)); } { c.v = new Object[20]; c.v[10] = Values.A; Object val1 = get1(); c.v[10] = Values.B; Object val2 = get1(); assertEquals(val1, Values.A); - assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); + assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); c.v = new Object[20]; c.v[10] = Values.C; Object val3 = get1(); - assertEquals(val3, (isStableEnabled ? Values.A : Values.C)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + : Values.C)); } { @@ -229,19 +262,21 @@ c.v = new Object[1][1]; c.v[0][0] = Values.A; Object val1 = get(); c.v[0][0] = Values.B; Object val2 = get(); assertEquals(val1, Values.A); - assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); + assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); c.v = new Object[1][1]; c.v[0][0] = Values.C; Object val3 = get(); - assertEquals(val3, (isStableEnabled ? Values.A : Values.C)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + : Values.C)); c.v[0] = new Object[1]; c.v[0][0] = Values.D; Object val4 = get(); - assertEquals(val4, (isStableEnabled ? Values.A : Values.D)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + : Values.D)); } { c.v = new Object[1][1]; Object[] val1 = get1(); c.v[0] = new Object[1]; Object[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -267,28 +302,31 @@ c.v = new Object[1][1][1]; c.v[0][0][0] = Values.A; Object val1 = get(); c.v[0][0][0] = Values.B; Object val2 = get(); assertEquals(val1, Values.A); - assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); + assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); c.v = new Object[1][1][1]; c.v[0][0][0] = Values.C; Object val3 = get(); - assertEquals(val3, (isStableEnabled ? Values.A : Values.C)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + : Values.C)); c.v[0] = new Object[1][1]; c.v[0][0][0] = Values.D; Object val4 = get(); - assertEquals(val4, (isStableEnabled ? Values.A : Values.D)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + : Values.D)); c.v[0][0] = new Object[1]; c.v[0][0][0] = Values.E; Object val5 = get(); - assertEquals(val5, (isStableEnabled ? Values.A : Values.E)); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + : Values.E)); } { c.v = new Object[1][1][1]; Object[] val1 = get1(); c.v[0][0] = new Object[1]; Object[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new Object[1][1][1]; Object[][] val1 = get2(); c.v[0] = new Object[1][1]; Object[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -315,37 +353,41 @@ c.v = new Object[1][1][1][1]; c.v[0][0][0][0] = Values.A; Object val1 = get(); c.v[0][0][0][0] = Values.B; Object val2 = get(); assertEquals(val1, Values.A); - assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); + assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); c.v = new Object[1][1][1][1]; c.v[0][0][0][0] = Values.C; Object val3 = get(); - assertEquals(val3, (isStableEnabled ? Values.A : Values.C)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + : Values.C)); c.v[0] = new Object[1][1][1]; c.v[0][0][0][0] = Values.D; Object val4 = get(); - assertEquals(val4, (isStableEnabled ? Values.A : Values.D)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + : Values.D)); c.v[0][0] = new Object[1][1]; c.v[0][0][0][0] = Values.E; Object val5 = get(); - assertEquals(val5, (isStableEnabled ? Values.A : Values.E)); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + : Values.E)); c.v[0][0][0] = new Object[1]; c.v[0][0][0][0] = Values.F; Object val6 = get(); - assertEquals(val6, (isStableEnabled ? Values.A : Values.F)); + assertEquals(val6, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + : Values.F)); } { c.v = new Object[1][1][1][1]; Object[] val1 = get1(); c.v[0][0][0] = new Object[1]; Object[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new Object[1][1][1][1]; Object[][] val1 = get2(); c.v[0][0] = new Object[1][1]; Object[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new Object[1][1][1][1]; Object[][][] val1 = get3(); c.v[0] = new Object[1][1][1]; Object[][][] val2 = get3(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -353,13 +395,11 @@ c.v = new Object[1][1][1][1]; Object[][][][] val2 = get4(); assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } - } } /* ==================================================== */ // Dynamic Dim is higher than static - static class ObjectArrayLowerDim0 { public @Stable Object v; @@ -407,7 +447,7 @@ c.v = new Object[1][1]; c.v[0] = new Object[0]; Object[] val1 = get1(); c.v[0] = new Object[0]; Object[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -443,14 +483,14 @@ c.v = new Object[1][1][1]; c.v[0][0] = new Object[0]; Object[] val1 = get1(); c.v[0][0] = new Object[0]; Object[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new Object[1][1][1]; c.v[0] = new Object[0][0]; Object[][] val1 = get2(); c.v[0] = new Object[0][0]; Object[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -585,7 +625,7 @@ elem.a = Values.B; Object val3 = get(); Object val4 = get1(); assertEquals(val1, Values.A); - assertEquals(val3, (isStableEnabled ? Values.A : Values.B)); + assertEquals(val3, (isServerWithStable ? Values.A : Values.B)); assertEquals(val2, Values.A); assertEquals(val4, Values.B); @@ -619,17 +659,4 @@ } } } - - static final boolean isStableEnabled; - static { - HotSpotDiagnosticMXBean diagnostic - = ManagementFactoryHelper.getDiagnosticMXBean(); - VMOption tmp; - try { - tmp = diagnostic.getVMOption("FoldStableValues"); - } catch (IllegalArgumentException e) { - tmp = null; - } - isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue())); - } } diff -r b67a3f81b630 -r d952af8cf67d test/compiler/stable/TestStableShort.java --- a/test/compiler/stable/TestStableShort.java Fri Jun 27 11:07:23 2014 +0100 +++ b/test/compiler/stable/TestStableShort.java Fri Jul 11 00:19:54 2014 -0700 @@ -26,9 +26,11 @@ /* * @test TestStableShort * @summary tests on stable fields and arrays - * @library /testlibrary - * @compile -XDignore.symbol.file TestStableShort.java + * @library /testlibrary /testlibrary/whitebox + * @build TestStableShort StableConfiguration sun.hotspot.WhiteBox + * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller + * java/lang/invoke/StableConfiguration * java/lang/invoke/TestStableShort * java/lang/invoke/TestStableShort$ShortStable * java/lang/invoke/TestStableShort$StaticShortStable @@ -48,46 +50,60 @@ * java/lang/invoke/TestStableShort$NestedStableField3 * java/lang/invoke/TestStableShort$NestedStableField3$A * java/lang/invoke/TestStableShort$DefaultValue + * java/lang/invoke/TestStableShort$DefaultStaticValue * java/lang/invoke/TestStableShort$ObjectArrayLowerDim2 * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableShort + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableShort * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+FoldStableValues + * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 + * java.lang.invoke.TestStableShort + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableShort * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:+UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableShort - * * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:-FoldStableValues -XX:-UseCompressedOop - * -server -XX:-TieredCompilation -Xcomp + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp + * -client -XX:-TieredCompilation + * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableShort */ package java.lang.invoke; -import com.sun.management.HotSpotDiagnosticMXBean; -import com.sun.management.VMOption; -import sun.management.ManagementFactoryHelper; import java.lang.reflect.InvocationTargetException; public class TestStableShort { + static final boolean isStableEnabled = StableConfiguration.isStableEnabled; + static final boolean isServerWithStable = StableConfiguration.isServerWithStable; + public static void main(String[] args) throws Exception { - System.out.println("@Stable enabled: "+isStableEnabled); - System.out.println(); - run(DefaultValue.class); run(ShortStable.class); + run(DefaultStaticValue.class); run(StaticShortStable.class); run(VolatileShortStable.class); @@ -145,6 +161,21 @@ /* ==================================================== */ + static class DefaultStaticValue { + public static @Stable short v; + + public static final DefaultStaticValue c = new DefaultStaticValue(); + public static short get() { return c.v; } + public static void test() throws Exception { + short val1 = get(); + c.v = 1; short val2 = get(); + assertEquals(val1, 0); + assertEquals(val2, 1); + } + } + + /* ==================================================== */ + static class StaticShortStable { public static @Stable short v; @@ -188,20 +219,22 @@ c.v = new short[1]; c.v[0] = 1; short val1 = get(); c.v[0] = 2; short val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new short[1]; c.v[0] = 3; short val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); } { c.v = new short[20]; c.v[10] = 1; short val1 = get1(); c.v[10] = 2; short val2 = get1(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new short[20]; c.v[10] = 3; short val3 = get1(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); } { @@ -226,19 +259,21 @@ c.v = new short[1][1]; c.v[0][0] = 1; short val1 = get(); c.v[0][0] = 2; short val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new short[1][1]; c.v[0][0] = 3; short val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); c.v[0] = new short[1]; c.v[0][0] = 4; short val4 = get(); - assertEquals(val4, (isStableEnabled ? 1 : 4)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 4)); } { c.v = new short[1][1]; short[] val1 = get1(); c.v[0] = new short[1]; short[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -264,28 +299,31 @@ c.v = new short[1][1][1]; c.v[0][0][0] = 1; short val1 = get(); c.v[0][0][0] = 2; short val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new short[1][1][1]; c.v[0][0][0] = 3; short val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); c.v[0] = new short[1][1]; c.v[0][0][0] = 4; short val4 = get(); - assertEquals(val4, (isStableEnabled ? 1 : 4)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 4)); c.v[0][0] = new short[1]; c.v[0][0][0] = 5; short val5 = get(); - assertEquals(val5, (isStableEnabled ? 1 : 5)); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 5)); } { c.v = new short[1][1][1]; short[] val1 = get1(); c.v[0][0] = new short[1]; short[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new short[1][1][1]; short[][] val1 = get2(); c.v[0] = new short[1][1]; short[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -312,37 +350,41 @@ c.v = new short[1][1][1][1]; c.v[0][0][0][0] = 1; short val1 = get(); c.v[0][0][0][0] = 2; short val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isStableEnabled ? 1 : 2)); + assertEquals(val2, (isServerWithStable ? 1 : 2)); c.v = new short[1][1][1][1]; c.v[0][0][0][0] = 3; short val3 = get(); - assertEquals(val3, (isStableEnabled ? 1 : 3)); + assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 3)); c.v[0] = new short[1][1][1]; c.v[0][0][0][0] = 4; short val4 = get(); - assertEquals(val4, (isStableEnabled ? 1 : 4)); + assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 4)); c.v[0][0] = new short[1][1]; c.v[0][0][0][0] = 5; short val5 = get(); - assertEquals(val5, (isStableEnabled ? 1 : 5)); + assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 5)); c.v[0][0][0] = new short[1]; c.v[0][0][0][0] = 6; short val6 = get(); - assertEquals(val6, (isStableEnabled ? 1 : 6)); + assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2) + : 6)); } { c.v = new short[1][1][1][1]; short[] val1 = get1(); c.v[0][0][0] = new short[1]; short[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new short[1][1][1][1]; short[][] val1 = get2(); c.v[0][0] = new short[1][1]; short[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new short[1][1][1][1]; short[][][] val1 = get3(); c.v[0] = new short[1][1][1]; short[][][] val2 = get3(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -350,13 +392,11 @@ c.v = new short[1][1][1][1]; short[][][][] val2 = get4(); assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } - } } /* ==================================================== */ // Dynamic Dim is higher than static - static class ObjectArrayLowerDim0 { public @Stable Object v; @@ -404,7 +444,7 @@ c.v = new short[1][1]; c.v[0] = new short[0]; short[] val1 = get1(); c.v[0] = new short[0]; short[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -440,14 +480,14 @@ c.v = new short[1][1][1]; c.v[0][0] = new short[0]; short[] val1 = get1(); c.v[0][0] = new short[0]; short[] val2 = get1(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { c.v = new short[1][1][1]; c.v[0] = new short[0][0]; short[][] val1 = get2(); c.v[0] = new short[0][0]; short[][] val2 = get2(); - assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); + assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); } { @@ -582,7 +622,7 @@ elem.a = 2; short val3 = get(); short val4 = get1(); assertEquals(val1, 1); - assertEquals(val3, (isStableEnabled ? 1 : 2)); + assertEquals(val3, (isServerWithStable ? 1 : 2)); assertEquals(val2, 1); assertEquals(val4, 2); @@ -616,17 +656,4 @@ } } } - - static final boolean isStableEnabled; - static { - HotSpotDiagnosticMXBean diagnostic - = ManagementFactoryHelper.getDiagnosticMXBean(); - VMOption tmp; - try { - tmp = diagnostic.getVMOption("FoldStableValues"); - } catch (IllegalArgumentException e) { - tmp = null; - } - isStableEnabled = (tmp == null ? false : Boolean.parseBoolean(tmp.getValue())); - } } diff -r b67a3f81b630 -r d952af8cf67d test/gc/logging/TestGCId.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/logging/TestGCId.java Fri Jul 11 00:19:54 2014 -0700 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test TestGCId + * @bug 8043607 + * @summary Ensure that the GCId is logged + * @key gc + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.ProcessTools; +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class TestGCId { + public static void main(String[] args) throws Exception { + testGCId("UseParallelGC", "PrintGC"); + testGCId("UseParallelGC", "PrintGCDetails"); + + testGCId("UseG1GC", "PrintGC"); + testGCId("UseG1GC", "PrintGCDetails"); + + testGCId("UseConcMarkSweepGC", "PrintGC"); + testGCId("UseConcMarkSweepGC", "PrintGCDetails"); + + testGCId("UseSerialGC", "PrintGC"); + testGCId("UseSerialGC", "PrintGCDetails"); + } + + private static void verifyContainsGCIDs(OutputAnalyzer output) { + output.shouldMatch("^#0: \\["); + output.shouldMatch("^#1: \\["); + output.shouldHaveExitValue(0); + } + + private static void verifyContainsNoGCIDs(OutputAnalyzer output) { + output.shouldNotMatch("^#[0-9]+: \\["); + output.shouldHaveExitValue(0); + } + + private static void testGCId(String gcFlag, String logFlag) throws Exception { + // GCID logging enabled + ProcessBuilder pb_enabled = + ProcessTools.createJavaProcessBuilder("-XX:+" + gcFlag, "-XX:+" + logFlag, "-Xmx10M", "-XX:+PrintGCID", GCTest.class.getName()); + verifyContainsGCIDs(new OutputAnalyzer(pb_enabled.start())); + + // GCID logging disabled + ProcessBuilder pb_disabled = + ProcessTools.createJavaProcessBuilder("-XX:+" + gcFlag, "-XX:+" + logFlag, "-Xmx10M", "-XX:-PrintGCID", GCTest.class.getName()); + verifyContainsNoGCIDs(new OutputAnalyzer(pb_disabled.start())); + + // GCID logging default + ProcessBuilder pb_default = + ProcessTools.createJavaProcessBuilder("-XX:+" + gcFlag, "-XX:+" + logFlag, "-Xmx10M", GCTest.class.getName()); + verifyContainsNoGCIDs(new OutputAnalyzer(pb_default.start())); + } + + static class GCTest { + private static byte[] garbage; + public static void main(String [] args) { + System.out.println("Creating garbage"); + // create 128MB of garbage. This should result in at least one GC + for (int i = 0; i < 1024; i++) { + garbage = new byte[128 * 1024]; + } + // do a system gc to get one more gc + System.gc(); + System.out.println("Done"); + } + } +}