mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-19 23:48:50 +00:00
Merge
This commit is contained in:
commit
9cc2cbba4b
1
.hgtags
1
.hgtags
@ -108,3 +108,4 @@ a36beda9b9de91231d92a2c529f21cc218fcf8d5 jdk7-b130
|
||||
d8af56da89bc0fc02a6b6ad78f51157a46d665ab jdk7-b131
|
||||
d61280d36755d1941fb487f554e8b7a6d0bca6a1 jdk7-b132
|
||||
fd444c61e7ed3d92b2a730da7c737b02191b682f jdk7-b133
|
||||
def8e16dd237a47fc067d66d4c616d7baaec6001 jdk7-b134
|
||||
|
||||
@ -108,3 +108,4 @@ cc58c11af15411042719e9c82707fdbef60a9e0f jdk7-b130
|
||||
5d86d951426aaf340b1ba84ae2d5ab5da65a71e2 jdk7-b131
|
||||
0f62a65fb666b337caa585015ab6ea2e60e709ca jdk7-b132
|
||||
c6f380693342feadccc5fe2c5adf500e861361aa jdk7-b133
|
||||
ddc2fcb3682ffd27f44354db666128827be7e3c3 jdk7-b134
|
||||
|
||||
9
README
9
README
@ -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.
|
||||
|
||||
@ -54,7 +54,11 @@
|
||||
<li><a href="#opensolaris">OpenSolaris</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#directories">Source Directory Structure</a> </li>
|
||||
<li><a href="#directories">Source Directory Structure</a>
|
||||
<ul>
|
||||
<li><a href="#drops">Managing the Source Drops</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#building">Build Information</a>
|
||||
<ul>
|
||||
<li><a href="#gmake">GNU Make (<tt><i>gmake</i></tt>)</a> </li>
|
||||
@ -65,7 +69,7 @@
|
||||
<ul>
|
||||
<li><a href="#bootjdk">Bootstrap JDK</a> </li>
|
||||
<li><a href="#importjdk">Optional Import JDK</a> </li>
|
||||
<li><a href="#ant">Ant</a> </li>
|
||||
<li><a href="#ant">Ant 1.7.1</a> </li>
|
||||
<li><a href="#cacerts">Certificate Authority File (cacert)</a> </li>
|
||||
<li><a href="#compilers">Compilers</a>
|
||||
<ul>
|
||||
@ -114,13 +118,13 @@
|
||||
<a href="http://mercurial.selenic.com/wiki/Mercurial">Mercurial</a>.
|
||||
If you are new to Mercurial, please see the
|
||||
<a href="http://mercurial.selenic.com/wiki/BeginnersGuides">Beginner Guides</a>
|
||||
or refer to the <a href=""http://hgbook.red-bean.com/">Mercurial Book</a>.
|
||||
or refer to the <a href="http://hgbook.red-bean.com/">Mercurial Book</a>.
|
||||
The first few chapters of the book provide an excellent overview of
|
||||
Mercurial, what it is and how it works.
|
||||
<br>
|
||||
For using Mercurial with the OpenJDK refer to the
|
||||
<a href=""http://openjdk.java.net/guide/repositories.html#installConfig">
|
||||
Developer Guide: Installing and Configuring Mercurial</a>
|
||||
<a href="http://openjdk.java.net/guide/repositories.html#installConfig">
|
||||
Developer Guide: Installing and Configuring Mercurial</a>
|
||||
section for more information.
|
||||
The Forest Extension is not part of the Mercurial install,
|
||||
and is optional,
|
||||
@ -146,14 +150,14 @@
|
||||
using the Forest Extension:
|
||||
<blockquote>
|
||||
<tt>
|
||||
hg fclone http://openjdk.java.net/jdk7/jdk7 <i>YourOpenJDK</i>
|
||||
hg fclone http://hg.openjdk.java.net/jdk7/jdk7 <i>YourOpenJDK</i>
|
||||
</tt>
|
||||
</blockquote>
|
||||
To get the entire set of OpenJDK Mercurial repositories
|
||||
without using the Forest Extension:
|
||||
<blockquote>
|
||||
<tt>
|
||||
hg clone http://openjdk.java.net/jdk7/jdk7 <i>YourOpenJDK</i>
|
||||
hg clone http://hg.openjdk.java.net/jdk7/jdk7 <i>YourOpenJDK</i>
|
||||
<br>cd <i>YourOpenJDK</i>
|
||||
<br>sh ./get_source.sh
|
||||
</tt>
|
||||
@ -207,66 +211,50 @@
|
||||
<tr>
|
||||
<td>Linux X86 (32-bit)</td>
|
||||
<td>Fedora 9</td>
|
||||
<td>gcc 4 </td>
|
||||
<td>JDK 6u14 FCS </td>
|
||||
<td>gcc 4.3 </td>
|
||||
<td>JDK 6u18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Linux X64 (64-bit)</td>
|
||||
<td>Fedora 9</td>
|
||||
<td>gcc 4 </td>
|
||||
<td>JDK 6u14 FCS </td>
|
||||
<td>gcc 4.3 </td>
|
||||
<td>JDK 6u18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Solaris SPARC (32-bit)</td>
|
||||
<td>Solaris 10u2 + patches
|
||||
<br>
|
||||
See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank">
|
||||
SunSolve</a> for patch downloads.
|
||||
</td>
|
||||
<td>Solaris 10 Update 6</td>
|
||||
<td>Sun Studio 12 Update 1 + patches</td>
|
||||
<td>JDK 6u14 FCS </td>
|
||||
<td>JDK 6u18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Solaris SPARCV9 (64-bit)</td>
|
||||
<td>Solaris 10u2 + patches
|
||||
<br>
|
||||
See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank">
|
||||
SunSolve</a> for patch downloads.
|
||||
</td>
|
||||
<td>Solaris 10 Update 6</td>
|
||||
<td>Sun Studio 12 Update 1 + patches</td>
|
||||
<td>JDK 6u14 FCS </td>
|
||||
<td>JDK 6u18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Solaris X86 (32-bit)</td>
|
||||
<td>Solaris 10u2 + patches
|
||||
<br>
|
||||
See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank">
|
||||
SunSolve</a> for patch downloads.
|
||||
</td>
|
||||
<td>Solaris 10 Update 6</td>
|
||||
<td>Sun Studio 12 Update 1 + patches</td>
|
||||
<td>JDK 6u14 FCS </td>
|
||||
<td>JDK 6u18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Solaris X64 (64-bit)</td>
|
||||
<td>Solaris 10u2 + patches
|
||||
<br>
|
||||
See <a href="http://sunsolve.sun.com/pub-cgi/show.pl?target=patches/JavaSE" target="_blank">
|
||||
SunSolve</a> for patch downloads.
|
||||
</td>
|
||||
<td>Solaris 10 Update 6</td>
|
||||
<td>Sun Studio 12 Update 1 + patches</td>
|
||||
<td>JDK 6u14 FCS </td>
|
||||
<td>JDK 6u18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Windows X86 (32-bit)</td>
|
||||
<td>Windows XP</td>
|
||||
<td>Microsoft Visual Studio C++ 2010 Professional Edition</td>
|
||||
<td>JDK 6u14 FCS </td>
|
||||
<td>JDK 6u18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Windows X64 (64-bit)</td>
|
||||
<td>Windows Server 2003 - Enterprise x64 Edition</td>
|
||||
<td>Microsoft Visual Studio C++ 2010 Professional Edition</td>
|
||||
<td>JDK 6u14 FCS </td>
|
||||
<td>JDK 6u18</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@ -300,7 +288,7 @@
|
||||
way to do it is to execute the following commands as user
|
||||
<tt>root</tt>:
|
||||
<p/>
|
||||
<code>yum-builddep java-openjdk</code>
|
||||
<code>yum-builddep java-1.6.0-openjdk</code>
|
||||
<p/>
|
||||
<code>yum install gcc gcc-c++</code>
|
||||
<p/>
|
||||
@ -345,10 +333,10 @@
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<!-- ------------------------------------------------------ -->
|
||||
<h3><a name="centos">CentOS 5.2</a></h3>
|
||||
<h3><a name="centos">CentOS 5.5</a></h3>
|
||||
<blockquote>
|
||||
After installing
|
||||
<a href="http://www.centos.org/">CentOS 5.2</a>
|
||||
<a href="http://www.centos.org/">CentOS 5.5</a>
|
||||
you need to make sure you have
|
||||
the following Development bundles installed:
|
||||
<blockquote>
|
||||
@ -356,7 +344,7 @@
|
||||
<li>Development Libraries</li>
|
||||
<li>Development Tools</li>
|
||||
<li>Java Development</li>
|
||||
<li>X Software Development</li>
|
||||
<li>X Software Development (Including XFree86-devel)</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<p>
|
||||
@ -552,15 +540,105 @@
|
||||
building the OpenJDK runtime libraries and misc files.
|
||||
The top level <tt>Makefile</tt>
|
||||
is used to build the entire OpenJDK.
|
||||
|
||||
<h3><a name="drops">Managing the Source Drops</a></h3>
|
||||
<blockquote>
|
||||
<p>
|
||||
The repositories <tt>jaxp</tt> and <tt>jaxws</tt> actually
|
||||
do not contain the sources for JAXP or JAX-WS.
|
||||
These products have their own open source procedures at their
|
||||
<a href="http://jaxp.java.net/">JAXP</a> and
|
||||
<a href="http://jax-ws.java.net/">JAX-WS</a> home pages.
|
||||
The OpenJDK project does need access to these sources to build
|
||||
a complete JDK image because JAXP and JAX-WS are part of the JDK.
|
||||
The current process for delivery of the JAXP and JAX-WS sources
|
||||
involves so called "source drop bundles" downloaded from a public
|
||||
website.
|
||||
There are many reasons for this current mechanism, and it is
|
||||
understood that this is not ideal for the open source community.
|
||||
It is possible this process could change in the future.
|
||||
<br>
|
||||
<b>NOTE:</b> The <a href="http://download.java.net/openjdk/jdk7/">
|
||||
Complete OpenJDK Source Bundles</a> <u>will</u> contain the JAXP and
|
||||
JAX-WS sources.
|
||||
</p>
|
||||
|
||||
<h4><a name="dropcreation">Creation of New Source Drop Bundles</a></h4>
|
||||
<blockquote>
|
||||
<ol>
|
||||
<li>
|
||||
The JAXP or JAX-WS team prepares a new zip bundle,
|
||||
places a copy in a public download area on java.net,
|
||||
sends us a link and a list of CRs (Change Request Numbers).
|
||||
The older download bundles should not be deleted.
|
||||
It is the responsibility of the JAXP and JAX-WS team to
|
||||
place the proper GPL legal notices on the sources
|
||||
and do any filtering or java re-packaging for the
|
||||
OpenJDK instances of these classes.
|
||||
</li>
|
||||
<li>
|
||||
The OpenJDK team copies this new bundle into shared
|
||||
area (e.g. <tt>/java/devtools/share/jdk7-drops</tt>).
|
||||
Older bundles are never deleted so we retain the history.
|
||||
</li>
|
||||
<li>
|
||||
The OpenJDK team edits the ant property file
|
||||
<tt>jaxp/jaxp.properties</tt> or
|
||||
<tt>jaxws/jaxws.properties</tt> to update the
|
||||
base URL, the zip bundle name, and the MD5 checksum
|
||||
of the zip bundle
|
||||
(on Solaris: <tt>sum -c md5 <i>bundlename</i></tt>)
|
||||
</li>
|
||||
<li>
|
||||
OpenJDK team reviews and commits those changes with the
|
||||
given CRs.
|
||||
</li>
|
||||
</ol>
|
||||
</blockquote>
|
||||
|
||||
<h4><a name="dropusage">Using Source Drop Bundles</a></h4>
|
||||
<blockquote>
|
||||
<p>
|
||||
The ant scripts that build <tt>jaxp</tt> and <tt>jaxws</tt>
|
||||
will attempt to locate these zip bundles from the directory
|
||||
in the environment variable
|
||||
<tt><a href="#ALT_DROPS_DIR">ALT_DROPS_DIR</a></tt>.
|
||||
The checksums protect from getting the wrong, corrupted, or
|
||||
improperly modified sources.
|
||||
Once the sources are made available, the population will not
|
||||
happen again unless a <tt>make clobber</tt> is requested
|
||||
or the <tt>jaxp/drop/</tt> or <tt>jaxws/drop/</tt>
|
||||
directory is explicitly deleted.
|
||||
<br>
|
||||
<b>NOTE:</b> The default Makefile and ant script behavior
|
||||
is to NOT download these bundles from the public http site.
|
||||
In general, doing downloads
|
||||
during the build process is not advised, it creates too much
|
||||
unpredictability in the build process.
|
||||
However, you can use <tt>make ALLOW_DOWNLOADS=true</tt> to
|
||||
tell the ant script that the download of the zip bundle is
|
||||
acceptable.
|
||||
</p>
|
||||
<p>
|
||||
The recommended procedure for keeping a cache of these
|
||||
source bundles would be to download them once, place them
|
||||
in a directory outside the repositories, and then set
|
||||
<tt><a href="#ALT_DROPS_DIR">ALT_DROPS_DIR</a></tt> to refer
|
||||
to that directory.
|
||||
These drop bundles do change occasionally, so the newer
|
||||
bundles may need to be added to this area from time to time.
|
||||
</p>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<!-- ------------------------------------------------------ -->
|
||||
<hr>
|
||||
<h2><a name="building">Build Information</a></h2>
|
||||
<blockquote>
|
||||
Building the OpenJDK
|
||||
is done with a <tt><i>gmake</i></tt>
|
||||
command line and various
|
||||
environment or make variable settings that direct the make rules
|
||||
is done with a <a href="#gmake">GNU <tt>make</tt></a> command line
|
||||
and various
|
||||
environment or make variable settings that direct the makefile rules
|
||||
to where various components have been installed.
|
||||
Where possible the makefiles will attempt to located the various
|
||||
components in the default locations or any component specific
|
||||
@ -578,7 +656,7 @@
|
||||
<pre><tt>
|
||||
bash
|
||||
. jdk/make/jdk_generic_profile.sh
|
||||
<i>gmake</i> sanity && <i>gmake</i>
|
||||
<a href="#gmake"><tt>make</tt></a> sanity && <a href="#gmake"><tt>make</tt></a>
|
||||
</tt></pre>
|
||||
</blockquote>
|
||||
<p>
|
||||
@ -599,25 +677,31 @@
|
||||
A few notes about using GNU make:
|
||||
<ul>
|
||||
<li>
|
||||
In general, you need GNU make version 3.81 or newer.
|
||||
You need GNU make version 3.81 or newer.
|
||||
</li>
|
||||
<li>
|
||||
Place the location of the GNU make binary in the <tt>PATH</tt>.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Linux:</strong>
|
||||
The <tt>/usr/bin/make</tt> command should work fine for you.
|
||||
The <tt>/usr/bin/make</tt> should be 3.81 or newer
|
||||
and should work fine for you.
|
||||
If this version is not 3.81 or newer,
|
||||
see the <a href="#buildgmake">"Building GNU make"</a> section.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Solaris:</strong>
|
||||
Do NOT use <tt>/usr/bin/make</tt> on Solaris.
|
||||
If your Solaris system has the software
|
||||
from the Solaris Companion CD installed,
|
||||
you should use <tt>gmake</tt>
|
||||
you should try and use <tt>gmake</tt>
|
||||
which will be located in either the <tt>/opt/sfw/bin</tt> or
|
||||
<tt>/usr/sfw/bin</tt> directory.
|
||||
In more recent versions of Solaris GNU make can be found
|
||||
at <tt>/usr/bin/gmake</tt>.
|
||||
In more recent versions of Solaris GNU make might be found
|
||||
at <tt>/usr/bin/gmake</tt>.<br>
|
||||
<b>NOTE:</b> It is very likely that this <tt>gmake</tt>
|
||||
could be 3.80, you need 3.81, in which case,
|
||||
see the <a href="#buildgmake">"Building GNU make"</a> section.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Windows:</strong>
|
||||
@ -627,30 +711,25 @@
|
||||
as a <tt>make.exe</tt> built for something like
|
||||
<a href="http://www.mkssoftware.com/">MKS</a>).
|
||||
<br>
|
||||
<b>WARNING:</b> Watch out for make version 3.81, it may
|
||||
<b>WARNING:</b> Watch out on some make 3.81 versions, it may
|
||||
not work due to a lack of support for MS-DOS drive letter paths
|
||||
like <tt>C:/</tt> or <tt>C:\</tt>.
|
||||
Use a 3.80 version, or find a newer
|
||||
version that has this problem fixed.
|
||||
The older 3.80 version of make.exe can be downloaded with this
|
||||
<a href="http://cygwin.paracoda.com/release/make/make-3.80-1.tar.bz2" target="_blank">
|
||||
link</a>.
|
||||
Use of this older 3.80 make.exe may require that you install the
|
||||
libintl2.dll library or libintl2 cygwin package which is
|
||||
no longer installed by default by the cygwin installer.
|
||||
<br>
|
||||
Also see the
|
||||
You may be able to use the information at the
|
||||
<a href="http://developer.mozilla.org/en/docs/Windows_build_prerequisites_using_cygwin#make" target="_blank">
|
||||
mozilla developer center</a>
|
||||
on this topic.
|
||||
<br>
|
||||
It's hoped that when make 3.82 starts shipping in a future cygwin
|
||||
release that this MS-DOS path issue will be fixed.
|
||||
In addition to the above 3.80 make.exe you can download
|
||||
this
|
||||
<br>
|
||||
It may be possible to download the version at
|
||||
<a href="http://www.cmake.org/files/cygwin/make.exe">
|
||||
www.cmake.org make.exe</a> which will not have a libintl2.dll
|
||||
dependency.
|
||||
www.cmake.org make.exe</a>.
|
||||
<br>
|
||||
It might be necessary for you to build your own GNU make 3.81,
|
||||
see the <a href="#buildgmake">"Building GNU make"</a> section
|
||||
in that case.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
@ -662,6 +741,34 @@
|
||||
The latest source to GNU make is available at
|
||||
<a href="http://ftp.gnu.org/pub/gnu/make/" target="_blank">
|
||||
ftp.gnu.org/pub/gnu/make/</a>.
|
||||
</p>
|
||||
<!-- ------------------------------------------------------ -->
|
||||
<h4><a name="buildgmake">Building GNU make</a></h4>
|
||||
<blockquote>
|
||||
First step is to get the GNU make 3.81 source from
|
||||
<a href="http://ftp.gnu.org/pub/gnu/make/" target="_blank">
|
||||
ftp.gnu.org/pub/gnu/make/</a>.
|
||||
Building is a little different depending on the OS and unix toolset
|
||||
on Windows:
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Linux:</strong>
|
||||
<tt>./configure && make</tt>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Solaris:</strong>
|
||||
<tt>./configure && gmake CC=gcc</tt>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Windows for CYGWIN:</strong>
|
||||
<tt>./configure && make</tt>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Windows for MKS: (CYGWIN is recommended)</strong>
|
||||
<tt>./configure && make -f Makefile.win32</tt>
|
||||
</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<!-- ------------------------------------------------------ -->
|
||||
<hr>
|
||||
@ -713,7 +820,7 @@
|
||||
</li>
|
||||
<li>
|
||||
Install
|
||||
<a href="#ant">Ant</a>,
|
||||
<a href="#ant">Ant 1.7.1 or newer</a>,
|
||||
make sure it is in your PATH.
|
||||
</li>
|
||||
</ol>
|
||||
@ -776,7 +883,7 @@
|
||||
</li>
|
||||
<li>
|
||||
Install
|
||||
<a href="#ant">Ant</a>,
|
||||
<a href="#ant">Ant 1.7.1 or newer</a>,
|
||||
make sure it is in your PATH.
|
||||
</li>
|
||||
</ol>
|
||||
@ -862,7 +969,7 @@
|
||||
</li>
|
||||
<li>
|
||||
Install
|
||||
<a href="#ant">Ant</a>,
|
||||
<a href="#ant">Ant 1.7.1 or newer</a>,
|
||||
make sure it is in your PATH and set
|
||||
<tt><a href="#ANT_HOME">ANT_HOME</a></tt>.
|
||||
</li>
|
||||
@ -923,14 +1030,20 @@
|
||||
<blockquote>
|
||||
All OpenJDK builds require access to least Ant 1.7.1.
|
||||
The Ant tool is available from the
|
||||
<a href="http://ant.apache.org" target="_blank">
|
||||
Ant download site</a>.
|
||||
<a href="http://archive.apache.org/dist/ant/binaries/apache-ant-1.7.1-bin.zip" target="_blank">
|
||||
Ant 1.7.1 archive download site</a>.
|
||||
You should always make sure <tt>ant</tt> is in your PATH, and
|
||||
on Windows you may also need to set
|
||||
<tt><a href="#ANT_HOME">ANT_HOME</a></tt>
|
||||
to point to the location of
|
||||
the Ant installation, this is the directory pathname
|
||||
that contains a <tt>bin and lib</tt>.
|
||||
<br>
|
||||
<b>WARNING:</b> Ant versions used from IDE tools like NetBeans
|
||||
or installed via system packages may not operate the same
|
||||
as the one obtained from the Ant download bundles.
|
||||
These system and IDE installers sometimes choose to change
|
||||
the ant installation enough to cause differences.
|
||||
</blockquote>
|
||||
<!-- ------------------------------------------------------ -->
|
||||
<h4><a name="cacerts">Certificate Authority File (cacert)</a></h4>
|
||||
@ -962,7 +1075,7 @@
|
||||
<blockquote>
|
||||
<strong><a name="gcc">Linux gcc/binutils</a></strong>
|
||||
<blockquote>
|
||||
The GNU gcc compiler version should be 4 or newer.
|
||||
The GNU gcc compiler version should be 4.3 or newer.
|
||||
The compiler used should be the default compiler installed
|
||||
in <tt>/usr/bin</tt>.
|
||||
</blockquote>
|
||||
@ -1047,21 +1160,16 @@
|
||||
<strong><a name="msvc32">Windows i586: Microsoft Visual Studio 2010 Compilers</a></strong>
|
||||
<blockquote>
|
||||
<p>
|
||||
<b>BEGIN WARNING</b>: At this time (Spring/Summer 2010) JDK 7 is starting a transition to
|
||||
use the newest VS2010 Microsoft compilers. These build instructions are updated
|
||||
to show where we are going. We have a QA process to go through before
|
||||
official builds actually use VS2010. So for now, official builds are
|
||||
still using VS2003. No other compilers are known to build the entire JDK,
|
||||
<b>BEGIN WARNING</b>: JDK 7 has transitioned to
|
||||
use the newest VS2010 Microsoft compilers.
|
||||
No other compilers are known to build the entire JDK,
|
||||
including non-open portions.
|
||||
So for now you should be able to build with either VS2003 or VS2010.
|
||||
We do not guarantee that VS2008 will work, although there is sufficient
|
||||
makefile support to make at least basic JDK builds plausible.
|
||||
Visual Studio 2010 Express compilers are now able to build all the
|
||||
open source repositories, but this is 32 bit only. To build 64 bit
|
||||
Windows binaries use the the 7.1 Windows SDK.<b>END WARNING.</b>
|
||||
Windows binaries use the the 7.1 Windows SDK.
|
||||
<b>END WARNING.</b>
|
||||
<p>
|
||||
The 32-bit OpenJDK Windows build
|
||||
requires
|
||||
The 32-bit OpenJDK Windows build requires
|
||||
Microsoft Visual Studio C++ 2010 (VS2010) Professional
|
||||
Edition or Express compiler.
|
||||
The compiler and other tools are expected to reside
|
||||
@ -1088,11 +1196,10 @@
|
||||
</blockquote>
|
||||
<strong><a name="msvc64">Windows x64: Microsoft Visual Studio 2010 Professional Compiler</a></strong>
|
||||
<blockquote>
|
||||
For <b>X64</b>, builds, when using the VS2010 Professional
|
||||
compiler, the 64 bit build set up is much the same as 32 bit
|
||||
For <b>X64</b>, the set up is much the same as 32 bit
|
||||
except that you run <tt>amd64\VCVARS64.BAT</tt>
|
||||
to set the compiler environment variables.
|
||||
Previously 64 bit builds had used the 64 bit compiler in
|
||||
Previously 64 bit builds had to use the 64 bit compiler in
|
||||
an unbundled Windows SDK but this is no longer necessary if
|
||||
you have VS2010 Professional.
|
||||
</blockquote>
|
||||
@ -1614,6 +1721,13 @@
|
||||
and on Windows with CYGWIN
|
||||
<tt>/usr/bin</tt>.
|
||||
</dd>
|
||||
<dt><tt><a name="ALT_DROPS_DIR">ALT_DROPS_DIR</a></tt> </dt>
|
||||
<dd>
|
||||
The location of any source drop bundles
|
||||
(see <a href="#drops">Managing the Source Drops</a>).
|
||||
The default will be
|
||||
<tt>$(ALT_JDK_DEVTOOLS_PATH)/share/jdk7-drops</tt>.
|
||||
</dd>
|
||||
<dt><a name="ALT_UNIXCCS_PATH"><tt>ALT_UNIXCCS_PATH</tt></a></dt>
|
||||
<dd>
|
||||
<strong>Solaris only:</strong>
|
||||
@ -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>
|
||||
|
||||
@ -108,3 +108,4 @@ d7532bcd3742f1576dd07ff9fbb535c9c9a276e9 jdk7-b126
|
||||
9d6dd2cdfcb92612dbd836ecded87770d52b49db jdk7-b131
|
||||
1b1e75e8f476e5c07f0d2b035993895e2603e1f0 jdk7-b132
|
||||
671fe2e623ffefb4b7c312be919fc71eb48c1df1 jdk7-b133
|
||||
918003855fa0dba5acf4bf1fe36526d2fc4c1ba8 jdk7-b134
|
||||
|
||||
@ -154,3 +154,5 @@ e9aa2ca89ad6c53420623d579765f9706ec523d7 hs21-b02
|
||||
0e531ab5ba04967a0e9aa6aef65e6eb3a0dcf632 jdk7-b132
|
||||
a8d643a4db47c7b58e0bcb49c77b5c3610de86a8 hs21-b03
|
||||
1b3a350709e4325d759bb453ff3fb6a463270488 jdk7-b133
|
||||
447e6faab4a8755d4860c2366630729dbaec111c jdk7-b134
|
||||
3c76374706ea8a77e15aec8310e831e5734f8775 hs21-b04
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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!
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 */);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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; }
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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");
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
@ -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.
|
||||
};
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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()) {
|
||||
|
||||
@ -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,
|
||||
|
||||
313
hotspot/src/share/vm/oops/instanceMirrorKlass.cpp
Normal file
313
hotspot/src/share/vm/oops/instanceMirrorKlass.cpp
Normal 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;
|
||||
}
|
||||
110
hotspot/src/share/vm/oops/instanceMirrorKlass.hpp
Normal file
110
hotspot/src/share/vm/oops/instanceMirrorKlass.hpp
Normal 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
|
||||
@ -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
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user