OpenJDK / jdk / hs
changeset 8950:0b2dcb077180
Merge
author | lana |
---|---|
date | Fri, 01 Apr 2011 16:55:47 -0700 |
parents | a07c7c410e02 3db1444f8ac8 |
children | 5c8029a3c2e1 |
files | hotspot/test/compiler/6987555/Test6987555.java hotspot/test/compiler/6991596/Test6991596.java jdk/make/com/sun/xml/Makefile jdk/make/java/dyn/Makefile jdk/src/share/classes/java/dyn/CallSite.java jdk/src/share/classes/java/dyn/ClassValue.java jdk/src/share/classes/java/dyn/ConstantCallSite.java jdk/src/share/classes/java/dyn/InvokeDynamic.java jdk/src/share/classes/java/dyn/InvokeDynamicBootstrapError.java jdk/src/share/classes/java/dyn/Linkage.java jdk/src/share/classes/java/dyn/MethodHandle.java jdk/src/share/classes/java/dyn/MethodHandles.java jdk/src/share/classes/java/dyn/MethodType.java jdk/src/share/classes/java/dyn/MethodTypeForm.java jdk/src/share/classes/java/dyn/MutableCallSite.java jdk/src/share/classes/java/dyn/SwitchPoint.java jdk/src/share/classes/java/dyn/VolatileCallSite.java jdk/src/share/classes/java/dyn/WrongMethodTypeException.java jdk/src/share/classes/java/dyn/package-info.java jdk/src/share/classes/org/relaxng/datatype/Datatype.java jdk/src/share/classes/org/relaxng/datatype/DatatypeBuilder.java jdk/src/share/classes/org/relaxng/datatype/DatatypeException.java jdk/src/share/classes/org/relaxng/datatype/DatatypeLibrary.java jdk/src/share/classes/org/relaxng/datatype/DatatypeLibraryFactory.java jdk/src/share/classes/org/relaxng/datatype/DatatypeStreamingValidator.java jdk/src/share/classes/org/relaxng/datatype/ValidationContext.java jdk/src/share/classes/org/relaxng/datatype/helpers/DatatypeLibraryLoader.java jdk/src/share/classes/org/relaxng/datatype/helpers/ParameterlessDatatypeBuilder.java jdk/src/share/classes/org/relaxng/datatype/helpers/StreamingValidatorImpl.java jdk/src/share/classes/sun/dyn/Access.java jdk/src/share/classes/sun/dyn/AdapterMethodHandle.java jdk/src/share/classes/sun/dyn/BoundMethodHandle.java jdk/src/share/classes/sun/dyn/CallSiteImpl.java jdk/src/share/classes/sun/dyn/DirectMethodHandle.java jdk/src/share/classes/sun/dyn/FilterGeneric.java jdk/src/share/classes/sun/dyn/FilterOneArgument.java jdk/src/share/classes/sun/dyn/FromGeneric.java jdk/src/share/classes/sun/dyn/InvokeGeneric.java jdk/src/share/classes/sun/dyn/Invokers.java jdk/src/share/classes/sun/dyn/MemberName.java jdk/src/share/classes/sun/dyn/MethodHandleImpl.java jdk/src/share/classes/sun/dyn/MethodHandleNatives.java jdk/src/share/classes/sun/dyn/MethodTypeImpl.java jdk/src/share/classes/sun/dyn/SpreadGeneric.java jdk/src/share/classes/sun/dyn/ToGeneric.java jdk/src/share/classes/sun/dyn/WrapperInstance.java jdk/src/share/classes/sun/dyn/anon/AnonymousClassLoader.java jdk/src/share/classes/sun/dyn/anon/ConstantPoolParser.java jdk/src/share/classes/sun/dyn/anon/ConstantPoolPatch.java jdk/src/share/classes/sun/dyn/anon/ConstantPoolVisitor.java jdk/src/share/classes/sun/dyn/anon/InvalidConstantPoolFormatException.java jdk/src/share/classes/sun/dyn/empty/Empty.java jdk/src/share/classes/sun/dyn/package-info.java jdk/src/share/classes/sun/dyn/util/BytecodeDescriptor.java jdk/src/share/classes/sun/dyn/util/BytecodeName.java jdk/src/share/classes/sun/dyn/util/ValueConversions.java jdk/src/share/classes/sun/dyn/util/VerifyAccess.java jdk/src/share/classes/sun/dyn/util/VerifyType.java jdk/src/share/classes/sun/dyn/util/Wrapper.java jdk/src/share/classes/sun/dyn/util/package-info.java jdk/src/solaris/bin/ergo_sparc.c jdk/src/solaris/bin/ergo_zero.c jdk/test/java/dyn/ClassValueTest.java jdk/test/java/dyn/InvokeDynamicPrintArgs.java jdk/test/java/dyn/InvokeGenericTest.java jdk/test/java/dyn/JavaDocExamplesTest.java jdk/test/java/dyn/MethodHandlesTest.java jdk/test/java/dyn/MethodTypeTest.java jdk/test/java/dyn/indify/Indify.java |
diffstat | 616 files changed, 62544 insertions(+), 36231 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Fri Apr 01 15:43:37 2011 +0400 +++ b/.hgtags Fri Apr 01 16:55:47 2011 -0700 @@ -108,3 +108,5 @@ d8af56da89bc0fc02a6b6ad78f51157a46d665ab jdk7-b131 d61280d36755d1941fb487f554e8b7a6d0bca6a1 jdk7-b132 fd444c61e7ed3d92b2a730da7c737b02191b682f jdk7-b133 +def8e16dd237a47fc067d66d4c616d7baaec6001 jdk7-b134 +f75a1efb141210901aabe00a834e0fc32bb8b337 jdk7-b135
--- a/.hgtags-top-repo Fri Apr 01 15:43:37 2011 +0400 +++ b/.hgtags-top-repo Fri Apr 01 16:55:47 2011 -0700 @@ -108,3 +108,5 @@ 5d86d951426aaf340b1ba84ae2d5ab5da65a71e2 jdk7-b131 0f62a65fb666b337caa585015ab6ea2e60e709ca jdk7-b132 c6f380693342feadccc5fe2c5adf500e861361aa jdk7-b133 +ddc2fcb3682ffd27f44354db666128827be7e3c3 jdk7-b134 +783bd02b4ab4596059c74b10a1793d7bd2f1c157 jdk7-b135
--- a/README Fri Apr 01 15:43:37 2011 +0400 +++ b/README Fri Apr 01 16:55:47 2011 -0700 @@ -29,13 +29,14 @@ Set the environment variable ALT_BOOTDIR to the location of JDK 6. 2. Check the sanity of doing a build with your current system: - gnumake sanity + make sanity See README-builds.html if you run into problems. 3. Do a complete build of the OpenJDK: - gnumake all + make all The resulting JDK image should be found in build/*/j2sdk-image -where gnumake is GNU make 3.81 or newer, /usr/bin/make on Linux and -/usr/sfw/bin/gmake or /opt/sfw/bin/gmake on Solaris. +where make is GNU make 3.81 or newer, /usr/bin/make on Linux usually +is 3.81 or newer. +Complete details are available in README-builds.html.
--- a/README-builds.html Fri Apr 01 15:43:37 2011 +0400 +++ b/README-builds.html Fri Apr 01 16:55:47 2011 -0700 @@ -54,7 +54,11 @@ <li><a href="#opensolaris">OpenSolaris</a></li> </ul> </li> - <li><a href="#directories">Source Directory Structure</a> </li> + <li><a href="#directories">Source Directory Structure</a> + <ul> + <li><a href="#drops">Managing the Source Drops</a></li> + </ul> + </li> <li><a href="#building">Build Information</a> <ul> <li><a href="#gmake">GNU Make (<tt><i>gmake</i></tt>)</a> </li> @@ -65,7 +69,7 @@ <ul> <li><a href="#bootjdk">Bootstrap JDK</a> </li> <li><a href="#importjdk">Optional Import JDK</a> </li> - <li><a href="#ant">Ant</a> </li> + <li><a href="#ant">Ant 1.7.1</a> </li> <li><a href="#cacerts">Certificate Authority File (cacert)</a> </li> <li><a href="#compilers">Compilers</a> <ul> @@ -114,13 +118,13 @@ <a href="http://mercurial.selenic.com/wiki/Mercurial">Mercurial</a>. If you are new to Mercurial, please see the <a href="http://mercurial.selenic.com/wiki/BeginnersGuides">Beginner Guides</a> - or refer to the <a href=""http://hgbook.red-bean.com/">Mercurial Book</a>. + or refer to the <a href="http://hgbook.red-bean.com/">Mercurial Book</a>. The first few chapters of the book provide an excellent overview of Mercurial, what it is and how it works. <br> For using Mercurial with the OpenJDK refer to the - <a href=""http://openjdk.java.net/guide/repositories.html#installConfig"> - Developer Guide: Installing and Configuring Mercurial</a> + <a href="http://openjdk.java.net/guide/repositories.html#installConfig"> + Developer Guide: Installing and Configuring Mercurial</a> section for more information. The Forest Extension is not part of the Mercurial install, and is optional, @@ -146,14 +150,14 @@ using the Forest Extension: <blockquote> <tt> - hg fclone http://openjdk.java.net/jdk7/jdk7 <i>YourOpenJDK</i> + hg fclone http://hg.openjdk.java.net/jdk7/jdk7 <i>YourOpenJDK</i> </tt> </blockquote> To get the entire set of OpenJDK Mercurial repositories without using the Forest Extension: <blockquote> <tt> - hg clone http://openjdk.java.net/jdk7/jdk7 <i>YourOpenJDK</i> + hg clone http://hg.openjdk.java.net/jdk7/jdk7 <i>YourOpenJDK</i> <br>cd <i>YourOpenJDK</i> <br>sh ./get_source.sh </tt> @@ -207,66 +211,50 @@ <tr> <td>Linux X86 (32-bit)</td> <td>Fedora 9</td> - <td>gcc 4 </td> - <td>JDK 6u14 FCS </td> + <td>gcc 4.3 </td> + <td>JDK 6u18</td> </tr> <tr> <td>Linux X64 (64-bit)</td> <td>Fedora 9</td> - <td>gcc 4 </td> - <td>JDK 6u14 FCS </td> + <td>gcc 4.3 </td> + <td>JDK 6u18</td> </tr> <tr> <td>Solaris SPARC (32-bit)</td> - <td>Solaris 10u2 + patches - <br> - See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank"> - SunSolve</a> for patch downloads. - </td> + <td>Solaris 10 Update 6</td> <td>Sun Studio 12 Update 1 + patches</td> - <td>JDK 6u14 FCS </td> + <td>JDK 6u18</td> </tr> <tr> <td>Solaris SPARCV9 (64-bit)</td> - <td>Solaris 10u2 + patches - <br> - See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank"> - SunSolve</a> for patch downloads. - </td> + <td>Solaris 10 Update 6</td> <td>Sun Studio 12 Update 1 + patches</td> - <td>JDK 6u14 FCS </td> + <td>JDK 6u18</td> </tr> <tr> <td>Solaris X86 (32-bit)</td> - <td>Solaris 10u2 + patches - <br> - See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank"> - SunSolve</a> for patch downloads. - </td> + <td>Solaris 10 Update 6</td> <td>Sun Studio 12 Update 1 + patches</td> - <td>JDK 6u14 FCS </td> + <td>JDK 6u18</td> </tr> <tr> <td>Solaris X64 (64-bit)</td> - <td>Solaris 10u2 + patches - <br> - See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank"> - SunSolve</a> for patch downloads. - </td> + <td>Solaris 10 Update 6</td> <td>Sun Studio 12 Update 1 + patches</td> - <td>JDK 6u14 FCS </td> + <td>JDK 6u18</td> </tr> <tr> <td>Windows X86 (32-bit)</td> <td>Windows XP</td> <td>Microsoft Visual Studio C++ 2010 Professional Edition</td> - <td>JDK 6u14 FCS </td> + <td>JDK 6u18</td> </tr> <tr> <td>Windows X64 (64-bit)</td> <td>Windows Server 2003 - Enterprise x64 Edition</td> <td>Microsoft Visual Studio C++ 2010 Professional Edition</td> - <td>JDK 6u14 FCS </td> + <td>JDK 6u18</td> </tr> </tbody> </table> @@ -300,7 +288,7 @@ way to do it is to execute the following commands as user <tt>root</tt>: <p/> - <code>yum-builddep java-openjdk</code> + <code>yum-builddep java-1.6.0-openjdk</code> <p/> <code>yum install gcc gcc-c++</code> <p/> @@ -345,10 +333,10 @@ </blockquote> </blockquote> <!-- ------------------------------------------------------ --> - <h3><a name="centos">CentOS 5.2</a></h3> + <h3><a name="centos">CentOS 5.5</a></h3> <blockquote> After installing - <a href="http://www.centos.org/">CentOS 5.2</a> + <a href="http://www.centos.org/">CentOS 5.5</a> you need to make sure you have the following Development bundles installed: <blockquote> @@ -356,7 +344,7 @@ <li>Development Libraries</li> <li>Development Tools</li> <li>Java Development</li> - <li>X Software Development</li> + <li>X Software Development (Including XFree86-devel)</li> </ul> </blockquote> <p> @@ -552,15 +540,105 @@ building the OpenJDK runtime libraries and misc files. The top level <tt>Makefile</tt> is used to build the entire OpenJDK. + + <h3><a name="drops">Managing the Source Drops</a></h3> + <blockquote> + <p> + The repositories <tt>jaxp</tt> and <tt>jaxws</tt> actually + do not contain the sources for JAXP or JAX-WS. + These products have their own open source procedures at their + <a href="http://jaxp.java.net/">JAXP</a> and + <a href="http://jax-ws.java.net/">JAX-WS</a> home pages. + The OpenJDK project does need access to these sources to build + a complete JDK image because JAXP and JAX-WS are part of the JDK. + The current process for delivery of the JAXP and JAX-WS sources + involves so called "source drop bundles" downloaded from a public + website. + There are many reasons for this current mechanism, and it is + understood that this is not ideal for the open source community. + It is possible this process could change in the future. + <br> + <b>NOTE:</b> The <a href="http://download.java.net/openjdk/jdk7/"> + Complete OpenJDK Source Bundles</a> <u>will</u> contain the JAXP and + JAX-WS sources. + </p> + + <h4><a name="dropcreation">Creation of New Source Drop Bundles</a></h4> + <blockquote> + <ol> + <li> + The JAXP or JAX-WS team prepares a new zip bundle, + places a copy in a public download area on java.net, + sends us a link and a list of CRs (Change Request Numbers). + The older download bundles should not be deleted. + It is the responsibility of the JAXP and JAX-WS team to + place the proper GPL legal notices on the sources + and do any filtering or java re-packaging for the + OpenJDK instances of these classes. + </li> + <li> + The OpenJDK team copies this new bundle into shared + area (e.g. <tt>/java/devtools/share/jdk7-drops</tt>). + Older bundles are never deleted so we retain the history. + </li> + <li> + The OpenJDK team edits the ant property file + <tt>jaxp/jaxp.properties</tt> or + <tt>jaxws/jaxws.properties</tt> to update the + base URL, the zip bundle name, and the MD5 checksum + of the zip bundle + (on Solaris: <tt>sum -c md5 <i>bundlename</i></tt>) + </li> + <li> + OpenJDK team reviews and commits those changes with the + given CRs. + </li> + </ol> + </blockquote> + + <h4><a name="dropusage">Using Source Drop Bundles</a></h4> + <blockquote> + <p> + The ant scripts that build <tt>jaxp</tt> and <tt>jaxws</tt> + will attempt to locate these zip bundles from the directory + in the environment variable + <tt><a href="#ALT_DROPS_DIR">ALT_DROPS_DIR</a></tt>. + The checksums protect from getting the wrong, corrupted, or + improperly modified sources. + Once the sources are made available, the population will not + happen again unless a <tt>make clobber</tt> is requested + or the <tt>jaxp/drop/</tt> or <tt>jaxws/drop/</tt> + directory is explicitly deleted. + <br> + <b>NOTE:</b> The default Makefile and ant script behavior + is to NOT download these bundles from the public http site. + In general, doing downloads + during the build process is not advised, it creates too much + unpredictability in the build process. + However, you can use <tt>make ALLOW_DOWNLOADS=true</tt> to + tell the ant script that the download of the zip bundle is + acceptable. + </p> + <p> + The recommended procedure for keeping a cache of these + source bundles would be to download them once, place them + in a directory outside the repositories, and then set + <tt><a href="#ALT_DROPS_DIR">ALT_DROPS_DIR</a></tt> to refer + to that directory. + These drop bundles do change occasionally, so the newer + bundles may need to be added to this area from time to time. + </p> + </blockquote> + </blockquote> </blockquote> <!-- ------------------------------------------------------ --> <hr> <h2><a name="building">Build Information</a></h2> <blockquote> Building the OpenJDK - is done with a <tt><i>gmake</i></tt> - command line and various - environment or make variable settings that direct the make rules + is done with a <a href="#gmake">GNU <tt>make</tt></a> command line + and various + environment or make variable settings that direct the makefile rules to where various components have been installed. Where possible the makefiles will attempt to located the various components in the default locations or any component specific @@ -578,7 +656,7 @@ <pre><tt> bash . jdk/make/jdk_generic_profile.sh - <i>gmake</i> sanity && <i>gmake</i> + <a href="#gmake"><tt>make</tt></a> sanity && <a href="#gmake"><tt>make</tt></a> </tt></pre> </blockquote> <p> @@ -599,25 +677,31 @@ A few notes about using GNU make: <ul> <li> - In general, you need GNU make version 3.81 or newer. + You need GNU make version 3.81 or newer. </li> <li> Place the location of the GNU make binary in the <tt>PATH</tt>. </li> <li> <strong>Linux:</strong> - The <tt>/usr/bin/make</tt> command should work fine for you. + The <tt>/usr/bin/make</tt> should be 3.81 or newer + and should work fine for you. + If this version is not 3.81 or newer, + see the <a href="#buildgmake">"Building GNU make"</a> section. </li> <li> <strong>Solaris:</strong> Do NOT use <tt>/usr/bin/make</tt> on Solaris. If your Solaris system has the software from the Solaris Companion CD installed, - you should use <tt>gmake</tt> + you should try and use <tt>gmake</tt> which will be located in either the <tt>/opt/sfw/bin</tt> or <tt>/usr/sfw/bin</tt> directory. - In more recent versions of Solaris GNU make can be found - at <tt>/usr/bin/gmake</tt>. + In more recent versions of Solaris GNU make might be found + at <tt>/usr/bin/gmake</tt>.<br> + <b>NOTE:</b> It is very likely that this <tt>gmake</tt> + could be 3.80, you need 3.81, in which case, + see the <a href="#buildgmake">"Building GNU make"</a> section. </li> <li> <strong>Windows:</strong> @@ -627,30 +711,25 @@ as a <tt>make.exe</tt> built for something like <a href="http://www.mkssoftware.com/">MKS</a>). <br> - <b>WARNING:</b> Watch out for make version 3.81, it may + <b>WARNING:</b> Watch out on some make 3.81 versions, it may not work due to a lack of support for MS-DOS drive letter paths like <tt>C:/</tt> or <tt>C:\</tt>. - Use a 3.80 version, or find a newer - version that has this problem fixed. - The older 3.80 version of make.exe can be downloaded with this - <a href="http://cygwin.paracoda.com/release/make/make-3.80-1.tar.bz2" target="_blank"> - link</a>. - Use of this older 3.80 make.exe may require that you install the - libintl2.dll library or libintl2 cygwin package which is - no longer installed by default by the cygwin installer. <br> - Also see the + You may be able to use the information at the <a href="http://developer.mozilla.org/en/docs/Windows_build_prerequisites_using_cygwin#make" target="_blank"> mozilla developer center</a> on this topic. <br> It's hoped that when make 3.82 starts shipping in a future cygwin release that this MS-DOS path issue will be fixed. - In addition to the above 3.80 make.exe you can download - this + <br> + It may be possible to download the version at <a href="http://www.cmake.org/files/cygwin/make.exe"> - www.cmake.org make.exe</a> which will not have a libintl2.dll - dependency. + www.cmake.org make.exe</a>. + <br> + It might be necessary for you to build your own GNU make 3.81, + see the <a href="#buildgmake">"Building GNU make"</a> section + in that case. </li> </ul> <p> @@ -662,6 +741,34 @@ The latest source to GNU make is available at <a href="http://ftp.gnu.org/pub/gnu/make/" target="_blank"> ftp.gnu.org/pub/gnu/make/</a>. + </p> + <!-- ------------------------------------------------------ --> + <h4><a name="buildgmake">Building GNU make</a></h4> + <blockquote> + First step is to get the GNU make 3.81 source from + <a href="http://ftp.gnu.org/pub/gnu/make/" target="_blank"> + ftp.gnu.org/pub/gnu/make/</a>. + Building is a little different depending on the OS and unix toolset + on Windows: + <ul> + <li> + <strong>Linux:</strong> + <tt>./configure && make</tt> + </li> + <li> + <strong>Solaris:</strong> + <tt>./configure && gmake CC=gcc</tt> + </li> + <li> + <strong>Windows for CYGWIN:</strong> + <tt>./configure && make</tt> + </li> + <li> + <strong>Windows for MKS: (CYGWIN is recommended)</strong> + <tt>./configure && make -f Makefile.win32</tt> + </li> + </ul> + </blockquote> </blockquote> <!-- ------------------------------------------------------ --> <hr> @@ -713,7 +820,7 @@ </li> <li> Install - <a href="#ant">Ant</a>, + <a href="#ant">Ant 1.7.1 or newer</a>, make sure it is in your PATH. </li> </ol> @@ -776,7 +883,7 @@ </li> <li> Install - <a href="#ant">Ant</a>, + <a href="#ant">Ant 1.7.1 or newer</a>, make sure it is in your PATH. </li> </ol> @@ -862,7 +969,7 @@ </li> <li> Install - <a href="#ant">Ant</a>, + <a href="#ant">Ant 1.7.1 or newer</a>, make sure it is in your PATH and set <tt><a href="#ANT_HOME">ANT_HOME</a></tt>. </li> @@ -923,14 +1030,20 @@ <blockquote> All OpenJDK builds require access to least Ant 1.7.1. The Ant tool is available from the - <a href="http://ant.apache.org" target="_blank"> - Ant download site</a>. + <a href="http://archive.apache.org/dist/ant/binaries/apache-ant-1.7.1-bin.zip" target="_blank"> + Ant 1.7.1 archive download site</a>. You should always make sure <tt>ant</tt> is in your PATH, and on Windows you may also need to set <tt><a href="#ANT_HOME">ANT_HOME</a></tt> to point to the location of the Ant installation, this is the directory pathname that contains a <tt>bin and lib</tt>. + <br> + <b>WARNING:</b> Ant versions used from IDE tools like NetBeans + or installed via system packages may not operate the same + as the one obtained from the Ant download bundles. + These system and IDE installers sometimes choose to change + the ant installation enough to cause differences. </blockquote> <!-- ------------------------------------------------------ --> <h4><a name="cacerts">Certificate Authority File (cacert)</a></h4> @@ -962,7 +1075,7 @@ <blockquote> <strong><a name="gcc">Linux gcc/binutils</a></strong> <blockquote> - The GNU gcc compiler version should be 4 or newer. + The GNU gcc compiler version should be 4.3 or newer. The compiler used should be the default compiler installed in <tt>/usr/bin</tt>. </blockquote> @@ -1047,21 +1160,16 @@ <strong><a name="msvc32">Windows i586: Microsoft Visual Studio 2010 Compilers</a></strong> <blockquote> <p> - <b>BEGIN WARNING</b>: At this time (Spring/Summer 2010) JDK 7 is starting a transition to - use the newest VS2010 Microsoft compilers. These build instructions are updated - to show where we are going. We have a QA process to go through before - official builds actually use VS2010. So for now, official builds are - still using VS2003. No other compilers are known to build the entire JDK, + <b>BEGIN WARNING</b>: JDK 7 has transitioned to + use the newest VS2010 Microsoft compilers. + No other compilers are known to build the entire JDK, including non-open portions. - So for now you should be able to build with either VS2003 or VS2010. - We do not guarantee that VS2008 will work, although there is sufficient - makefile support to make at least basic JDK builds plausible. Visual Studio 2010 Express compilers are now able to build all the open source repositories, but this is 32 bit only. To build 64 bit - Windows binaries use the the 7.1 Windows SDK.<b>END WARNING.</b> + Windows binaries use the the 7.1 Windows SDK. + <b>END WARNING.</b> <p> - The 32-bit OpenJDK Windows build - requires + The 32-bit OpenJDK Windows build requires Microsoft Visual Studio C++ 2010 (VS2010) Professional Edition or Express compiler. The compiler and other tools are expected to reside @@ -1088,11 +1196,10 @@ </blockquote> <strong><a name="msvc64">Windows x64: Microsoft Visual Studio 2010 Professional Compiler</a></strong> <blockquote> - For <b>X64</b>, builds, when using the VS2010 Professional - compiler, the 64 bit build set up is much the same as 32 bit + For <b>X64</b>, the set up is much the same as 32 bit except that you run <tt>amd64\VCVARS64.BAT</tt> to set the compiler environment variables. - Previously 64 bit builds had used the 64 bit compiler in + Previously 64 bit builds had to use the 64 bit compiler in an unbundled Windows SDK but this is no longer necessary if you have VS2010 Professional. </blockquote> @@ -1614,6 +1721,13 @@ and on Windows with CYGWIN <tt>/usr/bin</tt>. </dd> + <dt><tt><a name="ALT_DROPS_DIR">ALT_DROPS_DIR</a></tt> </dt> + <dd> + The location of any source drop bundles + (see <a href="#drops">Managing the Source Drops</a>). + The default will be + <tt>$(ALT_JDK_DEVTOOLS_PATH)/share/jdk7-drops</tt>. + </dd> <dt><a name="ALT_UNIXCCS_PATH"><tt>ALT_UNIXCCS_PATH</tt></a></dt> <dd> <strong>Solaris only:</strong> @@ -1649,6 +1763,12 @@ Where each of these directories contain the import JDK image for that platform. </dd> + <dt><a name="ALT_OPENWIN_HOME"><tt>ALT_OPENWIN_HOME</tt></a></dt> + <dd> + The top-level directory of the libraries and include files for the platform's + graphical programming environment. The default location is platform specific. + For example, on Linux it defaults to <tt>/usr/X11R6/</tt>. + </dd> <dt><strong>Windows specific:</strong></dt> <dd> <dl> @@ -1659,9 +1779,8 @@ located. The default is whatever WINDOWSSDKDIR is set to (or WindowsSdkDir) or the path - <pre> - c:\Program Files\Microsoft SDKs\Windows\v6.1a - </pre> + <br> + <tt>c:\Program Files\Microsoft SDKs\Windows\v7.0a</tt> </dd> <dt><tt><a name="ALT_DXSDK_PATH">ALT_DXSDK_PATH</a></tt> </dt> <dd> @@ -1678,10 +1797,160 @@ </dd> </dl> </dd> + <dt><strong>Cross-Compilation Support:</strong></dt> + <dd> + <dl> + <dt><a name="CROSS_COMPILE_ARCH"><tt>CROSS_COMPILE_ARCH</tt></a> </dt> + <dd> + Set to the target architecture of a cross-compilation build. If set, this + variable is used to signify that we are cross-compiling. The expectation + is that <a href="#ALT_COMPILER_PATH"><tt>ALT_COMPILER_PATH</tt></a> is set + to point to the cross-compiler and that any cross-compilation specific flags + are passed using <a href="#EXTRA_CFLAGS"><tt>EXTRA_CFLAGS</tt></a>. + The <a href="#ALT_OPENWIN_HOME"><tt>ALT_OPENWIN_HOME</tt></a> variable should + also be set to point to the graphical header files (e.g. X11) provided with + the cross-compiler. + When cross-compiling we skip execution of any demos etc that may be built, and + also skip binary-file verification. + </dd> + <dt><tt><a name="EXTRA_CFLAGS">EXTRA_CFLAGS</a></tt> </dt> + <dd> + Used to pass cross-compilation options to the cross-compiler. + These are added to the <tt>CFLAGS</tt> and <tt>CXXFLAGS</tt> variables. + </dd> + <dt><tt><a name="USE_ONLY_BOOTDIR_TOOLS">USE_ONLY_BOOTDIR_TOOLS</a></tt> </dt> + <dd> + Used primarily for cross-compilation builds (and always set in that case) + this variable indicates that tools from the boot JDK should be used during + the build process, not the tools (<tt>javac</tt>, <tt>javah</tt>, <tt>jar</tt>) + just built (which can't execute on the build host). + </dd> + <dt><tt><a name="HOST_CC">HOST_CC</a></tt> </dt> + <dd> + The location of the C compiler to generate programs to run on the build host. + Some parts of the build generate programs that are then compiled and executed + to produce other parts of the build. Normally the primary C compiler is used + to do this, but when cross-compiling that would be the cross-compiler and the + resulting program could not be executed. + On Linux this defaults to <tt>/usr/bin/gcc</tt>; on other platforms it must be + set explicitly. + </dd> + </dl> + <dt><strong>Specialized Build Options:</strong></dt> + <dd> + Some build variables exist to support specialized build environments and/or specialized + build products. Their use is only supported in those contexts: + <dl> + <dt><tt><a name="BUILD_CLIENT_ONLY">BUILD_CLIENT_ONLY</a></tt> </dt> + <dd> + Indicates this build will only contain the Hotspot client VM. In addition to + controlling the Hotspot build target, it ensures that we don't try to copy + any server VM files/directories, and defines a default <tt>jvm.cfg</tt> file + suitable for a client-only environment. Using this in a 64-bit build will + generate a sanity warning as 64-bit client builds are not directly supported. + </dd> + <dt><tt><a name="BUILD_HEADLESS_ONLY"></a>BUILD_HEADLESS_ONLY</tt> </dt> + <dd> + Used when the build environment has no graphical capabilities at all. This + excludes building anything that requires graphical libraries to be available. + </dd> + <dt><tt><a name="JAVASE_EMBEDDED"></a>JAVASE_EMBEDDED</tt> </dt> + <dd> + Used to indicate this is a build of the Oracle Java SE Embedded product. + This will enable the directives included in the SE-Embedded specific build + files. + </dd> + <dt><tt><a name="LIBZIP_CAN_USE_MMAP">LIBZIP_CAN_USE_MMAP</a></tt> </dt> + <dd> + If set to false, disables the use of mmap by the zip utility. Otherwise, + mmap will be used. + </dd> + <dt><tt><a name="COMPRESS_JARS"></a>COMPRESS_JARS</tt> </dt> + <dd> + If set to true, causes certain jar files that would otherwise be built without + compression, to use compression. + </dd> + </dl> + </dd> </dl> </blockquote> <!-- ------------------------------------------------------ --> <hr> + <h2><a name="hints">Hints and Tips</a></h2> + <blockquote> + You don't have to use all these hints and tips, and in fact people do actually + build with systems that contradict these, but they might prove to be + helpful to some. + <ul> + <li> + If <tt>make sanity</tt> does not work, find out why, fix that + before going any further. Or at least understand what the + complaints are from it. + </li> + <li> + JDK: Keep in mind that you are building a JDK, but you need + a JDK (BOOTDIR JDK) to build this JDK. + </li> + <li> + Ant: The ant utility is a java application and besides having + ant available to you, it's important that ant finds the right + java to run with. Make sure you can type <tt>ant -version</tt> + and get clean results with no error messages. + </li> + <li> + Linux: Try and favor the system packages over building your own + or getting packages from other areas. + Most Linux builds should be possible with the system's + available packages. + </li> + <li> + Solaris: Typically you will need to get compilers on your systems + and occasionally GNU make 3.81 if a gmake binary is not available. + The gmake binary might not be 3.81, be careful. + </li> + <li> + Windows VS2010: + <ul> + <li> + Only the C++ part of VS2010 is needed. + Try to let the installation go to the default install directory. + Always reboot your system after installing VS2010. + The system environment variable VS100COMNTOOLS should be + set in your environment. + </li> + <li> + Make sure that TMP and TEMP are also set in the environment + and refer to Windows paths that exist, like <tt>C:\temp</tt>, + not <tt>/tmp</tt>, not <tt>/cygdrive/c/temp</tt>, and not <tt>C:/temp</tt>. + <tt>C:\temp</tt> is just an example, it is assumed that this area is + private to the user, so by default after installs you should + see a unique user path in these variables. + </li> + <li> + You need to use vsvars32.bat or vsvars64.bat to get the + PATH, INCLUDE, LIB, LIBPATH, and WINDOWSSDKDIR + variables set in your shell environment. + These bat files are not easy to use from a shell environment. + However, there is a script placed in the root jdk7 repository called + vsvars.sh that can help, it should only be done once in a shell + that will be doing the build, e.g.<br> + <tt>sh ./make/scripts/vsvars.sh -v10 > settings<br> + eval `cat settings`</tt><br> + Or just <tt>eval `sh ./make/scripts/vsvars.sh -v10`</tt>. + </li> + </ul> + </li> + <li> + Windows: PATH order is critical, see the + <a href="#paths">paths</a> section for more information. + </li> + <li> + Windows 64bit builds: Use ARCH_DATA_MODEL=64. + </li> + </ul> + </blockquote> + <!-- ------------------------------------------------------ --> + <hr> <h2><a name="troubleshooting">Troubleshooting</a></h2> <blockquote> A build can fail for any number of reasons. @@ -1707,6 +1976,19 @@ below, with suggestions for remedies. <ul> <li> + <b>Corrupted Bundles on Windows:</b> + <blockquote> + Some virus scanning software has been known to corrupt the + downloading of zip bundles. + It may be necessary to disable the 'on access' or 'real time' + virus scanning features to prevent this corruption. + This type of "real time" virus scanning can also slow down the + build process significantly. + Temporarily disabling the feature, or excluding the build + output directory may be necessary to get correct and faster builds. + </blockquote> + </li> + <li> <b>Slow Builds:</b> <blockquote> If your build machine seems to be overloaded from too many @@ -1801,7 +2083,11 @@ </blockquote> </li> <li> - <b>Windows Error Message: <tt>*** fatal error - couldn't allocate heap, ... </tt></b> + <b>Windows Error Messages:</b><br> + <tt>*** fatal error - couldn't allocate heap, ... </tt><br> + <tt>rm fails with "Directory not empty"</tt><br> + <tt>unzip fails with "cannot create ... Permission denied"</tt><br> + <tt>unzip fails with "cannot create ... Error 50"</tt><br> <blockquote> The CYGWIN software can conflict with other non-CYGWIN software. See the CYGWIN FAQ section on @@ -1810,12 +2096,11 @@ </blockquote> </li> <li> - <b>Windows Error Message: <tt>*** multiple target patterns. Stop.</tt></b> + <b>Windows Error Message: <tt>spawn failed</tt></b> <blockquote> - The CYGWIN make version 3.81 may not like the Windows <tt>C:/</tt> - style paths, it may not like the ':' character in the path - when used in a makefile target definition. - See the <a href="#gmake"><tt><i>gmake</i></tt></a> section. + Try rebooting the system, or there could be some kind of + issue with the disk or disk partition being used. + Sometimes it comes with a "Permission Denied" message. </blockquote> </li> </ul>
--- a/corba/.hgtags Fri Apr 01 15:43:37 2011 +0400 +++ b/corba/.hgtags Fri Apr 01 16:55:47 2011 -0700 @@ -108,3 +108,5 @@ 9d6dd2cdfcb92612dbd836ecded87770d52b49db jdk7-b131 1b1e75e8f476e5c07f0d2b035993895e2603e1f0 jdk7-b132 671fe2e623ffefb4b7c312be919fc71eb48c1df1 jdk7-b133 +918003855fa0dba5acf4bf1fe36526d2fc4c1ba8 jdk7-b134 +e0b72ae5dc5e824b342801c8d1d336a55eb54e2c jdk7-b135
--- a/hotspot/.hgtags Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/.hgtags Fri Apr 01 16:55:47 2011 -0700 @@ -154,3 +154,7 @@ 0e531ab5ba04967a0e9aa6aef65e6eb3a0dcf632 jdk7-b132 a8d643a4db47c7b58e0bcb49c77b5c3610de86a8 hs21-b03 1b3a350709e4325d759bb453ff3fb6a463270488 jdk7-b133 +447e6faab4a8755d4860c2366630729dbaec111c jdk7-b134 +3c76374706ea8a77e15aec8310e831e5734f8775 hs21-b04 +b898f0fc3cedc972d884d31a751afd75969531cf jdk7-b135 +b898f0fc3cedc972d884d31a751afd75969531cf hs21-b05
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/FieldImpl.java Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/FieldImpl.java Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ // get the value of static field ValueImpl getValue() { - return getValue(saField.getFieldHolder()); + return getValue(saField.getFieldHolder().getJavaMirror()); } // get the value of this Field from a specific Oop
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/StringTable.java Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/StringTable.java Fri Apr 01 16:55:47 2011 -0700 @@ -44,12 +44,10 @@ private static synchronized void initialize(TypeDataBase db) { Type type = db.lookupType("StringTable"); theTableField = type.getAddressField("_the_table"); - stringTableSize = db.lookupIntConstant("StringTable::string_table_size").intValue(); } // Fields private static AddressField theTableField; - private static int stringTableSize; // Accessors public static StringTable getTheTable() { @@ -57,10 +55,6 @@ return (StringTable) VMObjectFactory.newObject(StringTable.class, tmp); } - public static int getStringTableSize() { - return stringTableSize; - } - public StringTable(Address addr) { super(addr); }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,7 @@ innerClasses = new OopField(type.getOopField("_inner_classes"), Oop.getHeaderSize()); nonstaticFieldSize = new CIntField(type.getCIntegerField("_nonstatic_field_size"), Oop.getHeaderSize()); staticFieldSize = new CIntField(type.getCIntegerField("_static_field_size"), Oop.getHeaderSize()); - staticOopFieldSize = new CIntField(type.getCIntegerField("_static_oop_field_size"), Oop.getHeaderSize()); + staticOopFieldCount = new CIntField(type.getCIntegerField("_static_oop_field_count"), Oop.getHeaderSize()); nonstaticOopMapSize = new CIntField(type.getCIntegerField("_nonstatic_oop_map_size"), Oop.getHeaderSize()); isMarkedDependent = new CIntField(type.getCIntegerField("_is_marked_dependent"), Oop.getHeaderSize()); initState = new CIntField(type.getCIntegerField("_init_state"), Oop.getHeaderSize()); @@ -140,7 +140,7 @@ private static OopField innerClasses; private static CIntField nonstaticFieldSize; private static CIntField staticFieldSize; - private static CIntField staticOopFieldSize; + private static CIntField staticOopFieldCount; private static CIntField nonstaticOopMapSize; private static CIntField isMarkedDependent; private static CIntField initState; @@ -261,8 +261,7 @@ public Symbol getSourceDebugExtension(){ return getSymbol(sourceDebugExtension); } public TypeArray getInnerClasses() { return (TypeArray) innerClasses.getValue(this); } public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); } - public long getStaticFieldSize() { return staticFieldSize.getValue(this); } - public long getStaticOopFieldSize() { return staticOopFieldSize.getValue(this); } + public long getStaticOopFieldCount() { return staticOopFieldCount.getValue(this); } public long getNonstaticOopMapSize() { return nonstaticOopMapSize.getValue(this); } public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; } public long getVtableLen() { return vtableLen.getValue(this); } @@ -453,7 +452,7 @@ visitor.doOop(innerClasses, true); visitor.doCInt(nonstaticFieldSize, true); visitor.doCInt(staticFieldSize, true); - visitor.doCInt(staticOopFieldSize, true); + visitor.doCInt(staticOopFieldCount, true); visitor.doCInt(nonstaticOopMapSize, true); visitor.doCInt(isMarkedDependent, true); visitor.doCInt(initState, true); @@ -692,7 +691,7 @@ public long getObjectSize() { long bodySize = alignObjectOffset(getVtableLen() * getHeap().getOopSize()) + alignObjectOffset(getItableLen() * getHeap().getOopSize()) - + (getStaticFieldSize() + getNonstaticOopMapSize()) * getHeap().getOopSize(); + + (getNonstaticOopMapSize()) * getHeap().getOopSize(); return alignObjectSize(headerSize + bodySize); }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/IntField.java Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/IntField.java Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,12 @@ super(holder, fieldArrayIndex); } - public int getValue(Oop obj) { return obj.getHandle().getJIntAt(getOffset()); } + public int getValue(Oop obj) { + if (!isVMField() && !obj.isInstance() && !obj.isArray()) { + throw new InternalError(obj.toString()); + } + return obj.getHandle().getJIntAt(getOffset()); + } public void setValue(Oop obj, int value) throws MutationException { // Fix this: setJIntAt is missing in Address }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopField.java Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopField.java Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,11 +41,17 @@ } public Oop getValue(Oop obj) { + if (!isVMField() && !obj.isInstance() && !obj.isArray()) { + throw new InternalError(); + } return obj.getHeap().newOop(getValueAsOopHandle(obj)); } /** Debugging support */ public OopHandle getValueAsOopHandle(Oop obj) { + if (!isVMField() && !obj.isInstance() && !obj.isArray()) { + throw new InternalError(obj.toString()); + } return obj.getHandle().getOopHandleAt(getOffset()); }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -274,13 +274,7 @@ // hc_klass is a HotSpot magic field and hence we can't // find it from InstanceKlass for java.lang.Class. TypeDataBase db = VM.getVM().getTypeDataBase(); - int hcKlassOffset = (int) Instance.getHeaderSize(); - try { - hcKlassOffset += (db.lookupIntConstant("java_lang_Class::hc_klass_offset").intValue() * - VM.getVM().getHeapOopSize()); - } catch (RuntimeException re) { - // ignore, currently java_lang_Class::hc_klass_offset is zero - } + int hcKlassOffset = (int) db.lookupType("java_lang_Class").getCIntegerField("klass_offset").getValue(); if (VM.getVM().isCompressedOopsEnabled()) { hcKlassField = new NarrowOopField(new NamedFieldIdentifier("hc_klass"), hcKlassOffset, true); } else {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -839,13 +839,13 @@ } private void readSystemProperties() { - InstanceKlass systemKls = getSystemDictionary().getSystemKlass(); + final InstanceKlass systemKls = getSystemDictionary().getSystemKlass(); systemKls.iterate(new DefaultOopVisitor() { ObjectReader objReader = new ObjectReader(); public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) { if (field.getID().getName().equals("props")) { try { - sysProps = (Properties) objReader.readObject(field.getValue(getObj())); + sysProps = (Properties) objReader.readObject(field.getValue(systemKls.getJavaMirror())); } catch (Exception e) { if (Assert.ASSERTS_ENABLED) { e.printStackTrace();
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -746,7 +746,7 @@ out.writeByte((byte)kind); if (ik != null) { // static field - writeField(field, ik); + writeField(field, ik.getJavaMirror()); } } }
--- a/hotspot/agent/test/jdi/sasanity.sh Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/agent/test/jdi/sasanity.sh Fri Apr 01 16:55:47 2011 -0700 @@ -43,6 +43,7 @@ fi jdk=$1 +shift OS=`uname` if [ "$OS" != "Linux" ]; then @@ -68,7 +69,7 @@ tmp=/tmp/sagsetup rm -f $tmp -$jdk/bin/java sagtarg > $tmp & +$jdk/bin/java $* sagtarg > $tmp & pid=$! while [ ! -s $tmp ] ; do # Kludge alert!
--- a/hotspot/make/hotspot_version Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/make/hotspot_version Fri Apr 01 16:55:47 2011 -0700 @@ -35,7 +35,7 @@ HS_MAJOR_VER=21 HS_MINOR_VER=0 -HS_BUILD_NUMBER=04 +HS_BUILD_NUMBER=06 JDK_MAJOR_VER=1 JDK_MINOR_VER=7
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -3179,7 +3179,7 @@ Label& wrong_method_type) { assert_different_registers(mtype_reg, mh_reg, temp_reg); // compare method type against that of the receiver - RegisterOrConstant mhtype_offset = delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg); + RegisterOrConstant mhtype_offset = delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg); load_heap_oop(mh_reg, mhtype_offset, temp_reg); cmp(temp_reg, mtype_reg); br(Assembler::notEqual, false, Assembler::pn, wrong_method_type); @@ -3195,14 +3195,14 @@ Register temp_reg) { assert_different_registers(vmslots_reg, mh_reg, temp_reg); // load mh.type.form.vmslots - if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) { + if (java_lang_invoke_MethodHandle::vmslots_offset_in_bytes() != 0) { // hoist vmslots into every mh to avoid dependent load chain - ld( Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); + ld( Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); } else { Register temp2_reg = vmslots_reg; - load_heap_oop(Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)), temp2_reg); - load_heap_oop(Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg)), temp2_reg); - ld( Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); + load_heap_oop(Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg)), temp2_reg); + load_heap_oop(Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg)), temp2_reg); + ld( Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)), vmslots_reg); } } @@ -3213,7 +3213,7 @@ // pick out the interpreted side of the handler // NOTE: vmentry is not an oop! - ld_ptr(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg), temp_reg); + ld_ptr(mh_reg, delayed_value(java_lang_invoke_MethodHandle::vmentry_offset_in_bytes, temp_reg), temp_reg); // off we go... ld_ptr(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes(), temp_reg);
--- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -301,7 +301,8 @@ // thread. assert(_obj != noreg, "must be a valid register"); assert(_oop_index >= 0, "must have oop index"); - __ ld_ptr(_obj, instanceKlass::init_thread_offset_in_bytes() + sizeof(klassOopDesc), G3); + __ load_heap_oop(_obj, java_lang_Class::klass_offset_in_bytes(), G3); + __ ld_ptr(G3, instanceKlass::init_thread_offset_in_bytes() + sizeof(klassOopDesc), G3); __ cmp(G2_thread, G3); __ br(Assembler::notEqual, false, Assembler::pn, call_patch); __ delayed()->nop();
--- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1188,7 +1188,7 @@ __ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH __ lduh(max_stack, O3); // Full size expression stack - guarantee(!EnableMethodHandles, "no support yet for java.dyn.MethodHandle"); //6815692 + guarantee(!EnableMethodHandles, "no support yet for java.lang.invoke.MethodHandle"); //6815692 //6815692//if (EnableMethodHandles) //6815692// __ inc(O3, methodOopDesc::extra_stack_entries()); __ sll(O3, LogBytesPerWord, O3);
--- a/hotspot/src/cpu/sparc/vm/dump_sparc.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/sparc/vm/dump_sparc.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -80,13 +80,19 @@ for (int j = 0; j < num_virtuals; ++j) { dummy_vtable[num_virtuals * i + j] = (void*)masm->pc(); __ save(SP, -256, SP); + int offset = (i << 8) + j; + Register src = G0; + if (!Assembler::is_simm13(offset)) { + __ sethi(offset, L0); + src = L0; + offset = offset & ((1 << 10) - 1); + } __ brx(Assembler::always, false, Assembler::pt, common_code); // Load L0 with a value indicating vtable/offset pair. // -- bits[ 7..0] (8 bits) which virtual method in table? - // -- bits[12..8] (5 bits) which virtual method table? - // -- must fit in 13-bit instruction immediate field. - __ delayed()->set((i << 8) + j, L0); + // -- bits[13..8] (6 bits) which virtual method table? + __ delayed()->or3(src, offset, L0); } }
--- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,6 +51,7 @@ define_pd_global(intx, OptoLoopAlignment, 16); // = 4*wordSize define_pd_global(intx, InlineFrequencyCount, 50); // we can use more inlining on the SPARC define_pd_global(intx, InlineSmallCode, 1500); + #ifdef _LP64 // Stack slots are 2X larger in LP64 than in the 32 bit VM. define_pd_global(intx, ThreadStackSize, 1024); @@ -71,4 +72,6 @@ define_pd_global(bool, UseMembar, false); +// GC Ergo Flags +define_pd_global(intx, CMSYoungGenPerWorker, 16*M); // default max size of CMS young gen, per GC worker thread #endif // CPU_SPARC_VM_GLOBALS_SPARC_HPP
--- a/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -260,7 +260,7 @@ // Method handle invoker -// Dispatch a method of the form java.dyn.MethodHandles::invoke(...) +// Dispatch a method of the form java.lang.invoke.MethodHandles::invoke(...) address InterpreterGenerator::generate_method_handle_entry(void) { if (!EnableMethodHandles) { return generate_abstract_entry();
--- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -112,8 +112,8 @@ } // given the MethodType, find out where the MH argument is buried - __ load_heap_oop(Address(O0_mtype, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, O1_scratch)), O4_argslot); - __ ldsw( Address(O4_argslot, __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, O1_scratch)), O4_argslot); + __ load_heap_oop(Address(O0_mtype, __ delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, O1_scratch)), O4_argslot); + __ ldsw( Address(O4_argslot, __ delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, O1_scratch)), O4_argslot); __ add(Gargs, __ argument_offset(O4_argslot, 1), O4_argbase); // Note: argument_address uses its input as a scratch register! __ ld_ptr(Address(O4_argbase, -Interpreter::stackElementSize), G3_method_handle); @@ -141,10 +141,10 @@ // load up an adapter from the calling type (Java weaves this) Register O2_form = O2_scratch; Register O3_adapter = O3_scratch; - __ load_heap_oop(Address(O0_mtype, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, O1_scratch)), O2_form); - // load_heap_oop(Address(O2_form, __ delayed_value(java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter); + __ load_heap_oop(Address(O0_mtype, __ delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, O1_scratch)), O2_form); + // load_heap_oop(Address(O2_form, __ delayed_value(java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter); // deal with old JDK versions: - __ add( Address(O2_form, __ delayed_value(java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter); + __ add( Address(O2_form, __ delayed_value(java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter); __ cmp(O3_adapter, O2_form); Label sorry_no_invoke_generic; __ brx(Assembler::lessUnsigned, false, Assembler::pn, sorry_no_invoke_generic); @@ -376,16 +376,16 @@ // which conversion op types are implemented here? int MethodHandles::adapter_conversion_ops_supported_mask() { - return ((1<<sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY) - |(1<<sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW) - |(1<<sun_dyn_AdapterMethodHandle::OP_CHECK_CAST) - |(1<<sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM) - |(1<<sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM) - |(1<<sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS) - |(1<<sun_dyn_AdapterMethodHandle::OP_ROT_ARGS) - |(1<<sun_dyn_AdapterMethodHandle::OP_DUP_ARGS) - |(1<<sun_dyn_AdapterMethodHandle::OP_DROP_ARGS) - //|(1<<sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS) //BUG! + return ((1<<java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS) + //|(1<<java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS) //BUG! ); // FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS. } @@ -413,22 +413,22 @@ const Register O1_actual = O1; const Register O2_required = O2; - guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); + guarantee(java_lang_invoke_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); // Some handy addresses: Address G5_method_fie( G5_method, in_bytes(methodOopDesc::from_interpreted_offset())); Address G5_method_fce( G5_method, in_bytes(methodOopDesc::from_compiled_offset())); - Address G3_mh_vmtarget( G3_method_handle, java_dyn_MethodHandle::vmtarget_offset_in_bytes()); + Address G3_mh_vmtarget( G3_method_handle, java_lang_invoke_MethodHandle::vmtarget_offset_in_bytes()); - Address G3_dmh_vmindex( G3_method_handle, sun_dyn_DirectMethodHandle::vmindex_offset_in_bytes()); + Address G3_dmh_vmindex( G3_method_handle, java_lang_invoke_DirectMethodHandle::vmindex_offset_in_bytes()); - Address G3_bmh_vmargslot( G3_method_handle, sun_dyn_BoundMethodHandle::vmargslot_offset_in_bytes()); - Address G3_bmh_argument( G3_method_handle, sun_dyn_BoundMethodHandle::argument_offset_in_bytes()); + Address G3_bmh_vmargslot( G3_method_handle, java_lang_invoke_BoundMethodHandle::vmargslot_offset_in_bytes()); + Address G3_bmh_argument( G3_method_handle, java_lang_invoke_BoundMethodHandle::argument_offset_in_bytes()); - Address G3_amh_vmargslot( G3_method_handle, sun_dyn_AdapterMethodHandle::vmargslot_offset_in_bytes()); - Address G3_amh_argument ( G3_method_handle, sun_dyn_AdapterMethodHandle::argument_offset_in_bytes()); - Address G3_amh_conversion(G3_method_handle, sun_dyn_AdapterMethodHandle::conversion_offset_in_bytes()); + Address G3_amh_vmargslot( G3_method_handle, java_lang_invoke_AdapterMethodHandle::vmargslot_offset_in_bytes()); + Address G3_amh_argument ( G3_method_handle, java_lang_invoke_AdapterMethodHandle::argument_offset_in_bytes()); + Address G3_amh_conversion(G3_method_handle, java_lang_invoke_AdapterMethodHandle::conversion_offset_in_bytes()); const int java_mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes(); @@ -453,7 +453,7 @@ __ mov(O5_savedSP, SP); // Cut the stack back to where the caller started. Label L_no_method; - // FIXME: fill in _raise_exception_method with a suitable sun.dyn method + // FIXME: fill in _raise_exception_method with a suitable java.lang.invoke method __ set(AddressLiteral((address) &_raise_exception_method), G5_method); __ ld_ptr(Address(G5_method, 0), G5_method); __ tst(G5_method); @@ -775,9 +775,13 @@ switch (ek) { case _adapter_opt_i2l: { - __ ldsw(arg_lsw, O2_scratch); // Load LSW - NOT_LP64(__ srlx(O2_scratch, BitsPerInt, O3_scratch)); // Move high bits to lower bits for std - __ st_long(O2_scratch, arg_msw); // Uses O2/O3 on !_LP64 +#ifdef _LP64 + __ ldsw(arg_lsw, O2_scratch); // Load LSW sign-extended +#else + __ ldsw(arg_lsw, O3_scratch); // Load LSW sign-extended + __ srlx(O3_scratch, BitsPerInt, O2_scratch); // Move MSW value to lower 32-bits for std +#endif + __ st_long(O2_scratch, arg_msw); // Uses O2/O3 on !_LP64 } break; case _adapter_opt_unboxl:
--- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -52,6 +52,22 @@ ICache::invalidate_range(instaddr, 7 * BytesPerInstWord); } +void NativeInstruction::verify_data64_sethi(address instaddr, intptr_t x) { + ResourceMark rm; + unsigned char buffer[10 * BytesPerInstWord]; + CodeBuffer buf(buffer, 10 * BytesPerInstWord); + MacroAssembler masm(&buf); + + Register destreg = inv_rd(*(unsigned int *)instaddr); + // Generate the proper sequence into a temporary buffer and compare + // it with the original sequence. + masm.patchable_sethi(x, destreg); + int len = buffer - masm.pc(); + for (int i = 0; i < len; i++) { + assert(instaddr[i] == buffer[i], "instructions must match"); + } +} + void NativeInstruction::verify() { // make sure code pattern is actually an instruction address address addr = addr_at(0);
--- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -254,6 +254,7 @@ // sethi. This only does the sethi. The disp field (bottom 10 bits) // must be handled separately. static void set_data64_sethi(address instaddr, intptr_t x); + static void verify_data64_sethi(address instaddr, intptr_t x); // combine the fields of a sethi/simm13 pair (simm13 = or, add, jmpl, ld/st) static int data32(int sethi_insn, int arith_insn) {
--- a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -30,7 +30,7 @@ #include "oops/oop.inline.hpp" #include "runtime/safepoint.hpp" -void Relocation::pd_set_data_value(address x, intptr_t o) { +void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { NativeInstruction* ip = nativeInstruction_at(addr()); jint inst = ip->long_at(0); assert(inst != NativeInstruction::illegal_instruction(), "no breakpoint"); @@ -83,7 +83,11 @@ guarantee(Assembler::is_simm13(simm13), "offset can't overflow simm13"); inst &= ~Assembler::simm( -1, 13); inst |= Assembler::simm(simm13, 13); - ip->set_long_at(0, inst); + if (verify_only) { + assert(ip->long_at(0) == inst, "instructions must match"); + } else { + ip->set_long_at(0, inst); + } } break; @@ -97,19 +101,36 @@ jint np = oopDesc::encode_heap_oop((oop)x); inst &= ~Assembler::hi22(-1); inst |= Assembler::hi22((intptr_t)np); - ip->set_long_at(0, inst); + if (verify_only) { + assert(ip->long_at(0) == inst, "instructions must match"); + } else { + ip->set_long_at(0, inst); + } inst2 = ip->long_at( NativeInstruction::nop_instruction_size ); guarantee(Assembler::inv_op(inst2)==Assembler::arith_op, "arith op"); - ip->set_long_at(NativeInstruction::nop_instruction_size, ip->set_data32_simm13( inst2, (intptr_t)np)); + if (verify_only) { + assert(ip->long_at(NativeInstruction::nop_instruction_size) == NativeInstruction::set_data32_simm13( inst2, (intptr_t)np), + "instructions must match"); + } else { + ip->set_long_at(NativeInstruction::nop_instruction_size, NativeInstruction::set_data32_simm13( inst2, (intptr_t)np)); + } break; } - ip->set_data64_sethi( ip->addr_at(0), (intptr_t)x ); + if (verify_only) { + ip->verify_data64_sethi( ip->addr_at(0), (intptr_t)x ); + } else { + ip->set_data64_sethi( ip->addr_at(0), (intptr_t)x ); + } #else guarantee(Assembler::inv_op2(inst)==Assembler::sethi_op2, "must be sethi"); inst &= ~Assembler::hi22( -1); inst |= Assembler::hi22((intptr_t)x); // (ignore offset; it doesn't play into the sethi) - ip->set_long_at(0, inst); + if (verify_only) { + assert(ip->long_at(0) == inst, "instructions must match"); + } else { + ip->set_long_at(0, inst); + } #endif } break;
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -3303,7 +3303,7 @@ __ sll(Rret, LogBytesPerWord, Rret); __ ld_ptr(Rtemp, Rret, Rret); // get return address - __ load_heap_oop(G5_callsite, __ delayed_value(java_dyn_CallSite::target_offset_in_bytes, Rscratch), G3_method_handle); + __ load_heap_oop(G5_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, Rscratch), G3_method_handle); __ null_check(G3_method_handle); // Adjust Rret first so Llast_SP can be same as Rret
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -7831,7 +7831,7 @@ void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg, Register temp_reg, Label& wrong_method_type) { - Address type_addr(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)); + Address type_addr(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg)); // compare method type against that of the receiver if (UseCompressedOops) { load_heap_oop(temp_reg, type_addr); @@ -7851,14 +7851,14 @@ Register temp_reg) { assert_different_registers(vmslots_reg, mh_reg, temp_reg); // load mh.type.form.vmslots - if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) { + if (java_lang_invoke_MethodHandle::vmslots_offset_in_bytes() != 0) { // hoist vmslots into every mh to avoid dependent load chain - movl(vmslots_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg))); + movl(vmslots_reg, Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::vmslots_offset_in_bytes, temp_reg))); } else { Register temp2_reg = vmslots_reg; - load_heap_oop(temp2_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg))); - load_heap_oop(temp2_reg, Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg))); - movl(vmslots_reg, Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg))); + load_heap_oop(temp2_reg, Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg))); + load_heap_oop(temp2_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg))); + movl(vmslots_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg))); } } @@ -7873,7 +7873,7 @@ // pick out the interpreted side of the handler // NOTE: vmentry is not an oop! - movptr(temp_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg))); + movptr(temp_reg, Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::vmentry_offset_in_bytes, temp_reg))); // off we go... jmp(Address(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes()));
--- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -313,10 +313,13 @@ } assert(_obj != noreg, "must be a valid register"); Register tmp = rax; - if (_obj == tmp) tmp = rbx; + Register tmp2 = rbx; __ push(tmp); + __ push(tmp2); + __ load_heap_oop(tmp2, Address(_obj, java_lang_Class::klass_offset_in_bytes())); __ get_thread(tmp); - __ cmpptr(tmp, Address(_obj, instanceKlass::init_thread_offset_in_bytes() + sizeof(klassOopDesc))); + __ cmpptr(tmp, Address(tmp2, instanceKlass::init_thread_offset_in_bytes() + sizeof(klassOopDesc))); + __ pop(tmp2); __ pop(tmp); __ jcc(Assembler::notEqual, call_patch);
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,4 +72,6 @@ define_pd_global(bool, UseMembar, false); +// GC Ergo Flags +define_pd_global(intx, CMSYoungGenPerWorker, 64*M); // default max size of CMS young gen, per GC worker thread #endif // CPU_X86_VM_GLOBALS_X86_HPP
--- a/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -231,7 +231,7 @@ // Method handle invoker -// Dispatch a method of the form java.dyn.MethodHandles::invoke(...) +// Dispatch a method of the form java.lang.invoke.MethodHandles::invoke(...) address InterpreterGenerator::generate_method_handle_entry(void) { if (!EnableMethodHandles) { return generate_abstract_entry();
--- a/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -318,7 +318,7 @@ // Method handle invoker -// Dispatch a method of the form java.dyn.MethodHandles::invoke(...) +// Dispatch a method of the form java.lang.invoke.MethodHandles::invoke(...) address InterpreterGenerator::generate_method_handle_entry(void) { if (!EnableMethodHandles) { return generate_abstract_entry();
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -125,9 +125,9 @@ } // given the MethodType, find out where the MH argument is buried - __ load_heap_oop(rdx_temp, Address(rax_mtype, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, rdi_temp))); + __ load_heap_oop(rdx_temp, Address(rax_mtype, __ delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, rdi_temp))); Register rdx_vmslots = rdx_temp; - __ movl(rdx_vmslots, Address(rdx_temp, __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, rdi_temp))); + __ movl(rdx_vmslots, Address(rdx_temp, __ delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, rdi_temp))); __ movptr(rcx_recv, __ argument_address(rdx_vmslots)); trace_method_handle(_masm, "invokeExact"); @@ -154,11 +154,11 @@ rcx_argslot, rbx_temp, rdx_temp); // load up an adapter from the calling type (Java weaves this) - __ load_heap_oop(rdx_temp, Address(rax_mtype, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, rdi_temp))); + __ load_heap_oop(rdx_temp, Address(rax_mtype, __ delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, rdi_temp))); Register rdx_adapter = rdx_temp; - // __ load_heap_oop(rdx_adapter, Address(rdx_temp, java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes())); + // __ load_heap_oop(rdx_adapter, Address(rdx_temp, java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes())); // deal with old JDK versions: - __ lea(rdi_temp, Address(rdx_temp, __ delayed_value(java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes, rdi_temp))); + __ lea(rdi_temp, Address(rdx_temp, __ delayed_value(java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes, rdi_temp))); __ cmpptr(rdi_temp, rdx_temp); Label sorry_no_invoke_generic; __ jcc(Assembler::below, sorry_no_invoke_generic); @@ -371,16 +371,16 @@ // which conversion op types are implemented here? int MethodHandles::adapter_conversion_ops_supported_mask() { - return ((1<<sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY) - |(1<<sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW) - |(1<<sun_dyn_AdapterMethodHandle::OP_CHECK_CAST) - |(1<<sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM) - |(1<<sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM) - |(1<<sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS) - |(1<<sun_dyn_AdapterMethodHandle::OP_ROT_ARGS) - |(1<<sun_dyn_AdapterMethodHandle::OP_DUP_ARGS) - |(1<<sun_dyn_AdapterMethodHandle::OP_DROP_ARGS) - //|(1<<sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS) //BUG! + return ((1<<java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS) + |(1<<java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS) + //|(1<<java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS) //BUG! ); // FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS. } @@ -415,21 +415,21 @@ const Register rarg2_required = LP64_ONLY(j_rarg2) NOT_LP64(rdi); assert_different_registers(rarg0_code, rarg1_actual, rarg2_required, saved_last_sp); - guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); + guarantee(java_lang_invoke_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); // some handy addresses Address rbx_method_fie( rbx, methodOopDesc::from_interpreted_offset() ); Address rbx_method_fce( rbx, methodOopDesc::from_compiled_offset() ); - Address rcx_mh_vmtarget( rcx_recv, java_dyn_MethodHandle::vmtarget_offset_in_bytes() ); - Address rcx_dmh_vmindex( rcx_recv, sun_dyn_DirectMethodHandle::vmindex_offset_in_bytes() ); + Address rcx_mh_vmtarget( rcx_recv, java_lang_invoke_MethodHandle::vmtarget_offset_in_bytes() ); + Address rcx_dmh_vmindex( rcx_recv, java_lang_invoke_DirectMethodHandle::vmindex_offset_in_bytes() ); - Address rcx_bmh_vmargslot( rcx_recv, sun_dyn_BoundMethodHandle::vmargslot_offset_in_bytes() ); - Address rcx_bmh_argument( rcx_recv, sun_dyn_BoundMethodHandle::argument_offset_in_bytes() ); + Address rcx_bmh_vmargslot( rcx_recv, java_lang_invoke_BoundMethodHandle::vmargslot_offset_in_bytes() ); + Address rcx_bmh_argument( rcx_recv, java_lang_invoke_BoundMethodHandle::argument_offset_in_bytes() ); - Address rcx_amh_vmargslot( rcx_recv, sun_dyn_AdapterMethodHandle::vmargslot_offset_in_bytes() ); - Address rcx_amh_argument( rcx_recv, sun_dyn_AdapterMethodHandle::argument_offset_in_bytes() ); - Address rcx_amh_conversion( rcx_recv, sun_dyn_AdapterMethodHandle::conversion_offset_in_bytes() ); + Address rcx_amh_vmargslot( rcx_recv, java_lang_invoke_AdapterMethodHandle::vmargslot_offset_in_bytes() ); + Address rcx_amh_argument( rcx_recv, java_lang_invoke_AdapterMethodHandle::argument_offset_in_bytes() ); + Address rcx_amh_conversion( rcx_recv, java_lang_invoke_AdapterMethodHandle::conversion_offset_in_bytes() ); Address vmarg; // __ argument_address(vmargslot) const int java_mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes(); @@ -460,7 +460,7 @@ Register rbx_method = rbx_temp; Label L_no_method; - // FIXME: fill in _raise_exception_method with a suitable sun.dyn method + // FIXME: fill in _raise_exception_method with a suitable java.lang.invoke method __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method)); __ testptr(rbx_method, rbx_method); __ jccb(Assembler::zero, L_no_method);
--- a/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -31,7 +31,7 @@ #include "runtime/safepoint.hpp" -void Relocation::pd_set_data_value(address x, intptr_t o) { +void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { #ifdef AMD64 x += o; typedef Assembler::WhichOperand WhichOperand; @@ -40,19 +40,35 @@ which == Assembler::narrow_oop_operand || which == Assembler::imm_operand, "format unpacks ok"); if (which == Assembler::imm_operand) { - *pd_address_in_code() = x; + if (verify_only) { + assert(*pd_address_in_code() == x, "instructions must match"); + } else { + *pd_address_in_code() = x; + } } else if (which == Assembler::narrow_oop_operand) { address disp = Assembler::locate_operand(addr(), which); - *(int32_t*) disp = oopDesc::encode_heap_oop((oop)x); + if (verify_only) { + assert(*(uint32_t*) disp == oopDesc::encode_heap_oop((oop)x), "instructions must match"); + } else { + *(int32_t*) disp = oopDesc::encode_heap_oop((oop)x); + } } else { // Note: Use runtime_call_type relocations for call32_operand. address ip = addr(); address disp = Assembler::locate_operand(ip, which); address next_ip = Assembler::locate_next_instruction(ip); - *(int32_t*) disp = x - next_ip; + if (verify_only) { + assert(*(int32_t*) disp == (x - next_ip), "instructions must match"); + } else { + *(int32_t*) disp = x - next_ip; + } } #else - *pd_address_in_code() = x + o; + if (verify_only) { + assert(*pd_address_in_code() == (x + o), "instructions must match"); + } else { + *pd_address_in_code() = x + o; + } #endif // AMD64 }
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -3110,7 +3110,7 @@ __ profile_call(rsi); } - __ movptr(rcx_method_handle, Address(rax_callsite, __ delayed_value(java_dyn_CallSite::target_offset_in_bytes, rcx))); + __ movptr(rcx_method_handle, Address(rax_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, rcx))); __ null_check(rcx_method_handle); __ prepare_to_jump_from_interpreted(); __ jump_to_method_handle_entry(rcx_method_handle, rdx);
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -3145,7 +3145,7 @@ __ profile_call(r13); } - __ load_heap_oop(rcx_method_handle, Address(rax_callsite, __ delayed_value(java_dyn_CallSite::target_offset_in_bytes, rcx))); + __ load_heap_oop(rcx_method_handle, Address(rax_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, rcx))); __ null_check(rcx_method_handle); __ prepare_to_jump_from_interpreted(); __ jump_to_method_handle_entry(rcx_method_handle, rdx);
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -436,6 +436,13 @@ UseCountLeadingZerosInstruction = true; } } + + // On family 21 processors default is no sw prefetch + if ( cpu_family() == 21 ) { + if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) { + AllocatePrefetchStyle = 0; + } + } } if( is_intel() ) { // Intel cpus specific settings
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -281,7 +281,7 @@ if (method->is_static()) { istate->set_oop_temp( - method->constants()->pool_holder()->klass_part()->java_mirror()); + method->constants()->pool_holder()->java_mirror()); mirror = istate->oop_temp_addr(); *(dst++) = &mirror; } @@ -667,7 +667,7 @@ (BasicObjectLock *) stack->alloc(monitor_words * wordSize); oop object; if (method->is_static()) - object = method->constants()->pool_holder()->klass_part()->java_mirror(); + object = method->constants()->pool_holder()->java_mirror(); else object = (oop) locals[0]; monitor->set_obj(object);
--- a/hotspot/src/os/solaris/dtrace/libjvm_db.c Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c Fri Apr 01 16:55:47 2011 -0700 @@ -524,6 +524,8 @@ CHECK_FAIL(err); err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_constantPoolOopDesc, &nameSymbol); CHECK_FAIL(err); + // The symbol is a CPSlot and has lower bit set to indicate metadata + nameSymbol &= (~1); // remove metadata lsb err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2); CHECK_FAIL(err); nameString = (char*)calloc(nameSymbolLength + 1, 1); @@ -535,6 +537,7 @@ CHECK_FAIL(err); err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_constantPoolOopDesc, &signatureSymbol); CHECK_FAIL(err); + signatureSymbol &= (~1); // remove metadata lsb err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2); CHECK_FAIL(err); signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
--- a/hotspot/src/os/windows/vm/os_windows.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/os/windows/vm/os_windows.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -3297,9 +3297,14 @@ "possibility of dangling Thread pointer"); OSThread* osthread = thread->osthread(); - bool interrupted; - interrupted = osthread->interrupted(); - if (clear_interrupted == true) { + bool interrupted = osthread->interrupted(); + // There is no synchronization between the setting of the interrupt + // and it being cleared here. It is critical - see 6535709 - that + // we only clear the interrupt state, and reset the interrupt event, + // if we are going to report that we were indeed interrupted - else + // an interrupt can be "lost", leading to spurious wakeups or lost wakeups + // depending on the timing + if (interrupted && clear_interrupted) { osthread->set_interrupted(false); ResetEvent(osthread->interrupt_event()); } // Otherwise leave the interrupted state alone
--- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -209,7 +209,7 @@ // limit this optimization to current block if (value != NULL && in_current_block(conv)) { set_canonical(new StoreField(x->obj(), x->offset(), x->field(), value, x->is_static(), - x->state_before(), x->is_loaded(), x->is_initialized())); + x->state_before(), x->needs_patching())); return; } }
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1456,12 +1456,12 @@ BasicType field_type = field->type()->basic_type(); ValueType* type = as_ValueType(field_type); // call will_link again to determine if the field is valid. - const bool is_loaded = holder->is_loaded() && - field->will_link(method()->holder(), code); - const bool is_initialized = is_loaded && holder->is_initialized(); + const bool needs_patching = !holder->is_loaded() || + !field->will_link(method()->holder(), code) || + PatchALot; ValueStack* state_before = NULL; - if (!is_initialized || PatchALot) { + if (!holder->is_initialized() || needs_patching) { // save state before instruction for debug info when // deoptimization happens during patching state_before = copy_state_before(); @@ -1469,20 +1469,16 @@ Value obj = NULL; if (code == Bytecodes::_getstatic || code == Bytecodes::_putstatic) { - // commoning of class constants should only occur if the class is - // fully initialized and resolved in this constant pool. The will_link test - // above essentially checks if this class is resolved in this constant pool - // so, the is_initialized flag should be suffiect. if (state_before != NULL) { // build a patching constant - obj = new Constant(new ClassConstant(holder), state_before); + obj = new Constant(new InstanceConstant(holder->java_mirror()), state_before); } else { - obj = new Constant(new ClassConstant(holder)); + obj = new Constant(new InstanceConstant(holder->java_mirror())); } } - const int offset = is_loaded ? field->offset() : -1; + const int offset = !needs_patching ? field->offset() : -1; switch (code) { case Bytecodes::_getstatic: { // check for compile-time constants, i.e., initialized static final fields @@ -1509,7 +1505,7 @@ state_before = copy_state_for_exception(); } push(type, append(new LoadField(append(obj), offset, field, true, - state_before, is_loaded, is_initialized))); + state_before, needs_patching))); } break; } @@ -1518,7 +1514,7 @@ if (state_before == NULL) { state_before = copy_state_for_exception(); } - append(new StoreField(append(obj), offset, field, val, true, state_before, is_loaded, is_initialized)); + append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching)); } break; case Bytecodes::_getfield : @@ -1526,8 +1522,8 @@ if (state_before == NULL) { state_before = copy_state_for_exception(); } - LoadField* load = new LoadField(apop(), offset, field, false, state_before, is_loaded, true); - Value replacement = is_loaded ? _memory->load(load) : load; + LoadField* load = new LoadField(apop(), offset, field, false, state_before, needs_patching); + Value replacement = !needs_patching ? _memory->load(load) : load; if (replacement != load) { assert(replacement->is_linked() || !replacement->can_be_linked(), "should already by linked"); push(type, replacement); @@ -1542,8 +1538,8 @@ if (state_before == NULL) { state_before = copy_state_for_exception(); } - StoreField* store = new StoreField(apop(), offset, field, val, false, state_before, is_loaded, true); - if (is_loaded) store = _memory->store(store); + StoreField* store = new StoreField(apop(), offset, field, val, false, state_before, needs_patching); + if (!needs_patching) store = _memory->store(store); if (store != NULL) { append(store); }
--- a/hotspot/src/share/vm/c1/c1_Instruction.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -323,8 +323,6 @@ CanTrapFlag, DirectCompareFlag, IsEliminatedFlag, - IsInitializedFlag, - IsLoadedFlag, IsSafepointFlag, IsStaticFlag, IsStrictfpFlag, @@ -693,7 +691,7 @@ public: // creation AccessField(Value obj, int offset, ciField* field, bool is_static, - ValueStack* state_before, bool is_loaded, bool is_initialized) + ValueStack* state_before, bool needs_patching) : Instruction(as_ValueType(field->type()->basic_type()), state_before) , _obj(obj) , _offset(offset) @@ -701,16 +699,9 @@ , _explicit_null_check(NULL) { set_needs_null_check(!is_static); - set_flag(IsLoadedFlag, is_loaded); - set_flag(IsInitializedFlag, is_initialized); set_flag(IsStaticFlag, is_static); + set_flag(NeedsPatchingFlag, needs_patching); ASSERT_VALUES - if (!is_loaded || (PatchALot && !field->is_volatile())) { - // need to patch if the holder wasn't loaded or we're testing - // using PatchALot. Don't allow PatchALot for fields which are - // known to be volatile they aren't patchable. - set_flag(NeedsPatchingFlag, true); - } // pin of all instructions with memory access pin(); } @@ -721,11 +712,14 @@ ciField* field() const { return _field; } BasicType field_type() const { return _field->type()->basic_type(); } bool is_static() const { return check_flag(IsStaticFlag); } - bool is_loaded() const { return check_flag(IsLoadedFlag); } - bool is_initialized() const { return check_flag(IsInitializedFlag); } NullCheck* explicit_null_check() const { return _explicit_null_check; } bool needs_patching() const { return check_flag(NeedsPatchingFlag); } + // Unresolved getstatic and putstatic can cause initialization. + // Technically it occurs at the Constant that materializes the base + // of the static fields but it's simpler to model it here. + bool is_init_point() const { return is_static() && (needs_patching() || !_field->holder()->is_initialized()); } + // manipulation // Under certain circumstances, if a previous NullCheck instruction @@ -745,15 +739,15 @@ public: // creation LoadField(Value obj, int offset, ciField* field, bool is_static, - ValueStack* state_before, bool is_loaded, bool is_initialized) - : AccessField(obj, offset, field, is_static, state_before, is_loaded, is_initialized) + ValueStack* state_before, bool needs_patching) + : AccessField(obj, offset, field, is_static, state_before, needs_patching) {} ciType* declared_type() const; ciType* exact_type() const; // generic - HASHING2(LoadField, is_loaded() && !field()->is_volatile(), obj()->subst(), offset()) // cannot be eliminated if not yet loaded or if volatile + HASHING2(LoadField, !needs_patching() && !field()->is_volatile(), obj()->subst(), offset()) // cannot be eliminated if needs patching or if volatile }; @@ -764,8 +758,8 @@ public: // creation StoreField(Value obj, int offset, ciField* field, Value value, bool is_static, - ValueStack* state_before, bool is_loaded, bool is_initialized) - : AccessField(obj, offset, field, is_static, state_before, is_loaded, is_initialized) + ValueStack* state_before, bool needs_patching) + : AccessField(obj, offset, field, is_static, state_before, needs_patching) , _value(value) { set_flag(NeedsWriteBarrierFlag, as_ValueType(field_type())->is_object());
--- a/hotspot/src/share/vm/c1/c1_LIR.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1156,7 +1156,7 @@ return is_invokedynamic() // An invokedynamic is always a MethodHandle call site. || - (method()->holder()->name() == ciSymbol::java_dyn_MethodHandle() && + (method()->holder()->name() == ciSymbol::java_lang_invoke_MethodHandle() && methodOopDesc::is_method_handle_invoke_name(method()->name()->sid())); }
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1559,9 +1559,7 @@ (info ? new CodeEmitInfo(info) : NULL)); } - if (is_volatile) { - assert(!needs_patching && x->is_loaded(), - "how do we know it's volatile if it's not loaded"); + if (is_volatile && !needs_patching) { volatile_field_store(value.result(), address, info); } else { LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none; @@ -1627,9 +1625,7 @@ address = generate_address(object.result(), x->offset(), field_type); } - if (is_volatile) { - assert(!needs_patching && x->is_loaded(), - "how do we know it's volatile if it's not loaded"); + if (is_volatile && !needs_patching) { volatile_field_load(address, reg, info); } else { LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none; @@ -2516,7 +2512,7 @@ __ load(new LIR_Address(tmp, call_site_offset, T_OBJECT), tmp); // Load target MethodHandle from CallSite object. - __ load(new LIR_Address(tmp, java_dyn_CallSite::target_offset_in_bytes(), T_OBJECT), receiver); + __ load(new LIR_Address(tmp, java_lang_invoke_CallSite::target_offset_in_bytes(), T_OBJECT), receiver); __ call_dynamic(target, receiver, result_register, SharedRuntime::get_resolve_opt_virtual_call_stub(),
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -2703,7 +2703,7 @@ assert(_fpu_stack_allocator != NULL, "must be present"); opr = _fpu_stack_allocator->to_fpu_stack(opr); - assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrHi is used)"); + assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrLo is used)"); #endif #ifdef SPARC assert(opr->fpu_regnrLo() == opr->fpu_regnrHi() + 1, "assumed in calculation (only fpu_regnrHi is used)"); @@ -2715,7 +2715,12 @@ assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrHi is used)"); #endif +#ifdef VM_LITTLE_ENDIAN + VMReg rname_first = frame_map()->fpu_regname(opr->fpu_regnrLo()); +#else VMReg rname_first = frame_map()->fpu_regname(opr->fpu_regnrHi()); +#endif + #ifdef _LP64 first = new LocationValue(Location::new_reg_loc(Location::dbl, rname_first)); second = &_int_0_scope_value;
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -808,7 +808,7 @@ { klassOop klass = resolve_field_return_klass(caller_method, bci, CHECK); // Save a reference to the class that has to be checked for initialization init_klass = KlassHandle(THREAD, klass); - k = klass; + k = klass->java_mirror(); } break; case Bytecodes::_new:
--- a/hotspot/src/share/vm/c1/c1_ValueMap.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/c1/c1_ValueMap.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -141,7 +141,8 @@ // visitor functions void do_StoreField (StoreField* x) { - if (!x->is_initialized()) { + if (x->is_init_point()) { + // putstatic is an initialization point so treat it as a wide kill kill_memory(); } else { kill_field(x->field()); @@ -159,7 +160,8 @@ 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()) { + if (x->is_init_point()) { + // getstatic is an initialization point so treat it as a wide kill kill_memory(); } }
--- a/hotspot/src/share/vm/ci/ciCPCache.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/ci/ciCPCache.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,8 +46,7 @@ // ciCPCache::is_f1_null_at bool ciCPCache::is_f1_null_at(int index) { VM_ENTRY_MARK; - oop f1 = entry_at(index)->f1(); - return (f1 == NULL); + return entry_at(index)->is_f1_null(); }
--- a/hotspot/src/share/vm/ci/ciCallSite.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/ci/ciCallSite.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ // Return the target MethodHandle of this CallSite. ciMethodHandle* ciCallSite::get_target() const { VM_ENTRY_MARK; - oop method_handle_oop = java_dyn_CallSite::target(get_oop()); + oop method_handle_oop = java_lang_invoke_CallSite::target(get_oop()); return CURRENT_ENV->get_object(method_handle_oop)->as_method_handle(); }
--- a/hotspot/src/share/vm/ci/ciCallSite.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/ci/ciCallSite.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ // ciCallSite // -// The class represents a java.dyn.CallSite object. +// The class represents a java.lang.invoke.CallSite object. class ciCallSite : public ciInstance { public: ciCallSite(instanceHandle h_i) : ciInstance(h_i) {}
--- a/hotspot/src/share/vm/ci/ciField.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/ci/ciField.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -177,7 +177,7 @@ // Never trust strangely unstable finals: System.out, etc. return false; // Even if general trusting is disabled, trust system-built closures in these packages. - if (holder->is_in_package("java/dyn") || holder->is_in_package("sun/dyn")) + if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke")) return true; return TrustFinalNonStaticFields; } @@ -191,8 +191,9 @@ // Check to see if the field is constant. if (_holder->is_initialized() && this->is_final()) { if (!this->is_static()) { - // A field can be constant if it's a final static field or if it's - // a final non-static field of a trusted class ({java,sun}.dyn). + // A field can be constant if it's a final static field or if + // it's a final non-static field of a trusted class (classes in + // java.lang.invoke and sun.invoke packages and subpackages). if (trust_final_non_static_fields(_holder)) { _is_constant = true; return; @@ -212,7 +213,7 @@ // may change. The three examples are java.lang.System.in, // java.lang.System.out, and java.lang.System.err. - Handle k = _holder->get_klassOop(); + KlassHandle k = _holder->get_klassOop(); assert( SystemDictionary::System_klass() != NULL, "Check once per vm"); if( k() == SystemDictionary::System_klass() ) { // Check offsets for case 2: System.in, System.out, or System.err @@ -224,36 +225,38 @@ } } + Handle mirror = k->java_mirror(); + _is_constant = true; switch(type()->basic_type()) { case T_BYTE: - _constant_value = ciConstant(type()->basic_type(), k->byte_field(_offset)); + _constant_value = ciConstant(type()->basic_type(), mirror->byte_field(_offset)); break; case T_CHAR: - _constant_value = ciConstant(type()->basic_type(), k->char_field(_offset)); + _constant_value = ciConstant(type()->basic_type(), mirror->char_field(_offset)); break; case T_SHORT: - _constant_value = ciConstant(type()->basic_type(), k->short_field(_offset)); + _constant_value = ciConstant(type()->basic_type(), mirror->short_field(_offset)); break; case T_BOOLEAN: - _constant_value = ciConstant(type()->basic_type(), k->bool_field(_offset)); + _constant_value = ciConstant(type()->basic_type(), mirror->bool_field(_offset)); break; case T_INT: - _constant_value = ciConstant(type()->basic_type(), k->int_field(_offset)); + _constant_value = ciConstant(type()->basic_type(), mirror->int_field(_offset)); break; case T_FLOAT: - _constant_value = ciConstant(k->float_field(_offset)); + _constant_value = ciConstant(mirror->float_field(_offset)); break; case T_DOUBLE: - _constant_value = ciConstant(k->double_field(_offset)); + _constant_value = ciConstant(mirror->double_field(_offset)); break; case T_LONG: - _constant_value = ciConstant(k->long_field(_offset)); + _constant_value = ciConstant(mirror->long_field(_offset)); break; case T_OBJECT: case T_ARRAY: { - oop o = k->obj_field(_offset); + oop o = mirror->obj_field(_offset); // A field will be "constant" if it is known always to be // a non-null reference to an instance of a particular class,
--- a/hotspot/src/share/vm/ci/ciInstance.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/ci/ciInstance.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -138,3 +138,9 @@ st->print(" type="); klass()->print(st); } + + +ciKlass* ciInstance::java_lang_Class_klass() { + VM_ENTRY_MARK; + return CURRENT_ENV->get_object(java_lang_Class::as_klassOop(get_oop()))->as_klass(); +}
--- a/hotspot/src/share/vm/ci/ciInstance.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/ci/ciInstance.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,6 +64,8 @@ // Constant value of a field at the specified offset. ciConstant field_value_by_offset(int field_offset); + + ciKlass* java_lang_Class_klass(); }; #endif // SHARE_VM_CI_CIINSTANCE_HPP
--- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,7 +85,6 @@ if (h_k() != SystemDictionary::Object_klass()) { super(); } - java_mirror(); //compute_nonstatic_fields(); // done outside of constructor } @@ -320,6 +319,9 @@ // Get the instance of java.lang.Class corresponding to this klass. // Cache it on this->_java_mirror. ciInstance* ciInstanceKlass::java_mirror() { + if (is_shared()) { + return ciKlass::java_mirror(); + } if (_java_mirror == NULL) { _java_mirror = ciKlass::java_mirror(); }
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/ci/ciMethod.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -769,7 +769,7 @@ // signature-polymorphic MethodHandle methods, invokeExact or invokeGeneric. bool ciMethod::is_method_handle_invoke() const { if (!is_loaded()) { - bool flag = (holder()->name() == ciSymbol::java_dyn_MethodHandle() && + bool flag = (holder()->name() == ciSymbol::java_lang_invoke_MethodHandle() && methodOopDesc::is_method_handle_invoke_name(name()->sid())); return flag; }
--- a/hotspot/src/share/vm/ci/ciMethodHandle.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/ci/ciMethodHandle.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ // ciMethodHandle // -// The class represents a java.dyn.MethodHandle object. +// The class represents a java.lang.invoke.MethodHandle object. class ciMethodHandle : public ciInstance { private: ciMethod* _callee;
--- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -342,9 +342,9 @@ return new (arena()) ciMethodData(h_md); } else if (o->is_instance()) { instanceHandle h_i(THREAD, (instanceOop)o); - if (java_dyn_CallSite::is_instance(o)) + if (java_lang_invoke_CallSite::is_instance(o)) return new (arena()) ciCallSite(h_i); - else if (java_dyn_MethodHandle::is_instance(o)) + else if (java_lang_invoke_MethodHandle::is_instance(o)) return new (arena()) ciMethodHandle(h_i); else return new (arena()) ciInstance(h_i); @@ -663,7 +663,7 @@ if (key->is_perm() && _non_perm_count == 0) { return emptyBucket; } else if (key->is_instance()) { - if (key->klass() == SystemDictionary::Class_klass()) { + if (key->klass() == SystemDictionary::Class_klass() && JavaObjectsInPerm) { // class mirror instances are always perm return emptyBucket; }
--- a/hotspot/src/share/vm/ci/ciStreams.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/ci/ciStreams.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -380,7 +380,7 @@ bool ignore; // report as InvokeDynamic for invokedynamic, which is syntactically classless if (cur_bc() == Bytecodes::_invokedynamic) - return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_InvokeDynamic(), false); + return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_lang_invoke_InvokeDynamic(), false); return CURRENT_ENV->get_klass_by_index(cpool, get_method_holder_index(), ignore, _holder); }
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ #include "memory/universe.inline.hpp" #include "oops/constantPoolOop.hpp" #include "oops/instanceKlass.hpp" +#include "oops/instanceMirrorKlass.hpp" #include "oops/klass.inline.hpp" #include "oops/klassOop.hpp" #include "oops/klassVtable.hpp" @@ -146,12 +147,14 @@ break; case JVM_CONSTANT_MethodHandle : case JVM_CONSTANT_MethodType : - if (!EnableMethodHandles || - _major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { + if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { classfile_parse_error( - (!EnableMethodHandles ? - "This JVM does not support constant tag %u in class file %s" : - "Class file version does not support constant tag %u in class file %s"), + "Class file version does not support constant tag %u in class file %s", + tag, CHECK); + } + if (!EnableMethodHandles) { + classfile_parse_error( + "This JVM does not support constant tag %u in class file %s", tag, CHECK); } if (tag == JVM_CONSTANT_MethodHandle) { @@ -170,12 +173,14 @@ case JVM_CONSTANT_InvokeDynamicTrans : // this tag appears only in old classfiles case JVM_CONSTANT_InvokeDynamic : { - if (!EnableInvokeDynamic || - _major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { + if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) { classfile_parse_error( - (!EnableInvokeDynamic ? - "This JVM does not support constant tag %u in class file %s" : - "Class file version does not support constant tag %u in class file %s"), + "Class file version does not support constant tag %u in class file %s", + tag, CHECK); + } + if (!EnableInvokeDynamic) { + classfile_parse_error( + "This JVM does not support constant tag %u in class file %s", tag, CHECK); } cfs->guarantee_more(5, CHECK); // bsm_index, nt, tag/access_flags @@ -1616,8 +1621,13 @@ AccessFlags access_flags; if (name == vmSymbols::class_initializer_name()) { - // We ignore the access flags for a class initializer. (JVM Spec. p. 116) - flags = JVM_ACC_STATIC; + // We ignore the other access flags for a valid class initializer. + // (JVM Spec 2nd ed., chapter 4.6) + if (_major_version < 51) { // backward compatibility + flags = JVM_ACC_STATIC; + } else if ((flags & JVM_ACC_STATIC) == JVM_ACC_STATIC) { + flags &= JVM_ACC_STATIC | JVM_ACC_STRICT; + } } else { verify_legal_method_modifiers(flags, is_interface, name, CHECK_(nullHandle)); } @@ -2597,54 +2607,6 @@ } -static void initialize_static_field(fieldDescriptor* fd, TRAPS) { - KlassHandle h_k (THREAD, fd->field_holder()); - assert(h_k.not_null() && fd->is_static(), "just checking"); - if (fd->has_initial_value()) { - BasicType t = fd->field_type(); - switch (t) { - case T_BYTE: - h_k()->byte_field_put(fd->offset(), fd->int_initial_value()); - break; - case T_BOOLEAN: - h_k()->bool_field_put(fd->offset(), fd->int_initial_value()); - break; - case T_CHAR: - h_k()->char_field_put(fd->offset(), fd->int_initial_value()); - break; - case T_SHORT: - h_k()->short_field_put(fd->offset(), fd->int_initial_value()); - break; - case T_INT: - h_k()->int_field_put(fd->offset(), fd->int_initial_value()); - break; - case T_FLOAT: - h_k()->float_field_put(fd->offset(), fd->float_initial_value()); - break; - case T_DOUBLE: - h_k()->double_field_put(fd->offset(), fd->double_initial_value()); - break; - case T_LONG: - h_k()->long_field_put(fd->offset(), fd->long_initial_value()); - break; - case T_OBJECT: - { - #ifdef ASSERT - TempNewSymbol sym = SymbolTable::new_symbol("Ljava/lang/String;", CHECK); - assert(fd->signature() == sym, "just checking"); - #endif - oop string = fd->string_initial_value(CHECK); - h_k()->obj_field_put(fd->offset(), string); - } - break; - default: - THROW_MSG(vmSymbols::java_lang_ClassFormatError(), - "Illegal ConstantValue attribute in class file"); - } - } -} - - void ClassFileParser::java_lang_ref_Reference_fix_pre(typeArrayHandle* fields_ptr, constantPoolHandle cp, FieldAllocationCount *fac_ptr, TRAPS) { // This code is for compatibility with earlier jdk's that do not @@ -2760,8 +2722,8 @@ } -void ClassFileParser::java_lang_Class_fix_pre(objArrayHandle* methods_ptr, - FieldAllocationCount *fac_ptr, TRAPS) { +void ClassFileParser::java_lang_Class_fix_pre(int* nonstatic_field_size, + FieldAllocationCount *fac_ptr) { // Add fake fields for java.lang.Class instances // // This is not particularly nice. We should consider adding a @@ -2778,10 +2740,13 @@ // versions because when the offsets are computed at bootstrap // time we don't know yet which version of the JDK we're running in. - // The values below are fake but will force two non-static oop fields and + // The values below are fake but will force three non-static oop fields and // a corresponding non-static oop map block to be allocated. const int extra = java_lang_Class::number_of_fake_oop_fields; fac_ptr->nonstatic_oop_count += extra; + + // Reserve some leading space for fake ints + *nonstatic_field_size += align_size_up(java_lang_Class::hc_number_of_fake_int_fields * BytesPerInt, heapOopSize) / heapOopSize; } @@ -2797,11 +2762,11 @@ // Force MethodHandle.vmentry to be an unmanaged pointer. // There is no way for a classfile to express this, so we must help it. -void ClassFileParser::java_dyn_MethodHandle_fix_pre(constantPoolHandle cp, +void ClassFileParser::java_lang_invoke_MethodHandle_fix_pre(constantPoolHandle cp, typeArrayHandle fields, FieldAllocationCount *fac_ptr, TRAPS) { - // Add fake fields for java.dyn.MethodHandle instances + // Add fake fields for java.lang.invoke.MethodHandle instances // // This is not particularly nice, but since there is no way to express // a native wordSize field in Java, we must do it at this level. @@ -2818,9 +2783,10 @@ } } + if (AllowTransitionalJSR292 && word_sig_index == 0) return; if (word_sig_index == 0) THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), - "missing I or J signature (for vmentry) in java.dyn.MethodHandle"); + "missing I or J signature (for vmentry) in java.lang.invoke.MethodHandle"); // Find vmentry field and change the signature. bool found_vmentry = false; @@ -2857,9 +2823,10 @@ } } + if (AllowTransitionalJSR292 && !found_vmentry) return; if (!found_vmentry) THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), - "missing vmentry byte field in java.dyn.MethodHandle"); + "missing vmentry byte field in java.lang.invoke.MethodHandle"); } @@ -3194,9 +3161,7 @@ int next_nonstatic_field_offset; // Calculate the starting byte offsets - next_static_oop_offset = (instanceKlass::header_size() + - align_object_offset(vtable_size) + - align_object_offset(itable_size)) * wordSize; + next_static_oop_offset = instanceMirrorKlass::offset_of_static_fields(); next_static_double_offset = next_static_oop_offset + (fac.static_oop_count * heapOopSize); if ( fac.static_double_count && @@ -3215,18 +3180,28 @@ fac.static_byte_count ), wordSize ); static_field_size = (next_static_type_offset - next_static_oop_offset) / wordSize; - first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() + - nonstatic_field_size * heapOopSize; - next_nonstatic_field_offset = first_nonstatic_field_offset; // Add fake fields for java.lang.Class instances (also see below) if (class_name == vmSymbols::java_lang_Class() && class_loader.is_null()) { - java_lang_Class_fix_pre(&methods, &fac, CHECK_(nullHandle)); + java_lang_Class_fix_pre(&nonstatic_field_size, &fac); } - // adjust the vmentry field declaration in java.dyn.MethodHandle - if (EnableMethodHandles && class_name == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) { - java_dyn_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); + first_nonstatic_field_offset = instanceOopDesc::base_offset_in_bytes() + + nonstatic_field_size * heapOopSize; + next_nonstatic_field_offset = first_nonstatic_field_offset; + + // adjust the vmentry field declaration in java.lang.invoke.MethodHandle + if (EnableMethodHandles && class_name == vmSymbols::java_lang_invoke_MethodHandle() && class_loader.is_null()) { + java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); + } + if (AllowTransitionalJSR292 && + EnableMethodHandles && class_name == vmSymbols::java_dyn_MethodHandle() && class_loader.is_null()) { + java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); + } + if (AllowTransitionalJSR292 && + EnableMethodHandles && class_name == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) { + // allow vmentry field in MethodHandleImpl also + java_lang_invoke_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle)); } // Add a fake "discovered" field if it is not present @@ -3546,7 +3521,7 @@ } // We can now create the basic klassOop for this klass - klassOop ik = oopFactory::new_instanceKlass(vtable_size, itable_size, + klassOop ik = oopFactory::new_instanceKlass(name, vtable_size, itable_size, static_field_size, total_oop_map_count, rt, CHECK_(nullHandle)); @@ -3568,7 +3543,7 @@ this_klass->set_class_loader(class_loader()); this_klass->set_nonstatic_field_size(nonstatic_field_size); this_klass->set_has_nonstatic_fields(has_nonstatic_fields); - this_klass->set_static_oop_field_size(fac.static_oop_count); + this_klass->set_static_oop_field_count(fac.static_oop_count); cp->set_pool_holder(this_klass()); error_handler.set_in_error(false); // turn off error handler for cp this_klass->set_constants(cp()); @@ -3629,9 +3604,6 @@ // Make sure this is the end of class file stream guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle)); - // Initialize static fields - this_klass->do_local_static_fields(&initialize_static_field, CHECK_(nullHandle)); - // VerifyOops believes that once this has been set, the object is completely loaded. // Compute transitive closure of interfaces this class implements this_klass->set_transitive_interfaces(transitive_interfaces()); @@ -3665,6 +3637,9 @@ check_illegal_static_method(this_klass, CHECK_(nullHandle)); } + // Allocate mirror and initialize static fields + java_lang_Class::create_mirror(this_klass, CHECK_(nullHandle)); + ClassLoadingService::notify_class_loaded(instanceKlass::cast(this_klass()), false /* not shared class */);
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/classfile/classFileParser.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -154,17 +154,18 @@ // Add the "discovered" field to java.lang.ref.Reference if // it does not exist. void java_lang_ref_Reference_fix_pre(typeArrayHandle* fields_ptr, - constantPoolHandle cp, FieldAllocationCount *fac_ptr, TRAPS); + constantPoolHandle cp, + FieldAllocationCount *fac_ptr, TRAPS); // Adjust the field allocation counts for java.lang.Class to add // fake fields. - void java_lang_Class_fix_pre(objArrayHandle* methods_ptr, - FieldAllocationCount *fac_ptr, TRAPS); + void java_lang_Class_fix_pre(int* nonstatic_field_size, + FieldAllocationCount *fac_ptr); // Adjust the next_nonstatic_oop_offset to place the fake fields // before any Java fields. void java_lang_Class_fix_post(int* next_nonstatic_oop_offset); - // Adjust the field allocation counts for java.dyn.MethodHandle to add + // Adjust the field allocation counts for java.lang.invoke.MethodHandle to add // a fake address (void*) field. - void java_dyn_MethodHandle_fix_pre(constantPoolHandle cp, + void java_lang_invoke_MethodHandle_fix_pre(constantPoolHandle cp, typeArrayHandle fields, FieldAllocationCount *fac_ptr, TRAPS);
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" #include "oops/instanceKlass.hpp" +#include "oops/instanceMirrorKlass.hpp" #include "oops/klass.hpp" #include "oops/klassOop.hpp" #include "oops/methodOop.hpp" @@ -66,6 +67,28 @@ return ik->find_local_field(name_symbol, signature_symbol, fd); } +static bool find_hacked_field(instanceKlass* ik, + Symbol* name_symbol, Symbol* signature_symbol, + fieldDescriptor* fd, + bool allow_super = false) { + bool found = find_field(ik, name_symbol, signature_symbol, fd, allow_super); + if (!found && AllowTransitionalJSR292) { + Symbol* backup_sig = SystemDictionary::find_backup_signature(signature_symbol); + if (backup_sig != NULL) { + found = find_field(ik, name_symbol, backup_sig, fd, allow_super); + if (TraceMethodHandles) { + ResourceMark rm; + tty->print_cr("MethodHandles: %s.%s: backup for %s => %s%s", + ik->name()->as_C_string(), name_symbol->as_C_string(), + signature_symbol->as_C_string(), backup_sig->as_C_string(), + (found ? "" : " (NOT FOUND)")); + } + } + } + return found; +} +#define find_field find_hacked_field /* remove after AllowTransitionalJSR292 */ + // Helpful routine for computing field offsets at run time rather than hardcoding them static void compute_offset(int &dest_offset, @@ -139,7 +162,7 @@ } Handle java_lang_String::create_tenured_from_unicode(jchar* unicode, int length, TRAPS) { - return basic_create_from_unicode(unicode, length, true, CHECK_NH); + return basic_create_from_unicode(unicode, length, JavaObjectsInPerm, CHECK_NH); } oop java_lang_String::create_oop_from_unicode(jchar* unicode, int length, TRAPS) { @@ -369,6 +392,75 @@ } } +static void initialize_static_field(fieldDescriptor* fd, TRAPS) { + Handle mirror (THREAD, fd->field_holder()->java_mirror()); + assert(mirror.not_null() && fd->is_static(), "just checking"); + if (fd->has_initial_value()) { + BasicType t = fd->field_type(); + switch (t) { + case T_BYTE: + mirror()->byte_field_put(fd->offset(), fd->int_initial_value()); + break; + case T_BOOLEAN: + mirror()->bool_field_put(fd->offset(), fd->int_initial_value()); + break; + case T_CHAR: + mirror()->char_field_put(fd->offset(), fd->int_initial_value()); + break; + case T_SHORT: + mirror()->short_field_put(fd->offset(), fd->int_initial_value()); + break; + case T_INT: + mirror()->int_field_put(fd->offset(), fd->int_initial_value()); + break; + case T_FLOAT: + mirror()->float_field_put(fd->offset(), fd->float_initial_value()); + break; + case T_DOUBLE: + mirror()->double_field_put(fd->offset(), fd->double_initial_value()); + break; + case T_LONG: + mirror()->long_field_put(fd->offset(), fd->long_initial_value()); + break; + case T_OBJECT: + { + #ifdef ASSERT + TempNewSymbol sym = SymbolTable::new_symbol("Ljava/lang/String;", CHECK); + assert(fd->signature() == sym, "just checking"); + #endif + oop string = fd->string_initial_value(CHECK); + mirror()->obj_field_put(fd->offset(), string); + } + break; + default: + THROW_MSG(vmSymbols::java_lang_ClassFormatError(), + "Illegal ConstantValue attribute in class file"); + } + } +} + + +// During bootstrap, java.lang.Class wasn't loaded so static field +// offsets were computed without the size added it. Go back and +// update all the static field offsets to included the size. +static void fixup_static_field(fieldDescriptor* fd, TRAPS) { + if (fd->is_static()) { + int real_offset = fd->offset() + instanceMirrorKlass::offset_of_static_fields(); + typeArrayOop fields = instanceKlass::cast(fd->field_holder())->fields(); + fields->short_at_put(fd->index() + instanceKlass::low_offset, extract_low_short_from_int(real_offset)); + fields->short_at_put(fd->index() + instanceKlass::high_offset, extract_high_short_from_int(real_offset)); + } +} + +void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) { + assert(instanceMirrorKlass::offset_of_static_fields() != 0, "must have been computed already"); + + if (k->oop_is_instance()) { + // Fixup the offsets + instanceKlass::cast(k())->do_local_static_fields(&fixup_static_field, CHECK); + } + create_mirror(k, CHECK); +} oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) { assert(k->java_mirror() == NULL, "should only assign mirror once"); @@ -378,12 +470,17 @@ // class is put into the system dictionary. int computed_modifiers = k->compute_modifier_flags(CHECK_0); k->set_modifier_flags(computed_modifiers); - if (SystemDictionary::Class_klass_loaded()) { + if (SystemDictionary::Class_klass_loaded() && (k->oop_is_instance() || k->oop_is_javaArray())) { // Allocate mirror (java.lang.Class instance) - Handle mirror = instanceKlass::cast(SystemDictionary::Class_klass())->allocate_permanent_instance(CHECK_0); + Handle mirror = instanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK_0); // Setup indirections mirror->obj_field_put(klass_offset, k()); k->set_java_mirror(mirror()); + + instanceMirrorKlass* mk = instanceMirrorKlass::cast(mirror->klass()); + java_lang_Class::set_oop_size(mirror(), mk->instance_size(k)); + java_lang_Class::set_static_oop_field_count(mirror(), mk->compute_static_oop_field_count(mirror())); + // It might also have a component mirror. This mirror must already exist. if (k->oop_is_javaArray()) { Handle comp_mirror; @@ -406,6 +503,9 @@ arrayKlass::cast(k->as_klassOop())->set_component_mirror(comp_mirror()); set_array_klass(comp_mirror(), k->as_klassOop()); } + } else if (k->oop_is_instance()) { + // Initialize static fields + instanceKlass::cast(k())->do_local_static_fields(&initialize_static_field, CHECK_NULL); } return mirror(); } else { @@ -414,21 +514,46 @@ } + +int java_lang_Class::oop_size(oop java_class) { + assert(oop_size_offset != 0, "must be set"); + return java_class->int_field(oop_size_offset); +} +void java_lang_Class::set_oop_size(oop java_class, int size) { + assert(oop_size_offset != 0, "must be set"); + java_class->int_field_put(oop_size_offset, size); +} +int java_lang_Class::static_oop_field_count(oop java_class) { + assert(static_oop_field_count_offset != 0, "must be set"); + return java_class->int_field(static_oop_field_count_offset); +} +void java_lang_Class::set_static_oop_field_count(oop java_class, int size) { + assert(static_oop_field_count_offset != 0, "must be set"); + java_class->int_field_put(static_oop_field_count_offset, size); +} + + + + oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) { // This should be improved by adding a field at the Java level or by // introducing a new VM klass (see comment in ClassFileParser) - oop java_class = instanceKlass::cast(SystemDictionary::Class_klass())->allocate_permanent_instance(CHECK_0); + oop java_class = instanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance((oop)NULL, CHECK_0); if (type != T_VOID) { klassOop aklass = Universe::typeArrayKlassObj(type); assert(aklass != NULL, "correct bootstrap"); set_array_klass(java_class, aklass); } + instanceMirrorKlass* mk = instanceMirrorKlass::cast(SystemDictionary::Class_klass()); + java_lang_Class::set_oop_size(java_class, mk->instance_size(oop(NULL))); + java_lang_Class::set_static_oop_field_count(java_class, 0); return java_class; } klassOop java_lang_Class::as_klassOop(oop java_class) { //%note memory_2 + assert(java_lang_Class::is_instance(java_class), "must be a Class object"); klassOop k = klassOop(java_class->obj_field(klass_offset)); assert(k == NULL || k->is_klass(), "type check"); return k; @@ -2130,7 +2255,7 @@ // Support for java_lang_ref_Reference oop java_lang_ref_Reference::pending_list_lock() { instanceKlass* ik = instanceKlass::cast(SystemDictionary::Reference_klass()); - char *addr = (((char *)ik->start_of_static_fields()) + static_lock_offset); + address addr = ik->static_field_addr(static_lock_offset); if (UseCompressedOops) { return oopDesc::load_decode_heap_oop((narrowOop *)addr); } else { @@ -2140,7 +2265,7 @@ HeapWord *java_lang_ref_Reference::pending_list_addr() { instanceKlass* ik = instanceKlass::cast(SystemDictionary::Reference_klass()); - char *addr = (((char *)ik->start_of_static_fields()) + static_pending_offset); + address addr = ik->static_field_addr(static_pending_offset); // XXX This might not be HeapWord aligned, almost rather be char *. return (HeapWord*)addr; } @@ -2163,54 +2288,54 @@ jlong java_lang_ref_SoftReference::clock() { instanceKlass* ik = instanceKlass::cast(SystemDictionary::SoftReference_klass()); - int offset = ik->offset_of_static_fields() + static_clock_offset; - - return SystemDictionary::SoftReference_klass()->long_field(offset); + jlong* offset = (jlong*)ik->static_field_addr(static_clock_offset); + return *offset; } void java_lang_ref_SoftReference::set_clock(jlong value) { instanceKlass* ik = instanceKlass::cast(SystemDictionary::SoftReference_klass()); - int offset = ik->offset_of_static_fields() + static_clock_offset; - - SystemDictionary::SoftReference_klass()->long_field_put(offset, value); + jlong* offset = (jlong*)ik->static_field_addr(static_clock_offset); + *offset = value; } -// Support for java_dyn_MethodHandle - -int java_dyn_MethodHandle::_type_offset; -int java_dyn_MethodHandle::_vmtarget_offset; -int java_dyn_MethodHandle::_vmentry_offset; -int java_dyn_MethodHandle::_vmslots_offset; - -int sun_dyn_MemberName::_clazz_offset; -int sun_dyn_MemberName::_name_offset; -int sun_dyn_MemberName::_type_offset; -int sun_dyn_MemberName::_flags_offset; -int sun_dyn_MemberName::_vmtarget_offset; -int sun_dyn_MemberName::_vmindex_offset; - -int sun_dyn_DirectMethodHandle::_vmindex_offset; - -int sun_dyn_BoundMethodHandle::_argument_offset; -int sun_dyn_BoundMethodHandle::_vmargslot_offset; - -int sun_dyn_AdapterMethodHandle::_conversion_offset; - -void java_dyn_MethodHandle::compute_offsets() { +// Support for java_lang_invoke_MethodHandle + +int java_lang_invoke_MethodHandle::_type_offset; +int java_lang_invoke_MethodHandle::_vmtarget_offset; +int java_lang_invoke_MethodHandle::_vmentry_offset; +int java_lang_invoke_MethodHandle::_vmslots_offset; + +int java_lang_invoke_MemberName::_clazz_offset; +int java_lang_invoke_MemberName::_name_offset; +int java_lang_invoke_MemberName::_type_offset; +int java_lang_invoke_MemberName::_flags_offset; +int java_lang_invoke_MemberName::_vmtarget_offset; +int java_lang_invoke_MemberName::_vmindex_offset; + +int java_lang_invoke_DirectMethodHandle::_vmindex_offset; + +int java_lang_invoke_BoundMethodHandle::_argument_offset; +int java_lang_invoke_BoundMethodHandle::_vmargslot_offset; + +int java_lang_invoke_AdapterMethodHandle::_conversion_offset; + +void java_lang_invoke_MethodHandle::compute_offsets() { klassOop k = SystemDictionary::MethodHandle_klass(); if (k != NULL && EnableMethodHandles) { - compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_dyn_MethodType_signature(), true); - compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature(), true); - compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::machine_word_signature(), true); + bool allow_super = false; + if (AllowTransitionalJSR292) allow_super = true; // temporary, to access java.dyn.MethodHandleImpl + compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_lang_invoke_MethodType_signature(), allow_super); + compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature(), allow_super); + compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::machine_word_signature(), allow_super); // Note: MH.vmslots (if it is present) is a hoisted copy of MH.type.form.vmslots. // It is optional pending experiments to keep or toss. - compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true); + compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), allow_super); } } -void sun_dyn_MemberName::compute_offsets() { +void java_lang_invoke_MemberName::compute_offsets() { klassOop k = SystemDictionary::MemberName_klass(); if (k != NULL && EnableMethodHandles) { compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); @@ -2222,14 +2347,14 @@ } } -void sun_dyn_DirectMethodHandle::compute_offsets() { +void java_lang_invoke_DirectMethodHandle::compute_offsets() { klassOop k = SystemDictionary::DirectMethodHandle_klass(); if (k != NULL && EnableMethodHandles) { compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature(), true); } } -void sun_dyn_BoundMethodHandle::compute_offsets() { +void java_lang_invoke_BoundMethodHandle::compute_offsets() { klassOop k = SystemDictionary::BoundMethodHandle_klass(); if (k != NULL && EnableMethodHandles) { compute_offset(_vmargslot_offset, k, vmSymbols::vmargslot_name(), vmSymbols::int_signature(), true); @@ -2237,22 +2362,22 @@ } } -void sun_dyn_AdapterMethodHandle::compute_offsets() { +void java_lang_invoke_AdapterMethodHandle::compute_offsets() { klassOop k = SystemDictionary::AdapterMethodHandle_klass(); if (k != NULL && EnableMethodHandles) { compute_offset(_conversion_offset, k, vmSymbols::conversion_name(), vmSymbols::int_signature(), true); } } -oop java_dyn_MethodHandle::type(oop mh) { +oop java_lang_invoke_MethodHandle::type(oop mh) { return mh->obj_field(_type_offset); } -void java_dyn_MethodHandle::set_type(oop mh, oop mtype) { +void java_lang_invoke_MethodHandle::set_type(oop mh, oop mtype) { mh->obj_field_put(_type_offset, mtype); } -int java_dyn_MethodHandle::vmslots(oop mh) { +int java_lang_invoke_MethodHandle::vmslots(oop mh) { int vmslots_offset = _vmslots_offset; if (vmslots_offset != 0) { #ifdef ASSERT @@ -2267,7 +2392,7 @@ } // if MH.vmslots exists, hoist into it the value of type.form.vmslots -void java_dyn_MethodHandle::init_vmslots(oop mh) { +void java_lang_invoke_MethodHandle::init_vmslots(oop mh) { int vmslots_offset = _vmslots_offset; if (vmslots_offset != 0) { mh->int_field_put(vmslots_offset, compute_vmslots(mh)); @@ -2276,20 +2401,20 @@ // fetch type.form.vmslots, which is the number of JVM stack slots // required to carry the arguments of this MH -int java_dyn_MethodHandle::compute_vmslots(oop mh) { +int java_lang_invoke_MethodHandle::compute_vmslots(oop mh) { oop mtype = type(mh); if (mtype == NULL) return 0; // Java code would get NPE - oop form = java_dyn_MethodType::form(mtype); + oop form = java_lang_invoke_MethodType::form(mtype); if (form == NULL) return 0; // Java code would get NPE - return java_dyn_MethodTypeForm::vmslots(form); + return java_lang_invoke_MethodTypeForm::vmslots(form); } // fetch the low-level entry point for this mh -MethodHandleEntry* java_dyn_MethodHandle::vmentry(oop mh) { +MethodHandleEntry* java_lang_invoke_MethodHandle::vmentry(oop mh) { return (MethodHandleEntry*) mh->address_field(_vmentry_offset); } -void java_dyn_MethodHandle::set_vmentry(oop mh, MethodHandleEntry* me) { +void java_lang_invoke_MethodHandle::set_vmentry(oop mh, MethodHandleEntry* me) { assert(_vmentry_offset != 0, "must be present"); // This is always the final step that initializes a valid method handle: @@ -2303,123 +2428,123 @@ /// MemberName accessors -oop sun_dyn_MemberName::clazz(oop mname) { +oop java_lang_invoke_MemberName::clazz(oop mname) { assert(is_instance(mname), "wrong type"); return mname->obj_field(_clazz_offset); } -void sun_dyn_MemberName::set_clazz(oop mname, oop clazz) { +void java_lang_invoke_MemberName::set_clazz(oop mname, oop clazz) { assert(is_instance(mname), "wrong type"); mname->obj_field_put(_clazz_offset, clazz); } -oop sun_dyn_MemberName::name(oop mname) { +oop java_lang_invoke_MemberName::name(oop mname) { assert(is_instance(mname), "wrong type"); return mname->obj_field(_name_offset); } -void sun_dyn_MemberName::set_name(oop mname, oop name) { +void java_lang_invoke_MemberName::set_name(oop mname, oop name) { assert(is_instance(mname), "wrong type"); mname->obj_field_put(_name_offset, name); } -oop sun_dyn_MemberName::type(oop mname) { +oop java_lang_invoke_MemberName::type(oop mname) { assert(is_instance(mname), "wrong type"); return mname->obj_field(_type_offset); } -void sun_dyn_MemberName::set_type(oop mname, oop type) { +void java_lang_invoke_MemberName::set_type(oop mname, oop type) { assert(is_instance(mname), "wrong type"); mname->obj_field_put(_type_offset, type); } -int sun_dyn_MemberName::flags(oop mname) { +int java_lang_invoke_MemberName::flags(oop mname) { assert(is_instance(mname), "wrong type"); return mname->int_field(_flags_offset); } -void sun_dyn_MemberName::set_flags(oop mname, int flags) { +void java_lang_invoke_MemberName::set_flags(oop mname, int flags) { assert(is_instance(mname), "wrong type"); mname->int_field_put(_flags_offset, flags); } -oop sun_dyn_MemberName::vmtarget(oop mname) { +oop java_lang_invoke_MemberName::vmtarget(oop mname) { assert(is_instance(mname), "wrong type"); return mname->obj_field(_vmtarget_offset); } -void sun_dyn_MemberName::set_vmtarget(oop mname, oop ref) { +void java_lang_invoke_MemberName::set_vmtarget(oop mname, oop ref) { assert(is_instance(mname), "wrong type"); mname->obj_field_put(_vmtarget_offset, ref); } -int sun_dyn_MemberName::vmindex(oop mname) { +int java_lang_invoke_MemberName::vmindex(oop mname) { assert(is_instance(mname), "wrong type"); return mname->int_field(_vmindex_offset); } -void sun_dyn_MemberName::set_vmindex(oop mname, int index) { +void java_lang_invoke_MemberName::set_vmindex(oop mname, int index) { assert(is_instance(mname), "wrong type"); mname->int_field_put(_vmindex_offset, index); } -oop java_dyn_MethodHandle::vmtarget(oop mh) { +oop java_lang_invoke_MethodHandle::vmtarget(oop mh) { assert(is_instance(mh), "MH only"); return mh->obj_field(_vmtarget_offset); } -void java_dyn_MethodHandle::set_vmtarget(oop mh, oop ref) { +void java_lang_invoke_MethodHandle::set_vmtarget(oop mh, oop ref) { assert(is_instance(mh), "MH only"); mh->obj_field_put(_vmtarget_offset, ref); } -int sun_dyn_DirectMethodHandle::vmindex(oop mh) { +int java_lang_invoke_DirectMethodHandle::vmindex(oop mh) { assert(is_instance(mh), "DMH only"); return mh->int_field(_vmindex_offset); } -void sun_dyn_DirectMethodHandle::set_vmindex(oop mh, int index) { +void java_lang_invoke_DirectMethodHandle::set_vmindex(oop mh, int index) { assert(is_instance(mh), "DMH only"); mh->int_field_put(_vmindex_offset, index); } -int sun_dyn_BoundMethodHandle::vmargslot(oop mh) { +int java_lang_invoke_BoundMethodHandle::vmargslot(oop mh) { assert(is_instance(mh), "BMH only"); return mh->int_field(_vmargslot_offset); } -oop sun_dyn_BoundMethodHandle::argument(oop mh) { +oop java_lang_invoke_BoundMethodHandle::argument(oop mh) { assert(is_instance(mh), "BMH only"); return mh->obj_field(_argument_offset); } -int sun_dyn_AdapterMethodHandle::conversion(oop mh) { +int java_lang_invoke_AdapterMethodHandle::conversion(oop mh) { assert(is_instance(mh), "AMH only"); return mh->int_field(_conversion_offset); } -void sun_dyn_AdapterMethodHandle::set_conversion(oop mh, int conv) { +void java_lang_invoke_AdapterMethodHandle::set_conversion(oop mh, int conv) { assert(is_instance(mh), "AMH only"); mh->int_field_put(_conversion_offset, conv); } -// Support for java_dyn_MethodType - -int java_dyn_MethodType::_rtype_offset; -int java_dyn_MethodType::_ptypes_offset; -int java_dyn_MethodType::_form_offset; - -void java_dyn_MethodType::compute_offsets() { +// Support for java_lang_invoke_MethodType + +int java_lang_invoke_MethodType::_rtype_offset; +int java_lang_invoke_MethodType::_ptypes_offset; +int java_lang_invoke_MethodType::_form_offset; + +void java_lang_invoke_MethodType::compute_offsets() { klassOop k = SystemDictionary::MethodType_klass(); if (k != NULL) { compute_offset(_rtype_offset, k, vmSymbols::rtype_name(), vmSymbols::class_signature()); compute_offset(_ptypes_offset, k, vmSymbols::ptypes_name(), vmSymbols::class_array_signature()); - compute_offset(_form_offset, k, vmSymbols::form_name(), vmSymbols::java_dyn_MethodTypeForm_signature()); + compute_offset(_form_offset, k, vmSymbols::form_name(), vmSymbols::java_lang_invoke_MethodTypeForm_signature()); } } -void java_dyn_MethodType::print_signature(oop mt, outputStream* st) { +void java_lang_invoke_MethodType::print_signature(oop mt, outputStream* st) { st->print("("); objArrayOop pts = ptypes(mt); for (int i = 0, limit = pts->length(); i < limit; i++) { @@ -2429,7 +2554,7 @@ java_lang_Class::print_signature(rtype(mt), st); } -Symbol* java_dyn_MethodType::as_signature(oop mt, bool intern_if_not_found, TRAPS) { +Symbol* java_lang_invoke_MethodType::as_signature(oop mt, bool intern_if_not_found, TRAPS) { ResourceMark rm; stringStream buffer(128); print_signature(mt, &buffer); @@ -2444,103 +2569,83 @@ return name; } -oop java_dyn_MethodType::rtype(oop mt) { +oop java_lang_invoke_MethodType::rtype(oop mt) { assert(is_instance(mt), "must be a MethodType"); return mt->obj_field(_rtype_offset); } -objArrayOop java_dyn_MethodType::ptypes(oop mt) { +objArrayOop java_lang_invoke_MethodType::ptypes(oop mt) { assert(is_instance(mt), "must be a MethodType"); return (objArrayOop) mt->obj_field(_ptypes_offset); } -oop java_dyn_MethodType::form(oop mt) { +oop java_lang_invoke_MethodType::form(oop mt) { assert(is_instance(mt), "must be a MethodType"); return mt->obj_field(_form_offset); } -oop java_dyn_MethodType::ptype(oop mt, int idx) { +oop java_lang_invoke_MethodType::ptype(oop mt, int idx) { return ptypes(mt)->obj_at(idx); } -int java_dyn_MethodType::ptype_count(oop mt) { +int java_lang_invoke_MethodType::ptype_count(oop mt) { return ptypes(mt)->length(); } -// Support for java_dyn_MethodTypeForm - -int java_dyn_MethodTypeForm::_vmslots_offset; -int java_dyn_MethodTypeForm::_erasedType_offset; -int java_dyn_MethodTypeForm::_genericInvoker_offset; - -void java_dyn_MethodTypeForm::compute_offsets() { +// Support for java_lang_invoke_MethodTypeForm + +int java_lang_invoke_MethodTypeForm::_vmslots_offset; +int java_lang_invoke_MethodTypeForm::_erasedType_offset; +int java_lang_invoke_MethodTypeForm::_genericInvoker_offset; + +void java_lang_invoke_MethodTypeForm::compute_offsets() { klassOop k = SystemDictionary::MethodTypeForm_klass(); if (k != NULL) { compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true); - compute_optional_offset(_erasedType_offset, k, vmSymbols::erasedType_name(), vmSymbols::java_dyn_MethodType_signature(), true); - compute_optional_offset(_genericInvoker_offset, k, vmSymbols::genericInvoker_name(), vmSymbols::java_dyn_MethodHandle_signature(), true); + compute_optional_offset(_erasedType_offset, k, vmSymbols::erasedType_name(), vmSymbols::java_lang_invoke_MethodType_signature(), true); + compute_optional_offset(_genericInvoker_offset, k, vmSymbols::genericInvoker_name(), vmSymbols::java_lang_invoke_MethodHandle_signature(), true); if (_genericInvoker_offset == 0) _genericInvoker_offset = -1; // set to explicit "empty" value } } -int java_dyn_MethodTypeForm::vmslots(oop mtform) { +int java_lang_invoke_MethodTypeForm::vmslots(oop mtform) { assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only"); return mtform->int_field(_vmslots_offset); } -oop java_dyn_MethodTypeForm::erasedType(oop mtform) { +oop java_lang_invoke_MethodTypeForm::erasedType(oop mtform) { assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only"); return mtform->obj_field(_erasedType_offset); } -oop java_dyn_MethodTypeForm::genericInvoker(oop mtform) { +oop java_lang_invoke_MethodTypeForm::genericInvoker(oop mtform) { assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only"); return mtform->obj_field(_genericInvoker_offset); } -// Support for java_dyn_CallSite - -int java_dyn_CallSite::_target_offset; -int java_dyn_CallSite::_caller_method_offset; -int java_dyn_CallSite::_caller_bci_offset; - -void java_dyn_CallSite::compute_offsets() { +// Support for java_lang_invoke_CallSite + +int java_lang_invoke_CallSite::_target_offset; + +void java_lang_invoke_CallSite::compute_offsets() { if (!EnableInvokeDynamic) return; klassOop k = SystemDictionary::CallSite_klass(); if (k != NULL) { - compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_dyn_MethodHandle_signature()); - compute_offset(_caller_method_offset, k, vmSymbols::vmmethod_name(), vmSymbols::sun_dyn_MemberName_signature()); - compute_offset(_caller_bci_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature()); + compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature()); } } -oop java_dyn_CallSite::target(oop site) { +oop java_lang_invoke_CallSite::target(oop site) { return site->obj_field(_target_offset); } -void java_dyn_CallSite::set_target(oop site, oop target) { +void java_lang_invoke_CallSite::set_target(oop site, oop target) { site->obj_field_put(_target_offset, target); } -oop java_dyn_CallSite::caller_method(oop site) { - return site->obj_field(_caller_method_offset); -} - -void java_dyn_CallSite::set_caller_method(oop site, oop ref) { - site->obj_field_put(_caller_method_offset, ref); -} - -jint java_dyn_CallSite::caller_bci(oop site) { - return site->int_field(_caller_bci_offset); -} - -void java_dyn_CallSite::set_caller_bci(oop site, jint bci) { - site->int_field_put(_caller_bci_offset, bci); -} - // Support for java_security_AccessControlContext @@ -2621,26 +2726,18 @@ // Support for java_lang_System - -void java_lang_System::compute_offsets() { - assert(offset_of_static_fields == 0, "offsets should be initialized only once"); - - instanceKlass* ik = instanceKlass::cast(SystemDictionary::System_klass()); - offset_of_static_fields = ik->offset_of_static_fields(); -} - int java_lang_System::in_offset_in_bytes() { - return (offset_of_static_fields + static_in_offset); + return (instanceMirrorKlass::offset_of_static_fields() + static_in_offset); } int java_lang_System::out_offset_in_bytes() { - return (offset_of_static_fields + static_out_offset); + return (instanceMirrorKlass::offset_of_static_fields() + static_out_offset); } int java_lang_System::err_offset_in_bytes() { - return (offset_of_static_fields + static_err_offset); + return (instanceMirrorKlass::offset_of_static_fields() + static_err_offset); } @@ -2653,6 +2750,8 @@ int java_lang_Class::array_klass_offset; int java_lang_Class::resolved_constructor_offset; int java_lang_Class::number_of_fake_oop_fields; +int java_lang_Class::oop_size_offset; +int java_lang_Class::static_oop_field_count_offset; int java_lang_Throwable::backtrace_offset; int java_lang_Throwable::detailMessage_offset; int java_lang_Throwable::cause_offset; @@ -2696,7 +2795,6 @@ int java_lang_ref_SoftReference::timestamp_offset; int java_lang_ref_SoftReference::static_clock_offset; int java_lang_ClassLoader::parent_offset; -int java_lang_System::offset_of_static_fields; int java_lang_System::static_in_offset; int java_lang_System::static_out_offset; int java_lang_System::static_err_offset; @@ -2813,10 +2911,19 @@ java_lang_String::count_offset = java_lang_String::offset_offset + sizeof (jint); java_lang_String::hash_offset = java_lang_String::count_offset + sizeof (jint); - // Do the Class Class - java_lang_Class::klass_offset = java_lang_Class::hc_klass_offset * x + header; - java_lang_Class::array_klass_offset = java_lang_Class::hc_array_klass_offset * x + header; - java_lang_Class::resolved_constructor_offset = java_lang_Class::hc_resolved_constructor_offset * x + header; + { + // Do the Class Class + int offset = header; + java_lang_Class::oop_size_offset = header; + offset += BytesPerInt; + java_lang_Class::static_oop_field_count_offset = offset; + offset = align_size_up(offset + BytesPerInt, x); + java_lang_Class::klass_offset = offset; + offset += x; + java_lang_Class::array_klass_offset = offset; + offset += x; + java_lang_Class::resolved_constructor_offset = offset; + } // This is NOT an offset java_lang_Class::number_of_fake_oop_fields = java_lang_Class::hc_number_of_fake_oop_fields; @@ -2873,20 +2980,19 @@ void JavaClasses::compute_offsets() { java_lang_Class::compute_offsets(); - java_lang_System::compute_offsets(); java_lang_Thread::compute_offsets(); java_lang_ThreadGroup::compute_offsets(); if (EnableMethodHandles) { - java_dyn_MethodHandle::compute_offsets(); - sun_dyn_MemberName::compute_offsets(); - sun_dyn_DirectMethodHandle::compute_offsets(); - sun_dyn_BoundMethodHandle::compute_offsets(); - sun_dyn_AdapterMethodHandle::compute_offsets(); - java_dyn_MethodType::compute_offsets(); - java_dyn_MethodTypeForm::compute_offsets(); + java_lang_invoke_MethodHandle::compute_offsets(); + java_lang_invoke_MemberName::compute_offsets(); + java_lang_invoke_DirectMethodHandle::compute_offsets(); + java_lang_invoke_BoundMethodHandle::compute_offsets(); + java_lang_invoke_AdapterMethodHandle::compute_offsets(); + java_lang_invoke_MethodType::compute_offsets(); + java_lang_invoke_MethodTypeForm::compute_offsets(); } if (EnableInvokeDynamic) { - java_dyn_CallSite::compute_offsets(); + java_lang_invoke_CallSite::compute_offsets(); } java_security_AccessControlContext::compute_offsets(); // Initialize reflection classes. The layouts of these classes @@ -2957,10 +3063,10 @@ tty->print_cr("Static field %s.%s appears to be nonstatic", klass_name, field_name); return false; } - if (fd.offset() == hardcoded_offset + h_klass->offset_of_static_fields()) { + if (fd.offset() == hardcoded_offset + instanceMirrorKlass::offset_of_static_fields()) { return true; } else { - tty->print_cr("Offset of static field %s.%s is hardcoded as %d but should really be %d.", klass_name, field_name, hardcoded_offset, fd.offset() - h_klass->offset_of_static_fields()); + tty->print_cr("Offset of static field %s.%s is hardcoded as %d but should really be %d.", klass_name, field_name, hardcoded_offset, fd.offset() - instanceMirrorKlass::offset_of_static_fields()); return false; } }
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -138,10 +138,8 @@ // The fake offsets are added by the class loader when java.lang.Class is loaded enum { - hc_klass_offset = 0, - hc_array_klass_offset = 1, - hc_resolved_constructor_offset = 2, - hc_number_of_fake_oop_fields = 3 + hc_number_of_fake_oop_fields = 3, + hc_number_of_fake_int_fields = 2 }; static int klass_offset; @@ -149,6 +147,9 @@ static int array_klass_offset; static int number_of_fake_oop_fields; + static int oop_size_offset; + static int static_oop_field_count_offset; + static void compute_offsets(); static bool offsets_computed; static int classRedefinedCount_offset; @@ -157,6 +158,7 @@ public: // Instance creation static oop create_mirror(KlassHandle k, TRAPS); + static void fixup_mirror(KlassHandle k, TRAPS); static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS); // Conversion static klassOop as_klassOop(oop java_class); @@ -191,6 +193,12 @@ static void set_classRedefinedCount(oop the_class_mirror, int value); // Support for parallelCapable field static bool parallelCapable(oop the_class_mirror); + + static int oop_size(oop java_class); + static void set_oop_size(oop java_class, int size); + static int static_oop_field_count(oop java_class); + static void set_static_oop_field_count(oop java_class, int size); + // Debugging friend class JavaClasses; friend class instanceKlass; // verification code accesses offsets @@ -794,11 +802,11 @@ }; -// Interface to java.dyn.MethodHandle objects +// Interface to java.lang.invoke.MethodHandle objects class MethodHandleEntry; -class java_dyn_MethodHandle: AllStatic { +class java_lang_invoke_MethodHandle: AllStatic { friend class JavaClasses; private: @@ -839,7 +847,7 @@ static int vmslots_offset_in_bytes() { return _vmslots_offset; } }; -class sun_dyn_DirectMethodHandle: public java_dyn_MethodHandle { +class java_lang_invoke_DirectMethodHandle: public java_lang_invoke_MethodHandle { friend class JavaClasses; private: @@ -864,7 +872,7 @@ static int vmindex_offset_in_bytes() { return _vmindex_offset; } }; -class sun_dyn_BoundMethodHandle: public java_dyn_MethodHandle { +class java_lang_invoke_BoundMethodHandle: public java_lang_invoke_MethodHandle { friend class JavaClasses; private: @@ -891,7 +899,7 @@ static int vmargslot_offset_in_bytes() { return _vmargslot_offset; } }; -class sun_dyn_AdapterMethodHandle: public sun_dyn_BoundMethodHandle { +class java_lang_invoke_AdapterMethodHandle: public java_lang_invoke_BoundMethodHandle { friend class JavaClasses; private: @@ -942,14 +950,14 @@ }; -// Interface to sun.dyn.MemberName objects +// Interface to java.lang.invoke.MemberName objects // (These are a private interface for Java code to query the class hierarchy.) -class sun_dyn_MemberName: AllStatic { +class java_lang_invoke_MemberName: AllStatic { friend class JavaClasses; private: - // From java.dyn.MemberName: + // From java.lang.invoke.MemberName: // private Class<?> clazz; // class in which the method is defined // private String name; // may be null if not yet materialized // private Object type; // may be null if not yet materialized @@ -1018,9 +1026,9 @@ }; -// Interface to java.dyn.MethodType objects +// Interface to java.lang.invoke.MethodType objects -class java_dyn_MethodType: AllStatic { +class java_lang_invoke_MethodType: AllStatic { friend class JavaClasses; private: @@ -1052,7 +1060,7 @@ static int form_offset_in_bytes() { return _form_offset; } }; -class java_dyn_MethodTypeForm: AllStatic { +class java_lang_invoke_MethodTypeForm: AllStatic { friend class JavaClasses; private: @@ -1075,9 +1083,9 @@ }; -// Interface to java.dyn.CallSite objects +// Interface to java.lang.invoke.CallSite objects -class java_dyn_CallSite: AllStatic { +class java_lang_invoke_CallSite: AllStatic { friend class JavaClasses; private: @@ -1165,13 +1173,10 @@ hc_static_err_offset = 2 }; - static int offset_of_static_fields; static int static_in_offset; static int static_out_offset; static int static_err_offset; - static void compute_offsets(); - public: static int in_offset_in_bytes(); static int out_offset_in_bytes();
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/classfile/symbolTable.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -88,7 +88,7 @@ void SymbolTable::unlink() { int removed = 0; int total = 0; - int memory_total = 0; + size_t memory_total = 0; for (int i = 0; i < the_table()->table_size(); ++i) { for (HashtableEntry<Symbol*>** p = the_table()->bucket_addr(i); *p != NULL; ) { HashtableEntry<Symbol*>* entry = *p; @@ -112,8 +112,10 @@ } symbols_removed += removed; symbols_counted += total; - if (PrintGCDetails) { - gclog_or_tty->print(" [Symbols=%d size=%dK] ", total, + // Exclude printing for normal PrintGCDetails because people parse + // this output. + if (PrintGCDetails && Verbose && WizardMode) { + gclog_or_tty->print(" [Symbols=%d size=" SIZE_FORMAT "K] ", total, (memory_total*HeapWordSize)/1024); } } @@ -528,7 +530,7 @@ Handle string; // try to reuse the string if possible - if (!string_or_null.is_null() && string_or_null()->is_perm()) { + if (!string_or_null.is_null() && (!JavaObjectsInPerm || string_or_null()->is_perm())) { string = string_or_null; } else { string = java_lang_String::create_tenured_from_unicode(name, len, CHECK_NULL); @@ -660,7 +662,7 @@ for ( ; p != NULL; p = p->next()) { oop s = p->literal(); guarantee(s != NULL, "interned string is NULL"); - guarantee(s->is_perm(), "interned string not in permspace"); + guarantee(s->is_perm() || !JavaObjectsInPerm, "interned string not in permspace"); int length; jchar* chars = java_lang_String::as_unicode_string(s, length);
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/classfile/symbolTable.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -216,18 +216,14 @@ oop basic_add(int index, Handle string_or_null, jchar* name, int len, unsigned int hashValue, TRAPS); - // Table size - enum { - string_table_size = 1009 - }; - oop lookup(int index, jchar* chars, int length, unsigned int hashValue); - StringTable() : Hashtable<oop>(string_table_size, sizeof (HashtableEntry<oop>)) {} + StringTable() : Hashtable<oop>((int)StringTableSize, + sizeof (HashtableEntry<oop>)) {} StringTable(HashtableBucket* t, int number_of_entries) - : Hashtable<oop>(string_table_size, sizeof (HashtableEntry<oop>), t, - number_of_entries) {} + : Hashtable<oop>((int)StringTableSize, sizeof (HashtableEntry<oop>), t, + number_of_entries) {} public: // The string table @@ -241,7 +237,7 @@ static void create_table(HashtableBucket* t, int length, int number_of_entries) { assert(_the_table == NULL, "One string table allowed."); - assert(length == string_table_size * sizeof(HashtableBucket), + assert((size_t)length == StringTableSize * sizeof(HashtableBucket), "bad shared string size."); _the_table = new StringTable(t, number_of_entries); }
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1887,27 +1887,99 @@ 0 }; +Symbol* SystemDictionary::find_backup_symbol(Symbol* symbol, + const char* from_prefix, + const char* to_prefix) { + assert(AllowTransitionalJSR292, ""); // delete this subroutine + Symbol* backup_symbol = NULL; + size_t from_len = strlen(from_prefix); + if (strncmp((const char*) symbol->base(), from_prefix, from_len) != 0) + return NULL; + char buf[100]; + size_t to_len = strlen(to_prefix); + size_t tail_len = symbol->utf8_length() - from_len; + size_t new_len = to_len + tail_len; + guarantee(new_len < sizeof(buf), "buf too small"); + memcpy(buf, to_prefix, to_len); + memcpy(buf + to_len, symbol->base() + from_len, tail_len); + buf[new_len] = '\0'; + vmSymbols::SID backup_sid = vmSymbols::find_sid(buf); + if (backup_sid != vmSymbols::NO_SID) { + backup_symbol = vmSymbols::symbol_at(backup_sid); + } + return backup_symbol; +} + +Symbol* SystemDictionary::find_backup_class_name(Symbol* symbol) { + assert(AllowTransitionalJSR292, ""); // delete this subroutine + if (symbol == NULL) return NULL; + Symbol* backup_symbol = find_backup_symbol(symbol, "java/lang/invoke/", "java/dyn/"); // AllowTransitionalJSR292 ONLY + if (backup_symbol == NULL) + backup_symbol = find_backup_symbol(symbol, "java/dyn/", "sun/dyn/"); // AllowTransitionalJSR292 ONLY + return backup_symbol; +} + +Symbol* SystemDictionary::find_backup_signature(Symbol* symbol) { + assert(AllowTransitionalJSR292, ""); // delete this subroutine + if (symbol == NULL) return NULL; + return find_backup_symbol(symbol, "Ljava/lang/invoke/", "Ljava/dyn/"); +} + bool SystemDictionary::initialize_wk_klass(WKID id, int init_opt, TRAPS) { assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob"); int info = wk_init_info[id - FIRST_WKID]; int sid = (info >> CEIL_LG_OPTION_LIMIT); Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid); klassOop* klassp = &_well_known_klasses[id]; - bool must_load = (init_opt < SystemDictionary::Opt); - bool try_load = true; + bool pre_load = (init_opt < SystemDictionary::Opt); + bool try_load = true; if (init_opt == SystemDictionary::Opt_Kernel) { #ifndef KERNEL try_load = false; #endif //KERNEL } - if ((*klassp) == NULL && try_load) { + Symbol* backup_symbol = NULL; // symbol to try if the current symbol fails + if (init_opt == SystemDictionary::Pre_JSR292) { + if (!EnableMethodHandles) try_load = false; // do not bother to load such classes + if (AllowTransitionalJSR292) { + backup_symbol = find_backup_class_name(symbol); + if (try_load && PreferTransitionalJSR292) { + while (backup_symbol != NULL) { + (*klassp) = resolve_or_null(backup_symbol, CHECK_0); // try backup early + if (TraceMethodHandles) { + ResourceMark rm; + tty->print_cr("MethodHandles: try backup first for %s => %s (%s)", + symbol->as_C_string(), backup_symbol->as_C_string(), + ((*klassp) == NULL) ? "no such class" : "backup load succeeded"); + } + if ((*klassp) != NULL) return true; + backup_symbol = find_backup_class_name(backup_symbol); // find next backup + } + } + } + } + if ((*klassp) != NULL) return true; + if (!try_load) return false; + while (symbol != NULL) { + bool must_load = (pre_load && (backup_symbol == NULL)); if (must_load) { (*klassp) = resolve_or_fail(symbol, true, CHECK_0); // load required class } else { (*klassp) = resolve_or_null(symbol, CHECK_0); // load optional klass } + if ((*klassp) != NULL) return true; + // Go around again. Example of long backup sequence: + // java.lang.invoke.MemberName, java.dyn.MemberName, sun.dyn.MemberName, ONLY if AllowTransitionalJSR292 + if (TraceMethodHandles && (backup_symbol != NULL)) { + ResourceMark rm; + tty->print_cr("MethodHandles: backup for %s => %s", + symbol->as_C_string(), backup_symbol->as_C_string()); + } + symbol = backup_symbol; + if (AllowTransitionalJSR292) + backup_symbol = find_backup_class_name(symbol); } - return ((*klassp) != NULL); + return false; } void SystemDictionary::initialize_wk_klasses_until(WKID limit_id, WKID &start_id, TRAPS) { @@ -2348,6 +2420,8 @@ if (THREAD->is_Compiler_thread()) return NULL; // do not attempt from within compiler bool for_invokeGeneric = (name_id == vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name)); + if (AllowInvokeForInvokeGeneric && name_id == vmSymbols::VM_SYMBOL_ENUM_NAME(invoke_name)) + for_invokeGeneric = true; bool found_on_bcp = false; Handle mt = find_method_handle_type(signature, accessing_klass, for_invokeGeneric, @@ -2376,7 +2450,7 @@ } } -// Ask Java code to find or construct a java.dyn.MethodType for the given +// Ask Java code to find or construct a java.lang.invoke.MethodType for the given // signature, as interpreted relative to the given class loader. // Because of class loader constraints, all method handle usage must be // consistent with this loader. @@ -2430,25 +2504,33 @@ } assert(arg == npts, ""); - // call sun.dyn.MethodHandleNatives::findMethodType(Class rt, Class[] pts) -> MethodType + // call java.lang.invoke.MethodHandleNatives::findMethodType(Class rt, Class[] pts) -> MethodType JavaCallArguments args(Handle(THREAD, rt())); args.push_oop(pts()); JavaValue result(T_OBJECT); + Symbol* findMethodHandleType_signature = vmSymbols::findMethodHandleType_signature(); + if (AllowTransitionalJSR292 && SystemDictionaryHandles::MethodType_klass()->name() == vmSymbols::java_dyn_MethodType()) { + findMethodHandleType_signature = vmSymbols::findMethodHandleType_TRANS_signature(); + } JavaCalls::call_static(&result, SystemDictionary::MethodHandleNatives_klass(), vmSymbols::findMethodHandleType_name(), - vmSymbols::findMethodHandleType_signature(), + findMethodHandleType_signature, &args, CHECK_(empty)); Handle method_type(THREAD, (oop) result.get_jobject()); if (for_invokeGeneric) { - // call sun.dyn.MethodHandleNatives::notifyGenericMethodType(MethodType) -> void + // call java.lang.invoke.MethodHandleNatives::notifyGenericMethodType(MethodType) -> void JavaCallArguments args(Handle(THREAD, method_type())); JavaValue no_result(T_VOID); + Symbol* notifyGenericMethodType_signature = vmSymbols::notifyGenericMethodType_signature(); + if (AllowTransitionalJSR292 && SystemDictionaryHandles::MethodType_klass()->name() == vmSymbols::java_dyn_MethodType()) { + notifyGenericMethodType_signature = vmSymbols::notifyGenericMethodType_TRANS_signature(); + } JavaCalls::call_static(&no_result, SystemDictionary::MethodHandleNatives_klass(), vmSymbols::notifyGenericMethodType_name(), - vmSymbols::notifyGenericMethodType_signature(), + notifyGenericMethodType_signature, &args, THREAD); if (HAS_PENDING_EXCEPTION) { // If the notification fails, just kill it. @@ -2489,7 +2571,7 @@ THROW_MSG_(vmSymbols::java_lang_LinkageError(), "bad signature", empty); } - // call sun.dyn.MethodHandleNatives::linkMethodHandleConstant(Class caller, int refKind, Class callee, String name, Object type) -> MethodHandle + // call java.lang.invoke.MethodHandleNatives::linkMethodHandleConstant(Class caller, int refKind, Class callee, String name, Object type) -> MethodHandle JavaCallArguments args; args.push_oop(caller->java_mirror()); // the referring class args.push_int(ref_kind); @@ -2497,15 +2579,19 @@ args.push_oop(name()); args.push_oop(type()); JavaValue result(T_OBJECT); + Symbol* linkMethodHandleConstant_signature = vmSymbols::linkMethodHandleConstant_signature(); + if (AllowTransitionalJSR292 && SystemDictionaryHandles::MethodHandle_klass()->name() == vmSymbols::java_dyn_MethodHandle()) { + linkMethodHandleConstant_signature = vmSymbols::linkMethodHandleConstant_TRANS_signature(); + } JavaCalls::call_static(&result, SystemDictionary::MethodHandleNatives_klass(), vmSymbols::linkMethodHandleConstant_name(), - vmSymbols::linkMethodHandleConstant_signature(), + linkMethodHandleConstant_signature, &args, CHECK_(empty)); return Handle(THREAD, (oop) result.get_jobject()); } -// Ask Java code to find or construct a java.dyn.CallSite for the given +// Ask Java code to find or construct a java.lang.invoke.CallSite for the given // name and signature, as interpreted relative to the given class loader. Handle SystemDictionary::make_dynamic_call_site(Handle bootstrap_method, Symbol* name, @@ -2516,13 +2602,13 @@ TRAPS) { Handle empty; guarantee(bootstrap_method.not_null() && - java_dyn_MethodHandle::is_instance(bootstrap_method()), + java_lang_invoke_MethodHandle::is_instance(bootstrap_method()), "caller must supply a valid BSM"); Handle caller_mname = MethodHandles::new_MemberName(CHECK_(empty)); MethodHandles::init_MemberName(caller_mname(), caller_method()); - // call sun.dyn.MethodHandleNatives::makeDynamicCallSite(bootm, name, mtype, info, caller_mname, caller_pos) + // call java.lang.invoke.MethodHandleNatives::makeDynamicCallSite(bootm, name, mtype, info, caller_mname, caller_pos) oop name_str_oop = StringTable::intern(name, CHECK_(empty)); // not a handle! JavaCallArguments args(Handle(THREAD, bootstrap_method())); args.push_oop(name_str_oop); @@ -2531,14 +2617,21 @@ args.push_oop(caller_mname()); args.push_int(caller_bci); JavaValue result(T_OBJECT); + Symbol* makeDynamicCallSite_signature = vmSymbols::makeDynamicCallSite_signature(); + if (AllowTransitionalJSR292 && SystemDictionaryHandles::MethodHandleNatives_klass()->name() == vmSymbols::sun_dyn_MethodHandleNatives()) { + makeDynamicCallSite_signature = vmSymbols::makeDynamicCallSite_TRANS_signature(); + } + if (AllowTransitionalJSR292 && SystemDictionaryHandles::MethodHandleNatives_klass()->name() == vmSymbols::java_dyn_MethodHandleNatives()) { + makeDynamicCallSite_signature = vmSymbols::makeDynamicCallSite_TRANS2_signature(); + } JavaCalls::call_static(&result, SystemDictionary::MethodHandleNatives_klass(), vmSymbols::makeDynamicCallSite_name(), - vmSymbols::makeDynamicCallSite_signature(), + makeDynamicCallSite_signature, &args, CHECK_(empty)); oop call_site_oop = (oop) result.get_jobject(); assert(call_site_oop->is_oop() - /*&& java_dyn_CallSite::is_instance(call_site_oop)*/, "must be sane"); + /*&& java_lang_invoke_CallSite::is_instance(call_site_oop)*/, "must be sane"); if (TraceMethodHandles) { #ifndef PRODUCT tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop);
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -144,18 +144,18 @@ template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ \ /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ - template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \ - template(MemberName_klass, sun_dyn_MemberName, Opt) \ - template(MethodHandleImpl_klass, sun_dyn_MethodHandleImpl, Opt) \ - template(MethodHandleNatives_klass, sun_dyn_MethodHandleNatives, Opt) \ - template(AdapterMethodHandle_klass, sun_dyn_AdapterMethodHandle, Opt) \ - template(BoundMethodHandle_klass, sun_dyn_BoundMethodHandle, Opt) \ - template(DirectMethodHandle_klass, sun_dyn_DirectMethodHandle, Opt) \ - template(MethodType_klass, java_dyn_MethodType, Opt) \ - template(MethodTypeForm_klass, java_dyn_MethodTypeForm, Opt) \ - template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \ - template(Linkage_klass, java_dyn_Linkage, Opt) \ - template(CallSite_klass, java_dyn_CallSite, Opt) \ + template(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre_JSR292) \ + template(MemberName_klass, java_lang_invoke_MemberName, Pre_JSR292) \ + template(MethodHandleImpl_klass, sun_dyn_MethodHandleImpl, Opt) /* AllowTransitionalJSR292 ONLY */ \ + template(MethodHandleNatives_klass, java_lang_invoke_MethodHandleNatives, Pre_JSR292) \ + template(AdapterMethodHandle_klass, java_lang_invoke_AdapterMethodHandle, Pre_JSR292) \ + template(BoundMethodHandle_klass, java_lang_invoke_BoundMethodHandle, Pre_JSR292) \ + template(DirectMethodHandle_klass, java_lang_invoke_DirectMethodHandle, Pre_JSR292) \ + template(MethodType_klass, java_lang_invoke_MethodType, Pre_JSR292) \ + template(MethodTypeForm_klass, java_lang_invoke_MethodTypeForm, Pre_JSR292) \ + template(WrongMethodTypeException_klass, java_lang_invoke_WrongMethodTypeException, Pre_JSR292) \ + template(Linkage_klass, java_lang_invoke_Linkage, Opt) /* AllowTransitionalJSR292 ONLY */ \ + template(CallSite_klass, java_lang_invoke_CallSite, Pre_JSR292) \ /* Note: MethodHandle must be first, and CallSite last in group */ \ \ template(StringBuffer_klass, java_lang_StringBuffer, Pre) \ @@ -207,6 +207,7 @@ enum InitOption { Pre, // preloaded; error if not present + Pre_JSR292, // preloaded if EnableMethodHandles // Order is significant. Options before this point require resolve_or_fail. // Options after this point will use resolve_or_null instead. @@ -401,6 +402,7 @@ } static klassOop check_klass_Pre(klassOop k) { return check_klass(k); } + static klassOop check_klass_Pre_JSR292(klassOop k) { return EnableInvokeDynamic ? check_klass(k) : k; } static klassOop check_klass_Opt(klassOop k) { return k; } static klassOop check_klass_Opt_Kernel(klassOop k) { return k; } //== Opt static klassOop check_klass_Opt_Only_JDK15(klassOop k) { @@ -420,6 +422,8 @@ initialize_wk_klasses_until((WKID) limit, start_id, THREAD); } + static Symbol* find_backup_symbol(Symbol* symbol, const char* from_prefix, const char* to_prefix); + public: #define WK_KLASS_DECLARE(name, ignore_symbol, option) \ static klassOop name() { return check_klass_##option(_well_known_klasses[WK_KLASS_ENUM_NAME(name)]); } @@ -441,6 +445,9 @@ static void load_abstract_ownable_synchronizer_klass(TRAPS); + static Symbol* find_backup_class_name(Symbol* class_name_symbol); + static Symbol* find_backup_signature(Symbol* signature_symbol); + private: // Tells whether ClassLoader.loadClassInternal is present static bool has_loadClassInternal() { return _has_loadClassInternal; } @@ -475,18 +482,18 @@ Handle loader2, bool is_method, TRAPS); // JSR 292 - // find the java.dyn.MethodHandles::invoke method for a given signature + // find the java.lang.invoke.MethodHandles::invoke method for a given signature static methodOop find_method_handle_invoke(Symbol* name, Symbol* signature, KlassHandle accessing_klass, TRAPS); - // ask Java to compute a java.dyn.MethodType object for a given signature + // ask Java to compute a java.lang.invoke.MethodType object for a given signature static Handle find_method_handle_type(Symbol* signature, KlassHandle accessing_klass, bool for_invokeGeneric, bool& return_bcp_flag, TRAPS); - // ask Java to compute a java.dyn.MethodHandle object for a given CP entry + // ask Java to compute a java.lang.invoke.MethodHandle object for a given CP entry static Handle link_method_handle_constant(KlassHandle caller, int ref_kind, //e.g., JVM_REF_invokeVirtual KlassHandle callee,
--- a/hotspot/src/share/vm/classfile/verifier.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/classfile/verifier.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1671,13 +1671,19 @@ VerificationType::long_type(), VerificationType::long2_type(), CHECK_VERIFY(this)); } else if (tag.is_method_handle()) { + Symbol* methodHandle_name = vmSymbols::java_lang_invoke_MethodHandle(); + if (AllowTransitionalJSR292 && !Universe::is_bootstrapping()) + methodHandle_name = SystemDictionaryHandles::MethodHandle_klass()->name(); current_frame->push_stack( VerificationType::reference_type( - vmSymbols::java_dyn_MethodHandle()), CHECK_VERIFY(this)); + methodHandle_name), CHECK_VERIFY(this)); } else if (tag.is_method_type()) { + Symbol* methodType_name = vmSymbols::java_lang_invoke_MethodType(); + if (AllowTransitionalJSR292 && !Universe::is_bootstrapping()) + methodType_name = SystemDictionaryHandles::MethodType_klass()->name(); current_frame->push_stack( VerificationType::reference_type( - vmSymbols::java_dyn_MethodType()), CHECK_VERIFY(this)); + methodType_name), CHECK_VERIFY(this)); } else { verify_error(bci, "Invalid index in ldc"); return;
--- a/hotspot/src/share/vm/classfile/vmSymbols.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -277,6 +277,12 @@ return sid; } +vmSymbols::SID vmSymbols::find_sid(const char* symbol_name) { + Symbol* symbol = SymbolTable::probe(symbol_name, (int) strlen(symbol_name)); + if (symbol == NULL) return NO_SID; + return find_sid(symbol); +} + static vmIntrinsics::ID wrapper_intrinsic(BasicType type, bool unboxing) { #define TYPE2(type, unboxing) ((int)(type)*2 + ((unboxing) ? 1 : 0)) switch (TYPE2(type, unboxing)) {
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -229,33 +229,60 @@ template(base_name, "base") \ \ /* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \ - template(java_dyn_InvokeDynamic, "java/dyn/InvokeDynamic") \ - template(java_dyn_Linkage, "java/dyn/Linkage") \ - template(java_dyn_CallSite, "java/dyn/CallSite") \ - template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \ - template(java_dyn_MethodType, "java/dyn/MethodType") \ - template(java_dyn_WrongMethodTypeException, "java/dyn/WrongMethodTypeException") \ - template(java_dyn_MethodType_signature, "Ljava/dyn/MethodType;") \ - template(java_dyn_MethodHandle_signature, "Ljava/dyn/MethodHandle;") \ + template(java_lang_invoke_InvokeDynamic, "java/lang/invoke/InvokeDynamic") \ + template(java_lang_invoke_Linkage, "java/lang/invoke/Linkage") \ + template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \ + template(java_lang_invoke_MethodHandle, "java/lang/invoke/MethodHandle") \ + template(java_lang_invoke_MethodType, "java/lang/invoke/MethodType") \ + template(java_lang_invoke_WrongMethodTypeException, "java/lang/invoke/WrongMethodTypeException") \ + template(java_lang_invoke_MethodType_signature, "Ljava/lang/invoke/MethodType;") \ + template(java_lang_invoke_MethodHandle_signature, "Ljava/lang/invoke/MethodHandle;") \ /* internal classes known only to the JVM: */ \ - template(java_dyn_MethodTypeForm, "java/dyn/MethodTypeForm") \ - template(java_dyn_MethodTypeForm_signature, "Ljava/dyn/MethodTypeForm;") \ - template(sun_dyn_MemberName, "sun/dyn/MemberName") \ - template(sun_dyn_MemberName_signature, "Lsun/dyn/MemberName;") \ - template(sun_dyn_MethodHandleImpl, "sun/dyn/MethodHandleImpl") \ - template(sun_dyn_MethodHandleNatives, "sun/dyn/MethodHandleNatives") \ - template(sun_dyn_AdapterMethodHandle, "sun/dyn/AdapterMethodHandle") \ - template(sun_dyn_BoundMethodHandle, "sun/dyn/BoundMethodHandle") \ - template(sun_dyn_DirectMethodHandle, "sun/dyn/DirectMethodHandle") \ - /* internal up-calls made only by the JVM, via class sun.dyn.MethodHandleNatives: */ \ + template(java_lang_invoke_MethodTypeForm, "java/lang/invoke/MethodTypeForm") \ + template(java_lang_invoke_MethodTypeForm_signature, "Ljava/lang/invoke/MethodTypeForm;") \ + template(java_lang_invoke_MemberName, "java/lang/invoke/MemberName") \ + template(java_lang_invoke_MethodHandleNatives, "java/lang/invoke/MethodHandleNatives") \ + template(java_lang_invoke_AdapterMethodHandle, "java/lang/invoke/AdapterMethodHandle") \ + template(java_lang_invoke_BoundMethodHandle, "java/lang/invoke/BoundMethodHandle") \ + template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \ + /* temporary transitional public names from 6839872: */ \ + template(java_dyn_InvokeDynamic, "java/dyn/InvokeDynamic") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_Linkage, "java/dyn/Linkage") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_CallSite, "java/dyn/CallSite") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_MethodHandle, "java/dyn/MethodHandle") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_MethodType, "java/dyn/MethodType") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_WrongMethodTypeException, "java/dyn/WrongMethodTypeException") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_MethodType_signature, "Ljava/dyn/MethodType;") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_MethodHandle_signature, "Ljava/dyn/MethodHandle;") /* AllowTransitionalJSR292 ONLY */ \ + /* temporary transitional internal names from 6839872: */ \ + template(java_dyn_MethodTypeForm, "java/dyn/MethodTypeForm") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_MethodTypeForm_signature, "Ljava/dyn/MethodTypeForm;") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_MemberName, "java/dyn/MemberName") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_MethodHandleNatives, "java/dyn/MethodHandleNatives") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_AdapterMethodHandle, "java/dyn/AdapterMethodHandle") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_BoundMethodHandle, "java/dyn/BoundMethodHandle") /* AllowTransitionalJSR292 ONLY */ \ + template(java_dyn_DirectMethodHandle, "java/dyn/DirectMethodHandle") /* AllowTransitionalJSR292 ONLY */ \ + /* temporary transitional internal names from EDR: */ \ + template(sun_dyn_MemberName, "sun/dyn/MemberName") /* AllowTransitionalJSR292 ONLY */ \ + template(sun_dyn_MethodHandleImpl, "sun/dyn/MethodHandleImpl") /* AllowTransitionalJSR292 ONLY */ \ + template(sun_dyn_MethodHandleNatives, "sun/dyn/MethodHandleNatives") /* AllowTransitionalJSR292 ONLY */ \ + template(sun_dyn_AdapterMethodHandle, "sun/dyn/AdapterMethodHandle") /* AllowTransitionalJSR292 ONLY */ \ + template(sun_dyn_BoundMethodHandle, "sun/dyn/BoundMethodHandle") /* AllowTransitionalJSR292 ONLY */ \ + template(sun_dyn_DirectMethodHandle, "sun/dyn/DirectMethodHandle") /* AllowTransitionalJSR292 ONLY */ \ + /* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \ template(findMethodHandleType_name, "findMethodHandleType") \ - template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/dyn/MethodType;") \ + template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \ + template(findMethodHandleType_TRANS_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/dyn/MethodType;") /* AllowTransitionalJSR292 ONLY */ \ template(notifyGenericMethodType_name, "notifyGenericMethodType") \ - template(notifyGenericMethodType_signature, "(Ljava/dyn/MethodType;)V") \ + template(notifyGenericMethodType_signature, "(Ljava/lang/invoke/MethodType;)V") \ + template(notifyGenericMethodType_TRANS_signature, "(Ljava/dyn/MethodType;)V") /* AllowTransitionalJSR292 ONLY */ \ template(linkMethodHandleConstant_name, "linkMethodHandleConstant") \ - template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/dyn/MethodHandle;") \ + template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;") \ + template(linkMethodHandleConstant_TRANS_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/dyn/MethodHandle;") /* AllowTransitionalJSR292 ONLY */ \ template(makeDynamicCallSite_name, "makeDynamicCallSite") \ - template(makeDynamicCallSite_signature, "(Ljava/dyn/MethodHandle;Ljava/lang/String;Ljava/dyn/MethodType;Ljava/lang/Object;Lsun/dyn/MemberName;I)Ljava/dyn/CallSite;") \ + template(makeDynamicCallSite_signature, "(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/invoke/MemberName;I)Ljava/lang/invoke/CallSite;") \ + template(makeDynamicCallSite_TRANS_signature, "(Ljava/dyn/MethodHandle;Ljava/lang/String;Ljava/dyn/MethodType;Ljava/lang/Object;Lsun/dyn/MemberName;I)Ljava/dyn/CallSite;") /* AllowTransitionalJSR292 ONLY */ \ + template(makeDynamicCallSite_TRANS2_signature, "(Ljava/dyn/MethodHandle;Ljava/lang/String;Ljava/dyn/MethodType;Ljava/lang/Object;Ljava/dyn/MemberName;I)Ljava/dyn/CallSite;") /* AllowTransitionalJSR292 ONLY */ \ NOT_LP64( do_alias(machine_word_signature, int_signature) ) \ LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \ \ @@ -882,13 +909,15 @@ \ do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_object_array_object_signature, F_R) \ /* (symbols invoke_name and invoke_signature defined above) */ \ - do_intrinsic(_checkSpreadArgument, sun_dyn_MethodHandleImpl, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) \ + do_intrinsic(_checkSpreadArgument, java_lang_invoke_MethodHandleNatives, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) \ + do_intrinsic(_checkSpreadArgument_TRANS,sun_dyn_MethodHandleImpl, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) /* AllowTransitionalJSR292 ONLY */ \ + do_intrinsic(_checkSpreadArgument_TRANS2,java_dyn_MethodHandleNatives, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) /* AllowTransitionalJSR292 ONLY */ \ do_name( checkSpreadArgument_name, "checkSpreadArgument") \ do_name( checkSpreadArgument_signature, "(Ljava/lang/Object;I)V") \ - do_intrinsic(_invokeExact, java_dyn_MethodHandle, invokeExact_name, object_array_object_signature, F_RN) \ - do_intrinsic(_invokeGeneric, java_dyn_MethodHandle, invokeGeneric_name, object_array_object_signature, F_RN) \ - do_intrinsic(_invokeVarargs, java_dyn_MethodHandle, invokeVarargs_name, object_array_object_signature, F_R) \ - do_intrinsic(_invokeDynamic, java_dyn_InvokeDynamic, star_name, object_array_object_signature, F_SN) \ + do_intrinsic(_invokeExact, java_lang_invoke_MethodHandle, invokeExact_name, object_array_object_signature, F_RN) \ + do_intrinsic(_invokeGeneric, java_lang_invoke_MethodHandle, invokeGeneric_name, object_array_object_signature, F_RN) \ + do_intrinsic(_invokeVarargs, java_lang_invoke_MethodHandle, invokeVarargs_name, object_array_object_signature, F_R) \ + do_intrinsic(_invokeDynamic, java_lang_invoke_InvokeDynamic, star_name, object_array_object_signature, F_SN) \ \ /* unboxing methods: */ \ do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \ @@ -995,6 +1024,7 @@ // Returns symbol's SID if one is assigned, else NO_SID. static SID find_sid(Symbol* symbol); + static SID find_sid(const char* symbol_name); #ifndef PRODUCT // No need for this in the product:
--- a/hotspot/src/share/vm/code/codeCache.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/code/codeCache.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -337,7 +337,6 @@ if (is_live) { // Perform cur->oops_do(f), maybe just once per nmethod. f->do_code_blob(cur); - cur->fix_oop_relocations(); } } @@ -552,6 +551,19 @@ } +void CodeCache::verify_oops() { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + VerifyOopClosure voc; + FOR_ALL_ALIVE_BLOBS(cb) { + if (cb->is_nmethod()) { + nmethod *nm = (nmethod*)cb; + nm->oops_do(&voc); + nm->verify_oop_relocations(); + } + } +} + + address CodeCache::first_address() { assert_locked_or_safepoint(CodeCache_lock); return (address)_heap->begin(); @@ -939,9 +951,16 @@ _heap->high(), _heap->high_boundary()); st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT - " adapters=" UINT32_FORMAT " free_code_cache=" SIZE_FORMAT + " adapters=" UINT32_FORMAT " free_code_cache=" SIZE_FORMAT "Kb" " largest_free_block=" SIZE_FORMAT, - CodeCache::nof_blobs(), CodeCache::nof_nmethods(), - CodeCache::nof_adapters(), CodeCache::unallocated_capacity(), - CodeCache::largest_free_block()); + nof_blobs(), nof_nmethods(), nof_adapters(), + unallocated_capacity()/K, largest_free_block()); } + +void CodeCache::log_state(outputStream* st) { + st->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'" + " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'" + " largest_free_block='" SIZE_FORMAT "'", + nof_blobs(), nof_nmethods(), nof_adapters(), + unallocated_capacity(), largest_free_block()); +}
--- a/hotspot/src/share/vm/code/codeCache.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/code/codeCache.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -122,6 +122,7 @@ // GC support static void gc_epilogue(); static void gc_prologue(); + static void verify_oops(); // If "unloading_occurred" is true, then unloads (i.e., breaks root links // to) any unmarked codeBlobs in the cache. Sets "marked_for_unloading" // to "true" iff some code got unloaded. @@ -147,6 +148,7 @@ static void verify(); // verifies the code cache static void print_trace(const char* event, CodeBlob* cb, int size = 0) PRODUCT_RETURN; static void print_bounds(outputStream* st); // Prints a summary of the bounds of the code cache + static void log_state(outputStream* st); // The full limits of the codeCache static address low_bound() { return (address) _heap->low_boundary(); } @@ -159,7 +161,7 @@ static size_t max_capacity() { return _heap->max_capacity(); } static size_t unallocated_capacity() { return _heap->unallocated_capacity(); } static size_t largest_free_block() { return _heap->largest_free_block(); } - static bool needs_flushing() { return unallocated_capacity() < CodeCacheFlushingMinimumFreeSpace; } + static bool needs_flushing() { return largest_free_block() < CodeCacheFlushingMinimumFreeSpace; } static bool needs_cache_clean() { return _needs_cache_clean; } static void set_needs_cache_clean(bool v) { _needs_cache_clean = v; }
--- a/hotspot/src/share/vm/code/nmethod.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/code/nmethod.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -170,7 +170,7 @@ int pc_desc_resets; // number of resets (= number of caches) int pc_desc_queries; // queries to nmethod::find_pc_desc int pc_desc_approx; // number of those which have approximate true - int pc_desc_repeats; // number of _last_pc_desc hits + int pc_desc_repeats; // number of _pc_descs[0] hits int pc_desc_hits; // number of LRU cache hits int pc_desc_tests; // total number of PcDesc examinations int pc_desc_searches; // total number of quasi-binary search steps @@ -278,40 +278,44 @@ void PcDescCache::reset_to(PcDesc* initial_pc_desc) { if (initial_pc_desc == NULL) { - _last_pc_desc = NULL; // native method + _pc_descs[0] = NULL; // native method; no PcDescs at all return; } NOT_PRODUCT(++nmethod_stats.pc_desc_resets); // reset the cache by filling it with benign (non-null) values assert(initial_pc_desc->pc_offset() < 0, "must be sentinel"); - _last_pc_desc = initial_pc_desc + 1; // first valid one is after sentinel for (int i = 0; i < cache_size; i++) _pc_descs[i] = initial_pc_desc; } PcDesc* PcDescCache::find_pc_desc(int pc_offset, bool approximate) { NOT_PRODUCT(++nmethod_stats.pc_desc_queries); - NOT_PRODUCT(if (approximate) ++nmethod_stats.pc_desc_approx); + NOT_PRODUCT(if (approximate) ++nmethod_stats.pc_desc_approx); + + // Note: one might think that caching the most recently + // read value separately would be a win, but one would be + // wrong. When many threads are updating it, the cache + // line it's in would bounce between caches, negating + // any benefit. // In order to prevent race conditions do not load cache elements // repeatedly, but use a local copy: PcDesc* res; - // Step one: Check the most recently returned value. - res = _last_pc_desc; - if (res == NULL) return NULL; // native method; no PcDescs at all + // Step one: Check the most recently added value. + res = _pc_descs[0]; + if (res == NULL) return NULL; // native method; no PcDescs at all if (match_desc(res, pc_offset, approximate)) { NOT_PRODUCT(++nmethod_stats.pc_desc_repeats); return res; } - // Step two: Check the LRU cache. - for (int i = 0; i < cache_size; i++) { + // Step two: Check the rest of the LRU cache. + for (int i = 1; i < cache_size; ++i) { res = _pc_descs[i]; - if (res->pc_offset() < 0) break; // optimization: skip empty cache + if (res->pc_offset() < 0) break; // optimization: skip empty cache if (match_desc(res, pc_offset, approximate)) { NOT_PRODUCT(++nmethod_stats.pc_desc_hits); - _last_pc_desc = res; // record this cache hit in case of repeat return res; } } @@ -322,24 +326,23 @@ void PcDescCache::add_pc_desc(PcDesc* pc_desc) { NOT_PRODUCT(++nmethod_stats.pc_desc_adds); - // Update the LRU cache by shifting pc_desc forward: + // Update the LRU cache by shifting pc_desc forward. for (int i = 0; i < cache_size; i++) { PcDesc* next = _pc_descs[i]; _pc_descs[i] = pc_desc; pc_desc = next; } - // Note: Do not update _last_pc_desc. It fronts for the LRU cache. } // adjust pcs_size so that it is a multiple of both oopSize and // sizeof(PcDesc) (assumes that if sizeof(PcDesc) is not a multiple // of oopSize, then 2*sizeof(PcDesc) is) -static int adjust_pcs_size(int pcs_size) { +static int adjust_pcs_size(int pcs_size) { int nsize = round_to(pcs_size, oopSize); if ((nsize % sizeof(PcDesc)) != 0) { nsize = pcs_size + sizeof(PcDesc); } - assert((nsize % oopSize) == 0, "correct alignment"); + assert((nsize % oopSize) == 0, "correct alignment"); return nsize; } @@ -650,6 +653,9 @@ _pc_desc_cache.reset_to(NULL); code_buffer->copy_oops_to(this); + if (ScavengeRootsInCode && detect_scavenge_root_oops()) { + CodeCache::add_scavenge_root_nmethod(this); + } debug_only(verify_scavenge_root_oops()); CodeCache::commit(this); } @@ -762,7 +768,7 @@ void* nmethod::operator new(size_t size, int nmethod_size) { // Always leave some room in the CodeCache for I2C/C2I adapters - if (CodeCache::unallocated_capacity() < CodeCacheMinimumFreeSpace) return NULL; + if (CodeCache::largest_free_block() < CodeCacheMinimumFreeSpace) return NULL; return CodeCache::allocate(nmethod_size); } @@ -1102,6 +1108,20 @@ } +void nmethod::verify_oop_relocations() { + // Ensure sure that the code matches the current oop values + RelocIterator iter(this, NULL, NULL); + while (iter.next()) { + if (iter.type() == relocInfo::oop_type) { + oop_Relocation* reloc = iter.oop_reloc(); + if (!reloc->oop_is_immediate()) { + reloc->verify_oop_relocation(); + } + } + } +} + + ScopeDesc* nmethod::scope_desc_at(address pc) { PcDesc* pd = pc_desc_at(pc); guarantee(pd != NULL, "scope must be present"); @@ -1180,14 +1200,17 @@ set_stack_traversal_mark(NMethodSweeper::traversal_count()); } -// Tell if a non-entrant method can be converted to a zombie (i.e., there is no activations on the stack) +// Tell if a non-entrant method can be converted to a zombie (i.e., +// there are no activations on the stack, not in use by the VM, +// and not in use by the ServiceThread) bool nmethod::can_not_entrant_be_converted() { assert(is_not_entrant(), "must be a non-entrant method"); // Since the nmethod sweeper only does partial sweep the sweeper's traversal // count can be greater than the stack traversal count before it hits the // nmethod for the second time. - return stack_traversal_mark()+1 < NMethodSweeper::traversal_count(); + return stack_traversal_mark()+1 < NMethodSweeper::traversal_count() && + !is_locked_by_vm(); } void nmethod::inc_decompile_count() { @@ -1294,6 +1317,7 @@ // Common functionality for both make_not_entrant and make_zombie bool nmethod::make_not_entrant_or_zombie(unsigned int state) { assert(state == zombie || state == not_entrant, "must be zombie or not_entrant"); + assert(!is_zombie(), "should not already be a zombie"); // Make sure neither the nmethod nor the method is flushed in case of a safepoint in code below. nmethodLocker nml(this); @@ -1301,11 +1325,6 @@ No_Safepoint_Verifier nsv; { - // If the method is already zombie there is nothing to do - if (is_zombie()) { - return false; - } - // invalidate osr nmethod before acquiring the patching lock since // they both acquire leaf locks and we don't want a deadlock. // This logic is equivalent to the logic below for patching the @@ -1375,13 +1394,12 @@ flush_dependencies(NULL); } - { - // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload event - // and it hasn't already been reported for this nmethod then report it now. - // (the event may have been reported earilier if the GC marked it for unloading). - Pause_No_Safepoint_Verifier pnsv(&nsv); - post_compiled_method_unload(); - } + // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload + // event and it hasn't already been reported for this nmethod then + // report it now. The event may have been reported earilier if the GC + // marked it for unloading). JvmtiDeferredEventQueue support means + // we no longer go to a safepoint here. + post_compiled_method_unload(); #ifdef ASSERT // It's no longer safe to access the oops section since zombie @@ -1566,7 +1584,7 @@ if (_jmethod_id != NULL && JvmtiExport::should_post_compiled_method_unload()) { assert(!unload_reported(), "already unloaded"); JvmtiDeferredEvent event = - JvmtiDeferredEvent::compiled_method_unload_event( + JvmtiDeferredEvent::compiled_method_unload_event(this, _jmethod_id, insts_begin()); if (SafepointSynchronize::is_at_safepoint()) { // Don't want to take the queueing lock. Add it as pending and @@ -1822,6 +1840,7 @@ assert(cur != NULL, "not NULL-terminated"); nmethod* next = cur->_oops_do_mark_link; cur->_oops_do_mark_link = NULL; + cur->fix_oop_relocations(); NOT_PRODUCT(if (TraceScavenge) cur->print_on(tty, "oops_do, unmark\n")); cur = next; } @@ -1881,7 +1900,7 @@ oop nmethod::embeddedOop_at(u_char* p) { - RelocIterator iter(this, p, p + oopSize); + RelocIterator iter(this, p, p + 1); while (iter.next()) if (iter.type() == relocInfo::oop_type) { return iter.oop_reloc()->oop_value(); @@ -2171,10 +2190,12 @@ lock_nmethod(_nm); } -void nmethodLocker::lock_nmethod(nmethod* nm) { +// Only JvmtiDeferredEvent::compiled_method_unload_event() +// should pass zombie_ok == true. +void nmethodLocker::lock_nmethod(nmethod* nm, bool zombie_ok) { if (nm == NULL) return; Atomic::inc(&nm->_lock_count); - guarantee(!nm->is_zombie(), "cannot lock a zombie method"); + guarantee(zombie_ok || !nm->is_zombie(), "cannot lock a zombie method"); } void nmethodLocker::unlock_nmethod(nmethod* nm) {
--- a/hotspot/src/share/vm/code/nmethod.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/code/nmethod.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -69,14 +69,13 @@ friend class VMStructs; private: enum { cache_size = 4 }; - PcDesc* _last_pc_desc; // most recent pc_desc found PcDesc* _pc_descs[cache_size]; // last cache_size pc_descs found public: - PcDescCache() { debug_only(_last_pc_desc = NULL); } + PcDescCache() { debug_only(_pc_descs[0] = NULL); } void reset_to(PcDesc* initial_pc_desc); PcDesc* find_pc_desc(int pc_offset, bool approximate); void add_pc_desc(PcDesc* pc_desc); - PcDesc* last_pc_desc() { return _last_pc_desc; } + PcDesc* last_pc_desc() { return _pc_descs[0]; } }; @@ -178,7 +177,7 @@ unsigned int _has_method_handle_invokes:1; // Has this method MethodHandle invokes? // Protected by Patching_lock - unsigned char _state; // {alive, not_entrant, zombie, unloaded) + unsigned char _state; // {alive, not_entrant, zombie, unloaded} #ifdef ASSERT bool _oops_are_stale; // indicates that it's no longer safe to access oops section @@ -194,7 +193,10 @@ NOT_PRODUCT(bool _has_debug_info; ) - // Nmethod Flushing lock (if non-zero, then the nmethod is not removed) + // Nmethod Flushing lock. If non-zero, then the nmethod is not removed + // and is not made into a zombie. However, once the nmethod is made into + // a zombie, it will be locked one final time if CompiledMethodUnload + // event processing needs to be done. jint _lock_count; // not_entrant method removal. Each mark_sweep pass will update @@ -457,6 +459,7 @@ public: void fix_oop_relocations(address begin, address end) { fix_oop_relocations(begin, end, false); } void fix_oop_relocations() { fix_oop_relocations(NULL, NULL, false); } + void verify_oop_relocations(); bool is_at_poll_return(address pc); bool is_at_poll_or_poll_return(address pc); @@ -522,8 +525,9 @@ void flush(); public: - // If returning true, it is unsafe to remove this nmethod even though it is a zombie - // nmethod, since the VM might have a reference to it. Should only be called from a safepoint. + // When true is returned, it is unsafe to remove this nmethod even if + // it is a zombie, since the VM or the ServiceThread might still be + // using it. bool is_locked_by_vm() const { return _lock_count >0; } // See comment at definition of _last_seen_on_stack @@ -689,13 +693,20 @@ }; -// Locks an nmethod so its code will not get removed, even if it is a zombie/not_entrant method +// Locks an nmethod so its code will not get removed and it will not +// be made into a zombie, even if it is a not_entrant method. After the +// nmethod becomes a zombie, if CompiledMethodUnload event processing +// needs to be done, then lock_nmethod() is used directly to keep the +// generated code from being reused too early. class nmethodLocker : public StackObj { nmethod* _nm; public: - static void lock_nmethod(nmethod* nm); // note: nm can be NULL + // note: nm can be NULL + // Only JvmtiDeferredEvent::compiled_method_unload_event() + // should pass zombie_ok == true. + static void lock_nmethod(nmethod* nm, bool zombie_ok = false); static void unlock_nmethod(nmethod* nm); // (ditto) nmethodLocker(address pc); // derive nm from pc
--- a/hotspot/src/share/vm/code/relocInfo.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/code/relocInfo.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -798,6 +798,14 @@ } +void oop_Relocation::verify_oop_relocation() { + if (!oop_is_immediate()) { + // get the oop from the pool, and re-insert it into the instruction: + verify_value(value()); + } +} + + RelocIterator virtual_call_Relocation::parse_ic(nmethod* &nm, address &ic_call, address &first_oop, oop* &oop_addr, bool *is_optimized) { assert(ic_call != NULL, "ic_call address must be set");
--- a/hotspot/src/share/vm/code/relocInfo.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/code/relocInfo.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -765,7 +765,8 @@ protected: // platform-dependent utilities for decoding and patching instructions - void pd_set_data_value (address x, intptr_t off); // a set or mem-ref + void pd_set_data_value (address x, intptr_t off, bool verify_only = false); // a set or mem-ref + void pd_verify_data_value (address x, intptr_t off) { pd_set_data_value(x, off, true); } address pd_call_destination (address orig_addr = NULL); void pd_set_call_destination (address x); void pd_swap_in_breakpoint (address x, short* instrs, int instrlen); @@ -880,6 +881,12 @@ else pd_set_data_value(x, o); } + void verify_value(address x) { + if (addr_in_const()) + assert(*(address*)addr() == x, "must agree"); + else + pd_verify_data_value(x, offset()); + } // The "o" (displacement) argument is relevant only to split relocations // on RISC machines. In some CPUs (SPARC), the set-hi and set-lo ins'ns @@ -950,6 +957,8 @@ void fix_oop_relocation(); // reasserts oop value + void verify_oop_relocation(); + address value() { return (address) *oop_addr(); } bool oop_is_immediate() { return oop_index() == 0; }
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1364,7 +1364,7 @@ // We need this HandleMark to avoid leaking VM handles. HandleMark hm(thread); - if (CodeCache::unallocated_capacity() < CodeCacheMinimumFreeSpace) { + if (CodeCache::largest_free_block() < CodeCacheMinimumFreeSpace) { // the code cache is really full handle_full_code_cache(); } else if (UseCodeCacheFlushing && CodeCache::needs_flushing()) { @@ -1645,11 +1645,13 @@ if (UseCompiler || AlwaysCompileLoopMethods ) { if (xtty != NULL) { xtty->begin_elem("code_cache_full"); + CodeCache::log_state(xtty); xtty->stamp(); xtty->end_elem(); } warning("CodeCache is full. Compiler has been disabled."); warning("Try increasing the code cache size using -XX:ReservedCodeCacheSize="); + CodeCache::print_bounds(tty); #ifndef PRODUCT if (CompileTheWorld || ExitOnFullCodeCache) { before_exit(JavaThread::current());
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -292,13 +292,15 @@ void CMSCollector::ref_processor_init() { if (_ref_processor == NULL) { // Allocate and initialize a reference processor - _ref_processor = ReferenceProcessor::create_ref_processor( - _span, // span - _cmsGen->refs_discovery_is_atomic(), // atomic_discovery - _cmsGen->refs_discovery_is_mt(), // mt_discovery - &_is_alive_closure, - ParallelGCThreads, - ParallelRefProcEnabled); + _ref_processor = + new ReferenceProcessor(_span, // span + (ParallelGCThreads > 1) && ParallelRefProcEnabled, // mt processing + (int) ParallelGCThreads, // mt processing degree + _cmsGen->refs_discovery_is_mt(), // mt discovery + (int) MAX2(ConcGCThreads, ParallelGCThreads), // mt discovery degree + _cmsGen->refs_discovery_is_atomic(), // discovery is not atomic + &_is_alive_closure, // closure for liveness info + false); // next field updates do not need write barrier // Initialize the _ref_processor field of CMSGen _cmsGen->set_ref_processor(_ref_processor); @@ -641,7 +643,7 @@ } // Support for multi-threaded concurrent phases - if (CollectedHeap::use_parallel_gc_threads() && CMSConcurrentMTEnabled) { + if (CMSConcurrentMTEnabled) { if (FLAG_IS_DEFAULT(ConcGCThreads)) { // just for now FLAG_SET_DEFAULT(ConcGCThreads, (ParallelGCThreads + 3)/4); @@ -1689,6 +1691,8 @@ MutexLockerEx y(CGC_lock, Mutex::_no_safepoint_check_flag); _full_gc_requested = true; CGC_lock->notify(); // nudge CMS thread + } else { + assert(gc_count > full_gc_count, "Error: causal loop"); } } @@ -1988,17 +1992,16 @@ // Temporarily widen the span of the weak reference processing to // the entire heap. MemRegion new_span(GenCollectedHeap::heap()->reserved_region()); - ReferenceProcessorSpanMutator x(ref_processor(), new_span); - + ReferenceProcessorSpanMutator rp_mut_span(ref_processor(), new_span); // Temporarily, clear the "is_alive_non_header" field of the // reference processor. - ReferenceProcessorIsAliveMutator y(ref_processor(), NULL); - + ReferenceProcessorIsAliveMutator rp_mut_closure(ref_processor(), NULL); // Temporarily make reference _processing_ single threaded (non-MT). - ReferenceProcessorMTProcMutator z(ref_processor(), false); - + ReferenceProcessorMTProcMutator rp_mut_mt_processing(ref_processor(), false); // Temporarily make refs discovery atomic - ReferenceProcessorAtomicMutator w(ref_processor(), true); + ReferenceProcessorAtomicMutator rp_mut_atomic(ref_processor(), true); + // Temporarily make reference _discovery_ single threaded (non-MT) + ReferenceProcessorMTDiscoveryMutator rp_mut_discovery(ref_processor(), false); ref_processor()->set_enqueuing_is_done(false); ref_processor()->enable_discovery(); @@ -4263,9 +4266,7 @@ // Refs discovery is already non-atomic. assert(!ref_processor()->discovery_is_atomic(), "Should be non-atomic"); - // Mutate the Refs discovery so it is MT during the - // multi-threaded marking phase. - ReferenceProcessorMTMutator mt(ref_processor(), num_workers > 1); + assert(ref_processor()->discovery_is_mt(), "Discovery should be MT"); DEBUG_ONLY(RememberKlassesChecker cmx(should_unload_classes());) conc_workers()->start_task(&tsk); while (tsk.yielded()) { @@ -4318,6 +4319,8 @@ ResourceMark rm; HandleMark hm; + // Temporarily make refs discovery single threaded (non-MT) + ReferenceProcessorMTDiscoveryMutator rp_mut_discovery(ref_processor(), false); MarkFromRootsClosure markFromRootsClosure(this, _span, &_markBitMap, &_markStack, &_revisitStack, CMSYield && asynch); // the last argument to iterate indicates whether the iteration @@ -4356,10 +4359,6 @@ verify_overflow_empty(); _abort_preclean = false; if (CMSPrecleaningEnabled) { - // Precleaning is currently not MT but the reference processor - // may be set for MT. Disable it temporarily here. - ReferenceProcessor* rp = ref_processor(); - ReferenceProcessorMTProcMutator z(rp, false); _eden_chunk_index = 0; size_t used = get_eden_used(); size_t capacity = get_eden_capacity(); @@ -4502,11 +4501,16 @@ _collectorState == AbortablePreclean, "incorrect state"); ResourceMark rm; HandleMark hm; + + // Precleaning is currently not MT but the reference processor + // may be set for MT. Disable it temporarily here. + ReferenceProcessor* rp = ref_processor(); + ReferenceProcessorMTDiscoveryMutator rp_mut_discovery(rp, false); + // Do one pass of scrubbing the discovered reference lists // to remove any reference objects with strongly-reachable // referents. if (clean_refs) { - ReferenceProcessor* rp = ref_processor(); CMSPrecleanRefsYieldClosure yield_cl(this); assert(rp->span().equals(_span), "Spans should be equal"); CMSKeepAliveClosure keep_alive(this, _span, &_markBitMap, @@ -5576,8 +5580,10 @@ // in the multi-threaded case, but we special-case n=1 here to get // repeatable measurements of the 1-thread overhead of the parallel code. if (n_workers > 1) { - // Make refs discovery MT-safe - ReferenceProcessorMTMutator mt(ref_processor(), true); + // Make refs discovery MT-safe, if it isn't already: it may not + // necessarily be so, since it's possible that we are doing + // ST marking. + ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), true); GenCollectedHeap::StrongRootsScope srs(gch); workers->run_task(&tsk); } else { @@ -5703,14 +5709,19 @@ CMSBitMap* mark_bit_map, AbstractWorkGang* workers, OopTaskQueueSet* task_queues): + // XXX Should superclass AGTWOQ also know about AWG since it knows + // about the task_queues used by the AWG? Then it could initialize + // the terminator() object. See 6984287. The set_for_termination() + // below is a temporary band-aid for the regression in 6984287. AbstractGangTaskWOopQueues("Process referents by policy in parallel", task_queues), _task(task), _collector(collector), _span(span), _mark_bit_map(mark_bit_map) - { - assert(_collector->_span.equals(_span) && !_span.is_empty(), - "Inconsistency in _span"); - } + { + assert(_collector->_span.equals(_span) && !_span.is_empty(), + "Inconsistency in _span"); + set_for_termination(workers->active_workers()); + } OopTaskQueueSet* task_queues() { return queues(); } @@ -5872,8 +5883,7 @@ // That is OK as long as the Reference lists are balanced (see // balance_all_queues() and balance_queues()). - - rp->set_mt_degree(ParallelGCThreads); + rp->set_active_mt_degree(ParallelGCThreads); CMSRefProcTaskExecutor task_executor(*this); rp->process_discovered_references(&_is_alive_closure, &cmsKeepAliveClosure, @@ -5920,14 +5930,18 @@ } { - TraceTime t("scrub symbol & string tables", PrintGCDetails, false, gclog_or_tty); - // Now clean up stale oops in StringTable - StringTable::unlink(&_is_alive_closure); + TraceTime t("scrub symbol table", PrintGCDetails, false, gclog_or_tty); // Clean up unreferenced symbols in symbol table. SymbolTable::unlink(); } } + if (should_unload_classes() || !JavaObjectsInPerm) { + TraceTime t("scrub string table", PrintGCDetails, false, gclog_or_tty); + // Now clean up stale oops in StringTable + StringTable::unlink(&_is_alive_closure); + } + verify_work_stacks_empty(); // Restore any preserved marks as a result of mark stack or // work queue overflow
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1133,7 +1133,7 @@ // rare that the cost of the CAS's involved is in the // noise. That's a measurement that should be done, and // the code simplified if that turns out to be the case. - return false; + return ConcGCThreads > 1; } // Override
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ volatile jint ConcurrentMarkSweepThread::_pending_yields = 0; volatile jint ConcurrentMarkSweepThread::_pending_decrements = 0; -volatile bool ConcurrentMarkSweepThread::_icms_enabled = false; +volatile jint ConcurrentMarkSweepThread::_icms_disabled = 0; volatile bool ConcurrentMarkSweepThread::_should_run = false; // When icms is enabled, the icms thread is stopped until explicitly // started. @@ -84,7 +84,7 @@ } } _sltMonitor = SLT_lock; - set_icms_enabled(CMSIncrementalMode); + assert(!CMSIncrementalMode || icms_is_enabled(), "Error"); } void ConcurrentMarkSweepThread::run() { @@ -341,11 +341,11 @@ void ConcurrentMarkSweepThread::icms_wait() { assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking"); - if (_should_stop && icms_enabled()) { + if (_should_stop && icms_is_enabled()) { MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag); trace_state("pause_icms"); _collector->stats().stop_cms_timer(); - while(!_should_run && icms_enabled()) { + while(!_should_run && icms_is_enabled()) { iCMS_lock->wait(Mutex::_no_safepoint_check_flag); } _collector->stats().start_cms_timer();
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ class ConcurrentMarkSweepGeneration; class CMSCollector; -// The Concurrent Mark Sweep GC Thread (could be several in the future). +// The Concurrent Mark Sweep GC Thread class ConcurrentMarkSweepThread: public ConcurrentGCThread { friend class VMStructs; friend class ConcurrentMarkSweepGeneration; // XXX should remove friendship @@ -55,8 +55,6 @@ static SurrogateLockerThread::SLT_msg_type _sltBuffer; static Monitor* _sltMonitor; - ConcurrentMarkSweepThread* _next; - static bool _should_terminate; enum CMS_flag_type { @@ -84,7 +82,7 @@ // Tracing messages, enabled by CMSTraceThreadState. static inline void trace_state(const char* desc); - static volatile bool _icms_enabled; // iCMS enabled? + static volatile int _icms_disabled; // a counter to track #iCMS disable & enable static volatile bool _should_run; // iCMS may run static volatile bool _should_stop; // iCMS should stop @@ -214,10 +212,25 @@ // Incremental mode is enabled globally by the flag CMSIncrementalMode. It // must also be enabled/disabled dynamically to allow foreground collections. - static inline void enable_icms() { _icms_enabled = true; } - static inline void disable_icms() { _icms_enabled = false; } - static inline void set_icms_enabled(bool val) { _icms_enabled = val; } - static inline bool icms_enabled() { return _icms_enabled; } +#define ICMS_ENABLING_ASSERT \ + assert((CMSIncrementalMode && _icms_disabled >= 0) || \ + (!CMSIncrementalMode && _icms_disabled <= 0), "Error") + + static inline void enable_icms() { + ICMS_ENABLING_ASSERT; + Atomic::dec(&_icms_disabled); + } + static inline void disable_icms() { + ICMS_ENABLING_ASSERT; + Atomic::inc(&_icms_disabled); + } + static inline bool icms_is_disabled() { + ICMS_ENABLING_ASSERT; + return _icms_disabled > 0; + } + static inline bool icms_is_enabled() { + return !icms_is_disabled(); + } }; inline void ConcurrentMarkSweepThread::trace_state(const char* desc) {
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -192,14 +192,18 @@ "total_collections() should be monotonically increasing"); MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag); + assert(_full_gc_count_before <= gch->total_full_collections(), "Error"); if (gch->total_full_collections() == _full_gc_count_before) { - // Disable iCMS until the full collection is done. + // Disable iCMS until the full collection is done, and + // remember that we did so. CMSCollector::disable_icms(); + _disabled_icms = true; // In case CMS thread was in icms_wait(), wake it up. CMSCollector::start_icms(); // Nudge the CMS thread to start a concurrent collection. CMSCollector::request_full_gc(_full_gc_count_before); } else { + assert(_full_gc_count_before < gch->total_full_collections(), "Error"); FullGCCount_lock->notify_all(); // Inform the Java thread its work is done } } @@ -259,6 +263,8 @@ FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag); } } - // Enable iCMS back. - CMSCollector::enable_icms(); + // Enable iCMS back if we disabled it earlier. + if (_disabled_icms) { + CMSCollector::enable_icms(); + } }
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -128,11 +128,14 @@ // VM operation to invoke a concurrent collection of the heap as a // GenCollectedHeap heap. class VM_GenCollectFullConcurrent: public VM_GC_Operation { + bool _disabled_icms; public: VM_GenCollectFullConcurrent(unsigned int gc_count_before, unsigned int full_gc_count_before, GCCause::Cause gc_cause) - : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */) { + : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */), + _disabled_icms(false) + { assert(FullGCCount_lock != NULL, "Error"); assert(UseAsyncConcMarkSweepGC, "Else will hang caller"); }
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -373,7 +373,7 @@ // RSet updating while within an evacuation pause. // In this case worker_i should be the id of a GC worker thread assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause"); - assert(worker_i < (int) DirtyCardQueueSet::num_par_ids(), "incorrect worker id"); + assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "incorrect worker id"); into_cset_dcq->enqueue(entry); } }
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1828,7 +1828,7 @@ G1CollectedHeap* g1h = G1CollectedHeap::heap(); _cleanup_list.verify_optional(); - FreeRegionList local_free_list("Local Cleanup List"); + FreeRegionList tmp_free_list("Tmp Free List"); if (G1ConcRegionFreeingVerbose) { gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : " @@ -1842,7 +1842,7 @@ HeapRegion* hr = _cleanup_list.remove_head(); assert(hr != NULL, "the list was not empty"); hr->rem_set()->clear(); - local_free_list.add_as_tail(hr); + tmp_free_list.add_as_tail(hr); // Instead of adding one region at a time to the secondary_free_list, // we accumulate them in the local list and move them a few at a @@ -1850,20 +1850,20 @@ // we do during this process. We'll also append the local list when // _cleanup_list is empty (which means we just removed the last // region from the _cleanup_list). - if ((local_free_list.length() % G1SecondaryFreeListAppendLength == 0) || + if ((tmp_free_list.length() % G1SecondaryFreeListAppendLength == 0) || _cleanup_list.is_empty()) { if (G1ConcRegionFreeingVerbose) { gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : " "appending "SIZE_FORMAT" entries to the " "secondary_free_list, clean list still has " SIZE_FORMAT" entries", - local_free_list.length(), + tmp_free_list.length(), _cleanup_list.length()); } { MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag); - g1h->secondary_free_list_add_as_tail(&local_free_list); + g1h->secondary_free_list_add_as_tail(&tmp_free_list); SecondaryFreeList_lock->notify_all(); } @@ -1874,7 +1874,7 @@ } } } - assert(local_free_list.is_empty(), "post-condition"); + assert(tmp_free_list.is_empty(), "post-condition"); } // Support closures for reference procssing in G1 @@ -2141,21 +2141,22 @@ G1CMKeepAliveClosure g1_keep_alive(g1h, this, nextMarkBitMap()); G1CMDrainMarkingStackClosure g1_drain_mark_stack(nextMarkBitMap(), &_markStack, &g1_keep_alive); - // We use the work gang from the G1CollectedHeap and we utilize all // the worker threads. - int active_workers = MAX2(MIN2(g1h->workers()->total_workers(), (int)_max_task_num), 1); + int active_workers = g1h->workers() ? g1h->workers()->total_workers() : 1; + active_workers = MAX2(MIN2(active_workers, (int)_max_task_num), 1); G1RefProcTaskExecutor par_task_executor(g1h, this, nextMarkBitMap(), g1h->workers(), active_workers); + if (rp->processing_is_mt()) { // Set the degree of MT here. If the discovery is done MT, there // may have been a different number of threads doing the discovery // and a different number of discovered lists may have Ref objects. // That is OK as long as the Reference lists are balanced (see // balance_all_queues() and balance_queues()). - rp->set_mt_degree(active_workers); + rp->set_active_mt_degree(active_workers); rp->process_discovered_references(&g1_is_alive, &g1_keep_alive, @@ -3182,7 +3183,7 @@ template <class T> void do_oop_work(T* p) { assert( _g1h->is_in_g1_reserved((HeapWord*) p), "invariant"); - assert(!_g1h->is_on_free_list( + assert(!_g1h->is_on_master_free_list( _g1h->heap_region_containing((HeapWord*) p)), "invariant"); oop obj = oopDesc::load_decode_heap_oop(p); @@ -3403,7 +3404,7 @@ void CMTask::push(oop obj) { HeapWord* objAddr = (HeapWord*) obj; assert(_g1h->is_in_g1_reserved(objAddr), "invariant"); - assert(!_g1h->is_on_free_list( + assert(!_g1h->is_on_master_free_list( _g1h->heap_region_containing((HeapWord*) objAddr)), "invariant"); assert(!_g1h->is_obj_ill(obj), "invariant"); assert(_nextMarkBitMap->isMarked(objAddr), "invariant"); @@ -3649,7 +3650,7 @@ (void*) obj); assert(_g1h->is_in_g1_reserved((HeapWord*) obj), "invariant" ); - assert(!_g1h->is_on_free_list( + assert(!_g1h->is_on_master_free_list( _g1h->heap_region_containing((HeapWord*) obj)), "invariant"); scan_object(obj);
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -237,9 +237,9 @@ // The following will finish freeing up any regions that we // found to be empty during cleanup. We'll do this part // without joining the suspendible set. If an evacuation pause - // takes places, then we would carry on freeing regions in + // takes place, then we would carry on freeing regions in // case they are needed by the pause. If a Full GC takes - // places, it would wait for us to process the regions + // place, it would wait for us to process the regions // reclaimed by cleanup. double cleanup_start_sec = os::elapsedTime();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -479,7 +479,7 @@ // Private methods. HeapRegion* -G1CollectedHeap::new_region_try_secondary_free_list(size_t word_size) { +G1CollectedHeap::new_region_try_secondary_free_list() { MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag); while (!_secondary_free_list.is_empty() || free_regions_coming()) { if (!_secondary_free_list.is_empty()) { @@ -531,7 +531,7 @@ gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : " "forced to look at the secondary_free_list"); } - res = new_region_try_secondary_free_list(word_size); + res = new_region_try_secondary_free_list(); if (res != NULL) { return res; } @@ -543,7 +543,7 @@ gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : " "res == NULL, trying the secondary_free_list"); } - res = new_region_try_secondary_free_list(word_size); + res = new_region_try_secondary_free_list(); } if (res == NULL && do_expand) { if (expand(word_size * HeapWordSize)) { @@ -579,6 +579,9 @@ int G1CollectedHeap::humongous_obj_allocate_find_first(size_t num_regions, size_t word_size) { + assert(isHumongous(word_size), "word_size should be humongous"); + assert(num_regions * HeapRegion::GrainWords >= word_size, "pre-condition"); + int first = -1; if (num_regions == 1) { // Only one region to allocate, no need to go through the slower @@ -600,7 +603,7 @@ // request. If we are only allocating one region we use the common // region allocation code (see above). wait_while_free_regions_coming(); - append_secondary_free_list_if_not_empty(); + append_secondary_free_list_if_not_empty_with_lock(); if (free_regions() >= num_regions) { first = _hrs->find_contiguous(num_regions); @@ -608,7 +611,7 @@ for (int i = first; i < first + (int) num_regions; ++i) { HeapRegion* hr = _hrs->at(i); assert(hr->is_empty(), "sanity"); - assert(is_on_free_list(hr), "sanity"); + assert(is_on_master_free_list(hr), "sanity"); hr->set_pending_removal(true); } _free_list.remove_all_pending(num_regions); @@ -618,6 +621,126 @@ return first; } +HeapWord* +G1CollectedHeap::humongous_obj_allocate_initialize_regions(int first, + size_t num_regions, + size_t word_size) { + assert(first != -1, "pre-condition"); + assert(isHumongous(word_size), "word_size should be humongous"); + assert(num_regions * HeapRegion::GrainWords >= word_size, "pre-condition"); + + // Index of last region in the series + 1. + int last = first + (int) num_regions; + + // We need to initialize the region(s) we just discovered. This is + // a bit tricky given that it can happen concurrently with + // refinement threads refining cards on these regions and + // potentially wanting to refine the BOT as they are scanning + // those cards (this can happen shortly after a cleanup; see CR + // 6991377). So we have to set up the region(s) carefully and in + // a specific order. + + // The word size sum of all the regions we will allocate. + size_t word_size_sum = num_regions * HeapRegion::GrainWords; + assert(word_size <= word_size_sum, "sanity"); + + // This will be the "starts humongous" region. + HeapRegion* first_hr = _hrs->at(first); + // The header of the new object will be placed at the bottom of + // the first region. + HeapWord* new_obj = first_hr->bottom(); + // This will be the new end of the first region in the series that + // should also match the end of the last region in the seriers. + HeapWord* new_end = new_obj + word_size_sum; + // This will be the new top of the first region that will reflect + // this allocation. + HeapWord* new_top = new_obj + word_size; + + // First, we need to zero the header of the space that we will be + // allocating. When we update top further down, some refinement + // threads might try to scan the region. By zeroing the header we + // ensure that any thread that will try to scan the region will + // come across the zero klass word and bail out. + // + // NOTE: It would not have been correct to have used + // CollectedHeap::fill_with_object() and make the space look like + // an int array. The thread that is doing the allocation will + // later update the object header to a potentially different array + // type and, for a very short period of time, the klass and length + // fields will be inconsistent. This could cause a refinement + // thread to calculate the object size incorrectly. + Copy::fill_to_words(new_obj, oopDesc::header_size(), 0); + + // We will set up the first region as "starts humongous". This + // will also update the BOT covering all the regions to reflect + // that there is a single object that starts at the bottom of the + // first region. + first_hr->set_startsHumongous(new_top, new_end); + + // Then, if there are any, we will set up the "continues + // humongous" regions. + HeapRegion* hr = NULL; + for (int i = first + 1; i < last; ++i) { + hr = _hrs->at(i); + hr->set_continuesHumongous(first_hr); + } + // If we have "continues humongous" regions (hr != NULL), then the + // end of the last one should match new_end. + assert(hr == NULL || hr->end() == new_end, "sanity"); + + // Up to this point no concurrent thread would have been able to + // do any scanning on any region in this series. All the top + // fields still point to bottom, so the intersection between + // [bottom,top] and [card_start,card_end] will be empty. Before we + // update the top fields, we'll do a storestore to make sure that + // no thread sees the update to top before the zeroing of the + // object header and the BOT initialization. + OrderAccess::storestore(); + + // Now that the BOT and the object header have been initialized, + // we can update top of the "starts humongous" region. + assert(first_hr->bottom() < new_top && new_top <= first_hr->end(), + "new_top should be in this region"); + first_hr->set_top(new_top); + + // Now, we will update the top fields of the "continues humongous" + // regions. The reason we need to do this is that, otherwise, + // these regions would look empty and this will confuse parts of + // G1. For example, the code that looks for a consecutive number + // of empty regions will consider them empty and try to + // re-allocate them. We can extend is_empty() to also include + // !continuesHumongous(), but it is easier to just update the top + // fields here. The way we set top for all regions (i.e., top == + // end for all regions but the last one, top == new_top for the + // last one) is actually used when we will free up the humongous + // region in free_humongous_region(). + hr = NULL; + for (int i = first + 1; i < last; ++i) { + hr = _hrs->at(i); + if ((i + 1) == last) { + // last continues humongous region + assert(hr->bottom() < new_top && new_top <= hr->end(), + "new_top should fall on this region"); + hr->set_top(new_top); + } else { + // not last one + assert(new_top > hr->end(), "new_top should be above this region"); + hr->set_top(hr->end()); + } + } + // If we have continues humongous regions (hr != NULL), then the + // end of the last one should match new_end and its top should + // match new_top. + assert(hr == NULL || + (hr->end() == new_end && hr->top() == new_top), "sanity"); + + assert(first_hr->used() == word_size * HeapWordSize, "invariant"); + _summary_bytes_used += first_hr->used(); + _humongous_set.add(first_hr); + + return new_obj; +} + // If could fit into free regions w/o expansion, try. // Otherwise, if can expand, do so. // Otherwise, if using ex regions might help, try with ex given back. @@ -653,121 +776,16 @@ } } + HeapWord* result = NULL; if (first != -1) { - // Index of last region in the series + 1. - int last = first + (int) num_regions; - - // We need to initialize the region(s) we just discovered. This is - // a bit tricky given that it can happen concurrently with - // refinement threads refining cards on these regions and - // potentially wanting to refine the BOT as they are scanning - // those cards (this can happen shortly after a cleanup; see CR - // 6991377). So we have to set up the region(s) carefully and in - // a specific order. - - // The word size sum of all the regions we will allocate. - size_t word_size_sum = num_regions * HeapRegion::GrainWords; - assert(word_size <= word_size_sum, "sanity"); - - // This will be the "starts humongous" region. - HeapRegion* first_hr = _hrs->at(first); - // The header of the new object will be placed at the bottom of - // the first region. - HeapWord* new_obj = first_hr->bottom(); - // This will be the new end of the first region in the series that - // should also match the end of the last region in the seriers. - HeapWord* new_end = new_obj + word_size_sum; - // This will be the new top of the first region that will reflect - // this allocation. - HeapWord* new_top = new_obj + word_size; - - // First, we need to zero the header of the space that we will be - // allocating. When we update top further down, some refinement - // threads might try to scan the region. By zeroing the header we - // ensure that any thread that will try to scan the region will - // come across the zero klass word and bail out. - // - // NOTE: It would not have been correct to have used - // CollectedHeap::fill_with_object() and make the space look like - // an int array. The thread that is doing the allocation will - // later update the object header to a potentially different array - // type and, for a very short period of time, the klass and length - // fields will be inconsistent. This could cause a refinement - // thread to calculate the object size incorrectly. - Copy::fill_to_words(new_obj, oopDesc::header_size(), 0); - - // We will set up the first region as "starts humongous". This - // will also update the BOT covering all the regions to reflect - // that there is a single object that starts at the bottom of the - // first region. - first_hr->set_startsHumongous(new_top, new_end); - - // Then, if there are any, we will set up the "continues - // humongous" regions. - HeapRegion* hr = NULL; - for (int i = first + 1; i < last; ++i) { - hr = _hrs->at(i); - hr->set_continuesHumongous(first_hr); - } - // If we have "continues humongous" regions (hr != NULL), then the - // end of the last one should match new_end. - assert(hr == NULL || hr->end() == new_end, "sanity"); - - // Up to this point no concurrent thread would have been able to - // do any scanning on any region in this series. All the top - // fields still point to bottom, so the intersection between - // [bottom,top] and [card_start,card_end] will be empty. Before we - // update the top fields, we'll do a storestore to make sure that - // no thread sees the update to top before the zeroing of the - // object header and the BOT initialization. - OrderAccess::storestore(); - - // Now that the BOT and the object header have been initialized, - // we can update top of the "starts humongous" region. - assert(first_hr->bottom() < new_top && new_top <= first_hr->end(), - "new_top should be in this region"); - first_hr->set_top(new_top); - - // Now, we will update the top fields of the "continues humongous" - // regions. The reason we need to do this is that, otherwise, - // these regions would look empty and this will confuse parts of - // G1. For example, the code that looks for a consecutive number - // of empty regions will consider them empty and try to - // re-allocate them. We can extend is_empty() to also include - // !continuesHumongous(), but it is easier to just update the top - // fields here. The way we set top for all regions (i.e., top == - // end for all regions but the last one, top == new_top for the - // last one) is actually used when we will free up the humongous - // region in free_humongous_region(). - hr = NULL; - for (int i = first + 1; i < last; ++i) { - hr = _hrs->at(i); - if ((i + 1) == last) { - // last continues humongous region - assert(hr->bottom() < new_top && new_top <= hr->end(), - "new_top should fall on this region"); - hr->set_top(new_top); - } else { - // not last one - assert(new_top > hr->end(), "new_top should be above this region"); - hr->set_top(hr->end()); - } - } - // If we have continues humongous regions (hr != NULL), then the - // end of the last one should match new_end and its top should - // match new_top. - assert(hr == NULL || - (hr->end() == new_end && hr->top() == new_top), "sanity"); - - assert(first_hr->used() == word_size * HeapWordSize, "invariant"); - _summary_bytes_used += first_hr->used(); - _humongous_set.add(first_hr); - - return new_obj; + result = + humongous_obj_allocate_initialize_regions(first, num_regions, word_size); + assert(result != NULL, "it should always return a valid result"); } verify_region_sets_optional(); - return NULL; + + return result; } void @@ -1389,7 +1407,7 @@ g1_policy()->record_full_collection_start(); wait_while_free_regions_coming(); - append_secondary_free_list_if_not_empty(); + append_secondary_free_list_if_not_empty_with_lock(); gc_prologue(true); increment_total_collections(true /* full gc */); @@ -1444,7 +1462,7 @@ // how reference processing currently works in G1. // Temporarily make reference _discovery_ single threaded (non-MT). - ReferenceProcessorMTMutator rp_disc_ser(ref_processor(), false); + ReferenceProcessorMTDiscoveryMutator rp_disc_ser(ref_processor(), false); // Temporarily make refs discovery atomic ReferenceProcessorAtomicMutator rp_disc_atomic(ref_processor(), true); @@ -2201,16 +2219,16 @@ SharedHeap::ref_processing_init(); MemRegion mr = reserved_region(); - _ref_processor = ReferenceProcessor::create_ref_processor( - mr, // span - false, // Reference discovery is not atomic - true, // mt_discovery - &_is_alive_closure, // is alive closure - // for efficiency - ParallelGCThreads, - ParallelRefProcEnabled, - true); // Setting next fields of discovered - // lists requires a barrier. + _ref_processor = + new ReferenceProcessor(mr, // span + ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing + (int) ParallelGCThreads, // degree of mt processing + ParallelGCThreads > 1 || ConcGCThreads > 1, // mt discovery + (int) MAX2(ParallelGCThreads, ConcGCThreads), // degree of mt discovery + false, // Reference discovery is not atomic + &_is_alive_closure, // is alive closure for efficiency + true); // Setting next fields of discovered + // lists requires a barrier. } size_t G1CollectedHeap::capacity() const { @@ -3377,15 +3395,14 @@ TraceMemoryManagerStats tms(false /* fullGC */); - // If there are any free regions available on the secondary_free_list - // make sure we append them to the free_list. However, we don't - // have to wait for the rest of the cleanup operation to - // finish. If it's still going on that's OK. If we run out of - // regions, the region allocation code will check the - // secondary_free_list and potentially wait if more free regions - // are coming (see new_region_try_secondary_free_list()). + // If the secondary_free_list is not empty, append it to the + // free_list. No need to wait for the cleanup operation to finish; + // the region allocation code will check the secondary_free_list + // and wait if necessary. If the G1StressConcRegionFreeing flag is + // set, skip this step so that the region allocation code has to + // get entries from the secondary_free_list. if (!G1StressConcRegionFreeing) { - append_secondary_free_list_if_not_empty(); + append_secondary_free_list_if_not_empty_with_lock(); } increment_gc_time_stamp(); @@ -5199,7 +5216,7 @@ size_t rs_lengths = 0; while (cur != NULL) { - assert(!is_on_free_list(cur), "sanity"); + assert(!is_on_master_free_list(cur), "sanity"); if (non_young) { if (cur->is_young()) { @@ -5543,13 +5560,10 @@ return; } - { - MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag); - // Make sure we append the secondary_free_list on the free_list so - // that all free regions we will come across can be safely - // attributed to the free_list. - append_secondary_free_list(); - } + // Make sure we append the secondary_free_list on the free_list so + // that all free regions we will come across can be safely + // attributed to the free_list. + append_secondary_free_list_if_not_empty_with_lock(); // Finally, make sure that the region accounting in the lists is // consistent with what we see in the heap.
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -56,7 +56,6 @@ class ConcurrentMark; class ConcurrentMarkThread; class ConcurrentG1Refine; -class ConcurrentZFThread; typedef OverflowTaskQueue<StarTask> RefToScanQueue; typedef GenericTaskQueueSet<RefToScanQueue> RefToScanQueueSet; @@ -64,12 +63,6 @@ typedef int RegionIdx_t; // needs to hold [ 0..max_regions() ) typedef int CardIdx_t; // needs to hold [ 0..CardsPerRegion ) -enum G1GCThreadGroups { - G1CRGroup = 0, - G1ZFGroup = 1, - G1CMGroup = 2 -}; - enum GCAllocPurpose { GCAllocForTenured, GCAllocForSurvived, @@ -294,9 +287,9 @@ // These are macros so that, if the assert fires, we get the correct // line number, file, etc. -#define heap_locking_asserts_err_msg(__extra_message) \ +#define heap_locking_asserts_err_msg(_extra_message_) \ err_msg("%s : Heap_lock locked: %s, at safepoint: %s, is VM thread: %s", \ - (__extra_message), \ + (_extra_message_), \ BOOL_TO_STR(Heap_lock->owned_by_self()), \ BOOL_TO_STR(SafepointSynchronize::is_at_safepoint()), \ BOOL_TO_STR(Thread::current()->is_VM_thread())) @@ -307,11 +300,11 @@ heap_locking_asserts_err_msg("should be holding the Heap_lock")); \ } while (0) -#define assert_heap_locked_or_at_safepoint(__should_be_vm_thread) \ +#define assert_heap_locked_or_at_safepoint(_should_be_vm_thread_) \ do { \ assert(Heap_lock->owned_by_self() || \ (SafepointSynchronize::is_at_safepoint() && \ - ((__should_be_vm_thread) == Thread::current()->is_VM_thread())), \ + ((_should_be_vm_thread_) == Thread::current()->is_VM_thread())), \ heap_locking_asserts_err_msg("should be holding the Heap_lock or " \ "should be at a safepoint")); \ } while (0) @@ -338,10 +331,10 @@ "should not be at a safepoint")); \ } while (0) -#define assert_at_safepoint(__should_be_vm_thread) \ +#define assert_at_safepoint(_should_be_vm_thread_) \ do { \ assert(SafepointSynchronize::is_at_safepoint() && \ - ((__should_be_vm_thread) == Thread::current()->is_VM_thread()), \ + ((_should_be_vm_thread_) == Thread::current()->is_VM_thread()), \ heap_locking_asserts_err_msg("should be at a safepoint")); \ } while (0) @@ -371,35 +364,40 @@ // will check whether there's anything available in the // secondary_free_list and/or wait for more regions to appear in that // list, if _free_regions_coming is set. - HeapRegion* new_region_try_secondary_free_list(size_t word_size); + HeapRegion* new_region_try_secondary_free_list(); - // It will try to allocate a single non-humongous HeapRegion - // sufficient for an allocation of the given word_size. If - // do_expand is true, it will attempt to expand the heap if - // necessary to satisfy the allocation request. Note that word_size - // is only used to make sure that we expand sufficiently but, given - // that the allocation request is assumed not to be humongous, - // having word_size is not strictly necessary (expanding by a single - // region will always be sufficient). But let's keep that parameter - // in case we need it in the future. + // Try to allocate a single non-humongous HeapRegion sufficient for + // an allocation of the given word_size. If do_expand is true, + // attempt to expand the heap if necessary to satisfy the allocation + // request. HeapRegion* new_region_work(size_t word_size, bool do_expand); - // It will try to allocate a new region to be used for allocation by - // mutator threads. It will not try to expand the heap if not region - // is available. + // Try to allocate a new region to be used for allocation by a + // mutator thread. Attempt to expand the heap if no region is + // available. HeapRegion* new_alloc_region(size_t word_size) { return new_region_work(word_size, false /* do_expand */); } - // It will try to allocate a new region to be used for allocation by - // a GC thread. It will try to expand the heap if no region is - // available. + // Try to allocate a new region to be used for allocation by a GC + // thread. Attempt to expand the heap if no region is available. HeapRegion* new_gc_alloc_region(int purpose, size_t word_size); + // Attempt to satisfy a humongous allocation request of the given + // size by finding a contiguous set of free regions of num_regions + // length and remove them from the master free list. Return the + // index of the first region or -1 if the search was unsuccessful. int humongous_obj_allocate_find_first(size_t num_regions, size_t word_size); - // Attempt to allocate an object of the given (very large) "word_size". - // Returns "NULL" on failure. + // Initialize a contiguous set of free regions of length num_regions + // and starting at index first so that they appear as a single + // humongous region. + HeapWord* humongous_obj_allocate_initialize_regions(int first, + size_t num_regions, + size_t word_size); + + // Attempt to allocate a humongous object of the given size. Return + // NULL if unsuccessful. HeapWord* humongous_obj_allocate(size_t word_size); // The following two methods, allocate_new_tlab() and @@ -776,7 +774,7 @@ // Invoke "save_marks" on all heap regions. void save_marks(); - // It frees a non-humongous region by initializing its contents and + // Frees a non-humongous region by initializing its contents and // adding it to the free list that's passed as a parameter (this is // usually a local list which will be appended to the master free // list later). The used bytes of freed regions are accumulated in @@ -787,13 +785,13 @@ FreeRegionList* free_list, bool par); - // It frees a humongous region by collapsing it into individual - // regions and calling free_region() for each of them. The freed - // regions will be added to the free list that's passed as a parameter - // (this is usually a local list which will be appended to the - // master free list later). The used bytes of freed regions are - // accumulated in pre_used. If par is true, the region's RSet will - // not be freed up. The assumption is that this will be done later. + // Frees a humongous region by collapsing it into individual regions + // and calling free_region() for each of them. The freed regions + // will be added to the free list that's passed as a parameter (this + // is usually a local list which will be appended to the master free + // list later). The used bytes of freed regions are accumulated in + // pre_used. If par is true, the region's RSet will not be freed + // up. The assumption is that this will be done later. void free_humongous_region(HeapRegion* hr, size_t* pre_used, FreeRegionList* free_list, @@ -1046,13 +1044,13 @@ #endif // HEAP_REGION_SET_FORCE_VERIFY #ifdef ASSERT - bool is_on_free_list(HeapRegion* hr) { + bool is_on_master_free_list(HeapRegion* hr) { return hr->containing_set() == &_free_list; } - bool is_on_humongous_set(HeapRegion* hr) { + bool is_in_humongous_set(HeapRegion* hr) { return hr->containing_set() == &_humongous_set; -} + } #endif // ASSERT // Wrapper for the region list operations that can be called from @@ -1066,7 +1064,9 @@ _free_list.add_as_tail(&_secondary_free_list); } - void append_secondary_free_list_if_not_empty() { + void append_secondary_free_list_if_not_empty_with_lock() { + // If the secondary free list looks empty there's no reason to + // take the lock and then try to append it. if (!_secondary_free_list.is_empty()) { MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag); append_secondary_free_list();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -81,6 +81,57 @@ // </NEW PREDICTION> +// Help class for avoiding interleaved logging +class LineBuffer: public StackObj { + +private: + static const int BUFFER_LEN = 1024; + static const int INDENT_CHARS = 3; + char _buffer[BUFFER_LEN]; + int _indent_level; + int _cur; + + void vappend(const char* format, va_list ap) { + int res = vsnprintf(&_buffer[_cur], BUFFER_LEN - _cur, format, ap); + if (res != -1) { + _cur += res; + } else { + DEBUG_ONLY(warning("buffer too small in LineBuffer");) + _buffer[BUFFER_LEN -1] = 0; + _cur = BUFFER_LEN; // vsnprintf above should not add to _buffer if we are called again + } + } + +public: + explicit LineBuffer(int indent_level): _indent_level(indent_level), _cur(0) { + for (; (_cur < BUFFER_LEN && _cur < (_indent_level * INDENT_CHARS)); _cur++) { + _buffer[_cur] = ' '; + } + } + +#ifndef PRODUCT + ~LineBuffer() { + assert(_cur == _indent_level * INDENT_CHARS, "pending data in buffer - append_and_print_cr() not called?"); + } +#endif + + void append(const char* format, ...) { + va_list ap; + va_start(ap, format); + vappend(format, ap); + va_end(ap); + } + + void append_and_print_cr(const char* format, ...) { + va_list ap; + va_start(ap, format); + vappend(format, ap); + va_end(ap); + gclog_or_tty->print_cr("%s", _buffer); + _cur = _indent_level * INDENT_CHARS; + } +}; + G1CollectorPolicy::G1CollectorPolicy() : _parallel_gc_threads(G1CollectedHeap::use_parallel_gc_threads() ? ParallelGCThreads : 1), @@ -1016,10 +1067,8 @@ bool summary) { double min = data[0], max = data[0]; double total = 0.0; - int j; - for (j = 0; j < level; ++j) - gclog_or_tty->print(" "); - gclog_or_tty->print("[%s (ms):", str); + LineBuffer buf(level); + buf.append("[%s (ms):", str); for (uint i = 0; i < ParallelGCThreads; ++i) { double val = data[i]; if (val < min) @@ -1027,18 +1076,16 @@ if (val > max) max = val; total += val; - gclog_or_tty->print(" %3.1lf", val); + buf.append(" %3.1lf", val); } if (summary) { - gclog_or_tty->print_cr(""); + buf.append_and_print_cr(""); double avg = total / (double) ParallelGCThreads; - gclog_or_tty->print(" "); - for (j = 0; j < level; ++j) - gclog_or_tty->print(" "); - gclog_or_tty->print("Avg: %5.1lf, Min: %5.1lf, Max: %5.1lf", + buf.append(" "); + buf.append("Avg: %5.1lf, Min: %5.1lf, Max: %5.1lf", avg, min, max); } - gclog_or_tty->print_cr("]"); + buf.append_and_print_cr("]"); } void G1CollectorPolicy::print_par_sizes(int level, @@ -1047,10 +1094,8 @@ bool summary) { double min = data[0], max = data[0]; double total = 0.0; - int j; - for (j = 0; j < level; ++j) - gclog_or_tty->print(" "); - gclog_or_tty->print("[%s :", str); + LineBuffer buf(level); + buf.append("[%s :", str); for (uint i = 0; i < ParallelGCThreads; ++i) { double val = data[i]; if (val < min) @@ -1058,34 +1103,28 @@ if (val > max) max = val; total += val; - gclog_or_tty->print(" %d", (int) val); + buf.append(" %d", (int) val); } if (summary) { - gclog_or_tty->print_cr(""); + buf.append_and_print_cr(""); double avg = total / (double) ParallelGCThreads; - gclog_or_tty->print(" "); - for (j = 0; j < level; ++j) - gclog_or_tty->print(" "); - gclog_or_tty->print("Sum: %d, Avg: %d, Min: %d, Max: %d", + buf.append(" "); + buf.append("Sum: %d, Avg: %d, Min: %d, Max: %d", (int)total, (int)avg, (int)min, (int)max); } - gclog_or_tty->print_cr("]"); + buf.append_and_print_cr("]"); } void G1CollectorPolicy::print_stats (int level, const char* str, double value) { - for (int j = 0; j < level; ++j) - gclog_or_tty->print(" "); - gclog_or_tty->print_cr("[%s: %5.1lf ms]", str, value); + LineBuffer(level).append_and_print_cr("[%s: %5.1lf ms]", str, value); } void G1CollectorPolicy::print_stats (int level, const char* str, int value) { - for (int j = 0; j < level; ++j) - gclog_or_tty->print(" "); - gclog_or_tty->print_cr("[%s: %d]", str, value); + LineBuffer(level).append_and_print_cr("[%s: %d]", str, value); } double G1CollectorPolicy::avg_value (double* data) { @@ -2060,17 +2099,11 @@ _g1->collection_set_iterate(&cs_closure); } -static void print_indent(int level) { - for (int j = 0; j < level+1; ++j) - gclog_or_tty->print(" "); -} - void G1CollectorPolicy::print_summary (int level, const char* str, NumberSeq* seq) const { double sum = seq->sum(); - print_indent(level); - gclog_or_tty->print_cr("%-24s = %8.2lf s (avg = %8.2lf ms)", + LineBuffer(level + 1).append_and_print_cr("%-24s = %8.2lf s (avg = %8.2lf ms)", str, sum / 1000.0, seq->avg()); } @@ -2078,8 +2111,7 @@ const char* str, NumberSeq* seq) const { print_summary(level, str, seq); - print_indent(level + 5); - gclog_or_tty->print_cr("(num = %5d, std dev = %8.2lf ms, max = %8.2lf ms)", + LineBuffer(level + 6).append_and_print_cr("(num = %5d, std dev = %8.2lf ms, max = %8.2lf ms)", seq->num(), seq->sd(), seq->maximum()); } @@ -2087,6 +2119,7 @@ NumberSeq* other_times_ms, NumberSeq* calc_other_times_ms) const { bool should_print = false; + LineBuffer buf(level + 2); double max_sum = MAX2(fabs(other_times_ms->sum()), fabs(calc_other_times_ms->sum())); @@ -2095,8 +2128,7 @@ double sum_ratio = max_sum / min_sum; if (sum_ratio > 1.1) { should_print = true; - print_indent(level + 1); - gclog_or_tty->print_cr("## CALCULATED OTHER SUM DOESN'T MATCH RECORDED ###"); + buf.append_and_print_cr("## CALCULATED OTHER SUM DOESN'T MATCH RECORDED ###"); } double max_avg = MAX2(fabs(other_times_ms->avg()), @@ -2106,30 +2138,25 @@ double avg_ratio = max_avg / min_avg; if (avg_ratio > 1.1) { should_print = true; - print_indent(level + 1); - gclog_or_tty->print_cr("## CALCULATED OTHER AVG DOESN'T MATCH RECORDED ###"); + buf.append_and_print_cr("## CALCULATED OTHER AVG DOESN'T MATCH RECORDED ###"); } if (other_times_ms->sum() < -0.01) { - print_indent(level + 1); - gclog_or_tty->print_cr("## RECORDED OTHER SUM IS NEGATIVE ###"); + buf.append_and_print_cr("## RECORDED OTHER SUM IS NEGATIVE ###"); } if (other_times_ms->avg() < -0.01) { - print_indent(level + 1); - gclog_or_tty->print_cr("## RECORDED OTHER AVG IS NEGATIVE ###"); + buf.append_and_print_cr("## RECORDED OTHER AVG IS NEGATIVE ###"); } if (calc_other_times_ms->sum() < -0.01) { should_print = true; - print_indent(level + 1); - gclog_or_tty->print_cr("## CALCULATED OTHER SUM IS NEGATIVE ###"); + buf.append_and_print_cr("## CALCULATED OTHER SUM IS NEGATIVE ###"); } if (calc_other_times_ms->avg() < -0.01) { should_print = true; - print_indent(level + 1); - gclog_or_tty->print_cr("## CALCULATED OTHER AVG IS NEGATIVE ###"); + buf.append_and_print_cr("## CALCULATED OTHER AVG IS NEGATIVE ###"); } if (should_print) @@ -2210,10 +2237,9 @@ } } } else { - print_indent(0); - gclog_or_tty->print_cr("none"); + LineBuffer(1).append_and_print_cr("none"); } - gclog_or_tty->print_cr(""); + LineBuffer(0).append_and_print_cr(""); } void G1CollectorPolicy::print_tracing_info() const { @@ -2532,7 +2558,7 @@ jint regions_added = parKnownGarbageCl.marked_regions_added(); _hrSorted->incNumMarkedHeapRegions(regions_added); if (G1PrintParCleanupStats) { - gclog_or_tty->print(" Thread %d called %d times, added %d regions to list.\n", + gclog_or_tty->print_cr(" Thread %d called %d times, added %d regions to list.", i, parKnownGarbageCl.invokes(), regions_added); } }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -185,22 +185,22 @@ G1CollectedHeap* _g1h; ModRefBarrierSet* _mrbs; CompactPoint _cp; - size_t _pre_used; - FreeRegionList _free_list; HumongousRegionSet _humongous_proxy_set; void free_humongous_region(HeapRegion* hr) { HeapWord* end = hr->end(); + size_t dummy_pre_used; + FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep"); + assert(hr->startsHumongous(), "Only the start of a humongous region should be freed."); - _g1h->free_humongous_region(hr, &_pre_used, &_free_list, + _g1h->free_humongous_region(hr, &dummy_pre_used, &dummy_free_list, &_humongous_proxy_set, false /* par */); - // Do we also need to do this for the continues humongous regions - // we just collapsed? hr->prepare_for_compaction(&_cp); // Also clear the part of the card table that will be unused after // compaction. _mrbs->clear(MemRegion(hr->compaction_top(), end)); + dummy_free_list.remove_all(); } public: @@ -208,8 +208,6 @@ : _g1h(G1CollectedHeap::heap()), _mrbs(G1CollectedHeap::heap()->mr_bs()), _cp(NULL, cs, cs->initialize_threshold()), - _pre_used(0), - _free_list("Local Free List for G1MarkSweep"), _humongous_proxy_set("G1MarkSweep Humongous Proxy Set") { } void update_sets() { @@ -219,7 +217,6 @@ NULL, /* free_list */ &_humongous_proxy_set, false /* par */); - _free_list.remove_all(); } bool doHeapRegion(HeapRegion* hr) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -86,28 +86,6 @@ bool idempotent() { return true; } }; -class IntoCSRegionClosure: public HeapRegionClosure { - IntoCSOopClosure _blk; - G1CollectedHeap* _g1; -public: - IntoCSRegionClosure(G1CollectedHeap* g1, OopsInHeapRegionClosure* blk) : - _g1(g1), _blk(g1, blk) {} - bool doHeapRegion(HeapRegion* r) { - if (!r->in_collection_set()) { - _blk.set_region(r); - if (r->isHumongous()) { - if (r->startsHumongous()) { - oop obj = oop(r->bottom()); - obj->oop_iterate(&_blk); - } - } else { - r->oop_before_save_marks_iterate(&_blk); - } - } - return false; - } -}; - class VerifyRSCleanCardOopClosure: public OopClosure { G1CollectedHeap* _g1; public: @@ -329,7 +307,7 @@ // is during RSet updating within an evacuation pause. // In this case worker_i should be the id of a GC worker thread. assert(SafepointSynchronize::is_at_safepoint(), "not during an evacuation pause"); - assert(worker_i < (int) DirtyCardQueueSet::num_par_ids(), "should be a GC worker"); + assert(worker_i < (int) (ParallelGCThreads == 0 ? 1 : ParallelGCThreads), "should be a GC worker"); if (_g1rs->concurrentRefineOneCard(card_ptr, worker_i, true)) { // 'card_ptr' contains references that point into the collection
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -53,8 +53,8 @@ class HeapRegionSetBase; #define HR_FORMAT "%d:["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]" -#define HR_FORMAT_PARAMS(__hr) (__hr)->hrs_index(), (__hr)->bottom(), \ - (__hr)->top(), (__hr)->end() +#define HR_FORMAT_PARAMS(_hr_) (_hr_)->hrs_index(), (_hr_)->bottom(), \ + (_hr_)->top(), (_hr_)->end() // A dirty card to oop closure for heap regions. It // knows how to get the G1 heap and how to use the bitmap @@ -518,13 +518,13 @@ containing_set, _containing_set)); _containing_set = containing_set; -} + } HeapRegionSetBase* containing_set() { return _containing_set; } #else // ASSERT void set_containing_set(HeapRegionSetBase* containing_set) { } - // containing_set() is only used in asserts so there's not reason + // containing_set() is only used in asserts so there's no reason // to provide a dummy version of it. #endif // ASSERT @@ -535,14 +535,15 @@ bool pending_removal() { return _pending_removal; } void set_pending_removal(bool pending_removal) { - // We can only set pending_removal to true, if it's false and the - // region belongs to a set. - assert(!pending_removal || - (!_pending_removal && containing_set() != NULL), "pre-condition"); - // We can only set pending_removal to false, if it's true and the - // region does not belong to a set. - assert( pending_removal || - ( _pending_removal && containing_set() == NULL), "pre-condition"); + if (pending_removal) { + assert(!_pending_removal && containing_set() != NULL, + "can only set pending removal to true if it's false and " + "the region belongs to a region set"); + } else { + assert( _pending_removal && containing_set() == NULL, + "can only set pending removal to false if it's true and " + "the region does not belong to a region set"); + } _pending_removal = pending_removal; }
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -165,7 +165,7 @@ assert(num_so_far <= num, "post-condition"); if (num_so_far == num) { - // we find enough space for the humongous object + // we found enough space for the humongous object assert(from <= first && first < _regions.length(), "post-condition"); assert(first < curr && (curr - first) == (int) num, "post-condition"); for (int i = first; i < first + (int) num; ++i) {
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -76,7 +76,8 @@ // that are available for allocation. size_t free_suffix(); - // Finds a contiguous set of empty regions of length num. + // Find a contiguous set of empty regions of length num and return + // the index of the first region or -1 if the search was unsuccessful. int find_contiguous(size_t num); // Apply the "doHeapRegion" method of "blk" to all regions in "this",
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -42,7 +42,7 @@ return region_num; } -void HeapRegionSetBase::fill_in_ext_msg(hrl_ext_msg* msg, const char* message) { +void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) { msg->append("[%s] %s " "ln: "SIZE_FORMAT" rn: "SIZE_FORMAT" " "cy: "SIZE_FORMAT" ud: "SIZE_FORMAT, @@ -109,30 +109,30 @@ // for the verification calls. If we do verification without the // appropriate locks and the set changes underneath our feet // verification might fail and send us on a wild goose chase. - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); guarantee(( is_empty() && length() == 0 && region_num() == 0 && total_used_bytes() == 0 && total_capacity_bytes() == 0) || (!is_empty() && length() >= 0 && region_num() >= 0 && total_used_bytes() >= 0 && total_capacity_bytes() >= 0), - hrl_ext_msg(this, "invariant")); + hrs_ext_msg(this, "invariant")); guarantee((!regions_humongous() && region_num() == length()) || ( regions_humongous() && region_num() >= length()), - hrl_ext_msg(this, "invariant")); + hrs_ext_msg(this, "invariant")); guarantee(!regions_empty() || total_used_bytes() == 0, - hrl_ext_msg(this, "invariant")); + hrs_ext_msg(this, "invariant")); guarantee(total_used_bytes() <= total_capacity_bytes(), - hrl_ext_msg(this, "invariant")); + hrs_ext_msg(this, "invariant")); } void HeapRegionSetBase::verify_start() { // See comment in verify() about MT safety and verification. - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); assert(!_verify_in_progress, - hrl_ext_msg(this, "verification should not be in progress")); + hrs_ext_msg(this, "verification should not be in progress")); // Do the basic verification first before we do the checks over the regions. HeapRegionSetBase::verify(); @@ -146,11 +146,11 @@ void HeapRegionSetBase::verify_next_region(HeapRegion* hr) { // See comment in verify() about MT safety and verification. - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); assert(_verify_in_progress, - hrl_ext_msg(this, "verification should be in progress")); + hrs_ext_msg(this, "verification should be in progress")); - guarantee(verify_region(hr, this), hrl_ext_msg(this, "region verification")); + guarantee(verify_region(hr, this), hrs_ext_msg(this, "region verification")); _calc_length += 1; if (!hr->isHumongous()) { @@ -164,28 +164,28 @@ void HeapRegionSetBase::verify_end() { // See comment in verify() about MT safety and verification. - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); assert(_verify_in_progress, - hrl_ext_msg(this, "verification should be in progress")); + hrs_ext_msg(this, "verification should be in progress")); guarantee(length() == _calc_length, - hrl_err_msg("[%s] length: "SIZE_FORMAT" should be == " + hrs_err_msg("[%s] length: "SIZE_FORMAT" should be == " "calc length: "SIZE_FORMAT, name(), length(), _calc_length)); guarantee(region_num() == _calc_region_num, - hrl_err_msg("[%s] region num: "SIZE_FORMAT" should be == " + hrs_err_msg("[%s] region num: "SIZE_FORMAT" should be == " "calc region num: "SIZE_FORMAT, name(), region_num(), _calc_region_num)); guarantee(total_capacity_bytes() == _calc_total_capacity_bytes, - hrl_err_msg("[%s] capacity bytes: "SIZE_FORMAT" should be == " + hrs_err_msg("[%s] capacity bytes: "SIZE_FORMAT" should be == " "calc capacity bytes: "SIZE_FORMAT, name(), total_capacity_bytes(), _calc_total_capacity_bytes)); guarantee(total_used_bytes() == _calc_total_used_bytes, - hrl_err_msg("[%s] used bytes: "SIZE_FORMAT" should be == " + hrs_err_msg("[%s] used bytes: "SIZE_FORMAT" should be == " "calc used bytes: "SIZE_FORMAT, name(), total_used_bytes(), _calc_total_used_bytes)); @@ -221,9 +221,9 @@ //////////////////// HeapRegionSet //////////////////// void HeapRegionSet::update_from_proxy(HeapRegionSet* proxy_set) { - hrl_assert_mt_safety_ok(this); - hrl_assert_mt_safety_ok(proxy_set); - hrl_assert_sets_match(this, proxy_set); + hrs_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(proxy_set); + hrs_assert_sets_match(this, proxy_set); verify_optional(); proxy_set->verify_optional(); @@ -231,19 +231,19 @@ if (proxy_set->is_empty()) return; assert(proxy_set->length() <= _length, - hrl_err_msg("[%s] proxy set length: "SIZE_FORMAT" " + hrs_err_msg("[%s] proxy set length: "SIZE_FORMAT" " "should be <= length: "SIZE_FORMAT, name(), proxy_set->length(), _length)); _length -= proxy_set->length(); assert(proxy_set->region_num() <= _region_num, - hrl_err_msg("[%s] proxy set region num: "SIZE_FORMAT" " + hrs_err_msg("[%s] proxy set region num: "SIZE_FORMAT" " "should be <= region num: "SIZE_FORMAT, name(), proxy_set->region_num(), _region_num)); _region_num -= proxy_set->region_num(); assert(proxy_set->total_used_bytes() <= _total_used_bytes, - hrl_err_msg("[%s] proxy set used bytes: "SIZE_FORMAT" " + hrs_err_msg("[%s] proxy set used bytes: "SIZE_FORMAT" " "should be <= used bytes: "SIZE_FORMAT, name(), proxy_set->total_used_bytes(), _total_used_bytes)); @@ -257,13 +257,13 @@ //////////////////// HeapRegionLinkedList //////////////////// -void HeapRegionLinkedList::fill_in_ext_msg_extra(hrl_ext_msg* msg) { +void HeapRegionLinkedList::fill_in_ext_msg_extra(hrs_ext_msg* msg) { msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail()); } void HeapRegionLinkedList::add_as_tail(HeapRegionLinkedList* from_list) { - hrl_assert_mt_safety_ok(this); - hrl_assert_mt_safety_ok(from_list); + hrs_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(from_list); verify_optional(); from_list->verify_optional(); @@ -283,10 +283,10 @@ #endif // ASSERT if (_tail != NULL) { - assert(length() > 0 && _head != NULL, hrl_ext_msg(this, "invariant")); + assert(length() > 0 && _head != NULL, hrs_ext_msg(this, "invariant")); _tail->set_next(from_list->_head); } else { - assert(length() == 0 && _head == NULL, hrl_ext_msg(this, "invariant")); + assert(length() == 0 && _head == NULL, hrs_ext_msg(this, "invariant")); _head = from_list->_head; } _tail = from_list->_tail; @@ -301,12 +301,12 @@ } void HeapRegionLinkedList::remove_all() { - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); verify_optional(); HeapRegion* curr = _head; while (curr != NULL) { - hrl_assert_region_ok(this, curr, this); + hrs_assert_region_ok(this, curr, this); HeapRegion* next = curr->next(); curr->set_next(NULL); @@ -319,9 +319,9 @@ } void HeapRegionLinkedList::remove_all_pending(size_t target_count) { - hrl_assert_mt_safety_ok(this); - assert(target_count > 1, hrl_ext_msg(this, "pre-condition")); - assert(!is_empty(), hrl_ext_msg(this, "pre-condition")); + hrs_assert_mt_safety_ok(this); + assert(target_count > 1, hrs_ext_msg(this, "pre-condition")); + assert(!is_empty(), hrs_ext_msg(this, "pre-condition")); verify_optional(); DEBUG_ONLY(size_t old_length = length();) @@ -330,27 +330,27 @@ HeapRegion* prev = NULL; size_t count = 0; while (curr != NULL) { - hrl_assert_region_ok(this, curr, this); + hrs_assert_region_ok(this, curr, this); HeapRegion* next = curr->next(); if (curr->pending_removal()) { assert(count < target_count, - hrl_err_msg("[%s] should not come across more regions " + hrs_err_msg("[%s] should not come across more regions " "pending for removal than target_count: "SIZE_FORMAT, name(), target_count)); if (prev == NULL) { - assert(_head == curr, hrl_ext_msg(this, "invariant")); + assert(_head == curr, hrs_ext_msg(this, "invariant")); _head = next; } else { - assert(_head != curr, hrl_ext_msg(this, "invariant")); + assert(_head != curr, hrs_ext_msg(this, "invariant")); prev->set_next(next); } if (next == NULL) { - assert(_tail == curr, hrl_ext_msg(this, "invariant")); + assert(_tail == curr, hrs_ext_msg(this, "invariant")); _tail = prev; } else { - assert(_tail != curr, hrl_ext_msg(this, "invariant")); + assert(_tail != curr, hrs_ext_msg(this, "invariant")); } curr->set_next(NULL); @@ -371,10 +371,10 @@ } assert(count == target_count, - hrl_err_msg("[%s] count: "SIZE_FORMAT" should be == " + hrs_err_msg("[%s] count: "SIZE_FORMAT" should be == " "target_count: "SIZE_FORMAT, name(), count, target_count)); assert(length() + target_count == old_length, - hrl_err_msg("[%s] new length should be consistent " + hrs_err_msg("[%s] new length should be consistent " "new length: "SIZE_FORMAT" old length: "SIZE_FORMAT" " "target_count: "SIZE_FORMAT, name(), length(), old_length, target_count)); @@ -385,7 +385,7 @@ void HeapRegionLinkedList::verify() { // See comment in HeapRegionSetBase::verify() about MT safety and // verification. - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); // This will also do the basic verification too. verify_start(); @@ -399,7 +399,7 @@ count += 1; guarantee(count < _unrealistically_long_length, - hrl_err_msg("[%s] the calculated length: "SIZE_FORMAT" " + hrs_err_msg("[%s] the calculated length: "SIZE_FORMAT" " "seems very long, is there maybe a cycle? " "curr: "PTR_FORMAT" prev0: "PTR_FORMAT" " "prev1: "PTR_FORMAT" length: "SIZE_FORMAT, @@ -410,7 +410,7 @@ curr = curr->next(); } - guarantee(_tail == prev0, hrl_ext_msg(this, "post-condition")); + guarantee(_tail == prev0, hrs_ext_msg(this, "post-condition")); verify_end(); }
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -28,8 +28,8 @@ #include "gc_implementation/g1/heapRegion.hpp" // Large buffer for some cases where the output might be larger than normal. -#define HRL_ERR_MSG_BUFSZ 512 -typedef FormatBuffer<HRL_ERR_MSG_BUFSZ> hrl_err_msg; +#define HRS_ERR_MSG_BUFSZ 512 +typedef FormatBuffer<HRS_ERR_MSG_BUFSZ> hrs_err_msg; // Set verification will be forced either if someone defines // HEAP_REGION_SET_FORCE_VERIFY to be 1, or in builds in which @@ -45,10 +45,10 @@ // (e.g., length, region num, used bytes sum) plus any shared // functionality (e.g., verification). -class hrl_ext_msg; +class hrs_ext_msg; class HeapRegionSetBase VALUE_OBJ_CLASS_SPEC { - friend class hrl_ext_msg; + friend class hrs_ext_msg; protected: static size_t calculate_region_num(HeapRegion* hr); @@ -104,10 +104,10 @@ virtual bool check_mt_safety() { return true; } // fill_in_ext_msg() writes the the values of the set's attributes - // in the custom err_msg (hrl_ext_msg). fill_in_ext_msg_extra() + // in the custom err_msg (hrs_ext_msg). fill_in_ext_msg_extra() // allows subclasses to append further information. - virtual void fill_in_ext_msg_extra(hrl_ext_msg* msg) { } - void fill_in_ext_msg(hrl_ext_msg* msg, const char* message); + virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg) { } + void fill_in_ext_msg(hrs_ext_msg* msg, const char* message); // It updates the fields of the set to reflect hr being added to // the set. @@ -170,9 +170,9 @@ // the fields of the associated set. This can be very helpful in // diagnosing failures. -class hrl_ext_msg : public hrl_err_msg { +class hrs_ext_msg : public hrs_err_msg { public: - hrl_ext_msg(HeapRegionSetBase* set, const char* message) : hrl_err_msg("") { + hrs_ext_msg(HeapRegionSetBase* set, const char* message) : hrs_err_msg("") { set->fill_in_ext_msg(this, message); } }; @@ -180,25 +180,25 @@ // These two macros are provided for convenience, to keep the uses of // these two asserts a bit more concise. -#define hrl_assert_mt_safety_ok(_set_) \ +#define hrs_assert_mt_safety_ok(_set_) \ do { \ - assert((_set_)->check_mt_safety(), hrl_ext_msg((_set_), "MT safety")); \ + assert((_set_)->check_mt_safety(), hrs_ext_msg((_set_), "MT safety")); \ } while (0) -#define hrl_assert_region_ok(_set_, _hr_, _expected_) \ +#define hrs_assert_region_ok(_set_, _hr_, _expected_) \ do { \ assert((_set_)->verify_region((_hr_), (_expected_)), \ - hrl_ext_msg((_set_), "region verification")); \ + hrs_ext_msg((_set_), "region verification")); \ } while (0) //////////////////// HeapRegionSet //////////////////// -#define hrl_assert_sets_match(_set1_, _set2_) \ +#define hrs_assert_sets_match(_set1_, _set2_) \ do { \ assert(((_set1_)->regions_humongous() == \ (_set2_)->regions_humongous()) && \ ((_set1_)->regions_empty() == (_set2_)->regions_empty()), \ - hrl_err_msg("the contents of set %s and set %s should match", \ + hrs_err_msg("the contents of set %s and set %s should match", \ (_set1_)->name(), (_set2_)->name())); \ } while (0) @@ -267,7 +267,7 @@ HeapRegion* tail() { return _tail; } protected: - virtual void fill_in_ext_msg_extra(hrl_ext_msg* msg); + virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg); // See the comment for HeapRegionSetBase::clear() virtual void clear(); @@ -309,10 +309,10 @@ virtual void print_on(outputStream* out, bool print_contents = false); }; -//////////////////// HeapRegionLinkedList //////////////////// +//////////////////// HeapRegionLinkedListIterator //////////////////// -// Iterator class that provides a convenient way to iterator over the -// regions in a HeapRegionLinkedList instance. +// Iterator class that provides a convenient way to iterate over the +// regions of a HeapRegionLinkedList instance. class HeapRegionLinkedListIterator : public StackObj { private:
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -42,8 +42,8 @@ } inline void HeapRegionSetBase::add_internal(HeapRegion* hr) { - hrl_assert_region_ok(this, hr, NULL); - assert(hr->next() == NULL, hrl_ext_msg(this, "should not already be linked")); + hrs_assert_region_ok(this, hr, NULL); + assert(hr->next() == NULL, hrs_ext_msg(this, "should not already be linked")); update_for_addition(hr); hr->set_containing_set(this); @@ -51,7 +51,7 @@ inline void HeapRegionSetBase::update_for_removal(HeapRegion* hr) { // Assumes the caller has already verified the region. - assert(_length > 0, hrl_ext_msg(this, "pre-condition")); + assert(_length > 0, hrs_ext_msg(this, "pre-condition")); _length -= 1; size_t region_num_diff; @@ -61,22 +61,22 @@ region_num_diff = calculate_region_num(hr); } assert(region_num_diff <= _region_num, - hrl_err_msg("[%s] region's region num: "SIZE_FORMAT" " + hrs_err_msg("[%s] region's region num: "SIZE_FORMAT" " "should be <= region num: "SIZE_FORMAT, name(), region_num_diff, _region_num)); _region_num -= region_num_diff; size_t used_bytes = hr->used(); assert(used_bytes <= _total_used_bytes, - hrl_err_msg("[%s] region's used bytes: "SIZE_FORMAT" " + hrs_err_msg("[%s] region's used bytes: "SIZE_FORMAT" " "should be <= used bytes: "SIZE_FORMAT, name(), used_bytes, _total_used_bytes)); _total_used_bytes -= used_bytes; } inline void HeapRegionSetBase::remove_internal(HeapRegion* hr) { - hrl_assert_region_ok(this, hr, this); - assert(hr->next() == NULL, hrl_ext_msg(this, "should already be unlinked")); + hrs_assert_region_ok(this, hr, this); + assert(hr->next() == NULL, hrs_ext_msg(this, "should already be unlinked")); hr->set_containing_set(NULL); update_for_removal(hr); @@ -85,13 +85,13 @@ //////////////////// HeapRegionSet //////////////////// inline void HeapRegionSet::add(HeapRegion* hr) { - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); // add_internal() will verify the region. add_internal(hr); } inline void HeapRegionSet::remove(HeapRegion* hr) { - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); // remove_internal() will verify the region. remove_internal(hr); } @@ -101,8 +101,8 @@ // No need to fo the MT safety check here given that this method // does not update the contents of the set but instead accumulates // the changes in proxy_set which is assumed to be thread-local. - hrl_assert_sets_match(this, proxy_set); - hrl_assert_region_ok(this, hr, this); + hrs_assert_sets_match(this, proxy_set); + hrs_assert_region_ok(this, hr, this); hr->set_containing_set(NULL); proxy_set->update_for_addition(hr); @@ -111,10 +111,10 @@ //////////////////// HeapRegionLinkedList //////////////////// inline void HeapRegionLinkedList::add_as_tail(HeapRegion* hr) { - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); assert((length() == 0 && _head == NULL && _tail == NULL) || (length() > 0 && _head != NULL && _tail != NULL), - hrl_ext_msg(this, "invariant")); + hrs_ext_msg(this, "invariant")); // add_internal() will verify the region. add_internal(hr); @@ -128,10 +128,10 @@ } inline HeapRegion* HeapRegionLinkedList::remove_head() { - hrl_assert_mt_safety_ok(this); - assert(!is_empty(), hrl_ext_msg(this, "the list should not be empty")); + hrs_assert_mt_safety_ok(this); + assert(!is_empty(), hrs_ext_msg(this, "the list should not be empty")); assert(length() > 0 && _head != NULL && _tail != NULL, - hrl_ext_msg(this, "invariant")); + hrs_ext_msg(this, "invariant")); // We need to unlink it first. HeapRegion* hr = _head; @@ -147,7 +147,7 @@ } inline HeapRegion* HeapRegionLinkedList::remove_head_or_null() { - hrl_assert_mt_safety_ok(this); + hrs_assert_mt_safety_ok(this); if (!is_empty()) { return remove_head();
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSets.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSets.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -52,7 +52,7 @@ FreeList_lock->owned_by_self())) || (!SafepointSynchronize::is_at_safepoint() && Heap_lock->owned_by_self()), - hrl_ext_msg(this, "master free list MT safety protocol")); + hrs_ext_msg(this, "master free list MT safety protocol")); return FreeRegionList::check_mt_safety(); } @@ -65,7 +65,7 @@ // while holding the SecondaryFreeList_lock. guarantee(SecondaryFreeList_lock->owned_by_self(), - hrl_ext_msg(this, "secondary free list MT safety protocol")); + hrs_ext_msg(this, "secondary free list MT safety protocol")); return FreeRegionList::check_mt_safety(); } @@ -81,7 +81,7 @@ return HeapRegionSet::verify_region_extra(hr); } -//////////////////// HumongousRegionSet //////////////////// +//////////////////// MasterHumongousRegionSet //////////////////// bool MasterHumongousRegionSet::check_mt_safety() { // Master Humongous Set MT safety protocol: @@ -97,6 +97,6 @@ OldSets_lock->owned_by_self())) || (!SafepointSynchronize::is_at_safepoint() && Heap_lock->owned_by_self()), - hrl_ext_msg(this, "master humongous set MT safety protocol")); + hrs_ext_msg(this, "master humongous set MT safety protocol")); return HumongousRegionSet::check_mt_safety(); }
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1530,13 +1530,15 @@ { if (_ref_processor == NULL) { // Allocate and initialize a reference processor - _ref_processor = ReferenceProcessor::create_ref_processor( - _reserved, // span - refs_discovery_is_atomic(), // atomic_discovery - refs_discovery_is_mt(), // mt_discovery - NULL, // is_alive_non_header - ParallelGCThreads, - ParallelRefProcEnabled); + _ref_processor = + new ReferenceProcessor(_reserved, // span + ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing + (int) ParallelGCThreads, // mt processing degree + refs_discovery_is_mt(), // mt discovery + (int) ParallelGCThreads, // mt discovery degree + refs_discovery_is_atomic(), // atomic_discovery + NULL, // is_alive_non_header + false); // write barrier for next field updates } }
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,9 +58,7 @@ void PSMarkSweep::initialize() { MemRegion mr = Universe::heap()->reserved_region(); - _ref_processor = new ReferenceProcessor(mr, - true, // atomic_discovery - false); // mt_discovery + _ref_processor = new ReferenceProcessor(mr); // a vanilla ref proc _counters = new CollectorCounters("PSMarkSweep", 1); }
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -827,13 +827,15 @@ assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); MemRegion mr = heap->reserved_region(); - _ref_processor = ReferenceProcessor::create_ref_processor( - mr, // span - true, // atomic_discovery - true, // mt_discovery - &_is_alive_closure, - ParallelGCThreads, - ParallelRefProcEnabled); + _ref_processor = + new ReferenceProcessor(mr, // span + ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing + (int) ParallelGCThreads, // mt processing degree + true, // mt discovery + (int) ParallelGCThreads, // mt discovery degree + true, // atomic_discovery + &_is_alive_closure, // non-header is alive closure + false); // write barrier for next field updates _counters = new CollectorCounters("PSParallelCompact", 1); // Initialize static fields in ParCompactionManager.
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -411,7 +411,7 @@ template <class T> void PSPromotionManager::process_array_chunk_work( oop obj, int start, int end) { - assert(start < end, "invariant"); + assert(start <= end, "invariant"); T* const base = (T*)objArrayOop(obj)->base(); T* p = base + start; T* const chunk_end = base + end;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/symbolTable.hpp" #include "gc_implementation/parallelScavenge/cardTableExtension.hpp" #include "gc_implementation/parallelScavenge/gcTaskManager.hpp" #include "gc_implementation/parallelScavenge/generationSizer.hpp" @@ -439,6 +440,14 @@ reference_processor()->enqueue_discovered_references(NULL); } + if (!JavaObjectsInPerm) { + // Unlink any dead interned Strings + StringTable::unlink(&_is_alive_closure); + // Process the remaining live ones + PSScavengeRootsClosure root_closure(promotion_manager); + StringTable::oops_do(&root_closure); + } + // Finally, flush the promotion_manager's labs, and deallocate its stacks. PSPromotionManager::post_scavenge(); @@ -796,13 +805,15 @@ // Initialize ref handling object for scavenging. MemRegion mr = young_gen->reserved(); - _ref_processor = ReferenceProcessor::create_ref_processor( - mr, // span - true, // atomic_discovery - true, // mt_discovery - NULL, // is_alive_non_header - ParallelGCThreads, - ParallelRefProcEnabled); + _ref_processor = + new ReferenceProcessor(mr, // span + ParallelRefProcEnabled && (ParallelGCThreads > 1), // mt processing + (int) ParallelGCThreads, // mt processing degree + true, // mt discovery + (int) ParallelGCThreads, // mt discovery degree + true, // atomic_discovery + NULL, // header provides liveness info + false); // next field updates do not need write barrier // Cache the cardtable BarrierSet* bs = Universe::heap()->barrier_set();
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -86,4 +86,21 @@ } } +class PSScavengeRootsClosure: public OopClosure { + private: + PSPromotionManager* _promotion_manager; + + protected: + template <class T> void do_oop_work(T *p) { + if (PSScavenge::should_scavenge(p)) { + // We never card mark roots, maybe call a func without test? + PSScavenge::copy_and_push_safe_barrier(_promotion_manager, p); + } + } + public: + PSScavengeRootsClosure(PSPromotionManager* pm) : _promotion_manager(pm) { } + void do_oop(oop* p) { PSScavengeRootsClosure::do_oop_work(p); } + void do_oop(narrowOop* p) { PSScavengeRootsClosure::do_oop_work(p); } +}; + #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSSCAVENGE_INLINE_HPP
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -30,7 +30,7 @@ #include "gc_implementation/parallelScavenge/psMarkSweep.hpp" #include "gc_implementation/parallelScavenge/psPromotionManager.hpp" #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" -#include "gc_implementation/parallelScavenge/psScavenge.hpp" +#include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "gc_implementation/parallelScavenge/psTasks.hpp" #include "memory/iterator.hpp" #include "memory/universe.hpp" @@ -46,24 +46,6 @@ // ScavengeRootsTask // -// Define before use -class PSScavengeRootsClosure: public OopClosure { - private: - PSPromotionManager* _promotion_manager; - - protected: - template <class T> void do_oop_work(T *p) { - if (PSScavenge::should_scavenge(p)) { - // We never card mark roots, maybe call a func without test? - PSScavenge::copy_and_push_safe_barrier(_promotion_manager, p); - } - } - public: - PSScavengeRootsClosure(PSPromotionManager* pm) : _promotion_manager(pm) { } - void do_oop(oop* p) { PSScavengeRootsClosure::do_oop_work(p); } - void do_oop(narrowOop* p) { PSScavengeRootsClosure::do_oop_work(p); } -}; - void ScavengeRootsTask::do_it(GCTaskManager* manager, uint which) { assert(Universe::heap()->is_gc_active(), "called outside gc");
--- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,7 +96,7 @@ empty, // empty method (code: _return) accessor, // accessor method (code: _aload_0, _getfield, _(a|i)return) abstract, // abstract method (throws an AbstractMethodException) - method_handle, // java.dyn.MethodHandles::invoke + method_handle, // java.lang.invoke.MethodHandles::invoke java_lang_math_sin, // implementation of java.lang.Math.sin (x) java_lang_math_cos, // implementation of java.lang.Math.cos (x) java_lang_math_tan, // implementation of java.lang.Math.tan (x)
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -656,7 +656,7 @@ // oop rcvr = locals[0].j.r; oop rcvr; if (METHOD->is_static()) { - rcvr = METHOD->constants()->pool_holder()->klass_part()->java_mirror(); + rcvr = METHOD->constants()->pool_holder()->java_mirror(); } else { rcvr = LOCALS_OBJECT(0); VERIFY_OOP(rcvr); @@ -2111,8 +2111,8 @@ break; case JVM_CONSTANT_Class: - VERIFY_OOP(constants->resolved_klass_at(index)->klass_part()->java_mirror()); - SET_STACK_OBJECT(constants->resolved_klass_at(index)->klass_part()->java_mirror(), 0); + VERIFY_OOP(constants->resolved_klass_at(index)->java_mirror()); + SET_STACK_OBJECT(constants->resolved_klass_at(index)->java_mirror(), 0); break; case JVM_CONSTANT_UnresolvedString:
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -118,7 +118,7 @@ if (tag.is_unresolved_klass() || tag.is_klass()) { klassOop klass = pool->klass_at(index, CHECK); - oop java_class = klass->klass_part()->java_mirror(); + oop java_class = klass->java_mirror(); thread->set_vm_result(java_class); } else { #ifdef ASSERT @@ -369,7 +369,10 @@ } // create exception - THROW_MSG(vmSymbols::java_dyn_WrongMethodTypeException(), message); + Symbol* java_lang_invoke_WrongMethodTypeException = vmSymbols::java_lang_invoke_WrongMethodTypeException(); + if (AllowTransitionalJSR292) + java_lang_invoke_WrongMethodTypeException = SystemDictionaryHandles::WrongMethodTypeException_klass()->name(); + THROW_MSG(java_lang_invoke_WrongMethodTypeException, message); } IRT_END @@ -794,7 +797,7 @@ Handle info; // optional argument(s) in JVM_CONSTANT_InvokeDynamic Handle bootm = SystemDictionary::find_bootstrap_method(caller_method, caller_bci, main_index, info, CHECK); - if (!java_dyn_MethodHandle::is_instance(bootm())) { + if (!java_lang_invoke_MethodHandle::is_instance(bootm())) { THROW_MSG(vmSymbols::java_lang_IllegalStateException(), "no bootstrap method found for invokedynamic"); } @@ -980,7 +983,8 @@ ConstantPoolCacheEntry *cp_entry)) // check the access_flags for the field in the klass - instanceKlass* ik = instanceKlass::cast((klassOop)cp_entry->f1()); + + instanceKlass* ik = instanceKlass::cast(java_lang_Class::as_klassOop(cp_entry->f1())); typeArrayOop fields = ik->fields(); int index = cp_entry->field_index(); assert(index < fields->length(), "holders field index is out of range"); @@ -1006,7 +1010,7 @@ // non-static field accessors have an object, but we need a handle h_obj = Handle(thread, obj); } - instanceKlassHandle h_cp_entry_f1(thread, (klassOop)cp_entry->f1()); + instanceKlassHandle h_cp_entry_f1(thread, java_lang_Class::as_klassOop(cp_entry->f1())); jfieldID fid = jfieldIDWorkaround::to_jfieldID(h_cp_entry_f1, cp_entry->f2(), is_static); JvmtiExport::post_field_access(thread, method(thread), bcp(thread), h_cp_entry_f1, h_obj, fid); IRT_END @@ -1014,7 +1018,7 @@ IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread, oopDesc* obj, ConstantPoolCacheEntry *cp_entry, jvalue *value)) - klassOop k = (klassOop)cp_entry->f1(); + klassOop k = java_lang_Class::as_klassOop(cp_entry->f1()); // check the access_flags for the field in the klass instanceKlass* ik = instanceKlass::cast(k);
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -217,11 +217,13 @@ if (EnableMethodHandles && klass() == SystemDictionary::MethodHandle_klass() && methodOopDesc::is_method_handle_invoke_name(name)) { - if (!MethodHandles::enabled()) { + if (!THREAD->is_Compiler_thread() && !MethodHandles::enabled()) { // Make sure the Java part of the runtime has been booted up. klassOop natives = SystemDictionary::MethodHandleNatives_klass(); if (natives == NULL || instanceKlass::cast(natives)->is_not_initialized()) { - SystemDictionary::resolve_or_fail(vmSymbols::sun_dyn_MethodHandleNatives(), + Symbol* natives_name = vmSymbols::java_lang_invoke_MethodHandleNatives(); + if (natives != NULL && AllowTransitionalJSR292) natives_name = Klass::cast(natives)->name(); + SystemDictionary::resolve_or_fail(natives_name, Handle(), Handle(), true, @@ -298,7 +300,7 @@ } void LinkResolver::resolve_dynamic_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) { - // The class is java.dyn.MethodHandle + // The class is java.lang.invoke.MethodHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); Symbol* method_name = vmSymbols::invokeExact_name();
--- a/hotspot/src/share/vm/memory/collectorPolicy.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -293,10 +293,11 @@ // Determine maximum size of gen0 size_t max_new_size = 0; - if (FLAG_IS_CMDLINE(MaxNewSize)) { + if (FLAG_IS_CMDLINE(MaxNewSize) || FLAG_IS_ERGO(MaxNewSize)) { if (MaxNewSize < min_alignment()) { max_new_size = min_alignment(); - } else if (MaxNewSize >= max_heap_byte_size()) { + } + if (MaxNewSize >= max_heap_byte_size()) { max_new_size = align_size_down(max_heap_byte_size() - min_alignment(), min_alignment()); warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or " @@ -333,7 +334,7 @@ assert(max_new_size > 0, "All paths should set max_new_size"); // Given the maximum gen0 size, determine the initial and - // minimum sizes. + // minimum gen0 sizes. if (max_heap_byte_size() == min_heap_byte_size()) { // The maximum and minimum heap sizes are the same so @@ -396,7 +397,7 @@ } if (PrintGCDetails && Verbose) { - gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT " Initial gen0 " + gclog_or_tty->print_cr("1: Minimum gen0 " SIZE_FORMAT " Initial gen0 " SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, min_gen0_size(), initial_gen0_size(), max_gen0_size()); } @@ -448,7 +449,7 @@ // At this point the minimum, initial and maximum sizes // of the overall heap and of gen0 have been determined. // The maximum gen1 size can be determined from the maximum gen0 - // and maximum heap size since not explicit flags exits + // and maximum heap size since no explicit flags exits // for setting the gen1 maximum. _max_gen1_size = max_heap_byte_size() - _max_gen0_size; _max_gen1_size = @@ -494,13 +495,13 @@ "generation sizes: using maximum heap = " SIZE_FORMAT " -XX:OldSize flag is being ignored", max_heap_byte_size()); - } + } // If there is an inconsistency between the OldSize and the minimum and/or // initial size of gen0, since OldSize was explicitly set, OldSize wins. if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size, min_heap_byte_size(), OldSize)) { if (PrintGCDetails && Verbose) { - gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT " Initial gen0 " + gclog_or_tty->print_cr("2: Minimum gen0 " SIZE_FORMAT " Initial gen0 " SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, min_gen0_size(), initial_gen0_size(), max_gen0_size()); } @@ -509,7 +510,7 @@ if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size, initial_heap_byte_size(), OldSize)) { if (PrintGCDetails && Verbose) { - gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT " Initial gen0 " + gclog_or_tty->print_cr("3: Minimum gen0 " SIZE_FORMAT " Initial gen0 " SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, min_gen0_size(), initial_gen0_size(), max_gen0_size()); }
--- a/hotspot/src/share/vm/memory/compactingPermGenGen.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/memory/compactingPermGenGen.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,7 +105,7 @@ public: enum { - vtbl_list_size = 16, // number of entries in the shared space vtable list. + vtbl_list_size = 17, // number of entries in the shared space vtable list. num_virtuals = 200 // number of virtual methods in Klass (or // subclass) objects, or greater. };
--- a/hotspot/src/share/vm/memory/dump.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/memory/dump.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1561,6 +1561,7 @@ // thread because it requires object allocation. LinkClassesClosure lcc(Thread::current()); object_iterate(&lcc); + ensure_parsability(false); // arg is actually don't care tty->print_cr("done. "); // Create and dump the shared spaces.
--- a/hotspot/src/share/vm/memory/generation.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/memory/generation.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,14 +83,11 @@ } // By default we get a single threaded default reference processor; -// generations needing multi-threaded refs discovery override this method. +// generations needing multi-threaded refs processing or discovery override this method. void Generation::ref_processor_init() { assert(_ref_processor == NULL, "a reference processor already exists"); assert(!_reserved.is_empty(), "empty generation?"); - _ref_processor = - new ReferenceProcessor(_reserved, // span - refs_discovery_is_atomic(), // atomic_discovery - refs_discovery_is_mt()); // mt_discovery + _ref_processor = new ReferenceProcessor(_reserved); // a vanilla reference processor if (_ref_processor == NULL) { vm_exit_during_initialization("Could not allocate ReferenceProcessor object"); }
--- a/hotspot/src/share/vm/memory/heap.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/memory/heap.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -316,12 +316,19 @@ } size_t CodeHeap::largest_free_block() const { + // First check unused space excluding free blocks. + size_t free_sz = size(_free_segments); + size_t unused = max_capacity() - allocated_capacity() - free_sz; + if (unused >= free_sz) + return unused; + + // Now check largest free block. size_t len = 0; for (FreeBlock* b = _freelist; b != NULL; b = b->link()) { if (b->length() > len) len = b->length(); } - return size(len); + return MAX2(unused, size(len)); } // Free list management
--- a/hotspot/src/share/vm/memory/oopFactory.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/memory/oopFactory.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,12 +117,12 @@ } -klassOop oopFactory::new_instanceKlass(int vtable_len, int itable_len, +klassOop oopFactory::new_instanceKlass(Symbol* name, int vtable_len, int itable_len, int static_field_size, unsigned int nonstatic_oop_map_count, ReferenceType rt, TRAPS) { instanceKlassKlass* ikk = instanceKlassKlass::cast(Universe::instanceKlassKlassObj()); - return ikk->allocate_instance_klass(vtable_len, itable_len, static_field_size, nonstatic_oop_map_count, rt, CHECK_NULL); + return ikk->allocate_instance_klass(name, vtable_len, itable_len, static_field_size, nonstatic_oop_map_count, rt, CHECK_NULL); }
--- a/hotspot/src/share/vm/memory/oopFactory.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/memory/oopFactory.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,7 +72,8 @@ TRAPS); // Instance classes - static klassOop new_instanceKlass(int vtable_len, int itable_len, + static klassOop new_instanceKlass(Symbol* name, + int vtable_len, int itable_len, int static_field_size, unsigned int nonstatic_oop_map_count, ReferenceType rt, TRAPS);
--- a/hotspot/src/share/vm/memory/referenceProcessor.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,40 +102,17 @@ "Unrecongnized RefDiscoveryPolicy"); } -ReferenceProcessor* -ReferenceProcessor::create_ref_processor(MemRegion span, - bool atomic_discovery, - bool mt_discovery, - BoolObjectClosure* is_alive_non_header, - int parallel_gc_threads, - bool mt_processing, - bool dl_needs_barrier) { - int mt_degree = 1; - if (parallel_gc_threads > 1) { - mt_degree = parallel_gc_threads; - } - ReferenceProcessor* rp = - new ReferenceProcessor(span, atomic_discovery, - mt_discovery, mt_degree, - mt_processing && (parallel_gc_threads > 0), - dl_needs_barrier); - if (rp == NULL) { - 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; -} - ReferenceProcessor::ReferenceProcessor(MemRegion span, - bool atomic_discovery, + bool mt_processing, + int mt_processing_degree, bool mt_discovery, - int mt_degree, - bool mt_processing, + int mt_discovery_degree, + bool atomic_discovery, + BoolObjectClosure* is_alive_non_header, bool discovered_list_needs_barrier) : _discovering_refs(false), _enqueuing_is_done(false), - _is_alive_non_header(NULL), + _is_alive_non_header(is_alive_non_header), _discovered_list_needs_barrier(discovered_list_needs_barrier), _bs(NULL), _processing_is_mt(mt_processing), @@ -144,8 +121,8 @@ _span = span; _discovery_is_atomic = atomic_discovery; _discovery_is_mt = mt_discovery; - _num_q = mt_degree; - _max_num_q = mt_degree; + _num_q = MAX2(1, mt_processing_degree); + _max_num_q = MAX2(_num_q, mt_discovery_degree); _discoveredSoftRefs = NEW_C_HEAP_ARRAY(DiscoveredList, _max_num_q * subclasses_of_ref); if (_discoveredSoftRefs == NULL) { vm_exit_during_initialization("Could not allocated RefProc Array"); @@ -163,6 +140,7 @@ if (discovered_list_needs_barrier) { _bs = Universe::heap()->barrier_set(); } + setup_policy(false /* default soft ref policy */); } #ifndef PRODUCT @@ -405,15 +383,14 @@ { } virtual void work(unsigned int work_id) { - assert(work_id < (unsigned int)_ref_processor.num_q(), "Index out-of-bounds"); + assert(work_id < (unsigned int)_ref_processor.max_num_q(), "Index out-of-bounds"); // Simplest first cut: static partitioning. int index = work_id; // The increment on "index" must correspond to the maximum number of queues // (n_queues) with which that ReferenceProcessor was created. That // is because of the "clever" way the discovered references lists were - // allocated and are indexed into. That number is ParallelGCThreads - // currently. Assert that. - assert(_n_queues == (int) ParallelGCThreads, "Different number not expected"); + // allocated and are indexed into. + assert(_n_queues == (int) _ref_processor.max_num_q(), "Different number not expected"); for (int j = 0; j < subclasses_of_ref; j++, index += _n_queues) { @@ -672,7 +649,7 @@ } } NOT_PRODUCT( - if (PrintGCDetails && TraceReferenceGC) { + if (PrintGCDetails && TraceReferenceGC && (iter.processed() > 0)) { gclog_or_tty->print_cr(" Dropped %d active Refs out of %d " "Refs in discovered list " INTPTR_FORMAT, iter.removed(), iter.processed(), (address)refs_list.head()); @@ -711,7 +688,7 @@ // Now close the newly reachable set complete_gc->do_void(); NOT_PRODUCT( - if (PrintGCDetails && TraceReferenceGC) { + if (PrintGCDetails && TraceReferenceGC && (iter.processed() > 0)) { gclog_or_tty->print_cr(" Dropped %d active Refs out of %d " "Refs in discovered list " INTPTR_FORMAT, iter.removed(), iter.processed(), (address)refs_list.head()); @@ -951,7 +928,7 @@ } if (PrintReferenceGC && PrintGCDetails) { size_t total = 0; - for (int i = 0; i < _num_q; ++i) { + for (int i = 0; i < _max_num_q; ++i) { total += refs_lists[i].length(); } gclog_or_tty->print(", %u refs", total); @@ -967,7 +944,7 @@ RefProcPhase1Task phase1(*this, refs_lists, policy, true /*marks_oops_alive*/); task_executor->execute(phase1); } else { - for (int i = 0; i < _num_q; i++) { + for (int i = 0; i < _max_num_q; i++) { process_phase1(refs_lists[i], policy, is_alive, keep_alive, complete_gc); } @@ -983,7 +960,7 @@ RefProcPhase2Task phase2(*this, refs_lists, !discovery_is_atomic() /*marks_oops_alive*/); task_executor->execute(phase2); } else { - for (int i = 0; i < _num_q; i++) { + for (int i = 0; i < _max_num_q; i++) { process_phase2(refs_lists[i], is_alive, keep_alive, complete_gc); } } @@ -994,7 +971,7 @@ RefProcPhase3Task phase3(*this, refs_lists, clear_referent, true /*marks_oops_alive*/); task_executor->execute(phase3); } else { - for (int i = 0; i < _num_q; i++) { + for (int i = 0; i < _max_num_q; i++) { process_phase3(refs_lists[i], clear_referent, is_alive, keep_alive, complete_gc); } @@ -1008,7 +985,7 @@ // for (int j = 0; j < _num_q; j++) { // int index = i * _max_num_q + j; for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) { - if (TraceReferenceGC && PrintGCDetails && ((i % _num_q) == 0)) { + if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) { gclog_or_tty->print_cr( "\nScrubbing %s discovered list of Null referents", list_name(i)); @@ -1350,7 +1327,7 @@ { TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC, false, gclog_or_tty); - for (int i = 0; i < _num_q; i++) { + for (int i = 0; i < _max_num_q; i++) { if (yield->should_return()) { return; } @@ -1363,7 +1340,7 @@ { TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC, false, gclog_or_tty); - for (int i = 0; i < _num_q; i++) { + for (int i = 0; i < _max_num_q; i++) { if (yield->should_return()) { return; } @@ -1376,7 +1353,7 @@ { TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC, false, gclog_or_tty); - for (int i = 0; i < _num_q; i++) { + for (int i = 0; i < _max_num_q; i++) { if (yield->should_return()) { return; } @@ -1433,7 +1410,7 @@ complete_gc->do_void(); NOT_PRODUCT( - if (PrintGCDetails && PrintReferenceGC) { + if (PrintGCDetails && PrintReferenceGC && (iter.processed() > 0)) { gclog_or_tty->print_cr(" Dropped %d Refs out of %d " "Refs in discovered list " INTPTR_FORMAT, iter.removed(), iter.processed(), (address)refs_list.head());
--- a/hotspot/src/share/vm/memory/referenceProcessor.hpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,7 +71,7 @@ bool _enqueuing_is_done; // true if all weak references enqueued bool _processing_is_mt; // true during phases when // reference processing is MT. - int _next_id; // round-robin counter in + int _next_id; // round-robin mod _num_q counter in // support of work distribution // For collectors that do not keep GC marking information @@ -103,7 +103,8 @@ public: int num_q() { return _num_q; } - void set_mt_degree(int v) { _num_q = v; } + int max_num_q() { return _max_num_q; } + void set_active_mt_degree(int v) { _num_q = v; } DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; } static oop sentinel_ref() { return _sentinelRef; } static oop* adr_sentinel_ref() { return &_sentinelRef; } @@ -216,6 +217,7 @@ VoidClosure* complete_gc, YieldClosure* yield); + // round-robin mod _num_q (not: _not_ mode _max_num_q) int next_id() { int id = _next_id; if (++_next_id == _num_q) { @@ -256,23 +258,15 @@ _max_num_q(0), _processing_is_mt(false), _next_id(0) - {} - - ReferenceProcessor(MemRegion span, bool atomic_discovery, - bool mt_discovery, - int mt_degree = 1, - bool mt_processing = false, - bool discovered_list_needs_barrier = false); + { } - // Allocates and initializes a reference processor. - static ReferenceProcessor* create_ref_processor( - MemRegion span, - bool atomic_discovery, - bool mt_discovery, - BoolObjectClosure* is_alive_non_header = NULL, - int parallel_gc_threads = 1, - bool mt_processing = false, - bool discovered_list_needs_barrier = false); + // Default parameters give you a vanilla reference processor. + ReferenceProcessor(MemRegion span, + bool mt_processing = false, int mt_processing_degree = 1, + bool mt_discovery = false, int mt_discovery_degree = 1, + bool atomic_discovery = true, + BoolObjectClosure* is_alive_non_header = NULL, + bool discovered_list_needs_barrier = false); // RefDiscoveryPolicy values enum DiscoveryPolicy { @@ -397,20 +391,20 @@ // A utility class to temporarily change the MT'ness of // reference discovery for the given ReferenceProcessor // in the scope that contains it. -class ReferenceProcessorMTMutator: StackObj { +class ReferenceProcessorMTDiscoveryMutator: StackObj { private: ReferenceProcessor* _rp; bool _saved_mt; public: - ReferenceProcessorMTMutator(ReferenceProcessor* rp, - bool mt): + ReferenceProcessorMTDiscoveryMutator(ReferenceProcessor* rp, + bool mt): _rp(rp) { _saved_mt = _rp->discovery_is_mt(); _rp->set_mt_discovery(mt); } - ~ReferenceProcessorMTMutator() { + ~ReferenceProcessorMTDiscoveryMutator() { _rp->set_mt_discovery(_saved_mt); } };
--- a/hotspot/src/share/vm/memory/sharedHeap.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/memory/sharedHeap.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -171,11 +171,13 @@ } if (!_process_strong_tasks->is_task_claimed(SH_PS_StringTable_oops_do)) { - if (so & SO_Strings) { - StringTable::oops_do(roots); - } - // Verify if the string table contents are in the perm gen - NOT_PRODUCT(StringTable::oops_do(&assert_is_perm_closure)); + if (so & SO_Strings || (!collecting_perm_gen && !JavaObjectsInPerm)) { + StringTable::oops_do(roots); + } + if (JavaObjectsInPerm) { + // Verify the string table contents are in the perm gen + NOT_PRODUCT(StringTable::oops_do(&assert_is_perm_closure)); + } } if (!_process_strong_tasks->is_task_claimed(SH_PS_CodeCache_oops_do)) {
--- a/hotspot/src/share/vm/memory/universe.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/memory/universe.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,6 +51,7 @@ #include "oops/cpCacheKlass.hpp" #include "oops/cpCacheOop.hpp" #include "oops/instanceKlass.hpp" +#include "oops/instanceMirrorKlass.hpp" #include "oops/instanceKlassKlass.hpp" #include "oops/instanceRefKlass.hpp" #include "oops/klassKlass.hpp" @@ -521,6 +522,7 @@ { objArrayKlassKlass o; add_vtable(list, &n, &o, count); } { instanceKlassKlass o; add_vtable(list, &n, &o, count); } { instanceKlass o; add_vtable(list, &n, &o, count); } + { instanceMirrorKlass o; add_vtable(list, &n, &o, count); } { instanceRefKlass o; add_vtable(list, &n, &o, count); } { typeArrayKlassKlass o; add_vtable(list, &n, &o, count); } { typeArrayKlass o; add_vtable(list, &n, &o, count); } @@ -547,7 +549,7 @@ KlassHandle k(THREAD, klassOop(obj)); // We will never reach the CATCH below since Exceptions::_throw will cause // the VM to exit if an exception is thrown during initialization - java_lang_Class::create_mirror(k, CATCH); + java_lang_Class::fixup_mirror(k, CATCH); // This call unconditionally creates a new mirror for k, // and links in k's component_mirror field if k is an array. // If k is an objArray, k's element type must already have @@ -605,6 +607,10 @@ // walk over permanent objects created so far (mostly classes) and fixup their mirrors. Note // that the number of objects allocated at this point is very small. assert(SystemDictionary::Class_klass_loaded(), "java.lang.Class should be loaded"); + + // Cache the start of the static fields + instanceMirrorKlass::init_offset_of_static_fields(); + FixupMirrorClosure blk; Universe::heap()->permanent_object_iterate(&blk); } @@ -1313,6 +1319,8 @@ JNIHandles::verify(); if (!silent) gclog_or_tty->print("C-heap "); os::check_heap(); + if (!silent) gclog_or_tty->print("code cache "); + CodeCache::verify_oops(); if (!silent) gclog_or_tty->print_cr("]"); _verify_in_progress = false;
--- a/hotspot/src/share/vm/oops/arrayKlassKlass.cpp Fri Apr 01 15:43:37 2011 +0400 +++ b/hotspot/src/share/vm/oops/arrayKlassKlass.cpp Fri Apr 01 16:55:47 2011 -0700 @@ -28,6 +28,13 @@ #include "oops/arrayKlassKlass.hpp" #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" +#ifndef SERIALGC +#include "gc_implementation/parNew/parOopClosures.inline.hpp" +#include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" +#include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" +#include "memory/cardTableRS.hpp" +#include "oops/oop.pcgc.inline.hpp" +#endif