This commit is contained in:
Tom Rodriguez 2011-03-25 18:19:22 -04:00
commit 9cc2cbba4b
169 changed files with 4237 additions and 1440 deletions

View File

@ -108,3 +108,4 @@ a36beda9b9de91231d92a2c529f21cc218fcf8d5 jdk7-b130
d8af56da89bc0fc02a6b6ad78f51157a46d665ab jdk7-b131
d61280d36755d1941fb487f554e8b7a6d0bca6a1 jdk7-b132
fd444c61e7ed3d92b2a730da7c737b02191b682f jdk7-b133
def8e16dd237a47fc067d66d4c616d7baaec6001 jdk7-b134

View File

@ -108,3 +108,4 @@ cc58c11af15411042719e9c82707fdbef60a9e0f jdk7-b130
5d86d951426aaf340b1ba84ae2d5ab5da65a71e2 jdk7-b131
0f62a65fb666b337caa585015ab6ea2e60e709ca jdk7-b132
c6f380693342feadccc5fe2c5adf500e861361aa jdk7-b133
ddc2fcb3682ffd27f44354db666128827be7e3c3 jdk7-b134

9
README
View File

@ -29,13 +29,14 @@ Simple Build Instructions:
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.

View File

@ -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 &amp;&amp; <i>gmake</i>
<a href="#gmake"><tt>make</tt></a> sanity &amp;&amp; <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>
@ -1659,9 +1773,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>
@ -1682,6 +1795,81 @@
</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.
@ -1706,6 +1894,19 @@
Some of the more common problems with builds are briefly described
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>
@ -1801,7 +2002,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 +2015,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>

View File

@ -108,3 +108,4 @@ d7532bcd3742f1576dd07ff9fbb535c9c9a276e9 jdk7-b126
9d6dd2cdfcb92612dbd836ecded87770d52b49db jdk7-b131
1b1e75e8f476e5c07f0d2b035993895e2603e1f0 jdk7-b132
671fe2e623ffefb4b7c312be919fc71eb48c1df1 jdk7-b133
918003855fa0dba5acf4bf1fe36526d2fc4c1ba8 jdk7-b134

View File

@ -154,3 +154,5 @@ e9aa2ca89ad6c53420623d579765f9706ec523d7 hs21-b02
0e531ab5ba04967a0e9aa6aef65e6eb3a0dcf632 jdk7-b132
a8d643a4db47c7b58e0bcb49c77b5c3610de86a8 hs21-b03
1b3a350709e4325d759bb453ff3fb6a463270488 jdk7-b133
447e6faab4a8755d4860c2366630729dbaec111c jdk7-b134
3c76374706ea8a77e15aec8310e831e5734f8775 hs21-b04

View File

@ -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 @@ public class FieldImpl extends TypeComponentImpl implements Field {
// 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

View File

@ -44,12 +44,10 @@ public class StringTable extends sun.jvm.hotspot.utilities.Hashtable {
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 @@ public class StringTable extends sun.jvm.hotspot.utilities.Hashtable {
return (StringTable) VMObjectFactory.newObject(StringTable.class, tmp);
}
public static int getStringTableSize() {
return stringTableSize;
}
public StringTable(Address addr) {
super(addr);
}

View File

@ -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 @@ public class InstanceKlass extends Klass {
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 @@ public class InstanceKlass extends Klass {
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 class InstanceKlass extends Klass {
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 @@ public class InstanceKlass extends Klass {
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 class InstanceKlass extends Klass {
public long getObjectSize() {
long bodySize = alignObjectOffset(getVtableLen() * getHeap().getOopSize())
+ alignObjectOffset(getItableLen() * getHeap().getOopSize())
+ (getStaticFieldSize() + getNonstaticOopMapSize()) * getHeap().getOopSize();
+ (getNonstaticOopMapSize()) * getHeap().getOopSize();
return alignObjectSize(headerSize + bodySize);
}

View File

@ -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 @@ public class IntField extends Field {
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
}

View File

@ -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 class OopField extends Field {
}
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());
}

View File

@ -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 @@ public class OopUtilities implements /* imports */ JVMTIThreadState {
// 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 {

View File

@ -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 @@ public class VM {
}
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();

View File

@ -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 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
out.writeByte((byte)kind);
if (ik != null) {
// static field
writeField(field, ik);
writeField(field, ik.getJavaMirror());
}
}
}

View File

@ -43,6 +43,7 @@ if [ "$1" == "-help" ]; then
fi
jdk=$1
shift
OS=`uname`
if [ "$OS" != "Linux" ]; then
@ -68,7 +69,7 @@ fi
tmp=/tmp/sagsetup
rm -f $tmp
$jdk/bin/java sagtarg > $tmp &
$jdk/bin/java $* sagtarg > $tmp &
pid=$!
while [ ! -s $tmp ] ; do
# Kludge alert!

View File

@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2011
HS_MAJOR_VER=21
HS_MINOR_VER=0
HS_BUILD_NUMBER=04
HS_BUILD_NUMBER=05
JDK_MAJOR_VER=1
JDK_MINOR_VER=7

View File

@ -301,7 +301,8 @@ void PatchingStub::emit_code(LIR_Assembler* ce) {
// 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();

View File

@ -80,13 +80,19 @@ void CompactingPermGenGen::generate_vtable_methods(void** vtbl_list,
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);
}
}

View File

@ -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, CodeEntryAlignment, 32);
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, RewriteFrequentPairs, true);
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

View File

@ -52,6 +52,22 @@ void NativeInstruction::set_data64_sethi(address instaddr, intptr_t x) {
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);

View File

@ -254,6 +254,7 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC {
// 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) {

View File

@ -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 @@ void Relocation::pd_set_data_value(address x, intptr_t o) {
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 @@ void Relocation::pd_set_data_value(address x, intptr_t o) {
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;

View File

@ -313,10 +313,13 @@ void PatchingStub::emit_code(LIR_Assembler* ce) {
}
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);

View File

@ -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, RewriteFrequentPairs, true);
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

View File

@ -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 @@ void Relocation::pd_set_data_value(address x, intptr_t o) {
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
}

View File

@ -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 @@ int CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) {
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 @@ InterpreterFrame *InterpreterFrame::build(const methodOop method, TRAPS) {
(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);

View File

@ -3297,9 +3297,14 @@ bool os::is_interrupted(Thread* thread, bool clear_interrupted) {
"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

View File

@ -1471,9 +1471,9 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
if (code == Bytecodes::_getstatic || code == Bytecodes::_putstatic) {
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()));
}
}

View File

@ -808,7 +808,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i
{ 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:

View File

@ -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 @@ size_t ciCPCache::get_f1_offset(int index) {
// 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();
}

View File

@ -213,7 +213,7 @@ void ciField::initialize_from(fieldDescriptor* fd) {
// 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
@ -225,36 +225,38 @@ void ciField::initialize_from(fieldDescriptor* fd) {
}
}
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,

View File

@ -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 @@ void ciInstance::print_impl(outputStream* st) {
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();
}

View File

@ -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 @@ public:
// 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

View File

@ -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 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
if (h_k() != SystemDictionary::Object_klass()) {
super();
}
java_mirror();
//compute_nonstatic_fields(); // done outside of constructor
}
@ -320,6 +319,9 @@ ciInstanceKlass* ciInstanceKlass::super() {
// 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();
}

View File

@ -663,7 +663,7 @@ ciObjectFactory::NonPermObject* &ciObjectFactory::find_non_perm(oop key) {
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;
}

View File

@ -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"
@ -2606,54 +2607,6 @@ typeArrayHandle ClassFileParser::assemble_annotations(u1* runtime_visible_annota
}
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
@ -2769,8 +2722,8 @@ void ClassFileParser::java_lang_ref_Reference_fix_pre(typeArrayHandle* fields_pt
}
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
@ -2787,10 +2740,13 @@ void ClassFileParser::java_lang_Class_fix_pre(objArrayHandle* methods_ptr,
// 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;
}
@ -3205,9 +3161,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
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 &&
@ -3226,15 +3180,16 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
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);
}
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));
@ -3566,7 +3521,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
}
// 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));
@ -3588,7 +3543,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
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());
@ -3649,9 +3604,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// 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());
@ -3685,6 +3637,9 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
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 */);

