This file often describes specific requirements for what we call the
- "minimum build environments" (MBE) for the JDK.
+ "minimum build environments" (MBE) for this
+ specific release of the JDK,
Building with the MBE will generate the most compatible
bits that install on, and run correctly on, the most variations
of the same base OS and hardware architecture.
@@ -116,22 +117,22 @@
+ These same sources do indeed build on many more systems than the
+ above older generation systems, again the above is just a minimum.
+
+ Compilation problems with newer or different C/C++ compilers is a
+ common problem.
+ Similarly, compilation problems related to changes to the
+ /usr/include or system header files is also a
+ common problem with newer or unreleased OS versions.
+ Please report these types of problems as bugs so that they
+ can be dealt with accordingly.
@@ -488,7 +500,7 @@
not work due to a lack of support for MS-DOS drive letter paths
like C:/ or C:\.
Use a 3.80 version, or find a newer
- version that has this problem fixed, like 3.82.
+ version that has this problem fixed.
The older 3.80 version of make.exe can be downloaded with this
link.
@@ -575,8 +587,8 @@
Install
- Ant, set
- ANT_HOME.
+ Ant,
+ make sure it is in your PATH.
@@ -592,7 +604,7 @@
Approximately 1.4 GB of free disk
space is needed for a 32-bit build.
- If you are building the 64bit version, you should
+ If you are building the 64-bit version, you should
run the command "isainfo -v" to verify that you have a
64-bit installation, it should say sparcv9 or
amd64.
@@ -640,8 +652,8 @@
Install
- Ant, set
- ANT_HOME.
+ Ant,
+ make sure it is in your PATH.
i586 only:
- The minimum recommended hardware for building the 32bit or X86
+ The minimum recommended hardware for building the 32-bit or X86
Windows version is an Pentium class processor or better, at least
512 MB of RAM, and approximately 600 MB of free disk space.
- NOTE: The Windows 2000 build machines need to use the
+ NOTE: The Windows build machines need to use the
file system NTFS.
Build machines formatted to FAT32 will not work
because FAT32 doesn't support case-sensitivity in file names.
@@ -719,8 +731,11 @@
Setup all environment variables for compilers
@@ -732,7 +747,8 @@
Install
- Ant, set
+ Ant,
+ make sure it is in your PATH and set
ANT_HOME.
@@ -787,7 +803,9 @@
you must first download and install the appropriate
binary plug bundles for the OpenJDK, go to the
OpenJDK site and select
- the "Bundles(7)" link and download the binaryplugs for
+ the
+ "Bundles(7)"
+ link and download the binaryplugs for
your particular platform.
The file downloaded is a jar file that must be extracted by running
the jar file with:
@@ -823,14 +841,12 @@
The Ant tool is available from the
Ant download site.
- You should always set
+ You should always make sure ant is in your PATH, and
+ on Windows you may also need to set
ANT_HOME
to point to the location of
the Ant installation, this is the directory pathname
that contains a bin and lib.
- It's also a good idea to also place its bin directory
- in the PATH environment variable, although it's
- not absolutely required.
- The GNU gcc compiler version should be 3.2.2 or newer.
- The binutils package should be 2.11.93.0.2-11 or newer.
+ The GNU gcc compiler version should be 4 or newer.
The compiler used should be the default compiler installed
in /usr/bin.
-
- Older Linux systems may require a gcc and bunutils update.
- The Redhat Enterprise Advanced Server 2.1 update 2 system
- is one of these systems.
- RedHat Linux users can obtain this binutils package from
- Redhat web site.
- You will need to remove the default compiler and binutils
- packages and install the required packages
- into the default location on the system.
- However if you have a new video card driver, like
- Geforce 4 it is best to use
- the same compiler as the kernel was built with to
- build the new video card driver module.
- So you should build the modules before making this change.
The 32-bit OpenJDK Windows build
- requires Microsoft Visual Studio .NET 2003 (VS2003) Professional
+ requires
+ Microsoft Visual Studio C++ 2008 (VS2008) Standard
Edition compiler.
The compiler and other tools are expected to reside
- in the location defined by the variable VS71COMNTOOLS which
- is set by the Microsoft Visual Studio .NET installer.
+ in the location defined by the variable
+ VS90COMNTOOLS which
+ is set by the Microsoft Visual Studio installer.
Once the compiler is installed,
it is recommended that you run VCVARS32.BAT
to set the compiler environment variables
- MSVCDIR,
INCLUDE,
LIB, and
PATH
@@ -923,16 +924,12 @@
OpenJDK.
The above environment variables MUST be set.
- The Microsoft Visual Studio .NET 2005 (VS2005) compiler
- will not work at this time due to the new runtime dll
- and the manifest requirements.
-
WARNING: Make sure you check out the
CYGWIN link.exe WARNING.
The path /usr/bin must be after the path to the
Visual Studio product.
On X64, the Microsoft Platform Software
Development Kit (SDK), April 2005 Edition compiler,
@@ -953,10 +950,9 @@
OpenJDK.
The above environment variables MUST be set.
- Note that this compiler may say it's version is a
- Microsoft Visual Studio .NET 2005 (VS2005), but be careful,
- it will not match the official VS2005 product.
- This Platform SDK compiler is only used on X64 builds.
+ This Platform SDK compiler is only used on X64 builds
+ but other parts of the Platform SDK may be used
+ for the X86 builds.
i586 only:
- The OpenJDK 32bit build requires access to
- MSVCRT.DLL version 6.00.8337.0 or newer.
+ The OpenJDK 32-bit build requires access to a redistributable
+ MSVCRT.DLL.
If the MSVCRT.DLL is not installed in
the system32 directory set the
ALT_MSVCRT_DLL_PATH
- variable to the location.
+ variable to the location of this file.
X64 only:
- The OpenJDK 64bit build requires access to
- MSVCRT.DLL version 7.0.3790.0 or newer, which is
+ The OpenJDK 64-bit build requires access to a redistributable
+ MSVCRT.DLL, which is
usually supplied by the
Platform SDK.
If it is not available from the Platform SDK,
set the
ALT_MSVCRT_DLL_PATH
- variable to the location.
+ variable to the location of this file.
i586 only:
The
OpenJDK
- build requires access to
- MSVCR71.DLL version 7.10.3052.4 or newer which should be
+ build requires access to a redistributable
+ MSVCR90.DLL which should be
supplied by the
- Visual Studio product
- If the MSVCR71.DLL is not available from the
+ Visual Studio product.
+ If the MSVCR90.DLL is not available from the
Visual Studio product
set the
- ALT_MSVCR71_DLL_PATH
- variable to the location.
+ ALT_MSVCR90_DLL_PATH
+ variable to the location of this file.
@@ -1359,13 +1355,38 @@
document) that can impact the build are:
The location of the Bootstrap JDK java
+ (see Bootstrap JDK)
+
The location of the C/C++ compilers
+ (see compilers)
+
The location or locations for the Unix command utilities
+ (e.g. /usr/bin)
+
+
+
MILESTONE
- The location of the binary plugs installation.
- See Binary Plugs for more information.
- You should always have a local copy of a
- recent Binary Plugs install image
- and set this variable to that location.
+ The milestone name for the build (e.g."beta").
+ The default value is "internal".
+
+
BUILD_NUMBER
+
+ The build number for the build (e.g. "b27").
+ The default value is "b00".
+
The ARCH_DATA_MODEL variable
+ is used to specify whether the build is to generate 32-bit or 64-bit
+ binaries.
+ The Solaris build supports either 32-bit or 64-bit builds, but
+ Windows and Linux will support only one, depending on the specific
+ OS being used.
+ Normally, setting this variable is only necessary on Solaris.
+ Set ARCH_DATA_MODEL to 32 for generating 32-bit binaries,
+ or to 64 for generating 64-bit binaries.
+ The location of the binary plugs installation.
+ See Binary Plugs for more information.
+ You should always have a local copy of a
+ recent Binary Plugs install image
+ and set this variable to that location.
+
+ The location of the CUPS header files.
+ See CUPS information for more information.
+ If this path does not exist the fallback path is
+ /usr/include.
+
- These are useful in managing builds on multiple platforms.
- The default network location for all of the binary plug images
- for all platforms.
- If ALT_BINARY_PLUGS_PATH
- is not set, this directory will be used and should contain
- the following directories:
- solaris-sparc,
- solaris-i586,
- solaris-sparcv9,
- solaris-amd64,
- linux-i586,
- linux-amd64,
- windows-i586,
- and
- windows-amd64.
- Where each of these directories contain the binary plugs image
- for that platform.
+ The location of the FreeType shared library.
+ See FreeType information for details.
+
+ The location of tools like the
+ zip and unzip
+ binaries, but might also contain the GNU make utility
+ (gmake).
+ So this area is a bit of a grab bag, especially on Windows.
+ The default value depends on the platform and
+ Unix Commands being used.
+ On Linux the default will be
+ $(ALT_JDK_DEVTOOLS_PATH)/linux/bin,
+ on Solaris
+ $(ALT_JDK_DEVTOOLS_PATH)/{sparc,i386}/bin,
+ and on Windows with CYGWIN
+ /usr/bin.
+
+ The default root location for many of the ALT path locations
+ of the following ALT variables.
+ The default value is
+ "/java" on Solaris and Linux,
+ "J:" on Windows.
- The location of the CUPS header files.
- See CUPS information for more information.
- If this path does not exist the fallback path is
- /usr/include.
-
- The location of tools like the
- zip and unzip
- binaries, but might also contain the GNU make utility
- (gmake).
- So this area is a bit of a grab bag, especially on Windows.
- The default value depends on the platform and
- Unix Commands being used.
- On Linux the default will be
- $(ALT_JDK_DEVTOOLS_PATH)/linux/bin,
- on Solaris
- $(ALT_JDK_DEVTOOLS_PATH)/{sparc,i386}/bin,
- on Windows with MKS
- %SYSTEMDRIVE%/UTILS,
- and on Windows with CYGWIN
- /usr/bin.
-
- Windows Only:
- The location of the
- Microsoft DirectX 9 SDK.
- The default will be to try and use the DirectX environment
- variable DXSDK_DIR,
- failing that, look in C:/DXSDK.
-
- Windows Only:
- The location of the Microsoft Visual Studio .NET 2003
- tools 'bin' directory.
- The default is usually derived from
- ALT_COMPILER_PATH.
-
- Windows i586 only:
- The location of the
- MSVCR71.DLL.
+ These are useful in managing builds on multiple platforms.
+ The default network location for all of the binary plug images
+ for all platforms.
+ If ALT_BINARY_PLUGS_PATH
+ is not set, this directory will be used and should contain
+ the following directories:
+ solaris-sparc,
+ solaris-i586,
+ solaris-sparcv9,
+ solaris-amd64,
+ linux-i586,
+ linux-amd64,
+ windows-i586,
+ and
+ windows-amd64.
+ Where each of these directories contain the binary plugs image
+ for that platform.
- The default root location for many of the ALT path locations
- of the following ALT variables.
- The default value is
- "/java" on Solaris and Linux,
- "J:" on Windows.
-
- An override for specifying where the
- Unix command set are located.
- The default location varies depending on the platform,
- "%SYSTEMDRIVE%/MKSNT" or
- $(ROOTDIR) on Windows with MKS, otherwise it's
- "/bin" or /usr/bin.
-
- An override for specifying where the
- Unix /usr/bin commands are located. You usually do not need
- to set this variable: the default location is /usr/bin)
-
The ARCH_DATA_MODEL variable
- is used to specify whether the build is to generate 32-bit or 64-bit
- binaries.
- The Solaris build supports either 32-bit or 64-bit builds, but
- Windows and Linux will support only one, depending on the specific
- OS being used.
- Normally, setting this variable is only necessary on Solaris.
- Set ARCH_DATA_MODEL to 32 for generating 32-bit binaries,
- or to 64 for generating 64-bit binaries.
-
-
BUILD_NUMBER
-
- The build number for the build (e.g. "b27").
- The default value is "b00".
-
-
MILESTONE
-
- The milestone name for the build (e.g."beta").
- The default value is "internal".
-
+ The location of the
+ Microsoft DirectX 9 SDK.
+ The default will be to try and use the DirectX environment
+ variable DXSDK_DIR,
+ failing that, look in C:/DXSDK.
+
+ i586 only:
+ The location of the
+ MSVCR90.DLL.
+
+
@@ -1661,8 +1637,8 @@
This is caused by a missing libstdc++.a library.
This is installed as part of a specific package
(e.g. libstdc++.so.devel.386).
- By default some 64bit Linux versions (e.g. Fedora)
- only install the 64bit version of the libstdc++ package.
+ By default some 64-bit Linux versions (e.g. Fedora)
+ only install the 64-bit version of the libstdc++ package.
Various parts of the JDK build require a static
link of the C++ runtime libraries to allow for maximum
portability of the built images.
diff -r c6ee85e55858 -r a85945264abc corba/.hgtags
--- a/corba/.hgtags Thu Dec 04 17:48:02 2008 -0800
+++ b/corba/.hgtags Fri Dec 05 15:06:37 2008 -0500
@@ -14,3 +14,4 @@
59d5848bdedebe91cc2753acce78911bcb4a66db jdk7-b37
08be802754b0296c91a7713b6d85a015dbcd5349 jdk7-b38
55078b6661e286e90387d1d9950bd865f5cc436e jdk7-b39
+184e21992f47a8d730df1adc5b21a108f3125489 jdk7-b40
diff -r c6ee85e55858 -r a85945264abc hotspot/.hgtags
--- a/hotspot/.hgtags Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/.hgtags Fri Dec 05 15:06:37 2008 -0500
@@ -14,3 +14,4 @@
9ee9cf798b59e7d51f8c0a686959f313867a55d6 jdk7-b37
d9bc824aa078573829bb66572af847e26e1bd12e jdk7-b38
49ca90d77f34571b0757ebfcb8a7848ef2696b88 jdk7-b39
+81a0cbe3b28460ce836109934ece03db7afaf9cc jdk7-b40
diff -r c6ee85e55858 -r a85945264abc hotspot/make/hotspot_version
--- a/hotspot/make/hotspot_version Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/make/hotspot_version Fri Dec 05 15:06:37 2008 -0500
@@ -35,7 +35,7 @@
HS_MAJOR_VER=14
HS_MINOR_VER=0
-HS_BUILD_NUMBER=07
+HS_BUILD_NUMBER=08
JDK_MAJOR_VER=1
JDK_MINOR_VER=7
diff -r c6ee85e55858 -r a85945264abc hotspot/make/windows/build.make
--- a/hotspot/make/windows/build.make Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/make/windows/build.make Fri Dec 05 15:06:37 2008 -0500
@@ -200,29 +200,6 @@
checkSA::
@echo Not building SA: ARCH = ia64
-!elseif exist("$(MSVCDIR)\PlatformSDK\Include\dbgeng.h")
-# These don't have to be set because the default
-# setting of INCLUDE and LIB already contain the needed dirs.
-SA_INCLUDE =
-SA_LIB =
-
-!elseif exist("$(SYSTEMROOT)\..\Program Files\Microsoft SDK\include\dbgeng.h")
-# These don't have to be set because the default
-# setting of INCLUDE and LIB already contain the needed dirs.
-SA_INCLUDE =
-SA_LIB =
-
-!else
-checkSA::
- @echo .
- @echo ERROR: Can't build SA because dbgeng.h does not exist here:
- @echo $(MSVCDIR)\PlatformSDK\Include\dbgeng.h
- @echo nor here:
- @echo $(SYSTEMROOT)\..\Program Files\Microsoft SDK\include\dbgeng.h
- @echo You must use Vis. Studio .Net 2003 on Win 32, and you must
- @echo have the Microsoft SDK installed on Win amd64.
- @echo You can disable building of SA by specifying BUILD_WIN_SA = 0
- @echo . && false
!endif # ! "$(BUILD_WIN_SA)" != "1"
#########################################################################
diff -r c6ee85e55858 -r a85945264abc hotspot/make/windows/makefiles/defs.make
--- a/hotspot/make/windows/makefiles/defs.make Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/make/windows/makefiles/defs.make Fri Dec 05 15:06:37 2008 -0500
@@ -119,7 +119,7 @@
# we want to release it. If we build it here,
# the SDK makefiles will copy it over and put it into
# the created image.
-BUILD_WIN_SA = 0
+BUILD_WIN_SA = 1
ifneq ($(ALT_BUILD_WIN_SA),)
BUILD_WIN_SA = $(ALT_BUILD_WIN_SA)
endif
diff -r c6ee85e55858 -r a85945264abc hotspot/make/windows/makefiles/sa.make
--- a/hotspot/make/windows/makefiles/sa.make Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/make/windows/makefiles/sa.make Fri Dec 05 15:06:37 2008 -0500
@@ -49,6 +49,9 @@
default:: $(GENERATED)\sa-jdi.jar
+# Remove the space between $(SA_BUILD_VERSION_PROP) and > below as it adds a white space
+# at the end of SA version string and causes a version mismatch with the target VM version.
+
$(GENERATED)\sa-jdi.jar: $(AGENT_FILES1:/=\) $(AGENT_FILES2:/=\)
@if not exist $(SA_CLASSDIR) mkdir $(SA_CLASSDIR)
@echo ...Building sa-jdi.jar
@@ -56,15 +59,15 @@
@$(COMPILE_JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -g -d $(SA_CLASSDIR) $(AGENT_FILES1:/=\)
@$(COMPILE_JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -g -d $(SA_CLASSDIR) $(AGENT_FILES2:/=\)
$(COMPILE_RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
- $(QUIETLY) echo $(SA_BUILD_VERSION_PROP) > $(SA_PROPERTIES)
- $(RUN_JAR) cf $@ -C saclasses .
- $(RUN_JAR) uf $@ -C $(AGENT_SRC_DIR:/=\) META-INF\services\com.sun.jdi.connect.Connector
+ $(QUIETLY) echo $(SA_BUILD_VERSION_PROP)> $(SA_PROPERTIES)
$(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js
$(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/utilities/soql/sa.js $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql
- $(QUIETLY) mkdir -p $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources
- $(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources/*
- $(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/ui/resources/*.png $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources/
- $(QUIETLY) cp -r $(AGENT_SRC_DIR)/images/* $(SA_CLASSDIR)/
+ $(QUIETLY) rm -rf $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources
+ $(QUIETLY) mkdir $(SA_CLASSDIR)\sun\jvm\hotspot\ui\resources
+ $(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/ui/resources/*.png $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources
+ $(QUIETLY) cp -r $(AGENT_SRC_DIR)/images/* $(SA_CLASSDIR)
+ $(RUN_JAR) cf $@ -C saclasses .
+ $(RUN_JAR) uf $@ -C $(AGENT_SRC_DIR:/=\) META-INF\services\com.sun.jdi.connect.Connector
$(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.windbg.WindbgDebuggerLocal
$(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.x86.X86ThreadContext
$(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.ia64.IA64ThreadContext
@@ -93,7 +96,7 @@
SA_CFLAGS = /nologo $(MS_RUNTIME_OPTION) /W3 /Gm $(GX_OPTION) /ZI /Od /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
!endif
!if "$(MT)" != ""
- SA_LINK_FLAGS = /manifest $(SA_LINK_FLAGS)
+SA_LINK_FLAGS = /manifest $(SA_LINK_FLAGS)
!endif
SASRCFILE = $(AGENT_DIR)/src/os/win32/windbg/sawindbg.cpp
SA_LFLAGS = $(SA_LINK_FLAGS) /nologo /subsystem:console /map /debug /machine:$(MACHINE)
diff -r c6ee85e55858 -r a85945264abc hotspot/src/os/linux/vm/os_linux.cpp
--- a/hotspot/src/os/linux/vm/os_linux.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -2272,7 +2272,9 @@
uncommit_memory(addr, bytes);
}
-void os::numa_make_global(char *addr, size_t bytes) { }
+void os::numa_make_global(char *addr, size_t bytes) {
+ Linux::numa_interleave_memory(addr, bytes);
+}
void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) {
Linux::numa_tonode_memory(addr, bytes, lgrp_hint);
@@ -2314,7 +2316,7 @@
extern "C" void numa_warn(int number, char *where, ...) { }
extern "C" void numa_error(char *where) { }
-void os::Linux::libnuma_init() {
+bool os::Linux::libnuma_init() {
// sched_getcpu() should be in libc.
set_sched_getcpu(CAST_TO_FN_PTR(sched_getcpu_func_t,
dlsym(RTLD_DEFAULT, "sched_getcpu")));
@@ -2330,31 +2332,51 @@
dlsym(handle, "numa_available")));
set_numa_tonode_memory(CAST_TO_FN_PTR(numa_tonode_memory_func_t,
dlsym(handle, "numa_tonode_memory")));
+ set_numa_interleave_memory(CAST_TO_FN_PTR(numa_interleave_memory_func_t,
+ dlsym(handle, "numa_interleave_memory")));
+
+
if (numa_available() != -1) {
+ set_numa_all_nodes((unsigned long*)dlsym(handle, "numa_all_nodes"));
// Create a cpu -> node mapping
_cpu_to_node = new (ResourceObj::C_HEAP) GrowableArray(0, true);
rebuild_cpu_to_node_map();
+ return true;
}
}
}
+ return false;
}
// rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id.
// The table is later used in get_node_by_cpu().
void os::Linux::rebuild_cpu_to_node_map() {
- int cpu_num = os::active_processor_count();
+ const size_t NCPUS = 32768; // Since the buffer size computation is very obscure
+ // in libnuma (possible values are starting from 16,
+ // and continuing up with every other power of 2, but less
+ // than the maximum number of CPUs supported by kernel), and
+ // is a subject to change (in libnuma version 2 the requirements
+ // are more reasonable) we'll just hardcode the number they use
+ // in the library.
+ const size_t BitsPerCLong = sizeof(long) * CHAR_BIT;
+
+ size_t cpu_num = os::active_processor_count();
+ size_t cpu_map_size = NCPUS / BitsPerCLong;
+ size_t cpu_map_valid_size =
+ MIN2((cpu_num + BitsPerCLong - 1) / BitsPerCLong, cpu_map_size);
+
cpu_to_node()->clear();
cpu_to_node()->at_grow(cpu_num - 1);
- int node_num = numa_get_groups_num();
- int cpu_map_size = (cpu_num + BitsPerLong - 1) / BitsPerLong;
+ size_t node_num = numa_get_groups_num();
+
unsigned long *cpu_map = NEW_C_HEAP_ARRAY(unsigned long, cpu_map_size);
- for (int i = 0; i < node_num; i++) {
+ for (size_t i = 0; i < node_num; i++) {
if (numa_node_to_cpus(i, cpu_map, cpu_map_size * sizeof(unsigned long)) != -1) {
- for (int j = 0; j < cpu_map_size; j++) {
+ for (size_t j = 0; j < cpu_map_valid_size; j++) {
if (cpu_map[j] != 0) {
- for (int k = 0; k < BitsPerLong; k++) {
+ for (size_t k = 0; k < BitsPerCLong; k++) {
if (cpu_map[j] & (1UL << k)) {
- cpu_to_node()->at_put(j * BitsPerLong + k, i);
+ cpu_to_node()->at_put(j * BitsPerCLong + k, i);
}
}
}
@@ -2377,7 +2399,8 @@
os::Linux::numa_max_node_func_t os::Linux::_numa_max_node;
os::Linux::numa_available_func_t os::Linux::_numa_available;
os::Linux::numa_tonode_memory_func_t os::Linux::_numa_tonode_memory;
-
+os::Linux::numa_interleave_memory_func_t os::Linux::_numa_interleave_memory;
+unsigned long* os::Linux::_numa_all_nodes;
bool os::uncommit_memory(char* addr, size_t size) {
return ::mmap(addr, size,
@@ -3695,7 +3718,17 @@
}
if (UseNUMA) {
- Linux::libnuma_init();
+ if (!Linux::libnuma_init()) {
+ UseNUMA = false;
+ } else {
+ if ((Linux::numa_max_node() < 1)) {
+ // There's only one node(they start from 0), disable NUMA.
+ UseNUMA = false;
+ }
+ }
+ if (!UseNUMA && ForceNUMA) {
+ UseNUMA = true;
+ }
}
if (MaxFDLimit) {
diff -r c6ee85e55858 -r a85945264abc hotspot/src/os/linux/vm/os_linux.hpp
--- a/hotspot/src/os/linux/vm/os_linux.hpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/os/linux/vm/os_linux.hpp Fri Dec 05 15:06:37 2008 -0500
@@ -146,7 +146,7 @@
static bool is_floating_stack() { return _is_floating_stack; }
static void libpthread_init();
- static void libnuma_init();
+ static bool libnuma_init();
// Minimum stack size a thread can be created with (allowing
// the VM to completely create the thread and enter user code)
@@ -240,20 +240,23 @@
typedef int (*numa_max_node_func_t)(void);
typedef int (*numa_available_func_t)(void);
typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node);
-
+ typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask);
static sched_getcpu_func_t _sched_getcpu;
static numa_node_to_cpus_func_t _numa_node_to_cpus;
static numa_max_node_func_t _numa_max_node;
static numa_available_func_t _numa_available;
static numa_tonode_memory_func_t _numa_tonode_memory;
+ static numa_interleave_memory_func_t _numa_interleave_memory;
+ static unsigned long* _numa_all_nodes;
static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; }
static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; }
static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; }
static void set_numa_available(numa_available_func_t func) { _numa_available = func; }
static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; }
-
+ static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; }
+ static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; }
public:
static int sched_getcpu() { return _sched_getcpu != NULL ? _sched_getcpu() : -1; }
static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) {
@@ -264,6 +267,11 @@
static int numa_tonode_memory(void *start, size_t size, int node) {
return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1;
}
+ static void numa_interleave_memory(void *start, size_t size) {
+ if (_numa_interleave_memory != NULL && _numa_all_nodes != NULL) {
+ _numa_interleave_memory(start, size, _numa_all_nodes);
+ }
+ }
static int get_node_by_cpu(int cpu_id);
};
diff -r c6ee85e55858 -r a85945264abc hotspot/src/os/solaris/vm/os_solaris.cpp
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -4638,7 +4638,7 @@
}
}
-void os::Solaris::liblgrp_init() {
+bool os::Solaris::liblgrp_init() {
void *handle = dlopen("liblgrp.so.1", RTLD_LAZY);
if (handle != NULL) {
os::Solaris::set_lgrp_home(CAST_TO_FN_PTR(lgrp_home_func_t, dlsym(handle, "lgrp_home")));
@@ -4653,9 +4653,9 @@
lgrp_cookie_t c = lgrp_init(LGRP_VIEW_CALLER);
set_lgrp_cookie(c);
- } else {
- warning("your OS does not support NUMA");
- }
+ return true;
+ }
+ return false;
}
void os::Solaris::misc_sym_init() {
@@ -4824,9 +4824,25 @@
vm_page_size()));
Solaris::libthread_init();
+
if (UseNUMA) {
- Solaris::liblgrp_init();
- }
+ if (!Solaris::liblgrp_init()) {
+ UseNUMA = false;
+ } else {
+ size_t lgrp_limit = os::numa_get_groups_num();
+ int *lgrp_ids = NEW_C_HEAP_ARRAY(int, lgrp_limit);
+ size_t lgrp_num = os::numa_get_leaf_groups(lgrp_ids, lgrp_limit);
+ FREE_C_HEAP_ARRAY(int, lgrp_ids);
+ if (lgrp_num < 2) {
+ // There's only one locality group, disable NUMA.
+ UseNUMA = false;
+ }
+ }
+ if (!UseNUMA && ForceNUMA) {
+ UseNUMA = true;
+ }
+ }
+
Solaris::misc_sym_init();
Solaris::signal_sets_init();
Solaris::init_signal_mem();
diff -r c6ee85e55858 -r a85945264abc hotspot/src/os/solaris/vm/os_solaris.hpp
--- a/hotspot/src/os/solaris/vm/os_solaris.hpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/os/solaris/vm/os_solaris.hpp Fri Dec 05 15:06:37 2008 -0500
@@ -176,7 +176,7 @@
public:
static void libthread_init();
static void synchronization_init();
- static void liblgrp_init();
+ static bool liblgrp_init();
// Load miscellaneous symbols.
static void misc_sym_init();
// This boolean allows users to forward their own non-matching signals
diff -r c6ee85e55858 -r a85945264abc hotspot/src/os/windows/vm/os_windows.cpp
--- a/hotspot/src/os/windows/vm/os_windows.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -3347,6 +3347,10 @@
// initialize thread priority policy
prio_init();
+ if (UseNUMA && !ForceNUMA) {
+ UseNUMA = false; // Currently unsupported.
+ }
+
return JNI_OK;
}
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -676,21 +676,6 @@
}
-void GraphBuilder::kill_field(ciField* field) {
- if (UseLocalValueNumbering) {
- vmap()->kill_field(field);
- }
-}
-
-
-void GraphBuilder::kill_array(Value value) {
- if (UseLocalValueNumbering) {
- vmap()->kill_array(value->type());
- }
- _memory->store_value(value);
-}
-
-
void GraphBuilder::kill_all() {
if (UseLocalValueNumbering) {
vmap()->kill_all();
@@ -987,8 +972,8 @@
length = append(new ArrayLength(array, lock_stack()));
}
StoreIndexed* result = new StoreIndexed(array, index, length, type, value, lock_stack());
- kill_array(value); // invalidate all CSEs that are memory accesses of the same type
append(result);
+ _memory->store_value(value);
}
@@ -1478,9 +1463,6 @@
case Bytecodes::_putstatic:
{ Value val = pop(type);
append(new StoreField(append(obj), offset, field, val, true, lock_stack(), state_copy, is_loaded, is_initialized));
- if (UseLocalValueNumbering) {
- vmap()->kill_field(field); // invalidate all CSEs that are memory accesses
- }
}
break;
case Bytecodes::_getfield :
@@ -1503,7 +1485,6 @@
if (is_loaded) store = _memory->store(store);
if (store != NULL) {
append(store);
- kill_field(field); // invalidate all CSEs that are accesses of this field
}
}
break;
@@ -1900,6 +1881,8 @@
assert(i2->bci() != -1, "should already be linked");
return i2;
}
+ ValueNumberingEffects vne(vmap());
+ i1->visit(&vne);
}
if (i1->as_Phi() == NULL && i1->as_Local() == NULL) {
@@ -1926,14 +1909,8 @@
assert(_last == i1, "adjust code below");
StateSplit* s = i1->as_StateSplit();
if (s != NULL && i1->as_BlockEnd() == NULL) {
- // Continue CSE across certain intrinsics
- Intrinsic* intrinsic = s->as_Intrinsic();
- if (UseLocalValueNumbering) {
- if (intrinsic == NULL || !intrinsic->preserves_state()) {
- vmap()->kill_all(); // for now, hopefully we need this only for calls eventually
- }
- }
if (EliminateFieldAccess) {
+ Intrinsic* intrinsic = s->as_Intrinsic();
if (s->as_Invoke() != NULL || (intrinsic && !intrinsic->preserves_state())) {
_memory->kill();
}
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/c1/c1_GraphBuilder.hpp
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp Fri Dec 05 15:06:37 2008 -0500
@@ -283,8 +283,6 @@
Dependencies* dependency_recorder() const; // = compilation()->dependencies()
bool direct_compare(ciKlass* k);
- void kill_field(ciField* field);
- void kill_array(Value value);
void kill_all();
ValueStack* lock_stack();
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/c1/c1_ValueMap.hpp
--- a/hotspot/src/share/vm/c1/c1_ValueMap.hpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/c1/c1_ValueMap.hpp Fri Dec 05 15:06:37 2008 -0500
@@ -133,53 +133,77 @@
virtual void kill_array(ValueType* type) = 0;
// visitor functions
- void do_StoreField (StoreField* x) { kill_field(x->field()); };
- void do_StoreIndexed (StoreIndexed* x) { kill_array(x->type()); };
- void do_MonitorEnter (MonitorEnter* x) { kill_memory(); };
- void do_MonitorExit (MonitorExit* x) { kill_memory(); };
- void do_Invoke (Invoke* x) { kill_memory(); };
- void do_UnsafePutRaw (UnsafePutRaw* x) { kill_memory(); };
- void do_UnsafePutObject(UnsafePutObject* x) { kill_memory(); };
- void do_Intrinsic (Intrinsic* x) { if (!x->preserves_state()) kill_memory(); };
+ void do_StoreField (StoreField* x) {
+ if (!x->is_initialized()) {
+ kill_memory();
+ } else {
+ kill_field(x->field());
+ }
+ }
+ void do_StoreIndexed (StoreIndexed* x) { kill_array(x->type()); }
+ void do_MonitorEnter (MonitorEnter* x) { kill_memory(); }
+ void do_MonitorExit (MonitorExit* x) { kill_memory(); }
+ void do_Invoke (Invoke* x) { kill_memory(); }
+ void do_UnsafePutRaw (UnsafePutRaw* x) { kill_memory(); }
+ void do_UnsafePutObject(UnsafePutObject* x) { kill_memory(); }
+ void do_Intrinsic (Intrinsic* x) { if (!x->preserves_state()) kill_memory(); }
- void do_Phi (Phi* x) { /* nothing to do */ };
- void do_Local (Local* x) { /* nothing to do */ };
- void do_Constant (Constant* x) { /* nothing to do */ };
- void do_LoadField (LoadField* x) { /* nothing to do */ };
- void do_ArrayLength (ArrayLength* x) { /* nothing to do */ };
- void do_LoadIndexed (LoadIndexed* x) { /* nothing to do */ };
- void do_NegateOp (NegateOp* x) { /* nothing to do */ };
- void do_ArithmeticOp (ArithmeticOp* x) { /* nothing to do */ };
- void do_ShiftOp (ShiftOp* x) { /* nothing to do */ };
- void do_LogicOp (LogicOp* x) { /* nothing to do */ };
- void do_CompareOp (CompareOp* x) { /* nothing to do */ };
- void do_IfOp (IfOp* x) { /* nothing to do */ };
- void do_Convert (Convert* x) { /* nothing to do */ };
- void do_NullCheck (NullCheck* x) { /* nothing to do */ };
- void do_NewInstance (NewInstance* x) { /* nothing to do */ };
- void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ };
- void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ };
- void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ };
- void do_CheckCast (CheckCast* x) { /* nothing to do */ };
- void do_InstanceOf (InstanceOf* x) { /* nothing to do */ };
- void do_BlockBegin (BlockBegin* x) { /* nothing to do */ };
- void do_Goto (Goto* x) { /* nothing to do */ };
- void do_If (If* x) { /* nothing to do */ };
- void do_IfInstanceOf (IfInstanceOf* x) { /* nothing to do */ };
- void do_TableSwitch (TableSwitch* x) { /* nothing to do */ };
- void do_LookupSwitch (LookupSwitch* x) { /* nothing to do */ };
- void do_Return (Return* x) { /* nothing to do */ };
- void do_Throw (Throw* x) { /* nothing to do */ };
- void do_Base (Base* x) { /* nothing to do */ };
- void do_OsrEntry (OsrEntry* x) { /* nothing to do */ };
- void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ };
- void do_RoundFP (RoundFP* x) { /* nothing to do */ };
- void do_UnsafeGetRaw (UnsafeGetRaw* x) { /* nothing to do */ };
- void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ };
- void do_UnsafePrefetchRead (UnsafePrefetchRead* x) { /* nothing to do */ };
- void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ };
- void do_ProfileCall (ProfileCall* x) { /* nothing to do */ };
- void do_ProfileCounter (ProfileCounter* x) { /* nothing to do */ };
+ void do_Phi (Phi* x) { /* nothing to do */ }
+ void do_Local (Local* x) { /* nothing to do */ }
+ void do_Constant (Constant* x) { /* nothing to do */ }
+ void do_LoadField (LoadField* x) {
+ if (!x->is_initialized()) {
+ kill_memory();
+ }
+ }
+ void do_ArrayLength (ArrayLength* x) { /* nothing to do */ }
+ void do_LoadIndexed (LoadIndexed* x) { /* nothing to do */ }
+ void do_NegateOp (NegateOp* x) { /* nothing to do */ }
+ void do_ArithmeticOp (ArithmeticOp* x) { /* nothing to do */ }
+ void do_ShiftOp (ShiftOp* x) { /* nothing to do */ }
+ void do_LogicOp (LogicOp* x) { /* nothing to do */ }
+ void do_CompareOp (CompareOp* x) { /* nothing to do */ }
+ void do_IfOp (IfOp* x) { /* nothing to do */ }
+ void do_Convert (Convert* x) { /* nothing to do */ }
+ void do_NullCheck (NullCheck* x) { /* nothing to do */ }
+ void do_NewInstance (NewInstance* x) { /* nothing to do */ }
+ void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ }
+ void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ }
+ void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ }
+ void do_CheckCast (CheckCast* x) { /* nothing to do */ }
+ void do_InstanceOf (InstanceOf* x) { /* nothing to do */ }
+ void do_BlockBegin (BlockBegin* x) { /* nothing to do */ }
+ void do_Goto (Goto* x) { /* nothing to do */ }
+ void do_If (If* x) { /* nothing to do */ }
+ void do_IfInstanceOf (IfInstanceOf* x) { /* nothing to do */ }
+ void do_TableSwitch (TableSwitch* x) { /* nothing to do */ }
+ void do_LookupSwitch (LookupSwitch* x) { /* nothing to do */ }
+ void do_Return (Return* x) { /* nothing to do */ }
+ void do_Throw (Throw* x) { /* nothing to do */ }
+ void do_Base (Base* x) { /* nothing to do */ }
+ void do_OsrEntry (OsrEntry* x) { /* nothing to do */ }
+ void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ }
+ void do_RoundFP (RoundFP* x) { /* nothing to do */ }
+ void do_UnsafeGetRaw (UnsafeGetRaw* x) { /* nothing to do */ }
+ void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ }
+ void do_UnsafePrefetchRead (UnsafePrefetchRead* x) { /* nothing to do */ }
+ void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ }
+ void do_ProfileCall (ProfileCall* x) { /* nothing to do */ }
+ void do_ProfileCounter (ProfileCounter* x) { /* nothing to do */ }
+};
+
+
+class ValueNumberingEffects: public ValueNumberingVisitor {
+ private:
+ ValueMap* _map;
+
+ public:
+ // implementation for abstract methods of ValueNumberingVisitor
+ void kill_memory() { _map->kill_memory(); }
+ void kill_field(ciField* field) { _map->kill_field(field); }
+ void kill_array(ValueType* type) { _map->kill_array(type); }
+
+ ValueNumberingEffects(ValueMap* map): _map(map) {}
};
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp Fri Dec 05 15:06:37 2008 -0500
@@ -325,24 +325,30 @@
// For objects in CMS generation, this closure marks
// given objects (transitively) as being reachable/live.
// This is currently used during the (weak) reference object
-// processing phase of the CMS final checkpoint step.
+// processing phase of the CMS final checkpoint step, as
+// well as during the concurrent precleaning of the discovered
+// reference lists.
class CMSKeepAliveClosure: public OopClosure {
private:
CMSCollector* _collector;
const MemRegion _span;
CMSMarkStack* _mark_stack;
CMSBitMap* _bit_map;
+ bool _concurrent_precleaning;
protected:
DO_OOP_WORK_DEFN
public:
CMSKeepAliveClosure(CMSCollector* collector, MemRegion span,
- CMSBitMap* bit_map, CMSMarkStack* mark_stack):
+ CMSBitMap* bit_map, CMSMarkStack* mark_stack,
+ bool cpc):
_collector(collector),
_span(span),
_bit_map(bit_map),
- _mark_stack(mark_stack) {
+ _mark_stack(mark_stack),
+ _concurrent_precleaning(cpc) {
assert(!_span.is_empty(), "Empty span could spell trouble");
}
+ bool concurrent_precleaning() const { return _concurrent_precleaning; }
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
inline void do_oop_nv(oop* p) { CMSKeepAliveClosure::do_oop_work(p); }
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -538,6 +538,7 @@
_survivor_chunk_capacity(0), // -- ditto --
_survivor_chunk_index(0), // -- ditto --
_ser_pmc_preclean_ovflw(0),
+ _ser_kac_preclean_ovflw(0),
_ser_pmc_remark_ovflw(0),
_par_pmc_remark_ovflw(0),
_ser_kac_ovflw(0),
@@ -1960,6 +1961,7 @@
ref_processor()->set_enqueuing_is_done(false);
ref_processor()->enable_discovery();
+ ref_processor()->setup_policy(clear_all_soft_refs);
// If an asynchronous collection finishes, the _modUnionTable is
// all clear. If we are assuming the collection from an asynchronous
// collection, clear the _modUnionTable.
@@ -2383,6 +2385,9 @@
Universe::verify(true);
}
+ // Snapshot the soft reference policy to be used in this collection cycle.
+ ref_processor()->setup_policy(clear_all_soft_refs);
+
bool init_mark_was_synchronous = false; // until proven otherwise
while (_collectorState != Idling) {
if (TraceCMSState) {
@@ -4388,10 +4393,10 @@
CMSPrecleanRefsYieldClosure yield_cl(this);
assert(rp->span().equals(_span), "Spans should be equal");
CMSKeepAliveClosure keep_alive(this, _span, &_markBitMap,
- &_markStack);
+ &_markStack, true /* preclean */);
CMSDrainMarkingStackClosure complete_trace(this,
- _span, &_markBitMap, &_markStack,
- &keep_alive);
+ _span, &_markBitMap, &_markStack,
+ &keep_alive, true /* preclean */);
// We don't want this step to interfere with a young
// collection because we don't want to take CPU
@@ -4590,11 +4595,11 @@
if (!dirtyRegion.is_empty()) {
assert(numDirtyCards > 0, "consistency check");
HeapWord* stop_point = NULL;
+ stopTimer();
+ CMSTokenSyncWithLocks ts(true, gen->freelistLock(),
+ bitMapLock());
+ startTimer();
{
- stopTimer();
- CMSTokenSyncWithLocks ts(true, gen->freelistLock(),
- bitMapLock());
- startTimer();
verify_work_stacks_empty();
verify_overflow_empty();
sample_eden();
@@ -4611,10 +4616,6 @@
assert((CMSPermGenPrecleaningEnabled && (gen == _permGen)) ||
(_collectorState == AbortablePreclean && should_abort_preclean()),
"Unparsable objects should only be in perm gen.");
-
- stopTimer();
- CMSTokenSyncWithLocks ts(true, bitMapLock());
- startTimer();
_modUnionTable.mark_range(MemRegion(stop_point, dirtyRegion.end()));
if (should_abort_preclean()) {
break; // out of preclean loop
@@ -4852,17 +4853,19 @@
// recurrence of that condition.
assert(_markStack.isEmpty(), "No grey objects");
size_t ser_ovflw = _ser_pmc_remark_ovflw + _ser_pmc_preclean_ovflw +
- _ser_kac_ovflw;
+ _ser_kac_ovflw + _ser_kac_preclean_ovflw;
if (ser_ovflw > 0) {
if (PrintCMSStatistics != 0) {
gclog_or_tty->print_cr("Marking stack overflow (benign) "
- "(pmc_pc="SIZE_FORMAT", pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT")",
+ "(pmc_pc="SIZE_FORMAT", pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT
+ ", kac_preclean="SIZE_FORMAT")",
_ser_pmc_preclean_ovflw, _ser_pmc_remark_ovflw,
- _ser_kac_ovflw);
+ _ser_kac_ovflw, _ser_kac_preclean_ovflw);
}
_markStack.expand();
_ser_pmc_remark_ovflw = 0;
_ser_pmc_preclean_ovflw = 0;
+ _ser_kac_preclean_ovflw = 0;
_ser_kac_ovflw = 0;
}
if (_par_pmc_remark_ovflw > 0 || _par_kac_ovflw > 0) {
@@ -5675,40 +5678,29 @@
ResourceMark rm;
HandleMark hm;
- ReferencePolicy* soft_ref_policy;
-
- assert(!ref_processor()->enqueuing_is_done(), "Enqueuing should not be complete");
- // Process weak references.
- if (clear_all_soft_refs) {
- soft_ref_policy = new AlwaysClearPolicy();
- } else {
-#ifdef COMPILER2
- soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif // COMPILER2
- }
- verify_work_stacks_empty();
ReferenceProcessor* rp = ref_processor();
assert(rp->span().equals(_span), "Spans should be equal");
+ assert(!rp->enqueuing_is_done(), "Enqueuing should not be complete");
+ // Process weak references.
+ rp->setup_policy(clear_all_soft_refs);
+ verify_work_stacks_empty();
+
CMSKeepAliveClosure cmsKeepAliveClosure(this, _span, &_markBitMap,
- &_markStack);
+ &_markStack, false /* !preclean */);
CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this,
_span, &_markBitMap, &_markStack,
- &cmsKeepAliveClosure);
+ &cmsKeepAliveClosure, false /* !preclean */);
{
TraceTime t("weak refs processing", PrintGCDetails, false, gclog_or_tty);
if (rp->processing_is_mt()) {
CMSRefProcTaskExecutor task_executor(*this);
- rp->process_discovered_references(soft_ref_policy,
- &_is_alive_closure,
+ rp->process_discovered_references(&_is_alive_closure,
&cmsKeepAliveClosure,
&cmsDrainMarkingStackClosure,
&task_executor);
} else {
- rp->process_discovered_references(soft_ref_policy,
- &_is_alive_closure,
+ rp->process_discovered_references(&_is_alive_closure,
&cmsKeepAliveClosure,
&cmsDrainMarkingStackClosure,
NULL);
@@ -6163,8 +6155,8 @@
#endif
size_t CMSCollector::block_size_using_printezis_bits(HeapWord* addr) const {
- assert(_markBitMap.isMarked(addr) && _markBitMap.isMarked(addr + 1),
- "missing Printezis mark?");
+ assert(_markBitMap.isMarked(addr) && _markBitMap.isMarked(addr + 1),
+ "missing Printezis mark?");
HeapWord* nextOneAddr = _markBitMap.getNextMarkedWordAddress(addr + 2);
size_t size = pointer_delta(nextOneAddr + 1, addr);
assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
@@ -8302,8 +8294,29 @@
}
)
if (simulate_overflow || !_mark_stack->push(obj)) {
- _collector->push_on_overflow_list(obj);
- _collector->_ser_kac_ovflw++;
+ if (_concurrent_precleaning) {
+ // We dirty the overflown object and let the remark
+ // phase deal with it.
+ assert(_collector->overflow_list_is_empty(), "Error");
+ // In the case of object arrays, we need to dirty all of
+ // the cards that the object spans. No locking or atomics
+ // are needed since no one else can be mutating the mod union
+ // table.
+ if (obj->is_objArray()) {
+ size_t sz = obj->size();
+ HeapWord* end_card_addr =
+ (HeapWord*)round_to((intptr_t)(addr+sz), CardTableModRefBS::card_size);
+ MemRegion redirty_range = MemRegion(addr, end_card_addr);
+ assert(!redirty_range.is_empty(), "Arithmetical tautology");
+ _collector->_modUnionTable.mark_range(redirty_range);
+ } else {
+ _collector->_modUnionTable.mark(addr);
+ }
+ _collector->_ser_kac_preclean_ovflw++;
+ } else {
+ _collector->push_on_overflow_list(obj);
+ _collector->_ser_kac_ovflw++;
+ }
}
}
}
@@ -8400,6 +8413,8 @@
void CMSDrainMarkingStackClosure::do_void() {
// the max number to take from overflow list at a time
const size_t num = _mark_stack->capacity()/4;
+ assert(!_concurrent_precleaning || _collector->overflow_list_is_empty(),
+ "Overflow list should be NULL during concurrent phases");
while (!_mark_stack->isEmpty() ||
// if stack is empty, check the overflow list
_collector->take_from_overflow_list(num, _mark_stack)) {
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Fri Dec 05 15:06:37 2008 -0500
@@ -592,6 +592,7 @@
size_t _ser_pmc_preclean_ovflw;
size_t _ser_pmc_remark_ovflw;
size_t _par_pmc_remark_ovflw;
+ size_t _ser_kac_preclean_ovflw;
size_t _ser_kac_ovflw;
size_t _par_kac_ovflw;
NOT_PRODUCT(size_t _num_par_pushes;)
@@ -1749,21 +1750,30 @@
// work-routine/closure used to complete transitive
// marking of objects as live after a certain point
// in which an initial set has been completely accumulated.
+// This closure is currently used both during the final
+// remark stop-world phase, as well as during the concurrent
+// precleaning of the discovered reference lists.
class CMSDrainMarkingStackClosure: public VoidClosure {
CMSCollector* _collector;
MemRegion _span;
CMSMarkStack* _mark_stack;
CMSBitMap* _bit_map;
CMSKeepAliveClosure* _keep_alive;
+ bool _concurrent_precleaning;
public:
CMSDrainMarkingStackClosure(CMSCollector* collector, MemRegion span,
CMSBitMap* bit_map, CMSMarkStack* mark_stack,
- CMSKeepAliveClosure* keep_alive):
+ CMSKeepAliveClosure* keep_alive,
+ bool cpc):
_collector(collector),
_span(span),
_bit_map(bit_map),
_mark_stack(mark_stack),
- _keep_alive(keep_alive) { }
+ _keep_alive(keep_alive),
+ _concurrent_precleaning(cpc) {
+ assert(_concurrent_precleaning == _keep_alive->concurrent_precleaning(),
+ "Mismatch");
+ }
void do_void();
};
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -811,6 +811,7 @@
ReferenceProcessor* rp = g1h->ref_processor();
rp->verify_no_references_recorded();
rp->enable_discovery(); // enable ("weak") refs discovery
+ rp->setup_policy(false); // snapshot the soft ref policy to be used in this cycle
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
satb_mq_set.set_process_completed_threshold(G1SATBProcessCompletedThreshold);
@@ -1829,32 +1830,21 @@
void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
ResourceMark rm;
HandleMark hm;
- ReferencePolicy* soft_ref_policy;
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+ ReferenceProcessor* rp = g1h->ref_processor();
// Process weak references.
- if (clear_all_soft_refs) {
- soft_ref_policy = new AlwaysClearPolicy();
- } else {
-#ifdef COMPILER2
- soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif
- }
+ rp->setup_policy(clear_all_soft_refs);
assert(_markStack.isEmpty(), "mark stack should be empty");
- G1CollectedHeap* g1 = G1CollectedHeap::heap();
- G1CMIsAliveClosure g1IsAliveClosure(g1);
-
- G1CMKeepAliveClosure g1KeepAliveClosure(g1, this, nextMarkBitMap());
+ G1CMIsAliveClosure g1IsAliveClosure (g1h);
+ G1CMKeepAliveClosure g1KeepAliveClosure(g1h, this, nextMarkBitMap());
G1CMDrainMarkingStackClosure
g1DrainMarkingStackClosure(nextMarkBitMap(), &_markStack,
&g1KeepAliveClosure);
// XXXYYY Also: copy the parallel ref processing code from CMS.
- ReferenceProcessor* rp = g1->ref_processor();
- rp->process_discovered_references(soft_ref_policy,
- &g1IsAliveClosure,
+ rp->process_discovered_references(&g1IsAliveClosure,
&g1KeepAliveClosure,
&g1DrainMarkingStackClosure,
NULL);
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -891,6 +891,7 @@
ReferenceProcessorIsAliveMutator rp_is_alive_null(ref_processor(), NULL);
ref_processor()->enable_discovery();
+ ref_processor()->setup_policy(clear_all_soft_refs);
// Do collection work
{
@@ -2463,7 +2464,7 @@
COMPILER2_PRESENT(DerivedPointerTable::clear());
- // We want to turn off ref discovere, if necessary, and turn it back on
+ // We want to turn off ref discovery, if necessary, and turn it back on
// on again later if we do.
bool was_enabled = ref_processor()->discovery_enabled();
if (was_enabled) ref_processor()->disable_discovery();
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -33,8 +33,9 @@
// hook up weak ref data so it can be used during Mark-Sweep
assert(GenMarkSweep::ref_processor() == NULL, "no stomping");
+ assert(rp != NULL, "should be non-NULL");
GenMarkSweep::_ref_processor = rp;
- assert(rp != NULL, "should be non-NULL");
+ rp->setup_policy(clear_all_softrefs);
// When collecting the permanent generation methodOops may be moving,
// so we either have to flush all bcp data or convert it into bci.
@@ -121,23 +122,12 @@
&GenMarkSweep::follow_root_closure);
// Process reference objects found during marking
- ReferencePolicy *soft_ref_policy;
- if (clear_all_softrefs) {
- soft_ref_policy = new AlwaysClearPolicy();
- } else {
-#ifdef COMPILER2
- soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif
- }
- assert(soft_ref_policy != NULL,"No soft reference policy");
- GenMarkSweep::ref_processor()->process_discovered_references(
- soft_ref_policy,
- &GenMarkSweep::is_alive,
- &GenMarkSweep::keep_alive,
- &GenMarkSweep::follow_stack_closure,
- NULL);
+ ReferenceProcessor* rp = GenMarkSweep::ref_processor();
+ rp->setup_policy(clear_all_softrefs);
+ rp->process_discovered_references(&GenMarkSweep::is_alive,
+ &GenMarkSweep::keep_alive,
+ &GenMarkSweep::follow_stack_closure,
+ NULL);
// Follow system dictionary roots and unload classes
bool purged_class = SystemDictionary::do_unloading(&GenMarkSweep::is_alive);
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -759,17 +759,12 @@
thread_state_set.steals(),
thread_state_set.pops()+thread_state_set.steals());
}
- assert(thread_state_set.pushes() == thread_state_set.pops() + thread_state_set.steals(),
+ assert(thread_state_set.pushes() == thread_state_set.pops()
+ + thread_state_set.steals(),
"Or else the queues are leaky.");
- // For now, process discovered weak refs sequentially.
-#ifdef COMPILER2
- ReferencePolicy *soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- ReferencePolicy *soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif // COMPILER2
-
// Process (weak) reference objects found during scavenge.
+ ReferenceProcessor* rp = ref_processor();
IsAliveClosure is_alive(this);
ScanWeakRefClosure scan_weak_ref(this);
KeepAliveClosure keep_alive(&scan_weak_ref);
@@ -778,18 +773,17 @@
set_promo_failure_scan_stack_closure(&scan_without_gc_barrier);
EvacuateFollowersClosureGeneral evacuate_followers(gch, _level,
&scan_without_gc_barrier, &scan_with_gc_barrier);
- if (ref_processor()->processing_is_mt()) {
+ rp->setup_policy(clear_all_soft_refs);
+ if (rp->processing_is_mt()) {
ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
- ref_processor()->process_discovered_references(
- soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers,
- &task_executor);
+ rp->process_discovered_references(&is_alive, &keep_alive,
+ &evacuate_followers, &task_executor);
} else {
thread_state_set.flush();
gch->set_par_threads(0); // 0 ==> non-parallel.
gch->save_marks();
- ref_processor()->process_discovered_references(
- soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers,
- NULL);
+ rp->process_discovered_references(&is_alive, &keep_alive,
+ &evacuate_followers, NULL);
}
if (!promotion_failed()) {
// Swap the survivor spaces.
@@ -851,14 +845,14 @@
SpecializationStats::print();
- ref_processor()->set_enqueuing_is_done(true);
- if (ref_processor()->processing_is_mt()) {
+ rp->set_enqueuing_is_done(true);
+ if (rp->processing_is_mt()) {
ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
- ref_processor()->enqueue_discovered_references(&task_executor);
+ rp->enqueue_discovered_references(&task_executor);
} else {
- ref_processor()->enqueue_discovered_references(NULL);
+ rp->enqueue_discovered_references(NULL);
}
- ref_processor()->verify_no_references_recorded();
+ rp->verify_no_references_recorded();
}
static int sum;
@@ -1211,7 +1205,7 @@
int n = 0;
while (cur != NULL) {
oop obj_to_push = cur->forwardee();
- oop next = oop(cur->klass());
+ oop next = oop(cur->klass_or_null());
cur->set_klass(obj_to_push->klass());
if (par_scan_state->should_be_partially_scanned(obj_to_push, cur)) {
obj_to_push = cur;
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -172,6 +172,7 @@
COMPILER2_PRESENT(DerivedPointerTable::clear());
ref_processor()->enable_discovery();
+ ref_processor()->setup_policy(clear_all_softrefs);
mark_sweep_phase1(clear_all_softrefs);
@@ -517,20 +518,9 @@
// Process reference objects found during marking
{
- ReferencePolicy *soft_ref_policy;
- if (clear_all_softrefs) {
- soft_ref_policy = new AlwaysClearPolicy();
- } else {
-#ifdef COMPILER2
- soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif // COMPILER2
- }
- assert(soft_ref_policy != NULL,"No soft reference policy");
+ ref_processor()->setup_policy(clear_all_softrefs);
ref_processor()->process_discovered_references(
- soft_ref_policy, is_alive_closure(), mark_and_push_closure(),
- follow_stack_closure(), NULL);
+ is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL);
}
// Follow system dictionary roots and unload classes
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -1578,6 +1578,7 @@
COMPILER2_PRESENT(DerivedPointerTable::clear());
ref_processor()->enable_discovery();
+ ref_processor()->setup_policy(maximum_heap_compaction);
bool marked_for_unloading = false;
@@ -1894,26 +1895,14 @@
// Process reference objects found during marking
{
TraceTime tm_r("reference processing", print_phases(), true, gclog_or_tty);
- ReferencePolicy *soft_ref_policy;
- if (maximum_heap_compaction) {
- soft_ref_policy = new AlwaysClearPolicy();
- } else {
-#ifdef COMPILER2
- soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif // COMPILER2
- }
- assert(soft_ref_policy != NULL, "No soft reference policy");
if (ref_processor()->processing_is_mt()) {
RefProcTaskExecutor task_executor;
ref_processor()->process_discovered_references(
- soft_ref_policy, is_alive_closure(), &mark_and_push_closure,
- &follow_stack_closure, &task_executor);
+ is_alive_closure(), &mark_and_push_closure, &follow_stack_closure,
+ &task_executor);
} else {
ref_processor()->process_discovered_references(
- soft_ref_policy, is_alive_closure(), &mark_and_push_closure,
- &follow_stack_closure, NULL);
+ is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, NULL);
}
}
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -330,6 +330,7 @@
COMPILER2_PRESENT(DerivedPointerTable::clear());
reference_processor()->enable_discovery();
+ reference_processor()->setup_policy(false);
// We track how much was promoted to the next generation for
// the AdaptiveSizePolicy.
@@ -394,24 +395,16 @@
// Process reference objects discovered during scavenge
{
-#ifdef COMPILER2
- ReferencePolicy *soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- ReferencePolicy *soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif // COMPILER2
-
+ reference_processor()->setup_policy(false); // not always_clear
PSKeepAliveClosure keep_alive(promotion_manager);
PSEvacuateFollowersClosure evac_followers(promotion_manager);
- assert(soft_ref_policy != NULL,"No soft reference policy");
if (reference_processor()->processing_is_mt()) {
PSRefProcTaskExecutor task_executor;
reference_processor()->process_discovered_references(
- soft_ref_policy, &_is_alive_closure, &keep_alive, &evac_followers,
- &task_executor);
+ &_is_alive_closure, &keep_alive, &evac_followers, &task_executor);
} else {
reference_processor()->process_discovered_references(
- soft_ref_policy, &_is_alive_closure, &keep_alive, &evac_followers,
- NULL);
+ &_is_alive_closure, &keep_alive, &evac_followers, NULL);
}
}
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp
--- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -414,9 +414,20 @@
if (limit > 0) {
limit = round_down(limit, page_size());
if (chunk_size > current_chunk_size(i)) {
- chunk_size = MIN2((off_t)chunk_size, (off_t)current_chunk_size(i) + (off_t)limit);
+ size_t upper_bound = pages_available * page_size();
+ if (upper_bound > limit &&
+ current_chunk_size(i) < upper_bound - limit) {
+ // The resulting upper bound should not exceed the available
+ // amount of memory (pages_available * page_size()).
+ upper_bound = current_chunk_size(i) + limit;
+ }
+ chunk_size = MIN2(chunk_size, upper_bound);
} else {
- chunk_size = MAX2((off_t)chunk_size, (off_t)current_chunk_size(i) - (off_t)limit);
+ size_t lower_bound = page_size();
+ if (current_chunk_size(i) > limit) { // lower_bound shouldn't underflow.
+ lower_bound = current_chunk_size(i) - limit;
+ }
+ chunk_size = MAX2(chunk_size, lower_bound);
}
}
assert(chunk_size <= pages_available * page_size(), "Chunk size out of range");
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/includeDB_core
--- a/hotspot/src/share/vm/includeDB_core Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/includeDB_core Fri Dec 05 15:06:37 2008 -0500
@@ -3435,6 +3435,7 @@
referenceProcessor.cpp systemDictionary.hpp
referenceProcessor.hpp instanceRefKlass.hpp
+referenceProcessor.hpp referencePolicy.hpp
reflection.cpp arguments.hpp
reflection.cpp handles.inline.hpp
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/memory/defNewGeneration.cpp
--- a/hotspot/src/share/vm/memory/defNewGeneration.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -540,14 +540,6 @@
assert(gch->no_allocs_since_save_marks(0),
"save marks have not been newly set.");
- // Weak refs.
- // FIXME: Are these storage leaks, or are they resource objects?
-#ifdef COMPILER2
- ReferencePolicy *soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- ReferencePolicy *soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif // COMPILER2
-
// Not very pretty.
CollectorPolicy* cp = gch->collector_policy();
@@ -574,8 +566,10 @@
evacuate_followers.do_void();
FastKeepAliveClosure keep_alive(this, &scan_weak_ref);
- ref_processor()->process_discovered_references(
- soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers, NULL);
+ ReferenceProcessor* rp = ref_processor();
+ rp->setup_policy(clear_all_soft_refs);
+ rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers,
+ NULL);
if (!promotion_failed()) {
// Swap the survivor spaces.
eden()->clear(SpaceDecorator::Mangle);
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/memory/genCollectedHeap.cpp
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -525,8 +525,9 @@
if (rp->discovery_is_atomic()) {
rp->verify_no_references_recorded();
rp->enable_discovery();
+ rp->setup_policy(clear_all_soft_refs);
} else {
- // collect() will enable discovery as appropriate
+ // collect() below will enable discovery as appropriate
}
_gens[i]->collect(full, clear_all_soft_refs, size, is_tlab);
if (!rp->enqueuing_is_done()) {
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/memory/genMarkSweep.cpp
--- a/hotspot/src/share/vm/memory/genMarkSweep.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -31,8 +31,9 @@
// hook up weak ref data so it can be used during Mark-Sweep
assert(ref_processor() == NULL, "no stomping");
+ assert(rp != NULL, "should be non-NULL");
_ref_processor = rp;
- assert(rp != NULL, "should be non-NULL");
+ rp->setup_policy(clear_all_softrefs);
TraceTime t1("Full GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
@@ -245,20 +246,9 @@
// Process reference objects found during marking
{
- ReferencePolicy *soft_ref_policy;
- if (clear_all_softrefs) {
- soft_ref_policy = new AlwaysClearPolicy();
- } else {
-#ifdef COMPILER2
- soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif // COMPILER2
- }
- assert(soft_ref_policy != NULL,"No soft reference policy");
+ ref_processor()->setup_policy(clear_all_softrefs);
ref_processor()->process_discovered_references(
- soft_ref_policy, &is_alive, &keep_alive,
- &follow_stack_closure, NULL);
+ &is_alive, &keep_alive, &follow_stack_closure, NULL);
}
// Follow system dictionary roots and unload classes
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/memory/referencePolicy.cpp
--- a/hotspot/src/share/vm/memory/referencePolicy.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/memory/referencePolicy.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -26,6 +26,11 @@
# include "incls/_referencePolicy.cpp.incl"
LRUCurrentHeapPolicy::LRUCurrentHeapPolicy() {
+ setup();
+}
+
+// Capture state (of-the-VM) information needed to evaluate the policy
+void LRUCurrentHeapPolicy::setup() {
_max_interval = (Universe::get_heap_free_at_last_gc() / M) * SoftRefLRUPolicyMSPerMB;
assert(_max_interval >= 0,"Sanity check");
}
@@ -47,6 +52,11 @@
/////////////////////// MaxHeap //////////////////////
LRUMaxHeapPolicy::LRUMaxHeapPolicy() {
+ setup();
+}
+
+// Capture state (of-the-VM) information needed to evaluate the policy
+void LRUMaxHeapPolicy::setup() {
size_t max_heap = MaxHeapSize;
max_heap -= Universe::get_heap_used_at_last_gc();
max_heap /= M;
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/memory/referencePolicy.hpp
--- a/hotspot/src/share/vm/memory/referencePolicy.hpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/memory/referencePolicy.hpp Fri Dec 05 15:06:37 2008 -0500
@@ -26,9 +26,11 @@
// should be cleared.
-class ReferencePolicy : public ResourceObj {
+class ReferencePolicy : public CHeapObj {
public:
virtual bool should_clear_reference(oop p) { ShouldNotReachHere(); return true; }
+ // Capture state (of-the-VM) information needed to evaluate the policy
+ virtual void setup() { /* do nothing */ }
};
class NeverClearPolicy : public ReferencePolicy {
@@ -48,6 +50,8 @@
public:
LRUCurrentHeapPolicy();
+ // Capture state (of-the-VM) information needed to evaluate the policy
+ void setup();
bool should_clear_reference(oop p);
};
@@ -58,5 +62,7 @@
public:
LRUMaxHeapPolicy();
+ // Capture state (of-the-VM) information needed to evaluate the policy
+ void setup();
bool should_clear_reference(oop p);
};
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/memory/referenceProcessor.cpp
--- a/hotspot/src/share/vm/memory/referenceProcessor.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -25,6 +25,11 @@
# include "incls/_precompiled.incl"
# include "incls/_referenceProcessor.cpp.incl"
+ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL;
+ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy = NULL;
+oop ReferenceProcessor::_sentinelRef = NULL;
+const int subclasses_of_ref = REF_PHANTOM - REF_OTHER;
+
// List of discovered references.
class DiscoveredList {
public:
@@ -47,7 +52,9 @@
}
bool empty() const { return head() == ReferenceProcessor::sentinel_ref(); }
size_t length() { return _len; }
- void set_length(size_t len) { _len = len; }
+ void set_length(size_t len) { _len = len; }
+ void inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); }
+ void dec_length(size_t dec) { _len -= dec; }
private:
// Set value depending on UseCompressedOops. This could be a template class
// but then we have to fix all the instantiations and declarations that use this class.
@@ -56,10 +63,6 @@
size_t _len;
};
-oop ReferenceProcessor::_sentinelRef = NULL;
-
-const int subclasses_of_ref = REF_PHANTOM - REF_OTHER;
-
void referenceProcessor_init() {
ReferenceProcessor::init_statics();
}
@@ -80,6 +83,12 @@
}
assert(_sentinelRef != NULL && _sentinelRef->is_oop(),
"Just constructed it!");
+ _always_clear_soft_ref_policy = new AlwaysClearPolicy();
+ _default_soft_ref_policy = new COMPILER2_PRESENT(LRUMaxHeapPolicy())
+ NOT_COMPILER2(LRUCurrentHeapPolicy());
+ if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) {
+ vm_exit_during_initialization("Could not allocate reference policy object");
+ }
guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery ||
RefDiscoveryPolicy == ReferentBasedDiscovery,
"Unrecongnized RefDiscoveryPolicy");
@@ -106,6 +115,7 @@
vm_exit_during_initialization("Could not allocate ReferenceProcessor object");
}
rp->set_is_alive_non_header(is_alive_non_header);
+ rp->setup_policy(false /* default soft ref policy */);
return rp;
}
@@ -192,7 +202,6 @@
}
void ReferenceProcessor::process_discovered_references(
- ReferencePolicy* policy,
BoolObjectClosure* is_alive,
OopClosure* keep_alive,
VoidClosure* complete_gc,
@@ -207,7 +216,7 @@
// Soft references
{
TraceTime tt("SoftReference", trace_time, false, gclog_or_tty);
- process_discovered_reflist(_discoveredSoftRefs, policy, true,
+ process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,
is_alive, keep_alive, complete_gc, task_executor);
}
@@ -436,13 +445,13 @@
// The "allow_null_referent" argument tells us to allow for the possibility
// of a NULL referent in the discovered Reference object. This typically
// happens in the case of concurrent collectors that may have done the
- // discovery concurrently or interleaved with mutator execution.
+ // discovery concurrently, or interleaved, with mutator execution.
inline void load_ptrs(DEBUG_ONLY(bool allow_null_referent));
// Move to the next discovered reference.
inline void next();
- // Remove the current reference from the list and move to the next.
+ // Remove the current reference from the list
inline void remove();
// Make the Reference object active again.
@@ -476,7 +485,6 @@
inline size_t removed() const { return _removed; }
)
-private:
inline void move_to_next();
private:
@@ -553,7 +561,7 @@
oopDesc::store_heap_oop((oop*)_prev_next, _next);
}
NOT_PRODUCT(_removed++);
- move_to_next();
+ _refs_list.dec_length(1);
}
inline void DiscoveredListIterator::move_to_next() {
@@ -591,12 +599,13 @@
gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy",
iter.obj(), iter.obj()->blueprint()->internal_name());
}
+ // Remove Reference object from list
+ iter.remove();
// Make the Reference object active again
iter.make_active();
// keep the referent around
iter.make_referent_alive();
- // Remove Reference object from list
- iter.remove();
+ iter.move_to_next();
} else {
iter.next();
}
@@ -629,12 +638,13 @@
iter.obj(), iter.obj()->blueprint()->internal_name());
}
// The referent is reachable after all.
+ // Remove Reference object from list.
+ iter.remove();
// Update the referent pointer as necessary: Note that this
// should not entail any recursive marking because the
// referent must already have been traversed.
iter.make_referent_alive();
- // Remove Reference object from list
- iter.remove();
+ iter.move_to_next();
} else {
iter.next();
}
@@ -670,6 +680,7 @@
} else {
keep_alive->do_oop((oop*)next_addr);
}
+ iter.move_to_next();
} else {
iter.next();
}
@@ -832,9 +843,9 @@
}
java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head());
ref_lists[to_idx].set_head(move_head);
- ref_lists[to_idx].set_length(ref_lists[to_idx].length() + refs_to_move);
+ ref_lists[to_idx].inc_length(refs_to_move);
ref_lists[from_idx].set_head(new_head);
- ref_lists[from_idx].set_length(ref_lists[from_idx].length() - refs_to_move);
+ ref_lists[from_idx].dec_length(refs_to_move);
} else {
++to_idx;
}
@@ -923,7 +934,6 @@
void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list) {
assert(!discovery_is_atomic(), "Else why call this method?");
DiscoveredListIterator iter(refs_list, NULL, NULL);
- size_t length = refs_list.length();
while (iter.has_next()) {
iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
oop next = java_lang_ref_Reference::next(iter.obj());
@@ -941,12 +951,11 @@
)
// Remove Reference object from list
iter.remove();
- --length;
+ iter.move_to_next();
} else {
iter.next();
}
}
- refs_list.set_length(length);
NOT_PRODUCT(
if (PrintGCDetails && TraceReferenceGC) {
gclog_or_tty->print(
@@ -1024,7 +1033,7 @@
// We have separate lists for enqueueing so no synchronization
// is necessary.
refs_list.set_head(obj);
- refs_list.set_length(refs_list.length() + 1);
+ refs_list.inc_length(1);
if (_discovered_list_needs_barrier) {
_bs->write_ref_field((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR");
}
@@ -1090,15 +1099,28 @@
// reachable.
if (is_alive_non_header() != NULL) {
oop referent = java_lang_ref_Reference::referent(obj);
- // We'd like to assert the following:
- // assert(referent != NULL, "Refs with null referents already filtered");
- // However, since this code may be executed concurrently with
- // mutators, which can clear() the referent, it is not
- // guaranteed that the referent is non-NULL.
+ // In the case of non-concurrent discovery, the last
+ // disjunct below should hold. It may not hold in the
+ // case of concurrent discovery because mutators may
+ // concurrently clear() a Reference.
+ assert(UseConcMarkSweepGC || UseG1GC || referent != NULL,
+ "Refs with null referents already filtered");
if (is_alive_non_header()->do_object_b(referent)) {
return false; // referent is reachable
}
}
+ if (rt == REF_SOFT) {
+ // For soft refs we can decide now if these are not
+ // current candidates for clearing, in which case we
+ // can mark through them now, rather than delaying that
+ // to the reference-processing phase. Since all current
+ // time-stamp policies advance the soft-ref clock only
+ // at a major collection cycle, this is always currently
+ // accurate.
+ if (!_current_soft_ref_policy->should_clear_reference(obj)) {
+ return false;
+ }
+ }
HeapWord* const discovered_addr = java_lang_ref_Reference::discovered_addr(obj);
const oop discovered = java_lang_ref_Reference::discovered(obj);
@@ -1168,7 +1190,7 @@
_bs->write_ref_field((oop*)discovered_addr, current_head);
}
list->set_head(obj);
- list->set_length(list->length() + 1);
+ list->inc_length(1);
}
// In the MT discovery case, it is currently possible to see
@@ -1209,45 +1231,48 @@
TraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC,
false, gclog_or_tty);
for (int i = 0; i < _num_q; i++) {
+ if (yield->should_return()) {
+ return;
+ }
preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
}
- if (yield->should_return()) {
- return;
- }
// Weak references
{
TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC,
false, gclog_or_tty);
for (int i = 0; i < _num_q; i++) {
+ if (yield->should_return()) {
+ return;
+ }
preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
}
- if (yield->should_return()) {
- return;
- }
// Final references
{
TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC,
false, gclog_or_tty);
for (int i = 0; i < _num_q; i++) {
+ if (yield->should_return()) {
+ return;
+ }
preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
}
- if (yield->should_return()) {
- return;
- }
// Phantom references
{
TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC,
false, gclog_or_tty);
for (int i = 0; i < _num_q; i++) {
+ if (yield->should_return()) {
+ return;
+ }
preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive,
keep_alive, complete_gc, yield);
}
@@ -1256,9 +1281,12 @@
// Walk the given discovered ref list, and remove all reference objects
// whose referents are still alive, whose referents are NULL or which
-// are not active (have a non-NULL next field). NOTE: For this to work
-// correctly, refs discovery can not be happening concurrently with this
-// step.
+// are not active (have a non-NULL next field). NOTE: When we are
+// thus precleaning the ref lists (which happens single-threaded today),
+// we do not disable refs discovery to honour the correct semantics of
+// java.lang.Reference. As a result, we need to be careful below
+// that ref removal steps interleave safely with ref discovery steps
+// (in this thread).
void
ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
BoolObjectClosure* is_alive,
@@ -1266,7 +1294,6 @@
VoidClosure* complete_gc,
YieldClosure* yield) {
DiscoveredListIterator iter(refs_list, keep_alive, is_alive);
- size_t length = refs_list.length();
while (iter.has_next()) {
iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
oop obj = iter.obj();
@@ -1281,7 +1308,6 @@
}
// Remove Reference object from list
iter.remove();
- --length;
// Keep alive its cohort.
iter.make_referent_alive();
if (UseCompressedOops) {
@@ -1291,12 +1317,11 @@
oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj);
keep_alive->do_oop(next_addr);
}
+ iter.move_to_next();
} else {
iter.next();
}
}
- refs_list.set_length(length);
-
// Close the reachable set
complete_gc->do_void();
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/memory/referenceProcessor.hpp
--- a/hotspot/src/share/vm/memory/referenceProcessor.hpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp Fri Dec 05 15:06:37 2008 -0500
@@ -23,7 +23,7 @@
*/
// ReferenceProcessor class encapsulates the per-"collector" processing
-// of "weak" references for GC. The interface is useful for supporting
+// of java.lang.Reference objects for GC. The interface is useful for supporting
// a generational abstraction, in particular when there are multiple
// generations that are being independently collected -- possibly
// concurrently and/or incrementally. Note, however, that the
@@ -75,6 +75,14 @@
// all collectors but the CMS collector).
BoolObjectClosure* _is_alive_non_header;
+ // Soft ref clearing policies
+ // . the default policy
+ static ReferencePolicy* _default_soft_ref_policy;
+ // . the "clear all" policy
+ static ReferencePolicy* _always_clear_soft_ref_policy;
+ // . the current policy below is either one of the above
+ ReferencePolicy* _current_soft_ref_policy;
+
// The discovered ref lists themselves
// The MT'ness degree of the queues below
@@ -90,6 +98,12 @@
DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; }
static oop sentinel_ref() { return _sentinelRef; }
static oop* adr_sentinel_ref() { return &_sentinelRef; }
+ ReferencePolicy* setup_policy(bool always_clear) {
+ _current_soft_ref_policy = always_clear ?
+ _always_clear_soft_ref_policy : _default_soft_ref_policy;
+ _current_soft_ref_policy->setup(); // snapshot the policy threshold
+ return _current_soft_ref_policy;
+ }
public:
// Process references with a certain reachability level.
@@ -297,8 +311,7 @@
bool discover_reference(oop obj, ReferenceType rt);
// Process references found during GC (called by the garbage collector)
- void process_discovered_references(ReferencePolicy* policy,
- BoolObjectClosure* is_alive,
+ void process_discovered_references(BoolObjectClosure* is_alive,
OopClosure* keep_alive,
VoidClosure* complete_gc,
AbstractRefProcTaskExecutor* task_executor);
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/memory/universe.cpp
--- a/hotspot/src/share/vm/memory/universe.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/memory/universe.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -96,7 +96,7 @@
bool Universe::_fully_initialized = false;
size_t Universe::_heap_capacity_at_last_gc;
-size_t Universe::_heap_used_at_last_gc;
+size_t Universe::_heap_used_at_last_gc = 0;
CollectedHeap* Universe::_collectedHeap = NULL;
address Universe::_heap_base = NULL;
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/oops/oop.inline.hpp
--- a/hotspot/src/share/vm/oops/oop.inline.hpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/oops/oop.inline.hpp Fri Dec 05 15:06:37 2008 -0500
@@ -92,7 +92,7 @@
// This is only to be used during GC, for from-space objects, so no
// barrier is needed.
if (UseCompressedOops) {
- _metadata._compressed_klass = encode_heap_oop_not_null(k);
+ _metadata._compressed_klass = encode_heap_oop(k); // may be null (parnew overflow handling)
} else {
_metadata._klass = (klassOop)k;
}
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/opto/callnode.cpp
--- a/hotspot/src/share/vm/opto/callnode.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/opto/callnode.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -395,7 +395,13 @@
OptoReg::regname(OptoReg::c_frame_pointer),
regalloc->reg2offset(box_reg));
}
- format_helper( regalloc, st, obj, "MON-OBJ[", i, &scobjs );
+ const char* obj_msg = "MON-OBJ[";
+ if (EliminateLocks) {
+ while( !box->is_BoxLock() ) box = box->in(1);
+ if (box->as_BoxLock()->is_eliminated())
+ obj_msg = "MON-OBJ(LOCK ELIMINATED)[";
+ }
+ format_helper( regalloc, st, obj, obj_msg, i, &scobjs );
}
for (i = 0; i < (uint)scobjs.length(); i++) {
@@ -908,8 +914,9 @@
add_req(lock->box_node());
add_req(lock->obj_node());
} else {
- add_req(NULL);
- add_req(NULL);
+ Node* top = Compile::current()->top();
+ add_req(top);
+ add_req(top);
}
jvms()->set_scloff(nextmon+MonitorEdges);
jvms()->set_endoff(req());
@@ -1382,7 +1389,7 @@
//
// If we are locking an unescaped object, the lock/unlock is unnecessary
//
- ConnectionGraph *cgr = Compile::current()->congraph();
+ ConnectionGraph *cgr = phase->C->congraph();
PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
if (cgr != NULL)
es = cgr->escape_state(obj_node(), phase);
@@ -1450,6 +1457,7 @@
// Mark it eliminated to update any counters
lock->set_eliminated();
+ lock->set_coarsened();
}
} else if (result != NULL && ctrl->is_Region() &&
iter->_worklist.member(ctrl)) {
@@ -1484,7 +1492,7 @@
//
// If we are unlocking an unescaped object, the lock/unlock is unnecessary.
//
- ConnectionGraph *cgr = Compile::current()->congraph();
+ ConnectionGraph *cgr = phase->C->congraph();
PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
if (cgr != NULL)
es = cgr->escape_state(obj_node(), phase);
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/opto/callnode.hpp
--- a/hotspot/src/share/vm/opto/callnode.hpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/opto/callnode.hpp Fri Dec 05 15:06:37 2008 -0500
@@ -780,7 +780,8 @@
//------------------------------AbstractLockNode-----------------------------------
class AbstractLockNode: public CallNode {
private:
- bool _eliminate; // indicates this lock can be safely eliminated
+ bool _eliminate; // indicates this lock can be safely eliminated
+ bool _coarsened; // indicates this lock was coarsened
#ifndef PRODUCT
NamedCounter* _counter;
#endif
@@ -801,6 +802,7 @@
public:
AbstractLockNode(const TypeFunc *tf)
: CallNode(tf, NULL, TypeRawPtr::BOTTOM),
+ _coarsened(false),
_eliminate(false)
{
#ifndef PRODUCT
@@ -819,6 +821,9 @@
// mark node as eliminated and update the counter if there is one
void set_eliminated();
+ bool is_coarsened() { return _coarsened; }
+ void set_coarsened() { _coarsened = true; }
+
// locking does not modify its arguments
virtual bool may_modify(const TypePtr *addr_t, PhaseTransform *phase){ return false;}
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/opto/compile.cpp
--- a/hotspot/src/share/vm/opto/compile.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/opto/compile.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -1532,11 +1532,6 @@
if (failing()) return;
- // get rid of the connection graph since it's information is not
- // updated by optimizations
- _congraph = NULL;
-
-
// Loop transforms on the ideal graph. Range Check Elimination,
// peeling, unrolling, etc.
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/opto/escape.cpp
--- a/hotspot/src/share/vm/opto/escape.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/opto/escape.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -199,7 +199,8 @@
es = ptnode_adr(idx)->escape_state();
// if we have already computed a value, return it
- if (es != PointsToNode::UnknownEscape)
+ if (es != PointsToNode::UnknownEscape &&
+ ptnode_adr(idx)->node_type() == PointsToNode::JavaObject)
return es;
// PointsTo() calls n->uncast() which can return a new ideal node.
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/opto/locknode.cpp
--- a/hotspot/src/share/vm/opto/locknode.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/opto/locknode.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -44,10 +44,15 @@
_inmask.Insert(reg);
}
+//-----------------------------hash--------------------------------------------
+uint BoxLockNode::hash() const {
+ return Node::hash() + _slot + (_is_eliminated ? Compile::current()->fixed_slots() : 0);
+}
+
//------------------------------cmp--------------------------------------------
uint BoxLockNode::cmp( const Node &n ) const {
const BoxLockNode &bn = (const BoxLockNode &)n;
- return bn._slot == _slot;
+ return bn._slot == _slot && bn._is_eliminated == _is_eliminated;
}
OptoReg::Name BoxLockNode::stack_slot(Node* box_node) {
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/opto/locknode.hpp
--- a/hotspot/src/share/vm/opto/locknode.hpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/opto/locknode.hpp Fri Dec 05 15:06:37 2008 -0500
@@ -36,7 +36,7 @@
virtual const RegMask &in_RegMask(uint) const;
virtual const RegMask &out_RegMask() const;
virtual uint size_of() const;
- virtual uint hash() const { return Node::hash() + _slot; }
+ virtual uint hash() const;
virtual uint cmp( const Node &n ) const;
virtual const class Type *bottom_type() const { return TypeRawPtr::BOTTOM; }
virtual uint ideal_reg() const { return Op_RegP; }
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/opto/macro.cpp
--- a/hotspot/src/share/vm/opto/macro.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/opto/macro.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -59,7 +59,7 @@
for (uint i = old_dbg_start; i < oldcall->req(); i++) {
Node* old_in = oldcall->in(i);
// Clone old SafePointScalarObjectNodes, adjusting their field contents.
- if (old_in->is_SafePointScalarObject()) {
+ if (old_in != NULL && old_in->is_SafePointScalarObject()) {
SafePointScalarObjectNode* old_sosn = old_in->as_SafePointScalarObject();
uint old_unique = C->unique();
Node* new_in = old_sosn->clone(jvms_adj, sosn_map);
@@ -1509,21 +1509,63 @@
if (!alock->is_eliminated()) {
return false;
}
- // Mark the box lock as eliminated if all correspondent locks are eliminated
- // to construct correct debug info.
- BoxLockNode* box = alock->box_node()->as_BoxLock();
- if (!box->is_eliminated()) {
- bool eliminate = true;
- for (DUIterator_Fast imax, i = box->fast_outs(imax); i < imax; i++) {
- Node *lck = box->fast_out(i);
- if (lck->is_Lock() && !lck->as_AbstractLock()->is_eliminated()) {
- eliminate = false;
- break;
- }
- }
- if (eliminate)
- box->set_eliminated();
- }
+ if (alock->is_Lock() && !alock->is_coarsened()) {
+ // Create new "eliminated" BoxLock node and use it
+ // in monitor debug info for the same object.
+ BoxLockNode* oldbox = alock->box_node()->as_BoxLock();
+ Node* obj = alock->obj_node();
+ if (!oldbox->is_eliminated()) {
+ BoxLockNode* newbox = oldbox->clone()->as_BoxLock();
+ newbox->set_eliminated();
+ transform_later(newbox);
+ // Replace old box node with new box for all users
+ // of the same object.
+ for (uint i = 0; i < oldbox->outcnt();) {
+
+ bool next_edge = true;
+ Node* u = oldbox->raw_out(i);
+ if (u == alock) {
+ i++;
+ continue; // It will be removed below
+ }
+ if (u->is_Lock() &&
+ u->as_Lock()->obj_node() == obj &&
+ // oldbox could be referenced in debug info also
+ u->as_Lock()->box_node() == oldbox) {
+ assert(u->as_Lock()->is_eliminated(), "sanity");
+ _igvn.hash_delete(u);
+ u->set_req(TypeFunc::Parms + 1, newbox);
+ next_edge = false;
+#ifdef ASSERT
+ } else if (u->is_Unlock() && u->as_Unlock()->obj_node() == obj) {
+ assert(u->as_Unlock()->is_eliminated(), "sanity");
+#endif
+ }
+ // Replace old box in monitor debug info.
+ if (u->is_SafePoint() && u->as_SafePoint()->jvms()) {
+ SafePointNode* sfn = u->as_SafePoint();
+ JVMState* youngest_jvms = sfn->jvms();
+ int max_depth = youngest_jvms->depth();
+ for (int depth = 1; depth <= max_depth; depth++) {
+ JVMState* jvms = youngest_jvms->of_depth(depth);
+ int num_mon = jvms->nof_monitors();
+ // Loop over monitors
+ for (int idx = 0; idx < num_mon; idx++) {
+ Node* obj_node = sfn->monitor_obj(jvms, idx);
+ Node* box_node = sfn->monitor_box(jvms, idx);
+ if (box_node == oldbox && obj_node == obj) {
+ int j = jvms->monitor_box_offset(idx);
+ _igvn.hash_delete(u);
+ u->set_req(j, newbox);
+ next_edge = false;
+ }
+ } // for (int idx = 0;
+ } // for (int depth = 1;
+ } // if (u->is_SafePoint()
+ if (next_edge) i++;
+ } // for (uint i = 0; i < oldbox->outcnt();)
+ } // if (!oldbox->is_eliminated())
+ } // if (alock->is_Lock() && !lock->is_coarsened())
#ifndef PRODUCT
if (PrintEliminateLocks) {
@@ -1562,6 +1604,15 @@
_igvn.subsume_node(ctrlproj, fallthroughproj);
_igvn.hash_delete(memproj);
_igvn.subsume_node(memproj, memproj_fallthrough);
+
+ // Delete FastLock node also if this Lock node is unique user
+ // (a loop peeling may clone a Lock node).
+ Node* flock = alock->as_Lock()->fastlock_node();
+ if (flock->outcnt() == 1) {
+ assert(flock->unique_out() == alock, "sanity");
+ _igvn.hash_delete(flock);
+ _igvn.subsume_node(flock, top());
+ }
}
// Seach for MemBarRelease node and delete it also.
@@ -1887,7 +1938,7 @@
bool PhaseMacroExpand::expand_macro_nodes() {
if (C->macro_count() == 0)
return false;
- // attempt to eliminate allocations
+ // First, attempt to eliminate locks
bool progress = true;
while (progress) {
progress = false;
@@ -1895,6 +1946,26 @@
Node * n = C->macro_node(i-1);
bool success = false;
debug_only(int old_macro_count = C->macro_count(););
+ if (n->is_AbstractLock()) {
+ success = eliminate_locking_node(n->as_AbstractLock());
+ } else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) {
+ _igvn.add_users_to_worklist(n);
+ _igvn.hash_delete(n);
+ _igvn.subsume_node(n, n->in(1));
+ success = true;
+ }
+ assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
+ progress = progress || success;
+ }
+ }
+ // Next, attempt to eliminate allocations
+ progress = true;
+ while (progress) {
+ progress = false;
+ for (int i = C->macro_count(); i > 0; i--) {
+ Node * n = C->macro_node(i-1);
+ bool success = false;
+ debug_only(int old_macro_count = C->macro_count(););
switch (n->class_id()) {
case Node::Class_Allocate:
case Node::Class_AllocateArray:
@@ -1902,17 +1973,10 @@
break;
case Node::Class_Lock:
case Node::Class_Unlock:
- success = eliminate_locking_node(n->as_AbstractLock());
+ assert(!n->as_AbstractLock()->is_eliminated(), "sanity");
break;
default:
- if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) {
- _igvn.add_users_to_worklist(n);
- _igvn.hash_delete(n);
- _igvn.subsume_node(n, n->in(1));
- success = true;
- } else {
- assert(false, "unknown node type in macro list");
- }
+ assert(false, "unknown node type in macro list");
}
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
progress = progress || success;
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/opto/output.cpp
--- a/hotspot/src/share/vm/opto/output.cpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/opto/output.cpp Fri Dec 05 15:06:37 2008 -0500
@@ -849,10 +849,8 @@
// Loop over monitors and insert into array
for(idx = 0; idx < num_mon; idx++) {
// Grab the node that defines this monitor
- Node* box_node;
- Node* obj_node;
- box_node = sfn->monitor_box(jvms, idx);
- obj_node = sfn->monitor_obj(jvms, idx);
+ Node* box_node = sfn->monitor_box(jvms, idx);
+ Node* obj_node = sfn->monitor_obj(jvms, idx);
// Create ScopeValue for object
ScopeValue *scval = NULL;
@@ -890,6 +888,7 @@
OptoReg::Name box_reg = BoxLockNode::stack_slot(box_node);
Location basic_lock = Location::new_stk_loc(Location::normal,_regalloc->reg2offset(box_reg));
+ while( !box_node->is_BoxLock() ) box_node = box_node->in(1);
monarray->append(new MonitorValue(scval, basic_lock, box_node->as_BoxLock()->is_eliminated()));
}
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/runtime/globals.hpp
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp Fri Dec 05 15:06:37 2008 -0500
@@ -342,6 +342,9 @@
product(bool, UseNUMA, false, \
"Use NUMA if available") \
\
+ product(bool, ForceNUMA, false, \
+ "Force NUMA optimizations on single-node/UMA systems") \
+ \
product(intx, NUMAChunkResizeWeight, 20, \
"Percentage (0-100) used to weight the current sample when " \
"computing exponentially decaying average for " \
@@ -1474,7 +1477,7 @@
"CMSPrecleanNumerator:CMSPrecleanDenominator yields convergence" \
" ratio") \
\
- product(bool, CMSPrecleanRefLists1, false, \
+ product(bool, CMSPrecleanRefLists1, true, \
"Preclean ref lists during (initial) preclean phase") \
\
product(bool, CMSPrecleanRefLists2, false, \
diff -r c6ee85e55858 -r a85945264abc hotspot/src/share/vm/utilities/macros.hpp
--- a/hotspot/src/share/vm/utilities/macros.hpp Thu Dec 04 17:48:02 2008 -0800
+++ b/hotspot/src/share/vm/utilities/macros.hpp Fri Dec 05 15:06:37 2008 -0500
@@ -65,8 +65,10 @@
// COMPILER2 variant
#ifdef COMPILER2
#define COMPILER2_PRESENT(code) code
+#define NOT_COMPILER2(code)
#else // COMPILER2
#define COMPILER2_PRESENT(code)
+#define NOT_COMPILER2(code) code
#endif // COMPILER2
diff -r c6ee85e55858 -r a85945264abc hotspot/test/compiler/6756768/Test6756768.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6756768/Test6756768.java Fri Dec 05 15:06:37 2008 -0500
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6756768
+ * @summary C1 generates invalid code
+ *
+ * @run main/othervm -Xcomp Test6756768
+ */
+
+class Test6756768a
+{
+ static boolean var_1 = true;
+}
+
+final class Test6756768b
+{
+ static boolean var_24 = false;
+ static int var_25 = 0;
+
+ static boolean var_temp1 = Test6756768a.var_1 = false;
+}
+
+public final class Test6756768 extends Test6756768a
+{
+ final static int var = var_1 ^ (Test6756768b.var_24 ? var_1 : var_1) ? Test6756768b.var_25 : 1;
+
+ static public void main(String[] args) {
+ if (var != 0) {
+ throw new InternalError("var = " + var);
+ }
+ }
+
+}
diff -r c6ee85e55858 -r a85945264abc hotspot/test/compiler/6756768/Test6756768_2.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6756768/Test6756768_2.java Fri Dec 05 15:06:37 2008 -0500
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6756768
+ * @summary C1 generates invalid code
+ *
+ * @run main/othervm -Xcomp Test6756768_2
+ */
+
+class Test6756768_2a {
+ static int var = ++Test6756768_2.var;
+}
+
+public class Test6756768_2 {
+ static int var = 1;
+
+ static Object d2 = null;
+
+ static void test_static_field() {
+ int v = var;
+ int v2 = Test6756768_2a.var;
+ int v3 = var;
+ var = v3;
+ }
+
+ public static void main(String[] args) {
+ var = 1;
+ test_static_field();
+ if (var != 2) {
+ throw new InternalError();
+ }
+ }
+}
diff -r c6ee85e55858 -r a85945264abc hotspot/test/compiler/6775880/Test.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6775880/Test.java Fri Dec 05 15:06:37 2008 -0500
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+/*
+ * @test
+ * @bug 6775880
+ * @summary EA +DeoptimizeALot: assert(mon_info->owner()->is_locked(),"object must be locked now")
+ * @compile -source 1.4 -target 1.4 Test.java
+ * @run main/othervm -server -Xbatch -XX:+DoEscapeAnalysis -XX:+DeoptimizeALot -XX:CompileCommand=exclude,java.lang.AbstractStringBuilder::append Test
+ */
+
+public class Test {
+
+ int cnt;
+ int b[];
+ String s;
+
+ String test() {
+ String res="";
+ for (int i=0; i < cnt; i++) {
+ if (i != 0) {
+ res = res +".";
+ }
+ res = res + b[i];
+ }
+ return res;
+ }
+
+ public static void main(String[] args) {
+ Test t = new Test();
+ t.cnt = 3;
+ t.b = new int[3];
+ t.b[0] = 0;
+ t.b[1] = 1;
+ t.b[2] = 2;
+ int j=0;
+ t.s = "";
+ for (int i=0; i<10001; i++) {
+ t.s = "c";
+ t.s = t.test();
+ }
+ System.out.println("After s=" + t.s);
+ }
+}
+
+
diff -r c6ee85e55858 -r a85945264abc jaxp/.hgtags
--- a/jaxp/.hgtags Thu Dec 04 17:48:02 2008 -0800
+++ b/jaxp/.hgtags Fri Dec 05 15:06:37 2008 -0500
@@ -14,3 +14,4 @@
af49591bc486d82aa04b832257de0d18adc9af52 jdk7-b37
e9f750f0a3a00413a7b77028b2ecdabb7129ae32 jdk7-b38
831b80be6cea8e7d7da197ccdac5fd4c701a5033 jdk7-b39
+54946f466e2c047c44c903f1bec400b685c2508e jdk7-b40
diff -r c6ee85e55858 -r a85945264abc jaxws/.hgtags
--- a/jaxws/.hgtags Thu Dec 04 17:48:02 2008 -0800
+++ b/jaxws/.hgtags Fri Dec 05 15:06:37 2008 -0500
@@ -14,3 +14,4 @@
a2a6f9edf761934faf59ea60d7fe7178371302cd jdk7-b37
9ce439969184c753a9ba3caf8ed277b05230f2e5 jdk7-b38
077bc9b1b035a409a76bd5366f73ed9dd9846934 jdk7-b39
+70a6ac6dd737fe45c2fadb57646195b2b4fe269d jdk7-b40
diff -r c6ee85e55858 -r a85945264abc jdk/.hgtags
--- a/jdk/.hgtags Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/.hgtags Fri Dec 05 15:06:37 2008 -0500
@@ -14,3 +14,4 @@
14f50aee4989b75934d385c56a83da0c23d2f68b jdk7-b37
cc5f810b5af8a3a83b0df5a29d9e24d7a0ff8086 jdk7-b38
4e51997582effa006dde5c6d8b8820b2045b9c7f jdk7-b39
+2201dad60231a3c3e0346e3a0250d69ca3b71fd4 jdk7-b40
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/com/sun/jmx/defaults/ServiceName.java
--- a/jdk/src/share/classes/com/sun/jmx/defaults/ServiceName.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/defaults/ServiceName.java Fri Dec 05 15:06:37 2008 -0500
@@ -69,9 +69,9 @@
/**
* The version of the JMX specification implemented by this product.
*
- * The value is 1.4.
+ * The value is 2.0.
*/
- public static final String JMX_SPEC_VERSION = "1.4";
+ public static final String JMX_SPEC_VERSION = "2.0";
/**
* The vendor of the JMX specification implemented by this product.
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/com/sun/jmx/event/EventParams.java
--- a/jdk/src/share/classes/com/sun/jmx/event/EventParams.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/event/EventParams.java Fri Dec 05 15:06:37 2008 -0500
@@ -41,7 +41,7 @@
@SuppressWarnings("cast") // cast for jdk 1.5
public static long getLeaseTimeout() {
- long timeout = EventClient.DEFAULT_LEASE_TIMEOUT;
+ long timeout = EventClient.DEFAULT_REQUESTED_LEASE_TIME;
try {
final GetPropertyAction act =
new GetPropertyAction(DEFAULT_LEASE_TIMEOUT);
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/com/sun/jmx/event/LeaseManager.java
--- a/jdk/src/share/classes/com/sun/jmx/event/LeaseManager.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/event/LeaseManager.java Fri Dec 05 15:06:37 2008 -0500
@@ -29,6 +29,7 @@
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
@@ -143,9 +144,10 @@
private final Runnable callback;
private ScheduledFuture> scheduled; // If null, the lease has expired.
+ private static final ThreadFactory threadFactory =
+ new DaemonThreadFactory("JMX LeaseManager %d");
private final ScheduledExecutorService executor
- = Executors.newScheduledThreadPool(1,
- new DaemonThreadFactory("JMX LeaseManager %d"));
+ = Executors.newScheduledThreadPool(1, threadFactory);
private static final ClassLogger logger =
new ClassLogger("javax.management.event", "LeaseManager");
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java
--- a/jdk/src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java Fri Dec 05 15:06:37 2008 -0500
@@ -55,9 +55,19 @@
import javax.management.namespace.MBeanServerSupport;
import javax.management.remote.IdentityMBeanServerForwarder;
+/**
+ *
An {@link MBeanServerForwarder} that simulates the existence of a
+ * given MBean. Requests for that MBean, call it X, are intercepted by the
+ * forwarder, and requests for any other MBean are forwarded to the next
+ * forwarder in the chain. Requests such as queryNames which can span both the
+ * X and other MBeans are handled by merging the results for X with the results
+ * from the next forwarder, unless the "visible" parameter is false, in which
+ * case X is invisible to such requests.
+ */
public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
private final ObjectName mbeanName;
+ private final boolean visible;
private DynamicMBean mbean;
private MBeanServer mbeanMBS = new MBeanServerSupport() {
@@ -85,10 +95,20 @@
return null;
}
+ // This will only be called if mbeanName has an empty domain.
+ // In that case a getAttribute (e.g.) of that name will have the
+ // domain replaced by MBeanServerSupport with the default domain,
+ // so we must be sure that the default domain is empty too.
+ @Override
+ public String getDefaultDomain() {
+ return mbeanName.getDomain();
+ }
};
- public SingleMBeanForwarder(ObjectName mbeanName, DynamicMBean mbean) {
+ public SingleMBeanForwarder(
+ ObjectName mbeanName, DynamicMBean mbean, boolean visible) {
this.mbeanName = mbeanName;
+ this.visible = visible;
setSingleMBean(mbean);
}
@@ -213,8 +233,10 @@
@Override
public String[] getDomains() {
- TreeSet domainSet =
- new TreeSet(Arrays.asList(super.getDomains()));
+ String[] domains = super.getDomains();
+ if (!visible)
+ return domains;
+ TreeSet domainSet = new TreeSet(Arrays.asList(domains));
domainSet.add(mbeanName.getDomain());
return domainSet.toArray(new String[domainSet.size()]);
}
@@ -222,7 +244,7 @@
@Override
public Integer getMBeanCount() {
Integer count = super.getMBeanCount();
- if (!super.isRegistered(mbeanName))
+ if (visible && !super.isRegistered(mbeanName))
count++;
return count;
}
@@ -284,7 +306,7 @@
*/
private boolean applies(ObjectName pattern) {
// we know pattern is not null.
- if (!pattern.apply(mbeanName))
+ if (!visible || !pattern.apply(mbeanName))
return false;
final String dompat = pattern.getDomain();
@@ -306,10 +328,12 @@
@Override
public Set queryMBeans(ObjectName name, QueryExp query) {
Set names = super.queryMBeans(name, query);
- if (name == null || applies(name) ) {
- // Don't assume mbs.queryNames returns a writable set.
- names = Util.cloneSet(names);
- names.addAll(mbeanMBS.queryMBeans(name, query));
+ if (visible) {
+ if (name == null || applies(name) ) {
+ // Don't assume mbs.queryNames returns a writable set.
+ names = Util.cloneSet(names);
+ names.addAll(mbeanMBS.queryMBeans(name, query));
+ }
}
return names;
}
@@ -317,10 +341,12 @@
@Override
public Set queryNames(ObjectName name, QueryExp query) {
Set names = super.queryNames(name, query);
- if (name == null || applies(name)) {
- // Don't assume mbs.queryNames returns a writable set.
- names = Util.cloneSet(names);
- names.addAll(mbeanMBS.queryNames(name, query));
+ if (visible) {
+ if (name == null || applies(name)) {
+ // Don't assume mbs.queryNames returns a writable set.
+ names = Util.cloneSet(names);
+ names.addAll(mbeanMBS.queryNames(name, query));
+ }
}
return names;
}
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java Fri Dec 05 15:06:37 2008 -0500
@@ -122,7 +122,7 @@
* {@link javax.management.MBeanServerFactory#newMBeanServer(java.lang.String)}
* instead.
*
- * By default, {@link MBeanServerInterceptor} are disabled. Use
+ * By default, interceptors are disabled. Use
* {@link #JmxMBeanServer(java.lang.String,javax.management.MBeanServer,javax.management.MBeanServerDelegate,boolean)} to enable them.
*
* @param domain The default domain name used by this MBeanServer.
@@ -239,7 +239,7 @@
this.mBeanServerDelegateObject = delegate;
this.outerShell = outer;
- final Repository repository = new Repository(domain,fairLock);
+ final Repository repository = new Repository(domain);
this.mbsInterceptor =
new NamespaceDispatchInterceptor(outer, delegate, instantiator,
repository);
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/com/sun/jmx/namespace/JMXNamespaceUtils.java
--- a/jdk/src/share/classes/com/sun/jmx/namespace/JMXNamespaceUtils.java Thu Dec 04 17:48:02 2008 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,354 +0,0 @@
-/*
- * Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package com.sun.jmx.namespace;
-
-import com.sun.jmx.defaults.JmxProperties;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
-import java.util.WeakHashMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.management.ListenerNotFoundException;
-import javax.management.MBeanServerConnection;
-import javax.management.NotificationFilter;
-import javax.management.NotificationListener;
-import javax.management.event.EventClient;
-import javax.management.event.EventClientDelegateMBean;
-import javax.management.namespace.JMXNamespace;
-import javax.management.namespace.JMXNamespaces;
-import javax.management.remote.JMXAddressable;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXServiceURL;
-import javax.security.auth.Subject;
-
-/**
- * A collection of methods that provide JMXConnector wrappers for
- * JMXRemoteNamepaces underlying connectors.
- *
- * This API is a Sun internal API and is subject to changes without notice.
- *
- * @since 1.7
- */
-public final class JMXNamespaceUtils {
-
- /**
- * A logger for this class.
- **/
- private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
-
-
- private static Map newWeakHashMap() {
- return new WeakHashMap();
- }
-
- /** There are no instances of this class */
- private JMXNamespaceUtils() {
- }
-
- // returns un unmodifiable view of a map.
- public static Map unmodifiableMap(Map aMap) {
- if (aMap == null || aMap.isEmpty())
- return Collections.emptyMap();
- return Collections.unmodifiableMap(aMap);
- }
-
-
- /**
- * A base class that helps writing JMXConnectors that return
- * MBeanServerConnection wrappers.
- * This base class wraps an inner JMXConnector (the source), and preserve
- * its caching policy. If a connection is cached in the source, its wrapper
- * will be cached in this connector too.
- * Author's note: rewriting this with java.lang.reflect.Proxy could be
- * envisaged. It would avoid the combinatory sub-classing introduced by
- * JMXAddressable.
- *
- * Note: all the standard JMXConnector implementations are serializable.
- * This implementation here is not. Should it be?
- * I believe it must not be serializable unless it becomes
- * part of a public API (either standard or officially exposed
- * and supported in a documented com.sun package)
- **/
- static class JMXCachingConnector
- implements JMXConnector {
-
- // private static final long serialVersionUID = -2279076110599707875L;
-
- final JMXConnector source;
-
- // if this object is made serializable, then the variable below
- // needs to become volatile transient and be lazyly-created...
- private final
- Map connectionMap;
-
-
- public JMXCachingConnector(JMXConnector source) {
- this.source = checkNonNull(source, "source");
- connectionMap = newWeakHashMap();
- }
-
- private MBeanServerConnection
- getCached(MBeanServerConnection inner) {
- return connectionMap.get(inner);
- }
-
- private MBeanServerConnection putCached(final MBeanServerConnection inner,
- final MBeanServerConnection wrapper) {
- if (inner == wrapper) return wrapper;
- synchronized (this) {
- final MBeanServerConnection concurrent =
- connectionMap.get(inner);
- if (concurrent != null) return concurrent;
- connectionMap.put(inner,wrapper);
- }
- return wrapper;
- }
-
- public void addConnectionNotificationListener(NotificationListener
- listener, NotificationFilter filter, Object handback) {
- source.addConnectionNotificationListener(listener,filter,handback);
- }
-
- public void close() throws IOException {
- source.close();
- }
-
- public void connect() throws IOException {
- source.connect();
- }
-
- public void connect(Map env) throws IOException {
- source.connect(env);
- }
-
- public String getConnectionId() throws IOException {
- return source.getConnectionId();
- }
-
- /**
- * Preserve caching policy of the underlying connector.
- **/
- public MBeanServerConnection
- getMBeanServerConnection() throws IOException {
- final MBeanServerConnection inner =
- source.getMBeanServerConnection();
- final MBeanServerConnection cached = getCached(inner);
- if (cached != null) return cached;
- final MBeanServerConnection wrapper = wrap(inner);
- return putCached(inner,wrapper);
- }
-
- public MBeanServerConnection
- getMBeanServerConnection(Subject delegationSubject)
- throws IOException {
- final MBeanServerConnection wrapped =
- source.getMBeanServerConnection(delegationSubject);
- synchronized (this) {
- final MBeanServerConnection cached = getCached(wrapped);
- if (cached != null) return cached;
- final MBeanServerConnection wrapper =
- wrapWithSubject(wrapped,delegationSubject);
- return putCached(wrapped,wrapper);
- }
- }
-
- public void removeConnectionNotificationListener(
- NotificationListener listener)
- throws ListenerNotFoundException {
- source.removeConnectionNotificationListener(listener);
- }
-
- public void removeConnectionNotificationListener(
- NotificationListener l, NotificationFilter f,
- Object handback) throws ListenerNotFoundException {
- source.removeConnectionNotificationListener(l,f,handback);
- }
-
- /**
- * This is the method that subclass will redefine. This method
- * is called by {@code this.getMBeanServerConnection()}.
- * {@code inner} is the connection returned by
- * {@code source.getMBeanServerConnection()}.
- **/
- protected MBeanServerConnection wrap(MBeanServerConnection inner)
- throws IOException {
- return inner;
- }
-
- /**
- * Subclass may also want to redefine this method.
- * By default it calls wrap(inner). This method
- * is called by {@code this.getMBeanServerConnection(Subject)}.
- * {@code inner} is the connection returned by
- * {@code source.getMBeanServerConnection(Subject)}.
- **/
- protected MBeanServerConnection wrapWithSubject(
- MBeanServerConnection inner, Subject delegationSubject)
- throws IOException {
- return wrap(inner);
- }
-
- @Override
- public String toString() {
- if (source instanceof JMXAddressable) {
- final JMXServiceURL address =
- ((JMXAddressable)source).getAddress();
- if (address != null)
- return address.toString();
- }
- return source.toString();
- }
-
- }
-
-
- /**
- * The name space connector can do 'cd'
- **/
- static class JMXNamespaceConnector extends JMXCachingConnector {
-
- // private static final long serialVersionUID = -4813611540843020867L;
-
- private final String toDir;
- private final boolean closeable;
-
- public JMXNamespaceConnector(JMXConnector source, String toDir,
- boolean closeable) {
- super(source);
- this.toDir = toDir;
- this.closeable = closeable;
- }
-
- @Override
- public void close() throws IOException {
- if (!closeable)
- throw new UnsupportedOperationException("close");
- else super.close();
- }
-
- @Override
- protected MBeanServerConnection wrap(MBeanServerConnection wrapped)
- throws IOException {
- if (LOG.isLoggable(Level.FINER))
- LOG.finer("Creating name space proxy connection for source: "+
- "namespace="+toDir);
- return JMXNamespaces.narrowToNamespace(wrapped,toDir);
- }
-
- @Override
- public String toString() {
- return "JMXNamespaces.narrowToNamespace("+
- super.toString()+
- ", \""+toDir+"\")";
- }
-
- }
-
- static class JMXEventConnector extends JMXCachingConnector {
-
- // private static final long serialVersionUID = 4742659236340242785L;
-
- JMXEventConnector(JMXConnector wrapped) {
- super(wrapped);
- }
-
- @Override
- protected MBeanServerConnection wrap(MBeanServerConnection inner)
- throws IOException {
- return EventClient.getEventClientConnection(inner);
- }
-
-
- @Override
- public String toString() {
- return "EventClient.withEventClient("+super.toString()+")";
- }
- }
-
- static class JMXAddressableEventConnector extends JMXEventConnector
- implements JMXAddressable {
-
- // private static final long serialVersionUID = -9128520234812124712L;
-
- JMXAddressableEventConnector(JMXConnector wrapped) {
- super(wrapped);
- }
-
- public JMXServiceURL getAddress() {
- return ((JMXAddressable)source).getAddress();
- }
- }
-
- /**
- * Creates a connector whose MBeamServerConnection will point to the
- * given sub name space inside the source connector.
- * @see JMXNamespace
- **/
- public static JMXConnector cd(final JMXConnector source,
- final String toNamespace,
- final boolean closeable)
- throws IOException {
-
- checkNonNull(source, "JMXConnector");
-
- if (toNamespace == null || toNamespace.equals(""))
- return source;
-
- return new JMXNamespaceConnector(source,toNamespace,closeable);
- }
-
-
- /**
- * Returns a JMX Connector that will use an {@link EventClient}
- * to subscribe for notifications. If the server doesn't have
- * an {@link EventClientDelegateMBean}, then the connector will
- * use the legacy notification mechanism instead.
- *
- * @param source The underlying JMX Connector wrapped by the returned
- * connector.
- * @return A JMX Connector that will uses an {@link EventClient}, if
- * available.
- * @see EventClient#getEventClientConnection(MBeanServerConnection)
- */
- public static JMXConnector withEventClient(final JMXConnector source) {
- checkNonNull(source, "JMXConnector");
- if (source instanceof JMXAddressable)
- return new JMXAddressableEventConnector(source);
- else
- return new JMXEventConnector(source);
- }
-
- public static T checkNonNull(T parameter, String name) {
- if (parameter == null)
- throw new IllegalArgumentException(name+" must not be null");
- return parameter;
- }
-
-
-}
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java
--- a/jdk/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java Fri Dec 05 15:06:37 2008 -0500
@@ -49,11 +49,6 @@
final int tlen;
final boolean identity;
-
- public ObjectNameRouter(String targetDirName) {
- this(targetDirName,null);
- }
-
/** Creates a new instance of ObjectNameRouter */
public ObjectNameRouter(final String remove, final String add) {
this.targetPrefix = (remove==null?"":remove);
@@ -186,6 +181,4 @@
b.append(NAMESPACE_SEPARATOR);
return b.toString();
}
-
-
}
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java
--- a/jdk/src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java Fri Dec 05 15:06:37 2008 -0500
@@ -31,7 +31,6 @@
import java.util.logging.Logger;
import javax.management.MBeanServerConnection;
-import javax.management.namespace.JMXNamespaces;
/**
@@ -61,18 +60,10 @@
* Creates a new instance of RoutingConnectionProxy
*/
public RoutingConnectionProxy(MBeanServerConnection source,
- String sourceDir) {
- this(source,sourceDir,"",false);
- }
-
- /**
- * Creates a new instance of RoutingConnectionProxy
- */
- public RoutingConnectionProxy(MBeanServerConnection source,
String sourceDir,
String targetDir,
- boolean forwardsContext) {
- super(source,sourceDir,targetDir,forwardsContext);
+ boolean probe) {
+ super(source, sourceDir, targetDir, probe);
if (LOG.isLoggable(Level.FINER))
LOG.finer("RoutingConnectionProxy for " + getSourceNamespace() +
@@ -85,15 +76,13 @@
final String sourceNs = getSourceNamespace();
String wrapped = String.valueOf(source());
if ("".equals(targetNs)) {
- if (forwardsContext)
- wrapped = "ClientContext.withDynamicContext("+wrapped+")";
return "JMXNamespaces.narrowToNamespace("+
wrapped+", \""+
sourceNs+"\")";
}
return this.getClass().getSimpleName()+"("+wrapped+", \""+
sourceNs+"\", \""+
- targetNs+"\", "+forwardsContext+")";
+ targetNs+"\")";
}
static final RoutingProxyFactory
@@ -102,22 +91,16 @@
() {
public RoutingConnectionProxy newInstance(MBeanServerConnection source,
- String sourcePath, String targetPath,
- boolean forwardsContext) {
+ String sourcePath, String targetPath, boolean probe) {
return new RoutingConnectionProxy(source,sourcePath,
- targetPath,forwardsContext);
- }
-
- public RoutingConnectionProxy newInstance(
- MBeanServerConnection source, String sourcePath) {
- return new RoutingConnectionProxy(source,sourcePath);
+ targetPath, probe);
}
};
- public static MBeanServerConnection cd(MBeanServerConnection source,
- String sourcePath) {
+ public static MBeanServerConnection cd(
+ MBeanServerConnection source, String sourcePath, boolean probe) {
return RoutingProxy.cd(RoutingConnectionProxy.class, FACTORY,
- source, sourcePath);
+ source, sourcePath, probe);
}
}
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java
--- a/jdk/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java Fri Dec 05 15:06:37 2008 -0500
@@ -30,6 +30,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanRegistrationException;
@@ -90,17 +91,9 @@
// targetNs= // context must be removed from object name
// sourceNs="" // nothing to add...
//
-// RoutingProxies can also be used on the client side to implement
-// "withClientContext" operations. In that case, the boolean parameter
-// 'forwards context' is set to true, targetNs is "", and sourceNS may
-// also be "". When forwardsContext is true, the RoutingProxy dynamically
-// creates an ObjectNameRouter for each operation - in order to dynamically add
-// the context attached to the thread to the routing ObjectName. This is
-// performed in the getObjectNameRouter() method.
-//
// Finally, in order to avoid too many layers of wrapping,
// RoutingConnectionProxy and RoutingServerProxy can be created through a
-// factory method that can concatenate namespace pathes in order to
+// factory method that can concatenate namespace paths in order to
// return a single RoutingProxy - rather than wrapping a RoutingProxy inside
// another RoutingProxy. See RoutingConnectionProxy.cd and
// RoutingServerProxy.cd
@@ -146,25 +139,27 @@
private final T source;
// The name space we're narrowing to (usually some name space in
- // the source MBeanServerConnection
+ // the source MBeanServerConnection), e.g. "a" for the namespace
+ // "a//". This is empty in the case of ClientContext described above.
private final String sourceNs;
- // The name space we pretend to be mounted in (usually "")
+ // The name space we pretend to be mounted in. This is empty except
+ // in the case of ClientContext described above (where it will be
+ // something like "jmx.context//foo=bar".
private final String targetNs;
// The name of the JMXNamespace that handles the source name space
private final ObjectName handlerName;
private final ObjectNameRouter router;
- final boolean forwardsContext;
private volatile String defaultDomain = null;
/**
* Creates a new instance of RoutingProxy
*/
protected RoutingProxy(T source,
- String sourceNs,
- String targetNs,
- boolean forwardsContext) {
+ String sourceNs,
+ String targetNs,
+ boolean probe) {
if (source == null) throw new IllegalArgumentException("null");
this.sourceNs = JMXNamespaces.normalizeNamespaceName(sourceNs);
@@ -177,13 +172,17 @@
// System.err.println("sourceNs: "+sourceNs);
this.handlerName =
JMXNamespaces.getNamespaceObjectName(this.sourceNs);
- try {
- // System.err.println("handlerName: "+handlerName);
- if (!source.isRegistered(handlerName))
- throw new IllegalArgumentException(sourceNs +
- ": no such name space");
- } catch (IOException x) {
- throw new IllegalArgumentException("source stale: "+x,x);
+ if (probe) {
+ try {
+ if (!source.isRegistered(handlerName)) {
+ InstanceNotFoundException infe =
+ new InstanceNotFoundException(handlerName);
+ throw new IllegalArgumentException(sourceNs +
+ ": no such name space", infe);
+ }
+ } catch (IOException x) {
+ throw new IllegalArgumentException("source stale: "+x,x);
+ }
}
}
this.source = source;
@@ -191,7 +190,6 @@
JMXNamespaces.normalizeNamespaceName(targetNs));
this.router =
new ObjectNameRouter(this.targetNs,this.sourceNs);
- this.forwardsContext = forwardsContext;
if (LOG.isLoggable(Level.FINER))
LOG.finer("RoutingProxy for " + this.sourceNs + " created");
@@ -200,14 +198,6 @@
@Override
public T source() { return source; }
- ObjectNameRouter getObjectNameRouter() {
-// TODO: uncomment this when contexts are added
-// if (forwardsContext)
-// return ObjectNameRouter.wrapWithContext(router);
-// else
- return router;
- }
-
@Override
public ObjectName toSource(ObjectName targetName)
throws MalformedObjectNameException {
@@ -222,8 +212,7 @@
if (defaultDomain != null)
targetName = targetName.withDomain(defaultDomain);
}
- final ObjectNameRouter r = getObjectNameRouter();
- return r.toSourceContext(targetName,true);
+ return router.toSourceContext(targetName,true);
}
@Override
@@ -243,8 +232,7 @@
public ObjectName toTarget(ObjectName sourceName)
throws MalformedObjectNameException {
if (sourceName == null) return null;
- final ObjectNameRouter r = getObjectNameRouter();
- return r.toTargetContext(sourceName,false);
+ return router.toTargetContext(sourceName,false);
}
private Object getAttributeFromHandler(String attributeName)
@@ -357,11 +345,8 @@
// instance.
static interface RoutingProxyFactory> {
- R newInstance(T source,
- String sourcePath, String targetPath,
- boolean forwardsContext);
- R newInstance(T source,
- String sourcePath);
+ public R newInstance(
+ T source, String sourcePath, String targetPath, boolean probe);
}
// Performs a narrowDownToNamespace operation.
@@ -377,7 +362,7 @@
static >
R cd(Class routingProxyClass,
RoutingProxyFactory factory,
- T source, String sourcePath) {
+ T source, String sourcePath, boolean probe) {
if (source == null) throw new IllegalArgumentException("null");
if (source.getClass().equals(routingProxyClass)) {
// cast is OK here, but findbugs complains unless we use class.cast
@@ -400,14 +385,13 @@
final String path =
JMXNamespaces.concat(other.getSourceNamespace(),
sourcePath);
- return factory.newInstance(other.source(),path,"",
- other.forwardsContext);
+ return factory.newInstance(other.source(), path, "", probe);
}
// Note: we could do possibly something here - but it would involve
// removing part of targetDir, and possibly adding
// something to sourcePath.
// Too complex to bother! => simply default to stacking...
}
- return factory.newInstance(source,sourcePath);
+ return factory.newInstance(source, sourcePath, "", probe);
}
}
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java
--- a/jdk/src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java Fri Dec 05 15:06:37 2008 -0500
@@ -54,7 +54,6 @@
import javax.management.QueryExp;
import javax.management.ReflectionException;
import javax.management.loading.ClassLoaderRepository;
-import javax.management.namespace.JMXNamespaces;
/**
* A RoutingServerProxy is an MBeanServer proxy that proxies a
@@ -76,19 +75,11 @@
extends RoutingProxy
implements MBeanServer {
- /**
- * Creates a new instance of RoutingServerProxy
- */
- public RoutingServerProxy(MBeanServer source,
- String sourceNs) {
- this(source,sourceNs,"",false);
- }
-
public RoutingServerProxy(MBeanServer source,
String sourceNs,
String targetNs,
- boolean forwardsContext) {
- super(source,sourceNs,targetNs,forwardsContext);
+ boolean probe) {
+ super(source, sourceNs, targetNs, probe);
}
/**
@@ -571,20 +562,15 @@
FACTORY = new RoutingProxyFactory() {
public RoutingServerProxy newInstance(MBeanServer source,
- String sourcePath, String targetPath,
- boolean forwardsContext) {
- return new RoutingServerProxy(source,sourcePath,
- targetPath,forwardsContext);
- }
-
- public RoutingServerProxy newInstance(
- MBeanServer source, String sourcePath) {
- return new RoutingServerProxy(source,sourcePath);
+ String sourcePath, String targetPath, boolean probe) {
+ return new RoutingServerProxy(
+ source, sourcePath, targetPath, probe);
}
};
- public static MBeanServer cd(MBeanServer source, String sourcePath) {
+ public static MBeanServer cd(
+ MBeanServer source, String sourcePath, boolean probe) {
return RoutingProxy.cd(RoutingServerProxy.class, FACTORY,
- source, sourcePath);
+ source, sourcePath, probe);
}
}
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java
--- a/jdk/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java Fri Dec 05 15:06:37 2008 -0500
@@ -430,13 +430,11 @@
* The {@code EventClient} is created lazily, when it is needed
* for the first time. If null, a default factory will be used
* (see {@link #createEventClient}).
- * @return the
+ * @return the MBeanServerConnection.
**/
public static MBeanServerConnection getEventConnectionFor(
MBeanServerConnection connection,
Callable eventClientFactory) {
- // if c already uses an EventClient no need to create a new one.
- //
if (connection instanceof EventClientFactory
&& eventClientFactory != null)
throw new IllegalArgumentException("connection already uses EventClient");
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java
--- a/jdk/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java Fri Dec 05 15:06:37 2008 -0500
@@ -497,6 +497,10 @@
delegate.setFixedLengthStreamingMode(contentLength);
}
+ public void setFixedLengthStreamingMode(long contentLength) {
+ delegate.setFixedLengthStreamingMode(contentLength);
+ }
+
public void setChunkedStreamingMode (int chunklen) {
delegate.setChunkedStreamingMode(chunklen);
}
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java
--- a/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java Fri Dec 05 15:06:37 2008 -0500
@@ -86,6 +86,8 @@
* the principal name from the configuration is used. In the
* case where the principal property is not set and the principal
* entry also does not exist, the user is prompted for the name.
+ * When this property of entry is set, and useTicketCache
+ * is set to true, only TGT belonging to this principal is used.
*
*
The following is a list of configuration options supported
* for Krb5LoginModule:
@@ -101,18 +103,19 @@
* to false if you do not want this module to use the ticket cache.
* (Default is False).
* This module will
- * search for the tickect
+ * search for the ticket
* cache in the following locations:
- * For Windows 2000, it will use Local Security Authority (LSA) API
- * to get the TGT. On Solaris and Linux
+ * On Solaris and Linux
* it will look for the ticket cache in /tmp/krb5cc_uid
* where the uid is numeric user
* identifier. If the ticket cache is
- * not available in either of the above locations, or if we are on a
- * different Windows platform, it will look for the cache as
+ * not available in the above location, or if we are on a
+ * Windows platform, it will look for the cache as
* {user.home}{file.separator}krb5cc_{user.name}.
* You can override the ticket cache location by using
- * ticketCache
+ * ticketCache.
+ * For Windows, if a ticket cannot be retrieved from the file ticket cache,
+ * it will use Local Security Authority (LSA) API to get the TGT.
*
*
ticketCache:
*
Set this to the name of the ticket
@@ -129,20 +132,20 @@
*
doNotPrompt:
*
Set this to true if you do not want to be
* prompted for the password
- * if credentials can
- * not be obtained from the cache or keytab.(Default is false)
- * If set to true authentication will fail if credentials can
- * not be obtained from the cache or keytab.
+ * if credentials can not be obtained from the cache, the keytab,
+ * or through shared state.(Default is false)
+ * If set to true, credential must be obtained through cache, keytab,
+ * or shared state. Otherwise, authentication will fail.
*
*
useKeyTab:
*
Set this to true if you
* want the module to get the principal's key from the
* the keytab.(default value is False)
- * If keyatb
+ * If keytab
* is not set then
* the module will locate the keytab from the
- * Kerberos configuration file.
- * If it is not specifed in the Kerberos configuration file
+ * Kerberos configuration file.
+ * If it is not specified in the Kerberos configuration file
* then it will look for the file
* {user.home}{file.separator}krb5.keytab.
*
@@ -210,20 +213,34 @@
* exist for the username and password in the shared
* state, or if authentication fails.
*
- * clearPass if, true, this LoginModule clears the
- * username and password stored in the module's shared
- * state after both phases of authentication
- * (login and commit) have completed.
+ * clearPass if, true, this LoginModule clears the
+ * username and password stored in the module's shared
+ * state after both phases of authentication
+ * (login and commit) have completed.
*
+ *
If the principal system property or key is already provided, the value of
+ * "javax.security.auth.login.name" in the shared state is ignored.
+ *
When multiple mechanisms to retrieve a ticket or key is provided, the
+ * preference order looks like this:
+ *
+ *
ticket cache
+ *
keytab
+ *
shared state
+ *
user prompt
+ *
+ *
Note that if any step fails, it will fallback to the next step.
+ * There's only one exception, it the shared state step fails and
+ * useFirstPass=true, no user prompt is made.
*
Examples of some configuration values for Krb5LoginModule in
* JAAS config file and the results are:
*
*
doNotPrompt=true;
*
- *
This is an illegal combination since useTicketCache
- * is not set and the user can not be prompted for the password.
+ *
This is an illegal combination since none of useTicketCache,
+ * useKeyTab, useFirstPass and tryFirstPass
+ * is set and the user can not be prompted for the password.
*
- *
ticketCache = < filename >;
+ *
ticketCache = <filename>;
*
*
This is an illegal combination since useTicketCache
* is not set to true and the ticketCache is set. A configuration error
@@ -240,9 +257,9 @@
*
*
This is an illegal combination since storeKey is set to
* true but the key can not be obtained either by prompting the user or from
- * the keytab.A configuration error will occur.
+ * the keytab, or from the shared state. A configuration error will occur.
*
- *
keyTab = < filename > doNotPrompt=true ;
+ *
keyTab = <filename> doNotPrompt=true ;
*
*
This is an illegal combination since useKeyTab is not set to true and
* the keyTab is set. A configuration error will occur.
@@ -260,7 +277,7 @@
* with the principal and TGT. If the TGT is not available,
* do not prompt the user, instead fail the authentication.
*
Get the TGT from the default cache for the principal and populate the
@@ -269,9 +286,9 @@
* authentication will fail.
*
*
useTicketCache = true
- * ticketCache=< file name >useKeyTab = true
- * keyTab=< keytab filename >
- * principal = < principal name >
+ * ticketCache=<file name>useKeyTab = true
+ * keyTab=<keytab filename>
+ * principal = <principal name>
* doNotPrompt=true;
*
*
Search the cache for the principal's TGT. If it is not available
@@ -281,7 +298,7 @@
* If the key is not available or valid then authentication will fail.
*
The TGT will be obtained from the cache specified.
* The Kerberos principal name used will be the principal name in
@@ -292,8 +309,8 @@
* The Subject will be populated with the TGT.
*
The principal's key will be retrieved from the keytab and added
- * to the Subject's private credentials. If the key
- * is not available, the
- * user will be prompted for the password; the key derived from the password
- * will be added to the Subject's private credentials set. The
- * client's TGT will be retrieved from the ticket cache and added to the
+ *
+ * The client's TGT will be retrieved from the ticket cache and added to the
* Subject's private credentials. If the TGT is not available
- * in the ticket cache, it will be obtained using the authentication
+ * in the ticket cache, or the TGT's client name does not match the principal
+ * name, Java will use a secret key to obtain the TGT using the authentication
* exchange and added to the Subject's private credentials.
+ * This secret key will be first retrieved from the keytab. If the key
+ * is not available, the user will be prompted for the password. In either
+ * case, the key derived from the password will be added to the
+ * Subject's private credentials set.
*
*
isInitiator = false
*
@@ -856,11 +875,13 @@
}
private void validateConfiguration() throws LoginException {
- if (doNotPrompt && !useTicketCache && !useKeyTab)
+ if (doNotPrompt && !useTicketCache && !useKeyTab
+ && !tryFirstPass && !useFirstPass)
throw new LoginException
("Configuration Error"
+ " - either doNotPrompt should be "
- + " false or useTicketCache/useKeyTab "
+ + " false or at least one of useTicketCache, "
+ + " useKeyTab, tryFirstPass and useFirstPass"
+ " should be true");
if (ticketCacheName != null && !useTicketCache)
throw new LoginException
@@ -872,11 +893,12 @@
throw new LoginException
("Configuration Error - useKeyTab should be set to true "
+ "to use the keytab" + keyTabName);
- if (storeKey && doNotPrompt && !useKeyTab)
+ if (storeKey && doNotPrompt && !useKeyTab
+ && !tryFirstPass && !useFirstPass)
throw new LoginException
- ("Configuration Error - either doNotPrompt "
- + "should be set to false or "
- + "useKeyTab must be set to true for storeKey option");
+ ("Configuration Error - either doNotPrompt should be set to "
+ + " false or at least one of tryFirstPass, useFirstPass "
+ + "or useKeyTab must be set to true for storeKey option");
if (renewTGT && !useTicketCache)
throw new LoginException
("Configuration Error"
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/java/net/HttpURLConnection.java
--- a/jdk/src/share/classes/java/net/HttpURLConnection.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/java/net/HttpURLConnection.java Fri Dec 05 15:06:37 2008 -0500
@@ -73,11 +73,24 @@
* The fixed content-length when using fixed-length streaming mode.
* A value of -1 means fixed-length streaming mode is disabled
* for output.
+ *
+ *
NOTE: {@link #fixedContentLengthLong} is recommended instead
+ * of this field, as it allows larger content lengths to be set.
+ *
* @since 1.5
*/
protected int fixedContentLength = -1;
/**
+ * The fixed content-length when using fixed-length streaming mode.
+ * A value of {@code -1} means fixed-length streaming mode is disabled
+ * for output.
+ *
+ * @since 1.7
+ */
+ protected long fixedContentLengthLong = -1;
+
+ /**
* Returns the key for the nth header field.
* Some implementations may treat the 0th
* header field as special, i.e. as the status line returned by the HTTP
@@ -109,6 +122,9 @@
* This exception can be queried for the details of the error.
*
* This method must be called before the URLConnection is connected.
+ *
+ * NOTE: {@link #setFixedLengthStreamingMode(long)} is recommended
+ * instead of this method as it allows larger content lengths to be set.
*
* @param contentLength The number of bytes which will be written
* to the OutputStream.
@@ -135,6 +151,52 @@
fixedContentLength = contentLength;
}
+ /**
+ * This method is used to enable streaming of a HTTP request body
+ * without internal buffering, when the content length is known in
+ * advance.
+ *
+ *
An exception will be thrown if the application attempts to write
+ * more data than the indicated content-length, or if the application
+ * closes the OutputStream before writing the indicated amount.
+ *
+ *
When output streaming is enabled, authentication and redirection
+ * cannot be handled automatically. A {@linkplain HttpRetryException} will
+ * be thrown when reading the response if authentication or redirection
+ * are required. This exception can be queried for the details of the
+ * error.
+ *
+ *
This method must be called before the URLConnection is connected.
+ *
+ *
The content length set by invoking this method takes precedence
+ * over any value set by {@link #setFixedLengthStreamingMode(int)}.
+ *
+ * @param contentLength
+ * The number of bytes which will be written to the OutputStream.
+ *
+ * @throws IllegalStateException
+ * if URLConnection is already connected or if a different
+ * streaming mode is already enabled.
+ *
+ * @throws IllegalArgumentException
+ * if a content length less than zero is specified.
+ *
+ * @since 1.7
+ */
+ public void setFixedLengthStreamingMode(long contentLength) {
+ if (connected) {
+ throw new IllegalStateException("Already connected");
+ }
+ if (chunkLength != -1) {
+ throw new IllegalStateException(
+ "Chunked encoding streaming mode set");
+ }
+ if (contentLength < 0) {
+ throw new IllegalArgumentException("invalid content length");
+ }
+ fixedContentLengthLong = contentLength;
+ }
+
/* Default chunk size (including chunk header) if not specified;
* we want to keep this in sync with the one defined in
* sun.net.www.http.ChunkedOutputStream
@@ -170,7 +232,7 @@
if (connected) {
throw new IllegalStateException ("Can't set streaming mode: already connected");
}
- if (fixedContentLength != -1) {
+ if (fixedContentLength != -1 || fixedContentLengthLong != -1) {
throw new IllegalStateException ("Fixed length streaming mode set");
}
chunkLength = chunklen <=0? DEFAULT_CHUNK_SIZE : chunklen;
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/java/security/cert/CertPathValidatorException.java
--- a/jdk/src/share/classes/java/security/cert/CertPathValidatorException.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/java/security/cert/CertPathValidatorException.java Fri Dec 05 15:06:37 2008 -0500
@@ -113,7 +113,7 @@
* permitted, and indicates that the cause is nonexistent or unknown.)
*/
public CertPathValidatorException(Throwable cause) {
- this(null, cause);
+ this((cause == null ? null : cause.toString()), cause);
}
/**
diff -r c6ee85e55858 -r a85945264abc jdk/src/share/classes/javax/management/AttributeList.java
--- a/jdk/src/share/classes/javax/management/AttributeList.java Thu Dec 04 17:48:02 2008 -0800
+++ b/jdk/src/share/classes/javax/management/AttributeList.java Fri Dec 05 15:06:37 2008 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2008 Sun Microsystems, Inc. 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
@@ -27,17 +27,23 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
/**
- * Represents a list of values for attributes of an MBean. The methods
- * used for the insertion of {@link javax.management.Attribute
- * Attribute} objects in the AttributeList overrides the
- * corresponding methods in the superclass
- * ArrayList. This is needed in order to insure that the
- * objects contained in the AttributeList are only
- * Attribute objects. This avoids getting an exception
- * when retrieving elements from the AttributeList.
+ *
Represents a list of values for attributes of an MBean. See the
+ * {@link MBeanServerConnection#getAttributes getAttributes} and
+ * {@link MBeanServerConnection#setAttributes setAttributes} methods of
+ * {@link MBeanServer} and {@link MBeanServerConnection}.
+ *
+ *
For compatibility reasons, it is possible, though
+ * highly discouraged, to add objects to an {@code AttributeList} that are
+ * not instances of {@code Attribute}. However, an {@code AttributeList}
+ * can be made type-safe, which means that an attempt to add
+ * an object that is not an {@code Attribute} will produce an {@code
+ * IllegalArgumentException}. An {@code AttributeList} becomes type-safe
+ * when the method {@link #asList()} is called on it.
*
* @since 1.5
*/
@@ -58,8 +64,8 @@
*/
public class AttributeList extends ArrayList