View File

@ -154,11 +154,12 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
// 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);

View File

@ -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"
@ -161,7 +162,7 @@ Handle java_lang_String::create_from_unicode(jchar* unicode, int length, TRAPS)
}
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) {
@ -391,6 +392,75 @@ void java_lang_String::print(Handle java_string, outputStream* st) {
}
}
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");
@ -400,12 +470,17 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) {
// 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;
@ -428,6 +503,9 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) {
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 {
@ -436,21 +514,46 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) {
}
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;
@ -2152,7 +2255,7 @@ void java_lang_boxing_object::print(BasicType type, jvalue* value, outputStream*
// 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 {
@ -2162,7 +2265,7 @@ oop java_lang_ref_Reference::pending_list_lock() {
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;
}
@ -2185,16 +2288,14 @@ jlong java_lang_ref_SoftReference::timestamp(oop ref) {
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;
}
@ -2625,26 +2726,18 @@ oop java_lang_ClassLoader::non_reflection_class_loader(oop loader) {
// 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);
}
@ -2657,6 +2750,8 @@ int java_lang_Class::klass_offset;
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;
@ -2700,7 +2795,6 @@ int java_lang_ref_Reference::number_of_fake_oop_fields;
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;
@ -2817,10 +2911,19 @@ void JavaClasses::compute_hard_coded_offsets() {
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;
@ -2877,7 +2980,6 @@ void JavaClasses::compute_hard_coded_offsets() {
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) {
@ -2961,10 +3063,10 @@ bool JavaClasses::check_static_offset(const char *klass_name, int hardcoded_offs
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;
}
}

View File

@ -138,10 +138,8 @@ class java_lang_Class : AllStatic {
// 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 @@ class java_lang_Class : AllStatic {
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 @@ class java_lang_Class : AllStatic {
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 @@ class java_lang_Class : AllStatic {
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
@ -1165,13 +1173,10 @@ class java_lang_System : AllStatic {
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();

View File

@ -530,7 +530,7 @@ oop StringTable::basic_add(int index, Handle string_or_null, jchar* name,
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);
@ -662,7 +662,7 @@ void StringTable::verify() {
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);

View File

@ -216,18 +216,14 @@ private:
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 @@ public:
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);
}

View File

@ -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 @@ void CodeCache::scavenge_root_nmethods_do(CodeBlobClosure* f) {
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::gc_epilogue() {
}
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();

View File

@ -122,6 +122,7 @@ class CodeCache : AllStatic {
// 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.

View File

@ -653,6 +653,9 @@ nmethod::nmethod(
_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);
}
@ -1105,6 +1108,20 @@ void nmethod::fix_oop_relocations(address begin, address end, bool initialize_im
}
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");
@ -1823,6 +1840,7 @@ void nmethod::oops_do_marking_epilogue() {
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;
}

View File

@ -459,6 +459,7 @@ private:
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);

View File

@ -798,6 +798,14 @@ void oop_Relocation::fix_oop_relocation() {
}
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");

View File

@ -765,7 +765,8 @@ class Relocation VALUE_OBJ_CLASS_SPEC {
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 @@ class DataRelocation : public Relocation {
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 @@ class oop_Relocation : public DataRelocation {
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; }

View File

@ -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 ConcurrentMarkSweepGeneration::ref_processor_init() {
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 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
}
// 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 @@ void CMSCollector::request_full_gc(unsigned int full_gc_count) {
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 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) {
// 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 @@ bool CMSCollector::do_marking_mt(bool asynch) {
// 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 @@ bool CMSCollector::do_marking_st(bool asynch) {
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 @@ void CMSCollector::preclean() {
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 @@ size_t CMSCollector::preclean_work(bool clean_refs, bool clean_survivor) {
_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 @@ void CMSCollector::do_remark_parallel() {
// 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 @@ public:
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 @@ void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) {
// 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 @@ void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) {
}
{
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

View File

@ -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 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
// 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

View File

@ -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 @@ int ConcurrentMarkSweepThread::_CMS_flag = CMS_nil;
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 @@ ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector)
}
}
_sltMonitor = SLT_lock;
set_icms_enabled(CMSIncrementalMode);
assert(!CMSIncrementalMode || icms_is_enabled(), "Error");
}
void ConcurrentMarkSweepThread::run() {
@ -341,11 +341,11 @@ void ConcurrentMarkSweepThread::stop_icms() {
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();

View File

@ -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 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread {
static SurrogateLockerThread::SLT_msg_type _sltBuffer;
static Monitor* _sltMonitor;
ConcurrentMarkSweepThread* _next;
static bool _should_terminate;
enum CMS_flag_type {
@ -84,7 +82,7 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread {
// 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 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread {
// 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) {

View File

@ -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 @@ void VM_GenCollectFullConcurrent::doit() {
"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 @@ void VM_GenCollectFullConcurrent::doit_epilogue() {
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();
}
}

View File

@ -128,11 +128,14 @@ class VM_CMS_Final_Remark: public VM_CMS_Operation {
// 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");
}

View File

@ -373,7 +373,7 @@ void ConcurrentG1Refine::clean_up_cache(int worker_i,
// 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);
}
}

View File

@ -1828,7 +1828,7 @@ void ConcurrentMark::completeCleanup() {
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 @@ void ConcurrentMark::completeCleanup() {
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 @@ void ConcurrentMark::completeCleanup() {
// 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 @@ void ConcurrentMark::completeCleanup() {
}
}
}
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 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
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 @@ public:
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::deal_with_reference(oop obj) {
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 CMTask::drain_local_queue(bool partially) {
(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);

View File

@ -237,9 +237,9 @@ void ConcurrentMarkThread::run() {
// 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();

View File

@ -479,7 +479,7 @@ G1CollectedHeap* G1CollectedHeap::_g1h;
// 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 @@ HeapRegion* G1CollectedHeap::new_region_work(size_t word_size,
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 @@ HeapRegion* G1CollectedHeap::new_region_work(size_t word_size,
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 @@ HeapRegion* G1CollectedHeap::new_gc_alloc_region(int purpose,
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 @@ int G1CollectedHeap::humongous_obj_allocate_find_first(size_t num_regions,
// 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 @@ int G1CollectedHeap::humongous_obj_allocate_find_first(size_t num_regions,
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 @@ int G1CollectedHeap::humongous_obj_allocate_find_first(size_t num_regions,
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* G1CollectedHeap::humongous_obj_allocate(size_t word_size) {
}
}
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 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
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 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
// 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 @@ void G1CollectedHeap::ref_processing_init() {
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 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
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 @@ void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) {
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 @@ void G1CollectedHeap::verify_region_sets() {
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.

View File

@ -56,7 +56,6 @@ class HeapRegionRemSetIterator;
class ConcurrentMark;
class ConcurrentMarkThread;
class ConcurrentG1Refine;
class ConcurrentZFThread;
typedef OverflowTaskQueue<StarTask> RefToScanQueue;
typedef GenericTaskQueueSet<RefToScanQueue> RefToScanQueueSet;
@ -64,12 +63,6 @@ typedef GenericTaskQueueSet<RefToScanQueue> RefToScanQueueSet;
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 @@ private:
// 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 @@ private:
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 @@ private:
"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 @@ protected:
// 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 @@ protected:
// 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 @@ protected:
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 @@ public:
#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 @@ public:
_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();

View File

@ -81,6 +81,57 @@ static double non_young_other_cost_per_region_ms_defaults[] = {
// </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 @@ void G1CollectorPolicy::print_par_stats(int level,
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 @@ void G1CollectorPolicy::print_par_stats(int level,
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 @@ void G1CollectorPolicy::print_par_sizes(int level,
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 @@ void G1CollectorPolicy::print_par_sizes(int level,
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 @@ void G1CollectorPolicy::count_CS_bytes_used() {
_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 @@ void G1CollectorPolicy::print_summary_sd (int level,
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 @@ void G1CollectorPolicy::check_other_times(int level,
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 @@ void G1CollectorPolicy::check_other_times(int level,
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 @@ void G1CollectorPolicy::check_other_times(int level,
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 @@ void G1CollectorPolicy::print_summary(PauseSummary* summary) const {
}
}
} 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 @@ public:
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);
}
}

View File

@ -185,22 +185,22 @@ class G1PrepareCompactClosure: public HeapRegionClosure {
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 @@ public:
: _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 @@ public:
NULL, /* free_list */
&_humongous_proxy_set,
false /* par */);
_free_list.remove_all();
}
bool doHeapRegion(HeapRegion* hr) {

View File

@ -86,28 +86,6 @@ public:
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 @@ public:
// 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

View File

@ -53,8 +53,8 @@ class HeapRegion;
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 @@ class HeapRegion: public G1OffsetTableContigSpace {
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 @@ class HeapRegion: public G1OffsetTableContigSpace {
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;
}

View File

@ -165,7 +165,7 @@ int HeapRegionSeq::find_contiguous_from(int from, size_t num) {
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) {

View File

@ -76,7 +76,8 @@ class HeapRegionSeq: public CHeapObj {
// 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",

View File

@ -42,7 +42,7 @@ size_t HeapRegionSetBase::calculate_region_num(HeapRegion* hr) {
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 @@ void HeapRegionSetBase::verify() {
// 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_start() {
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_next_region(HeapRegion* hr) {
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 @@ HeapRegionSetBase::HeapRegionSetBase(const char* name)
//////////////////// 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 @@ void HeapRegionSet::update_from_proxy(HeapRegionSet* proxy_set) {
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 @@ void HeapRegionSet::update_from_proxy(HeapRegionSet* proxy_set) {
//////////////////// 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 @@ void HeapRegionLinkedList::add_as_tail(HeapRegionLinkedList* from_list) {
#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::add_as_tail(HeapRegionLinkedList* from_list) {
}
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() {
}
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 @@ void HeapRegionLinkedList::remove_all_pending(size_t target_count) {
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 @@ void HeapRegionLinkedList::remove_all_pending(size_t target_count) {
}
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::remove_all_pending(size_t target_count) {
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 @@ void HeapRegionLinkedList::verify() {
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 @@ void HeapRegionLinkedList::verify() {
curr = curr->next();
}
guarantee(_tail == prev0, hrl_ext_msg(this, "post-condition"));
guarantee(_tail == prev0, hrs_ext_msg(this, "post-condition"));
verify_end();
}

View File

@ -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 @@ typedef FormatBuffer<HRL_ERR_MSG_BUFSZ> hrl_err_msg;
// (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 @@ protected:
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 @@ public:
// 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 @@ public:
// 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 @@ private:
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 @@ public:
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:

View File

@ -42,8 +42,8 @@ inline void HeapRegionSetBase::update_for_addition(HeapRegion* hr) {
}
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::add_internal(HeapRegion* hr) {
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 @@ inline void HeapRegionSetBase::update_for_removal(HeapRegion* hr) {
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 @@ inline void HeapRegionSetBase::remove_internal(HeapRegion* hr) {
//////////////////// 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 @@ inline void HeapRegionSet::remove_with_proxy(HeapRegion* hr,
// 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 @@ inline void HeapRegionSet::remove_with_proxy(HeapRegion* hr,
//////////////////// 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 void HeapRegionLinkedList::add_as_tail(HeapRegion* hr) {
}
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() {
}
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();

View File

@ -52,7 +52,7 @@ bool MasterFreeRegionList::check_mt_safety() {
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 @@ bool SecondaryFreeRegionList::check_mt_safety() {
// 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 @@ const char* HumongousRegionSet::verify_region_extra(HeapRegion* hr) {
return HeapRegionSet::verify_region_extra(hr);
}
//////////////////// HumongousRegionSet ////////////////////
//////////////////// MasterHumongousRegionSet ////////////////////
bool MasterHumongousRegionSet::check_mt_safety() {
// Master Humongous Set MT safety protocol:
@ -97,6 +97,6 @@ bool MasterHumongousRegionSet::check_mt_safety() {
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();
}

View File

@ -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 @@ void ParNewGeneration::ref_processor_init()
{
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
}
}

View File

@ -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 @@ CollectorCounters* PSMarkSweep::_counters = NULL;
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);
}

View File

@ -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 @@ void PSParallelCompact::post_initialize() {
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.

View File

@ -411,7 +411,7 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) {
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;

View File

@ -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 @@ bool PSScavenge::invoke_no_policy() {
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 @@ void PSScavenge::initialize() {
// 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();

View File

@ -86,4 +86,21 @@ inline void PSScavenge::copy_and_push_safe_barrier(PSPromotionManager* pm,
}
}
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

View File

@ -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");

View File

@ -656,7 +656,7 @@ BytecodeInterpreter::run(interpreterState istate) {
// 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 @@ run:
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:

View File

@ -118,7 +118,7 @@ IRT_ENTRY(void, InterpreterRuntime::ldc(JavaThread* thread, bool wide))
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
@ -983,7 +983,8 @@ IRT_ENTRY(void, InterpreterRuntime::post_field_access(JavaThread *thread, oopDes
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");
@ -1009,7 +1010,7 @@ ConstantPoolCacheEntry *cp_entry))
// 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
@ -1017,7 +1018,7 @@ IRT_END
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);

View File

@ -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 @@ void GenCollectorPolicy::initialize_size_info() {
// 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 @@ void GenCollectorPolicy::initialize_size_info() {
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 @@ void GenCollectorPolicy::initialize_size_info() {
}
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 @@ void TwoGenerationCollectorPolicy::initialize_size_info() {
// 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 @@ void TwoGenerationCollectorPolicy::initialize_size_info() {
"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 @@ void TwoGenerationCollectorPolicy::initialize_size_info() {
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());
}

View File

@ -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 @@ private:
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.
};

View File

@ -1561,6 +1561,7 @@ void GenCollectedHeap::preload_and_dump(TRAPS) {
// 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.

View File

@ -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 @@ void Generation::print_heap_change(size_t prev_used) const {
}
// 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");
}

View File

@ -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 @@ constantPoolCacheOop oopFactory::new_constantPoolCache(int length,
}
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);
}

View File

@ -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 @@ class oopFactory: AllStatic {
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);

View File

@ -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 @@ void ReferenceProcessor::init_statics() {
"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_discovery,
int mt_degree,
bool mt_processing,
int mt_processing_degree,
bool mt_discovery,
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 @@ ReferenceProcessor::ReferenceProcessor(MemRegion span,
_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 @@ ReferenceProcessor::ReferenceProcessor(MemRegion span,
if (discovered_list_needs_barrier) {
_bs = Universe::heap()->barrier_set();
}
setup_policy(false /* default soft ref policy */);
}
#ifndef PRODUCT
@ -405,15 +383,14 @@ public:
{ }
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 @@ ReferenceProcessor::pp2_work(DiscoveredList& refs_list,
}
}
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 @@ ReferenceProcessor::pp2_work_concurrent_discovery(DiscoveredList& refs_list,
// 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 @@ ReferenceProcessor::process_discovered_reflist(
}
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 @@ ReferenceProcessor::process_discovered_reflist(
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 @@ ReferenceProcessor::process_discovered_reflist(
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 @@ ReferenceProcessor::process_discovered_reflist(
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 @@ void ReferenceProcessor::clean_up_discovered_references() {
// 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 @@ void ReferenceProcessor::preclean_discovered_references(
{
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 @@ void ReferenceProcessor::preclean_discovered_references(
{
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 @@ void ReferenceProcessor::preclean_discovered_references(
{
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 @@ ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
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());

View File

@ -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 @@ class ReferenceProcessor : public CHeapObj {
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 @@ class ReferenceProcessor : public CHeapObj {
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 @@ class ReferenceProcessor : public CHeapObj {
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,24 +258,16 @@ class ReferenceProcessor : public CHeapObj {
_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,
// 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);
// 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);
// RefDiscoveryPolicy values
enum DiscoveryPolicy {
ReferenceBasedDiscovery = 0,
@ -397,20 +391,20 @@ class ReferenceProcessorSpanMutator: StackObj {
// 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);
}
};

View File

@ -171,11 +171,13 @@ void SharedHeap::process_strong_roots(bool activate_scope,
}
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)) {

View File

@ -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 @@ void Universe::init_self_patching_vtbl_list(void** list, int count) {
{ 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 @@ class FixupMirrorClosure: public ObjectClosure {
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 @@ void Universe::fixup_mirrors(TRAPS) {
// 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 @@ void Universe::verify(bool allow_dirty, bool silent, bool option) {
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;

View File

@ -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
klassOop arrayKlassKlass::create_klass(TRAPS) {
@ -104,9 +111,12 @@ int arrayKlassKlass::oop_oop_iterate(oop obj, OopClosure* blk) {
int arrayKlassKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) {
assert(obj->is_klass(), "must be klass");
arrayKlass* ak = arrayKlass::cast(klassOop(obj));
blk->do_oop(ak->adr_component_mirror());
blk->do_oop(ak->adr_lower_dimension());
blk->do_oop(ak->adr_higher_dimension());
oop* addr = ak->adr_component_mirror();
if (mr.contains(addr)) blk->do_oop(addr);
addr = ak->adr_lower_dimension();
if (mr.contains(addr)) blk->do_oop(addr);
addr = ak->adr_higher_dimension();
if (mr.contains(addr)) blk->do_oop(addr);
ak->vtable()->oop_oop_iterate_m(blk, mr);
return klassKlass::oop_oop_iterate_m(obj, blk, mr);
}
@ -114,6 +124,12 @@ int arrayKlassKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) {
#ifndef SERIALGC
void arrayKlassKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
assert(obj->blueprint()->oop_is_arrayKlass(),"must be an array klass");
arrayKlass* ak = arrayKlass::cast(klassOop(obj));
oop* p = ak->adr_component_mirror();
if (PSScavenge::should_scavenge(p)) {
pm->claim_or_forward_depth(p);
}
klassKlass::oop_push_contents(pm, obj);
}
int arrayKlassKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {

View File

@ -285,10 +285,11 @@ int constantPoolKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
void constantPoolKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
assert(obj->is_constantPool(), "should be constant pool");
constantPoolOop cp = (constantPoolOop) obj;
if (AnonymousClasses && cp->has_pseudo_string() && cp->tags() != NULL) {
oop* base = (oop*)cp->base();
for (int i = 0; i < cp->length(); ++i, ++base) {
if (cp->tags() != NULL &&
(!JavaObjectsInPerm || (AnonymousClasses && cp->has_pseudo_string()))) {
for (int i = 1; i < cp->length(); ++i) {
if (cp->tag_at(i).is_string()) {
oop* base = cp->obj_at_addr_raw(i);
if (PSScavenge::should_scavenge(base)) {
pm->claim_or_forward_depth(base);
}
@ -460,7 +461,8 @@ void constantPoolKlass::oop_verify_on(oop obj, outputStream* st) {
if (cp->tag_at(i).is_string()) {
if (!cp->has_pseudo_string()) {
if (entry.is_oop()) {
guarantee(entry.get_oop()->is_perm(), "should be in permspace");
guarantee(!JavaObjectsInPerm || entry.get_oop()->is_perm(),
"should be in permspace");
guarantee(entry.get_oop()->is_instance(), "should be instance");
}
} else {

View File

@ -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
@ -481,7 +481,7 @@ oop constantPoolOopDesc::resolve_constant_at_impl(constantPoolHandle this_oop, i
{
klassOop resolved = klass_at_impl(this_oop, index, CHECK_NULL);
// ldc wants the java mirror.
result_oop = resolved->klass_part()->java_mirror();
result_oop = resolved->java_mirror();
break;
}

View File

@ -168,22 +168,18 @@ int constantPoolCacheKlass::oop_adjust_pointers(oop obj) {
void constantPoolCacheKlass::oop_push_contents(PSPromotionManager* pm,
oop obj) {
assert(obj->is_constantPoolCache(), "should be constant pool");
if (EnableInvokeDynamic) {
if (ScavengeRootsInCode) {
constantPoolCacheOop cache = (constantPoolCacheOop)obj;
// during a scavenge, it is safe to inspect my pool, since it is perm
constantPoolOop pool = cache->constant_pool();
assert(pool->is_constantPool(), "should be constant pool");
if (pool->has_invokedynamic()) {
for (int i = 0; i < cache->length(); i++) {
ConstantPoolCacheEntry* e = cache->entry_at(i);
oop* p = (oop*)&e->_f1;
if (e->is_secondary_entry()) {
if (PSScavenge::should_scavenge(p))
pm->claim_or_forward_depth(p);
assert(!(e->is_vfinal() && PSScavenge::should_scavenge((oop*)&e->_f2)),
"no live oops here");
}
}
for (int i = 0; i < cache->length(); i++) {
ConstantPoolCacheEntry* e = cache->entry_at(i);
oop* p = (oop*)&e->_f1;
if (PSScavenge::should_scavenge(p))
pm->claim_or_forward_depth(p);
assert(!(e->is_vfinal() && PSScavenge::should_scavenge((oop*)&e->_f2)),
"no live oops here");
}
}
}

View File

@ -133,7 +133,7 @@ void ConstantPoolCacheEntry::set_field(Bytecodes::Code get_code,
TosState field_type,
bool is_final,
bool is_volatile) {
set_f1(field_holder());
set_f1(field_holder()->java_mirror());
set_f2(field_offset);
// The field index is used by jvm/ti and is the index into fields() array
// in holder instanceKlass. This is scaled by instanceKlass::next_offset.

View File

@ -37,6 +37,7 @@
#include "memory/oopFactory.hpp"
#include "memory/permGen.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceMirrorKlass.hpp"
#include "oops/instanceOop.hpp"
#include "oops/methodOop.hpp"
#include "oops/objArrayKlassKlass.hpp"
@ -649,6 +650,7 @@ instanceOop instanceKlass::register_finalizer(instanceOop i, TRAPS) {
}
instanceOop instanceKlass::allocate_instance(TRAPS) {
assert(!oop_is_instanceMirror(), "wrong allocation path");
bool has_finalizer_flag = has_finalizer(); // Query before possible GC
int size = size_helper(); // Query before forming handle.
@ -669,6 +671,7 @@ instanceOop instanceKlass::allocate_permanent_instance(TRAPS) {
// instances so simply disallow finalizable perm objects. This can
// be relaxed if a need for it is found.
assert(!has_finalizer(), "perm objects not allowed to have finalizers");
assert(!oop_is_instanceMirror(), "wrong allocation path");
int size = size_helper(); // Query before forming handle.
KlassHandle h_k(THREAD, as_klassOop());
instanceOop i = (instanceOop)
@ -898,6 +901,7 @@ void instanceKlass::methods_do(void f(methodOop method)) {
}
}
void instanceKlass::do_local_static_fields(FieldClosure* cl) {
fieldDescriptor fd;
int length = fields()->length();
@ -1609,36 +1613,6 @@ template <class T> void assert_nothing(T *p) {}
// The following macros call specialized macros, passing either oop or
// narrowOop as the specialization type. These test the UseCompressedOops
// flag.
#define InstanceKlass_OOP_ITERATE(start_p, count, \
do_oop, assert_fn) \
{ \
if (UseCompressedOops) { \
InstanceKlass_SPECIALIZED_OOP_ITERATE(narrowOop, \
start_p, count, \
do_oop, assert_fn) \
} else { \
InstanceKlass_SPECIALIZED_OOP_ITERATE(oop, \
start_p, count, \
do_oop, assert_fn) \
} \
}
#define InstanceKlass_BOUNDED_OOP_ITERATE(start_p, count, low, high, \
do_oop, assert_fn) \
{ \
if (UseCompressedOops) { \
InstanceKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \
start_p, count, \
low, high, \
do_oop, assert_fn) \
} else { \
InstanceKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop, \
start_p, count, \
low, high, \
do_oop, assert_fn) \
} \
}
#define InstanceKlass_OOP_MAP_ITERATE(obj, do_oop, assert_fn) \
{ \
/* Compute oopmap block range. The common case \
@ -1711,38 +1685,6 @@ template <class T> void assert_nothing(T *p) {}
} \
}
void instanceKlass::follow_static_fields() {
InstanceKlass_OOP_ITERATE( \
start_of_static_fields(), static_oop_field_size(), \
MarkSweep::mark_and_push(p), \
assert_is_in_closed_subset)
}
#ifndef SERIALGC
void instanceKlass::follow_static_fields(ParCompactionManager* cm) {
InstanceKlass_OOP_ITERATE( \
start_of_static_fields(), static_oop_field_size(), \
PSParallelCompact::mark_and_push(cm, p), \
assert_is_in)
}
#endif // SERIALGC
void instanceKlass::adjust_static_fields() {
InstanceKlass_OOP_ITERATE( \
start_of_static_fields(), static_oop_field_size(), \
MarkSweep::adjust_pointer(p), \
assert_nothing)
}
#ifndef SERIALGC
void instanceKlass::update_static_fields() {
InstanceKlass_OOP_ITERATE( \
start_of_static_fields(), static_oop_field_size(), \
PSParallelCompact::adjust_pointer(p), \
assert_nothing)
}
#endif // SERIALGC
void instanceKlass::oop_follow_contents(oop obj) {
assert(obj != NULL, "can't follow the content of NULL object");
obj->follow_header();
@ -1829,22 +1771,6 @@ ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
#endif // !SERIALGC
void instanceKlass::iterate_static_fields(OopClosure* closure) {
InstanceKlass_OOP_ITERATE( \
start_of_static_fields(), static_oop_field_size(), \
closure->do_oop(p), \
assert_is_in_reserved)
}
void instanceKlass::iterate_static_fields(OopClosure* closure,
MemRegion mr) {
InstanceKlass_BOUNDED_OOP_ITERATE( \
start_of_static_fields(), static_oop_field_size(), \
mr.start(), mr.end(), \
(closure)->do_oop_v(p), \
assert_is_in_closed_subset)
}
int instanceKlass::oop_adjust_pointers(oop obj) {
int size = size_helper();
InstanceKlass_OOP_MAP_ITERATE( \
@ -1873,21 +1799,6 @@ int instanceKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
return size_helper();
}
void instanceKlass::push_static_fields(PSPromotionManager* pm) {
InstanceKlass_OOP_ITERATE( \
start_of_static_fields(), static_oop_field_size(), \
if (PSScavenge::should_scavenge(p)) { \
pm->claim_or_forward_depth(p); \
}, \
assert_nothing )
}
void instanceKlass::copy_static_fields(ParCompactionManager* cm) {
InstanceKlass_OOP_ITERATE( \
start_of_static_fields(), static_oop_field_size(), \
PSParallelCompact::adjust_pointer(p), \
assert_is_in)
}
#endif // SERIALGC
// This klass is alive but the implementor link is not followed/updated.
@ -2002,6 +1913,11 @@ void instanceKlass::set_source_debug_extension(Symbol* n) {
if (_source_debug_extension != NULL) _source_debug_extension->increment_refcount();
}
address instanceKlass::static_field_addr(int offset) {
return (address)(offset + instanceMirrorKlass::offset_of_static_fields() + (intptr_t)java_mirror());
}
const char* instanceKlass::signature_name() const {
const char* src = (const char*) (name()->as_C_string());
const int src_length = (int)strlen(src);
@ -2369,7 +2285,7 @@ nmethod* instanceKlass::lookup_osr_nmethod(const methodOop m, int bci, int comp_
void FieldPrinter::do_field(fieldDescriptor* fd) {
_st->print(BULLET);
if (fd->is_static() || (_obj == NULL)) {
if (_obj == NULL) {
fd->print_on(_st);
_st->cr();
} else {
@ -2399,8 +2315,8 @@ void instanceKlass::oop_print_on(oop obj, outputStream* st) {
}
st->print_cr(BULLET"---- fields (total size %d words):", oop_size(obj));
FieldPrinter print_nonstatic_field(st, obj);
do_nonstatic_fields(&print_nonstatic_field);
FieldPrinter print_field(st, obj);
do_nonstatic_fields(&print_field);
if (as_klassOop() == SystemDictionary::Class_klass()) {
st->print(BULLET"signature: ");
@ -2418,6 +2334,12 @@ void instanceKlass::oop_print_on(oop obj, outputStream* st) {
st->print(BULLET"fake entry for array: ");
array_klass->print_value_on(st);
st->cr();
st->print_cr(BULLET"fake entry for oop_size: %d", java_lang_Class::oop_size(obj));
st->print_cr(BULLET"fake entry for static_oop_field_count: %d", java_lang_Class::static_oop_field_count(obj));
klassOop real_klass = java_lang_Class::as_klassOop(obj);
if (real_klass && real_klass->klass_part()->oop_is_instance()) {
instanceKlass::cast(real_klass)->do_local_static_fields(&print_field);
}
} else if (as_klassOop() == SystemDictionary::MethodType_klass()) {
st->print(BULLET"signature: ");
java_lang_invoke_MethodType::print_signature(obj, st);
@ -2560,7 +2482,7 @@ void JNIid::deallocate(JNIid* current) {
void JNIid::verify(klassOop holder) {
int first_field_offset = instanceKlass::cast(holder)->offset_of_static_fields();
int first_field_offset = instanceMirrorKlass::offset_of_static_fields();
int end_field_offset;
end_field_offset = first_field_offset + (instanceKlass::cast(holder)->static_field_size() * wordSize);

View File

@ -75,8 +75,6 @@
// [Java vtable length ]
// [oop map cache (stack maps) ]
// [EMBEDDED Java vtable ] size in words = vtable_len
// [EMBEDDED static oop fields ] size in words = static_oop_fields_size
// [ static non-oop fields ] size in words = static_field_size - static_oop_fields_size
// [EMBEDDED nonstatic oop-map blocks] size in words = nonstatic_oop_map_size
//
// The embedded nonstatic oop-map blocks are short pairs (offset, length) indicating
@ -230,7 +228,7 @@ class instanceKlass: public Klass {
// (including inherited fields but after header_size()).
int _nonstatic_field_size;
int _static_field_size; // number words used by static fields (oop and non-oop) in this klass
int _static_oop_field_size;// number of static oop fields in this klass
int _static_oop_field_count;// number of static oop fields in this klass
int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks
bool _is_marked_dependent; // used for marking during flushing and deoptimization
bool _rewritten; // methods rewritten.
@ -281,8 +279,8 @@ class instanceKlass: public Klass {
int static_field_size() const { return _static_field_size; }
void set_static_field_size(int size) { _static_field_size = size; }
int static_oop_field_size() const { return _static_oop_field_size; }
void set_static_oop_field_size(int size) { _static_oop_field_size = size; }
int static_oop_field_count() const { return _static_oop_field_count; }
void set_static_oop_field_count(int size) { _static_oop_field_count = size; }
// Java vtable
int vtable_length() const { return _vtable_len; }
@ -660,6 +658,7 @@ class instanceKlass: public Klass {
// Casting from klassOop
static instanceKlass* cast(klassOop k) {
assert(k->is_klass(), "must be");
Klass* kp = k->klass_part();
assert(kp->null_vtbl() || kp->oop_is_instance_slow(), "cast to instanceKlass");
return (instanceKlass*) kp;
@ -667,7 +666,7 @@ class instanceKlass: public Klass {
// Sizing (in words)
static int header_size() { return align_object_offset(oopDesc::header_size() + sizeof(instanceKlass)/HeapWordSize); }
int object_size() const { return object_size(align_object_offset(vtable_length()) + align_object_offset(itable_length()) + static_field_size() + nonstatic_oop_map_size()); }
int object_size() const { return object_size(align_object_offset(vtable_length()) + align_object_offset(itable_length()) + nonstatic_oop_map_size()); }
static int vtable_start_offset() { return header_size(); }
static int vtable_length_offset() { return oopDesc::header_size() + offset_of(instanceKlass, _vtable_len) / HeapWordSize; }
static int object_size(int extra) { return align_object_size(header_size() + extra); }
@ -676,20 +675,12 @@ class instanceKlass: public Klass {
intptr_t* start_of_itable() const { return start_of_vtable() + align_object_offset(vtable_length()); }
int itable_offset_in_words() const { return start_of_itable() - (intptr_t*)as_klassOop(); }
// Static field offset is an offset into the Heap, should be converted by
// based on UseCompressedOop for traversal
HeapWord* start_of_static_fields() const {
return (HeapWord*)(start_of_itable() + align_object_offset(itable_length()));
}
intptr_t* end_of_itable() const { return start_of_itable() + itable_length(); }
int offset_of_static_fields() const {
return (intptr_t)start_of_static_fields() - (intptr_t)as_klassOop();
}
address static_field_addr(int offset);
OopMapBlock* start_of_nonstatic_oop_maps() const {
return (OopMapBlock*) (start_of_static_fields() + static_field_size());
return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length()));
}
// Allocation profiling support
@ -719,8 +710,6 @@ class instanceKlass: public Klass {
// Garbage collection
void oop_follow_contents(oop obj);
void follow_static_fields();
void adjust_static_fields();
int oop_adjust_pointers(oop obj);
bool object_is_parsable() const { return _init_state != unparsable_by_gc; }
// Value of _init_state must be zero (unparsable_by_gc) when klass field is set.
@ -732,16 +721,6 @@ class instanceKlass: public Klass {
// Parallel Scavenge and Parallel Old
PARALLEL_GC_DECLS
#ifndef SERIALGC
// Parallel Scavenge
void push_static_fields(PSPromotionManager* pm);
// Parallel Old
void follow_static_fields(ParCompactionManager* cm);
void copy_static_fields(ParCompactionManager* cm);
void update_static_fields();
#endif // SERIALGC
// Naming
const char* signature_name() const;
@ -770,9 +749,6 @@ class instanceKlass: public Klass {
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
#endif // !SERIALGC
void iterate_static_fields(OopClosure* closure);
void iterate_static_fields(OopClosure* closure, MemRegion mr);
private:
// initialization state
#ifdef ASSERT
@ -926,6 +902,10 @@ class JNIid: public CHeapObj {
// Identifier lookup
JNIid* find(int offset);
bool find_local_field(fieldDescriptor* fd) {
return instanceKlass::cast(holder())->find_local_field_from_offset(offset(), true, fd);
}
// Garbage collection support
oop* holder_addr() { return (oop*)&_holder; }
void oops_do(OopClosure* f);

View File

@ -31,6 +31,7 @@
#include "memory/gcLocker.hpp"
#include "oops/constantPoolOop.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceMirrorKlass.hpp"
#include "oops/instanceKlassKlass.hpp"
#include "oops/instanceRefKlass.hpp"
#include "oops/objArrayKlassKlass.hpp"
@ -86,7 +87,6 @@ void instanceKlassKlass::oop_follow_contents(oop obj) {
assert(klassOop(obj)->klass_part()->oop_is_instance_slow(), "must be instance klass");
instanceKlass* ik = instanceKlass::cast(klassOop(obj));
ik->follow_static_fields();
{
HandleMark hm;
ik->vtable()->oop_follow_contents();
@ -127,7 +127,6 @@ void instanceKlassKlass::oop_follow_contents(ParCompactionManager* cm,
assert(klassOop(obj)->klass_part()->oop_is_instance_slow(), "must be instance klass");
instanceKlass* ik = instanceKlass::cast(klassOop(obj));
ik->follow_static_fields(cm);
ik->vtable()->oop_follow_contents(cm);
ik->itable()->oop_follow_contents(cm);
@ -168,7 +167,6 @@ int instanceKlassKlass::oop_oop_iterate(oop obj, OopClosure* blk) {
// Don't call size() or oop_size() since that is a virtual call.
int size = ik->object_size();
ik->iterate_static_fields(blk);
ik->vtable()->oop_oop_iterate(blk);
ik->itable()->oop_oop_iterate(blk);
@ -209,7 +207,6 @@ int instanceKlassKlass::oop_oop_iterate_m(oop obj, OopClosure* blk,
// Don't call size() or oop_size() since that is a virtual call.
int size = ik->object_size();
ik->iterate_static_fields(blk, mr);
ik->vtable()->oop_oop_iterate_m(blk, mr);
ik->itable()->oop_oop_iterate_m(blk, mr);
@ -266,7 +263,6 @@ int instanceKlassKlass::oop_adjust_pointers(oop obj) {
assert(klassOop(obj)->klass_part()->oop_is_instance_slow(), "must be instance klass");
instanceKlass* ik = instanceKlass::cast(klassOop(obj));
ik->adjust_static_fields();
ik->vtable()->oop_adjust_pointers();
ik->itable()->oop_adjust_pointers();
@ -300,7 +296,6 @@ int instanceKlassKlass::oop_adjust_pointers(oop obj) {
#ifndef SERIALGC
void instanceKlassKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
instanceKlass* ik = instanceKlass::cast(klassOop(obj));
ik->push_static_fields(pm);
oop* loader_addr = ik->adr_class_loader();
if (PSScavenge::should_scavenge(loader_addr)) {
@ -336,7 +331,6 @@ int instanceKlassKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
"must be instance klass");
instanceKlass* ik = instanceKlass::cast(klassOop(obj));
ik->update_static_fields();
ik->vtable()->oop_update_pointers(cm);
ik->itable()->oop_update_pointers(cm);
@ -356,22 +350,28 @@ int instanceKlassKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
#endif // SERIALGC
klassOop
instanceKlassKlass::allocate_instance_klass(int vtable_len, int itable_len,
instanceKlassKlass::allocate_instance_klass(Symbol* name, int vtable_len, int itable_len,
int static_field_size,
unsigned nonstatic_oop_map_count,
ReferenceType rt, TRAPS) {
const int nonstatic_oop_map_size =
instanceKlass::nonstatic_oop_map_size(nonstatic_oop_map_count);
int size = instanceKlass::object_size(align_object_offset(vtable_len) + align_object_offset(itable_len) + static_field_size + nonstatic_oop_map_size);
int size = instanceKlass::object_size(align_object_offset(vtable_len) + align_object_offset(itable_len) + nonstatic_oop_map_size);
// Allocation
KlassHandle h_this_klass(THREAD, as_klassOop());
KlassHandle k;
if (rt == REF_NONE) {
// regular klass
instanceKlass o;
k = base_create_klass(h_this_klass, size, o.vtbl_value(), CHECK_NULL);
if (name != vmSymbols::java_lang_Class()) {
// regular klass
instanceKlass o;
k = base_create_klass(h_this_klass, size, o.vtbl_value(), CHECK_NULL);
} else {
// Class
instanceMirrorKlass o;
k = base_create_klass(h_this_klass, size, o.vtbl_value(), CHECK_NULL);
}
} else {
// reference klass
instanceRefKlass o;
@ -408,7 +408,7 @@ instanceKlassKlass::allocate_instance_klass(int vtable_len, int itable_len,
ik->set_source_debug_extension(NULL);
ik->set_array_name(NULL);
ik->set_inner_classes(NULL);
ik->set_static_oop_field_size(0);
ik->set_static_oop_field_count(0);
ik->set_nonstatic_field_size(0);
ik->set_is_marked_dependent(false);
ik->set_init_state(instanceKlass::allocated);
@ -442,9 +442,6 @@ instanceKlassKlass::allocate_instance_klass(int vtable_len, int itable_len,
// To get verify to work - must be set to partial loaded before first GC point.
k()->set_partially_loaded();
}
// GC can happen here
java_lang_Class::create_mirror(k, CHECK_NULL); // Allocate mirror
return k();
}
@ -566,13 +563,6 @@ void instanceKlassKlass::oop_print_on(oop obj, outputStream* st) {
FieldPrinter print_nonstatic_field(st);
ik->do_nonstatic_fields(&print_nonstatic_field);
st->print(BULLET"static oop maps: ");
if (ik->static_oop_field_size() > 0) {
int first_offset = ik->offset_of_static_fields();
st->print("%d-%d", first_offset, first_offset + ik->static_oop_field_size() - 1);
}
st->cr();
st->print(BULLET"non-static oop maps: ");
OopMapBlock* map = ik->start_of_nonstatic_oop_maps();
OopMapBlock* end_map = map + ik->nonstatic_oop_map_count();
@ -630,7 +620,6 @@ void instanceKlassKlass::oop_verify_on(oop obj, outputStream* st) {
// Verify static fields
VerifyFieldClosure blk;
ik->iterate_static_fields(&blk);
// Verify vtables
if (ik->is_linked()) {

View File

@ -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
@ -41,7 +41,8 @@ class instanceKlassKlass : public klassKlass {
// Allocation
DEFINE_ALLOCATE_PERMANENT(instanceKlassKlass);
static klassOop create_klass(TRAPS);
klassOop allocate_instance_klass(int vtable_len,
klassOop allocate_instance_klass(Symbol* name,
int vtable_len,
int itable_len,
int static_field_size,
unsigned int nonstatic_oop_map_count,

View File

@ -0,0 +1,313 @@
/*
* Copyright (c) 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc_implementation/shared/markSweep.inline.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "memory/genOopClosures.inline.hpp"
#include "memory/oopFactory.hpp"
#include "memory/permGen.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceMirrorKlass.hpp"
#include "oops/instanceOop.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "runtime/handles.inline.hpp"
#ifndef SERIALGC
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
#include "gc_implementation/g1/g1RemSet.inline.hpp"
#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
#include "gc_implementation/parNew/parOopClosures.inline.hpp"
#include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
#include "oops/oop.pcgc.inline.hpp"
#endif
int instanceMirrorKlass::_offset_of_static_fields = 0;
#ifdef ASSERT
template <class T> void assert_is_in(T *p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
oop o = oopDesc::decode_heap_oop_not_null(heap_oop);
assert(Universe::heap()->is_in(o), "should be in heap");
}
}
template <class T> void assert_is_in_closed_subset(T *p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
oop o = oopDesc::decode_heap_oop_not_null(heap_oop);
assert(Universe::heap()->is_in_closed_subset(o), "should be in closed");
}
}
template <class T> void assert_is_in_reserved(T *p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
oop o = oopDesc::decode_heap_oop_not_null(heap_oop);
assert(Universe::heap()->is_in_reserved(o), "should be in reserved");
}
}
template <class T> void assert_nothing(T *p) {}
#else
template <class T> void assert_is_in(T *p) {}
template <class T> void assert_is_in_closed_subset(T *p) {}
template <class T> void assert_is_in_reserved(T *p) {}
template <class T> void assert_nothing(T *p) {}
#endif // ASSERT
#define InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE( \
T, start_p, count, do_oop, \
assert_fn) \
{ \
T* p = (T*)(start_p); \
T* const end = p + (count); \
while (p < end) { \
(assert_fn)(p); \
do_oop; \
++p; \
} \
}
#define InstanceMirrorKlass_SPECIALIZED_BOUNDED_OOP_ITERATE( \
T, start_p, count, low, high, \
do_oop, assert_fn) \
{ \
T* const l = (T*)(low); \
T* const h = (T*)(high); \
assert(mask_bits((intptr_t)l, sizeof(T)-1) == 0 && \
mask_bits((intptr_t)h, sizeof(T)-1) == 0, \
"bounded region must be properly aligned"); \
T* p = (T*)(start_p); \
T* end = p + (count); \
if (p < l) p = l; \
if (end > h) end = h; \
while (p < end) { \
(assert_fn)(p); \
do_oop; \
++p; \
} \
}
#define InstanceMirrorKlass_OOP_ITERATE(start_p, count, \
do_oop, assert_fn) \
{ \
if (UseCompressedOops) { \
InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE(narrowOop, \
start_p, count, \
do_oop, assert_fn) \
} else { \
InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE(oop, \
start_p, count, \
do_oop, assert_fn) \
} \
}
// The following macros call specialized macros, passing either oop or
// narrowOop as the specialization type. These test the UseCompressedOops
// flag.
#define InstanceMirrorKlass_BOUNDED_OOP_ITERATE(start_p, count, low, high, \
do_oop, assert_fn) \
{ \
if (UseCompressedOops) { \
InstanceMirrorKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \
start_p, count, \
low, high, \
do_oop, assert_fn) \
} else { \
InstanceMirrorKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop, \
start_p, count, \
low, high, \
do_oop, assert_fn) \
} \
}
void instanceMirrorKlass::oop_follow_contents(oop obj) {
instanceKlass::oop_follow_contents(obj);
InstanceMirrorKlass_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj), \
MarkSweep::mark_and_push(p), \
assert_is_in_closed_subset)
}
#ifndef SERIALGC
void instanceMirrorKlass::oop_follow_contents(ParCompactionManager* cm,
oop obj) {
instanceKlass::oop_follow_contents(cm, obj);
InstanceMirrorKlass_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj), \
PSParallelCompact::mark_and_push(cm, p), \
assert_is_in)
}
#endif // SERIALGC
int instanceMirrorKlass::oop_adjust_pointers(oop obj) {
int size = oop_size(obj);
instanceKlass::oop_adjust_pointers(obj);
InstanceMirrorKlass_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj), \
MarkSweep::adjust_pointer(p), \
assert_nothing)
return size;
}
#define InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(T, nv_suffix) \
InstanceMirrorKlass_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj), \
(closure)->do_oop##nv_suffix(p), \
assert_is_in_closed_subset) \
return oop_size(obj); \
#define InstanceMirrorKlass_BOUNDED_SPECIALIZED_OOP_ITERATE(T, nv_suffix, mr) \
InstanceMirrorKlass_BOUNDED_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj), \
mr.start(), mr.end(), \
(closure)->do_oop##nv_suffix(p), \
assert_is_in_closed_subset) \
return oop_size(obj); \
// Macro to define instanceMirrorKlass::oop_oop_iterate for virtual/nonvirtual for
// all closures. Macros calling macros above for each oop size.
#define InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
\
int instanceMirrorKlass:: \
oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { \
/* Get size before changing pointers */ \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk); \
\
instanceKlass::oop_oop_iterate##nv_suffix(obj, closure); \
\
if (UseCompressedOops) { \
InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(narrowOop, nv_suffix); \
} else { \
InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(oop, nv_suffix); \
} \
}
#ifndef SERIALGC
#define InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
\
int instanceMirrorKlass:: \
oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { \
/* Get size before changing pointers */ \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk); \
\
instanceKlass::oop_oop_iterate_backwards##nv_suffix(obj, closure); \
\
if (UseCompressedOops) { \
InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(narrowOop, nv_suffix); \
} else { \
InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(oop, nv_suffix); \
} \
}
#endif // !SERIALGC
#define InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \
\
int instanceMirrorKlass:: \
oop_oop_iterate##nv_suffix##_m(oop obj, \
OopClosureType* closure, \
MemRegion mr) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk); \
\
instanceKlass::oop_oop_iterate##nv_suffix##_m(obj, closure, mr); \
if (UseCompressedOops) { \
InstanceMirrorKlass_BOUNDED_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, mr); \
} else { \
InstanceMirrorKlass_BOUNDED_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, mr); \
} \
}
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN)
#ifndef SERIALGC
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
#endif // SERIALGC
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m)
#ifndef SERIALGC
void instanceMirrorKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
instanceKlass::oop_push_contents(pm, obj);
InstanceMirrorKlass_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj),\
if (PSScavenge::should_scavenge(p)) { \
pm->claim_or_forward_depth(p); \
}, \
assert_nothing )
}
int instanceMirrorKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
instanceKlass::oop_update_pointers(cm, obj);
InstanceMirrorKlass_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj),\
PSParallelCompact::adjust_pointer(p), \
assert_nothing)
return oop_size(obj);
}
#endif // SERIALGC
int instanceMirrorKlass::instance_size(KlassHandle k) {
if (k() != NULL && k->oop_is_instance()) {
return align_object_size(size_helper() + instanceKlass::cast(k())->static_field_size());
}
return size_helper();
}
instanceOop instanceMirrorKlass::allocate_instance(KlassHandle k, TRAPS) {
// Query before forming handle.
int size = instance_size(k);
KlassHandle h_k(THREAD, as_klassOop());
instanceOop i;
if (JavaObjectsInPerm) {
i = (instanceOop) CollectedHeap::permanent_obj_allocate(h_k, size, CHECK_NULL);
} else {
assert(ScavengeRootsInCode > 0, "must be");
i = (instanceOop) CollectedHeap::obj_allocate(h_k, size, CHECK_NULL);
}
return i;
}
int instanceMirrorKlass::oop_size(oop obj) const {
return java_lang_Class::oop_size(obj);
}
int instanceMirrorKlass::compute_static_oop_field_count(oop obj) {
klassOop k = java_lang_Class::as_klassOop(obj);
if (k != NULL && k->klass_part()->oop_is_instance()) {
return instanceKlass::cast(k)->static_oop_field_count();
}
return 0;
}

View File

@ -0,0 +1,110 @@
/*
* Copyright (c) 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_OOPS_INSTANCEMIRRORKLASS_HPP
#define SHARE_VM_OOPS_INSTANCEMIRRORKLASS_HPP
#include "oops/instanceKlass.hpp"
// An instanceMirrorKlass is a specialized instanceKlass for
// java.lang.Class instances. These instances are special because
// they contain the static fields of the class in addition to the
// normal fields of Class. This means they are variable sized
// instances and need special logic for computing their size and for
// iteration of their oops.
class instanceMirrorKlass: public instanceKlass {
private:
static int _offset_of_static_fields;
public:
// Type testing
bool oop_is_instanceMirror() const { return true; }
// Casting from klassOop
static instanceMirrorKlass* cast(klassOop k) {
assert(k->klass_part()->oop_is_instanceMirror(), "cast to instanceMirrorKlass");
return (instanceMirrorKlass*) k->klass_part();
}
// Returns the size of the instance including the extra static fields.
virtual int oop_size(oop obj) const;
// Static field offset is an offset into the Heap, should be converted by
// based on UseCompressedOop for traversal
static HeapWord* start_of_static_fields(oop obj) {
return (HeapWord*)((intptr_t)obj + offset_of_static_fields());
}
static void init_offset_of_static_fields() {
// Cache the offset of the static fields in the Class instance
assert(_offset_of_static_fields == 0, "once");
_offset_of_static_fields = instanceMirrorKlass::cast(SystemDictionary::Class_klass())->size_helper() << LogHeapWordSize;
}
static int offset_of_static_fields() {
return _offset_of_static_fields;
}
int compute_static_oop_field_count(oop obj);
// Given a Klass return the size of the instance
int instance_size(KlassHandle k);
// allocation
DEFINE_ALLOCATE_PERMANENT(instanceMirrorKlass);
instanceOop allocate_instance(KlassHandle k, TRAPS);
// Garbage collection
int oop_adjust_pointers(oop obj);
void oop_follow_contents(oop obj);
// Parallel Scavenge and Parallel Old
PARALLEL_GC_DECLS
int oop_oop_iterate(oop obj, OopClosure* blk) {
return oop_oop_iterate_v(obj, blk);
}
int oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) {
return oop_oop_iterate_v_m(obj, blk, mr);
}
#define InstanceMirrorKlass_OOP_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
int oop_oop_iterate##nv_suffix(oop obj, OopClosureType* blk); \
int oop_oop_iterate##nv_suffix##_m(oop obj, OopClosureType* blk, MemRegion mr);
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DECL)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DECL)
#ifndef SERIALGC
#define InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \
int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk);
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
#endif // !SERIALGC
};
#endif // SHARE_VM_OOPS_INSTANCEMIRRORKLASS_HPP

View File

@ -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
@ -577,6 +577,7 @@ class Klass : public Klass_vtbl {
public:
// type testing operations
virtual bool oop_is_instance_slow() const { return false; }
virtual bool oop_is_instanceMirror() const { return false; }
virtual bool oop_is_instanceRef() const { return false; }
virtual bool oop_is_array() const { return false; }
virtual bool oop_is_objArray_slow() const { return false; }
@ -811,4 +812,8 @@ class Klass : public Klass_vtbl {
#endif
};
inline oop klassOopDesc::java_mirror() const { return klass_part()->java_mirror(); }
#endif // SHARE_VM_OOPS_KLASS_HPP

View File

@ -41,6 +41,10 @@
#include "oops/typeArrayKlass.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
@ -175,6 +179,12 @@ int klassKlass::oop_adjust_pointers(oop obj) {
#ifndef SERIALGC
void klassKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
Klass* k = Klass::cast(klassOop(obj));
oop* p = k->adr_java_mirror();
if (PSScavenge::should_scavenge(p)) {
pm->claim_or_forward_depth(p);
}
}
int klassKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
@ -233,7 +243,7 @@ void klassKlass::oop_verify_on(oop obj, outputStream* st) {
if (k->java_mirror() != NULL || (k->oop_is_instance() && instanceKlass::cast(klassOop(obj))->is_loaded())) {
guarantee(k->java_mirror() != NULL, "should be allocated");
guarantee(k->java_mirror()->is_perm(), "should be in permspace");
guarantee(k->java_mirror()->is_perm() || !JavaObjectsInPerm, "should be in permspace");
guarantee(k->java_mirror()->is_instance(), "should be instance");
}
}

Some files were not shown because too many files have changed in this diff Show More