mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 19:44:41 +02:00
Merge
This commit is contained in:
commit
88d2bc6d8d
1393 changed files with 45972 additions and 38110 deletions
3
.hgtags
3
.hgtags
|
@ -45,3 +45,6 @@ eb24af1404aec8aa140c4cd4d13d2839b150dd41 jdk7-b67
|
||||||
bca2225b66d78c4bf4d9801f54cac7715a598650 jdk7-b68
|
bca2225b66d78c4bf4d9801f54cac7715a598650 jdk7-b68
|
||||||
1b662b1ed14eb4ae31d5138a36c433b13d941dc5 jdk7-b69
|
1b662b1ed14eb4ae31d5138a36c433b13d941dc5 jdk7-b69
|
||||||
207f694795c448c17753eff1a2f50363106960c2 jdk7-b70
|
207f694795c448c17753eff1a2f50363106960c2 jdk7-b70
|
||||||
|
c5d39b6be65cba0effb5f466ea48fe43764d0e0c jdk7-b71
|
||||||
|
df4bcd06e1d0ab306efa5a44f24a409dc0c0c742 jdk7-b72
|
||||||
|
ce74bd35ce948d629a356e168797f44b593b1578 jdk7-b73
|
||||||
|
|
|
@ -45,3 +45,6 @@ c4523c6f82048f420bf0d57c4cd47976753b7d2c jdk7-b67
|
||||||
e1b972ff53cd58f825791f8ed9b2deffd16e768c jdk7-b68
|
e1b972ff53cd58f825791f8ed9b2deffd16e768c jdk7-b68
|
||||||
82e6c820c51ac27882b77755d42efefdbf1dcda0 jdk7-b69
|
82e6c820c51ac27882b77755d42efefdbf1dcda0 jdk7-b69
|
||||||
175cb3fe615998d1004c6d3fd96e6d2e86b6772d jdk7-b70
|
175cb3fe615998d1004c6d3fd96e6d2e86b6772d jdk7-b70
|
||||||
|
4c36e9853dda27bdac5ef4839a610509fbe31d34 jdk7-b71
|
||||||
|
0d7e03b426df27c21dcc44ffb9178eacd1b04f10 jdk7-b72
|
||||||
|
3ac6dcf7823205546fbbc3d4ea59f37358d0b0d4 jdk7-b73
|
||||||
|
|
|
@ -38,12 +38,17 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#introduction">Introduction</a></li>
|
<li><a href="#introduction">Introduction</a></li>
|
||||||
<li><a href="#MBE">Minimum Build Environments</a></li>
|
<li><a href="#MBE">Minimum Build Environments</a></li>
|
||||||
<li><a href="#SDBE">Specific Developer Build Environments</a></li>
|
<li><a href="#SDBE">Specific Developer Build Environments</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#fedora">Fedora Linux</a> </li>
|
<li><a href="#fedora">Fedora Linux</a> </li>
|
||||||
<li><a href="#centos">CentOS Linux</a> </li>
|
<li><a href="#centos">CentOS Linux</a> </li>
|
||||||
|
<li><a href="#debian">Debian GNU/Linux</a></li>
|
||||||
<li><a href="#ubuntu">Ubuntu Linux</a> </li>
|
<li><a href="#ubuntu">Ubuntu Linux</a> </li>
|
||||||
|
<li><a href="#opensuse">OpenSUSE</a></li>
|
||||||
|
<li><a href="#mandriva">Mandriva</a></li>
|
||||||
|
<li><a href="#opensolaris">OpenSolaris</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</li>
|
||||||
<li><a href="#directories">Source Directory Structure</a> </li>
|
<li><a href="#directories">Source Directory Structure</a> </li>
|
||||||
<li><a href="#building">Build Information</a>
|
<li><a href="#building">Build Information</a>
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -68,7 +73,6 @@
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#zip">Zip and Unzip</a> </li>
|
<li><a href="#zip">Zip and Unzip</a> </li>
|
||||||
<li><a href="#freetype">FreeType2 Fonts</a> </li>
|
<li><a href="#freetype">FreeType2 Fonts</a> </li>
|
||||||
<li><a href="#jibx">JIBX Libraries</a> </li>
|
|
||||||
<li>Linux and Solaris:
|
<li>Linux and Solaris:
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#cups">CUPS Include files</a> </li>
|
<li><a href="#cups">CUPS Include files</a> </li>
|
||||||
|
@ -210,24 +214,59 @@
|
||||||
we will try to provide what information we have available to us.
|
we will try to provide what information we have available to us.
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<!-- ------------------------------------------------------ -->
|
<!-- ------------------------------------------------------ -->
|
||||||
<h3><a name="fedora">Fedora 9</a></h3>
|
<h3><a name="fedora">Fedora</a></h3>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
After installing
|
<h4>Fedora 9</h4>
|
||||||
<a href="http://www.fedoraproject.org/">Fedora 9</a>
|
|
||||||
you need to make sure you have
|
|
||||||
the "Software Development" bundle installed, plus the
|
|
||||||
following packages:
|
|
||||||
<blockquote>
|
|
||||||
<ul>
|
|
||||||
<li>cups devel: Cups Development Package</li>
|
|
||||||
<li>freetype 2.3+ devel: Freetype 2.3 Development Package</li>
|
|
||||||
<li>hg: Mercurial, if you need to clone or manage source repositories</li>
|
|
||||||
<li>ksh: May be needed when using <tt>webrev</tt></li>
|
|
||||||
</ul>
|
|
||||||
</blockquote>
|
|
||||||
<p>
|
<p>
|
||||||
Always a good idea to do a complete Software Update/Refresh
|
<blockquote>
|
||||||
after you get all the packages installed.
|
After installing <a href="http://fedoraproject.org">Fedora</a> 9
|
||||||
|
you need to install several build dependencies. The simplest
|
||||||
|
way to do it is to execute the following commands as user
|
||||||
|
<tt>root</tt>:
|
||||||
|
<p/>
|
||||||
|
<code>yum-builddep java-openjdk</code>
|
||||||
|
<p/>
|
||||||
|
<code>yum install gcc gcc-c++</code>
|
||||||
|
<p/>
|
||||||
|
In addition, it's necessary to set a few environment variables for the build:
|
||||||
|
|
||||||
|
<p/>
|
||||||
|
<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-openjdk</code>
|
||||||
|
</blockquote>
|
||||||
|
<h4>Fedora 10</h4>
|
||||||
|
<p>
|
||||||
|
<blockquote>
|
||||||
|
After installing <a href="http://fedoraproject.org">Fedora</a> 10
|
||||||
|
you need to install several build dependencies. The simplest
|
||||||
|
way to do it is to execute the following commands as user
|
||||||
|
<tt>root</tt>:
|
||||||
|
<p/>
|
||||||
|
<code>yum-builddep java-1.6.0-openjdk</code>
|
||||||
|
<p/>
|
||||||
|
<code>yum install gcc gcc-c++</code>
|
||||||
|
<p/>
|
||||||
|
In addition, it's necessary to set a few environment variables for the build:
|
||||||
|
|
||||||
|
<p/>
|
||||||
|
<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-openjdk</code>
|
||||||
|
</blockquote>
|
||||||
|
<h4>Fedora 11</h4>
|
||||||
|
<p>
|
||||||
|
<blockquote>
|
||||||
|
After installing <a href="http://fedoraproject.org">Fedora</a> 11
|
||||||
|
you need to install several build dependencies. The simplest
|
||||||
|
way to do it is to execute the following commands as user
|
||||||
|
<tt>root</tt>:
|
||||||
|
<p/>
|
||||||
|
<code>yum-builddep java-1.6.0-openjdk</code>
|
||||||
|
<p/>
|
||||||
|
<code>yum install gcc gcc-c++</code>
|
||||||
|
<p/>
|
||||||
|
In addition, it's necessary to set a few environment variables for the build:
|
||||||
|
|
||||||
|
<p/>
|
||||||
|
<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-openjdk</code>
|
||||||
|
</blockquote>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<!-- ------------------------------------------------------ -->
|
<!-- ------------------------------------------------------ -->
|
||||||
<h3><a name="centos">CentOS 5.2</a></h3>
|
<h3><a name="centos">CentOS 5.2</a></h3>
|
||||||
|
@ -270,142 +309,143 @@
|
||||||
it's needed.
|
it's needed.
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<!-- ------------------------------------------------------ -->
|
<!-- ------------------------------------------------------ -->
|
||||||
|
<h3><a name="debian">Debian</a></h3>
|
||||||
|
<blockquote>
|
||||||
|
<h4>Debian 5.0 (Lenny)</h4>
|
||||||
|
<p>
|
||||||
|
<blockquote>
|
||||||
|
After installing <a href="http://debian.org">Debian</a> 5
|
||||||
|
you need to install several build dependencies.
|
||||||
|
The simplest way to install the build dependencies is to
|
||||||
|
execute the following commands as user <tt>root</tt>:
|
||||||
|
<p/>
|
||||||
|
<code>aptitude build-dep openjdk-6</code>
|
||||||
|
<p/>
|
||||||
|
<code>aptitude install openjdk-6-jdk libmotif-dev</code>
|
||||||
|
<p/>
|
||||||
|
In addition, it's necessary to set a few environment variables for the build:
|
||||||
|
<p/>
|
||||||
|
<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-6-openjdk</code>
|
||||||
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
|
<!-- ====================================================== -->
|
||||||
<h3><a name="ubuntu">Ubuntu</a></h3>
|
<h3><a name="ubuntu">Ubuntu</a></h3>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
In addition to needing the Bootstrap JDK and the Binary Plugs,
|
<h4>Ubuntu 8.04</h4>
|
||||||
when building on Ubuntu you will need to
|
|
||||||
make sure certain packages are installed.
|
|
||||||
In particular, certain X11 packages, make, m4, gawk, gcc 4,
|
|
||||||
binutils, cups, freetype
|
|
||||||
and alsa.
|
|
||||||
<!-- ------------------------------------------------------ -->
|
|
||||||
<h4>Ubuntu 6.06</h4>
|
|
||||||
<p>
|
<p>
|
||||||
The following list of packages for Ubuntu 6.06 is a working set that
|
|
||||||
does appear to work.
|
|
||||||
<p>
|
|
||||||
<b>Note that it's quite possible that some of these
|
|
||||||
packages are not required, so anyone discovering that some of the
|
|
||||||
packages listed below are NOT required,
|
|
||||||
please let the
|
|
||||||
OpenJDK
|
|
||||||
team know.</b>
|
|
||||||
<p>
|
|
||||||
All the packages below can be installed with the
|
|
||||||
Synaptic Package manager provided with the base Ubuntu 6.06 release.
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<ul>
|
After installing <a href="http://ubuntu.org">Ubuntu</a> 8.04
|
||||||
<li>binutils (2.16.1cvs20060117-1ubuntu2.1)</li>
|
you need to install several build dependencies.
|
||||||
<li>cpp (4:4.0.3-1)</li>
|
<p/>
|
||||||
<li>cpp-4.0 (4.0.3-1ubuntu5)</li>
|
First, you need to enable the universe repository in the
|
||||||
<li>libfreetype6-dev</li>
|
Software Sources application and reload the repository
|
||||||
<li>g++ (4:4.0.3-1)</li>
|
information. The Software Sources application is available
|
||||||
<li>g++-4.0 (4.0.3-1ubuntu5)</li>
|
under the System/Administration menu.
|
||||||
<li>gawk (1:3.1.5-2build1)</li>
|
<p/>
|
||||||
<li>gcc (4:4.0.3-1)</li>
|
The simplest way to install the build dependencies is to
|
||||||
<li>gcc-4.0 (4.0.3-1ubuntu5)</li>
|
execute the following commands:
|
||||||
<li>libasound2-dev (1.0.10-2ubuntu4)</li>
|
<p/>
|
||||||
<li>libc6 (2.3.6-0ubuntu20) to 2.3.6-0ubuntu20.4</li>
|
<code>sudo aptitude build-dep openjdk-6</code>
|
||||||
<li>libc6-dev (2.3.6-0ubuntu20.4)</li>
|
<p/>
|
||||||
<li>libc6-i686 (2.3.6-0ubuntu20) to 2.3.6-0ubuntu20.4</li>
|
<code>sudo aptitude install openjdk-6-jdk</code>
|
||||||
<li>libcupsys2-dev (1.2.2-0ubuntu0.6.06)</li>
|
<p/>
|
||||||
<li>libgcrypt11-dev (1.2.2-1)</li>
|
In addition, it's necessary to set a few environment variables for the build:
|
||||||
<li>libgnutls-dev (1.2.9-2ubuntu1.1)</li>
|
<p/>
|
||||||
<li>libgnutls12 (1.2.9-2ubuntu1) to 1.2.9-2ubuntu1.1</li>
|
<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-6-openjdk</code>
|
||||||
<li>libgpg-error-dev (1.1-4)</li>
|
|
||||||
<li>libice-dev (2:1.0.0-0ubuntu2)</li>
|
|
||||||
<li>liblockfile1 (1.06.1)</li>
|
|
||||||
<li>libopencdk8-dev (0.5.7-2)</li>
|
|
||||||
<li>libpopt-dev (1.7-5)</li>
|
|
||||||
<li>libsm-dev (2:1.0.0-0ubuntu2)</li>
|
|
||||||
<li>libstdc++6-4.0-dev (4.0.3-1ubuntu5)</li>
|
|
||||||
<li>libtasn1-2-dev (0.2.17-1ubuntu1)</li>
|
|
||||||
<li>libx11-dev (2:1.0.0-0ubuntu9)</li>
|
|
||||||
<li>libxau-dev (1:1.0.0-0ubuntu4)</li>
|
|
||||||
<li>libxaw-headers (2:1.0.1-0ubuntu3)</li>
|
|
||||||
<li>libxaw7-dev (2:1.0.1-0ubuntu3)</li>
|
|
||||||
<li>libxdmcp-dev (1:1.0.0-0ubuntu2)</li>
|
|
||||||
<li>libxext-dev (2:1.0.0-0ubuntu4)</li>
|
|
||||||
<li>libxi-dev (2:1.0.0-0ubuntu3) </li>
|
|
||||||
<li>libxmu-dev (2:1.0.0-0ubuntu3)</li>
|
|
||||||
<li>libxmu-headers (2:1.0.0-0ubuntu3)</li>
|
|
||||||
<li>libxmuu-dev (2:1.0.0-0ubuntu3)</li>
|
|
||||||
<li>libxp-dev (6.8.2-11ubuntu2)</li>
|
|
||||||
<li>libxpm-dev (1:3.5.4.2-0ubuntu3)</li>
|
|
||||||
<li>libxrandr-dev (1:1.1.0.2-0ubuntu4)</li>
|
|
||||||
<li>libxt-dev (1:1.0.0-0ubuntu3)</li>
|
|
||||||
<li>libxtrap-dev (2:1.0.0-0ubuntu2)</li>
|
|
||||||
<li>libxtst-dev (2:1.0.1-0ubuntu2)</li>
|
|
||||||
<li>libxv-dev (2:1.0.1-0ubuntu3)</li>
|
|
||||||
<li>linux-kernel-headers (2.6.11.2-0ubuntu18)</li>
|
|
||||||
<li>m4 (1.4.4-1)</li>
|
|
||||||
<li>make (3.80+3.81.b4-1)</li>
|
|
||||||
<li>ssl-cert (1.0.13)</li>
|
|
||||||
<li>x-dev (7.0.4-0ubuntu2)</li>
|
|
||||||
<li>x11proto-core-dev (7.0.4-0ubuntu2)</li>
|
|
||||||
<li>x11proto-input-dev (1.3.2-0ubuntu2)</li>
|
|
||||||
<li>x11proto-kb-dev (1.0.2-0ubuntu2)</li>
|
|
||||||
<li>x11proto-randr-dev (1.1.2-0ubuntu2)</li>
|
|
||||||
<li>x11proto-record-dev (1.13.2-0ubuntu2)</li>
|
|
||||||
<li>x11proto-trap-dev (3.4.3-0ubuntu2)</li>
|
|
||||||
<li>x11proto-video-dev (2.2.2-0ubuntu2)</li>
|
|
||||||
<li>x11proto-xext-dev (7.0.2-0ubuntu2)</li>
|
|
||||||
<li>xlibs-dev (7.0.0-0ubuntu45)</li>
|
|
||||||
<li>zlib1g-dev (1:1.2.3-6ubuntu4)</li>
|
|
||||||
</ul>
|
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<!-- ------------------------------------------------------ -->
|
<h4>Ubuntu 8.10</h4>
|
||||||
<h4>Ubuntu 7.04</h4>
|
|
||||||
<p>
|
<p>
|
||||||
Using the Synaptic Package Manager, download the following
|
|
||||||
packages (double indented packages are automatically aquired
|
|
||||||
due to package dependencies):
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<ul>
|
After installing <a href="http://ubuntu.org">Ubuntu</a> 8.10
|
||||||
<li>build-essential</li>
|
you need to install several build dependencies. The simplest
|
||||||
<ul>
|
way to do it is to execute the following commands:
|
||||||
<li>dpkg-dev</li>
|
<p/>
|
||||||
<li>g++</li>
|
<code>sudo aptitude build-dep openjdk-6</code>
|
||||||
<li>g++-4.1</li>
|
<p/>
|
||||||
<li>libc6-dev</li>
|
<code>sudo aptitude install openjdk-6-jdk</code>
|
||||||
<li>libstdc++6.4.1-dev</li>
|
<p/>
|
||||||
<li>linux-libc-dev</li>
|
In addition, it's necessary to set a few environment variables for the build:
|
||||||
</ul>
|
<p/>
|
||||||
<li>gawk</li>
|
<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-6-openjdk</code>
|
||||||
<li>m4</li>
|
</blockquote>
|
||||||
<li>libasound2-dev</li>
|
<h4>Ubuntu 9.04</h4>
|
||||||
<li>libcupsys2-dev</li>
|
<p>
|
||||||
<ul>
|
<blockquote>
|
||||||
<li>libgcrypt11-dev</li>
|
After installing <a href="http://ubuntu.org">Ubuntu</a> 9.04
|
||||||
<li>lgnutls-dev</li>
|
you need to install several build dependencies. The simplest
|
||||||
<li>libgpg-error-dev</li>
|
way to do it is to execute the following commands:
|
||||||
<li>liblzo-dev</li>
|
<p/>
|
||||||
<li>libopencdk8-dev</li>
|
<code>sudo aptitude build-dep openjdk-6</code>
|
||||||
<li>libpopt-dev</li>
|
<p/>
|
||||||
<li>libtasn1-3-dev</li>
|
<code>sudo aptitude install openjdk-6-jdk</code>
|
||||||
<li>zlib1g-dev</li>
|
<p/>
|
||||||
</ul>
|
In addition, it's necessary to set a few environment variables for the build:
|
||||||
<li>sun-java6-jdk</li>
|
<p/>
|
||||||
<ul>
|
<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-6-openjdk</code>
|
||||||
<li>java-common</li>
|
</blockquote>
|
||||||
<li>libltdl3</li>
|
</blockquote>
|
||||||
<li>odbcinst1debian1</li>
|
<!-- ====================================================== -->
|
||||||
<li>sun-java6-bin</li>
|
<h3><a name="opensuse">OpenSUSE</a></h3>
|
||||||
<li>sun-java6-jre</li>
|
<blockquote>
|
||||||
<li>unixodbc</li>
|
<h4>OpenSUSE 11.1</h4>
|
||||||
</ul>
|
<p>
|
||||||
<li>xlibs-dev</li>
|
<blockquote>
|
||||||
<ul>
|
After installing <a href="http://opensuse.org">OpenSUSE</a> 11.1
|
||||||
<li>(many)</li>
|
you need to install several build dependencies.
|
||||||
</ul>
|
The simplest way to install the build dependencies is to
|
||||||
<li>x11proto-print-dev</li>
|
execute the following commands:
|
||||||
<li>libxaw7-dev</li>
|
<p/>
|
||||||
<ul>
|
<code>sudo zypper source-install -d java-1_6_0-openjdk</code>
|
||||||
<li>libxaw-headers</li>
|
<p/>
|
||||||
</ul>
|
<code>sudo zypper install make</code>
|
||||||
<li>libxp-dev</li>
|
<p/>
|
||||||
<li>libfreetype6-dev</li>
|
In addition, it is necessary to set a few environment variables for the build:
|
||||||
</ul>
|
<p/>
|
||||||
|
<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-1.6.0-openjdk</code>
|
||||||
|
<p/>
|
||||||
|
Finally, you need to unset the <code>JAVA_HOME</code> environment variable:
|
||||||
|
<p/>
|
||||||
|
<code>export -n JAVA_HOME</code>
|
||||||
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
|
<!-- ====================================================== -->
|
||||||
|
<h3><a name="mandriva">Mandriva</a></h3>
|
||||||
|
<blockquote>
|
||||||
|
<h4>Mandriva Linux One 2009 Spring</h4>
|
||||||
|
<p>
|
||||||
|
<blockquote>
|
||||||
|
After installing <a href="http://mandriva.org">Mandriva</a> Linux One 2009 Spring
|
||||||
|
you need to install several build dependencies.
|
||||||
|
The simplest way to install the build dependencies is to
|
||||||
|
execute the following commands as user <tt>root</tt>:
|
||||||
|
<p/>
|
||||||
|
<code>urpmi java-1.6.0-openjdk-devel ant make gcc gcc-c++ freetype-devel zip unzip libcups2-devel libxrender1-devel libalsa2-devel libstc++-static-devel libxtst6-devel libxi-devel</code>
|
||||||
|
<p/>
|
||||||
|
In addition, it is necessary to set a few environment variables for the build:
|
||||||
|
<p/>
|
||||||
|
<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-1.6.0-openjdk</code>
|
||||||
|
</blockquote>
|
||||||
|
</blockquote>
|
||||||
|
<!-- ====================================================== -->
|
||||||
|
<h3><a name="opensolaris">OpenSolaris</a></h3>
|
||||||
|
<blockquote>
|
||||||
|
<h4>OpenSolaris 2009.06</h4>
|
||||||
|
<p>
|
||||||
|
<blockquote>
|
||||||
|
After installing <a href="http://opensolaris.org">OpenSolaris</a> 2009.06
|
||||||
|
you need to install several build dependencies.
|
||||||
|
The simplest way to install the build dependencies is to
|
||||||
|
execute the following commands:
|
||||||
|
<p/>
|
||||||
|
<code>pfexec pkg install SUNWgmake SUNWj6dev SUNWant sunstudioexpress SUNWcups SUNWzip SUNWunzip SUNWxwhl SUNWxorg-headers SUNWaudh SUNWfreetype2</code>
|
||||||
|
<p/>
|
||||||
|
In addition, it is necessary to set a few environment variables for the build:
|
||||||
|
<p/>
|
||||||
|
<code>export LANG=C ALT_COMPILER_PATH=/opt/SunStudioExpress/bin/ ALT_CUPS_HEADERS_PATH=/usr/include/</code>
|
||||||
|
<p/>
|
||||||
|
Finally, you need to make sure that the build process can find the Sun Studio compilers:
|
||||||
|
<p/>
|
||||||
|
<code>export PATH=$PATH:/opt/SunStudioExpress/bin/</code>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<!-- ------------------------------------------------------ -->
|
<!-- ------------------------------------------------------ -->
|
||||||
|
@ -596,11 +636,6 @@
|
||||||
Install or upgrade the <a href="#freetype">FreeType development
|
Install or upgrade the <a href="#freetype">FreeType development
|
||||||
package</a>.
|
package</a>.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
Install the
|
|
||||||
<a href="#jibx">JIBX Libraries</a>, set
|
|
||||||
<tt><a href="#ALT_JIBX_LIBS_PATH">ALT_JIBX_LIBS_PATH</a></tt>.
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
Install
|
Install
|
||||||
<a href="#ant">Ant</a>,
|
<a href="#ant">Ant</a>,
|
||||||
|
@ -669,11 +704,6 @@
|
||||||
<li>
|
<li>
|
||||||
Install the <a href="#xrender">XRender Include files</a>.
|
Install the <a href="#xrender">XRender Include files</a>.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
Install the
|
|
||||||
<a href="#jibx">JIBX Libraries</a>, set
|
|
||||||
<tt><a href="#ALT_JIBX_LIBS_PATH">ALT_JIBX_LIBS_PATH</a></tt>.
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
Install
|
Install
|
||||||
<a href="#ant">Ant</a>,
|
<a href="#ant">Ant</a>,
|
||||||
|
@ -769,11 +799,6 @@
|
||||||
Install
|
Install
|
||||||
<a href="#dxsdk">Microsoft DirectX SDK</a>.
|
<a href="#dxsdk">Microsoft DirectX SDK</a>.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
Install the
|
|
||||||
<a href="#jibx">JIBX Libraries</a>, set
|
|
||||||
<tt><a href="#ALT_JIBX_LIBS_PATH">ALT_JIBX_LIBS_PATH</a></tt>.
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
Install
|
Install
|
||||||
<a href="#ant">Ant</a>,
|
<a href="#ant">Ant</a>,
|
||||||
|
@ -903,27 +928,6 @@
|
||||||
fine for most JDK developers.
|
fine for most JDK developers.
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<!-- ------------------------------------------------------ -->
|
<!-- ------------------------------------------------------ -->
|
||||||
<h4><a name="jibx">JIBX</a></h4>
|
|
||||||
<blockquote>
|
|
||||||
JIBX libraries version 1.1.5 is required for building the OpenJDK.
|
|
||||||
Namely, the following JAR files from the JIBX distribution package
|
|
||||||
are required:
|
|
||||||
<ul>
|
|
||||||
<li>bcel.jar
|
|
||||||
<li>jibx-bind.jar
|
|
||||||
<li>jibx-run.jar
|
|
||||||
<li>xpp3.jar
|
|
||||||
</ul>
|
|
||||||
<p>
|
|
||||||
You can download the package from the
|
|
||||||
<a href="http://jibx.sourceforge.net" target="_blank">JIBX site</a>.
|
|
||||||
<p>
|
|
||||||
You will need to set the
|
|
||||||
<tt><a href="#ALT_JIBX_LIBS_PATH">ALT_JIBX_LIBS_PATH</a></tt>
|
|
||||||
environment variable to refer to place where the JAR files,
|
|
||||||
above, are located.
|
|
||||||
</blockquote>
|
|
||||||
<!-- ------------------------------------------------------ -->
|
|
||||||
<h4><a name="compilers">Compilers</a></h4>
|
<h4><a name="compilers">Compilers</a></h4>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<strong><a name="gcc">Linux gcc/binutils</a></strong>
|
<strong><a name="gcc">Linux gcc/binutils</a></strong>
|
||||||
|
@ -1496,12 +1500,6 @@
|
||||||
The default will refer to
|
The default will refer to
|
||||||
<tt>jdk/src/share/lib/security/cacerts</tt>.
|
<tt>jdk/src/share/lib/security/cacerts</tt>.
|
||||||
</dd>
|
</dd>
|
||||||
<dt><tt><a name="ALT_JIBX_LIBS_PATH">ALT_JIBX_LIBS_PATH</a></tt></dt>
|
|
||||||
<dd>
|
|
||||||
The location of the <a href="#jibx">JIBX libraries</a> file.
|
|
||||||
The default value is
|
|
||||||
<tt>$(ALT_SLASH_JAVA)/devtools/share/jibx/lib</tt>.
|
|
||||||
</dd>
|
|
||||||
<dt><a name="ALT_CUPS_HEADERS_PATH"><tt>ALT_CUPS_HEADERS_PATH</tt></a> </dt>
|
<dt><a name="ALT_CUPS_HEADERS_PATH"><tt>ALT_CUPS_HEADERS_PATH</tt></a> </dt>
|
||||||
<dd>
|
<dd>
|
||||||
The location of the CUPS header files.
|
The location of the CUPS header files.
|
||||||
|
|
|
@ -45,3 +45,6 @@ a12ea7c7b497b4ba7830550095ef633bd6f43971 jdk7-b67
|
||||||
5182bcc9c60cac429d1f7988676cec7320752be3 jdk7-b68
|
5182bcc9c60cac429d1f7988676cec7320752be3 jdk7-b68
|
||||||
8120d308ec4e805c5588b8d9372844d781c4112d jdk7-b69
|
8120d308ec4e805c5588b8d9372844d781c4112d jdk7-b69
|
||||||
175bd68779546078dbdb6dacd7f0aced79ed22b1 jdk7-b70
|
175bd68779546078dbdb6dacd7f0aced79ed22b1 jdk7-b70
|
||||||
|
3f1ef7f899ea2aec189c4fb67e5c8fa374437c50 jdk7-b71
|
||||||
|
c793a31209263fbb867c23c752599d85c21abb73 jdk7-b72
|
||||||
|
b751c528c55560cf2adeaeef24b39ca1f4d1cbf7 jdk7-b73
|
||||||
|
|
|
@ -141,12 +141,12 @@ $(CLASSES_JAR):
|
||||||
|
|
||||||
#----- src.zip
|
#----- src.zip
|
||||||
|
|
||||||
SRC_ZIP_FILES = $(shell $(FIND) $(SRC_CLASSES_DIR) \( -name SCCS -o -name \*-template \) -prune -o -type f -print )
|
SRC_ZIP_FILES = $(shell $(FIND) $(SRC_CLASSES_DIR) \( -name \*-template \) -prune -o -type f -print )
|
||||||
|
|
||||||
SRC_ZIP = $(LIB_DIR)/src.zip
|
SRC_ZIP = $(LIB_DIR)/src.zip
|
||||||
$(SRC_ZIP): $(SRC_ZIP_FILES)
|
$(SRC_ZIP): $(SRC_ZIP_FILES)
|
||||||
abs_src_zip=`cd $(@D) ; pwd`/$(@F) ; \
|
abs_src_zip=`cd $(@D) ; pwd`/$(@F) ; \
|
||||||
( cd $(SRC_CLASSES_DIR) ; $(FIND) . \( -name SCCS -o -name \*-template \) -prune -o -type f -print | $(ZIP) -q $$abs_src_zip -@ ) ; \
|
( cd $(SRC_CLASSES_DIR) ; $(FIND) . \( -name \*-template \) -prune -o -type f -print | $(ZIP) -q $$abs_src_zip -@ ) ; \
|
||||||
( cd $(GENSRC_DIR) ; $(FIND) . -type f -print | $(ZIP) -q $$abs_src_zip -@ ) ;
|
( cd $(GENSRC_DIR) ; $(FIND) . -type f -print | $(ZIP) -q $$abs_src_zip -@ ) ;
|
||||||
|
|
||||||
#----- bin.zip
|
#----- bin.zip
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved.
|
# Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,21 +25,28 @@
|
||||||
|
|
||||||
# Input: BUILDDIR PACKAGE PKGDIR PROGRAM BUILDTOOL_SOURCE_ROOT BUILDTOOL_MAIN
|
# Input: BUILDDIR PACKAGE PKGDIR PROGRAM BUILDTOOL_SOURCE_ROOT BUILDTOOL_MAIN
|
||||||
|
|
||||||
|
# All subdirectories under the package root for the tool (max depth 4)
|
||||||
|
_WC_DIRS = * */* */*/* */*/*/*
|
||||||
|
|
||||||
BUILDTOOL_MAIN_SOURCE_FILE = $(BUILDTOOL_SOURCE_ROOT)/$(BUILDTOOL_MAIN)
|
BUILDTOOL_MAIN_SOURCE_FILE = $(BUILDTOOL_SOURCE_ROOT)/$(BUILDTOOL_MAIN)
|
||||||
BUILDTOOL_MANIFEST_FILE = $(BUILDTOOLCLASSDIR)/$(PROGRAM)_manifest.mf
|
BUILDTOOL_MANIFEST_FILE = $(BUILDTOOLCLASSDIR)/$(PROGRAM)_manifest.mf
|
||||||
BUILDTOOL_JAR_FILE = $(BUILDTOOLJARDIR)/$(PROGRAM).jar
|
BUILDTOOL_JAR_FILE = $(BUILDTOOLJARDIR)/$(PROGRAM).jar
|
||||||
BUILDTOOL_ALL_FILES := $(shell $(CD) $(BUILDTOOL_SOURCE_ROOT) \
|
|
||||||
&& $(FIND) $(PKGDIR) $(SCM_DIRS_prune) -o -type f -print)
|
|
||||||
BUILTTOOL_MAINCLASS = $(subst /,.,$(BUILDTOOL_MAIN:%.java=%))
|
BUILTTOOL_MAINCLASS = $(subst /,.,$(BUILDTOOL_MAIN:%.java=%))
|
||||||
|
|
||||||
all build: $(BUILDTOOL_JAR_FILE) tool_info
|
# Wildcard patterns that find all the sources for this build tool
|
||||||
|
BUILDTOOL_WC_PATTERNS = $(BUILDTOOL_SOURCE_ROOT)/$(PKGDIR)/*.java \
|
||||||
|
$(patsubst %, $(BUILDTOOL_SOURCE_ROOT)/$(PKGDIR)/%/*.java, $(_WC_DIRS))
|
||||||
|
|
||||||
|
# Wildcard expansion that finds all the files
|
||||||
|
BUILDTOOL_SRC_FILES := $(wildcard $(BUILDTOOL_WC_PATTERNS))
|
||||||
|
|
||||||
|
all build: $(BUILDTOOL_JAR_FILE)
|
||||||
|
|
||||||
$(BUILDTOOL_MANIFEST_FILE): $(BUILDTOOL_MAIN_SOURCE_FILE)
|
$(BUILDTOOL_MANIFEST_FILE): $(BUILDTOOL_MAIN_SOURCE_FILE)
|
||||||
@$(prep-target)
|
@$(prep-target)
|
||||||
$(ECHO) "Main-Class: $(BUILTTOOL_MAINCLASS)" > $@
|
$(ECHO) "Main-Class: $(BUILTTOOL_MAINCLASS)" > $@
|
||||||
|
|
||||||
$(BUILDTOOL_JAR_FILE): $(BUILDTOOL_MANIFEST_FILE) \
|
$(BUILDTOOL_JAR_FILE): $(BUILDTOOL_MANIFEST_FILE) $(BUILDTOOL_SRC_FILES)
|
||||||
$(BUILDTOOL_ALL_FILES:%=$(BUILDTOOL_SOURCE_ROOT)/%)
|
|
||||||
@$(prep-target)
|
@$(prep-target)
|
||||||
@$(MKDIR) -p $(BUILDTOOLCLASSDIR)
|
@$(MKDIR) -p $(BUILDTOOLCLASSDIR)
|
||||||
$(BOOT_JAVAC_CMD) -d $(BUILDTOOLCLASSDIR) \
|
$(BOOT_JAVAC_CMD) -d $(BUILDTOOLCLASSDIR) \
|
||||||
|
@ -49,23 +56,8 @@ $(BUILDTOOL_JAR_FILE): $(BUILDTOOL_MANIFEST_FILE) \
|
||||||
$(JAR_JFLAGS) || $(RM) $@
|
$(JAR_JFLAGS) || $(RM) $@
|
||||||
@$(java-vm-cleanup)
|
@$(java-vm-cleanup)
|
||||||
|
|
||||||
# Printing out a build tool information line
|
|
||||||
define printBuildToolSetting
|
|
||||||
if [ "$2" != "" ] ; then $(PRINTF) "%-25s %s\n" "$1:" "$2"; fi
|
|
||||||
endef
|
|
||||||
|
|
||||||
# Print out the build tool information
|
|
||||||
tool_info:
|
|
||||||
@$(ECHO) "========================================================="
|
|
||||||
@$(call printBuildToolSetting,BUILDTOOL,$(PROGRAM))
|
|
||||||
@$(call printBuildToolSetting,PACKAGE,$(PACKAGE))
|
|
||||||
@$(call printBuildToolSetting,BUILDTOOL_SOURCE_ROOT,$(BUILDTOOL_SOURCE_ROOT))
|
|
||||||
@$(call printBuildToolSetting,BUILTTOOL_MAINCLASS,$(BUILTTOOL_MAINCLASS))
|
|
||||||
@$(call printBuildToolSetting,BUILDTOOL_JAR_FILE,$(BUILDTOOL_JAR_FILE))
|
|
||||||
@$(ECHO) "========================================================="
|
|
||||||
|
|
||||||
clean clobber::
|
clean clobber::
|
||||||
$(RM) -r $(BUILDTOOLCLASSDIR)/$(PKGDIR)
|
$(RM) -r $(BUILDTOOLCLASSDIR)/$(PKGDIR) \
|
||||||
$(RM) $(BUILDTOOL_MANIFEST_FILE)
|
$(BUILDTOOL_MANIFEST_FILE) \
|
||||||
$(RM) $(BUILDTOOL_JAR_FILE)
|
$(BUILDTOOL_JAR_FILE)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright 1998-1999 Sun Microsystems, Inc. All Rights Reserved.
|
# Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -56,11 +56,3 @@ ifndef USE_IMPLICITS
|
||||||
%: %.sh
|
%: %.sh
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#
|
|
||||||
# If you are using RCS, you must set the variable USE_RCS at the make
|
|
||||||
# command line. Otherwise we disable RCS.
|
|
||||||
#
|
|
||||||
ifndef USE_RCS
|
|
||||||
%:: %,v
|
|
||||||
%:: RCS/%,v
|
|
||||||
endif
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved.
|
# Copyright 1995-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -310,125 +310,32 @@ endef
|
||||||
SUBDIRS_MAKEFLAGS-clobber = INCREMENTAL_BUILD=false
|
SUBDIRS_MAKEFLAGS-clobber = INCREMENTAL_BUILD=false
|
||||||
SUBDIRS_MAKEFLAGS-clean = INCREMENTAL_BUILD=false
|
SUBDIRS_MAKEFLAGS-clean = INCREMENTAL_BUILD=false
|
||||||
|
|
||||||
# Current directory
|
|
||||||
CURRENT_DIRECTORY := $(shell $(PWD))
|
|
||||||
|
|
||||||
# If no timing wanted, we need to define these as empty
|
|
||||||
ifdef NO_TIMING
|
|
||||||
|
|
||||||
TIMING_ID:=NA
|
|
||||||
|
|
||||||
define TIMING_start
|
|
||||||
t=0:0:0:0
|
|
||||||
endef
|
|
||||||
|
|
||||||
define TIMING_end
|
|
||||||
time_used=0
|
|
||||||
endef
|
|
||||||
|
|
||||||
else # NO_TIMING
|
|
||||||
|
|
||||||
# Default timing id
|
|
||||||
TIMING_ID:=$(shell $(BASENAME) $(CURRENT_DIRECTORY))
|
|
||||||
|
|
||||||
# Timing start (must be used in same shell, e.g. same command line)
|
|
||||||
# Defines the shell variable $1 to have the start time.
|
|
||||||
define TIMING_start
|
|
||||||
$1=`$(DATE) +%j:%H:%M:%S`
|
|
||||||
endef
|
|
||||||
|
|
||||||
# Timing end (must be used in same shell, e.g. same command line)
|
|
||||||
# Expects shell variable $1 to have been defined as the start time.
|
|
||||||
# Expects shell variable $2 to have timing id string
|
|
||||||
# Sets total_seconds shell variable as the total seconds used.
|
|
||||||
# Sets time_used shell variable to contain format "%dh%dm%ds"
|
|
||||||
define TIMING_end
|
|
||||||
begTime="$${$1}"; \
|
|
||||||
timing_id="$${$2}"; \
|
|
||||||
endTime=`$(DATE) +%j:%H:%M:%S`; \
|
|
||||||
d1=`$(ECHO) $${begTime} | $(CUT) -d':' -f1 | $(SED) -e 's@^0*@@'`; \
|
|
||||||
if [ "$${d1}" = "" ] ; then d1=0; fi; \
|
|
||||||
h1=`$(ECHO) $${begTime} | $(CUT) -d':' -f2 | $(SED) -e 's@^0*@@'`; \
|
|
||||||
if [ "$${h1}" = "" ] ; then h1=0; fi; \
|
|
||||||
m1=`$(ECHO) $${begTime} | $(CUT) -d':' -f3 | $(SED) -e 's@^0*@@'`; \
|
|
||||||
if [ "$${m1}" = "" ] ; then m1=0; fi; \
|
|
||||||
s1=`$(ECHO) $${begTime} | $(CUT) -d':' -f4 | $(SED) -e 's@^0*@@'`; \
|
|
||||||
if [ "$${s1}" = "" ] ; then s1=0; fi; \
|
|
||||||
d2=`$(ECHO) $${endTime} | $(CUT) -d':' -f1 | $(SED) -e 's@^0*@@'`; \
|
|
||||||
if [ "$${d2}" = "" ] ; then d2=0; fi; \
|
|
||||||
h2=`$(ECHO) $${endTime} | $(CUT) -d':' -f2 | $(SED) -e 's@^0*@@'`; \
|
|
||||||
if [ "$${h2}" = "" ] ; then h2=0; fi; \
|
|
||||||
m2=`$(ECHO) $${endTime} | $(CUT) -d':' -f3 | $(SED) -e 's@^0*@@'`; \
|
|
||||||
if [ "$${m2}" = "" ] ; then m2=0; fi; \
|
|
||||||
s2=`$(ECHO) $${endTime} | $(CUT) -d':' -f4 | $(SED) -e 's@^0*@@'`; \
|
|
||||||
if [ "$${s2}" = "" ] ; then s2=0; fi; \
|
|
||||||
t1_secs=`$(EXPR) $${d1} '*' 60 '*' 60 '*' 24 '+' $${h1} '*' 60 '*' 60 \
|
|
||||||
'+' $${m1} '*' 60 '+' $${s1}`; \
|
|
||||||
t2_secs=`$(EXPR) $${d2} '*' 60 '*' 60 '*' 24 '+' $${h2} '*' 60 '*' 60 \
|
|
||||||
'+' $${m2} '*' 60 '+' $${s2}`; \
|
|
||||||
total_seconds=`$(EXPR) $${t2_secs} '-' $${t1_secs}`; \
|
|
||||||
if [ "$${total_seconds}" -lt 0 ] ; then total_seconds=0; fi; \
|
|
||||||
t_hour=`$(EXPR) $${total_seconds} '/' '(' 60 '*' 60 ')'`h; \
|
|
||||||
t_min=`$(EXPR) '(' $${total_seconds} '%' '(' 60 '*' 60 ')' ')' '/' 60`m; \
|
|
||||||
t_sec=`$(EXPR) $${total_seconds} '%' 60`s; \
|
|
||||||
time_used=$${t_sec}; \
|
|
||||||
if [ "$${t_hour}" != "0h" ] ; then \
|
|
||||||
time_used=$${t_hour}$${t_min}$${t_sec}; \
|
|
||||||
elif [ "$${t_min}" != "0m" ] ; then \
|
|
||||||
time_used=$${t_min}$${t_sec}; \
|
|
||||||
else \
|
|
||||||
time_used=$${t_sec}; \
|
|
||||||
fi; \
|
|
||||||
$(PRINTF) " Timing: %05d seconds or %s for %s\n" \
|
|
||||||
$${total_seconds} $${time_used} $${timing_id}
|
|
||||||
endef
|
|
||||||
|
|
||||||
endif # NO_TIMING
|
|
||||||
|
|
||||||
# Given a SUBDIRS list, cd into them and make them
|
# Given a SUBDIRS list, cd into them and make them
|
||||||
# SUBDIRS_MAKEFLAGS Make settings for a subdir make
|
# SUBDIRS_MAKEFLAGS Make settings for a subdir make
|
||||||
# SUBDIRS_MAKEFLAGS-$@ Make settings specific to this target
|
# SUBDIRS_MAKEFLAGS-$@ Make settings specific to this target
|
||||||
define SUBDIRS-loop
|
define SUBDIRS-loop
|
||||||
@$(ECHO) "Begin Processing SUBDIRS: $(SUBDIRS)"
|
|
||||||
@for i in DUMMY $(SUBDIRS) ; do \
|
@for i in DUMMY $(SUBDIRS) ; do \
|
||||||
if [ "$$i" != "DUMMY" ] ; then \
|
if [ "$$i" != "DUMMY" ] ; then \
|
||||||
$(ECHO) ">>>Recursively making "$$i" "$@" @ `$(DATE)` ..."; \
|
$(MAKE) -C $${i} $@ \
|
||||||
timing_id="$(TIMING_ID)-`$(BASENAME) $${i}`"; \
|
|
||||||
$(call TIMING_start,startTime); \
|
|
||||||
curDir=$(CURRENT_DIRECTORY); \
|
|
||||||
$(CD) $$i; $(MAKE) $@ TIMING_ID=$${timing_id} \
|
|
||||||
$(SUBDIRS_MAKEFLAGS) \
|
$(SUBDIRS_MAKEFLAGS) \
|
||||||
$(SUBDIRS_MAKEFLAGS-$@) \
|
$(SUBDIRS_MAKEFLAGS-$@) \
|
||||||
FULL_VERSION=$(FULL_VERSION) \
|
FULL_VERSION=$(FULL_VERSION) \
|
||||||
RELEASE=$(RELEASE) || exit 1; \
|
RELEASE=$(RELEASE) || exit 1; \
|
||||||
$(CD) $${curDir}; \
|
|
||||||
$(call TIMING_end,startTime,timing_id); \
|
|
||||||
$(ECHO) "<<<Finished Recursively making "$$i" "$@" @ `$(DATE)`." ; \
|
|
||||||
fi ; \
|
fi ; \
|
||||||
done
|
done
|
||||||
@$(ECHO) "Done Processing SUBDIRS: $(SUBDIRS)"
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
# Given a OTHERSUBDIRS list, cd into them and make them (extra loop define)
|
# Given a OTHERSUBDIRS list, cd into them and make them (extra loop define)
|
||||||
# OTHERSUBDIRS_MAKEFLAGS Make settings for a subdir make
|
# OTHERSUBDIRS_MAKEFLAGS Make settings for a subdir make
|
||||||
define OTHERSUBDIRS-loop
|
define OTHERSUBDIRS-loop
|
||||||
@$(ECHO) "Begin Processing OTHERSUBDIRS: $(OTHERSUBDIRS)"
|
|
||||||
@for i in DUMMY $(OTHERSUBDIRS) ; do \
|
@for i in DUMMY $(OTHERSUBDIRS) ; do \
|
||||||
if [ "$$i" != "DUMMY" ] ; then \
|
if [ "$$i" != "DUMMY" ] ; then \
|
||||||
$(ECHO) ">>>Recursively making "$$i" "$@" @ `$(DATE)` ..."; \
|
$(MAKE) -C $${i} $@ \
|
||||||
timing_id="$(TIMING_ID)-`$(BASENAME) $${i}`"; \
|
|
||||||
$(call TIMING_start,startTime); \
|
|
||||||
curDir=$(CURRENT_DIRECTORY); \
|
|
||||||
$(CD) $$i; $(MAKE) $@ TIMING_ID=$${timing_id} \
|
|
||||||
$(OTHERSUBDIRS_MAKEFLAGS) \
|
$(OTHERSUBDIRS_MAKEFLAGS) \
|
||||||
FULL_VERSION=$(FULL_VERSION) \
|
FULL_VERSION=$(FULL_VERSION) \
|
||||||
RELEASE=$(RELEASE) || exit 1; \
|
RELEASE=$(RELEASE) || exit 1; \
|
||||||
$(CD) $${curDir}; \
|
|
||||||
$(call TIMING_end,startTime,timing_id); \
|
|
||||||
$(ECHO) "<<<Finished Recursively making "$$i" "$@" @ `$(DATE)`." ; \
|
|
||||||
fi ; \
|
fi ; \
|
||||||
done
|
done
|
||||||
@$(ECHO) "Done Processing OTHERSUBDIRS: $(OTHERSUBDIRS)"
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -460,46 +367,23 @@ else
|
||||||
VERSION_DEFINES = -DRELEASE='"$(RELEASE)"'
|
VERSION_DEFINES = -DRELEASE='"$(RELEASE)"'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Note: As a rule, GNU Make rules should not appear in any of the
|
# Prevent the use of many default suffix rules we do not need
|
||||||
# Defs*.gmk files. These were added for Kestrel-Solaris and do address
|
.SUFFIXES:
|
||||||
# a TeamWare bug. They should be moved elsewhere for Merlin.
|
.SUFFIXES: .c .o .h .obj .cpp .hpp .java .class
|
||||||
#
|
|
||||||
# Override gnumake built-in rules which do sccs get operations badly.
|
|
||||||
# (They put the checked out code in the current directory, not in the
|
|
||||||
# directory of the original file.)
|
|
||||||
# Since this is a symptom of a teamware failure, complain and die on the spot.
|
|
||||||
|
|
||||||
# This message immediately goes to stdout and the build terminates.
|
|
||||||
define SCCS-trouble
|
|
||||||
$(error \
|
|
||||||
"ERROR: File $@ referenced while building in $(CURRENT_DIRECTORY) \
|
|
||||||
is out of date with respect to its SCCS file $<. \
|
|
||||||
This can happen from an unresolved Teamware conflict, a file movement, or \
|
|
||||||
a failure in which SCCS files are updated but the 'sccs get' was not done. \
|
|
||||||
You should double check for other out of date files in your workspace. \
|
|
||||||
Or run: cd $(TOPDIR) && $(MAKE) sccs_get")
|
|
||||||
endef
|
|
||||||
|
|
||||||
%:: s.%
|
|
||||||
@$(SCCS-trouble)
|
|
||||||
%:: SCCS/s.%
|
|
||||||
@$(SCCS-trouble)
|
|
||||||
@$(ECHO) " is out of date with respect to its SCCS file." >> $(WARNING_FILE)
|
|
||||||
@$(ECHO) " This file may be from an unresolved Teamware conflict." >> $(WARNING_FILE)
|
|
||||||
@$(ECHO) " This is also a symptom of a Teamware bringover/putback failure" >> $(WARNING_FILE)
|
|
||||||
@$(ECHO) " in which SCCS files are updated but not checked out." >> $(WARNING_FILE)
|
|
||||||
@$(ECHO) " Check for other out of date files in your workspace." >> $(WARNING_FILE)
|
|
||||||
@$(ECHO) "" >> $(WARNING_FILE)
|
|
||||||
@#exit 666
|
|
||||||
|
|
||||||
|
# Make sure we are all insane
|
||||||
ifdef INSANE
|
ifdef INSANE
|
||||||
export INSANE
|
export INSANE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef ALT_COPYRIGHT_YEAR
|
# Make sure we have the current year
|
||||||
COPYRIGHT_YEAR = $(ALT_COPYRIGHT_YEAR)
|
ifndef COPYRIGHT_YEAR
|
||||||
else
|
ifdef ALT_COPYRIGHT_YEAR
|
||||||
COPYRIGHT_YEAR = $(shell $(DATE) '+%Y')
|
COPYRIGHT_YEAR := $(ALT_COPYRIGHT_YEAR)
|
||||||
|
else
|
||||||
|
COPYRIGHT_YEAR := $(shell $(DATE) '+%Y')
|
||||||
|
endif
|
||||||
|
export COPYRIGHT_YEAR
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Install of imported file (JDK_IMPORT_PATH, or some other external location)
|
# Install of imported file (JDK_IMPORT_PATH, or some other external location)
|
||||||
|
|
|
@ -27,17 +27,6 @@
|
||||||
#
|
#
|
||||||
# Rules shared by all Java makefiles.
|
# Rules shared by all Java makefiles.
|
||||||
#
|
#
|
||||||
# Used to apply to source file $<, checks code conventions, issues warnings.
|
|
||||||
define check-conventions
|
|
||||||
if [ "$(CONVENTION_WATCH)" = "true" ] ; then \
|
|
||||||
if [ "`$(CAT) -n -v -t $< | $(EGREP) -v '\@\(\#\)' | $(EGREP) '\^[MLI]'`" != "" ] ; then \
|
|
||||||
$(ECHO) "WARNING: File contains tabs, ^M, or ^L characters: $<"; \
|
|
||||||
if [ "$(CONVENTION_DETAILS)" = "true" ] ; then \
|
|
||||||
$(CAT) -n -v -t $< | $(EGREP) -v '\@\(\#\)' | $(EGREP) '\^[MLI]' ; \
|
|
||||||
fi; \
|
|
||||||
fi; \
|
|
||||||
fi
|
|
||||||
endef
|
|
||||||
|
|
||||||
# Make sure the default rule is all
|
# Make sure the default rule is all
|
||||||
rules_default_rule: all
|
rules_default_rule: all
|
||||||
|
@ -162,7 +151,6 @@ JAVA_SOURCE_LIST=$(TEMPDIR)/.classes.list
|
||||||
# Add a java source to the list
|
# Add a java source to the list
|
||||||
define add-java-file
|
define add-java-file
|
||||||
$(ECHO) "$?" >> $(JAVA_SOURCE_LIST)
|
$(ECHO) "$?" >> $(JAVA_SOURCE_LIST)
|
||||||
$(check-conventions)
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
$(CLASSDESTDIR)/%.class: $(GENSRCDIR)/%.java
|
$(CLASSDESTDIR)/%.class: $(GENSRCDIR)/%.java
|
||||||
|
@ -197,11 +185,8 @@ JAVAC_PREFER_SOURCE = -Xprefer:source
|
||||||
|
|
||||||
.compile.classlist : $(JAVA_SOURCE_LIST)
|
.compile.classlist : $(JAVA_SOURCE_LIST)
|
||||||
@$(MKDIR) -p $(CLASSDESTDIR)
|
@$(MKDIR) -p $(CLASSDESTDIR)
|
||||||
@if [ `$(CAT) $(JAVA_SOURCE_LIST) | $(WC) -l` -ge 1 ] ; then \
|
if [ -s $(JAVA_SOURCE_LIST) ] ; then \
|
||||||
$(ECHO) "# Java sources to be compiled: (listed in file $(JAVA_SOURCE_LIST))"; \
|
|
||||||
$(CAT) $(JAVA_SOURCE_LIST); \
|
$(CAT) $(JAVA_SOURCE_LIST); \
|
||||||
$(ECHO) "# Running javac:"; \
|
|
||||||
$(ECHO) $(JAVAC_CMD) $(JAVAC_PREFER_SOURCE) -sourcepath "$(SOURCEPATH)" -d $(CLASSDESTDIR) @$(JAVA_SOURCE_LIST); \
|
|
||||||
$(JAVAC_CMD) $(JAVAC_PREFER_SOURCE) -sourcepath "$(SOURCEPATH)" -d $(CLASSDESTDIR) @$(JAVA_SOURCE_LIST); \
|
$(JAVAC_CMD) $(JAVAC_PREFER_SOURCE) -sourcepath "$(SOURCEPATH)" -d $(CLASSDESTDIR) @$(JAVA_SOURCE_LIST); \
|
||||||
fi
|
fi
|
||||||
@$(java-vm-cleanup)
|
@$(java-vm-cleanup)
|
||||||
|
@ -220,10 +205,7 @@ endif
|
||||||
packages.clean:
|
packages.clean:
|
||||||
ifeq ($(DONT_CLOBBER_CLASSES),false)
|
ifeq ($(DONT_CLOBBER_CLASSES),false)
|
||||||
ifdef AUTO_FILES_JAVA_DIRS
|
ifdef AUTO_FILES_JAVA_DIRS
|
||||||
@for sdir in $(AUTO_FILES_JAVA_DIRS); do \
|
$(RM) -r $(patsubst %, $(CLASSDESTDIR)/%, $(AUTO_FILES_JAVA_DIRS))
|
||||||
$(ECHO) "$(RM) -r $(CLASSDESTDIR)/$$sdir"; \
|
|
||||||
$(RM) -r $(CLASSDESTDIR)/$$sdir; \
|
|
||||||
done
|
|
||||||
else
|
else
|
||||||
$(RM) -r $(CLASSDESTDIR)/$(PKGDIR)
|
$(RM) -r $(CLASSDESTDIR)/$(PKGDIR)
|
||||||
endif
|
endif
|
||||||
|
@ -259,15 +241,13 @@ classheaders: classes $(CLASSHDR_DOTFILE)
|
||||||
|
|
||||||
$(CLASSHDR_DOTFILE): $(CLASSES_export)
|
$(CLASSHDR_DOTFILE): $(CLASSES_export)
|
||||||
$(prep-target)
|
$(prep-target)
|
||||||
@$(ECHO) "# Running javah:"
|
|
||||||
$(JAVAH_CMD) -d $(CLASSHDRDIR)/ \
|
$(JAVAH_CMD) -d $(CLASSHDRDIR)/ \
|
||||||
$(CLASSES.export) $(subst $$,\$$,$(EXPORTED_inner))
|
$(CLASSES.export) $(subst $$,\$$,$(EXPORTED_inner))
|
||||||
@$(java-vm-cleanup)
|
@$(java-vm-cleanup)
|
||||||
@$(TOUCH) $@
|
@$(TOUCH) $@
|
||||||
|
|
||||||
classheaders.clean:
|
classheaders.clean:
|
||||||
$(RM) $(CLASSHDR_DOTFILE)
|
$(RM) -r $(CLASSHDRDIR) $(CLASSHDR_DOTFILE)
|
||||||
$(RM) -r $(CLASSHDRDIR)
|
|
||||||
|
|
||||||
else # FILES_export
|
else # FILES_export
|
||||||
|
|
||||||
|
|
|
@ -48,11 +48,17 @@ ifeq ($(PLATFORM), windows)
|
||||||
NMAKE = MFLAGS= MAKEFLAGS= $(COMPILER_PATH)nmake -nologo
|
NMAKE = MFLAGS= MAKEFLAGS= $(COMPILER_PATH)nmake -nologo
|
||||||
|
|
||||||
# Compiler version and type (Always get word after "Version")
|
# Compiler version and type (Always get word after "Version")
|
||||||
|
ifndef CC_VER
|
||||||
CC_VER := $(shell $(CC) 2>&1 | $(HEAD) -n 1 | $(SED) 's/.*\(Version.*\)/\1/' | $(NAWK) '{print $$2}')
|
CC_VER := $(shell $(CC) 2>&1 | $(HEAD) -n 1 | $(SED) 's/.*\(Version.*\)/\1/' | $(NAWK) '{print $$2}')
|
||||||
|
export CC_VER
|
||||||
|
endif
|
||||||
|
|
||||||
# SDK-64 and MSVC6 put REBASE.EXE in a different places - go figure...
|
# SDK-64 and MSVC6 put REBASE.EXE in a different places - go figure...
|
||||||
ifeq ($(ARCH_DATA_MODEL), 32)
|
ifeq ($(ARCH_DATA_MODEL), 32)
|
||||||
|
ifndef LINK_VER
|
||||||
LINK_VER := $(shell $(LINK) | $(HEAD) -n 1 | $(NAWK) '{print $$6}')
|
LINK_VER := $(shell $(LINK) | $(HEAD) -n 1 | $(NAWK) '{print $$6}')
|
||||||
|
export LINK_VER
|
||||||
|
endif
|
||||||
CC_MAJORVER :=$(call MajorVersion,$(CC_VER))
|
CC_MAJORVER :=$(call MajorVersion,$(CC_VER))
|
||||||
ifeq ($(CC_MAJORVER), 13)
|
ifeq ($(CC_MAJORVER), 13)
|
||||||
# This should be: CC_VER=13.10.3077 LINK_VER=7.10.3077
|
# This should be: CC_VER=13.10.3077 LINK_VER=7.10.3077
|
||||||
|
@ -93,7 +99,10 @@ ifeq ($(PLATFORM), windows)
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
# else ARCH_DATA_MODEL is 64
|
# else ARCH_DATA_MODEL is 64
|
||||||
|
ifndef LINK_VER
|
||||||
LINK_VER := $(shell $(LINK) | $(HEAD) -n 1 | $(NAWK) '{print $$6}')
|
LINK_VER := $(shell $(LINK) | $(HEAD) -n 1 | $(NAWK) '{print $$6}')
|
||||||
|
export LINK_VER
|
||||||
|
endif
|
||||||
CC_MAJORVER :=$(call MajorVersion,$(CC_VER))
|
CC_MAJORVER :=$(call MajorVersion,$(CC_VER))
|
||||||
CC_MINORVER :=$(call MinorVersion,$(CC_VER))
|
CC_MINORVER :=$(call MinorVersion,$(CC_VER))
|
||||||
CC_MICROVER :=$(call MicroVersion,$(CC_VER))
|
CC_MICROVER :=$(call MicroVersion,$(CC_VER))
|
||||||
|
|
|
@ -116,7 +116,6 @@ RC = $(UTILS_COMMAND_PATH)rc
|
||||||
RMDIR = $(UTILS_COMMAND_PATH)rmdir
|
RMDIR = $(UTILS_COMMAND_PATH)rmdir
|
||||||
RPM = $(UTILS_COMMAND_PATH)rpm
|
RPM = $(UTILS_COMMAND_PATH)rpm
|
||||||
RPMBUILD = $(UTILS_COMMAND_PATH)rpmbuild
|
RPMBUILD = $(UTILS_COMMAND_PATH)rpmbuild
|
||||||
SCCS = $(UTILS_CCS_BIN_PATH)sccs
|
|
||||||
SED = $(UTILS_COMMAND_PATH)sed
|
SED = $(UTILS_COMMAND_PATH)sed
|
||||||
SH = $(UTILS_COMMAND_PATH)sh
|
SH = $(UTILS_COMMAND_PATH)sh
|
||||||
SHOWREV = $(UTILS_USR_BIN_PATH)showrev
|
SHOWREV = $(UTILS_USR_BIN_PATH)showrev
|
||||||
|
|
|
@ -113,11 +113,12 @@ _system_drive:=$(call CheckValue,_system_drive,C:)
|
||||||
|
|
||||||
# UNIXCOMMAND_PATH: path to where the most common Unix commands are.
|
# UNIXCOMMAND_PATH: path to where the most common Unix commands are.
|
||||||
# NOTE: Must end with / so that it could be empty, allowing PATH usage.
|
# NOTE: Must end with / so that it could be empty, allowing PATH usage.
|
||||||
ifdef ALT_UNIXCOMMAND_PATH
|
ifndef UNIXCOMMAND_PATH
|
||||||
|
ifdef ALT_UNIXCOMMAND_PATH
|
||||||
xALT_UNIXCOMMAND_PATH :="$(subst \,/,$(ALT_UNIXCOMMAND_PATH))"
|
xALT_UNIXCOMMAND_PATH :="$(subst \,/,$(ALT_UNIXCOMMAND_PATH))"
|
||||||
fxALT_UNIXCOMMAND_PATH :=$(call FullPath,$(xALT_UNIXCOMMAND_PATH))
|
fxALT_UNIXCOMMAND_PATH :=$(call FullPath,$(xALT_UNIXCOMMAND_PATH))
|
||||||
UNIXCOMMAND_PATH :=$(call PrefixPath,$(fxALT_UNIXCOMMAND_PATH))
|
UNIXCOMMAND_PATH :=$(call PrefixPath,$(fxALT_UNIXCOMMAND_PATH))
|
||||||
else
|
else
|
||||||
ifdef USING_CYGWIN
|
ifdef USING_CYGWIN
|
||||||
UNIXCOMMAND_PATH :=$(call PrefixPath,/usr/bin)
|
UNIXCOMMAND_PATH :=$(call PrefixPath,/usr/bin)
|
||||||
else
|
else
|
||||||
|
@ -132,13 +133,18 @@ else
|
||||||
UNIXCOMMAND_PATH :=$(call PrefixPath,$(_rootdir)/mksnt)
|
UNIXCOMMAND_PATH :=$(call PrefixPath,$(_rootdir)/mksnt)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
UNIXCOMMAND_PATH:=$(call AltCheckSpaces,UNIXCOMMAND_PATH)
|
||||||
|
export UNIXCOMMAND_PATH
|
||||||
endif
|
endif
|
||||||
UNIXCOMMAND_PATH:=$(call AltCheckSpaces,UNIXCOMMAND_PATH)
|
|
||||||
|
|
||||||
# Get version of MKS or CYGWIN
|
# Get version of MKS or CYGWIN
|
||||||
ifdef USING_CYGWIN
|
ifdef USING_CYGWIN
|
||||||
_CYGWIN_VER :=$(shell $(UNAME))
|
ifndef CYGWIN_VER
|
||||||
CYGWIN_VER :=$(call GetVersion,$(_CYGWIN_VER))
|
_CYGWIN_VER :=$(shell $(UNAME))
|
||||||
|
CYGWIN_VER :=$(call GetVersion,$(_CYGWIN_VER))
|
||||||
|
export CYGWIN_VER
|
||||||
|
endif
|
||||||
else # MKS
|
else # MKS
|
||||||
_MKS_VER :=$(shell $(MKSINFO) 2>&1 | $(GREP) Release | $(TAIL) -1 | $(SED) -e 's@.*\(Release.*\)@\1@')
|
_MKS_VER :=$(shell $(MKSINFO) 2>&1 | $(GREP) Release | $(TAIL) -1 | $(SED) -e 's@.*\(Release.*\)@\1@')
|
||||||
MKS_VER :=$(call GetVersion,$(_MKS_VER))
|
MKS_VER :=$(call GetVersion,$(_MKS_VER))
|
||||||
|
@ -168,194 +174,188 @@ endif # MKS
|
||||||
|
|
||||||
# Process Windows values into FullPath values, these paths may have \ chars
|
# Process Windows values into FullPath values, these paths may have \ chars
|
||||||
|
|
||||||
# System root
|
|
||||||
ifdef SYSTEMROOT
|
|
||||||
xSYSTEMROOT :="$(subst \,/,$(SYSTEMROOT))"
|
|
||||||
_system_root :=$(call FullPath,$(xSYSTEMROOT))
|
|
||||||
else
|
|
||||||
ifdef SystemRoot
|
|
||||||
xSYSTEMROOT :="$(subst \,/,$(SystemRoot))"
|
|
||||||
_system_root :=$(call FullPath,$(xSYSTEMROOT))
|
|
||||||
else
|
|
||||||
ifdef WINDIR
|
|
||||||
xWINDIR :="$(subst \,/,$(WINDIR))"
|
|
||||||
_system_root :=$(call FullPath,$(xWINDIR))
|
|
||||||
else
|
|
||||||
ifdef windir
|
|
||||||
xWINDIR :="$(subst \,/,$(windir))"
|
|
||||||
_system_root :=$(call FullPath,$(xWINDIR))
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
_system_root:=$(call CheckValue,_system_root,$(_system_drive)/WINNT)
|
|
||||||
|
|
||||||
# Program Files directory
|
# Program Files directory
|
||||||
ifdef PROGRAMFILES
|
ifndef SHORTPROGRAMFILES
|
||||||
|
ifdef PROGRAMFILES
|
||||||
xPROGRAMFILES :="$(subst \,/,$(PROGRAMFILES))"
|
xPROGRAMFILES :="$(subst \,/,$(PROGRAMFILES))"
|
||||||
else
|
else
|
||||||
ifeq ($(ARCH_DATA_MODEL), 32)
|
ifeq ($(ARCH_DATA_MODEL), 32)
|
||||||
xPROGRAMFILES :="$(_system_drive)/Program Files"
|
xPROGRAMFILES :="$(_system_drive)/Program Files"
|
||||||
else
|
else
|
||||||
xPROGRAMFILES :="$(_system_drive)/Program Files (x86)"
|
xPROGRAMFILES :="$(_system_drive)/Program Files (x86)"
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
ifeq ($(ARCH_DATA_MODEL), 32)
|
ifeq ($(ARCH_DATA_MODEL), 32)
|
||||||
_program_files :=$(call FullPath,$(xPROGRAMFILES))
|
SHORTPROGRAMFILES :=$(call FullPath,$(xPROGRAMFILES))
|
||||||
else
|
else
|
||||||
ifdef PROGRAMW6432
|
ifdef PROGRAMW6432
|
||||||
xPROGRAMW6432 :="$(subst \,/,$(PROGRAMW6432))"
|
xPROGRAMW6432 :="$(subst \,/,$(PROGRAMW6432))"
|
||||||
else
|
else
|
||||||
xPROGRAMW6432 :="$(_system_drive)/Program Files"
|
xPROGRAMW6432 :="$(_system_drive)/Program Files"
|
||||||
endif
|
endif
|
||||||
_program_files :=$(call FullPath,$(xPROGRAMW6432))
|
SHORTPROGRAMFILES :=$(call FullPath,$(xPROGRAMW6432))
|
||||||
_program_files32 :=$(call FullPath,$(xPROGRAMFILES))
|
|
||||||
ifneq ($(word 1,$(_program_files32)),$(_program_files32))
|
|
||||||
_program_files32:=
|
|
||||||
endif
|
endif
|
||||||
endif
|
ifneq ($(word 1,$(SHORTPROGRAMFILES)),$(SHORTPROGRAMFILES))
|
||||||
ifneq ($(word 1,$(_program_files)),$(_program_files))
|
SHORTPROGRAMFILES :=
|
||||||
_program_files:=
|
endif
|
||||||
|
export SHORTPROGRAMFILES
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Compilers, SDK, and Visual Studio (MSDEV) [32bit is different from 64bit]
|
# Compilers, SDK, and Visual Studio (MSDEV) [32bit is different from 64bit]
|
||||||
ifeq ($(ARCH_DATA_MODEL), 32)
|
ifeq ($(ARCH_DATA_MODEL), 32)
|
||||||
|
ifndef SHORTMSVCDIR
|
||||||
# Try looking in MSVCDIR or MSVCDir area first (set by vcvars32.bat)
|
# Try looking in MSVCDIR or MSVCDir area first (set by vcvars32.bat)
|
||||||
ifdef MSVCDIR
|
ifdef MSVCDIR
|
||||||
xMSVCDIR :="$(subst \,/,$(MSVCDIR))"
|
xMSVCDIR :="$(subst \,/,$(MSVCDIR))"
|
||||||
_msvc_dir :=$(call FullPath,$(xMSVCDIR))
|
SHORTMSVCDIR :=$(call FullPath,$(xMSVCDIR))
|
||||||
else
|
else
|
||||||
ifdef MSVCDir
|
ifdef MSVCDir
|
||||||
xMSVCDIR :="$(subst \,/,$(MSVCDir))"
|
xMSVCDIR :="$(subst \,/,$(MSVCDir))"
|
||||||
_msvc_dir :=$(call FullPath,$(xMSVCDIR))
|
SHORTMSVCDIR :=$(call FullPath,$(xMSVCDIR))
|
||||||
else
|
else
|
||||||
ifneq ($(_program_files),)
|
ifneq ($(SHORTPROGRAMFILES),)
|
||||||
xMSVCDIR :="$(_program_files)/Microsoft Visual Studio .NET 2003/Vc7"
|
xMSVCDIR :="$(SHORTPROGRAMFILES)/Microsoft Visual Studio .NET 2003/Vc7"
|
||||||
_msvc_dir :=$(call FullPath,$(xMSVCDIR))
|
SHORTMSVCDIR :=$(call FullPath,$(xMSVCDIR))
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
ifneq ($(subst MSDev98,OLDOLDOLD,$(_msvc_dir)),$(_msvc_dir))
|
ifneq ($(subst MSDev98,OLDOLDOLD,$(SHORTMSVCDIR)),$(SHORTMSVCDIR))
|
||||||
_msvc_dir :=
|
SHORTMSVCDIR :=
|
||||||
endif
|
endif
|
||||||
# If we still don't have it, look for VS71COMNTOOLS, setup by installer?
|
# If we still don't have it, look for VS71COMNTOOLS, setup by installer?
|
||||||
ifeq ($(_msvc_dir),)
|
ifeq ($(SHORTMSVCDIR),)
|
||||||
ifdef VS71COMNTOOLS # /Common/Tools directory, use ../../Vc7
|
ifdef VS71COMNTOOLS # /Common/Tools directory, use ../../Vc7
|
||||||
xVS71COMNTOOLS :="$(subst \,/,$(VS71COMNTOOLS))"
|
xVS71COMNTOOLS :="$(subst \,/,$(VS71COMNTOOLS))"
|
||||||
_vs71tools :=$(call FullPath,$(xVS71COMNTOOLS))
|
_vs71tools :=$(call FullPath,$(xVS71COMNTOOLS))
|
||||||
endif
|
endif
|
||||||
ifneq ($(_vs71tools),)
|
ifneq ($(_vs71tools),)
|
||||||
_msvc_dir :=$(_vs71tools)/../../Vc7
|
SHORTMSVCDIR :=$(_vs71tools)/../../Vc7
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
ifneq ($(_msvc_dir),)
|
export SHORTMSVCDIR
|
||||||
_compiler_bin :=$(_msvc_dir)/Bin
|
endif
|
||||||
_redist_sdk :=$(_msvc_dir)/../SDK/v1.1/Bin
|
ifneq ($(SHORTMSVCDIR),)
|
||||||
_ms_sdk :=$(_msvc_dir)/PlatformSDK
|
SHORTCOMPILERBIN :=$(SHORTMSVCDIR)/Bin
|
||||||
|
SHORTPSDK :=$(SHORTMSVCDIR)/PlatformSDK
|
||||||
|
export SHORTCOMPILERBIN
|
||||||
|
export SHORTPSDK
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# The Microsoft Platform SDK installed by itself
|
# The Microsoft Platform SDK installed by itself
|
||||||
ifneq ($(_program_files),)
|
ifneq ($(SHORTPROGRAMFILES),)
|
||||||
xPSDK :="$(_program_files)/Microsoft Platform SDK"
|
ifndef SHORTPSDK
|
||||||
_psdk :=$(call FullPath,$(xPSDK))
|
xPSDK :="$(SHORTPROGRAMFILES)/Microsoft Platform SDK"
|
||||||
ifeq ($(_psdk),)
|
SHORTPSDK :=$(call FullPath,$(xPSDK))
|
||||||
xPSDK :="$(_program_files)/Microsoft SDK"
|
ifeq ($(SHORTPSDK),)
|
||||||
_psdk :=$(call FullPath,$(xMSSDK))
|
xPSDK :="$(SHORTPROGRAMFILES)/Microsoft SDK"
|
||||||
|
SHORTPSDK :=$(call FullPath,$(xMSSDK))
|
||||||
|
endif
|
||||||
|
export SHORTPSDK
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# If no SDK found yet, look in other places
|
# If no SDK found yet, look in other places
|
||||||
ifeq ($(_ms_sdk),)
|
ifndef SHORTPSDK
|
||||||
ifdef MSSDK
|
ifdef MSSDK
|
||||||
xMSSDK :="$(subst \,/,$(MSSDK))"
|
xMSSDK :="$(subst \,/,$(MSSDK))"
|
||||||
_ms_sdk :=$(call FullPath,$(xMSSDK))
|
SHORTPSDK :=$(call FullPath,$(xMSSDK))
|
||||||
else
|
else
|
||||||
ifdef MSSdk
|
ifdef MSSdk
|
||||||
xMSSDK :="$(subst \,/,$(MSSdk))"
|
xMSSDK :="$(subst \,/,$(MSSdk))"
|
||||||
_ms_sdk :=$(call FullPath,$(xMSSDK))
|
SHORTPSDK :=$(call FullPath,$(xMSSDK))
|
||||||
else
|
|
||||||
_ms_sdk :=$(_psdk)
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
export SHORTPSDK
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Compilers for 64bit are from SDK
|
# Compilers for 64bit are from SDK
|
||||||
ifeq ($(ARCH_DATA_MODEL), 64)
|
ifeq ($(ARCH_DATA_MODEL), 64)
|
||||||
|
ifndef SHORTCOMPILERBIN
|
||||||
xMSSDK61 :="C:/Program Files/Microsoft SDKs/Windows/v6.1/"
|
xMSSDK61 :="C:/Program Files/Microsoft SDKs/Windows/v6.1/"
|
||||||
MSSDK61 :=$(call FullPath,$(xMSSDK61))
|
MSSDK61 :=$(call FullPath,$(xMSSDK61))
|
||||||
xVS2008 :="C:/Program Files (x86)/Microsoft Visual Studio 9.0/"
|
xVS2008 :="C:/Program Files (x86)/Microsoft Visual Studio 9.0/"
|
||||||
_vs2008 :=$(call FullPath,$(xVS2008))
|
_vs2008 :=$(call FullPath,$(xVS2008))
|
||||||
ifneq ($(_vs2008),)
|
ifneq ($(_vs2008),)
|
||||||
ifeq ($(ARCH), ia64)
|
ifeq ($(ARCH), ia64)
|
||||||
_compiler_bin :=$(_vs2008)/VC/Bin/x86_ia64
|
SHORTCOMPILERBIN :=$(_vs2008)/VC/Bin/x86_ia64
|
||||||
endif
|
endif
|
||||||
ifeq ($(ARCH), amd64)
|
ifeq ($(ARCH), amd64)
|
||||||
_compiler_bin :=$(_vs2008)/VC/Bin/$(ARCH)
|
SHORTCOMPILERBIN :=$(_vs2008)/VC/Bin/$(ARCH)
|
||||||
_redist_sdk :=$(MSSDK61)/VC/redist
|
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
ifneq ($(_ms_sdk),)
|
ifneq ($(SHORTPSDK),)
|
||||||
ifeq ($(ARCH), ia64)
|
ifeq ($(ARCH), ia64)
|
||||||
_compiler_bin :=$(_ms_sdk)/Bin/Win64
|
SHORTCOMPILERBIN :=$(SHORTPSDK)/Bin/Win64
|
||||||
endif
|
endif
|
||||||
ifeq ($(ARCH), amd64)
|
ifeq ($(ARCH), amd64)
|
||||||
_compiler_bin :=$(_ms_sdk)/Bin/Win64/x86/$(ARCH)
|
SHORTCOMPILERBIN :=$(SHORTPSDK)/Bin/Win64/x86/$(ARCH)
|
||||||
_redist_sdk :=$(_ms_sdk)/redist/win64/AMD64
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
export SHORTCOMPILERBIN
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Location on system where jdk installs might be
|
# Location on system where jdk installs might be
|
||||||
ifneq ($(_program_files),)
|
ifneq ($(SHORTPROGRAMFILES),)
|
||||||
USRJDKINSTANCES_PATH =$(_program_files)/Java
|
USRJDKINSTANCES_PATH =$(SHORTPROGRAMFILES)/Java
|
||||||
else
|
else
|
||||||
USRJDKINSTANCES_PATH =$(_system_drive)/
|
USRJDKINSTANCES_PATH =$(_system_drive)/
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# SLASH_JAVA: location of all network accessable files
|
# SLASH_JAVA: location of all network accessable files
|
||||||
ifdef ALT_SLASH_JAVA
|
ifndef SLASH_JAVA
|
||||||
|
ifdef ALT_SLASH_JAVA
|
||||||
xALT_SLASH_JAVA :="$(subst \,/,$(ALT_SLASH_JAVA))"
|
xALT_SLASH_JAVA :="$(subst \,/,$(ALT_SLASH_JAVA))"
|
||||||
SLASH_JAVA :=$(call FullPath,$(xALT_SLASH_JAVA))
|
SLASH_JAVA :=$(call FullPath,$(xALT_SLASH_JAVA))
|
||||||
else
|
else
|
||||||
ifdef ALT_JDK_JAVA_DRIVE
|
ifdef ALT_JDK_JAVA_DRIVE
|
||||||
SLASH_JAVA =$(JDK_JAVA_DRIVE)
|
SLASH_JAVA =$(JDK_JAVA_DRIVE)
|
||||||
else
|
else
|
||||||
SLASH_JAVA =J:
|
SLASH_JAVA =J:
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
SLASH_JAVA:=$(call AltCheckSpaces,SLASH_JAVA)
|
||||||
|
SLASH_JAVA:=$(call AltCheckValue,SLASH_JAVA)
|
||||||
|
export SLASH_JAVA
|
||||||
endif
|
endif
|
||||||
SLASH_JAVA:=$(call AltCheckSpaces,SLASH_JAVA)
|
|
||||||
SLASH_JAVA:=$(call AltCheckValue,SLASH_JAVA)
|
|
||||||
|
|
||||||
# JDK_DEVTOOLS_DIR: common path for all the java devtools
|
# JDK_DEVTOOLS_DIR: common path for all the java devtools
|
||||||
ifdef ALT_JDK_DEVTOOLS_DIR
|
ifndef JDK_DEVTOOLS_DIR
|
||||||
|
ifdef ALT_JDK_DEVTOOLS_DIR
|
||||||
xALT_JDK_DEVTOOLS_DIR :="$(subst \,/,$(ALT_JDK_DEVTOOLS_DIR))"
|
xALT_JDK_DEVTOOLS_DIR :="$(subst \,/,$(ALT_JDK_DEVTOOLS_DIR))"
|
||||||
JDK_DEVTOOLS_DIR :=$(call FullPath,$(xALT_JDK_DEVTOOLS_DIR))
|
JDK_DEVTOOLS_DIR :=$(call FullPath,$(xALT_JDK_DEVTOOLS_DIR))
|
||||||
else
|
else
|
||||||
JDK_DEVTOOLS_DIR =$(SLASH_JAVA)/devtools
|
JDK_DEVTOOLS_DIR =$(SLASH_JAVA)/devtools
|
||||||
|
endif
|
||||||
|
JDK_DEVTOOLS_DIR:=$(call AltCheckSpaces,JDK_DEVTOOLS_DIR)
|
||||||
|
JDK_DEVTOOLS_DIR:=$(call AltCheckValue,JDK_DEVTOOLS_DIR)
|
||||||
|
export JDK_DEVTOOLS_DIR
|
||||||
endif
|
endif
|
||||||
JDK_DEVTOOLS_DIR:=$(call AltCheckSpaces,JDK_DEVTOOLS_DIR)
|
|
||||||
JDK_DEVTOOLS_DIR:=$(call AltCheckValue,JDK_DEVTOOLS_DIR)
|
|
||||||
|
|
||||||
# COMPILER_PATH: path to where the compiler and tools are installed.
|
# COMPILER_PATH: path to where the compiler and tools are installed.
|
||||||
# NOTE: Must end with / so that it could be empty, allowing PATH usage.
|
# NOTE: Must end with / so that it could be empty, allowing PATH usage.
|
||||||
ifdef ALT_COMPILER_PATH
|
ifndef COMPILER_PATH
|
||||||
|
ifdef ALT_COMPILER_PATH
|
||||||
xALT_COMPILER_PATH :="$(subst \,/,$(ALT_COMPILER_PATH))"
|
xALT_COMPILER_PATH :="$(subst \,/,$(ALT_COMPILER_PATH))"
|
||||||
fxALT_COMPILER_PATH :=$(call FullPath,$(xALT_COMPILER_PATH))
|
fxALT_COMPILER_PATH :=$(call FullPath,$(xALT_COMPILER_PATH))
|
||||||
COMPILER_PATH :=$(call PrefixPath,$(fxALT_COMPILER_PATH))
|
COMPILER_PATH :=$(call PrefixPath,$(fxALT_COMPILER_PATH))
|
||||||
else
|
else
|
||||||
COMPILER_PATH :=$(call PrefixPath,$(_compiler_bin))
|
COMPILER_PATH :=$(call PrefixPath,$(SHORTCOMPILERBIN))
|
||||||
|
endif
|
||||||
|
COMPILER_PATH :=$(call AltCheckSpaces,COMPILER_PATH)
|
||||||
|
export COMPILER_PATH
|
||||||
endif
|
endif
|
||||||
COMPILER_PATH :=$(call AltCheckSpaces,COMPILER_PATH)
|
|
||||||
|
|
||||||
# MSDEVTOOLS_PATH: path to where the additional MS Compiler tools are.
|
# MSDEVTOOLS_PATH: path to where the additional MS Compiler tools are.
|
||||||
# NOTE: Must end with / so that it could be empty, allowing PATH usage.
|
# NOTE: Must end with / so that it could be empty, allowing PATH usage.
|
||||||
ifdef ALT_MSDEVTOOLS_PATH
|
ifndef MSDEVTOOLS_PATH
|
||||||
|
ifdef ALT_MSDEVTOOLS_PATH
|
||||||
xALT_MSDEVTOOLS_PATH :="$(subst \,/,$(ALT_MSDEVTOOLS_PATH))"
|
xALT_MSDEVTOOLS_PATH :="$(subst \,/,$(ALT_MSDEVTOOLS_PATH))"
|
||||||
fxALT_MSDEVTOOLS_PATH :=$(call FullPath,$(xALT_MSDEVTOOLS_PATH))
|
fxALT_MSDEVTOOLS_PATH :=$(call FullPath,$(xALT_MSDEVTOOLS_PATH))
|
||||||
MSDEVTOOLS_PATH :=$(call PrefixPath,$(fxALT_MSDEVTOOLS_PATH))
|
MSDEVTOOLS_PATH :=$(call PrefixPath,$(fxALT_MSDEVTOOLS_PATH))
|
||||||
else
|
else
|
||||||
ifeq ($(ARCH_DATA_MODEL), 64)
|
ifeq ($(ARCH_DATA_MODEL), 64)
|
||||||
ifdef MSTOOLS
|
ifdef MSTOOLS
|
||||||
xMSTOOLS :="$(subst \,/,$(MSTOOLS))"
|
xMSTOOLS :="$(subst \,/,$(MSTOOLS))"
|
||||||
|
@ -372,22 +372,25 @@ else
|
||||||
_ms_tools_bin :=$(_ms_tools)/Bin
|
_ms_tools_bin :=$(_ms_tools)/Bin
|
||||||
else
|
else
|
||||||
# Assumes compiler bin is .../Bin/win64/x86/AMD64, rc.exe is 3 levels up
|
# Assumes compiler bin is .../Bin/win64/x86/AMD64, rc.exe is 3 levels up
|
||||||
_ms_tools_bin :=$(_compiler_bin)/../../..
|
_ms_tools_bin :=$(SHORTCOMPILERBIN)/../../..
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
_ms_tools_bin :=$(_compiler_bin)
|
_ms_tools_bin :=$(SHORTCOMPILERBIN)
|
||||||
endif
|
endif
|
||||||
MSDEVTOOLS_PATH :=$(call PrefixPath,$(_ms_tools_bin))
|
MSDEVTOOLS_PATH :=$(call PrefixPath,$(_ms_tools_bin))
|
||||||
|
endif
|
||||||
|
MSDEVTOOLS_PATH:=$(call AltCheckSpaces,MSDEVTOOLS_PATH)
|
||||||
|
export MSDEVTOOLS_PATH
|
||||||
endif
|
endif
|
||||||
MSDEVTOOLS_PATH:=$(call AltCheckSpaces,MSDEVTOOLS_PATH)
|
|
||||||
|
|
||||||
# DEVTOOLS_PATH: for other tools required for building (such as zip, etc.)
|
# DEVTOOLS_PATH: for other tools required for building (such as zip, etc.)
|
||||||
# NOTE: Must end with / so that it could be empty, allowing PATH usage.
|
# NOTE: Must end with / so that it could be empty, allowing PATH usage.
|
||||||
ifdef ALT_DEVTOOLS_PATH
|
ifndef DEVTOOLS_PATH
|
||||||
|
ifdef ALT_DEVTOOLS_PATH
|
||||||
xALT_DEVTOOLS_PATH :="$(subst \,/,$(ALT_DEVTOOLS_PATH))"
|
xALT_DEVTOOLS_PATH :="$(subst \,/,$(ALT_DEVTOOLS_PATH))"
|
||||||
fxALT_DEVTOOLS_PATH :=$(call FullPath,$(xALT_DEVTOOLS_PATH))
|
fxALT_DEVTOOLS_PATH :=$(call FullPath,$(xALT_DEVTOOLS_PATH))
|
||||||
DEVTOOLS_PATH :=$(call PrefixPath,$(fxALT_DEVTOOLS_PATH))
|
DEVTOOLS_PATH :=$(call PrefixPath,$(fxALT_DEVTOOLS_PATH))
|
||||||
else
|
else
|
||||||
ifdef USING_CYGWIN
|
ifdef USING_CYGWIN
|
||||||
DEVTOOLS_PATH :=$(UNIXCOMMAND_PATH)
|
DEVTOOLS_PATH :=$(UNIXCOMMAND_PATH)
|
||||||
else
|
else
|
||||||
|
@ -395,8 +398,10 @@ else
|
||||||
fxDEVTOOLS_PATH :=$(call FullPath,$(xDEVTOOLS_PATH))
|
fxDEVTOOLS_PATH :=$(call FullPath,$(xDEVTOOLS_PATH))
|
||||||
DEVTOOLS_PATH :=$(call PrefixPath,$(fxDEVTOOLS_PATH))
|
DEVTOOLS_PATH :=$(call PrefixPath,$(fxDEVTOOLS_PATH))
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
DEVTOOLS_PATH:=$(call AltCheckSpaces,DEVTOOLS_PATH)
|
||||||
|
export DEVTOOLS_PATH
|
||||||
endif
|
endif
|
||||||
DEVTOOLS_PATH:=$(call AltCheckSpaces,DEVTOOLS_PATH)
|
|
||||||
|
|
||||||
# _BOOTDIR1: First choice for a Bootstrap JDK, previous released JDK.
|
# _BOOTDIR1: First choice for a Bootstrap JDK, previous released JDK.
|
||||||
# _BOOTDIR2: Second choice
|
# _BOOTDIR2: Second choice
|
||||||
|
@ -410,20 +415,26 @@ endif
|
||||||
|
|
||||||
# BUILD_JDK_IMPORT_PATH: location of JDK install trees to import for
|
# BUILD_JDK_IMPORT_PATH: location of JDK install trees to import for
|
||||||
# multiple platforms, e.g. windows-i586, solaris-sparc, linux-586, etc.
|
# multiple platforms, e.g. windows-i586, solaris-sparc, linux-586, etc.
|
||||||
ifdef ALT_BUILD_JDK_IMPORT_PATH
|
ifndef BUILD_JDK_IMPORT_PATH
|
||||||
|
ifdef ALT_BUILD_JDK_IMPORT_PATH
|
||||||
BUILD_JDK_IMPORT_PATH :=$(call FullPath,$(ALT_BUILD_JDK_IMPORT_PATH))
|
BUILD_JDK_IMPORT_PATH :=$(call FullPath,$(ALT_BUILD_JDK_IMPORT_PATH))
|
||||||
else
|
else
|
||||||
BUILD_JDK_IMPORT_PATH = $(PROMOTED_BUILD_BINARIES)
|
BUILD_JDK_IMPORT_PATH = $(PROMOTED_BUILD_BINARIES)
|
||||||
|
endif
|
||||||
|
BUILD_JDK_IMPORT_PATH:=$(call AltCheckSpaces,BUILD_JDK_IMPORT_PATH)
|
||||||
|
BUILD_JDK_IMPORT_PATH:=$(call AltCheckValue,BUILD_JDK_IMPORT_PATH)
|
||||||
|
export BUILD_JDK_IMPORT_PATH
|
||||||
endif
|
endif
|
||||||
BUILD_JDK_IMPORT_PATH:=$(call AltCheckSpaces,BUILD_JDK_IMPORT_PATH)
|
|
||||||
BUILD_JDK_IMPORT_PATH:=$(call AltCheckValue,BUILD_JDK_IMPORT_PATH)
|
|
||||||
|
|
||||||
# JDK_IMPORT_PATH: location of previously built JDK (this version) to import
|
# JDK_IMPORT_PATH: location of previously built JDK (this version) to import
|
||||||
ifdef ALT_JDK_IMPORT_PATH
|
ifndef JDK_IMPORT_PATH
|
||||||
|
ifdef ALT_JDK_IMPORT_PATH
|
||||||
JDK_IMPORT_PATH :=$(call FullPath,$(ALT_JDK_IMPORT_PATH))
|
JDK_IMPORT_PATH :=$(call FullPath,$(ALT_JDK_IMPORT_PATH))
|
||||||
else
|
else
|
||||||
JDK_IMPORT_PATH = $(BUILD_JDK_IMPORT_PATH)/$(PLATFORM)-$(ARCH)$(_JDK_IMPORT_VARIANT)
|
JDK_IMPORT_PATH = $(BUILD_JDK_IMPORT_PATH)/$(PLATFORM)-$(ARCH)$(_JDK_IMPORT_VARIANT)
|
||||||
|
endif
|
||||||
|
JDK_IMPORT_PATH:=$(call AltCheckSpaces,JDK_IMPORT_PATH)
|
||||||
|
JDK_IMPORT_PATH:=$(call AltCheckValue,JDK_IMPORT_PATH)
|
||||||
|
export JDK_IMPORT_PATH
|
||||||
endif
|
endif
|
||||||
JDK_IMPORT_PATH:=$(call AltCheckSpaces,JDK_IMPORT_PATH)
|
|
||||||
JDK_IMPORT_PATH:=$(call AltCheckValue,JDK_IMPORT_PATH)
|
|
||||||
|
|
||||||
|
|
|
@ -228,12 +228,15 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# FULL_VERSION is RELEASE and -BUILD_NUMBER if BUILD_NUMBER is set
|
# FULL_VERSION is RELEASE and -BUILD_NUMBER if BUILD_NUMBER is set
|
||||||
ifdef BUILD_NUMBER
|
ifndef FULL_VERSION
|
||||||
|
ifdef BUILD_NUMBER
|
||||||
FULL_VERSION = $(RELEASE)-$(BUILD_NUMBER)
|
FULL_VERSION = $(RELEASE)-$(BUILD_NUMBER)
|
||||||
else
|
else
|
||||||
BUILD_NUMBER = b00
|
BUILD_NUMBER = b00
|
||||||
USER_RELEASE_SUFFIX := $(shell echo $(USER)_`date '+%d_%b_%Y_%H_%M' | tr "A-Z" "a-z"`)
|
USER_RELEASE_SUFFIX := $(shell echo $(USER)_`date '+%d_%b_%Y_%H_%M' | tr "A-Z" "a-z"`)
|
||||||
FULL_VERSION = $(RELEASE)-$(USER_RELEASE_SUFFIX)-$(BUILD_NUMBER)
|
FULL_VERSION = $(RELEASE)-$(USER_RELEASE_SUFFIX)-$(BUILD_NUMBER)
|
||||||
|
endif
|
||||||
|
export FULL_VERSION
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Promoted build location
|
# Promoted build location
|
||||||
|
|
|
@ -84,21 +84,14 @@ PLATFORM_SHARED=done
|
||||||
# REQUIRED_LINUX_VER linux only: required version of linux
|
# REQUIRED_LINUX_VER linux only: required version of linux
|
||||||
# REQUIRED_LINUX_FULLVER linux only: required full version of linux
|
# REQUIRED_LINUX_FULLVER linux only: required full version of linux
|
||||||
|
|
||||||
SYSTEM_UNAME := $(shell uname)
|
ifndef SYSTEM_UNAME
|
||||||
|
SYSTEM_UNAME := $(shell uname)
|
||||||
|
export SYSTEM_UNAME
|
||||||
|
endif
|
||||||
|
|
||||||
# Normal boot jdk is previous release, but a hard requirement is a 1.5 boot
|
# Normal boot jdk is previous release, but a hard requirement is a 1.5 boot
|
||||||
REQUIRED_BOOT_VER = 1.5
|
REQUIRED_BOOT_VER = 1.5
|
||||||
|
|
||||||
#
|
|
||||||
# Prune out all known SCM (Source Code Management) directories
|
|
||||||
# so they will not be included when copying directory trees
|
|
||||||
# or packaging up .jar files, etc. This applies to all workspaces.
|
|
||||||
#
|
|
||||||
SCM_DIRs = .hg .svn CVS RCS SCCS Codemgr_wsdata deleted_files
|
|
||||||
# When changing SCM_DIRs also change SCM_DIRS_rexp and SCM_DIRS_prune:
|
|
||||||
SCM_DIRS_rexp = ".hg|.svn|CVS|RCS|SCCS|Codemgr_wsdata|deleted_files"
|
|
||||||
SCM_DIRS_prune = \( -name .hg -o -name .svn -o -name CVS -o -name RCS -o -name SCCS -o -name Codemgr_wsdata -o -name deleted_files \) -prune
|
|
||||||
|
|
||||||
# Don't define this unless it's not defined
|
# Don't define this unless it's not defined
|
||||||
ifndef VARIANT
|
ifndef VARIANT
|
||||||
VARIANT=OPT
|
VARIANT=OPT
|
||||||
|
@ -372,6 +365,7 @@ ifeq ($(PLATFORM), windows)
|
||||||
REQUIRED_FREE_SPACE=500000
|
REQUIRED_FREE_SPACE=500000
|
||||||
OS_VENDOR = Microsoft
|
OS_VENDOR = Microsoft
|
||||||
# How much RAM does this machine have:
|
# How much RAM does this machine have:
|
||||||
|
ifndef MB_OF_MEMORY
|
||||||
MB_OF_MEMORY := $(shell \
|
MB_OF_MEMORY := $(shell \
|
||||||
if [ -f "C:/cygwin/bin/free.exe" ] ; then \
|
if [ -f "C:/cygwin/bin/free.exe" ] ; then \
|
||||||
( C:/cygwin/bin/bash.exe -c "C:/cygwin/bin/free.exe -m" ) | \
|
( C:/cygwin/bin/bash.exe -c "C:/cygwin/bin/free.exe -m" ) | \
|
||||||
|
@ -380,6 +374,8 @@ ifeq ($(PLATFORM), windows)
|
||||||
else \
|
else \
|
||||||
echo "512"; \
|
echo "512"; \
|
||||||
fi)
|
fi)
|
||||||
|
export MB_OF_MEMORY
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Machines with 512Mb or less of real memory are considered low memory
|
# Machines with 512Mb or less of real memory are considered low memory
|
||||||
|
@ -387,7 +383,8 @@ endif
|
||||||
# system swapping during the build.
|
# system swapping during the build.
|
||||||
# If we don't know, assume 512. Subtract 128 from MB for VM MAX.
|
# If we don't know, assume 512. Subtract 128 from MB for VM MAX.
|
||||||
# Don't set VM max over 1024-128=896.
|
# Don't set VM max over 1024-128=896.
|
||||||
ifneq ($(MB_OF_MEMORY),)
|
ifndef MAX_VM_MEMORY
|
||||||
|
ifneq ($(MB_OF_MEMORY),)
|
||||||
LOW_MEMORY_MACHINE := $(shell \
|
LOW_MEMORY_MACHINE := $(shell \
|
||||||
if [ $(MB_OF_MEMORY) -le 512 ] ; then \
|
if [ $(MB_OF_MEMORY) -le 512 ] ; then \
|
||||||
echo "true"; \
|
echo "true"; \
|
||||||
|
@ -406,11 +403,16 @@ ifneq ($(MB_OF_MEMORY),)
|
||||||
else \
|
else \
|
||||||
echo "128"; \
|
echo "128"; \
|
||||||
fi)
|
fi)
|
||||||
else
|
else
|
||||||
MB_OF_MEMORY := unknown
|
MB_OF_MEMORY := unknown
|
||||||
LOW_MEMORY_MACHINE := true
|
LOW_MEMORY_MACHINE := true
|
||||||
MAX_VM_MEMORY := 384
|
MAX_VM_MEMORY := 384
|
||||||
MIN_VM_MEMORY := 128
|
MIN_VM_MEMORY := 128
|
||||||
|
endif
|
||||||
|
export MAX_VM_MEMORY
|
||||||
|
export MIN_VM_MEMORY
|
||||||
|
export LOW_MEMORY_MACHINE
|
||||||
|
export MAX_VM_MEMORY
|
||||||
endif
|
endif
|
||||||
|
|
||||||
REQUIRED_ZIP_VER = 2.2
|
REQUIRED_ZIP_VER = 2.2
|
||||||
|
|
|
@ -34,8 +34,8 @@ solaris_i586_5.10,\
|
||||||
solaris_x64_5.10,\
|
solaris_x64_5.10,\
|
||||||
linux_i586_2.6,\
|
linux_i586_2.6,\
|
||||||
linux_x64_2.6,\
|
linux_x64_2.6,\
|
||||||
windows_i586,\
|
windows_i586_5.0,\
|
||||||
windows_x64
|
windows_x64_5.2
|
||||||
|
|
||||||
# The different build flavors we want
|
# The different build flavors we want
|
||||||
jprt.build.flavors=product,fastdebug
|
jprt.build.flavors=product,fastdebug
|
||||||
|
|
|
@ -45,3 +45,6 @@ ba313800759b678979434d6da8ed3bf49eb8bea4 jdk7-b65
|
||||||
d07e68298d4e17ebf93d8299e43fcc3ded26472a jdk7-b68
|
d07e68298d4e17ebf93d8299e43fcc3ded26472a jdk7-b68
|
||||||
54fd4d9232969ea6cd3d236e5ad276183bb0d423 jdk7-b69
|
54fd4d9232969ea6cd3d236e5ad276183bb0d423 jdk7-b69
|
||||||
0632c3e615a315ff11e2ab1d64f4d82ff9853461 jdk7-b70
|
0632c3e615a315ff11e2ab1d64f4d82ff9853461 jdk7-b70
|
||||||
|
50a95aa4a247f0cbbf66df285a8b1d78ffb153d9 jdk7-b71
|
||||||
|
a94714c550658fd6741793ef036cb9625dc2ab1a jdk7-b72
|
||||||
|
faf94d94786b621f8e13cbcc941ca69c6d967c3f jdk7-b73
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
# Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
# Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
|
# Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
|
# Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -33,6 +33,7 @@ import sun.jvm.hotspot.utilities.*;
|
||||||
|
|
||||||
public class CodeCache {
|
public class CodeCache {
|
||||||
private static AddressField heapField;
|
private static AddressField heapField;
|
||||||
|
private static AddressField scavengeRootNMethodsField;
|
||||||
private static VirtualConstructor virtualConstructor;
|
private static VirtualConstructor virtualConstructor;
|
||||||
|
|
||||||
private CodeHeap heap;
|
private CodeHeap heap;
|
||||||
|
@ -49,6 +50,7 @@ public class CodeCache {
|
||||||
Type type = db.lookupType("CodeCache");
|
Type type = db.lookupType("CodeCache");
|
||||||
|
|
||||||
heapField = type.getAddressField("_heap");
|
heapField = type.getAddressField("_heap");
|
||||||
|
scavengeRootNMethodsField = type.getAddressField("_scavenge_root_nmethods");
|
||||||
|
|
||||||
virtualConstructor = new VirtualConstructor(db);
|
virtualConstructor = new VirtualConstructor(db);
|
||||||
// Add mappings for all possible CodeBlob subclasses
|
// Add mappings for all possible CodeBlob subclasses
|
||||||
|
@ -67,6 +69,10 @@ public class CodeCache {
|
||||||
heap = (CodeHeap) VMObjectFactory.newObject(CodeHeap.class, heapField.getValue());
|
heap = (CodeHeap) VMObjectFactory.newObject(CodeHeap.class, heapField.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NMethod scavengeRootMethods() {
|
||||||
|
return (NMethod) VMObjectFactory.newObject(NMethod.class, scavengeRootNMethodsField.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean contains(Address p) {
|
public boolean contains(Address p) {
|
||||||
return getHeap().contains(p);
|
return getHeap().contains(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,10 @@ public class NMethod extends CodeBlob {
|
||||||
/** != InvocationEntryBci if this nmethod is an on-stack replacement method */
|
/** != InvocationEntryBci if this nmethod is an on-stack replacement method */
|
||||||
private static CIntegerField entryBCIField;
|
private static CIntegerField entryBCIField;
|
||||||
/** To support simple linked-list chaining of nmethods */
|
/** To support simple linked-list chaining of nmethods */
|
||||||
private static AddressField linkField;
|
private static AddressField osrLinkField;
|
||||||
|
private static AddressField scavengeRootLinkField;
|
||||||
|
private static CIntegerField scavengeRootStateField;
|
||||||
|
|
||||||
/** Offsets for different nmethod parts */
|
/** Offsets for different nmethod parts */
|
||||||
private static CIntegerField exceptionOffsetField;
|
private static CIntegerField exceptionOffsetField;
|
||||||
private static CIntegerField deoptOffsetField;
|
private static CIntegerField deoptOffsetField;
|
||||||
|
@ -87,7 +90,10 @@ public class NMethod extends CodeBlob {
|
||||||
zombieInstructionSizeField = type.getCIntegerField("_zombie_instruction_size");
|
zombieInstructionSizeField = type.getCIntegerField("_zombie_instruction_size");
|
||||||
methodField = type.getOopField("_method");
|
methodField = type.getOopField("_method");
|
||||||
entryBCIField = type.getCIntegerField("_entry_bci");
|
entryBCIField = type.getCIntegerField("_entry_bci");
|
||||||
linkField = type.getAddressField("_link");
|
osrLinkField = type.getAddressField("_osr_link");
|
||||||
|
scavengeRootLinkField = type.getAddressField("_scavenge_root_link");
|
||||||
|
scavengeRootStateField = type.getCIntegerField("_scavenge_root_state");
|
||||||
|
|
||||||
exceptionOffsetField = type.getCIntegerField("_exception_offset");
|
exceptionOffsetField = type.getCIntegerField("_exception_offset");
|
||||||
deoptOffsetField = type.getCIntegerField("_deoptimize_offset");
|
deoptOffsetField = type.getCIntegerField("_deoptimize_offset");
|
||||||
origPCOffsetField = type.getCIntegerField("_orig_pc_offset");
|
origPCOffsetField = type.getCIntegerField("_orig_pc_offset");
|
||||||
|
@ -219,10 +225,19 @@ public class NMethod extends CodeBlob {
|
||||||
return getEntryBCI();
|
return getEntryBCI();
|
||||||
}
|
}
|
||||||
|
|
||||||
public NMethod getLink() {
|
public NMethod getOSRLink() {
|
||||||
return (NMethod) VMObjectFactory.newObject(NMethod.class, linkField.getValue(addr));
|
return (NMethod) VMObjectFactory.newObject(NMethod.class, osrLinkField.getValue(addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NMethod getScavengeRootLink() {
|
||||||
|
return (NMethod) VMObjectFactory.newObject(NMethod.class, scavengeRootLinkField.getValue(addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getScavengeRootState() {
|
||||||
|
return (int) scavengeRootStateField.getValue(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Tells whether frames described by this nmethod can be
|
/** Tells whether frames described by this nmethod can be
|
||||||
deoptimized. Note: native wrappers cannot be deoptimized. */
|
deoptimized. Note: native wrappers cannot be deoptimized. */
|
||||||
public boolean canBeDeoptimized() { return isJavaMethod(); }
|
public boolean canBeDeoptimized() { return isJavaMethod(); }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2009
|
||||||
|
|
||||||
HS_MAJOR_VER=17
|
HS_MAJOR_VER=17
|
||||||
HS_MINOR_VER=0
|
HS_MINOR_VER=0
|
||||||
HS_BUILD_NUMBER=01
|
HS_BUILD_NUMBER=03
|
||||||
|
|
||||||
JDK_MAJOR_VER=1
|
JDK_MAJOR_VER=1
|
||||||
JDK_MINOR_VER=7
|
JDK_MINOR_VER=7
|
||||||
|
|
|
@ -4676,3 +4676,50 @@ void MacroAssembler::reinit_heapbase() {
|
||||||
load_ptr_contents(base, G6_heapbase);
|
load_ptr_contents(base, G6_heapbase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compare char[] arrays aligned to 4 bytes.
|
||||||
|
void MacroAssembler::char_arrays_equals(Register ary1, Register ary2,
|
||||||
|
Register limit, Register result,
|
||||||
|
Register chr1, Register chr2, Label& Ldone) {
|
||||||
|
Label Lvector, Lloop;
|
||||||
|
assert(chr1 == result, "should be the same");
|
||||||
|
|
||||||
|
// Note: limit contains number of bytes (2*char_elements) != 0.
|
||||||
|
andcc(limit, 0x2, chr1); // trailing character ?
|
||||||
|
br(Assembler::zero, false, Assembler::pt, Lvector);
|
||||||
|
delayed()->nop();
|
||||||
|
|
||||||
|
// compare the trailing char
|
||||||
|
sub(limit, sizeof(jchar), limit);
|
||||||
|
lduh(ary1, limit, chr1);
|
||||||
|
lduh(ary2, limit, chr2);
|
||||||
|
cmp(chr1, chr2);
|
||||||
|
br(Assembler::notEqual, true, Assembler::pt, Ldone);
|
||||||
|
delayed()->mov(G0, result); // not equal
|
||||||
|
|
||||||
|
// only one char ?
|
||||||
|
br_on_reg_cond(rc_z, true, Assembler::pn, limit, Ldone);
|
||||||
|
delayed()->add(G0, 1, result); // zero-length arrays are equal
|
||||||
|
|
||||||
|
// word by word compare, dont't need alignment check
|
||||||
|
bind(Lvector);
|
||||||
|
// Shift ary1 and ary2 to the end of the arrays, negate limit
|
||||||
|
add(ary1, limit, ary1);
|
||||||
|
add(ary2, limit, ary2);
|
||||||
|
neg(limit, limit);
|
||||||
|
|
||||||
|
lduw(ary1, limit, chr1);
|
||||||
|
bind(Lloop);
|
||||||
|
lduw(ary2, limit, chr2);
|
||||||
|
cmp(chr1, chr2);
|
||||||
|
br(Assembler::notEqual, true, Assembler::pt, Ldone);
|
||||||
|
delayed()->mov(G0, result); // not equal
|
||||||
|
inccc(limit, 2*sizeof(jchar));
|
||||||
|
// annul LDUW if branch is not taken to prevent access past end of array
|
||||||
|
br(Assembler::notZero, true, Assembler::pt, Lloop);
|
||||||
|
delayed()->lduw(ary1, limit, chr1); // hoisted
|
||||||
|
|
||||||
|
// Caller should set it:
|
||||||
|
// add(G0, 1, result); // equals
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -2455,6 +2455,11 @@ public:
|
||||||
void inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2);
|
void inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2);
|
||||||
void inc_counter(int* counter_addr, Register Rtmp1, Register Rtmp2);
|
void inc_counter(int* counter_addr, Register Rtmp1, Register Rtmp2);
|
||||||
|
|
||||||
|
// Compare char[] arrays aligned to 4 bytes.
|
||||||
|
void char_arrays_equals(Register ary1, Register ary2,
|
||||||
|
Register limit, Register result,
|
||||||
|
Register chr1, Register chr2, Label& Ldone);
|
||||||
|
|
||||||
#undef VIRTUAL
|
#undef VIRTUAL
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -2171,7 +2171,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
|
||||||
// subtype which we can't check or src is the same array as dst
|
// subtype which we can't check or src is the same array as dst
|
||||||
// but not necessarily exactly of type default_type.
|
// but not necessarily exactly of type default_type.
|
||||||
Label known_ok, halt;
|
Label known_ok, halt;
|
||||||
jobject2reg(op->expected_type()->encoding(), tmp);
|
jobject2reg(op->expected_type()->constant_encoding(), tmp);
|
||||||
__ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2);
|
__ ld_ptr(dst, oopDesc::klass_offset_in_bytes(), tmp2);
|
||||||
if (basic_type != T_OBJECT) {
|
if (basic_type != T_OBJECT) {
|
||||||
__ cmp(tmp, tmp2);
|
__ cmp(tmp, tmp2);
|
||||||
|
@ -2429,7 +2429,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
|
||||||
assert(data->is_BitData(), "need BitData for checkcast");
|
assert(data->is_BitData(), "need BitData for checkcast");
|
||||||
Register mdo = k_RInfo;
|
Register mdo = k_RInfo;
|
||||||
Register data_val = Rtmp1;
|
Register data_val = Rtmp1;
|
||||||
jobject2reg(md->encoding(), mdo);
|
jobject2reg(md->constant_encoding(), mdo);
|
||||||
|
|
||||||
int mdo_offset_bias = 0;
|
int mdo_offset_bias = 0;
|
||||||
if (!Assembler::is_simm13(md->byte_offset_of_slot(data, DataLayout::header_offset()) + data->size_in_bytes())) {
|
if (!Assembler::is_simm13(md->byte_offset_of_slot(data, DataLayout::header_offset()) + data->size_in_bytes())) {
|
||||||
|
@ -2452,7 +2452,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
|
||||||
// patching may screw with our temporaries on sparc,
|
// patching may screw with our temporaries on sparc,
|
||||||
// so let's do it before loading the class
|
// so let's do it before loading the class
|
||||||
if (k->is_loaded()) {
|
if (k->is_loaded()) {
|
||||||
jobject2reg(k->encoding(), k_RInfo);
|
jobject2reg(k->constant_encoding(), k_RInfo);
|
||||||
} else {
|
} else {
|
||||||
jobject2reg_with_patching(k_RInfo, op->info_for_patch());
|
jobject2reg_with_patching(k_RInfo, op->info_for_patch());
|
||||||
}
|
}
|
||||||
|
@ -2513,7 +2513,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
|
||||||
// patching may screw with our temporaries on sparc,
|
// patching may screw with our temporaries on sparc,
|
||||||
// so let's do it before loading the class
|
// so let's do it before loading the class
|
||||||
if (k->is_loaded()) {
|
if (k->is_loaded()) {
|
||||||
jobject2reg(k->encoding(), k_RInfo);
|
jobject2reg(k->constant_encoding(), k_RInfo);
|
||||||
} else {
|
} else {
|
||||||
jobject2reg_with_patching(k_RInfo, op->info_for_patch());
|
jobject2reg_with_patching(k_RInfo, op->info_for_patch());
|
||||||
}
|
}
|
||||||
|
@ -2717,7 +2717,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||||
assert(op->tmp1()->is_single_cpu(), "tmp1 must be allocated");
|
assert(op->tmp1()->is_single_cpu(), "tmp1 must be allocated");
|
||||||
Register mdo = op->mdo()->as_register();
|
Register mdo = op->mdo()->as_register();
|
||||||
Register tmp1 = op->tmp1()->as_register();
|
Register tmp1 = op->tmp1()->as_register();
|
||||||
jobject2reg(md->encoding(), mdo);
|
jobject2reg(md->constant_encoding(), mdo);
|
||||||
int mdo_offset_bias = 0;
|
int mdo_offset_bias = 0;
|
||||||
if (!Assembler::is_simm13(md->byte_offset_of_slot(data, CounterData::count_offset()) +
|
if (!Assembler::is_simm13(md->byte_offset_of_slot(data, CounterData::count_offset()) +
|
||||||
data->size_in_bytes())) {
|
data->size_in_bytes())) {
|
||||||
|
@ -2774,7 +2774,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||||
if (receiver == NULL) {
|
if (receiver == NULL) {
|
||||||
Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)) -
|
Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)) -
|
||||||
mdo_offset_bias);
|
mdo_offset_bias);
|
||||||
jobject2reg(known_klass->encoding(), tmp1);
|
jobject2reg(known_klass->constant_encoding(), tmp1);
|
||||||
__ st_ptr(tmp1, recv_addr);
|
__ st_ptr(tmp1, recv_addr);
|
||||||
Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)) -
|
Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)) -
|
||||||
mdo_offset_bias);
|
mdo_offset_bias);
|
||||||
|
|
|
@ -668,7 +668,7 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
|
||||||
__ add(obj.result(), offset.result(), addr);
|
__ add(obj.result(), offset.result(), addr);
|
||||||
|
|
||||||
if (type == objectType) { // Write-barrier needed for Object fields.
|
if (type == objectType) { // Write-barrier needed for Object fields.
|
||||||
pre_barrier(obj.result(), false, NULL);
|
pre_barrier(addr, false, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == objectType)
|
if (type == objectType)
|
||||||
|
@ -896,7 +896,7 @@ void LIRGenerator::do_NewTypeArray(NewTypeArray* x) {
|
||||||
LIR_Opr len = length.result();
|
LIR_Opr len = length.result();
|
||||||
BasicType elem_type = x->elt_type();
|
BasicType elem_type = x->elt_type();
|
||||||
|
|
||||||
__ oop2reg(ciTypeArrayKlass::make(elem_type)->encoding(), klass_reg);
|
__ oop2reg(ciTypeArrayKlass::make(elem_type)->constant_encoding(), klass_reg);
|
||||||
|
|
||||||
CodeStub* slow_path = new NewTypeArrayStub(klass_reg, len, reg, info);
|
CodeStub* slow_path = new NewTypeArrayStub(klass_reg, len, reg, info);
|
||||||
__ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path);
|
__ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path);
|
||||||
|
|
|
@ -2838,63 +2838,41 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
||||||
enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{
|
enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result) %{
|
||||||
Label Ldone, Lloop;
|
Label Ldone, Lloop;
|
||||||
MacroAssembler _masm(&cbuf);
|
MacroAssembler _masm(&cbuf);
|
||||||
|
|
||||||
Register str1_reg = reg_to_register_object($str1$$reg);
|
Register str1_reg = reg_to_register_object($str1$$reg);
|
||||||
Register str2_reg = reg_to_register_object($str2$$reg);
|
Register str2_reg = reg_to_register_object($str2$$reg);
|
||||||
Register tmp1_reg = reg_to_register_object($tmp1$$reg);
|
Register cnt1_reg = reg_to_register_object($cnt1$$reg);
|
||||||
Register tmp2_reg = reg_to_register_object($tmp2$$reg);
|
Register cnt2_reg = reg_to_register_object($cnt2$$reg);
|
||||||
Register result_reg = reg_to_register_object($result$$reg);
|
Register result_reg = reg_to_register_object($result$$reg);
|
||||||
|
|
||||||
// Get the first character position in both strings
|
assert(result_reg != str1_reg &&
|
||||||
// [8] char array, [12] offset, [16] count
|
result_reg != str2_reg &&
|
||||||
int value_offset = java_lang_String:: value_offset_in_bytes();
|
result_reg != cnt1_reg &&
|
||||||
int offset_offset = java_lang_String::offset_offset_in_bytes();
|
result_reg != cnt2_reg ,
|
||||||
int count_offset = java_lang_String:: count_offset_in_bytes();
|
"need different registers");
|
||||||
|
|
||||||
// load str1 (jchar*) base address into tmp1_reg
|
|
||||||
__ load_heap_oop(str1_reg, value_offset, tmp1_reg);
|
|
||||||
__ ld(str1_reg, offset_offset, result_reg);
|
|
||||||
__ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg);
|
|
||||||
__ ld(str1_reg, count_offset, str1_reg); // hoisted
|
|
||||||
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
|
|
||||||
__ load_heap_oop(str2_reg, value_offset, tmp2_reg); // hoisted
|
|
||||||
__ add(result_reg, tmp1_reg, tmp1_reg);
|
|
||||||
|
|
||||||
// load str2 (jchar*) base address into tmp2_reg
|
|
||||||
// __ ld_ptr(str2_reg, value_offset, tmp2_reg); // hoisted
|
|
||||||
__ ld(str2_reg, offset_offset, result_reg);
|
|
||||||
__ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg);
|
|
||||||
__ ld(str2_reg, count_offset, str2_reg); // hoisted
|
|
||||||
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
|
|
||||||
__ subcc(str1_reg, str2_reg, O7); // hoisted
|
|
||||||
__ add(result_reg, tmp2_reg, tmp2_reg);
|
|
||||||
|
|
||||||
// Compute the minimum of the string lengths(str1_reg) and the
|
// Compute the minimum of the string lengths(str1_reg) and the
|
||||||
// difference of the string lengths (stack)
|
// difference of the string lengths (stack)
|
||||||
|
|
||||||
// discard string base pointers, after loading up the lengths
|
|
||||||
// __ ld(str1_reg, count_offset, str1_reg); // hoisted
|
|
||||||
// __ ld(str2_reg, count_offset, str2_reg); // hoisted
|
|
||||||
|
|
||||||
// See if the lengths are different, and calculate min in str1_reg.
|
// See if the lengths are different, and calculate min in str1_reg.
|
||||||
// Stash diff in O7 in case we need it for a tie-breaker.
|
// Stash diff in O7 in case we need it for a tie-breaker.
|
||||||
Label Lskip;
|
Label Lskip;
|
||||||
// __ subcc(str1_reg, str2_reg, O7); // hoisted
|
__ subcc(cnt1_reg, cnt2_reg, O7);
|
||||||
__ sll(str1_reg, exact_log2(sizeof(jchar)), str1_reg); // scale the limit
|
__ sll(cnt1_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit
|
||||||
__ br(Assembler::greater, true, Assembler::pt, Lskip);
|
__ br(Assembler::greater, true, Assembler::pt, Lskip);
|
||||||
// str2 is shorter, so use its count:
|
// cnt2 is shorter, so use its count:
|
||||||
__ delayed()->sll(str2_reg, exact_log2(sizeof(jchar)), str1_reg); // scale the limit
|
__ delayed()->sll(cnt2_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit
|
||||||
__ bind(Lskip);
|
__ bind(Lskip);
|
||||||
|
|
||||||
// reallocate str1_reg, str2_reg, result_reg
|
// reallocate cnt1_reg, cnt2_reg, result_reg
|
||||||
// Note: limit_reg holds the string length pre-scaled by 2
|
// Note: limit_reg holds the string length pre-scaled by 2
|
||||||
Register limit_reg = str1_reg;
|
Register limit_reg = cnt1_reg;
|
||||||
Register chr2_reg = str2_reg;
|
Register chr2_reg = cnt2_reg;
|
||||||
Register chr1_reg = result_reg;
|
Register chr1_reg = result_reg;
|
||||||
// tmp{12} are the base pointers
|
// str{12} are the base pointers
|
||||||
|
|
||||||
// Is the minimum length zero?
|
// Is the minimum length zero?
|
||||||
__ cmp(limit_reg, (int)(0 * sizeof(jchar))); // use cast to resolve overloading ambiguity
|
__ cmp(limit_reg, (int)(0 * sizeof(jchar))); // use cast to resolve overloading ambiguity
|
||||||
|
@ -2902,8 +2880,8 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||||
__ delayed()->mov(O7, result_reg); // result is difference in lengths
|
__ delayed()->mov(O7, result_reg); // result is difference in lengths
|
||||||
|
|
||||||
// Load first characters
|
// Load first characters
|
||||||
__ lduh(tmp1_reg, 0, chr1_reg);
|
__ lduh(str1_reg, 0, chr1_reg);
|
||||||
__ lduh(tmp2_reg, 0, chr2_reg);
|
__ lduh(str2_reg, 0, chr2_reg);
|
||||||
|
|
||||||
// Compare first characters
|
// Compare first characters
|
||||||
__ subcc(chr1_reg, chr2_reg, chr1_reg);
|
__ subcc(chr1_reg, chr2_reg, chr1_reg);
|
||||||
|
@ -2915,7 +2893,7 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||||
// Check after comparing first character to see if strings are equivalent
|
// Check after comparing first character to see if strings are equivalent
|
||||||
Label LSkip2;
|
Label LSkip2;
|
||||||
// Check if the strings start at same location
|
// Check if the strings start at same location
|
||||||
__ cmp(tmp1_reg, tmp2_reg);
|
__ cmp(str1_reg, str2_reg);
|
||||||
__ brx(Assembler::notEqual, true, Assembler::pt, LSkip2);
|
__ brx(Assembler::notEqual, true, Assembler::pt, LSkip2);
|
||||||
__ delayed()->nop();
|
__ delayed()->nop();
|
||||||
|
|
||||||
|
@ -2932,23 +2910,23 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||||
__ br(Assembler::equal, true, Assembler::pn, Ldone);
|
__ br(Assembler::equal, true, Assembler::pn, Ldone);
|
||||||
__ delayed()->mov(O7, result_reg); // result is difference in lengths
|
__ delayed()->mov(O7, result_reg); // result is difference in lengths
|
||||||
|
|
||||||
// Shift tmp1_reg and tmp2_reg to the end of the arrays, negate limit
|
// Shift str1_reg and str2_reg to the end of the arrays, negate limit
|
||||||
__ add(tmp1_reg, limit_reg, tmp1_reg);
|
__ add(str1_reg, limit_reg, str1_reg);
|
||||||
__ add(tmp2_reg, limit_reg, tmp2_reg);
|
__ add(str2_reg, limit_reg, str2_reg);
|
||||||
__ neg(chr1_reg, limit_reg); // limit = -(limit-2)
|
__ neg(chr1_reg, limit_reg); // limit = -(limit-2)
|
||||||
|
|
||||||
// Compare the rest of the characters
|
// Compare the rest of the characters
|
||||||
__ lduh(tmp1_reg, limit_reg, chr1_reg);
|
__ lduh(str1_reg, limit_reg, chr1_reg);
|
||||||
__ bind(Lloop);
|
__ bind(Lloop);
|
||||||
// __ lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted
|
// __ lduh(str1_reg, limit_reg, chr1_reg); // hoisted
|
||||||
__ lduh(tmp2_reg, limit_reg, chr2_reg);
|
__ lduh(str2_reg, limit_reg, chr2_reg);
|
||||||
__ subcc(chr1_reg, chr2_reg, chr1_reg);
|
__ subcc(chr1_reg, chr2_reg, chr1_reg);
|
||||||
__ br(Assembler::notZero, false, Assembler::pt, Ldone);
|
__ br(Assembler::notZero, false, Assembler::pt, Ldone);
|
||||||
assert(chr1_reg == result_reg, "result must be pre-placed");
|
assert(chr1_reg == result_reg, "result must be pre-placed");
|
||||||
__ delayed()->inccc(limit_reg, sizeof(jchar));
|
__ delayed()->inccc(limit_reg, sizeof(jchar));
|
||||||
// annul LDUH if branch is not taken to prevent access past end of string
|
// annul LDUH if branch is not taken to prevent access past end of string
|
||||||
__ br(Assembler::notZero, true, Assembler::pt, Lloop);
|
__ br(Assembler::notZero, true, Assembler::pt, Lloop);
|
||||||
__ delayed()->lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted
|
__ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted
|
||||||
|
|
||||||
// If strings are equal up to min length, return the length difference.
|
// If strings are equal up to min length, return the length difference.
|
||||||
__ mov(O7, result_reg);
|
__ mov(O7, result_reg);
|
||||||
|
@ -2957,125 +2935,80 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||||
__ bind(Ldone);
|
__ bind(Ldone);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{
|
enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result) %{
|
||||||
Label Lword, Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone;
|
Label Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone;
|
||||||
MacroAssembler _masm(&cbuf);
|
MacroAssembler _masm(&cbuf);
|
||||||
|
|
||||||
Register str1_reg = reg_to_register_object($str1$$reg);
|
Register str1_reg = reg_to_register_object($str1$$reg);
|
||||||
Register str2_reg = reg_to_register_object($str2$$reg);
|
Register str2_reg = reg_to_register_object($str2$$reg);
|
||||||
Register tmp1_reg = reg_to_register_object($tmp1$$reg);
|
Register cnt_reg = reg_to_register_object($cnt$$reg);
|
||||||
Register tmp2_reg = reg_to_register_object($tmp2$$reg);
|
Register tmp1_reg = O7;
|
||||||
Register result_reg = reg_to_register_object($result$$reg);
|
Register result_reg = reg_to_register_object($result$$reg);
|
||||||
|
|
||||||
// Get the first character position in both strings
|
assert(result_reg != str1_reg &&
|
||||||
// [8] char array, [12] offset, [16] count
|
result_reg != str2_reg &&
|
||||||
int value_offset = java_lang_String:: value_offset_in_bytes();
|
result_reg != cnt_reg &&
|
||||||
int offset_offset = java_lang_String::offset_offset_in_bytes();
|
result_reg != tmp1_reg ,
|
||||||
int count_offset = java_lang_String:: count_offset_in_bytes();
|
"need different registers");
|
||||||
|
|
||||||
// load str1 (jchar*) base address into tmp1_reg
|
__ cmp(str1_reg, str2_reg); //same char[] ?
|
||||||
__ load_heap_oop(Address(str1_reg, value_offset), tmp1_reg);
|
|
||||||
__ ld(Address(str1_reg, offset_offset), result_reg);
|
|
||||||
__ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg);
|
|
||||||
__ ld(Address(str1_reg, count_offset), str1_reg); // hoisted
|
|
||||||
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
|
|
||||||
__ load_heap_oop(Address(str2_reg, value_offset), tmp2_reg); // hoisted
|
|
||||||
__ add(result_reg, tmp1_reg, tmp1_reg);
|
|
||||||
|
|
||||||
// load str2 (jchar*) base address into tmp2_reg
|
|
||||||
// __ ld_ptr(Address(str2_reg, value_offset), tmp2_reg); // hoisted
|
|
||||||
__ ld(Address(str2_reg, offset_offset), result_reg);
|
|
||||||
__ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg);
|
|
||||||
__ ld(Address(str2_reg, count_offset), str2_reg); // hoisted
|
|
||||||
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
|
|
||||||
__ cmp(str1_reg, str2_reg); // hoisted
|
|
||||||
__ add(result_reg, tmp2_reg, tmp2_reg);
|
|
||||||
|
|
||||||
__ sll(str1_reg, exact_log2(sizeof(jchar)), str1_reg);
|
|
||||||
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
|
|
||||||
__ delayed()->mov(G0, result_reg); // not equal
|
|
||||||
|
|
||||||
__ br_zero(Assembler::equal, true, Assembler::pn, str1_reg, Ldone);
|
|
||||||
__ delayed()->add(G0, 1, result_reg); //equals
|
|
||||||
|
|
||||||
__ cmp(tmp1_reg, tmp2_reg); //same string ?
|
|
||||||
__ brx(Assembler::equal, true, Assembler::pn, Ldone);
|
__ brx(Assembler::equal, true, Assembler::pn, Ldone);
|
||||||
__ delayed()->add(G0, 1, result_reg);
|
__ delayed()->add(G0, 1, result_reg);
|
||||||
|
|
||||||
|
__ br_on_reg_cond(Assembler::rc_z, true, Assembler::pn, cnt_reg, Ldone);
|
||||||
|
__ delayed()->add(G0, 1, result_reg); // count == 0
|
||||||
|
|
||||||
//rename registers
|
//rename registers
|
||||||
Register limit_reg = str1_reg;
|
Register limit_reg = cnt_reg;
|
||||||
Register chr2_reg = str2_reg;
|
|
||||||
Register chr1_reg = result_reg;
|
Register chr1_reg = result_reg;
|
||||||
// tmp{12} are the base pointers
|
Register chr2_reg = tmp1_reg;
|
||||||
|
|
||||||
//check for alignment and position the pointers to the ends
|
//check for alignment and position the pointers to the ends
|
||||||
__ or3(tmp1_reg, tmp2_reg, chr1_reg);
|
__ or3(str1_reg, str2_reg, chr1_reg);
|
||||||
__ andcc(chr1_reg, 0x3, chr1_reg); // notZero means at least one not 4-byte aligned
|
__ andcc(chr1_reg, 0x3, chr1_reg);
|
||||||
__ br(Assembler::notZero, false, Assembler::pn, Lchar);
|
// notZero means at least one not 4-byte aligned.
|
||||||
__ delayed()->nop();
|
// We could optimize the case when both arrays are not aligned
|
||||||
|
// but it is not frequent case and it requires additional checks.
|
||||||
|
__ br(Assembler::notZero, false, Assembler::pn, Lchar); // char by char compare
|
||||||
|
__ delayed()->sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); // set byte count
|
||||||
|
|
||||||
__ bind(Lword);
|
// Compare char[] arrays aligned to 4 bytes.
|
||||||
__ and3(limit_reg, 0x2, O7); //remember the remainder (either 0 or 2)
|
__ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg,
|
||||||
__ andn(limit_reg, 0x3, limit_reg);
|
chr1_reg, chr2_reg, Ldone);
|
||||||
__ br_zero(Assembler::zero, false, Assembler::pn, limit_reg, Lpost_word);
|
|
||||||
__ delayed()->nop();
|
|
||||||
|
|
||||||
__ add(tmp1_reg, limit_reg, tmp1_reg);
|
|
||||||
__ add(tmp2_reg, limit_reg, tmp2_reg);
|
|
||||||
__ neg(limit_reg);
|
|
||||||
|
|
||||||
__ lduw(tmp1_reg, limit_reg, chr1_reg);
|
|
||||||
__ bind(Lword_loop);
|
|
||||||
__ lduw(tmp2_reg, limit_reg, chr2_reg);
|
|
||||||
__ cmp(chr1_reg, chr2_reg);
|
|
||||||
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
|
|
||||||
__ delayed()->mov(G0, result_reg);
|
|
||||||
__ inccc(limit_reg, 2*sizeof(jchar));
|
|
||||||
// annul LDUW if branch i s not taken to prevent access past end of string
|
|
||||||
__ br(Assembler::notZero, true, Assembler::pt, Lword_loop); //annul on taken
|
|
||||||
__ delayed()->lduw(tmp1_reg, limit_reg, chr1_reg); // hoisted
|
|
||||||
|
|
||||||
__ bind(Lpost_word);
|
|
||||||
__ br_zero(Assembler::zero, true, Assembler::pt, O7, Ldone);
|
|
||||||
__ delayed()->add(G0, 1, result_reg);
|
|
||||||
|
|
||||||
__ lduh(tmp1_reg, 0, chr1_reg);
|
|
||||||
__ lduh(tmp2_reg, 0, chr2_reg);
|
|
||||||
__ cmp (chr1_reg, chr2_reg);
|
|
||||||
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
|
|
||||||
__ delayed()->mov(G0, result_reg);
|
|
||||||
__ ba(false,Ldone);
|
__ ba(false,Ldone);
|
||||||
__ delayed()->add(G0, 1, result_reg);
|
__ delayed()->add(G0, 1, result_reg);
|
||||||
|
|
||||||
|
// char by char compare
|
||||||
__ bind(Lchar);
|
__ bind(Lchar);
|
||||||
__ add(tmp1_reg, limit_reg, tmp1_reg);
|
__ add(str1_reg, limit_reg, str1_reg);
|
||||||
__ add(tmp2_reg, limit_reg, tmp2_reg);
|
__ add(str2_reg, limit_reg, str2_reg);
|
||||||
__ neg(limit_reg); //negate count
|
__ neg(limit_reg); //negate count
|
||||||
|
|
||||||
__ lduh(tmp1_reg, limit_reg, chr1_reg);
|
__ lduh(str1_reg, limit_reg, chr1_reg);
|
||||||
|
// Lchar_loop
|
||||||
__ bind(Lchar_loop);
|
__ bind(Lchar_loop);
|
||||||
__ lduh(tmp2_reg, limit_reg, chr2_reg);
|
__ lduh(str2_reg, limit_reg, chr2_reg);
|
||||||
__ cmp(chr1_reg, chr2_reg);
|
__ cmp(chr1_reg, chr2_reg);
|
||||||
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
|
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
|
||||||
__ delayed()->mov(G0, result_reg); //not equal
|
__ delayed()->mov(G0, result_reg); //not equal
|
||||||
__ inccc(limit_reg, sizeof(jchar));
|
__ inccc(limit_reg, sizeof(jchar));
|
||||||
// annul LDUH if branch is not taken to prevent access past end of string
|
// annul LDUH if branch is not taken to prevent access past end of string
|
||||||
__ br(Assembler::notZero, true, Assembler::pt, Lchar_loop); //annul on taken
|
__ br(Assembler::notZero, true, Assembler::pt, Lchar_loop);
|
||||||
__ delayed()->lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted
|
__ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted
|
||||||
|
|
||||||
__ add(G0, 1, result_reg); //equal
|
__ add(G0, 1, result_reg); //equal
|
||||||
|
|
||||||
__ bind(Ldone);
|
__ bind(Ldone);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{
|
enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, notemp_iRegI result) %{
|
||||||
Label Lvector, Ldone, Lloop;
|
Label Lvector, Ldone, Lloop;
|
||||||
MacroAssembler _masm(&cbuf);
|
MacroAssembler _masm(&cbuf);
|
||||||
|
|
||||||
Register ary1_reg = reg_to_register_object($ary1$$reg);
|
Register ary1_reg = reg_to_register_object($ary1$$reg);
|
||||||
Register ary2_reg = reg_to_register_object($ary2$$reg);
|
Register ary2_reg = reg_to_register_object($ary2$$reg);
|
||||||
Register tmp1_reg = reg_to_register_object($tmp1$$reg);
|
Register tmp1_reg = reg_to_register_object($tmp1$$reg);
|
||||||
Register tmp2_reg = reg_to_register_object($tmp2$$reg);
|
Register tmp2_reg = O7;
|
||||||
Register result_reg = reg_to_register_object($result$$reg);
|
Register result_reg = reg_to_register_object($result$$reg);
|
||||||
|
|
||||||
int length_offset = arrayOopDesc::length_offset_in_bytes();
|
int length_offset = arrayOopDesc::length_offset_in_bytes();
|
||||||
|
@ -3101,7 +3034,7 @@ enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, n
|
||||||
__ br(Assembler::notEqual, true, Assembler::pn, Ldone);
|
__ br(Assembler::notEqual, true, Assembler::pn, Ldone);
|
||||||
__ delayed()->mov(G0, result_reg); // not equal
|
__ delayed()->mov(G0, result_reg); // not equal
|
||||||
|
|
||||||
__ br_zero(Assembler::zero, true, Assembler::pn, tmp1_reg, Ldone);
|
__ br_on_reg_cond(Assembler::rc_z, true, Assembler::pn, tmp1_reg, Ldone);
|
||||||
__ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal
|
__ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal
|
||||||
|
|
||||||
// load array addresses
|
// load array addresses
|
||||||
|
@ -3109,45 +3042,16 @@ enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, n
|
||||||
__ add(ary2_reg, base_offset, ary2_reg);
|
__ add(ary2_reg, base_offset, ary2_reg);
|
||||||
|
|
||||||
// renaming registers
|
// renaming registers
|
||||||
Register chr1_reg = tmp2_reg; // for characters in ary1
|
Register chr1_reg = result_reg; // for characters in ary1
|
||||||
Register chr2_reg = result_reg; // for characters in ary2
|
Register chr2_reg = tmp2_reg; // for characters in ary2
|
||||||
Register limit_reg = tmp1_reg; // length
|
Register limit_reg = tmp1_reg; // length
|
||||||
|
|
||||||
// set byte count
|
// set byte count
|
||||||
__ sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg);
|
__ sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg);
|
||||||
__ andcc(limit_reg, 0x2, chr1_reg); //trailing character ?
|
|
||||||
__ br(Assembler::zero, false, Assembler::pt, Lvector);
|
|
||||||
__ delayed()->nop();
|
|
||||||
|
|
||||||
//compare the trailing char
|
|
||||||
__ sub(limit_reg, sizeof(jchar), limit_reg);
|
|
||||||
__ lduh(ary1_reg, limit_reg, chr1_reg);
|
|
||||||
__ lduh(ary2_reg, limit_reg, chr2_reg);
|
|
||||||
__ cmp(chr1_reg, chr2_reg);
|
|
||||||
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
|
|
||||||
__ delayed()->mov(G0, result_reg); // not equal
|
|
||||||
|
|
||||||
// only one char ?
|
|
||||||
__ br_zero(Assembler::zero, true, Assembler::pn, limit_reg, Ldone);
|
|
||||||
__ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal
|
|
||||||
|
|
||||||
__ bind(Lvector);
|
|
||||||
// Shift ary1_reg and ary2_reg to the end of the arrays, negate limit
|
|
||||||
__ add(ary1_reg, limit_reg, ary1_reg);
|
|
||||||
__ add(ary2_reg, limit_reg, ary2_reg);
|
|
||||||
__ neg(limit_reg, limit_reg);
|
|
||||||
|
|
||||||
__ lduw(ary1_reg, limit_reg, chr1_reg);
|
|
||||||
__ bind(Lloop);
|
|
||||||
__ lduw(ary2_reg, limit_reg, chr2_reg);
|
|
||||||
__ cmp(chr1_reg, chr2_reg);
|
|
||||||
__ br(Assembler::notEqual, false, Assembler::pt, Ldone);
|
|
||||||
__ delayed()->mov(G0, result_reg); // not equal
|
|
||||||
__ inccc(limit_reg, 2*sizeof(jchar));
|
|
||||||
// annul LDUW if branch is not taken to prevent access past end of string
|
|
||||||
__ br(Assembler::notZero, true, Assembler::pt, Lloop); //annul on taken
|
|
||||||
__ delayed()->lduw(ary1_reg, limit_reg, chr1_reg); // hoisted
|
|
||||||
|
|
||||||
|
// Compare char[] arrays aligned to 4 bytes.
|
||||||
|
__ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg,
|
||||||
|
chr1_reg, chr2_reg, Ldone);
|
||||||
__ add(G0, 1, result_reg); // equals
|
__ add(G0, 1, result_reg); // equals
|
||||||
|
|
||||||
__ bind(Ldone);
|
__ bind(Ldone);
|
||||||
|
@ -9471,33 +9375,33 @@ instruct clear_array(iRegX cnt, iRegP base, iRegX temp, Universe dummy, flagsReg
|
||||||
ins_pipe(long_memory_op);
|
ins_pipe(long_memory_op);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result,
|
instruct string_compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
|
||||||
o7RegI tmp3, flagsReg ccr) %{
|
o7RegI tmp, flagsReg ccr) %{
|
||||||
match(Set result (StrComp str1 str2));
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3);
|
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp);
|
||||||
ins_cost(300);
|
ins_cost(300);
|
||||||
format %{ "String Compare $str1,$str2 -> $result" %}
|
format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %}
|
||||||
ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, result) );
|
ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result) );
|
||||||
ins_pipe(long_memory_op);
|
ins_pipe(long_memory_op);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct string_equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result,
|
instruct string_equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result,
|
||||||
o7RegI tmp3, flagsReg ccr) %{
|
o7RegI tmp, flagsReg ccr) %{
|
||||||
match(Set result (StrEquals str1 str2));
|
match(Set result (StrEquals (Binary str1 str2) cnt));
|
||||||
effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3);
|
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr);
|
||||||
ins_cost(300);
|
ins_cost(300);
|
||||||
format %{ "String Equals $str1,$str2 -> $result" %}
|
format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %}
|
||||||
ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, result) );
|
ins_encode( enc_String_Equals(str1, str2, cnt, result) );
|
||||||
ins_pipe(long_memory_op);
|
ins_pipe(long_memory_op);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result,
|
instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result,
|
||||||
flagsReg ccr) %{
|
o7RegI tmp2, flagsReg ccr) %{
|
||||||
match(Set result (AryEq ary1 ary2));
|
match(Set result (AryEq ary1 ary2));
|
||||||
effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr);
|
effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr);
|
||||||
ins_cost(300);
|
ins_cost(300);
|
||||||
format %{ "Array Equals $ary1,$ary2 -> $result" %}
|
format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1,$tmp2" %}
|
||||||
ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result));
|
ins_encode( enc_Array_Equals(ary1, ary2, tmp1, result));
|
||||||
ins_pipe(long_memory_op);
|
ins_pipe(long_memory_op);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
|
@ -8404,6 +8404,319 @@ void MacroAssembler::reinit_heapbase() {
|
||||||
}
|
}
|
||||||
#endif // _LP64
|
#endif // _LP64
|
||||||
|
|
||||||
|
// IndexOf substring.
|
||||||
|
void MacroAssembler::string_indexof(Register str1, Register str2,
|
||||||
|
Register cnt1, Register cnt2, Register result,
|
||||||
|
XMMRegister vec, Register tmp) {
|
||||||
|
assert(UseSSE42Intrinsics, "SSE4.2 is required");
|
||||||
|
|
||||||
|
Label RELOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR,
|
||||||
|
SCAN_SUBSTR, RET_NOT_FOUND, CLEANUP;
|
||||||
|
|
||||||
|
push(str1); // string addr
|
||||||
|
push(str2); // substr addr
|
||||||
|
push(cnt2); // substr count
|
||||||
|
jmpb(PREP_FOR_SCAN);
|
||||||
|
|
||||||
|
// Substr count saved at sp
|
||||||
|
// Substr saved at sp+1*wordSize
|
||||||
|
// String saved at sp+2*wordSize
|
||||||
|
|
||||||
|
// Reload substr for rescan
|
||||||
|
bind(RELOAD_SUBSTR);
|
||||||
|
movl(cnt2, Address(rsp, 0));
|
||||||
|
movptr(str2, Address(rsp, wordSize));
|
||||||
|
// We came here after the beginninig of the substring was
|
||||||
|
// matched but the rest of it was not so we need to search
|
||||||
|
// again. Start from the next element after the previous match.
|
||||||
|
subptr(str1, result); // Restore counter
|
||||||
|
shrl(str1, 1);
|
||||||
|
addl(cnt1, str1);
|
||||||
|
lea(str1, Address(result, 2)); // Reload string
|
||||||
|
|
||||||
|
// Load substr
|
||||||
|
bind(PREP_FOR_SCAN);
|
||||||
|
movdqu(vec, Address(str2, 0));
|
||||||
|
addl(cnt1, 8); // prime the loop
|
||||||
|
subptr(str1, 16);
|
||||||
|
|
||||||
|
// Scan string for substr in 16-byte vectors
|
||||||
|
bind(SCAN_TO_SUBSTR);
|
||||||
|
subl(cnt1, 8);
|
||||||
|
addptr(str1, 16);
|
||||||
|
|
||||||
|
// pcmpestri
|
||||||
|
// inputs:
|
||||||
|
// xmm - substring
|
||||||
|
// rax - substring length (elements count)
|
||||||
|
// mem - scaned string
|
||||||
|
// rdx - string length (elements count)
|
||||||
|
// 0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
|
||||||
|
// outputs:
|
||||||
|
// rcx - matched index in string
|
||||||
|
assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri");
|
||||||
|
|
||||||
|
pcmpestri(vec, Address(str1, 0), 0x0d);
|
||||||
|
jcc(Assembler::above, SCAN_TO_SUBSTR); // CF == 0 && ZF == 0
|
||||||
|
jccb(Assembler::aboveEqual, RET_NOT_FOUND); // CF == 0
|
||||||
|
|
||||||
|
// Fallthrough: found a potential substr
|
||||||
|
|
||||||
|
// Make sure string is still long enough
|
||||||
|
subl(cnt1, tmp);
|
||||||
|
cmpl(cnt1, cnt2);
|
||||||
|
jccb(Assembler::negative, RET_NOT_FOUND);
|
||||||
|
// Compute start addr of substr
|
||||||
|
lea(str1, Address(str1, tmp, Address::times_2));
|
||||||
|
movptr(result, str1); // save
|
||||||
|
|
||||||
|
// Compare potential substr
|
||||||
|
addl(cnt1, 8); // prime the loop
|
||||||
|
addl(cnt2, 8);
|
||||||
|
subptr(str1, 16);
|
||||||
|
subptr(str2, 16);
|
||||||
|
|
||||||
|
// Scan 16-byte vectors of string and substr
|
||||||
|
bind(SCAN_SUBSTR);
|
||||||
|
subl(cnt1, 8);
|
||||||
|
subl(cnt2, 8);
|
||||||
|
addptr(str1, 16);
|
||||||
|
addptr(str2, 16);
|
||||||
|
movdqu(vec, Address(str2, 0));
|
||||||
|
pcmpestri(vec, Address(str1, 0), 0x0d);
|
||||||
|
jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0
|
||||||
|
jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0
|
||||||
|
|
||||||
|
// Compute substr offset
|
||||||
|
subptr(result, Address(rsp, 2*wordSize));
|
||||||
|
shrl(result, 1); // index
|
||||||
|
jmpb(CLEANUP);
|
||||||
|
|
||||||
|
bind(RET_NOT_FOUND);
|
||||||
|
movl(result, -1);
|
||||||
|
|
||||||
|
bind(CLEANUP);
|
||||||
|
addptr(rsp, 3*wordSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare strings.
|
||||||
|
void MacroAssembler::string_compare(Register str1, Register str2,
|
||||||
|
Register cnt1, Register cnt2, Register result,
|
||||||
|
XMMRegister vec1, XMMRegister vec2) {
|
||||||
|
Label LENGTH_DIFF_LABEL, POP_LABEL, DONE_LABEL, WHILE_HEAD_LABEL;
|
||||||
|
|
||||||
|
// Compute the minimum of the string lengths and the
|
||||||
|
// difference of the string lengths (stack).
|
||||||
|
// Do the conditional move stuff
|
||||||
|
movl(result, cnt1);
|
||||||
|
subl(cnt1, cnt2);
|
||||||
|
push(cnt1);
|
||||||
|
if (VM_Version::supports_cmov()) {
|
||||||
|
cmovl(Assembler::lessEqual, cnt2, result);
|
||||||
|
} else {
|
||||||
|
Label GT_LABEL;
|
||||||
|
jccb(Assembler::greater, GT_LABEL);
|
||||||
|
movl(cnt2, result);
|
||||||
|
bind(GT_LABEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the minimum length zero?
|
||||||
|
testl(cnt2, cnt2);
|
||||||
|
jcc(Assembler::zero, LENGTH_DIFF_LABEL);
|
||||||
|
|
||||||
|
// Load first characters
|
||||||
|
load_unsigned_short(result, Address(str1, 0));
|
||||||
|
load_unsigned_short(cnt1, Address(str2, 0));
|
||||||
|
|
||||||
|
// Compare first characters
|
||||||
|
subl(result, cnt1);
|
||||||
|
jcc(Assembler::notZero, POP_LABEL);
|
||||||
|
decrementl(cnt2);
|
||||||
|
jcc(Assembler::zero, LENGTH_DIFF_LABEL);
|
||||||
|
|
||||||
|
{
|
||||||
|
// Check after comparing first character to see if strings are equivalent
|
||||||
|
Label LSkip2;
|
||||||
|
// Check if the strings start at same location
|
||||||
|
cmpptr(str1, str2);
|
||||||
|
jccb(Assembler::notEqual, LSkip2);
|
||||||
|
|
||||||
|
// Check if the length difference is zero (from stack)
|
||||||
|
cmpl(Address(rsp, 0), 0x0);
|
||||||
|
jcc(Assembler::equal, LENGTH_DIFF_LABEL);
|
||||||
|
|
||||||
|
// Strings might not be equivalent
|
||||||
|
bind(LSkip2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Advance to next character
|
||||||
|
addptr(str1, 2);
|
||||||
|
addptr(str2, 2);
|
||||||
|
|
||||||
|
if (UseSSE42Intrinsics) {
|
||||||
|
// With SSE4.2, use double quad vector compare
|
||||||
|
Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL;
|
||||||
|
// Setup to compare 16-byte vectors
|
||||||
|
movl(cnt1, cnt2);
|
||||||
|
andl(cnt2, 0xfffffff8); // cnt2 holds the vector count
|
||||||
|
andl(cnt1, 0x00000007); // cnt1 holds the tail count
|
||||||
|
testl(cnt2, cnt2);
|
||||||
|
jccb(Assembler::zero, COMPARE_TAIL);
|
||||||
|
|
||||||
|
lea(str2, Address(str2, cnt2, Address::times_2));
|
||||||
|
lea(str1, Address(str1, cnt2, Address::times_2));
|
||||||
|
negptr(cnt2);
|
||||||
|
|
||||||
|
bind(COMPARE_VECTORS);
|
||||||
|
movdqu(vec1, Address(str1, cnt2, Address::times_2));
|
||||||
|
movdqu(vec2, Address(str2, cnt2, Address::times_2));
|
||||||
|
pxor(vec1, vec2);
|
||||||
|
ptest(vec1, vec1);
|
||||||
|
jccb(Assembler::notZero, VECTOR_NOT_EQUAL);
|
||||||
|
addptr(cnt2, 8);
|
||||||
|
jcc(Assembler::notZero, COMPARE_VECTORS);
|
||||||
|
jmpb(COMPARE_TAIL);
|
||||||
|
|
||||||
|
// Mismatched characters in the vectors
|
||||||
|
bind(VECTOR_NOT_EQUAL);
|
||||||
|
lea(str1, Address(str1, cnt2, Address::times_2));
|
||||||
|
lea(str2, Address(str2, cnt2, Address::times_2));
|
||||||
|
movl(cnt1, 8);
|
||||||
|
|
||||||
|
// Compare tail (< 8 chars), or rescan last vectors to
|
||||||
|
// find 1st mismatched characters
|
||||||
|
bind(COMPARE_TAIL);
|
||||||
|
testl(cnt1, cnt1);
|
||||||
|
jccb(Assembler::zero, LENGTH_DIFF_LABEL);
|
||||||
|
movl(cnt2, cnt1);
|
||||||
|
// Fallthru to tail compare
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shift str2 and str1 to the end of the arrays, negate min
|
||||||
|
lea(str1, Address(str1, cnt2, Address::times_2, 0));
|
||||||
|
lea(str2, Address(str2, cnt2, Address::times_2, 0));
|
||||||
|
negptr(cnt2);
|
||||||
|
|
||||||
|
// Compare the rest of the characters
|
||||||
|
bind(WHILE_HEAD_LABEL);
|
||||||
|
load_unsigned_short(result, Address(str1, cnt2, Address::times_2, 0));
|
||||||
|
load_unsigned_short(cnt1, Address(str2, cnt2, Address::times_2, 0));
|
||||||
|
subl(result, cnt1);
|
||||||
|
jccb(Assembler::notZero, POP_LABEL);
|
||||||
|
increment(cnt2);
|
||||||
|
jcc(Assembler::notZero, WHILE_HEAD_LABEL);
|
||||||
|
|
||||||
|
// Strings are equal up to min length. Return the length difference.
|
||||||
|
bind(LENGTH_DIFF_LABEL);
|
||||||
|
pop(result);
|
||||||
|
jmpb(DONE_LABEL);
|
||||||
|
|
||||||
|
// Discard the stored length difference
|
||||||
|
bind(POP_LABEL);
|
||||||
|
addptr(rsp, wordSize);
|
||||||
|
|
||||||
|
// That's it
|
||||||
|
bind(DONE_LABEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare char[] arrays aligned to 4 bytes or substrings.
|
||||||
|
void MacroAssembler::char_arrays_equals(bool is_array_equ, Register ary1, Register ary2,
|
||||||
|
Register limit, Register result, Register chr,
|
||||||
|
XMMRegister vec1, XMMRegister vec2) {
|
||||||
|
Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR;
|
||||||
|
|
||||||
|
int length_offset = arrayOopDesc::length_offset_in_bytes();
|
||||||
|
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
|
||||||
|
|
||||||
|
// Check the input args
|
||||||
|
cmpptr(ary1, ary2);
|
||||||
|
jcc(Assembler::equal, TRUE_LABEL);
|
||||||
|
|
||||||
|
if (is_array_equ) {
|
||||||
|
// Need additional checks for arrays_equals.
|
||||||
|
andptr(ary1, ary2);
|
||||||
|
jcc(Assembler::zero, FALSE_LABEL); // One pointer is NULL
|
||||||
|
|
||||||
|
// Check the lengths
|
||||||
|
movl(limit, Address(ary1, length_offset));
|
||||||
|
cmpl(limit, Address(ary2, length_offset));
|
||||||
|
jcc(Assembler::notEqual, FALSE_LABEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// count == 0
|
||||||
|
testl(limit, limit);
|
||||||
|
jcc(Assembler::zero, TRUE_LABEL);
|
||||||
|
|
||||||
|
if (is_array_equ) {
|
||||||
|
// Load array address
|
||||||
|
lea(ary1, Address(ary1, base_offset));
|
||||||
|
lea(ary2, Address(ary2, base_offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
shll(limit, 1); // byte count != 0
|
||||||
|
movl(result, limit); // copy
|
||||||
|
|
||||||
|
if (UseSSE42Intrinsics) {
|
||||||
|
// With SSE4.2, use double quad vector compare
|
||||||
|
Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
|
||||||
|
// Compare 16-byte vectors
|
||||||
|
andl(result, 0x0000000e); // tail count (in bytes)
|
||||||
|
andl(limit, 0xfffffff0); // vector count (in bytes)
|
||||||
|
jccb(Assembler::zero, COMPARE_TAIL);
|
||||||
|
|
||||||
|
lea(ary1, Address(ary1, limit, Address::times_1));
|
||||||
|
lea(ary2, Address(ary2, limit, Address::times_1));
|
||||||
|
negptr(limit);
|
||||||
|
|
||||||
|
bind(COMPARE_WIDE_VECTORS);
|
||||||
|
movdqu(vec1, Address(ary1, limit, Address::times_1));
|
||||||
|
movdqu(vec2, Address(ary2, limit, Address::times_1));
|
||||||
|
pxor(vec1, vec2);
|
||||||
|
ptest(vec1, vec1);
|
||||||
|
jccb(Assembler::notZero, FALSE_LABEL);
|
||||||
|
addptr(limit, 16);
|
||||||
|
jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
|
||||||
|
|
||||||
|
bind(COMPARE_TAIL); // limit is zero
|
||||||
|
movl(limit, result);
|
||||||
|
// Fallthru to tail compare
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare 4-byte vectors
|
||||||
|
andl(limit, 0xfffffffc); // vector count (in bytes)
|
||||||
|
jccb(Assembler::zero, COMPARE_CHAR);
|
||||||
|
|
||||||
|
lea(ary1, Address(ary1, limit, Address::times_1));
|
||||||
|
lea(ary2, Address(ary2, limit, Address::times_1));
|
||||||
|
negptr(limit);
|
||||||
|
|
||||||
|
bind(COMPARE_VECTORS);
|
||||||
|
movl(chr, Address(ary1, limit, Address::times_1));
|
||||||
|
cmpl(chr, Address(ary2, limit, Address::times_1));
|
||||||
|
jccb(Assembler::notEqual, FALSE_LABEL);
|
||||||
|
addptr(limit, 4);
|
||||||
|
jcc(Assembler::notZero, COMPARE_VECTORS);
|
||||||
|
|
||||||
|
// Compare trailing char (final 2 bytes), if any
|
||||||
|
bind(COMPARE_CHAR);
|
||||||
|
testl(result, 0x2); // tail char
|
||||||
|
jccb(Assembler::zero, TRUE_LABEL);
|
||||||
|
load_unsigned_short(chr, Address(ary1, 0));
|
||||||
|
load_unsigned_short(limit, Address(ary2, 0));
|
||||||
|
cmpl(chr, limit);
|
||||||
|
jccb(Assembler::notEqual, FALSE_LABEL);
|
||||||
|
|
||||||
|
bind(TRUE_LABEL);
|
||||||
|
movl(result, 1); // return true
|
||||||
|
jmpb(DONE);
|
||||||
|
|
||||||
|
bind(FALSE_LABEL);
|
||||||
|
xorl(result, result); // return false
|
||||||
|
|
||||||
|
// That's it
|
||||||
|
bind(DONE);
|
||||||
|
}
|
||||||
|
|
||||||
Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) {
|
Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) {
|
||||||
switch (cond) {
|
switch (cond) {
|
||||||
// Note some conditions are synonyms for others
|
// Note some conditions are synonyms for others
|
||||||
|
|
|
@ -2206,6 +2206,20 @@ public:
|
||||||
void movl2ptr(Register dst, Address src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(movl(dst, src)); }
|
void movl2ptr(Register dst, Address src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(movl(dst, src)); }
|
||||||
void movl2ptr(Register dst, Register src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(if (dst != src) movl(dst, src)); }
|
void movl2ptr(Register dst, Register src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(if (dst != src) movl(dst, src)); }
|
||||||
|
|
||||||
|
// IndexOf strings.
|
||||||
|
void string_indexof(Register str1, Register str2,
|
||||||
|
Register cnt1, Register cnt2, Register result,
|
||||||
|
XMMRegister vec, Register tmp);
|
||||||
|
|
||||||
|
// Compare strings.
|
||||||
|
void string_compare(Register str1, Register str2,
|
||||||
|
Register cnt1, Register cnt2, Register result,
|
||||||
|
XMMRegister vec1, XMMRegister vec2);
|
||||||
|
|
||||||
|
// Compare char[] arrays.
|
||||||
|
void char_arrays_equals(bool is_array_equ, Register ary1, Register ary2,
|
||||||
|
Register limit, Register result, Register chr,
|
||||||
|
XMMRegister vec1, XMMRegister vec2);
|
||||||
|
|
||||||
#undef VIRTUAL
|
#undef VIRTUAL
|
||||||
|
|
||||||
|
|
|
@ -1638,7 +1638,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
|
||||||
jobject2reg_with_patching(k_RInfo, op->info_for_patch());
|
jobject2reg_with_patching(k_RInfo, op->info_for_patch());
|
||||||
} else {
|
} else {
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
__ movoop(k_RInfo, k->encoding());
|
__ movoop(k_RInfo, k->constant_encoding());
|
||||||
#else
|
#else
|
||||||
k_RInfo = noreg;
|
k_RInfo = noreg;
|
||||||
#endif // _LP64
|
#endif // _LP64
|
||||||
|
@ -1661,7 +1661,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
|
||||||
assert(data != NULL, "need data for checkcast");
|
assert(data != NULL, "need data for checkcast");
|
||||||
assert(data->is_BitData(), "need BitData for checkcast");
|
assert(data->is_BitData(), "need BitData for checkcast");
|
||||||
Register mdo = klass_RInfo;
|
Register mdo = klass_RInfo;
|
||||||
__ movoop(mdo, md->encoding());
|
__ movoop(mdo, md->constant_encoding());
|
||||||
Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset()));
|
Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset()));
|
||||||
int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant());
|
int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant());
|
||||||
__ orl(data_addr, header_bits);
|
__ orl(data_addr, header_bits);
|
||||||
|
@ -1679,7 +1679,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
__ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
|
__ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
|
||||||
#else
|
#else
|
||||||
__ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->encoding());
|
__ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding());
|
||||||
#endif // _LP64
|
#endif // _LP64
|
||||||
} else {
|
} else {
|
||||||
__ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
|
__ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
|
||||||
|
@ -1696,7 +1696,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
__ cmpptr(k_RInfo, Address(klass_RInfo, k->super_check_offset()));
|
__ cmpptr(k_RInfo, Address(klass_RInfo, k->super_check_offset()));
|
||||||
#else
|
#else
|
||||||
__ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->encoding());
|
__ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->constant_encoding());
|
||||||
#endif // _LP64
|
#endif // _LP64
|
||||||
if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) {
|
if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) {
|
||||||
__ jcc(Assembler::notEqual, *stub->entry());
|
__ jcc(Assembler::notEqual, *stub->entry());
|
||||||
|
@ -1707,7 +1707,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
__ cmpptr(klass_RInfo, k_RInfo);
|
__ cmpptr(klass_RInfo, k_RInfo);
|
||||||
#else
|
#else
|
||||||
__ cmpoop(klass_RInfo, k->encoding());
|
__ cmpoop(klass_RInfo, k->constant_encoding());
|
||||||
#endif // _LP64
|
#endif // _LP64
|
||||||
__ jcc(Assembler::equal, done);
|
__ jcc(Assembler::equal, done);
|
||||||
|
|
||||||
|
@ -1715,7 +1715,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
__ push(k_RInfo);
|
__ push(k_RInfo);
|
||||||
#else
|
#else
|
||||||
__ pushoop(k->encoding());
|
__ pushoop(k->constant_encoding());
|
||||||
#endif // _LP64
|
#endif // _LP64
|
||||||
__ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
|
__ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
|
||||||
__ pop(klass_RInfo);
|
__ pop(klass_RInfo);
|
||||||
|
@ -1763,7 +1763,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
|
||||||
if (!k->is_loaded()) {
|
if (!k->is_loaded()) {
|
||||||
jobject2reg_with_patching(k_RInfo, op->info_for_patch());
|
jobject2reg_with_patching(k_RInfo, op->info_for_patch());
|
||||||
} else {
|
} else {
|
||||||
LP64_ONLY(__ movoop(k_RInfo, k->encoding()));
|
LP64_ONLY(__ movoop(k_RInfo, k->constant_encoding()));
|
||||||
}
|
}
|
||||||
assert(obj != k_RInfo, "must be different");
|
assert(obj != k_RInfo, "must be different");
|
||||||
|
|
||||||
|
@ -1774,7 +1774,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
|
||||||
// get object class
|
// get object class
|
||||||
// not a safepoint as obj null check happens earlier
|
// not a safepoint as obj null check happens earlier
|
||||||
if (LP64_ONLY(false &&) k->is_loaded()) {
|
if (LP64_ONLY(false &&) k->is_loaded()) {
|
||||||
NOT_LP64(__ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->encoding()));
|
NOT_LP64(__ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding()));
|
||||||
k_RInfo = noreg;
|
k_RInfo = noreg;
|
||||||
} else {
|
} else {
|
||||||
__ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
|
__ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
|
||||||
|
@ -1791,14 +1791,14 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
|
||||||
#ifndef _LP64
|
#ifndef _LP64
|
||||||
if (k->is_loaded()) {
|
if (k->is_loaded()) {
|
||||||
// See if we get an immediate positive hit
|
// See if we get an immediate positive hit
|
||||||
__ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->encoding());
|
__ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->constant_encoding());
|
||||||
__ jcc(Assembler::equal, one);
|
__ jcc(Assembler::equal, one);
|
||||||
if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() == k->super_check_offset()) {
|
if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() == k->super_check_offset()) {
|
||||||
// check for self
|
// check for self
|
||||||
__ cmpoop(klass_RInfo, k->encoding());
|
__ cmpoop(klass_RInfo, k->constant_encoding());
|
||||||
__ jcc(Assembler::equal, one);
|
__ jcc(Assembler::equal, one);
|
||||||
__ push(klass_RInfo);
|
__ push(klass_RInfo);
|
||||||
__ pushoop(k->encoding());
|
__ pushoop(k->constant_encoding());
|
||||||
__ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
|
__ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
|
||||||
__ pop(klass_RInfo);
|
__ pop(klass_RInfo);
|
||||||
__ pop(dst);
|
__ pop(dst);
|
||||||
|
@ -3112,7 +3112,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
|
||||||
// subtype which we can't check or src is the same array as dst
|
// subtype which we can't check or src is the same array as dst
|
||||||
// but not necessarily exactly of type default_type.
|
// but not necessarily exactly of type default_type.
|
||||||
Label known_ok, halt;
|
Label known_ok, halt;
|
||||||
__ movoop(tmp, default_type->encoding());
|
__ movoop(tmp, default_type->constant_encoding());
|
||||||
if (basic_type != T_OBJECT) {
|
if (basic_type != T_OBJECT) {
|
||||||
__ cmpptr(tmp, dst_klass_addr);
|
__ cmpptr(tmp, dst_klass_addr);
|
||||||
__ jcc(Assembler::notEqual, halt);
|
__ jcc(Assembler::notEqual, halt);
|
||||||
|
@ -3200,7 +3200,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||||
assert(data->is_CounterData(), "need CounterData for calls");
|
assert(data->is_CounterData(), "need CounterData for calls");
|
||||||
assert(op->mdo()->is_single_cpu(), "mdo must be allocated");
|
assert(op->mdo()->is_single_cpu(), "mdo must be allocated");
|
||||||
Register mdo = op->mdo()->as_register();
|
Register mdo = op->mdo()->as_register();
|
||||||
__ movoop(mdo, md->encoding());
|
__ movoop(mdo, md->constant_encoding());
|
||||||
Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()));
|
Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()));
|
||||||
__ addl(counter_addr, DataLayout::counter_increment);
|
__ addl(counter_addr, DataLayout::counter_increment);
|
||||||
Bytecodes::Code bc = method->java_code_at_bci(bci);
|
Bytecodes::Code bc = method->java_code_at_bci(bci);
|
||||||
|
@ -3240,7 +3240,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||||
ciKlass* receiver = vc_data->receiver(i);
|
ciKlass* receiver = vc_data->receiver(i);
|
||||||
if (receiver == NULL) {
|
if (receiver == NULL) {
|
||||||
Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)));
|
Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)));
|
||||||
__ movoop(recv_addr, known_klass->encoding());
|
__ movoop(recv_addr, known_klass->constant_encoding());
|
||||||
Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)));
|
Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)));
|
||||||
__ addl(data_addr, DataLayout::counter_increment);
|
__ addl(data_addr, DataLayout::counter_increment);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -994,7 +994,7 @@ void LIRGenerator::do_NewTypeArray(NewTypeArray* x) {
|
||||||
LIR_Opr len = length.result();
|
LIR_Opr len = length.result();
|
||||||
BasicType elem_type = x->elt_type();
|
BasicType elem_type = x->elt_type();
|
||||||
|
|
||||||
__ oop2reg(ciTypeArrayKlass::make(elem_type)->encoding(), klass_reg);
|
__ oop2reg(ciTypeArrayKlass::make(elem_type)->constant_encoding(), klass_reg);
|
||||||
|
|
||||||
CodeStub* slow_path = new NewTypeArrayStub(klass_reg, len, reg, info);
|
CodeStub* slow_path = new NewTypeArrayStub(klass_reg, len, reg, info);
|
||||||
__ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path);
|
__ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path);
|
||||||
|
|
|
@ -379,7 +379,7 @@ void emit_d32_reloc(CodeBuffer &cbuf, int d32, RelocationHolder const& rspec,
|
||||||
int format) {
|
int format) {
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
if (rspec.reloc()->type() == relocInfo::oop_type && d32 != 0 && d32 != (int)Universe::non_oop_word()) {
|
if (rspec.reloc()->type() == relocInfo::oop_type && d32 != 0 && d32 != (int)Universe::non_oop_word()) {
|
||||||
assert(oop(d32)->is_oop() && oop(d32)->is_perm(), "cannot embed non-perm oops in code");
|
assert(oop(d32)->is_oop() && (ScavengeRootsInCode || !oop(d32)->is_scavengable()), "cannot embed scavengable oops in code");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
cbuf.relocate(cbuf.inst_mark(), rspec, format);
|
cbuf.relocate(cbuf.inst_mark(), rspec, format);
|
||||||
|
@ -3701,458 +3701,6 @@ encode %{
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
enc_class enc_String_Compare(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2,
|
|
||||||
eAXRegI tmp3, eBXRegI tmp4, eCXRegI result) %{
|
|
||||||
Label ECX_GOOD_LABEL, LENGTH_DIFF_LABEL,
|
|
||||||
POP_LABEL, DONE_LABEL, CONT_LABEL,
|
|
||||||
WHILE_HEAD_LABEL;
|
|
||||||
MacroAssembler masm(&cbuf);
|
|
||||||
|
|
||||||
XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg);
|
|
||||||
XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg);
|
|
||||||
|
|
||||||
// Get the first character position in both strings
|
|
||||||
// [8] char array, [12] offset, [16] count
|
|
||||||
int value_offset = java_lang_String::value_offset_in_bytes();
|
|
||||||
int offset_offset = java_lang_String::offset_offset_in_bytes();
|
|
||||||
int count_offset = java_lang_String::count_offset_in_bytes();
|
|
||||||
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
|
|
||||||
|
|
||||||
masm.movptr(rax, Address(rsi, value_offset));
|
|
||||||
masm.movl(rcx, Address(rsi, offset_offset));
|
|
||||||
masm.lea(rax, Address(rax, rcx, Address::times_2, base_offset));
|
|
||||||
masm.movptr(rbx, Address(rdi, value_offset));
|
|
||||||
masm.movl(rcx, Address(rdi, offset_offset));
|
|
||||||
masm.lea(rbx, Address(rbx, rcx, Address::times_2, base_offset));
|
|
||||||
|
|
||||||
// Compute the minimum of the string lengths(rsi) and the
|
|
||||||
// difference of the string lengths (stack)
|
|
||||||
|
|
||||||
if (VM_Version::supports_cmov()) {
|
|
||||||
masm.movl(rdi, Address(rdi, count_offset));
|
|
||||||
masm.movl(rsi, Address(rsi, count_offset));
|
|
||||||
masm.movl(rcx, rdi);
|
|
||||||
masm.subl(rdi, rsi);
|
|
||||||
masm.push(rdi);
|
|
||||||
masm.cmovl(Assembler::lessEqual, rsi, rcx);
|
|
||||||
} else {
|
|
||||||
masm.movl(rdi, Address(rdi, count_offset));
|
|
||||||
masm.movl(rcx, Address(rsi, count_offset));
|
|
||||||
masm.movl(rsi, rdi);
|
|
||||||
masm.subl(rdi, rcx);
|
|
||||||
masm.push(rdi);
|
|
||||||
masm.jccb(Assembler::lessEqual, ECX_GOOD_LABEL);
|
|
||||||
masm.movl(rsi, rcx);
|
|
||||||
// rsi holds min, rcx is unused
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is the minimum length zero?
|
|
||||||
masm.bind(ECX_GOOD_LABEL);
|
|
||||||
masm.testl(rsi, rsi);
|
|
||||||
masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL);
|
|
||||||
|
|
||||||
// Load first characters
|
|
||||||
masm.load_unsigned_short(rcx, Address(rbx, 0));
|
|
||||||
masm.load_unsigned_short(rdi, Address(rax, 0));
|
|
||||||
|
|
||||||
// Compare first characters
|
|
||||||
masm.subl(rcx, rdi);
|
|
||||||
masm.jcc(Assembler::notZero, POP_LABEL);
|
|
||||||
masm.decrementl(rsi);
|
|
||||||
masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL);
|
|
||||||
|
|
||||||
{
|
|
||||||
// Check after comparing first character to see if strings are equivalent
|
|
||||||
Label LSkip2;
|
|
||||||
// Check if the strings start at same location
|
|
||||||
masm.cmpptr(rbx,rax);
|
|
||||||
masm.jccb(Assembler::notEqual, LSkip2);
|
|
||||||
|
|
||||||
// Check if the length difference is zero (from stack)
|
|
||||||
masm.cmpl(Address(rsp, 0), 0x0);
|
|
||||||
masm.jcc(Assembler::equal, LENGTH_DIFF_LABEL);
|
|
||||||
|
|
||||||
// Strings might not be equivalent
|
|
||||||
masm.bind(LSkip2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Advance to next character
|
|
||||||
masm.addptr(rax, 2);
|
|
||||||
masm.addptr(rbx, 2);
|
|
||||||
|
|
||||||
if (UseSSE42Intrinsics) {
|
|
||||||
// With SSE4.2, use double quad vector compare
|
|
||||||
Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL;
|
|
||||||
// Setup to compare 16-byte vectors
|
|
||||||
masm.movl(rdi, rsi);
|
|
||||||
masm.andl(rsi, 0xfffffff8); // rsi holds the vector count
|
|
||||||
masm.andl(rdi, 0x00000007); // rdi holds the tail count
|
|
||||||
masm.testl(rsi, rsi);
|
|
||||||
masm.jccb(Assembler::zero, COMPARE_TAIL);
|
|
||||||
|
|
||||||
masm.lea(rax, Address(rax, rsi, Address::times_2));
|
|
||||||
masm.lea(rbx, Address(rbx, rsi, Address::times_2));
|
|
||||||
masm.negl(rsi);
|
|
||||||
|
|
||||||
masm.bind(COMPARE_VECTORS);
|
|
||||||
masm.movdqu(tmp1Reg, Address(rax, rsi, Address::times_2));
|
|
||||||
masm.movdqu(tmp2Reg, Address(rbx, rsi, Address::times_2));
|
|
||||||
masm.pxor(tmp1Reg, tmp2Reg);
|
|
||||||
masm.ptest(tmp1Reg, tmp1Reg);
|
|
||||||
masm.jccb(Assembler::notZero, VECTOR_NOT_EQUAL);
|
|
||||||
masm.addl(rsi, 8);
|
|
||||||
masm.jcc(Assembler::notZero, COMPARE_VECTORS);
|
|
||||||
masm.jmpb(COMPARE_TAIL);
|
|
||||||
|
|
||||||
// Mismatched characters in the vectors
|
|
||||||
masm.bind(VECTOR_NOT_EQUAL);
|
|
||||||
masm.lea(rax, Address(rax, rsi, Address::times_2));
|
|
||||||
masm.lea(rbx, Address(rbx, rsi, Address::times_2));
|
|
||||||
masm.movl(rdi, 8);
|
|
||||||
|
|
||||||
// Compare tail (< 8 chars), or rescan last vectors to
|
|
||||||
// find 1st mismatched characters
|
|
||||||
masm.bind(COMPARE_TAIL);
|
|
||||||
masm.testl(rdi, rdi);
|
|
||||||
masm.jccb(Assembler::zero, LENGTH_DIFF_LABEL);
|
|
||||||
masm.movl(rsi, rdi);
|
|
||||||
// Fallthru to tail compare
|
|
||||||
}
|
|
||||||
|
|
||||||
//Shift rax, and rbx, to the end of the arrays, negate min
|
|
||||||
masm.lea(rax, Address(rax, rsi, Address::times_2, 0));
|
|
||||||
masm.lea(rbx, Address(rbx, rsi, Address::times_2, 0));
|
|
||||||
masm.negl(rsi);
|
|
||||||
|
|
||||||
// Compare the rest of the characters
|
|
||||||
masm.bind(WHILE_HEAD_LABEL);
|
|
||||||
masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0));
|
|
||||||
masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0));
|
|
||||||
masm.subl(rcx, rdi);
|
|
||||||
masm.jccb(Assembler::notZero, POP_LABEL);
|
|
||||||
masm.incrementl(rsi);
|
|
||||||
masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL);
|
|
||||||
|
|
||||||
// Strings are equal up to min length. Return the length difference.
|
|
||||||
masm.bind(LENGTH_DIFF_LABEL);
|
|
||||||
masm.pop(rcx);
|
|
||||||
masm.jmpb(DONE_LABEL);
|
|
||||||
|
|
||||||
// Discard the stored length difference
|
|
||||||
masm.bind(POP_LABEL);
|
|
||||||
masm.addptr(rsp, 4);
|
|
||||||
|
|
||||||
// That's it
|
|
||||||
masm.bind(DONE_LABEL);
|
|
||||||
%}
|
|
||||||
|
|
||||||
enc_class enc_String_Equals(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2,
|
|
||||||
eBXRegI tmp3, eCXRegI tmp4, eAXRegI result) %{
|
|
||||||
Label RET_TRUE, RET_FALSE, DONE, COMPARE_VECTORS, COMPARE_CHAR;
|
|
||||||
MacroAssembler masm(&cbuf);
|
|
||||||
|
|
||||||
XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg);
|
|
||||||
XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg);
|
|
||||||
|
|
||||||
int value_offset = java_lang_String::value_offset_in_bytes();
|
|
||||||
int offset_offset = java_lang_String::offset_offset_in_bytes();
|
|
||||||
int count_offset = java_lang_String::count_offset_in_bytes();
|
|
||||||
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
|
|
||||||
|
|
||||||
// does source == target string?
|
|
||||||
masm.cmpptr(rdi, rsi);
|
|
||||||
masm.jcc(Assembler::equal, RET_TRUE);
|
|
||||||
|
|
||||||
// get and compare counts
|
|
||||||
masm.movl(rcx, Address(rdi, count_offset));
|
|
||||||
masm.movl(rax, Address(rsi, count_offset));
|
|
||||||
masm.cmpl(rcx, rax);
|
|
||||||
masm.jcc(Assembler::notEqual, RET_FALSE);
|
|
||||||
masm.testl(rax, rax);
|
|
||||||
masm.jcc(Assembler::zero, RET_TRUE);
|
|
||||||
|
|
||||||
// get source string offset and value
|
|
||||||
masm.movptr(rbx, Address(rsi, value_offset));
|
|
||||||
masm.movl(rax, Address(rsi, offset_offset));
|
|
||||||
masm.leal(rsi, Address(rbx, rax, Address::times_2, base_offset));
|
|
||||||
|
|
||||||
// get compare string offset and value
|
|
||||||
masm.movptr(rbx, Address(rdi, value_offset));
|
|
||||||
masm.movl(rax, Address(rdi, offset_offset));
|
|
||||||
masm.leal(rdi, Address(rbx, rax, Address::times_2, base_offset));
|
|
||||||
|
|
||||||
// Set byte count
|
|
||||||
masm.shll(rcx, 1);
|
|
||||||
masm.movl(rax, rcx);
|
|
||||||
|
|
||||||
if (UseSSE42Intrinsics) {
|
|
||||||
// With SSE4.2, use double quad vector compare
|
|
||||||
Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
|
|
||||||
// Compare 16-byte vectors
|
|
||||||
masm.andl(rcx, 0xfffffff0); // vector count (in bytes)
|
|
||||||
masm.andl(rax, 0x0000000e); // tail count (in bytes)
|
|
||||||
masm.testl(rcx, rcx);
|
|
||||||
masm.jccb(Assembler::zero, COMPARE_TAIL);
|
|
||||||
masm.lea(rdi, Address(rdi, rcx, Address::times_1));
|
|
||||||
masm.lea(rsi, Address(rsi, rcx, Address::times_1));
|
|
||||||
masm.negl(rcx);
|
|
||||||
|
|
||||||
masm.bind(COMPARE_WIDE_VECTORS);
|
|
||||||
masm.movdqu(tmp1Reg, Address(rdi, rcx, Address::times_1));
|
|
||||||
masm.movdqu(tmp2Reg, Address(rsi, rcx, Address::times_1));
|
|
||||||
masm.pxor(tmp1Reg, tmp2Reg);
|
|
||||||
masm.ptest(tmp1Reg, tmp1Reg);
|
|
||||||
masm.jccb(Assembler::notZero, RET_FALSE);
|
|
||||||
masm.addl(rcx, 16);
|
|
||||||
masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
|
|
||||||
masm.bind(COMPARE_TAIL);
|
|
||||||
masm.movl(rcx, rax);
|
|
||||||
// Fallthru to tail compare
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare 4-byte vectors
|
|
||||||
masm.andl(rcx, 0xfffffffc); // vector count (in bytes)
|
|
||||||
masm.andl(rax, 0x00000002); // tail char (in bytes)
|
|
||||||
masm.testl(rcx, rcx);
|
|
||||||
masm.jccb(Assembler::zero, COMPARE_CHAR);
|
|
||||||
masm.lea(rdi, Address(rdi, rcx, Address::times_1));
|
|
||||||
masm.lea(rsi, Address(rsi, rcx, Address::times_1));
|
|
||||||
masm.negl(rcx);
|
|
||||||
|
|
||||||
masm.bind(COMPARE_VECTORS);
|
|
||||||
masm.movl(rbx, Address(rdi, rcx, Address::times_1));
|
|
||||||
masm.cmpl(rbx, Address(rsi, rcx, Address::times_1));
|
|
||||||
masm.jccb(Assembler::notEqual, RET_FALSE);
|
|
||||||
masm.addl(rcx, 4);
|
|
||||||
masm.jcc(Assembler::notZero, COMPARE_VECTORS);
|
|
||||||
|
|
||||||
// Compare trailing char (final 2 bytes), if any
|
|
||||||
masm.bind(COMPARE_CHAR);
|
|
||||||
masm.testl(rax, rax);
|
|
||||||
masm.jccb(Assembler::zero, RET_TRUE);
|
|
||||||
masm.load_unsigned_short(rbx, Address(rdi, 0));
|
|
||||||
masm.load_unsigned_short(rcx, Address(rsi, 0));
|
|
||||||
masm.cmpl(rbx, rcx);
|
|
||||||
masm.jccb(Assembler::notEqual, RET_FALSE);
|
|
||||||
|
|
||||||
masm.bind(RET_TRUE);
|
|
||||||
masm.movl(rax, 1); // return true
|
|
||||||
masm.jmpb(DONE);
|
|
||||||
|
|
||||||
masm.bind(RET_FALSE);
|
|
||||||
masm.xorl(rax, rax); // return false
|
|
||||||
|
|
||||||
masm.bind(DONE);
|
|
||||||
%}
|
|
||||||
|
|
||||||
enc_class enc_String_IndexOf(eSIRegP str1, eDIRegP str2, regXD tmp1, eAXRegI tmp2,
|
|
||||||
eCXRegI tmp3, eDXRegI tmp4, eBXRegI result) %{
|
|
||||||
// SSE4.2 version
|
|
||||||
Label LOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR,
|
|
||||||
SCAN_SUBSTR, RET_NEG_ONE, RET_NOT_FOUND, CLEANUP, DONE;
|
|
||||||
MacroAssembler masm(&cbuf);
|
|
||||||
|
|
||||||
XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg);
|
|
||||||
|
|
||||||
// Get the first character position in both strings
|
|
||||||
// [8] char array, [12] offset, [16] count
|
|
||||||
int value_offset = java_lang_String::value_offset_in_bytes();
|
|
||||||
int offset_offset = java_lang_String::offset_offset_in_bytes();
|
|
||||||
int count_offset = java_lang_String::count_offset_in_bytes();
|
|
||||||
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
|
|
||||||
|
|
||||||
// Get counts for string and substr
|
|
||||||
masm.movl(rdx, Address(rsi, count_offset));
|
|
||||||
masm.movl(rax, Address(rdi, count_offset));
|
|
||||||
// Check for substr count > string count
|
|
||||||
masm.cmpl(rax, rdx);
|
|
||||||
masm.jcc(Assembler::greater, RET_NEG_ONE);
|
|
||||||
|
|
||||||
// Start the indexOf operation
|
|
||||||
// Get start addr of string
|
|
||||||
masm.movptr(rbx, Address(rsi, value_offset));
|
|
||||||
masm.movl(rcx, Address(rsi, offset_offset));
|
|
||||||
masm.lea(rsi, Address(rbx, rcx, Address::times_2, base_offset));
|
|
||||||
masm.push(rsi);
|
|
||||||
|
|
||||||
// Get start addr of substr
|
|
||||||
masm.movptr(rbx, Address(rdi, value_offset));
|
|
||||||
masm.movl(rcx, Address(rdi, offset_offset));
|
|
||||||
masm.lea(rdi, Address(rbx, rcx, Address::times_2, base_offset));
|
|
||||||
masm.push(rdi);
|
|
||||||
masm.push(rax);
|
|
||||||
masm.jmpb(PREP_FOR_SCAN);
|
|
||||||
|
|
||||||
// Substr count saved at sp
|
|
||||||
// Substr saved at sp+4
|
|
||||||
// String saved at sp+8
|
|
||||||
|
|
||||||
// Prep to load substr for scan
|
|
||||||
masm.bind(LOAD_SUBSTR);
|
|
||||||
masm.movptr(rdi, Address(rsp, 4));
|
|
||||||
masm.movl(rax, Address(rsp, 0));
|
|
||||||
|
|
||||||
// Load substr
|
|
||||||
masm.bind(PREP_FOR_SCAN);
|
|
||||||
masm.movdqu(tmp1Reg, Address(rdi, 0));
|
|
||||||
masm.addl(rdx, 8); // prime the loop
|
|
||||||
masm.subptr(rsi, 16);
|
|
||||||
|
|
||||||
// Scan string for substr in 16-byte vectors
|
|
||||||
masm.bind(SCAN_TO_SUBSTR);
|
|
||||||
masm.subl(rdx, 8);
|
|
||||||
masm.addptr(rsi, 16);
|
|
||||||
masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d);
|
|
||||||
masm.jcc(Assembler::above, SCAN_TO_SUBSTR); // CF == 0 && ZF == 0
|
|
||||||
masm.jccb(Assembler::aboveEqual, RET_NOT_FOUND); // CF == 0
|
|
||||||
|
|
||||||
// Fallthru: found a potential substr
|
|
||||||
|
|
||||||
// Make sure string is still long enough
|
|
||||||
masm.subl(rdx, rcx);
|
|
||||||
masm.cmpl(rdx, rax);
|
|
||||||
masm.jccb(Assembler::negative, RET_NOT_FOUND);
|
|
||||||
// Compute start addr of substr
|
|
||||||
masm.lea(rsi, Address(rsi, rcx, Address::times_2));
|
|
||||||
masm.movptr(rbx, rsi);
|
|
||||||
|
|
||||||
// Compare potential substr
|
|
||||||
masm.addl(rdx, 8); // prime the loop
|
|
||||||
masm.addl(rax, 8);
|
|
||||||
masm.subptr(rsi, 16);
|
|
||||||
masm.subptr(rdi, 16);
|
|
||||||
|
|
||||||
// Scan 16-byte vectors of string and substr
|
|
||||||
masm.bind(SCAN_SUBSTR);
|
|
||||||
masm.subl(rax, 8);
|
|
||||||
masm.subl(rdx, 8);
|
|
||||||
masm.addptr(rsi, 16);
|
|
||||||
masm.addptr(rdi, 16);
|
|
||||||
masm.movdqu(tmp1Reg, Address(rdi, 0));
|
|
||||||
masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d);
|
|
||||||
masm.jcc(Assembler::noOverflow, LOAD_SUBSTR); // OF == 0
|
|
||||||
masm.jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0
|
|
||||||
|
|
||||||
// Compute substr offset
|
|
||||||
masm.movptr(rsi, Address(rsp, 8));
|
|
||||||
masm.subptr(rbx, rsi);
|
|
||||||
masm.shrl(rbx, 1);
|
|
||||||
masm.jmpb(CLEANUP);
|
|
||||||
|
|
||||||
masm.bind(RET_NEG_ONE);
|
|
||||||
masm.movl(rbx, -1);
|
|
||||||
masm.jmpb(DONE);
|
|
||||||
|
|
||||||
masm.bind(RET_NOT_FOUND);
|
|
||||||
masm.movl(rbx, -1);
|
|
||||||
|
|
||||||
masm.bind(CLEANUP);
|
|
||||||
masm.addptr(rsp, 12);
|
|
||||||
|
|
||||||
masm.bind(DONE);
|
|
||||||
%}
|
|
||||||
|
|
||||||
enc_class enc_Array_Equals(eDIRegP ary1, eSIRegP ary2, regXD tmp1, regXD tmp2,
|
|
||||||
eBXRegI tmp3, eDXRegI tmp4, eAXRegI result) %{
|
|
||||||
Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR;
|
|
||||||
MacroAssembler masm(&cbuf);
|
|
||||||
|
|
||||||
XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg);
|
|
||||||
XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg);
|
|
||||||
Register ary1Reg = as_Register($ary1$$reg);
|
|
||||||
Register ary2Reg = as_Register($ary2$$reg);
|
|
||||||
Register tmp3Reg = as_Register($tmp3$$reg);
|
|
||||||
Register tmp4Reg = as_Register($tmp4$$reg);
|
|
||||||
Register resultReg = as_Register($result$$reg);
|
|
||||||
|
|
||||||
int length_offset = arrayOopDesc::length_offset_in_bytes();
|
|
||||||
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
|
|
||||||
|
|
||||||
// Check the input args
|
|
||||||
masm.cmpptr(ary1Reg, ary2Reg);
|
|
||||||
masm.jcc(Assembler::equal, TRUE_LABEL);
|
|
||||||
masm.testptr(ary1Reg, ary1Reg);
|
|
||||||
masm.jcc(Assembler::zero, FALSE_LABEL);
|
|
||||||
masm.testptr(ary2Reg, ary2Reg);
|
|
||||||
masm.jcc(Assembler::zero, FALSE_LABEL);
|
|
||||||
|
|
||||||
// Check the lengths
|
|
||||||
masm.movl(tmp4Reg, Address(ary1Reg, length_offset));
|
|
||||||
masm.movl(resultReg, Address(ary2Reg, length_offset));
|
|
||||||
masm.cmpl(tmp4Reg, resultReg);
|
|
||||||
masm.jcc(Assembler::notEqual, FALSE_LABEL);
|
|
||||||
masm.testl(resultReg, resultReg);
|
|
||||||
masm.jcc(Assembler::zero, TRUE_LABEL);
|
|
||||||
|
|
||||||
// Load array addrs
|
|
||||||
masm.lea(ary1Reg, Address(ary1Reg, base_offset));
|
|
||||||
masm.lea(ary2Reg, Address(ary2Reg, base_offset));
|
|
||||||
|
|
||||||
// Set byte count
|
|
||||||
masm.shll(tmp4Reg, 1);
|
|
||||||
masm.movl(resultReg, tmp4Reg);
|
|
||||||
|
|
||||||
if (UseSSE42Intrinsics) {
|
|
||||||
// With SSE4.2, use double quad vector compare
|
|
||||||
Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
|
|
||||||
// Compare 16-byte vectors
|
|
||||||
masm.andl(tmp4Reg, 0xfffffff0); // vector count (in bytes)
|
|
||||||
masm.andl(resultReg, 0x0000000e); // tail count (in bytes)
|
|
||||||
masm.testl(tmp4Reg, tmp4Reg);
|
|
||||||
masm.jccb(Assembler::zero, COMPARE_TAIL);
|
|
||||||
masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.negl(tmp4Reg);
|
|
||||||
|
|
||||||
masm.bind(COMPARE_WIDE_VECTORS);
|
|
||||||
masm.movdqu(tmp1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.movdqu(tmp2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.pxor(tmp1Reg, tmp2Reg);
|
|
||||||
masm.ptest(tmp1Reg, tmp1Reg);
|
|
||||||
|
|
||||||
masm.jccb(Assembler::notZero, FALSE_LABEL);
|
|
||||||
masm.addl(tmp4Reg, 16);
|
|
||||||
masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
|
|
||||||
masm.bind(COMPARE_TAIL);
|
|
||||||
masm.movl(tmp4Reg, resultReg);
|
|
||||||
// Fallthru to tail compare
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare 4-byte vectors
|
|
||||||
masm.andl(tmp4Reg, 0xfffffffc); // vector count (in bytes)
|
|
||||||
masm.andl(resultReg, 0x00000002); // tail char (in bytes)
|
|
||||||
masm.testl(tmp4Reg, tmp4Reg);
|
|
||||||
masm.jccb(Assembler::zero, COMPARE_CHAR);
|
|
||||||
masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.negl(tmp4Reg);
|
|
||||||
|
|
||||||
masm.bind(COMPARE_VECTORS);
|
|
||||||
masm.movl(tmp3Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.cmpl(tmp3Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.jccb(Assembler::notEqual, FALSE_LABEL);
|
|
||||||
masm.addl(tmp4Reg, 4);
|
|
||||||
masm.jcc(Assembler::notZero, COMPARE_VECTORS);
|
|
||||||
|
|
||||||
// Compare trailing char (final 2 bytes), if any
|
|
||||||
masm.bind(COMPARE_CHAR);
|
|
||||||
masm.testl(resultReg, resultReg);
|
|
||||||
masm.jccb(Assembler::zero, TRUE_LABEL);
|
|
||||||
masm.load_unsigned_short(tmp3Reg, Address(ary1Reg, 0));
|
|
||||||
masm.load_unsigned_short(tmp4Reg, Address(ary2Reg, 0));
|
|
||||||
masm.cmpl(tmp3Reg, tmp4Reg);
|
|
||||||
masm.jccb(Assembler::notEqual, FALSE_LABEL);
|
|
||||||
|
|
||||||
masm.bind(TRUE_LABEL);
|
|
||||||
masm.movl(resultReg, 1); // return true
|
|
||||||
masm.jmpb(DONE);
|
|
||||||
|
|
||||||
masm.bind(FALSE_LABEL);
|
|
||||||
masm.xorl(resultReg, resultReg); // return false
|
|
||||||
|
|
||||||
// That's it
|
|
||||||
masm.bind(DONE);
|
|
||||||
%}
|
|
||||||
|
|
||||||
enc_class enc_pop_rdx() %{
|
enc_class enc_pop_rdx() %{
|
||||||
emit_opcode(cbuf,0x5A);
|
emit_opcode(cbuf,0x5A);
|
||||||
|
@ -12718,48 +12266,64 @@ instruct rep_stos(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlag
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct string_compare(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2,
|
instruct string_compare(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eBXRegI cnt2,
|
||||||
eAXRegI tmp3, eBXRegI tmp4, eCXRegI result, eFlagsReg cr) %{
|
eAXRegI result, regXD tmp1, regXD tmp2, eFlagsReg cr) %{
|
||||||
match(Set result (StrComp str1 str2));
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
|
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
|
||||||
//ins_cost(300);
|
|
||||||
|
|
||||||
format %{ "String Compare $str1,$str2 -> $result // KILL EAX, EBX" %}
|
format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1, $tmp2" %}
|
||||||
ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
|
ins_encode %{
|
||||||
|
__ string_compare($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register, $result$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
|
||||||
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// fast string equals
|
// fast string equals
|
||||||
instruct string_equals(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2,
|
instruct string_equals(eDIRegP str1, eSIRegP str2, eCXRegI cnt, eAXRegI result,
|
||||||
eBXRegI tmp3, eCXRegI tmp4, eAXRegI result, eFlagsReg cr) %{
|
regXD tmp1, regXD tmp2, eBXRegI tmp3, eFlagsReg cr) %{
|
||||||
match(Set result (StrEquals str1 str2));
|
match(Set result (StrEquals (Binary str1 str2) cnt));
|
||||||
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
|
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr);
|
||||||
|
|
||||||
format %{ "String Equals $str1,$str2 -> $result // KILL EBX, ECX" %}
|
format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
|
||||||
ins_encode( enc_String_Equals(tmp1, tmp2, str1, str2, tmp3, tmp4, result) );
|
ins_encode %{
|
||||||
|
__ char_arrays_equals(false, $str1$$Register, $str2$$Register,
|
||||||
|
$cnt$$Register, $result$$Register, $tmp3$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
|
||||||
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct string_indexof(eSIRegP str1, eDIRegP str2, regXD tmp1, eAXRegI tmp2,
|
instruct string_indexof(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
|
||||||
eCXRegI tmp3, eDXRegI tmp4, eBXRegI result, eFlagsReg cr) %{
|
eBXRegI result, regXD tmp1, eCXRegI tmp2, eFlagsReg cr) %{
|
||||||
predicate(UseSSE42Intrinsics);
|
predicate(UseSSE42Intrinsics);
|
||||||
match(Set result (StrIndexOf str1 str2));
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, KILL tmp2, KILL tmp3, KILL tmp4, KILL cr);
|
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp2, KILL cr);
|
||||||
|
|
||||||
format %{ "String IndexOf $str1,$str2 -> $result // KILL EAX, ECX, EDX" %}
|
format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp2, $tmp1" %}
|
||||||
ins_encode( enc_String_IndexOf(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
|
ins_encode %{
|
||||||
|
__ string_indexof($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register, $result$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$Register);
|
||||||
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// fast array equals
|
// fast array equals
|
||||||
instruct array_equals(eDIRegP ary1, eSIRegP ary2, regXD tmp1, regXD tmp2, eBXRegI tmp3,
|
instruct array_equals(eDIRegP ary1, eSIRegP ary2, eAXRegI result,
|
||||||
eDXRegI tmp4, eAXRegI result, eFlagsReg cr) %{
|
regXD tmp1, regXD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr)
|
||||||
|
%{
|
||||||
match(Set result (AryEq ary1 ary2));
|
match(Set result (AryEq ary1 ary2));
|
||||||
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
|
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
|
||||||
//ins_cost(300);
|
//ins_cost(300);
|
||||||
|
|
||||||
format %{ "Array Equals $ary1,$ary2 -> $result // KILL EBX, EDX" %}
|
format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
|
||||||
ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, tmp4, result) );
|
ins_encode %{
|
||||||
|
__ char_arrays_equals(true, $ary1$$Register, $ary2$$Register,
|
||||||
|
$tmp3$$Register, $result$$Register, $tmp4$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
|
||||||
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
|
@ -683,7 +683,7 @@ void emit_d32_reloc(CodeBuffer& cbuf,
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
if (rspec.reloc()->type() == relocInfo::oop_type &&
|
if (rspec.reloc()->type() == relocInfo::oop_type &&
|
||||||
d32 != 0 && d32 != (intptr_t) Universe::non_oop_word()) {
|
d32 != 0 && d32 != (intptr_t) Universe::non_oop_word()) {
|
||||||
assert(oop((intptr_t)d32)->is_oop() && oop((intptr_t)d32)->is_perm(), "cannot embed non-perm oops in code");
|
assert(oop((intptr_t)d32)->is_oop() && (ScavengeRootsInCode || !oop((intptr_t)d32)->is_scavengable()), "cannot embed scavengable oops in code");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
cbuf.relocate(cbuf.inst_mark(), rspec, format);
|
cbuf.relocate(cbuf.inst_mark(), rspec, format);
|
||||||
|
@ -721,8 +721,8 @@ void emit_d64_reloc(CodeBuffer& cbuf,
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
if (rspec.reloc()->type() == relocInfo::oop_type &&
|
if (rspec.reloc()->type() == relocInfo::oop_type &&
|
||||||
d64 != 0 && d64 != (int64_t) Universe::non_oop_word()) {
|
d64 != 0 && d64 != (int64_t) Universe::non_oop_word()) {
|
||||||
assert(oop(d64)->is_oop() && oop(d64)->is_perm(),
|
assert(oop(d64)->is_oop() && (ScavengeRootsInCode || !oop(d64)->is_scavengable()),
|
||||||
"cannot embed non-perm oops in code");
|
"cannot embed scavengable oops in code");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
cbuf.relocate(cbuf.inst_mark(), rspec, format);
|
cbuf.relocate(cbuf.inst_mark(), rspec, format);
|
||||||
|
@ -3701,448 +3701,6 @@ encode %{
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
enc_class enc_String_Compare(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2,
|
|
||||||
rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result) %{
|
|
||||||
Label RCX_GOOD_LABEL, LENGTH_DIFF_LABEL,
|
|
||||||
POP_LABEL, DONE_LABEL, CONT_LABEL,
|
|
||||||
WHILE_HEAD_LABEL;
|
|
||||||
MacroAssembler masm(&cbuf);
|
|
||||||
|
|
||||||
XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg);
|
|
||||||
XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg);
|
|
||||||
|
|
||||||
// Get the first character position in both strings
|
|
||||||
// [8] char array, [12] offset, [16] count
|
|
||||||
int value_offset = java_lang_String::value_offset_in_bytes();
|
|
||||||
int offset_offset = java_lang_String::offset_offset_in_bytes();
|
|
||||||
int count_offset = java_lang_String::count_offset_in_bytes();
|
|
||||||
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
|
|
||||||
|
|
||||||
masm.load_heap_oop(rax, Address(rsi, value_offset));
|
|
||||||
masm.movl(rcx, Address(rsi, offset_offset));
|
|
||||||
masm.lea(rax, Address(rax, rcx, Address::times_2, base_offset));
|
|
||||||
masm.load_heap_oop(rbx, Address(rdi, value_offset));
|
|
||||||
masm.movl(rcx, Address(rdi, offset_offset));
|
|
||||||
masm.lea(rbx, Address(rbx, rcx, Address::times_2, base_offset));
|
|
||||||
|
|
||||||
// Compute the minimum of the string lengths(rsi) and the
|
|
||||||
// difference of the string lengths (stack)
|
|
||||||
|
|
||||||
// do the conditional move stuff
|
|
||||||
masm.movl(rdi, Address(rdi, count_offset));
|
|
||||||
masm.movl(rsi, Address(rsi, count_offset));
|
|
||||||
masm.movl(rcx, rdi);
|
|
||||||
masm.subl(rdi, rsi);
|
|
||||||
masm.push(rdi);
|
|
||||||
masm.cmov(Assembler::lessEqual, rsi, rcx);
|
|
||||||
|
|
||||||
// Is the minimum length zero?
|
|
||||||
masm.bind(RCX_GOOD_LABEL);
|
|
||||||
masm.testl(rsi, rsi);
|
|
||||||
masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL);
|
|
||||||
|
|
||||||
// Load first characters
|
|
||||||
masm.load_unsigned_short(rcx, Address(rbx, 0));
|
|
||||||
masm.load_unsigned_short(rdi, Address(rax, 0));
|
|
||||||
|
|
||||||
// Compare first characters
|
|
||||||
masm.subl(rcx, rdi);
|
|
||||||
masm.jcc(Assembler::notZero, POP_LABEL);
|
|
||||||
masm.decrementl(rsi);
|
|
||||||
masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL);
|
|
||||||
|
|
||||||
{
|
|
||||||
// Check after comparing first character to see if strings are equivalent
|
|
||||||
Label LSkip2;
|
|
||||||
// Check if the strings start at same location
|
|
||||||
masm.cmpptr(rbx, rax);
|
|
||||||
masm.jccb(Assembler::notEqual, LSkip2);
|
|
||||||
|
|
||||||
// Check if the length difference is zero (from stack)
|
|
||||||
masm.cmpl(Address(rsp, 0), 0x0);
|
|
||||||
masm.jcc(Assembler::equal, LENGTH_DIFF_LABEL);
|
|
||||||
|
|
||||||
// Strings might not be equivalent
|
|
||||||
masm.bind(LSkip2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Advance to next character
|
|
||||||
masm.addptr(rax, 2);
|
|
||||||
masm.addptr(rbx, 2);
|
|
||||||
|
|
||||||
if (UseSSE42Intrinsics) {
|
|
||||||
// With SSE4.2, use double quad vector compare
|
|
||||||
Label COMPARE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_TAIL;
|
|
||||||
// Setup to compare 16-byte vectors
|
|
||||||
masm.movl(rdi, rsi);
|
|
||||||
masm.andl(rsi, 0xfffffff8); // rsi holds the vector count
|
|
||||||
masm.andl(rdi, 0x00000007); // rdi holds the tail count
|
|
||||||
masm.testl(rsi, rsi);
|
|
||||||
masm.jccb(Assembler::zero, COMPARE_TAIL);
|
|
||||||
|
|
||||||
masm.lea(rax, Address(rax, rsi, Address::times_2));
|
|
||||||
masm.lea(rbx, Address(rbx, rsi, Address::times_2));
|
|
||||||
masm.negptr(rsi);
|
|
||||||
|
|
||||||
masm.bind(COMPARE_VECTORS);
|
|
||||||
masm.movdqu(tmp1Reg, Address(rax, rsi, Address::times_2));
|
|
||||||
masm.movdqu(tmp2Reg, Address(rbx, rsi, Address::times_2));
|
|
||||||
masm.pxor(tmp1Reg, tmp2Reg);
|
|
||||||
masm.ptest(tmp1Reg, tmp1Reg);
|
|
||||||
masm.jccb(Assembler::notZero, VECTOR_NOT_EQUAL);
|
|
||||||
masm.addptr(rsi, 8);
|
|
||||||
masm.jcc(Assembler::notZero, COMPARE_VECTORS);
|
|
||||||
masm.jmpb(COMPARE_TAIL);
|
|
||||||
|
|
||||||
// Mismatched characters in the vectors
|
|
||||||
masm.bind(VECTOR_NOT_EQUAL);
|
|
||||||
masm.lea(rax, Address(rax, rsi, Address::times_2));
|
|
||||||
masm.lea(rbx, Address(rbx, rsi, Address::times_2));
|
|
||||||
masm.movl(rdi, 8);
|
|
||||||
|
|
||||||
// Compare tail (< 8 chars), or rescan last vectors to
|
|
||||||
// find 1st mismatched characters
|
|
||||||
masm.bind(COMPARE_TAIL);
|
|
||||||
masm.testl(rdi, rdi);
|
|
||||||
masm.jccb(Assembler::zero, LENGTH_DIFF_LABEL);
|
|
||||||
masm.movl(rsi, rdi);
|
|
||||||
// Fallthru to tail compare
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shift RAX and RBX to the end of the arrays, negate min
|
|
||||||
masm.lea(rax, Address(rax, rsi, Address::times_2, 0));
|
|
||||||
masm.lea(rbx, Address(rbx, rsi, Address::times_2, 0));
|
|
||||||
masm.negptr(rsi);
|
|
||||||
|
|
||||||
// Compare the rest of the characters
|
|
||||||
masm.bind(WHILE_HEAD_LABEL);
|
|
||||||
masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0));
|
|
||||||
masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0));
|
|
||||||
masm.subl(rcx, rdi);
|
|
||||||
masm.jccb(Assembler::notZero, POP_LABEL);
|
|
||||||
masm.increment(rsi);
|
|
||||||
masm.jcc(Assembler::notZero, WHILE_HEAD_LABEL);
|
|
||||||
|
|
||||||
// Strings are equal up to min length. Return the length difference.
|
|
||||||
masm.bind(LENGTH_DIFF_LABEL);
|
|
||||||
masm.pop(rcx);
|
|
||||||
masm.jmpb(DONE_LABEL);
|
|
||||||
|
|
||||||
// Discard the stored length difference
|
|
||||||
masm.bind(POP_LABEL);
|
|
||||||
masm.addptr(rsp, 8);
|
|
||||||
|
|
||||||
// That's it
|
|
||||||
masm.bind(DONE_LABEL);
|
|
||||||
%}
|
|
||||||
|
|
||||||
enc_class enc_String_IndexOf(rsi_RegP str1, rdi_RegP str2, regD tmp1, rax_RegI tmp2,
|
|
||||||
rcx_RegI tmp3, rdx_RegI tmp4, rbx_RegI result) %{
|
|
||||||
// SSE4.2 version
|
|
||||||
Label LOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR,
|
|
||||||
SCAN_SUBSTR, RET_NEG_ONE, RET_NOT_FOUND, CLEANUP, DONE;
|
|
||||||
MacroAssembler masm(&cbuf);
|
|
||||||
|
|
||||||
XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg);
|
|
||||||
|
|
||||||
// Get the first character position in both strings
|
|
||||||
// [8] char array, [12] offset, [16] count
|
|
||||||
int value_offset = java_lang_String::value_offset_in_bytes();
|
|
||||||
int offset_offset = java_lang_String::offset_offset_in_bytes();
|
|
||||||
int count_offset = java_lang_String::count_offset_in_bytes();
|
|
||||||
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
|
|
||||||
|
|
||||||
// Get counts for string and substr
|
|
||||||
masm.movl(rdx, Address(rsi, count_offset));
|
|
||||||
masm.movl(rax, Address(rdi, count_offset));
|
|
||||||
// Check for substr count > string count
|
|
||||||
masm.cmpl(rax, rdx);
|
|
||||||
masm.jcc(Assembler::greater, RET_NEG_ONE);
|
|
||||||
|
|
||||||
// Start the indexOf operation
|
|
||||||
// Get start addr of string
|
|
||||||
masm.load_heap_oop(rbx, Address(rsi, value_offset));
|
|
||||||
masm.movl(rcx, Address(rsi, offset_offset));
|
|
||||||
masm.lea(rsi, Address(rbx, rcx, Address::times_2, base_offset));
|
|
||||||
masm.push(rsi);
|
|
||||||
|
|
||||||
// Get start addr of substr
|
|
||||||
masm.load_heap_oop(rbx, Address(rdi, value_offset));
|
|
||||||
masm.movl(rcx, Address(rdi, offset_offset));
|
|
||||||
masm.lea(rdi, Address(rbx, rcx, Address::times_2, base_offset));
|
|
||||||
masm.push(rdi);
|
|
||||||
masm.push(rax);
|
|
||||||
masm.jmpb(PREP_FOR_SCAN);
|
|
||||||
|
|
||||||
// Substr count saved at sp
|
|
||||||
// Substr saved at sp+8
|
|
||||||
// String saved at sp+16
|
|
||||||
|
|
||||||
// Prep to load substr for scan
|
|
||||||
masm.bind(LOAD_SUBSTR);
|
|
||||||
masm.movptr(rdi, Address(rsp, 8));
|
|
||||||
masm.movl(rax, Address(rsp, 0));
|
|
||||||
|
|
||||||
// Load substr
|
|
||||||
masm.bind(PREP_FOR_SCAN);
|
|
||||||
masm.movdqu(tmp1Reg, Address(rdi, 0));
|
|
||||||
masm.addq(rdx, 8); // prime the loop
|
|
||||||
masm.subptr(rsi, 16);
|
|
||||||
|
|
||||||
// Scan string for substr in 16-byte vectors
|
|
||||||
masm.bind(SCAN_TO_SUBSTR);
|
|
||||||
masm.subq(rdx, 8);
|
|
||||||
masm.addptr(rsi, 16);
|
|
||||||
masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d);
|
|
||||||
masm.jcc(Assembler::above, SCAN_TO_SUBSTR);
|
|
||||||
masm.jccb(Assembler::aboveEqual, RET_NOT_FOUND);
|
|
||||||
|
|
||||||
// Fallthru: found a potential substr
|
|
||||||
|
|
||||||
//Make sure string is still long enough
|
|
||||||
masm.subl(rdx, rcx);
|
|
||||||
masm.cmpl(rdx, rax);
|
|
||||||
masm.jccb(Assembler::negative, RET_NOT_FOUND);
|
|
||||||
// Compute start addr of substr
|
|
||||||
masm.lea(rsi, Address(rsi, rcx, Address::times_2));
|
|
||||||
masm.movptr(rbx, rsi);
|
|
||||||
|
|
||||||
// Compare potential substr
|
|
||||||
masm.addq(rdx, 8); // prime the loop
|
|
||||||
masm.addq(rax, 8);
|
|
||||||
masm.subptr(rsi, 16);
|
|
||||||
masm.subptr(rdi, 16);
|
|
||||||
|
|
||||||
// Scan 16-byte vectors of string and substr
|
|
||||||
masm.bind(SCAN_SUBSTR);
|
|
||||||
masm.subq(rax, 8);
|
|
||||||
masm.subq(rdx, 8);
|
|
||||||
masm.addptr(rsi, 16);
|
|
||||||
masm.addptr(rdi, 16);
|
|
||||||
masm.movdqu(tmp1Reg, Address(rdi, 0));
|
|
||||||
masm.pcmpestri(tmp1Reg, Address(rsi, 0), 0x0d);
|
|
||||||
masm.jcc(Assembler::noOverflow, LOAD_SUBSTR); // OF == 0
|
|
||||||
masm.jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0
|
|
||||||
|
|
||||||
// Compute substr offset
|
|
||||||
masm.movptr(rsi, Address(rsp, 16));
|
|
||||||
masm.subptr(rbx, rsi);
|
|
||||||
masm.shrl(rbx, 1);
|
|
||||||
masm.jmpb(CLEANUP);
|
|
||||||
|
|
||||||
masm.bind(RET_NEG_ONE);
|
|
||||||
masm.movl(rbx, -1);
|
|
||||||
masm.jmpb(DONE);
|
|
||||||
|
|
||||||
masm.bind(RET_NOT_FOUND);
|
|
||||||
masm.movl(rbx, -1);
|
|
||||||
|
|
||||||
masm.bind(CLEANUP);
|
|
||||||
masm.addptr(rsp, 24);
|
|
||||||
|
|
||||||
masm.bind(DONE);
|
|
||||||
%}
|
|
||||||
|
|
||||||
enc_class enc_String_Equals(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2,
|
|
||||||
rbx_RegI tmp3, rcx_RegI tmp2, rax_RegI result) %{
|
|
||||||
Label RET_TRUE, RET_FALSE, DONE, COMPARE_VECTORS, COMPARE_CHAR;
|
|
||||||
MacroAssembler masm(&cbuf);
|
|
||||||
|
|
||||||
XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg);
|
|
||||||
XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg);
|
|
||||||
|
|
||||||
int value_offset = java_lang_String::value_offset_in_bytes();
|
|
||||||
int offset_offset = java_lang_String::offset_offset_in_bytes();
|
|
||||||
int count_offset = java_lang_String::count_offset_in_bytes();
|
|
||||||
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
|
|
||||||
|
|
||||||
// does source == target string?
|
|
||||||
masm.cmpptr(rdi, rsi);
|
|
||||||
masm.jcc(Assembler::equal, RET_TRUE);
|
|
||||||
|
|
||||||
// get and compare counts
|
|
||||||
masm.movl(rcx, Address(rdi, count_offset));
|
|
||||||
masm.movl(rax, Address(rsi, count_offset));
|
|
||||||
masm.cmpl(rcx, rax);
|
|
||||||
masm.jcc(Assembler::notEqual, RET_FALSE);
|
|
||||||
masm.testl(rax, rax);
|
|
||||||
masm.jcc(Assembler::zero, RET_TRUE);
|
|
||||||
|
|
||||||
// get source string offset and value
|
|
||||||
masm.load_heap_oop(rbx, Address(rsi, value_offset));
|
|
||||||
masm.movl(rax, Address(rsi, offset_offset));
|
|
||||||
masm.lea(rsi, Address(rbx, rax, Address::times_2, base_offset));
|
|
||||||
|
|
||||||
// get compare string offset and value
|
|
||||||
masm.load_heap_oop(rbx, Address(rdi, value_offset));
|
|
||||||
masm.movl(rax, Address(rdi, offset_offset));
|
|
||||||
masm.lea(rdi, Address(rbx, rax, Address::times_2, base_offset));
|
|
||||||
|
|
||||||
// Set byte count
|
|
||||||
masm.shll(rcx, 1);
|
|
||||||
masm.movl(rax, rcx);
|
|
||||||
|
|
||||||
if (UseSSE42Intrinsics) {
|
|
||||||
// With SSE4.2, use double quad vector compare
|
|
||||||
Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
|
|
||||||
// Compare 16-byte vectors
|
|
||||||
masm.andl(rcx, 0xfffffff0); // vector count (in bytes)
|
|
||||||
masm.andl(rax, 0x0000000e); // tail count (in bytes)
|
|
||||||
masm.testl(rcx, rcx);
|
|
||||||
masm.jccb(Assembler::zero, COMPARE_TAIL);
|
|
||||||
masm.lea(rdi, Address(rdi, rcx, Address::times_1));
|
|
||||||
masm.lea(rsi, Address(rsi, rcx, Address::times_1));
|
|
||||||
masm.negptr(rcx);
|
|
||||||
|
|
||||||
masm.bind(COMPARE_WIDE_VECTORS);
|
|
||||||
masm.movdqu(tmp1Reg, Address(rdi, rcx, Address::times_1));
|
|
||||||
masm.movdqu(tmp2Reg, Address(rsi, rcx, Address::times_1));
|
|
||||||
masm.pxor(tmp1Reg, tmp2Reg);
|
|
||||||
masm.ptest(tmp1Reg, tmp1Reg);
|
|
||||||
masm.jccb(Assembler::notZero, RET_FALSE);
|
|
||||||
masm.addptr(rcx, 16);
|
|
||||||
masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
|
|
||||||
masm.bind(COMPARE_TAIL);
|
|
||||||
masm.movl(rcx, rax);
|
|
||||||
// Fallthru to tail compare
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare 4-byte vectors
|
|
||||||
masm.andl(rcx, 0xfffffffc); // vector count (in bytes)
|
|
||||||
masm.andl(rax, 0x00000002); // tail char (in bytes)
|
|
||||||
masm.testl(rcx, rcx);
|
|
||||||
masm.jccb(Assembler::zero, COMPARE_CHAR);
|
|
||||||
masm.lea(rdi, Address(rdi, rcx, Address::times_1));
|
|
||||||
masm.lea(rsi, Address(rsi, rcx, Address::times_1));
|
|
||||||
masm.negptr(rcx);
|
|
||||||
|
|
||||||
masm.bind(COMPARE_VECTORS);
|
|
||||||
masm.movl(rbx, Address(rdi, rcx, Address::times_1));
|
|
||||||
masm.cmpl(rbx, Address(rsi, rcx, Address::times_1));
|
|
||||||
masm.jccb(Assembler::notEqual, RET_FALSE);
|
|
||||||
masm.addptr(rcx, 4);
|
|
||||||
masm.jcc(Assembler::notZero, COMPARE_VECTORS);
|
|
||||||
|
|
||||||
// Compare trailing char (final 2 bytes), if any
|
|
||||||
masm.bind(COMPARE_CHAR);
|
|
||||||
masm.testl(rax, rax);
|
|
||||||
masm.jccb(Assembler::zero, RET_TRUE);
|
|
||||||
masm.load_unsigned_short(rbx, Address(rdi, 0));
|
|
||||||
masm.load_unsigned_short(rcx, Address(rsi, 0));
|
|
||||||
masm.cmpl(rbx, rcx);
|
|
||||||
masm.jccb(Assembler::notEqual, RET_FALSE);
|
|
||||||
|
|
||||||
masm.bind(RET_TRUE);
|
|
||||||
masm.movl(rax, 1); // return true
|
|
||||||
masm.jmpb(DONE);
|
|
||||||
|
|
||||||
masm.bind(RET_FALSE);
|
|
||||||
masm.xorl(rax, rax); // return false
|
|
||||||
|
|
||||||
masm.bind(DONE);
|
|
||||||
%}
|
|
||||||
|
|
||||||
enc_class enc_Array_Equals(rdi_RegP ary1, rsi_RegP ary2, regD tmp1, regD tmp2,
|
|
||||||
rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result) %{
|
|
||||||
Label TRUE_LABEL, FALSE_LABEL, DONE, COMPARE_VECTORS, COMPARE_CHAR;
|
|
||||||
MacroAssembler masm(&cbuf);
|
|
||||||
|
|
||||||
XMMRegister tmp1Reg = as_XMMRegister($tmp1$$reg);
|
|
||||||
XMMRegister tmp2Reg = as_XMMRegister($tmp2$$reg);
|
|
||||||
Register ary1Reg = as_Register($ary1$$reg);
|
|
||||||
Register ary2Reg = as_Register($ary2$$reg);
|
|
||||||
Register tmp3Reg = as_Register($tmp3$$reg);
|
|
||||||
Register tmp4Reg = as_Register($tmp4$$reg);
|
|
||||||
Register resultReg = as_Register($result$$reg);
|
|
||||||
|
|
||||||
int length_offset = arrayOopDesc::length_offset_in_bytes();
|
|
||||||
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
|
|
||||||
|
|
||||||
// Check the input args
|
|
||||||
masm.cmpq(ary1Reg, ary2Reg);
|
|
||||||
masm.jcc(Assembler::equal, TRUE_LABEL);
|
|
||||||
masm.testq(ary1Reg, ary1Reg);
|
|
||||||
masm.jcc(Assembler::zero, FALSE_LABEL);
|
|
||||||
masm.testq(ary2Reg, ary2Reg);
|
|
||||||
masm.jcc(Assembler::zero, FALSE_LABEL);
|
|
||||||
|
|
||||||
// Check the lengths
|
|
||||||
masm.movl(tmp4Reg, Address(ary1Reg, length_offset));
|
|
||||||
masm.movl(resultReg, Address(ary2Reg, length_offset));
|
|
||||||
masm.cmpl(tmp4Reg, resultReg);
|
|
||||||
masm.jcc(Assembler::notEqual, FALSE_LABEL);
|
|
||||||
masm.testl(resultReg, resultReg);
|
|
||||||
masm.jcc(Assembler::zero, TRUE_LABEL);
|
|
||||||
|
|
||||||
//load array address
|
|
||||||
masm.lea(ary1Reg, Address(ary1Reg, base_offset));
|
|
||||||
masm.lea(ary2Reg, Address(ary2Reg, base_offset));
|
|
||||||
|
|
||||||
//set byte count
|
|
||||||
masm.shll(tmp4Reg, 1);
|
|
||||||
masm.movl(resultReg,tmp4Reg);
|
|
||||||
|
|
||||||
if (UseSSE42Intrinsics){
|
|
||||||
// With SSE4.2, use double quad vector compare
|
|
||||||
Label COMPARE_WIDE_VECTORS, COMPARE_TAIL;
|
|
||||||
// Compare 16-byte vectors
|
|
||||||
masm.andl(tmp4Reg, 0xfffffff0); // vector count (in bytes)
|
|
||||||
masm.andl(resultReg, 0x0000000e); // tail count (in bytes)
|
|
||||||
masm.testl(tmp4Reg, tmp4Reg);
|
|
||||||
masm.jccb(Assembler::zero, COMPARE_TAIL);
|
|
||||||
masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.negptr(tmp4Reg);
|
|
||||||
|
|
||||||
masm.bind(COMPARE_WIDE_VECTORS);
|
|
||||||
masm.movdqu(tmp1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.movdqu(tmp2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.pxor(tmp1Reg, tmp2Reg);
|
|
||||||
masm.ptest(tmp1Reg, tmp1Reg);
|
|
||||||
|
|
||||||
masm.jccb(Assembler::notZero, FALSE_LABEL);
|
|
||||||
masm.addptr(tmp4Reg, 16);
|
|
||||||
masm.jcc(Assembler::notZero, COMPARE_WIDE_VECTORS);
|
|
||||||
masm.bind(COMPARE_TAIL);
|
|
||||||
masm.movl(tmp4Reg, resultReg);
|
|
||||||
// Fallthru to tail compare
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare 4-byte vectors
|
|
||||||
masm.andl(tmp4Reg, 0xfffffffc); // vector count (in bytes)
|
|
||||||
masm.andl(resultReg, 0x00000002); // tail char (in bytes)
|
|
||||||
masm.testl(tmp4Reg, tmp4Reg); //if tmp2 == 0, only compare char
|
|
||||||
masm.jccb(Assembler::zero, COMPARE_CHAR);
|
|
||||||
masm.lea(ary1Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.lea(ary2Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.negptr(tmp4Reg);
|
|
||||||
|
|
||||||
masm.bind(COMPARE_VECTORS);
|
|
||||||
masm.movl(tmp3Reg, Address(ary1Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.cmpl(tmp3Reg, Address(ary2Reg, tmp4Reg, Address::times_1));
|
|
||||||
masm.jccb(Assembler::notEqual, FALSE_LABEL);
|
|
||||||
masm.addptr(tmp4Reg, 4);
|
|
||||||
masm.jcc(Assembler::notZero, COMPARE_VECTORS);
|
|
||||||
|
|
||||||
// Compare trailing char (final 2 bytes), if any
|
|
||||||
masm.bind(COMPARE_CHAR);
|
|
||||||
masm.testl(resultReg, resultReg);
|
|
||||||
masm.jccb(Assembler::zero, TRUE_LABEL);
|
|
||||||
masm.load_unsigned_short(tmp3Reg, Address(ary1Reg, 0));
|
|
||||||
masm.load_unsigned_short(tmp4Reg, Address(ary2Reg, 0));
|
|
||||||
masm.cmpl(tmp3Reg, tmp4Reg);
|
|
||||||
masm.jccb(Assembler::notEqual, FALSE_LABEL);
|
|
||||||
|
|
||||||
masm.bind(TRUE_LABEL);
|
|
||||||
masm.movl(resultReg, 1); // return true
|
|
||||||
masm.jmpb(DONE);
|
|
||||||
|
|
||||||
masm.bind(FALSE_LABEL);
|
|
||||||
masm.xorl(resultReg, resultReg); // return false
|
|
||||||
|
|
||||||
// That's it
|
|
||||||
masm.bind(DONE);
|
|
||||||
%}
|
|
||||||
|
|
||||||
enc_class enc_rethrow()
|
enc_class enc_rethrow()
|
||||||
%{
|
%{
|
||||||
|
@ -12096,52 +11654,67 @@ instruct rep_stos(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy,
|
||||||
ins_pipe(pipe_slow);
|
ins_pipe(pipe_slow);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct string_compare(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2,
|
instruct string_compare(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rbx_RegI cnt2,
|
||||||
rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result, rFlagsReg cr)
|
rax_RegI result, regD tmp1, regD tmp2, rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
match(Set result (StrComp str1 str2));
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
|
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
|
||||||
//ins_cost(300);
|
|
||||||
|
|
||||||
format %{ "String Compare $str1, $str2 -> $result // XXX KILL RAX, RBX" %}
|
format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1, $tmp2" %}
|
||||||
ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
|
ins_encode %{
|
||||||
|
__ string_compare($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register, $result$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
|
||||||
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct string_indexof(rsi_RegP str1, rdi_RegP str2, regD tmp1, rax_RegI tmp2,
|
instruct string_indexof(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
|
||||||
rcx_RegI tmp3, rdx_RegI tmp4, rbx_RegI result, rFlagsReg cr)
|
rbx_RegI result, regD tmp1, rcx_RegI tmp2, rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
predicate(UseSSE42Intrinsics);
|
predicate(UseSSE42Intrinsics);
|
||||||
match(Set result (StrIndexOf str1 str2));
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, KILL tmp2, KILL tmp3, KILL tmp4, KILL cr);
|
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp2, KILL cr);
|
||||||
|
|
||||||
format %{ "String IndexOf $str1,$str2 -> $result // KILL RAX, RCX, RDX" %}
|
format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1, $tmp2" %}
|
||||||
ins_encode( enc_String_IndexOf(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
|
ins_encode %{
|
||||||
|
__ string_indexof($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register, $result$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$Register);
|
||||||
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// fast string equals
|
// fast string equals
|
||||||
instruct string_equals(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, rbx_RegI tmp3,
|
instruct string_equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, rax_RegI result,
|
||||||
rcx_RegI tmp4, rax_RegI result, rFlagsReg cr)
|
regD tmp1, regD tmp2, rbx_RegI tmp3, rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
match(Set result (StrEquals str1 str2));
|
match(Set result (StrEquals (Binary str1 str2) cnt));
|
||||||
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
|
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp3, KILL cr);
|
||||||
|
|
||||||
format %{ "String Equals $str1,$str2 -> $result // KILL RBX, RCX" %}
|
format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
|
||||||
ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
|
ins_encode %{
|
||||||
|
__ char_arrays_equals(false, $str1$$Register, $str2$$Register,
|
||||||
|
$cnt$$Register, $result$$Register, $tmp3$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
|
||||||
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// fast array equals
|
// fast array equals
|
||||||
instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, regD tmp1, regD tmp2, rax_RegI tmp3,
|
instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
|
||||||
rbx_RegI tmp4, rcx_RegI result, rFlagsReg cr)
|
regD tmp1, regD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
match(Set result (AryEq ary1 ary2));
|
match(Set result (AryEq ary1 ary2));
|
||||||
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
|
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
|
||||||
//ins_cost(300);
|
//ins_cost(300);
|
||||||
|
|
||||||
format %{ "Array Equals $ary1,$ary2 -> $result // KILL RAX, RBX" %}
|
format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
|
||||||
ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, tmp4, result) );
|
ins_encode %{
|
||||||
|
__ char_arrays_equals(true, $ary1$$Register, $ary2$$Register,
|
||||||
|
$tmp3$$Register, $result$$Register, $tmp4$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
|
||||||
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -828,11 +828,13 @@ uint InstructForm::oper_input_base(FormDict &globals) {
|
||||||
return AdlcVMDeps::Parms; // Skip the machine-state edges
|
return AdlcVMDeps::Parms; // Skip the machine-state edges
|
||||||
|
|
||||||
if( _matrule->_rChild &&
|
if( _matrule->_rChild &&
|
||||||
( strcmp(_matrule->_rChild->_opType,"StrComp" )==0 ||
|
( strcmp(_matrule->_rChild->_opType,"AryEq" )==0 ||
|
||||||
|
strcmp(_matrule->_rChild->_opType,"StrComp" )==0 ||
|
||||||
strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 ||
|
strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 ||
|
||||||
strcmp(_matrule->_rChild->_opType,"StrIndexOf")==0 )) {
|
strcmp(_matrule->_rChild->_opType,"StrIndexOf")==0 )) {
|
||||||
// String.(compareTo/equals/indexOf) take 1 control and 4 memory edges.
|
// String.(compareTo/equals/indexOf) and Arrays.equals
|
||||||
return 5;
|
// take 1 control and 1 memory edges.
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for handling of 'Memory' input/edge in the ideal world.
|
// Check for handling of 'Memory' input/edge in the ideal world.
|
||||||
|
|
|
@ -1442,7 +1442,7 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
|
||||||
switch (field_type) {
|
switch (field_type) {
|
||||||
case T_ARRAY:
|
case T_ARRAY:
|
||||||
case T_OBJECT:
|
case T_OBJECT:
|
||||||
if (field_val.as_object()->has_encoding()) {
|
if (field_val.as_object()->should_be_constant()) {
|
||||||
constant = new Constant(as_ValueType(field_val));
|
constant = new Constant(as_ValueType(field_val));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -133,12 +133,12 @@ void InstructionPrinter::print_object(Value obj) {
|
||||||
ciMethod* m = (ciMethod*)value;
|
ciMethod* m = (ciMethod*)value;
|
||||||
output()->print("<method %s.%s>", m->holder()->name()->as_utf8(), m->name()->as_utf8());
|
output()->print("<method %s.%s>", m->holder()->name()->as_utf8(), m->name()->as_utf8());
|
||||||
} else {
|
} else {
|
||||||
output()->print("<object 0x%x>", value->encoding());
|
output()->print("<object 0x%x>", value->constant_encoding());
|
||||||
}
|
}
|
||||||
} else if (type->as_InstanceConstant() != NULL) {
|
} else if (type->as_InstanceConstant() != NULL) {
|
||||||
output()->print("<instance 0x%x>", type->as_InstanceConstant()->value()->encoding());
|
output()->print("<instance 0x%x>", type->as_InstanceConstant()->value()->constant_encoding());
|
||||||
} else if (type->as_ArrayConstant() != NULL) {
|
} else if (type->as_ArrayConstant() != NULL) {
|
||||||
output()->print("<array 0x%x>", type->as_ArrayConstant()->value()->encoding());
|
output()->print("<array 0x%x>", type->as_ArrayConstant()->value()->constant_encoding());
|
||||||
} else if (type->as_ClassConstant() != NULL) {
|
} else if (type->as_ClassConstant() != NULL) {
|
||||||
ciInstanceKlass* klass = type->as_ClassConstant()->value();
|
ciInstanceKlass* klass = type->as_ClassConstant()->value();
|
||||||
if (!klass->is_loaded()) {
|
if (!klass->is_loaded()) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -440,7 +440,7 @@ void LIRGenerator::jobject2reg_with_patching(LIR_Opr r, ciObject* obj, CodeEmitI
|
||||||
__ oop2reg_patch(NULL, r, info);
|
__ oop2reg_patch(NULL, r, info);
|
||||||
} else {
|
} else {
|
||||||
// no patching needed
|
// no patching needed
|
||||||
__ oop2reg(obj->encoding(), r);
|
__ oop2reg(obj->constant_encoding(), r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -831,7 +831,7 @@ void LIRGenerator::profile_branch(If* if_instr, If::Condition cond) {
|
||||||
int taken_count_offset = md->byte_offset_of_slot(data, BranchData::taken_offset());
|
int taken_count_offset = md->byte_offset_of_slot(data, BranchData::taken_offset());
|
||||||
int not_taken_count_offset = md->byte_offset_of_slot(data, BranchData::not_taken_offset());
|
int not_taken_count_offset = md->byte_offset_of_slot(data, BranchData::not_taken_offset());
|
||||||
LIR_Opr md_reg = new_register(T_OBJECT);
|
LIR_Opr md_reg = new_register(T_OBJECT);
|
||||||
__ move(LIR_OprFact::oopConst(md->encoding()), md_reg);
|
__ move(LIR_OprFact::oopConst(md->constant_encoding()), md_reg);
|
||||||
LIR_Opr data_offset_reg = new_register(T_INT);
|
LIR_Opr data_offset_reg = new_register(T_INT);
|
||||||
__ cmove(lir_cond(cond),
|
__ cmove(lir_cond(cond),
|
||||||
LIR_OprFact::intConst(taken_count_offset),
|
LIR_OprFact::intConst(taken_count_offset),
|
||||||
|
@ -1071,7 +1071,7 @@ void LIRGenerator::do_Return(Return* x) {
|
||||||
LIR_OprList* args = new LIR_OprList();
|
LIR_OprList* args = new LIR_OprList();
|
||||||
args->append(getThreadPointer());
|
args->append(getThreadPointer());
|
||||||
LIR_Opr meth = new_register(T_OBJECT);
|
LIR_Opr meth = new_register(T_OBJECT);
|
||||||
__ oop2reg(method()->encoding(), meth);
|
__ oop2reg(method()->constant_encoding(), meth);
|
||||||
args->append(meth);
|
args->append(meth);
|
||||||
call_runtime(&signature, args, CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), voidType, NULL);
|
call_runtime(&signature, args, CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), voidType, NULL);
|
||||||
}
|
}
|
||||||
|
@ -1784,7 +1784,7 @@ void LIRGenerator::do_Throw(Throw* x) {
|
||||||
LIR_OprList* args = new LIR_OprList();
|
LIR_OprList* args = new LIR_OprList();
|
||||||
args->append(getThreadPointer());
|
args->append(getThreadPointer());
|
||||||
LIR_Opr meth = new_register(T_OBJECT);
|
LIR_Opr meth = new_register(T_OBJECT);
|
||||||
__ oop2reg(method()->encoding(), meth);
|
__ oop2reg(method()->constant_encoding(), meth);
|
||||||
args->append(meth);
|
args->append(meth);
|
||||||
call_runtime(&signature, args, CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), voidType, NULL);
|
call_runtime(&signature, args, CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), voidType, NULL);
|
||||||
}
|
}
|
||||||
|
@ -2207,7 +2207,7 @@ void LIRGenerator::do_Base(Base* x) {
|
||||||
LIR_OprList* args = new LIR_OprList();
|
LIR_OprList* args = new LIR_OprList();
|
||||||
args->append(getThreadPointer());
|
args->append(getThreadPointer());
|
||||||
LIR_Opr meth = new_register(T_OBJECT);
|
LIR_Opr meth = new_register(T_OBJECT);
|
||||||
__ oop2reg(method()->encoding(), meth);
|
__ oop2reg(method()->constant_encoding(), meth);
|
||||||
args->append(meth);
|
args->append(meth);
|
||||||
call_runtime(&signature, args, CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), voidType, NULL);
|
call_runtime(&signature, args, CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), voidType, NULL);
|
||||||
}
|
}
|
||||||
|
@ -2216,7 +2216,7 @@ void LIRGenerator::do_Base(Base* x) {
|
||||||
LIR_Opr obj;
|
LIR_Opr obj;
|
||||||
if (method()->is_static()) {
|
if (method()->is_static()) {
|
||||||
obj = new_register(T_OBJECT);
|
obj = new_register(T_OBJECT);
|
||||||
__ oop2reg(method()->holder()->java_mirror()->encoding(), obj);
|
__ oop2reg(method()->holder()->java_mirror()->constant_encoding(), obj);
|
||||||
} else {
|
} else {
|
||||||
Local* receiver = x->state()->local_at(0)->as_Local();
|
Local* receiver = x->state()->local_at(0)->as_Local();
|
||||||
assert(receiver != NULL, "must already exist");
|
assert(receiver != NULL, "must already exist");
|
||||||
|
@ -2660,7 +2660,7 @@ void LIRGenerator::increment_invocation_counter(CodeEmitInfo* info, bool backedg
|
||||||
}
|
}
|
||||||
|
|
||||||
LIR_Opr meth = new_register(T_OBJECT);
|
LIR_Opr meth = new_register(T_OBJECT);
|
||||||
__ oop2reg(method()->encoding(), meth);
|
__ oop2reg(method()->constant_encoding(), meth);
|
||||||
LIR_Opr result = increment_and_return_counter(meth, offset, InvocationCounter::count_increment);
|
LIR_Opr result = increment_and_return_counter(meth, offset, InvocationCounter::count_increment);
|
||||||
__ cmp(lir_cond_aboveEqual, result, LIR_OprFact::intConst(limit));
|
__ cmp(lir_cond_aboveEqual, result, LIR_OprFact::intConst(limit));
|
||||||
CodeStub* overflow = new CounterOverflowStub(info, info->bci());
|
CodeStub* overflow = new CounterOverflowStub(info, info->bci());
|
||||||
|
|
|
@ -86,7 +86,7 @@ ValueType* ValueType::join(ValueType* y) const {
|
||||||
|
|
||||||
jobject ObjectType::encoding() const {
|
jobject ObjectType::encoding() const {
|
||||||
assert(is_constant(), "must be");
|
assert(is_constant(), "must be");
|
||||||
return constant_value()->encoding();
|
return constant_value()->constant_encoding();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjectType::is_loaded() const {
|
bool ObjectType::is_loaded() const {
|
||||||
|
|
|
@ -257,7 +257,7 @@ ciMethod* ciEnv::get_method_from_handle(jobject method) {
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciEnv::make_array
|
// ciEnv::make_array
|
||||||
ciArray* ciEnv::make_array(GrowableArray<ciObject*>* objects) {
|
ciArray* ciEnv::make_system_array(GrowableArray<ciObject*>* objects) {
|
||||||
VM_ENTRY_MARK;
|
VM_ENTRY_MARK;
|
||||||
int length = objects->length();
|
int length = objects->length();
|
||||||
objArrayOop a = oopFactory::new_system_objArray(length, THREAD);
|
objArrayOop a = oopFactory::new_system_objArray(length, THREAD);
|
||||||
|
|
|
@ -339,8 +339,8 @@ public:
|
||||||
// but consider adding to vmSymbols.hpp instead.
|
// but consider adding to vmSymbols.hpp instead.
|
||||||
|
|
||||||
// Use this to make a holder for non-perm compile time constants.
|
// Use this to make a holder for non-perm compile time constants.
|
||||||
// The resulting array is guaranteed to satisfy "has_encoding".
|
// The resulting array is guaranteed to satisfy "can_be_constant".
|
||||||
ciArray* make_array(GrowableArray<ciObject*>* objects);
|
ciArray* make_system_array(GrowableArray<ciObject*>* objects);
|
||||||
|
|
||||||
// converts the ciKlass* representing the holder of a method into a
|
// converts the ciKlass* representing the holder of a method into a
|
||||||
// ciInstanceKlass*. This is needed since the holder of a method in
|
// ciInstanceKlass*. This is needed since the holder of a method in
|
||||||
|
|
|
@ -325,10 +325,10 @@ ciTypeFlow* ciMethod::get_osr_flow_analysis(int osr_bci) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciMethod::liveness_at_bci
|
// ciMethod::raw_liveness_at_bci
|
||||||
//
|
//
|
||||||
// Which local variables are live at a specific bci?
|
// Which local variables are live at a specific bci?
|
||||||
MethodLivenessResult ciMethod::liveness_at_bci(int bci) {
|
MethodLivenessResult ciMethod::raw_liveness_at_bci(int bci) {
|
||||||
check_is_loaded();
|
check_is_loaded();
|
||||||
if (_liveness == NULL) {
|
if (_liveness == NULL) {
|
||||||
// Create the liveness analyzer.
|
// Create the liveness analyzer.
|
||||||
|
@ -336,7 +336,17 @@ MethodLivenessResult ciMethod::liveness_at_bci(int bci) {
|
||||||
_liveness = new (arena) MethodLiveness(arena, this);
|
_liveness = new (arena) MethodLiveness(arena, this);
|
||||||
_liveness->compute_liveness();
|
_liveness->compute_liveness();
|
||||||
}
|
}
|
||||||
MethodLivenessResult result = _liveness->get_liveness_at(bci);
|
return _liveness->get_liveness_at(bci);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciMethod::liveness_at_bci
|
||||||
|
//
|
||||||
|
// Which local variables are live at a specific bci? When debugging
|
||||||
|
// will return true for all locals in some cases to improve debug
|
||||||
|
// information.
|
||||||
|
MethodLivenessResult ciMethod::liveness_at_bci(int bci) {
|
||||||
|
MethodLivenessResult result = raw_liveness_at_bci(bci);
|
||||||
if (CURRENT_ENV->jvmti_can_access_local_variables() || DeoptimizeALot || CompileTheWorld) {
|
if (CURRENT_ENV->jvmti_can_access_local_variables() || DeoptimizeALot || CompileTheWorld) {
|
||||||
// Keep all locals live for the user's edification and amusement.
|
// Keep all locals live for the user's edification and amusement.
|
||||||
result.at_put_range(0, result.size(), true);
|
result.at_put_range(0, result.size(), true);
|
||||||
|
|
|
@ -149,6 +149,12 @@ class ciMethod : public ciObject {
|
||||||
bool has_monitor_bytecodes() const { return _uses_monitors; }
|
bool has_monitor_bytecodes() const { return _uses_monitors; }
|
||||||
bool has_balanced_monitors();
|
bool has_balanced_monitors();
|
||||||
|
|
||||||
|
// Returns a bitmap indicating which locals are required to be
|
||||||
|
// maintained as live for deopt. raw_liveness_at_bci is always the
|
||||||
|
// direct output of the liveness computation while liveness_at_bci
|
||||||
|
// may mark all locals as live to improve support for debugging Java
|
||||||
|
// code by maintaining the state of as many locals as possible.
|
||||||
|
MethodLivenessResult raw_liveness_at_bci(int bci);
|
||||||
MethodLivenessResult liveness_at_bci(int bci);
|
MethodLivenessResult liveness_at_bci(int bci);
|
||||||
|
|
||||||
// Get the interpreters viewpoint on oop liveness. MethodLiveness is
|
// Get the interpreters viewpoint on oop liveness. MethodLiveness is
|
||||||
|
|
|
@ -55,6 +55,7 @@ ciObject::ciObject(oop o) {
|
||||||
}
|
}
|
||||||
_klass = NULL;
|
_klass = NULL;
|
||||||
_ident = 0;
|
_ident = 0;
|
||||||
|
init_flags_from(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
@ -69,6 +70,7 @@ ciObject::ciObject(Handle h) {
|
||||||
}
|
}
|
||||||
_klass = NULL;
|
_klass = NULL;
|
||||||
_ident = 0;
|
_ident = 0;
|
||||||
|
init_flags_from(h());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
@ -158,7 +160,7 @@ int ciObject::hash() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciObject::encoding
|
// ciObject::constant_encoding
|
||||||
//
|
//
|
||||||
// The address which the compiler should embed into the
|
// The address which the compiler should embed into the
|
||||||
// generated code to represent this oop. This address
|
// generated code to represent this oop. This address
|
||||||
|
@ -172,16 +174,24 @@ int ciObject::hash() {
|
||||||
//
|
//
|
||||||
// This method should be changed to return an generified address
|
// This method should be changed to return an generified address
|
||||||
// to discourage use of the JNI handle.
|
// to discourage use of the JNI handle.
|
||||||
jobject ciObject::encoding() {
|
jobject ciObject::constant_encoding() {
|
||||||
assert(is_null_object() || handle() != NULL, "cannot embed null pointer");
|
assert(is_null_object() || handle() != NULL, "cannot embed null pointer");
|
||||||
assert(has_encoding(), "oop must be NULL or perm");
|
assert(can_be_constant(), "oop must be NULL or perm");
|
||||||
return handle();
|
return handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciObject::has_encoding
|
// ciObject::can_be_constant
|
||||||
bool ciObject::has_encoding() {
|
bool ciObject::can_be_constant() {
|
||||||
return handle() == NULL || is_perm();
|
if (ScavengeRootsInCode >= 1) return true; // now everybody can encode as a constant
|
||||||
|
return handle() == NULL || !is_scavengable();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciObject::should_be_constant()
|
||||||
|
bool ciObject::should_be_constant() {
|
||||||
|
if (ScavengeRootsInCode >= 2) return true; // force everybody to be a constant
|
||||||
|
return handle() == NULL || !is_scavengable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -195,8 +205,9 @@ bool ciObject::has_encoding() {
|
||||||
void ciObject::print(outputStream* st) {
|
void ciObject::print(outputStream* st) {
|
||||||
st->print("<%s", type_string());
|
st->print("<%s", type_string());
|
||||||
GUARDED_VM_ENTRY(print_impl(st);)
|
GUARDED_VM_ENTRY(print_impl(st);)
|
||||||
st->print(" ident=%d %s address=0x%x>", ident(),
|
st->print(" ident=%d %s%s address=0x%x>", ident(),
|
||||||
is_perm() ? "PERM" : "",
|
is_perm() ? "PERM" : "",
|
||||||
|
is_scavengable() ? "SCAVENGABLE" : "",
|
||||||
(address)this);
|
(address)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,9 +51,10 @@ private:
|
||||||
ciKlass* _klass;
|
ciKlass* _klass;
|
||||||
uint _ident;
|
uint _ident;
|
||||||
|
|
||||||
enum { FLAG_BITS = 1};
|
enum { FLAG_BITS = 2 };
|
||||||
enum {
|
enum {
|
||||||
PERM_FLAG = 1
|
PERM_FLAG = 1,
|
||||||
|
SCAVENGABLE_FLAG = 2
|
||||||
};
|
};
|
||||||
protected:
|
protected:
|
||||||
ciObject();
|
ciObject();
|
||||||
|
@ -68,8 +69,15 @@ protected:
|
||||||
return JNIHandles::resolve_non_null(_handle);
|
return JNIHandles::resolve_non_null(_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_perm() {
|
void init_flags_from(oop x) {
|
||||||
_ident |= PERM_FLAG;
|
int flags = 0;
|
||||||
|
if (x != NULL) {
|
||||||
|
if (x->is_perm())
|
||||||
|
flags |= PERM_FLAG;
|
||||||
|
if (x->is_scavengable())
|
||||||
|
flags |= SCAVENGABLE_FLAG;
|
||||||
|
}
|
||||||
|
_ident |= flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Virtual behavior of the print() method.
|
// Virtual behavior of the print() method.
|
||||||
|
@ -91,17 +99,27 @@ public:
|
||||||
// A hash value for the convenience of compilers.
|
// A hash value for the convenience of compilers.
|
||||||
int hash();
|
int hash();
|
||||||
|
|
||||||
// Tells if this oop has an encoding. (I.e., is it null or perm?)
|
// Tells if this oop has an encoding as a constant.
|
||||||
|
// True if is_scavengable is false.
|
||||||
|
// Also true if ScavengeRootsInCode is non-zero.
|
||||||
// If it does not have an encoding, the compiler is responsible for
|
// If it does not have an encoding, the compiler is responsible for
|
||||||
// making other arrangements for dealing with the oop.
|
// making other arrangements for dealing with the oop.
|
||||||
// See ciEnv::make_perm_array
|
// See ciEnv::make_array
|
||||||
bool has_encoding();
|
bool can_be_constant();
|
||||||
|
|
||||||
|
// Tells if this oop should be made a constant.
|
||||||
|
// True if is_scavengable is false or ScavengeRootsInCode > 1.
|
||||||
|
bool should_be_constant();
|
||||||
|
|
||||||
// Is this object guaranteed to be in the permanent part of the heap?
|
// Is this object guaranteed to be in the permanent part of the heap?
|
||||||
// If so, CollectedHeap::can_elide_permanent_oop_store_barriers is relevant.
|
// If so, CollectedHeap::can_elide_permanent_oop_store_barriers is relevant.
|
||||||
// If the answer is false, no guarantees are made.
|
// If the answer is false, no guarantees are made.
|
||||||
bool is_perm() { return (_ident & PERM_FLAG) != 0; }
|
bool is_perm() { return (_ident & PERM_FLAG) != 0; }
|
||||||
|
|
||||||
|
// Might this object possibly move during a scavenge operation?
|
||||||
|
// If the answer is true and ScavengeRootsInCode==0, the oop cannot be embedded in code.
|
||||||
|
bool is_scavengable() { return (_ident & SCAVENGABLE_FLAG) != 0; }
|
||||||
|
|
||||||
// The address which the compiler should embed into the
|
// The address which the compiler should embed into the
|
||||||
// generated code to represent this oop. This address
|
// generated code to represent this oop. This address
|
||||||
// is not the true address of the oop -- it will get patched
|
// is not the true address of the oop -- it will get patched
|
||||||
|
@ -109,7 +127,7 @@ public:
|
||||||
//
|
//
|
||||||
// Usage note: no address arithmetic allowed. Oop must
|
// Usage note: no address arithmetic allowed. Oop must
|
||||||
// be registered with the oopRecorder.
|
// be registered with the oopRecorder.
|
||||||
jobject encoding();
|
jobject constant_encoding();
|
||||||
|
|
||||||
// What kind of ciObject is this?
|
// What kind of ciObject is this?
|
||||||
virtual bool is_null_object() const { return false; }
|
virtual bool is_null_object() const { return false; }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -261,12 +261,11 @@ ciObject* ciObjectFactory::get(oop key) {
|
||||||
ciObject* new_object = create_new_object(keyHandle());
|
ciObject* new_object = create_new_object(keyHandle());
|
||||||
assert(keyHandle() == new_object->get_oop(), "must be properly recorded");
|
assert(keyHandle() == new_object->get_oop(), "must be properly recorded");
|
||||||
init_ident_of(new_object);
|
init_ident_of(new_object);
|
||||||
if (!keyHandle->is_perm()) {
|
if (!new_object->is_perm()) {
|
||||||
// Not a perm-space object.
|
// Not a perm-space object.
|
||||||
insert_non_perm(bucket, keyHandle(), new_object);
|
insert_non_perm(bucket, keyHandle(), new_object);
|
||||||
return new_object;
|
return new_object;
|
||||||
}
|
}
|
||||||
new_object->set_perm();
|
|
||||||
if (len != _ci_objects->length()) {
|
if (len != _ci_objects->length()) {
|
||||||
// creating the new object has recursively entered new objects
|
// creating the new object has recursively entered new objects
|
||||||
// into the table. We need to recompute our index.
|
// into the table. We need to recompute our index.
|
||||||
|
|
|
@ -2486,8 +2486,13 @@ void ciTypeFlow::build_loop_tree(Block* blk) {
|
||||||
// Assume irreducible entries need more data flow
|
// Assume irreducible entries need more data flow
|
||||||
add_to_work_list(succ);
|
add_to_work_list(succ);
|
||||||
}
|
}
|
||||||
lp = lp->parent();
|
Loop* plp = lp->parent();
|
||||||
assert(lp != NULL, "nested loop must have parent by now");
|
if (plp == NULL) {
|
||||||
|
// This only happens for some irreducible cases. The parent
|
||||||
|
// will be updated during a later pass.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lp = plp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge loop tree branch for all successors.
|
// Merge loop tree branch for all successors.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -2417,6 +2417,8 @@ Handle SystemDictionary::make_dynamic_call_site(KlassHandle caller,
|
||||||
vmSymbols::makeSite_name(), vmSymbols::makeSite_signature(),
|
vmSymbols::makeSite_name(), vmSymbols::makeSite_signature(),
|
||||||
&args, CHECK_(empty));
|
&args, CHECK_(empty));
|
||||||
oop call_site_oop = (oop) result.get_jobject();
|
oop call_site_oop = (oop) result.get_jobject();
|
||||||
|
assert(call_site_oop->is_oop()
|
||||||
|
/*&& sun_dyn_CallSiteImpl::is_instance(call_site_oop)*/, "must be sane");
|
||||||
sun_dyn_CallSiteImpl::set_vmmethod(call_site_oop, mh_invdyn());
|
sun_dyn_CallSiteImpl::set_vmmethod(call_site_oop, mh_invdyn());
|
||||||
if (TraceMethodHandles) {
|
if (TraceMethodHandles) {
|
||||||
tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop);
|
tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop);
|
||||||
|
@ -2453,6 +2455,8 @@ Handle SystemDictionary::find_bootstrap_method(KlassHandle caller,
|
||||||
oop boot_method_oop = (oop) result.get_jobject();
|
oop boot_method_oop = (oop) result.get_jobject();
|
||||||
|
|
||||||
if (boot_method_oop != NULL) {
|
if (boot_method_oop != NULL) {
|
||||||
|
assert(boot_method_oop->is_oop()
|
||||||
|
&& java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane");
|
||||||
// probably no race conditions, but let's be careful:
|
// probably no race conditions, but let's be careful:
|
||||||
if (Atomic::cmpxchg_ptr(boot_method_oop, ik->adr_bootstrap_method(), NULL) == NULL)
|
if (Atomic::cmpxchg_ptr(boot_method_oop, ik->adr_bootstrap_method(), NULL) == NULL)
|
||||||
ik->set_bootstrap_method(boot_method_oop);
|
ik->set_bootstrap_method(boot_method_oop);
|
||||||
|
|
|
@ -175,6 +175,8 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
|
||||||
OopClosure* keep_alive,
|
OopClosure* keep_alive,
|
||||||
bool unloading_occurred);
|
bool unloading_occurred);
|
||||||
virtual void oops_do(OopClosure* f) = 0;
|
virtual void oops_do(OopClosure* f) = 0;
|
||||||
|
// (All CodeBlob subtypes other than NMethod currently have
|
||||||
|
// an empty oops_do() method.
|
||||||
|
|
||||||
// OopMap for frame
|
// OopMap for frame
|
||||||
OopMapSet* oop_maps() const { return _oop_maps; }
|
OopMapSet* oop_maps() const { return _oop_maps; }
|
||||||
|
|
|
@ -95,6 +95,7 @@ CodeHeap * CodeCache::_heap = new CodeHeap();
|
||||||
int CodeCache::_number_of_blobs = 0;
|
int CodeCache::_number_of_blobs = 0;
|
||||||
int CodeCache::_number_of_nmethods_with_dependencies = 0;
|
int CodeCache::_number_of_nmethods_with_dependencies = 0;
|
||||||
bool CodeCache::_needs_cache_clean = false;
|
bool CodeCache::_needs_cache_clean = false;
|
||||||
|
nmethod* CodeCache::_scavenge_root_nmethods = NULL;
|
||||||
|
|
||||||
|
|
||||||
CodeBlob* CodeCache::first() {
|
CodeBlob* CodeCache::first() {
|
||||||
|
@ -148,10 +149,7 @@ CodeBlob* CodeCache::allocate(int size) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
verify_if_often();
|
verify_if_often();
|
||||||
if (PrintCodeCache2) { // Need to add a new flag
|
print_trace("allocation", cb, size);
|
||||||
ResourceMark rm;
|
|
||||||
tty->print_cr("CodeCache allocation: addr: " INTPTR_FORMAT ", size: 0x%x\n", cb, size);
|
|
||||||
}
|
|
||||||
return cb;
|
return cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,10 +157,7 @@ void CodeCache::free(CodeBlob* cb) {
|
||||||
assert_locked_or_safepoint(CodeCache_lock);
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
verify_if_often();
|
verify_if_often();
|
||||||
|
|
||||||
if (PrintCodeCache2) { // Need to add a new flag
|
print_trace("free", cb);
|
||||||
ResourceMark rm;
|
|
||||||
tty->print_cr("CodeCache free: addr: " INTPTR_FORMAT ", size: 0x%x\n", cb, cb->size());
|
|
||||||
}
|
|
||||||
if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) {
|
if (cb->is_nmethod() && ((nmethod *)cb)->has_dependencies()) {
|
||||||
_number_of_nmethods_with_dependencies--;
|
_number_of_nmethods_with_dependencies--;
|
||||||
}
|
}
|
||||||
|
@ -260,14 +255,148 @@ void CodeCache::do_unloading(BoolObjectClosure* is_alive,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeCache::oops_do(OopClosure* f) {
|
void CodeCache::blobs_do(CodeBlobClosure* f) {
|
||||||
assert_locked_or_safepoint(CodeCache_lock);
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
FOR_ALL_ALIVE_BLOBS(cb) {
|
FOR_ALL_ALIVE_BLOBS(cb) {
|
||||||
cb->oops_do(f);
|
f->do_code_blob(cb);
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
if (cb->is_nmethod())
|
||||||
|
((nmethod*)cb)->verify_scavenge_root_oops();
|
||||||
|
#endif //ASSERT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Walk the list of methods which might contain non-perm oops.
|
||||||
|
void CodeCache::scavenge_root_nmethods_do(CodeBlobClosure* f) {
|
||||||
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
|
debug_only(mark_scavenge_root_nmethods());
|
||||||
|
|
||||||
|
for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) {
|
||||||
|
debug_only(cur->clear_scavenge_root_marked());
|
||||||
|
assert(cur->scavenge_root_not_marked(), "");
|
||||||
|
assert(cur->on_scavenge_root_list(), "else shouldn't be on this list");
|
||||||
|
|
||||||
|
bool is_live = (!cur->is_zombie() && !cur->is_unloaded());
|
||||||
|
#ifndef PRODUCT
|
||||||
|
if (TraceScavenge) {
|
||||||
|
cur->print_on(tty, is_live ? "scavenge root" : "dead scavenge root"); tty->cr();
|
||||||
|
}
|
||||||
|
#endif //PRODUCT
|
||||||
|
if (is_live)
|
||||||
|
// Perform cur->oops_do(f), maybe just once per nmethod.
|
||||||
|
f->do_code_blob(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for stray marks.
|
||||||
|
debug_only(verify_perm_nmethods(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeCache::add_scavenge_root_nmethod(nmethod* nm) {
|
||||||
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
|
nm->set_on_scavenge_root_list();
|
||||||
|
nm->set_scavenge_root_link(_scavenge_root_nmethods);
|
||||||
|
set_scavenge_root_nmethods(nm);
|
||||||
|
print_trace("add_scavenge_root", nm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeCache::drop_scavenge_root_nmethod(nmethod* nm) {
|
||||||
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
|
print_trace("drop_scavenge_root", nm);
|
||||||
|
nmethod* last = NULL;
|
||||||
|
nmethod* cur = scavenge_root_nmethods();
|
||||||
|
while (cur != NULL) {
|
||||||
|
nmethod* next = cur->scavenge_root_link();
|
||||||
|
if (cur == nm) {
|
||||||
|
if (last != NULL)
|
||||||
|
last->set_scavenge_root_link(next);
|
||||||
|
else set_scavenge_root_nmethods(next);
|
||||||
|
nm->set_scavenge_root_link(NULL);
|
||||||
|
nm->clear_on_scavenge_root_list();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
last = cur;
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
assert(false, "should have been on list");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeCache::prune_scavenge_root_nmethods() {
|
||||||
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
|
debug_only(mark_scavenge_root_nmethods());
|
||||||
|
|
||||||
|
nmethod* last = NULL;
|
||||||
|
nmethod* cur = scavenge_root_nmethods();
|
||||||
|
while (cur != NULL) {
|
||||||
|
nmethod* next = cur->scavenge_root_link();
|
||||||
|
debug_only(cur->clear_scavenge_root_marked());
|
||||||
|
assert(cur->scavenge_root_not_marked(), "");
|
||||||
|
assert(cur->on_scavenge_root_list(), "else shouldn't be on this list");
|
||||||
|
|
||||||
|
if (!cur->is_zombie() && !cur->is_unloaded()
|
||||||
|
&& cur->detect_scavenge_root_oops()) {
|
||||||
|
// Keep it. Advance 'last' to prevent deletion.
|
||||||
|
last = cur;
|
||||||
|
} else {
|
||||||
|
// Prune it from the list, so we don't have to look at it any more.
|
||||||
|
print_trace("prune_scavenge_root", cur);
|
||||||
|
cur->set_scavenge_root_link(NULL);
|
||||||
|
cur->clear_on_scavenge_root_list();
|
||||||
|
if (last != NULL)
|
||||||
|
last->set_scavenge_root_link(next);
|
||||||
|
else set_scavenge_root_nmethods(next);
|
||||||
|
}
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for stray marks.
|
||||||
|
debug_only(verify_perm_nmethods(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef PRODUCT
|
||||||
|
void CodeCache::asserted_non_scavengable_nmethods_do(CodeBlobClosure* f) {
|
||||||
|
// While we are here, verify the integrity of the list.
|
||||||
|
mark_scavenge_root_nmethods();
|
||||||
|
for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) {
|
||||||
|
assert(cur->on_scavenge_root_list(), "else shouldn't be on this list");
|
||||||
|
cur->clear_scavenge_root_marked();
|
||||||
|
}
|
||||||
|
verify_perm_nmethods(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temporarily mark nmethods that are claimed to be on the non-perm list.
|
||||||
|
void CodeCache::mark_scavenge_root_nmethods() {
|
||||||
|
FOR_ALL_ALIVE_BLOBS(cb) {
|
||||||
|
if (cb->is_nmethod()) {
|
||||||
|
nmethod *nm = (nmethod*)cb;
|
||||||
|
assert(nm->scavenge_root_not_marked(), "clean state");
|
||||||
|
if (nm->on_scavenge_root_list())
|
||||||
|
nm->set_scavenge_root_marked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the closure is given, run it on the unlisted nmethods.
|
||||||
|
// Also make sure that the effects of mark_scavenge_root_nmethods is gone.
|
||||||
|
void CodeCache::verify_perm_nmethods(CodeBlobClosure* f_or_null) {
|
||||||
|
FOR_ALL_ALIVE_BLOBS(cb) {
|
||||||
|
bool call_f = (f_or_null != NULL);
|
||||||
|
if (cb->is_nmethod()) {
|
||||||
|
nmethod *nm = (nmethod*)cb;
|
||||||
|
assert(nm->scavenge_root_not_marked(), "must be already processed");
|
||||||
|
if (nm->on_scavenge_root_list())
|
||||||
|
call_f = false; // don't show this one to the client
|
||||||
|
nm->verify_scavenge_root_oops();
|
||||||
|
} else {
|
||||||
|
call_f = false; // not an nmethod
|
||||||
|
}
|
||||||
|
if (call_f) f_or_null->do_code_blob(cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif //PRODUCT
|
||||||
|
|
||||||
void CodeCache::gc_prologue() {
|
void CodeCache::gc_prologue() {
|
||||||
|
assert(!nmethod::oops_do_marking_is_active(), "oops_do_marking_epilogue must be called");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -285,6 +414,8 @@ void CodeCache::gc_epilogue() {
|
||||||
cb->fix_oop_relocations();
|
cb->fix_oop_relocations();
|
||||||
}
|
}
|
||||||
set_needs_cache_clean(false);
|
set_needs_cache_clean(false);
|
||||||
|
prune_scavenge_root_nmethods();
|
||||||
|
assert(!nmethod::oops_do_marking_is_active(), "oops_do_marking_prologue must be called");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -508,6 +639,14 @@ void CodeCache::verify_if_often() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CodeCache::print_trace(const char* event, CodeBlob* cb, int size) {
|
||||||
|
if (PrintCodeCache2) { // Need to add a new flag
|
||||||
|
ResourceMark rm;
|
||||||
|
if (size == 0) size = cb->size();
|
||||||
|
tty->print_cr("CodeCache %s: addr: " INTPTR_FORMAT ", size: 0x%x", event, cb, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CodeCache::print_internals() {
|
void CodeCache::print_internals() {
|
||||||
int nmethodCount = 0;
|
int nmethodCount = 0;
|
||||||
int runtimeStubCount = 0;
|
int runtimeStubCount = 0;
|
||||||
|
|
|
@ -45,8 +45,13 @@ class CodeCache : AllStatic {
|
||||||
static int _number_of_blobs;
|
static int _number_of_blobs;
|
||||||
static int _number_of_nmethods_with_dependencies;
|
static int _number_of_nmethods_with_dependencies;
|
||||||
static bool _needs_cache_clean;
|
static bool _needs_cache_clean;
|
||||||
|
static nmethod* _scavenge_root_nmethods; // linked via nm->scavenge_root_link()
|
||||||
|
|
||||||
static void verify_if_often() PRODUCT_RETURN;
|
static void verify_if_often() PRODUCT_RETURN;
|
||||||
|
|
||||||
|
static void mark_scavenge_root_nmethods() PRODUCT_RETURN;
|
||||||
|
static void verify_perm_nmethods(CodeBlobClosure* f_or_null) PRODUCT_RETURN;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
|
@ -61,6 +66,7 @@ class CodeCache : AllStatic {
|
||||||
static void flush(); // flushes all CodeBlobs
|
static void flush(); // flushes all CodeBlobs
|
||||||
static bool contains(void *p); // returns whether p is included
|
static bool contains(void *p); // returns whether p is included
|
||||||
static void blobs_do(void f(CodeBlob* cb)); // iterates over all CodeBlobs
|
static void blobs_do(void f(CodeBlob* cb)); // iterates over all CodeBlobs
|
||||||
|
static void blobs_do(CodeBlobClosure* f); // iterates over all CodeBlobs
|
||||||
static void nmethods_do(void f(nmethod* nm)); // iterates over all nmethods
|
static void nmethods_do(void f(nmethod* nm)); // iterates over all nmethods
|
||||||
|
|
||||||
// Lookup
|
// Lookup
|
||||||
|
@ -106,12 +112,24 @@ class CodeCache : AllStatic {
|
||||||
static void do_unloading(BoolObjectClosure* is_alive,
|
static void do_unloading(BoolObjectClosure* is_alive,
|
||||||
OopClosure* keep_alive,
|
OopClosure* keep_alive,
|
||||||
bool unloading_occurred);
|
bool unloading_occurred);
|
||||||
static void oops_do(OopClosure* f);
|
static void oops_do(OopClosure* f) {
|
||||||
|
CodeBlobToOopClosure oopc(f, /*do_marking=*/ false);
|
||||||
|
blobs_do(&oopc);
|
||||||
|
}
|
||||||
|
static void asserted_non_scavengable_nmethods_do(CodeBlobClosure* f = NULL) PRODUCT_RETURN;
|
||||||
|
static void scavenge_root_nmethods_do(CodeBlobClosure* f);
|
||||||
|
|
||||||
|
static nmethod* scavenge_root_nmethods() { return _scavenge_root_nmethods; }
|
||||||
|
static void set_scavenge_root_nmethods(nmethod* nm) { _scavenge_root_nmethods = nm; }
|
||||||
|
static void add_scavenge_root_nmethod(nmethod* nm);
|
||||||
|
static void drop_scavenge_root_nmethod(nmethod* nm);
|
||||||
|
static void prune_scavenge_root_nmethods();
|
||||||
|
|
||||||
// Printing/debugging
|
// Printing/debugging
|
||||||
static void print() PRODUCT_RETURN; // prints summary
|
static void print() PRODUCT_RETURN; // prints summary
|
||||||
static void print_internals();
|
static void print_internals();
|
||||||
static void verify(); // verifies the code cache
|
static void verify(); // verifies the code cache
|
||||||
|
static void print_trace(const char* event, CodeBlob* cb, int size = 0) PRODUCT_RETURN;
|
||||||
|
|
||||||
// The full limits of the codeCache
|
// The full limits of the codeCache
|
||||||
static address low_bound() { return (address) _heap->low_boundary(); }
|
static address low_bound() { return (address) _heap->low_boundary(); }
|
||||||
|
|
|
@ -299,7 +299,7 @@ void DebugInformationRecorder::describe_scope(int pc_offset,
|
||||||
stream()->write_int(sender_stream_offset);
|
stream()->write_int(sender_stream_offset);
|
||||||
|
|
||||||
// serialize scope
|
// serialize scope
|
||||||
jobject method_enc = (method == NULL)? NULL: method->encoding();
|
jobject method_enc = (method == NULL)? NULL: method->constant_encoding();
|
||||||
stream()->write_int(oop_recorder()->find_index(method_enc));
|
stream()->write_int(oop_recorder()->find_index(method_enc));
|
||||||
stream()->write_bci(bci);
|
stream()->write_bci(bci);
|
||||||
assert(method == NULL ||
|
assert(method == NULL ||
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -302,7 +302,7 @@ void Dependencies::encode_content_bytes() {
|
||||||
bytes.write_byte(code_byte);
|
bytes.write_byte(code_byte);
|
||||||
for (int j = 0; j < stride; j++) {
|
for (int j = 0; j < stride; j++) {
|
||||||
if (j == skipj) continue;
|
if (j == skipj) continue;
|
||||||
bytes.write_int(_oop_recorder->find_index(deps->at(i+j)->encoding()));
|
bytes.write_int(_oop_recorder->find_index(deps->at(i+j)->constant_encoding()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -581,10 +581,13 @@ nmethod::nmethod(
|
||||||
debug_only(No_Safepoint_Verifier nsv;)
|
debug_only(No_Safepoint_Verifier nsv;)
|
||||||
assert_locked_or_safepoint(CodeCache_lock);
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
|
|
||||||
NOT_PRODUCT(_has_debug_info = false; )
|
NOT_PRODUCT(_has_debug_info = false);
|
||||||
|
_oops_do_mark_link = NULL;
|
||||||
_method = method;
|
_method = method;
|
||||||
_entry_bci = InvocationEntryBci;
|
_entry_bci = InvocationEntryBci;
|
||||||
_link = NULL;
|
_osr_link = NULL;
|
||||||
|
_scavenge_root_link = NULL;
|
||||||
|
_scavenge_root_state = 0;
|
||||||
_compiler = NULL;
|
_compiler = NULL;
|
||||||
// We have no exception handler or deopt handler make the
|
// We have no exception handler or deopt handler make the
|
||||||
// values something that will never match a pc like the nmethod vtable entry
|
// values something that will never match a pc like the nmethod vtable entry
|
||||||
|
@ -618,7 +621,7 @@ nmethod::nmethod(
|
||||||
_stack_traversal_mark = 0;
|
_stack_traversal_mark = 0;
|
||||||
|
|
||||||
code_buffer->copy_oops_to(this);
|
code_buffer->copy_oops_to(this);
|
||||||
debug_only(check_store();)
|
debug_only(verify_scavenge_root_oops());
|
||||||
CodeCache::commit(this);
|
CodeCache::commit(this);
|
||||||
VTune::create_nmethod(this);
|
VTune::create_nmethod(this);
|
||||||
}
|
}
|
||||||
|
@ -668,10 +671,13 @@ nmethod::nmethod(
|
||||||
debug_only(No_Safepoint_Verifier nsv;)
|
debug_only(No_Safepoint_Verifier nsv;)
|
||||||
assert_locked_or_safepoint(CodeCache_lock);
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
|
|
||||||
NOT_PRODUCT(_has_debug_info = false; )
|
NOT_PRODUCT(_has_debug_info = false);
|
||||||
|
_oops_do_mark_link = NULL;
|
||||||
_method = method;
|
_method = method;
|
||||||
_entry_bci = InvocationEntryBci;
|
_entry_bci = InvocationEntryBci;
|
||||||
_link = NULL;
|
_osr_link = NULL;
|
||||||
|
_scavenge_root_link = NULL;
|
||||||
|
_scavenge_root_state = 0;
|
||||||
_compiler = NULL;
|
_compiler = NULL;
|
||||||
// We have no exception handler or deopt handler make the
|
// We have no exception handler or deopt handler make the
|
||||||
// values something that will never match a pc like the nmethod vtable entry
|
// values something that will never match a pc like the nmethod vtable entry
|
||||||
|
@ -703,7 +709,7 @@ nmethod::nmethod(
|
||||||
_stack_traversal_mark = 0;
|
_stack_traversal_mark = 0;
|
||||||
|
|
||||||
code_buffer->copy_oops_to(this);
|
code_buffer->copy_oops_to(this);
|
||||||
debug_only(check_store();)
|
debug_only(verify_scavenge_root_oops());
|
||||||
CodeCache::commit(this);
|
CodeCache::commit(this);
|
||||||
VTune::create_nmethod(this);
|
VTune::create_nmethod(this);
|
||||||
}
|
}
|
||||||
|
@ -770,12 +776,15 @@ nmethod::nmethod(
|
||||||
debug_only(No_Safepoint_Verifier nsv;)
|
debug_only(No_Safepoint_Verifier nsv;)
|
||||||
assert_locked_or_safepoint(CodeCache_lock);
|
assert_locked_or_safepoint(CodeCache_lock);
|
||||||
|
|
||||||
NOT_PRODUCT(_has_debug_info = false; )
|
NOT_PRODUCT(_has_debug_info = false);
|
||||||
|
_oops_do_mark_link = NULL;
|
||||||
_method = method;
|
_method = method;
|
||||||
_compile_id = compile_id;
|
_compile_id = compile_id;
|
||||||
_comp_level = comp_level;
|
_comp_level = comp_level;
|
||||||
_entry_bci = entry_bci;
|
_entry_bci = entry_bci;
|
||||||
_link = NULL;
|
_osr_link = NULL;
|
||||||
|
_scavenge_root_link = NULL;
|
||||||
|
_scavenge_root_state = 0;
|
||||||
_compiler = compiler;
|
_compiler = compiler;
|
||||||
_orig_pc_offset = orig_pc_offset;
|
_orig_pc_offset = orig_pc_offset;
|
||||||
#ifdef HAVE_DTRACE_H
|
#ifdef HAVE_DTRACE_H
|
||||||
|
@ -813,7 +822,10 @@ nmethod::nmethod(
|
||||||
code_buffer->copy_oops_to(this);
|
code_buffer->copy_oops_to(this);
|
||||||
debug_info->copy_to(this);
|
debug_info->copy_to(this);
|
||||||
dependencies->copy_to(this);
|
dependencies->copy_to(this);
|
||||||
debug_only(check_store();)
|
if (ScavengeRootsInCode && detect_scavenge_root_oops()) {
|
||||||
|
CodeCache::add_scavenge_root_nmethod(this);
|
||||||
|
}
|
||||||
|
debug_only(verify_scavenge_root_oops());
|
||||||
|
|
||||||
CodeCache::commit(this);
|
CodeCache::commit(this);
|
||||||
|
|
||||||
|
@ -902,23 +914,30 @@ void nmethod::print_on(outputStream* st, const char* title) const {
|
||||||
if (st != NULL) {
|
if (st != NULL) {
|
||||||
ttyLocker ttyl;
|
ttyLocker ttyl;
|
||||||
// Print a little tag line that looks like +PrintCompilation output:
|
// Print a little tag line that looks like +PrintCompilation output:
|
||||||
st->print("%3d%c %s",
|
int tlen = (int) strlen(title);
|
||||||
|
bool do_nl = false;
|
||||||
|
if (tlen > 0 && title[tlen-1] == '\n') { tlen--; do_nl = true; }
|
||||||
|
st->print("%3d%c %.*s",
|
||||||
compile_id(),
|
compile_id(),
|
||||||
is_osr_method() ? '%' :
|
is_osr_method() ? '%' :
|
||||||
method() != NULL &&
|
method() != NULL &&
|
||||||
is_native_method() ? 'n' : ' ',
|
is_native_method() ? 'n' : ' ',
|
||||||
title);
|
tlen, title);
|
||||||
#ifdef TIERED
|
#ifdef TIERED
|
||||||
st->print(" (%d) ", comp_level());
|
st->print(" (%d) ", comp_level());
|
||||||
#endif // TIERED
|
#endif // TIERED
|
||||||
if (WizardMode) st->print(" (" INTPTR_FORMAT ")", this);
|
if (WizardMode) st->print(" (" INTPTR_FORMAT ")", this);
|
||||||
if (method() != NULL) {
|
if (Universe::heap()->is_gc_active() && method() != NULL) {
|
||||||
|
st->print("(method)");
|
||||||
|
} else if (method() != NULL) {
|
||||||
method()->print_short_name(st);
|
method()->print_short_name(st);
|
||||||
if (is_osr_method())
|
if (is_osr_method())
|
||||||
st->print(" @ %d", osr_entry_bci());
|
st->print(" @ %d", osr_entry_bci());
|
||||||
if (method()->code_size() > 0)
|
if (method()->code_size() > 0)
|
||||||
st->print(" (%d bytes)", method()->code_size());
|
st->print(" (%d bytes)", method()->code_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (do_nl) st->cr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1033,6 +1052,7 @@ void nmethod::cleanup_inline_caches() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a private interface with the sweeper.
|
||||||
void nmethod::mark_as_seen_on_stack() {
|
void nmethod::mark_as_seen_on_stack() {
|
||||||
assert(is_not_entrant(), "must be a non-entrant method");
|
assert(is_not_entrant(), "must be a non-entrant method");
|
||||||
set_stack_traversal_mark(NMethodSweeper::traversal_count());
|
set_stack_traversal_mark(NMethodSweeper::traversal_count());
|
||||||
|
@ -1077,6 +1097,7 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
|
||||||
" unloadable], methodOop(" INTPTR_FORMAT
|
" unloadable], methodOop(" INTPTR_FORMAT
|
||||||
"), cause(" INTPTR_FORMAT ")",
|
"), cause(" INTPTR_FORMAT ")",
|
||||||
this, (address)_method, (address)cause);
|
this, (address)_method, (address)cause);
|
||||||
|
if (!Universe::heap()->is_gc_active())
|
||||||
cause->klass()->print();
|
cause->klass()->print();
|
||||||
}
|
}
|
||||||
// Unlink the osr method, so we do not look this up again
|
// Unlink the osr method, so we do not look this up again
|
||||||
|
@ -1109,7 +1130,8 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
|
||||||
// The methodOop is gone at this point
|
// The methodOop is gone at this point
|
||||||
assert(_method == NULL, "Tautology");
|
assert(_method == NULL, "Tautology");
|
||||||
|
|
||||||
set_link(NULL);
|
set_osr_link(NULL);
|
||||||
|
//set_scavenge_root_link(NULL); // done by prune_scavenge_root_nmethods
|
||||||
NMethodSweeper::notify(this);
|
NMethodSweeper::notify(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1295,6 +1317,10 @@ void nmethod::flush() {
|
||||||
ec = next;
|
ec = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (on_scavenge_root_list()) {
|
||||||
|
CodeCache::drop_scavenge_root_nmethod(this);
|
||||||
|
}
|
||||||
|
|
||||||
((CodeBlob*)(this))->flush();
|
((CodeBlob*)(this))->flush();
|
||||||
|
|
||||||
CodeCache::free(this);
|
CodeCache::free(this);
|
||||||
|
@ -1354,7 +1380,10 @@ bool nmethod::can_unload(BoolObjectClosure* is_alive,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(unloading_occurred, "Inconsistency in unloading");
|
// If ScavengeRootsInCode is true, an nmethod might be unloaded
|
||||||
|
// simply because one of its constant oops has gone dead.
|
||||||
|
// No actual classes need to be unloaded in order for this to occur.
|
||||||
|
assert(unloading_occurred || ScavengeRootsInCode, "Inconsistency in unloading");
|
||||||
make_unloaded(is_alive, obj);
|
make_unloaded(is_alive, obj);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1529,13 +1558,12 @@ void nmethod::do_unloading(BoolObjectClosure* is_alive,
|
||||||
// the (strong) marking phase, and then again when walking
|
// the (strong) marking phase, and then again when walking
|
||||||
// the code cache contents during the weak roots processing
|
// the code cache contents during the weak roots processing
|
||||||
// phase. The two uses are distinguished by means of the
|
// phase. The two uses are distinguished by means of the
|
||||||
// do_nmethods() method in the closure "f" below -- which
|
// 'do_strong_roots_only' flag, which is true in the first
|
||||||
// answers "yes" in the first case, and "no" in the second
|
|
||||||
// case. We want to walk the weak roots in the nmethod
|
// case. We want to walk the weak roots in the nmethod
|
||||||
// only in the second case. The weak roots in the nmethod
|
// only in the second case. The weak roots in the nmethod
|
||||||
// are the oops in the ExceptionCache and the InlineCache
|
// are the oops in the ExceptionCache and the InlineCache
|
||||||
// oops.
|
// oops.
|
||||||
void nmethod::oops_do(OopClosure* f) {
|
void nmethod::oops_do(OopClosure* f, bool do_strong_roots_only) {
|
||||||
// make sure the oops ready to receive visitors
|
// make sure the oops ready to receive visitors
|
||||||
assert(!is_zombie() && !is_unloaded(),
|
assert(!is_zombie() && !is_unloaded(),
|
||||||
"should not call follow on zombie or unloaded nmethod");
|
"should not call follow on zombie or unloaded nmethod");
|
||||||
|
@ -1553,7 +1581,7 @@ void nmethod::oops_do(OopClosure* f) {
|
||||||
|
|
||||||
// Compiled code
|
// Compiled code
|
||||||
f->do_oop((oop*) &_method);
|
f->do_oop((oop*) &_method);
|
||||||
if (!f->do_nmethods()) {
|
if (!do_strong_roots_only) {
|
||||||
// weak roots processing phase -- update ExceptionCache oops
|
// weak roots processing phase -- update ExceptionCache oops
|
||||||
ExceptionCache* ec = exception_cache();
|
ExceptionCache* ec = exception_cache();
|
||||||
while(ec != NULL) {
|
while(ec != NULL) {
|
||||||
|
@ -1579,12 +1607,108 @@ void nmethod::oops_do(OopClosure* f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scopes
|
// Scopes
|
||||||
|
// This includes oop constants not inlined in the code stream.
|
||||||
for (oop* p = oops_begin(); p < oops_end(); p++) {
|
for (oop* p = oops_begin(); p < oops_end(); p++) {
|
||||||
if (*p == Universe::non_oop_word()) continue; // skip non-oops
|
if (*p == Universe::non_oop_word()) continue; // skip non-oops
|
||||||
f->do_oop(p);
|
f->do_oop(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define NMETHOD_SENTINEL ((nmethod*)badAddress)
|
||||||
|
|
||||||
|
nmethod* volatile nmethod::_oops_do_mark_nmethods;
|
||||||
|
|
||||||
|
// An nmethod is "marked" if its _mark_link is set non-null.
|
||||||
|
// Even if it is the end of the linked list, it will have a non-null link value,
|
||||||
|
// as long as it is on the list.
|
||||||
|
// This code must be MP safe, because it is used from parallel GC passes.
|
||||||
|
bool nmethod::test_set_oops_do_mark() {
|
||||||
|
assert(nmethod::oops_do_marking_is_active(), "oops_do_marking_prologue must be called");
|
||||||
|
nmethod* observed_mark_link = _oops_do_mark_link;
|
||||||
|
if (observed_mark_link == NULL) {
|
||||||
|
// Claim this nmethod for this thread to mark.
|
||||||
|
observed_mark_link = (nmethod*)
|
||||||
|
Atomic::cmpxchg_ptr(NMETHOD_SENTINEL, &_oops_do_mark_link, NULL);
|
||||||
|
if (observed_mark_link == NULL) {
|
||||||
|
|
||||||
|
// Atomically append this nmethod (now claimed) to the head of the list:
|
||||||
|
nmethod* observed_mark_nmethods = _oops_do_mark_nmethods;
|
||||||
|
for (;;) {
|
||||||
|
nmethod* required_mark_nmethods = observed_mark_nmethods;
|
||||||
|
_oops_do_mark_link = required_mark_nmethods;
|
||||||
|
observed_mark_nmethods = (nmethod*)
|
||||||
|
Atomic::cmpxchg_ptr(this, &_oops_do_mark_nmethods, required_mark_nmethods);
|
||||||
|
if (observed_mark_nmethods == required_mark_nmethods)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Mark was clear when we first saw this guy.
|
||||||
|
NOT_PRODUCT(if (TraceScavenge) print_on(tty, "oops_do, mark\n"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// On fall through, another racing thread marked this nmethod before we did.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nmethod::oops_do_marking_prologue() {
|
||||||
|
NOT_PRODUCT(if (TraceScavenge) tty->print_cr("[oops_do_marking_prologue"));
|
||||||
|
assert(_oops_do_mark_nmethods == NULL, "must not call oops_do_marking_prologue twice in a row");
|
||||||
|
// We use cmpxchg_ptr instead of regular assignment here because the user
|
||||||
|
// may fork a bunch of threads, and we need them all to see the same state.
|
||||||
|
void* observed = Atomic::cmpxchg_ptr(NMETHOD_SENTINEL, &_oops_do_mark_nmethods, NULL);
|
||||||
|
guarantee(observed == NULL, "no races in this sequential code");
|
||||||
|
}
|
||||||
|
|
||||||
|
void nmethod::oops_do_marking_epilogue() {
|
||||||
|
assert(_oops_do_mark_nmethods != NULL, "must not call oops_do_marking_epilogue twice in a row");
|
||||||
|
nmethod* cur = _oops_do_mark_nmethods;
|
||||||
|
while (cur != NMETHOD_SENTINEL) {
|
||||||
|
assert(cur != NULL, "not NULL-terminated");
|
||||||
|
nmethod* next = cur->_oops_do_mark_link;
|
||||||
|
cur->_oops_do_mark_link = NULL;
|
||||||
|
NOT_PRODUCT(if (TraceScavenge) cur->print_on(tty, "oops_do, unmark\n"));
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
void* required = _oops_do_mark_nmethods;
|
||||||
|
void* observed = Atomic::cmpxchg_ptr(NULL, &_oops_do_mark_nmethods, required);
|
||||||
|
guarantee(observed == required, "no races in this sequential code");
|
||||||
|
NOT_PRODUCT(if (TraceScavenge) tty->print_cr("oops_do_marking_epilogue]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
class DetectScavengeRoot: public OopClosure {
|
||||||
|
bool _detected_scavenge_root;
|
||||||
|
public:
|
||||||
|
DetectScavengeRoot() : _detected_scavenge_root(false)
|
||||||
|
{ NOT_PRODUCT(_print_nm = NULL); }
|
||||||
|
bool detected_scavenge_root() { return _detected_scavenge_root; }
|
||||||
|
virtual void do_oop(oop* p) {
|
||||||
|
if ((*p) != NULL && (*p)->is_scavengable()) {
|
||||||
|
NOT_PRODUCT(maybe_print(p));
|
||||||
|
_detected_scavenge_root = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
|
||||||
|
|
||||||
|
#ifndef PRODUCT
|
||||||
|
nmethod* _print_nm;
|
||||||
|
void maybe_print(oop* p) {
|
||||||
|
if (_print_nm == NULL) return;
|
||||||
|
if (!_detected_scavenge_root) _print_nm->print_on(tty, "new scavenge root");
|
||||||
|
tty->print_cr(""PTR_FORMAT"[offset=%d] detected non-perm oop "PTR_FORMAT" (found at "PTR_FORMAT")",
|
||||||
|
_print_nm, (int)((intptr_t)p - (intptr_t)_print_nm),
|
||||||
|
(intptr_t)(*p), (intptr_t)p);
|
||||||
|
(*p)->print();
|
||||||
|
}
|
||||||
|
#endif //PRODUCT
|
||||||
|
};
|
||||||
|
|
||||||
|
bool nmethod::detect_scavenge_root_oops() {
|
||||||
|
DetectScavengeRoot detect_scavenge_root;
|
||||||
|
NOT_PRODUCT(if (TraceScavenge) detect_scavenge_root._print_nm = this);
|
||||||
|
oops_do(&detect_scavenge_root);
|
||||||
|
return detect_scavenge_root.detected_scavenge_root();
|
||||||
|
}
|
||||||
|
|
||||||
// Method that knows how to preserve outgoing arguments at call. This method must be
|
// Method that knows how to preserve outgoing arguments at call. This method must be
|
||||||
// called with a frame corresponding to a Java invoke
|
// called with a frame corresponding to a Java invoke
|
||||||
void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) {
|
void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) {
|
||||||
|
@ -1899,6 +2023,24 @@ bool nmethod::is_deopt_pc(address pc) {
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Verification
|
// Verification
|
||||||
|
|
||||||
|
class VerifyOopsClosure: public OopClosure {
|
||||||
|
nmethod* _nm;
|
||||||
|
bool _ok;
|
||||||
|
public:
|
||||||
|
VerifyOopsClosure(nmethod* nm) : _nm(nm), _ok(true) { }
|
||||||
|
bool ok() { return _ok; }
|
||||||
|
virtual void do_oop(oop* p) {
|
||||||
|
if ((*p) == NULL || (*p)->is_oop()) return;
|
||||||
|
if (_ok) {
|
||||||
|
_nm->print_nmethod(true);
|
||||||
|
_ok = false;
|
||||||
|
}
|
||||||
|
tty->print_cr("*** non-oop "PTR_FORMAT" found at "PTR_FORMAT" (offset %d)",
|
||||||
|
(intptr_t)(*p), (intptr_t)p, (int)((intptr_t)p - (intptr_t)_nm));
|
||||||
|
}
|
||||||
|
virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
|
||||||
|
};
|
||||||
|
|
||||||
void nmethod::verify() {
|
void nmethod::verify() {
|
||||||
|
|
||||||
// Hmm. OSR methods can be deopted but not marked as zombie or not_entrant
|
// Hmm. OSR methods can be deopted but not marked as zombie or not_entrant
|
||||||
|
@ -1932,6 +2074,11 @@ void nmethod::verify() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VerifyOopsClosure voc(this);
|
||||||
|
oops_do(&voc);
|
||||||
|
assert(voc.ok(), "embedded oops must be OK");
|
||||||
|
verify_scavenge_root_oops();
|
||||||
|
|
||||||
verify_scopes();
|
verify_scopes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1995,19 +2142,34 @@ void nmethod::verify_scopes() {
|
||||||
// Non-product code
|
// Non-product code
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
|
||||||
void nmethod::check_store() {
|
class DebugScavengeRoot: public OopClosure {
|
||||||
// Make sure all oops in the compiled code are tenured
|
nmethod* _nm;
|
||||||
|
bool _ok;
|
||||||
|
public:
|
||||||
|
DebugScavengeRoot(nmethod* nm) : _nm(nm), _ok(true) { }
|
||||||
|
bool ok() { return _ok; }
|
||||||
|
virtual void do_oop(oop* p) {
|
||||||
|
if ((*p) == NULL || !(*p)->is_scavengable()) return;
|
||||||
|
if (_ok) {
|
||||||
|
_nm->print_nmethod(true);
|
||||||
|
_ok = false;
|
||||||
|
}
|
||||||
|
tty->print_cr("*** non-perm oop "PTR_FORMAT" found at "PTR_FORMAT" (offset %d)",
|
||||||
|
(intptr_t)(*p), (intptr_t)p, (int)((intptr_t)p - (intptr_t)_nm));
|
||||||
|
(*p)->print();
|
||||||
|
}
|
||||||
|
virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
|
||||||
|
};
|
||||||
|
|
||||||
RelocIterator iter(this);
|
void nmethod::verify_scavenge_root_oops() {
|
||||||
while (iter.next()) {
|
if (!on_scavenge_root_list()) {
|
||||||
if (iter.type() == relocInfo::oop_type) {
|
// Actually look inside, to verify the claim that it's clean.
|
||||||
oop_Relocation* reloc = iter.oop_reloc();
|
DebugScavengeRoot debug_scavenge_root(this);
|
||||||
oop obj = reloc->oop_value();
|
oops_do(&debug_scavenge_root);
|
||||||
if (obj != NULL && !obj->is_perm()) {
|
if (!debug_scavenge_root.ok())
|
||||||
fatal("must be permanent oop in compiled code");
|
fatal("found an unadvertised bad non-perm oop in the code cache");
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
assert(scavenge_root_not_marked(), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
@ -2040,6 +2202,7 @@ void nmethod::print() const {
|
||||||
if (is_not_entrant()) tty->print("not_entrant ");
|
if (is_not_entrant()) tty->print("not_entrant ");
|
||||||
if (is_zombie()) tty->print("zombie ");
|
if (is_zombie()) tty->print("zombie ");
|
||||||
if (is_unloaded()) tty->print("unloaded ");
|
if (is_unloaded()) tty->print("unloaded ");
|
||||||
|
if (on_scavenge_root_list()) tty->print("scavenge_root ");
|
||||||
tty->print_cr("}:");
|
tty->print_cr("}:");
|
||||||
}
|
}
|
||||||
if (size () > 0) tty->print_cr(" total in heap [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
|
if (size () > 0) tty->print_cr(" total in heap [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -125,6 +125,7 @@ class xmlStream;
|
||||||
class nmethod : public CodeBlob {
|
class nmethod : public CodeBlob {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
friend class NMethodSweeper;
|
friend class NMethodSweeper;
|
||||||
|
friend class CodeCache; // non-perm oops
|
||||||
private:
|
private:
|
||||||
// Shared fields for all nmethod's
|
// Shared fields for all nmethod's
|
||||||
static int _zombie_instruction_size;
|
static int _zombie_instruction_size;
|
||||||
|
@ -132,7 +133,12 @@ class nmethod : public CodeBlob {
|
||||||
methodOop _method;
|
methodOop _method;
|
||||||
int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method
|
int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method
|
||||||
|
|
||||||
nmethod* _link; // To support simple linked-list chaining of nmethods
|
// To support simple linked-list chaining of nmethods:
|
||||||
|
nmethod* _osr_link; // from instanceKlass::osr_nmethods_head
|
||||||
|
nmethod* _scavenge_root_link; // from CodeCache::scavenge_root_nmethods
|
||||||
|
|
||||||
|
static nmethod* volatile _oops_do_mark_nmethods;
|
||||||
|
nmethod* volatile _oops_do_mark_link;
|
||||||
|
|
||||||
AbstractCompiler* _compiler; // The compiler which compiled this nmethod
|
AbstractCompiler* _compiler; // The compiler which compiled this nmethod
|
||||||
|
|
||||||
|
@ -174,6 +180,8 @@ class nmethod : public CodeBlob {
|
||||||
// used by jvmti to track if an unload event has been posted for this nmethod.
|
// used by jvmti to track if an unload event has been posted for this nmethod.
|
||||||
bool _unload_reported;
|
bool _unload_reported;
|
||||||
|
|
||||||
|
jbyte _scavenge_root_state;
|
||||||
|
|
||||||
NOT_PRODUCT(bool _has_debug_info; )
|
NOT_PRODUCT(bool _has_debug_info; )
|
||||||
|
|
||||||
// Nmethod Flushing lock (if non-zero, then the nmethod is not removed)
|
// Nmethod Flushing lock (if non-zero, then the nmethod is not removed)
|
||||||
|
@ -242,7 +250,6 @@ class nmethod : public CodeBlob {
|
||||||
|
|
||||||
// helper methods
|
// helper methods
|
||||||
void* operator new(size_t size, int nmethod_size);
|
void* operator new(size_t size, int nmethod_size);
|
||||||
void check_store();
|
|
||||||
|
|
||||||
const char* reloc_string_for(u_char* begin, u_char* end);
|
const char* reloc_string_for(u_char* begin, u_char* end);
|
||||||
void make_not_entrant_or_zombie(int state);
|
void make_not_entrant_or_zombie(int state);
|
||||||
|
@ -406,6 +413,24 @@ class nmethod : public CodeBlob {
|
||||||
int version() const { return flags.version; }
|
int version() const { return flags.version; }
|
||||||
void set_version(int v);
|
void set_version(int v);
|
||||||
|
|
||||||
|
// Non-perm oop support
|
||||||
|
bool on_scavenge_root_list() const { return (_scavenge_root_state & 1) != 0; }
|
||||||
|
protected:
|
||||||
|
enum { npl_on_list = 0x01, npl_marked = 0x10 };
|
||||||
|
void set_on_scavenge_root_list() { _scavenge_root_state = npl_on_list; }
|
||||||
|
void clear_on_scavenge_root_list() { _scavenge_root_state = 0; }
|
||||||
|
// assertion-checking and pruning logic uses the bits of _scavenge_root_state
|
||||||
|
#ifndef PRODUCT
|
||||||
|
void set_scavenge_root_marked() { _scavenge_root_state |= npl_marked; }
|
||||||
|
void clear_scavenge_root_marked() { _scavenge_root_state &= ~npl_marked; }
|
||||||
|
bool scavenge_root_not_marked() { return (_scavenge_root_state &~ npl_on_list) == 0; }
|
||||||
|
// N.B. there is no positive marked query, and we only use the not_marked query for asserts.
|
||||||
|
#endif //PRODUCT
|
||||||
|
nmethod* scavenge_root_link() const { return _scavenge_root_link; }
|
||||||
|
void set_scavenge_root_link(nmethod *n) { _scavenge_root_link = n; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
// Sweeper support
|
// Sweeper support
|
||||||
long stack_traversal_mark() { return _stack_traversal_mark; }
|
long stack_traversal_mark() { return _stack_traversal_mark; }
|
||||||
void set_stack_traversal_mark(long l) { _stack_traversal_mark = l; }
|
void set_stack_traversal_mark(long l) { _stack_traversal_mark = l; }
|
||||||
|
@ -424,8 +449,8 @@ class nmethod : public CodeBlob {
|
||||||
int osr_entry_bci() const { assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); return _entry_bci; }
|
int osr_entry_bci() const { assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); return _entry_bci; }
|
||||||
address osr_entry() const { assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); return _osr_entry_point; }
|
address osr_entry() const { assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); return _osr_entry_point; }
|
||||||
void invalidate_osr_method();
|
void invalidate_osr_method();
|
||||||
nmethod* link() const { return _link; }
|
nmethod* osr_link() const { return _osr_link; }
|
||||||
void set_link(nmethod *n) { _link = n; }
|
void set_osr_link(nmethod *n) { _osr_link = n; }
|
||||||
|
|
||||||
// tells whether frames described by this nmethod can be deoptimized
|
// tells whether frames described by this nmethod can be deoptimized
|
||||||
// note: native wrappers cannot be deoptimized.
|
// note: native wrappers cannot be deoptimized.
|
||||||
|
@ -465,7 +490,16 @@ class nmethod : public CodeBlob {
|
||||||
|
|
||||||
void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map,
|
void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map,
|
||||||
OopClosure* f);
|
OopClosure* f);
|
||||||
void oops_do(OopClosure* f);
|
virtual void oops_do(OopClosure* f) { oops_do(f, false); }
|
||||||
|
void oops_do(OopClosure* f, bool do_strong_roots_only);
|
||||||
|
bool detect_scavenge_root_oops();
|
||||||
|
void verify_scavenge_root_oops() PRODUCT_RETURN;
|
||||||
|
|
||||||
|
bool test_set_oops_do_mark();
|
||||||
|
static void oops_do_marking_prologue();
|
||||||
|
static void oops_do_marking_epilogue();
|
||||||
|
static bool oops_do_marking_is_active() { return _oops_do_mark_nmethods != NULL; }
|
||||||
|
DEBUG_ONLY(bool test_oops_do_mark() { return _oops_do_mark_link != NULL; })
|
||||||
|
|
||||||
// ScopeDesc for an instruction
|
// ScopeDesc for an instruction
|
||||||
ScopeDesc* scope_desc_at(address pc);
|
ScopeDesc* scope_desc_at(address pc);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -47,20 +47,15 @@ class MarkRefsIntoClosure: public OopsInGenClosure {
|
||||||
private:
|
private:
|
||||||
const MemRegion _span;
|
const MemRegion _span;
|
||||||
CMSBitMap* _bitMap;
|
CMSBitMap* _bitMap;
|
||||||
const bool _should_do_nmethods;
|
|
||||||
protected:
|
protected:
|
||||||
DO_OOP_WORK_DEFN
|
DO_OOP_WORK_DEFN
|
||||||
public:
|
public:
|
||||||
MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap,
|
MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap);
|
||||||
bool should_do_nmethods);
|
|
||||||
virtual void do_oop(oop* p);
|
virtual void do_oop(oop* p);
|
||||||
virtual void do_oop(narrowOop* p);
|
virtual void do_oop(narrowOop* p);
|
||||||
inline void do_oop_nv(oop* p) { MarkRefsIntoClosure::do_oop_work(p); }
|
inline void do_oop_nv(oop* p) { MarkRefsIntoClosure::do_oop_work(p); }
|
||||||
inline void do_oop_nv(narrowOop* p) { MarkRefsIntoClosure::do_oop_work(p); }
|
inline void do_oop_nv(narrowOop* p) { MarkRefsIntoClosure::do_oop_work(p); }
|
||||||
bool do_header() { return true; }
|
bool do_header() { return true; }
|
||||||
virtual const bool do_nmethods() const {
|
|
||||||
return _should_do_nmethods;
|
|
||||||
}
|
|
||||||
Prefetch::style prefetch_style() {
|
Prefetch::style prefetch_style() {
|
||||||
return Prefetch::do_read;
|
return Prefetch::do_read;
|
||||||
}
|
}
|
||||||
|
@ -73,20 +68,16 @@ class MarkRefsIntoVerifyClosure: public OopsInGenClosure {
|
||||||
const MemRegion _span;
|
const MemRegion _span;
|
||||||
CMSBitMap* _verification_bm;
|
CMSBitMap* _verification_bm;
|
||||||
CMSBitMap* _cms_bm;
|
CMSBitMap* _cms_bm;
|
||||||
const bool _should_do_nmethods;
|
|
||||||
protected:
|
protected:
|
||||||
DO_OOP_WORK_DEFN
|
DO_OOP_WORK_DEFN
|
||||||
public:
|
public:
|
||||||
MarkRefsIntoVerifyClosure(MemRegion span, CMSBitMap* verification_bm,
|
MarkRefsIntoVerifyClosure(MemRegion span, CMSBitMap* verification_bm,
|
||||||
CMSBitMap* cms_bm, bool should_do_nmethods);
|
CMSBitMap* cms_bm);
|
||||||
virtual void do_oop(oop* p);
|
virtual void do_oop(oop* p);
|
||||||
virtual void do_oop(narrowOop* p);
|
virtual void do_oop(narrowOop* p);
|
||||||
inline void do_oop_nv(oop* p) { MarkRefsIntoVerifyClosure::do_oop_work(p); }
|
inline void do_oop_nv(oop* p) { MarkRefsIntoVerifyClosure::do_oop_work(p); }
|
||||||
inline void do_oop_nv(narrowOop* p) { MarkRefsIntoVerifyClosure::do_oop_work(p); }
|
inline void do_oop_nv(narrowOop* p) { MarkRefsIntoVerifyClosure::do_oop_work(p); }
|
||||||
bool do_header() { return true; }
|
bool do_header() { return true; }
|
||||||
virtual const bool do_nmethods() const {
|
|
||||||
return _should_do_nmethods;
|
|
||||||
}
|
|
||||||
Prefetch::style prefetch_style() {
|
Prefetch::style prefetch_style() {
|
||||||
return Prefetch::do_read;
|
return Prefetch::do_read;
|
||||||
}
|
}
|
||||||
|
@ -228,7 +219,6 @@ class MarkRefsIntoAndScanClosure: public OopsInGenClosure {
|
||||||
inline void do_oop_nv(oop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); }
|
inline void do_oop_nv(oop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); }
|
||||||
inline void do_oop_nv(narrowOop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); }
|
inline void do_oop_nv(narrowOop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); }
|
||||||
bool do_header() { return true; }
|
bool do_header() { return true; }
|
||||||
virtual const bool do_nmethods() const { return true; }
|
|
||||||
Prefetch::style prefetch_style() {
|
Prefetch::style prefetch_style() {
|
||||||
return Prefetch::do_read;
|
return Prefetch::do_read;
|
||||||
}
|
}
|
||||||
|
@ -273,7 +263,6 @@ class Par_MarkRefsIntoAndScanClosure: public OopsInGenClosure {
|
||||||
inline void do_oop_nv(oop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); }
|
inline void do_oop_nv(oop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); }
|
||||||
inline void do_oop_nv(narrowOop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); }
|
inline void do_oop_nv(narrowOop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); }
|
||||||
bool do_header() { return true; }
|
bool do_header() { return true; }
|
||||||
virtual const bool do_nmethods() const { return true; }
|
|
||||||
// When ScanMarkedObjectsAgainClosure is used,
|
// When ScanMarkedObjectsAgainClosure is used,
|
||||||
// it passes [Par_]MarkRefsIntoAndScanClosure to oop_oop_iterate(),
|
// it passes [Par_]MarkRefsIntoAndScanClosure to oop_oop_iterate(),
|
||||||
// and this delegation is used.
|
// and this delegation is used.
|
||||||
|
|
|
@ -2852,14 +2852,17 @@ void CMSCollector::verify_after_remark_work_1() {
|
||||||
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
||||||
|
|
||||||
// Mark from roots one level into CMS
|
// Mark from roots one level into CMS
|
||||||
MarkRefsIntoClosure notOlder(_span, verification_mark_bm(), true /* nmethods */);
|
MarkRefsIntoClosure notOlder(_span, verification_mark_bm());
|
||||||
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
||||||
|
|
||||||
gch->gen_process_strong_roots(_cmsGen->level(),
|
gch->gen_process_strong_roots(_cmsGen->level(),
|
||||||
true, // younger gens are roots
|
true, // younger gens are roots
|
||||||
|
true, // activate StrongRootsScope
|
||||||
true, // collecting perm gen
|
true, // collecting perm gen
|
||||||
SharedHeap::ScanningOption(roots_scanning_options()),
|
SharedHeap::ScanningOption(roots_scanning_options()),
|
||||||
NULL, ¬Older);
|
¬Older,
|
||||||
|
true, // walk code active on stacks
|
||||||
|
NULL);
|
||||||
|
|
||||||
// Now mark from the roots
|
// Now mark from the roots
|
||||||
assert(_revisitStack.isEmpty(), "Should be empty");
|
assert(_revisitStack.isEmpty(), "Should be empty");
|
||||||
|
@ -2901,13 +2904,16 @@ void CMSCollector::verify_after_remark_work_2() {
|
||||||
|
|
||||||
// Mark from roots one level into CMS
|
// Mark from roots one level into CMS
|
||||||
MarkRefsIntoVerifyClosure notOlder(_span, verification_mark_bm(),
|
MarkRefsIntoVerifyClosure notOlder(_span, verification_mark_bm(),
|
||||||
markBitMap(), true /* nmethods */);
|
markBitMap());
|
||||||
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
||||||
gch->gen_process_strong_roots(_cmsGen->level(),
|
gch->gen_process_strong_roots(_cmsGen->level(),
|
||||||
true, // younger gens are roots
|
true, // younger gens are roots
|
||||||
|
true, // activate StrongRootsScope
|
||||||
true, // collecting perm gen
|
true, // collecting perm gen
|
||||||
SharedHeap::ScanningOption(roots_scanning_options()),
|
SharedHeap::ScanningOption(roots_scanning_options()),
|
||||||
NULL, ¬Older);
|
¬Older,
|
||||||
|
true, // walk code active on stacks
|
||||||
|
NULL);
|
||||||
|
|
||||||
// Now mark from the roots
|
// Now mark from the roots
|
||||||
assert(_revisitStack.isEmpty(), "Should be empty");
|
assert(_revisitStack.isEmpty(), "Should be empty");
|
||||||
|
@ -3484,8 +3490,10 @@ void CMSCollector::checkpointRootsInitialWork(bool asynch) {
|
||||||
FalseClosure falseClosure;
|
FalseClosure falseClosure;
|
||||||
// In the case of a synchronous collection, we will elide the
|
// In the case of a synchronous collection, we will elide the
|
||||||
// remark step, so it's important to catch all the nmethod oops
|
// remark step, so it's important to catch all the nmethod oops
|
||||||
// in this step; hence the last argument to the constrcutor below.
|
// in this step.
|
||||||
MarkRefsIntoClosure notOlder(_span, &_markBitMap, !asynch /* nmethods */);
|
// The final 'true' flag to gen_process_strong_roots will ensure this.
|
||||||
|
// If 'async' is true, we can relax the nmethod tracing.
|
||||||
|
MarkRefsIntoClosure notOlder(_span, &_markBitMap);
|
||||||
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
||||||
|
|
||||||
verify_work_stacks_empty();
|
verify_work_stacks_empty();
|
||||||
|
@ -3504,9 +3512,12 @@ void CMSCollector::checkpointRootsInitialWork(bool asynch) {
|
||||||
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
||||||
gch->gen_process_strong_roots(_cmsGen->level(),
|
gch->gen_process_strong_roots(_cmsGen->level(),
|
||||||
true, // younger gens are roots
|
true, // younger gens are roots
|
||||||
|
true, // activate StrongRootsScope
|
||||||
true, // collecting perm gen
|
true, // collecting perm gen
|
||||||
SharedHeap::ScanningOption(roots_scanning_options()),
|
SharedHeap::ScanningOption(roots_scanning_options()),
|
||||||
NULL, ¬Older);
|
¬Older,
|
||||||
|
true, // walk all of code cache if (so & SO_CodeCache)
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear mod-union table; it will be dirtied in the prologue of
|
// Clear mod-union table; it will be dirtied in the prologue of
|
||||||
|
@ -5040,9 +5051,15 @@ void CMSParRemarkTask::work(int i) {
|
||||||
_timer.start();
|
_timer.start();
|
||||||
gch->gen_process_strong_roots(_collector->_cmsGen->level(),
|
gch->gen_process_strong_roots(_collector->_cmsGen->level(),
|
||||||
false, // yg was scanned above
|
false, // yg was scanned above
|
||||||
|
false, // this is parallel code
|
||||||
true, // collecting perm gen
|
true, // collecting perm gen
|
||||||
SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
|
SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
|
||||||
NULL, &par_mrias_cl);
|
&par_mrias_cl,
|
||||||
|
true, // walk all of code cache if (so & SO_CodeCache)
|
||||||
|
NULL);
|
||||||
|
assert(_collector->should_unload_classes()
|
||||||
|
|| (_collector->CMSCollector::roots_scanning_options() & SharedHeap::SO_CodeCache),
|
||||||
|
"if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
|
||||||
_timer.stop();
|
_timer.stop();
|
||||||
if (PrintCMSStatistics != 0) {
|
if (PrintCMSStatistics != 0) {
|
||||||
gclog_or_tty->print_cr(
|
gclog_or_tty->print_cr(
|
||||||
|
@ -5423,7 +5440,6 @@ void CMSCollector::do_remark_parallel() {
|
||||||
|
|
||||||
// Set up for parallel process_strong_roots work.
|
// Set up for parallel process_strong_roots work.
|
||||||
gch->set_par_threads(n_workers);
|
gch->set_par_threads(n_workers);
|
||||||
gch->change_strong_roots_parity();
|
|
||||||
// We won't be iterating over the cards in the card table updating
|
// We won't be iterating over the cards in the card table updating
|
||||||
// the younger_gen cards, so we shouldn't call the following else
|
// the younger_gen cards, so we shouldn't call the following else
|
||||||
// the verification code as well as subsequent younger_refs_iterate
|
// the verification code as well as subsequent younger_refs_iterate
|
||||||
|
@ -5454,8 +5470,10 @@ void CMSCollector::do_remark_parallel() {
|
||||||
if (n_workers > 1) {
|
if (n_workers > 1) {
|
||||||
// Make refs discovery MT-safe
|
// Make refs discovery MT-safe
|
||||||
ReferenceProcessorMTMutator mt(ref_processor(), true);
|
ReferenceProcessorMTMutator mt(ref_processor(), true);
|
||||||
|
GenCollectedHeap::StrongRootsScope srs(gch);
|
||||||
workers->run_task(&tsk);
|
workers->run_task(&tsk);
|
||||||
} else {
|
} else {
|
||||||
|
GenCollectedHeap::StrongRootsScope srs(gch);
|
||||||
tsk.work(0);
|
tsk.work(0);
|
||||||
}
|
}
|
||||||
gch->set_par_threads(0); // 0 ==> non-parallel.
|
gch->set_par_threads(0); // 0 ==> non-parallel.
|
||||||
|
@ -5539,11 +5557,18 @@ void CMSCollector::do_remark_non_parallel() {
|
||||||
verify_work_stacks_empty();
|
verify_work_stacks_empty();
|
||||||
|
|
||||||
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
|
||||||
|
GenCollectedHeap::StrongRootsScope srs(gch);
|
||||||
gch->gen_process_strong_roots(_cmsGen->level(),
|
gch->gen_process_strong_roots(_cmsGen->level(),
|
||||||
true, // younger gens as roots
|
true, // younger gens as roots
|
||||||
|
false, // use the local StrongRootsScope
|
||||||
true, // collecting perm gen
|
true, // collecting perm gen
|
||||||
SharedHeap::ScanningOption(roots_scanning_options()),
|
SharedHeap::ScanningOption(roots_scanning_options()),
|
||||||
NULL, &mrias_cl);
|
&mrias_cl,
|
||||||
|
true, // walk code active on stacks
|
||||||
|
NULL);
|
||||||
|
assert(should_unload_classes()
|
||||||
|
|| (roots_scanning_options() & SharedHeap::SO_CodeCache),
|
||||||
|
"if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
|
||||||
}
|
}
|
||||||
verify_work_stacks_empty();
|
verify_work_stacks_empty();
|
||||||
// Restore evacuated mark words, if any, used for overflow list links
|
// Restore evacuated mark words, if any, used for overflow list links
|
||||||
|
@ -6418,10 +6443,9 @@ void CMSMarkStack::expand() {
|
||||||
// generation then this will lose younger_gen cards!
|
// generation then this will lose younger_gen cards!
|
||||||
|
|
||||||
MarkRefsIntoClosure::MarkRefsIntoClosure(
|
MarkRefsIntoClosure::MarkRefsIntoClosure(
|
||||||
MemRegion span, CMSBitMap* bitMap, bool should_do_nmethods):
|
MemRegion span, CMSBitMap* bitMap):
|
||||||
_span(span),
|
_span(span),
|
||||||
_bitMap(bitMap),
|
_bitMap(bitMap)
|
||||||
_should_do_nmethods(should_do_nmethods)
|
|
||||||
{
|
{
|
||||||
assert(_ref_processor == NULL, "deliberately left NULL");
|
assert(_ref_processor == NULL, "deliberately left NULL");
|
||||||
assert(_bitMap->covers(_span), "_bitMap/_span mismatch");
|
assert(_bitMap->covers(_span), "_bitMap/_span mismatch");
|
||||||
|
@ -6442,12 +6466,11 @@ void MarkRefsIntoClosure::do_oop(narrowOop* p) { MarkRefsIntoClosure::do_oop_wor
|
||||||
|
|
||||||
// A variant of the above, used for CMS marking verification.
|
// A variant of the above, used for CMS marking verification.
|
||||||
MarkRefsIntoVerifyClosure::MarkRefsIntoVerifyClosure(
|
MarkRefsIntoVerifyClosure::MarkRefsIntoVerifyClosure(
|
||||||
MemRegion span, CMSBitMap* verification_bm, CMSBitMap* cms_bm,
|
MemRegion span, CMSBitMap* verification_bm, CMSBitMap* cms_bm):
|
||||||
bool should_do_nmethods):
|
|
||||||
_span(span),
|
_span(span),
|
||||||
_verification_bm(verification_bm),
|
_verification_bm(verification_bm),
|
||||||
_cms_bm(cms_bm),
|
_cms_bm(cms_bm)
|
||||||
_should_do_nmethods(should_do_nmethods) {
|
{
|
||||||
assert(_ref_processor == NULL, "deliberately left NULL");
|
assert(_ref_processor == NULL, "deliberately left NULL");
|
||||||
assert(_verification_bm->covers(_span), "_verification_bm/_span mismatch");
|
assert(_verification_bm->covers(_span), "_verification_bm/_span mismatch");
|
||||||
}
|
}
|
||||||
|
|
|
@ -746,10 +746,11 @@ void ConcurrentMark::checkpointRootsInitialPre() {
|
||||||
// clear the mark bitmap (no grey objects to start with)
|
// clear the mark bitmap (no grey objects to start with)
|
||||||
_nextMarkBitMap->clearAll();
|
_nextMarkBitMap->clearAll();
|
||||||
PrintReachableClosure prcl(_nextMarkBitMap);
|
PrintReachableClosure prcl(_nextMarkBitMap);
|
||||||
g1h->process_strong_roots(
|
g1h->process_strong_roots(true, // activate StrongRootsScope
|
||||||
false, // fake perm gen collection
|
false, // fake perm gen collection
|
||||||
SharedHeap::SO_AllClasses,
|
SharedHeap::SO_AllClasses,
|
||||||
&prcl, // Regular roots
|
&prcl, // Regular roots
|
||||||
|
NULL, // do not visit active blobs
|
||||||
&prcl // Perm Gen Roots
|
&prcl // Perm Gen Roots
|
||||||
);
|
);
|
||||||
// The root iteration above "consumed" dirty cards in the perm gen.
|
// The root iteration above "consumed" dirty cards in the perm gen.
|
||||||
|
@ -852,9 +853,11 @@ void ConcurrentMark::checkpointRootsInitial() {
|
||||||
g1h->set_marking_started();
|
g1h->set_marking_started();
|
||||||
g1h->rem_set()->prepare_for_younger_refs_iterate(false);
|
g1h->rem_set()->prepare_for_younger_refs_iterate(false);
|
||||||
|
|
||||||
g1h->process_strong_roots(false, // fake perm gen collection
|
g1h->process_strong_roots(true, // activate StrongRootsScope
|
||||||
|
false, // fake perm gen collection
|
||||||
SharedHeap::SO_AllClasses,
|
SharedHeap::SO_AllClasses,
|
||||||
¬Older, // Regular roots
|
¬Older, // Regular roots
|
||||||
|
NULL, // do not visit active blobs
|
||||||
&older // Perm Gen Roots
|
&older // Perm Gen Roots
|
||||||
);
|
);
|
||||||
checkpointRootsInitialPost();
|
checkpointRootsInitialPost();
|
||||||
|
@ -1915,7 +1918,7 @@ void ConcurrentMark::checkpointRootsFinalWork() {
|
||||||
g1h->ensure_parsability(false);
|
g1h->ensure_parsability(false);
|
||||||
|
|
||||||
if (ParallelGCThreads > 0) {
|
if (ParallelGCThreads > 0) {
|
||||||
g1h->change_strong_roots_parity();
|
G1CollectedHeap::StrongRootsScope srs(g1h);
|
||||||
// this is remark, so we'll use up all available threads
|
// this is remark, so we'll use up all available threads
|
||||||
int active_workers = ParallelGCThreads;
|
int active_workers = ParallelGCThreads;
|
||||||
set_phase(active_workers, false);
|
set_phase(active_workers, false);
|
||||||
|
@ -1932,7 +1935,7 @@ void ConcurrentMark::checkpointRootsFinalWork() {
|
||||||
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
|
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
|
||||||
guarantee( satb_mq_set.completed_buffers_num() == 0, "invariant" );
|
guarantee( satb_mq_set.completed_buffers_num() == 0, "invariant" );
|
||||||
} else {
|
} else {
|
||||||
g1h->change_strong_roots_parity();
|
G1CollectedHeap::StrongRootsScope srs(g1h);
|
||||||
// this is remark, so we'll use up all available threads
|
// this is remark, so we'll use up all available threads
|
||||||
int active_workers = 1;
|
int active_workers = 1;
|
||||||
set_phase(active_workers, false);
|
set_phase(active_workers, false);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -2300,9 +2300,12 @@ void G1CollectedHeap::verify(bool allow_dirty,
|
||||||
if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) {
|
if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) {
|
||||||
if (!silent) { gclog_or_tty->print("roots "); }
|
if (!silent) { gclog_or_tty->print("roots "); }
|
||||||
VerifyRootsClosure rootsCl(use_prev_marking);
|
VerifyRootsClosure rootsCl(use_prev_marking);
|
||||||
process_strong_roots(false,
|
CodeBlobToOopClosure blobsCl(&rootsCl, /*do_marking=*/ false);
|
||||||
|
process_strong_roots(true, // activate StrongRootsScope
|
||||||
|
false,
|
||||||
SharedHeap::SO_AllClasses,
|
SharedHeap::SO_AllClasses,
|
||||||
&rootsCl,
|
&rootsCl,
|
||||||
|
&blobsCl,
|
||||||
&rootsCl);
|
&rootsCl);
|
||||||
rem_set()->invalidate(perm_gen()->used_region(), false);
|
rem_set()->invalidate(perm_gen()->used_region(), false);
|
||||||
if (!silent) { gclog_or_tty->print("heapRegions "); }
|
if (!silent) { gclog_or_tty->print("heapRegions "); }
|
||||||
|
@ -3987,8 +3990,14 @@ g1_process_strong_roots(bool collecting_perm_gen,
|
||||||
BufferingOopsInGenClosure buf_scan_perm(scan_perm);
|
BufferingOopsInGenClosure buf_scan_perm(scan_perm);
|
||||||
buf_scan_perm.set_generation(perm_gen());
|
buf_scan_perm.set_generation(perm_gen());
|
||||||
|
|
||||||
process_strong_roots(collecting_perm_gen, so,
|
// Walk the code cache w/o buffering, because StarTask cannot handle
|
||||||
|
// unaligned oop locations.
|
||||||
|
CodeBlobToOopClosure eager_scan_code_roots(scan_non_heap_roots, /*do_marking=*/ true);
|
||||||
|
|
||||||
|
process_strong_roots(false, // no scoping; this is parallel code
|
||||||
|
collecting_perm_gen, so,
|
||||||
&buf_scan_non_heap_roots,
|
&buf_scan_non_heap_roots,
|
||||||
|
&eager_scan_code_roots,
|
||||||
&buf_scan_perm);
|
&buf_scan_perm);
|
||||||
// Finish up any enqueued closure apps.
|
// Finish up any enqueued closure apps.
|
||||||
buf_scan_non_heap_roots.done();
|
buf_scan_non_heap_roots.done();
|
||||||
|
@ -4078,7 +4087,8 @@ G1CollectedHeap::scan_scan_only_set(OopsInHeapRegionClosure* oc,
|
||||||
void
|
void
|
||||||
G1CollectedHeap::g1_process_weak_roots(OopClosure* root_closure,
|
G1CollectedHeap::g1_process_weak_roots(OopClosure* root_closure,
|
||||||
OopClosure* non_root_closure) {
|
OopClosure* non_root_closure) {
|
||||||
SharedHeap::process_weak_roots(root_closure, non_root_closure);
|
CodeBlobToOopClosure roots_in_blobs(root_closure, /*do_marking=*/ false);
|
||||||
|
SharedHeap::process_weak_roots(root_closure, &roots_in_blobs, non_root_closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4112,15 +4122,16 @@ void G1CollectedHeap::evacuate_collection_set() {
|
||||||
|
|
||||||
init_for_evac_failure(NULL);
|
init_for_evac_failure(NULL);
|
||||||
|
|
||||||
change_strong_roots_parity(); // In preparation for parallel strong roots.
|
|
||||||
rem_set()->prepare_for_younger_refs_iterate(true);
|
rem_set()->prepare_for_younger_refs_iterate(true);
|
||||||
|
|
||||||
assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty");
|
assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty");
|
||||||
double start_par = os::elapsedTime();
|
double start_par = os::elapsedTime();
|
||||||
if (ParallelGCThreads > 0) {
|
if (ParallelGCThreads > 0) {
|
||||||
// The individual threads will set their evac-failure closures.
|
// The individual threads will set their evac-failure closures.
|
||||||
|
StrongRootsScope srs(this);
|
||||||
workers()->run_task(&g1_par_task);
|
workers()->run_task(&g1_par_task);
|
||||||
} else {
|
} else {
|
||||||
|
StrongRootsScope srs(this);
|
||||||
g1_par_task.work(0);
|
g1_par_task.work(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -121,9 +121,11 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
|
||||||
|
|
||||||
SharedHeap* sh = SharedHeap::heap();
|
SharedHeap* sh = SharedHeap::heap();
|
||||||
|
|
||||||
sh->process_strong_roots(true, // Collecting permanent generation.
|
sh->process_strong_roots(true, // activeate StrongRootsScope
|
||||||
|
true, // Collecting permanent generation.
|
||||||
SharedHeap::SO_SystemClasses,
|
SharedHeap::SO_SystemClasses,
|
||||||
&GenMarkSweep::follow_root_closure,
|
&GenMarkSweep::follow_root_closure,
|
||||||
|
&GenMarkSweep::follow_code_root_closure,
|
||||||
&GenMarkSweep::follow_root_closure);
|
&GenMarkSweep::follow_root_closure);
|
||||||
|
|
||||||
// Process reference objects found during marking
|
// Process reference objects found during marking
|
||||||
|
@ -286,9 +288,11 @@ void G1MarkSweep::mark_sweep_phase3() {
|
||||||
|
|
||||||
SharedHeap* sh = SharedHeap::heap();
|
SharedHeap* sh = SharedHeap::heap();
|
||||||
|
|
||||||
sh->process_strong_roots(true, // Collecting permanent generation.
|
sh->process_strong_roots(true, // activate StrongRootsScope
|
||||||
|
true, // Collecting permanent generation.
|
||||||
SharedHeap::SO_AllClasses,
|
SharedHeap::SO_AllClasses,
|
||||||
&GenMarkSweep::adjust_root_pointer_closure,
|
&GenMarkSweep::adjust_root_pointer_closure,
|
||||||
|
NULL, // do not touch code cache here
|
||||||
&GenMarkSweep::adjust_pointer_closure);
|
&GenMarkSweep::adjust_pointer_closure);
|
||||||
|
|
||||||
g1h->ref_processor()->weak_oops_do(&GenMarkSweep::adjust_root_pointer_closure);
|
g1h->ref_processor()->weak_oops_do(&GenMarkSweep::adjust_root_pointer_closure);
|
||||||
|
|
|
@ -373,6 +373,7 @@ psScavenge.inline.hpp parallelScavengeHeap.hpp
|
||||||
psScavenge.inline.hpp psPromotionManager.hpp
|
psScavenge.inline.hpp psPromotionManager.hpp
|
||||||
psScavenge.inline.hpp psScavenge.hpp
|
psScavenge.inline.hpp psScavenge.hpp
|
||||||
|
|
||||||
|
pcTasks.cpp codeCache.hpp
|
||||||
pcTasks.cpp collectedHeap.hpp
|
pcTasks.cpp collectedHeap.hpp
|
||||||
pcTasks.cpp fprofiler.hpp
|
pcTasks.cpp fprofiler.hpp
|
||||||
pcTasks.cpp jniHandles.hpp
|
pcTasks.cpp jniHandles.hpp
|
||||||
|
@ -392,6 +393,7 @@ pcTasks.hpp gcTaskManager.hpp
|
||||||
pcTasks.hpp psTasks.hpp
|
pcTasks.hpp psTasks.hpp
|
||||||
|
|
||||||
psTasks.cpp cardTableExtension.hpp
|
psTasks.cpp cardTableExtension.hpp
|
||||||
|
psTasks.cpp codeCache.hpp
|
||||||
psTasks.cpp fprofiler.hpp
|
psTasks.cpp fprofiler.hpp
|
||||||
psTasks.cpp gcTaskManager.hpp
|
psTasks.cpp gcTaskManager.hpp
|
||||||
psTasks.cpp iterator.hpp
|
psTasks.cpp iterator.hpp
|
||||||
|
|
|
@ -482,10 +482,12 @@ void ParNewGenTask::work(int i) {
|
||||||
gch->gen_process_strong_roots(_gen->level(),
|
gch->gen_process_strong_roots(_gen->level(),
|
||||||
true, // Process younger gens, if any,
|
true, // Process younger gens, if any,
|
||||||
// as strong roots.
|
// as strong roots.
|
||||||
false,// not collecting perm generation.
|
false, // no scope; this is parallel code
|
||||||
|
false, // not collecting perm generation.
|
||||||
SharedHeap::SO_AllClasses,
|
SharedHeap::SO_AllClasses,
|
||||||
&par_scan_state.older_gen_closure(),
|
&par_scan_state.to_space_root_closure(),
|
||||||
&par_scan_state.to_space_root_closure());
|
true, // walk *all* scavengable nmethods
|
||||||
|
&par_scan_state.older_gen_closure());
|
||||||
par_scan_state.end_strong_roots();
|
par_scan_state.end_strong_roots();
|
||||||
|
|
||||||
// "evacuate followers".
|
// "evacuate followers".
|
||||||
|
@ -799,15 +801,16 @@ void ParNewGeneration::collect(bool full,
|
||||||
ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set);
|
ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set);
|
||||||
int n_workers = workers->total_workers();
|
int n_workers = workers->total_workers();
|
||||||
gch->set_par_threads(n_workers);
|
gch->set_par_threads(n_workers);
|
||||||
gch->change_strong_roots_parity();
|
|
||||||
gch->rem_set()->prepare_for_younger_refs_iterate(true);
|
gch->rem_set()->prepare_for_younger_refs_iterate(true);
|
||||||
// It turns out that even when we're using 1 thread, doing the work in a
|
// It turns out that even when we're using 1 thread, doing the work in a
|
||||||
// separate thread causes wide variance in run times. We can't help this
|
// separate thread causes wide variance in run times. We can't help this
|
||||||
// in the multi-threaded case, but we special-case n=1 here to get
|
// 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.
|
// repeatable measurements of the 1-thread overhead of the parallel code.
|
||||||
if (n_workers > 1) {
|
if (n_workers > 1) {
|
||||||
|
GenCollectedHeap::StrongRootsScope srs(gch);
|
||||||
workers->run_task(&tsk);
|
workers->run_task(&tsk);
|
||||||
} else {
|
} else {
|
||||||
|
GenCollectedHeap::StrongRootsScope srs(gch);
|
||||||
tsk.work(0);
|
tsk.work(0);
|
||||||
}
|
}
|
||||||
thread_state_set.reset();
|
thread_state_set.reset();
|
||||||
|
|
|
@ -962,6 +962,14 @@ void ParallelScavengeHeap::resize_old_gen(size_t desired_free_space) {
|
||||||
_old_gen->resize(desired_free_space);
|
_old_gen->resize(desired_free_space);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParallelScavengeHeap::ParStrongRootsScope::ParStrongRootsScope() {
|
||||||
|
// nothing particular
|
||||||
|
}
|
||||||
|
|
||||||
|
ParallelScavengeHeap::ParStrongRootsScope::~ParStrongRootsScope() {
|
||||||
|
// nothing particular
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
void ParallelScavengeHeap::record_gen_tops_before_GC() {
|
void ParallelScavengeHeap::record_gen_tops_before_GC() {
|
||||||
if (ZapUnusedHeapArea) {
|
if (ZapUnusedHeapArea) {
|
||||||
|
|
|
@ -234,6 +234,13 @@ class ParallelScavengeHeap : public CollectedHeap {
|
||||||
|
|
||||||
// Mangle the unused parts of all spaces in the heap
|
// Mangle the unused parts of all spaces in the heap
|
||||||
void gen_mangle_unused_area() PRODUCT_RETURN;
|
void gen_mangle_unused_area() PRODUCT_RETURN;
|
||||||
|
|
||||||
|
// Call these in sequential code around the processing of strong roots.
|
||||||
|
class ParStrongRootsScope : public MarkingCodeBlobClosure::MarkScope {
|
||||||
|
public:
|
||||||
|
ParStrongRootsScope();
|
||||||
|
~ParStrongRootsScope();
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
inline size_t ParallelScavengeHeap::set_alignment(size_t& var, size_t val)
|
inline size_t ParallelScavengeHeap::set_alignment(size_t& var, size_t val)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -39,12 +39,13 @@ void ThreadRootsMarkingTask::do_it(GCTaskManager* manager, uint which) {
|
||||||
ParCompactionManager* cm =
|
ParCompactionManager* cm =
|
||||||
ParCompactionManager::gc_thread_compaction_manager(which);
|
ParCompactionManager::gc_thread_compaction_manager(which);
|
||||||
PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
|
PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
|
||||||
|
CodeBlobToOopClosure mark_and_push_in_blobs(&mark_and_push_closure, /*do_marking=*/ true);
|
||||||
|
|
||||||
if (_java_thread != NULL)
|
if (_java_thread != NULL)
|
||||||
_java_thread->oops_do(&mark_and_push_closure);
|
_java_thread->oops_do(&mark_and_push_closure, &mark_and_push_in_blobs);
|
||||||
|
|
||||||
if (_vm_thread != NULL)
|
if (_vm_thread != NULL)
|
||||||
_vm_thread->oops_do(&mark_and_push_closure);
|
_vm_thread->oops_do(&mark_and_push_closure, &mark_and_push_in_blobs);
|
||||||
|
|
||||||
// Do the real work
|
// Do the real work
|
||||||
cm->drain_marking_stacks(&mark_and_push_closure);
|
cm->drain_marking_stacks(&mark_and_push_closure);
|
||||||
|
@ -78,7 +79,8 @@ void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) {
|
||||||
case threads:
|
case threads:
|
||||||
{
|
{
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
Threads::oops_do(&mark_and_push_closure);
|
CodeBlobToOopClosure each_active_code_blob(&mark_and_push_closure, /*do_marking=*/ true);
|
||||||
|
Threads::oops_do(&mark_and_push_closure, &each_active_code_blob);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -106,6 +108,11 @@ void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) {
|
||||||
vmSymbols::oops_do(&mark_and_push_closure);
|
vmSymbols::oops_do(&mark_and_push_closure);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case code_cache:
|
||||||
|
// Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
|
||||||
|
//CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(&mark_and_push_closure));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fatal("Unknown root type");
|
fatal("Unknown root type");
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,8 @@ class MarkFromRootsTask : public GCTask {
|
||||||
jvmti = 7,
|
jvmti = 7,
|
||||||
system_dictionary = 8,
|
system_dictionary = 8,
|
||||||
vm_symbols = 9,
|
vm_symbols = 9,
|
||||||
reference_processing = 10
|
reference_processing = 10,
|
||||||
|
code_cache = 11
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
RootType _root_type;
|
RootType _root_type;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -511,16 +511,22 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
|
||||||
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
|
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
|
||||||
|
|
||||||
// General strong roots.
|
// General strong roots.
|
||||||
|
{
|
||||||
|
ParallelScavengeHeap::ParStrongRootsScope psrs;
|
||||||
Universe::oops_do(mark_and_push_closure());
|
Universe::oops_do(mark_and_push_closure());
|
||||||
ReferenceProcessor::oops_do(mark_and_push_closure());
|
ReferenceProcessor::oops_do(mark_and_push_closure());
|
||||||
JNIHandles::oops_do(mark_and_push_closure()); // Global (strong) JNI handles
|
JNIHandles::oops_do(mark_and_push_closure()); // Global (strong) JNI handles
|
||||||
Threads::oops_do(mark_and_push_closure());
|
CodeBlobToOopClosure each_active_code_blob(mark_and_push_closure(), /*do_marking=*/ true);
|
||||||
|
Threads::oops_do(mark_and_push_closure(), &each_active_code_blob);
|
||||||
ObjectSynchronizer::oops_do(mark_and_push_closure());
|
ObjectSynchronizer::oops_do(mark_and_push_closure());
|
||||||
FlatProfiler::oops_do(mark_and_push_closure());
|
FlatProfiler::oops_do(mark_and_push_closure());
|
||||||
Management::oops_do(mark_and_push_closure());
|
Management::oops_do(mark_and_push_closure());
|
||||||
JvmtiExport::oops_do(mark_and_push_closure());
|
JvmtiExport::oops_do(mark_and_push_closure());
|
||||||
SystemDictionary::always_strong_oops_do(mark_and_push_closure());
|
SystemDictionary::always_strong_oops_do(mark_and_push_closure());
|
||||||
vmSymbols::oops_do(mark_and_push_closure());
|
vmSymbols::oops_do(mark_and_push_closure());
|
||||||
|
// Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
|
||||||
|
//CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(mark_and_push_closure()));
|
||||||
|
}
|
||||||
|
|
||||||
// Flush marking stack.
|
// Flush marking stack.
|
||||||
follow_stack();
|
follow_stack();
|
||||||
|
@ -617,7 +623,7 @@ void PSMarkSweep::mark_sweep_phase3() {
|
||||||
Universe::oops_do(adjust_root_pointer_closure());
|
Universe::oops_do(adjust_root_pointer_closure());
|
||||||
ReferenceProcessor::oops_do(adjust_root_pointer_closure());
|
ReferenceProcessor::oops_do(adjust_root_pointer_closure());
|
||||||
JNIHandles::oops_do(adjust_root_pointer_closure()); // Global (strong) JNI handles
|
JNIHandles::oops_do(adjust_root_pointer_closure()); // Global (strong) JNI handles
|
||||||
Threads::oops_do(adjust_root_pointer_closure());
|
Threads::oops_do(adjust_root_pointer_closure(), NULL);
|
||||||
ObjectSynchronizer::oops_do(adjust_root_pointer_closure());
|
ObjectSynchronizer::oops_do(adjust_root_pointer_closure());
|
||||||
FlatProfiler::oops_do(adjust_root_pointer_closure());
|
FlatProfiler::oops_do(adjust_root_pointer_closure());
|
||||||
Management::oops_do(adjust_root_pointer_closure());
|
Management::oops_do(adjust_root_pointer_closure());
|
||||||
|
@ -625,6 +631,7 @@ void PSMarkSweep::mark_sweep_phase3() {
|
||||||
// SO_AllClasses
|
// SO_AllClasses
|
||||||
SystemDictionary::oops_do(adjust_root_pointer_closure());
|
SystemDictionary::oops_do(adjust_root_pointer_closure());
|
||||||
vmSymbols::oops_do(adjust_root_pointer_closure());
|
vmSymbols::oops_do(adjust_root_pointer_closure());
|
||||||
|
//CodeCache::scavenge_root_nmethods_oops_do(adjust_root_pointer_closure());
|
||||||
|
|
||||||
// Now adjust pointers in remaining weak roots. (All of which should
|
// Now adjust pointers in remaining weak roots. (All of which should
|
||||||
// have been cleared if they pointed to non-surviving objects.)
|
// have been cleared if they pointed to non-surviving objects.)
|
||||||
|
|
|
@ -2322,6 +2322,7 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm,
|
||||||
|
|
||||||
{
|
{
|
||||||
TraceTime tm_m("par mark", print_phases(), true, gclog_or_tty);
|
TraceTime tm_m("par mark", print_phases(), true, gclog_or_tty);
|
||||||
|
ParallelScavengeHeap::ParStrongRootsScope psrs;
|
||||||
|
|
||||||
GCTaskQueue* q = GCTaskQueue::create();
|
GCTaskQueue* q = GCTaskQueue::create();
|
||||||
|
|
||||||
|
@ -2335,6 +2336,7 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm,
|
||||||
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::system_dictionary));
|
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::system_dictionary));
|
||||||
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::jvmti));
|
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::jvmti));
|
||||||
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::vm_symbols));
|
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::vm_symbols));
|
||||||
|
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::code_cache));
|
||||||
|
|
||||||
if (parallel_gc_threads > 1) {
|
if (parallel_gc_threads > 1) {
|
||||||
for (uint j = 0; j < parallel_gc_threads; j++) {
|
for (uint j = 0; j < parallel_gc_threads; j++) {
|
||||||
|
@ -2408,7 +2410,7 @@ void PSParallelCompact::adjust_roots() {
|
||||||
Universe::oops_do(adjust_root_pointer_closure());
|
Universe::oops_do(adjust_root_pointer_closure());
|
||||||
ReferenceProcessor::oops_do(adjust_root_pointer_closure());
|
ReferenceProcessor::oops_do(adjust_root_pointer_closure());
|
||||||
JNIHandles::oops_do(adjust_root_pointer_closure()); // Global (strong) JNI handles
|
JNIHandles::oops_do(adjust_root_pointer_closure()); // Global (strong) JNI handles
|
||||||
Threads::oops_do(adjust_root_pointer_closure());
|
Threads::oops_do(adjust_root_pointer_closure(), NULL);
|
||||||
ObjectSynchronizer::oops_do(adjust_root_pointer_closure());
|
ObjectSynchronizer::oops_do(adjust_root_pointer_closure());
|
||||||
FlatProfiler::oops_do(adjust_root_pointer_closure());
|
FlatProfiler::oops_do(adjust_root_pointer_closure());
|
||||||
Management::oops_do(adjust_root_pointer_closure());
|
Management::oops_do(adjust_root_pointer_closure());
|
||||||
|
|
|
@ -799,7 +799,6 @@ class PSParallelCompact : AllStatic {
|
||||||
FollowRootClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
|
FollowRootClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
|
||||||
virtual void do_oop(oop* p);
|
virtual void do_oop(oop* p);
|
||||||
virtual void do_oop(narrowOop* p);
|
virtual void do_oop(narrowOop* p);
|
||||||
virtual const bool do_nmethods() const { return true; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class FollowStackClosure: public VoidClosure {
|
class FollowStackClosure: public VoidClosure {
|
||||||
|
@ -817,6 +816,8 @@ class PSParallelCompact : AllStatic {
|
||||||
AdjustPointerClosure(bool is_root) : _is_root(is_root) { }
|
AdjustPointerClosure(bool is_root) : _is_root(is_root) { }
|
||||||
virtual void do_oop(oop* p);
|
virtual void do_oop(oop* p);
|
||||||
virtual void do_oop(narrowOop* p);
|
virtual void do_oop(narrowOop* p);
|
||||||
|
// do not walk from thread stacks to the code cache on this phase
|
||||||
|
virtual void do_code_blob(CodeBlob* cb) const { }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Closure for verifying update of pointers. Does not
|
// Closure for verifying update of pointers. Does not
|
||||||
|
@ -1063,7 +1064,6 @@ class PSParallelCompact : AllStatic {
|
||||||
MarkAndPushClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
|
MarkAndPushClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
|
||||||
virtual void do_oop(oop* p);
|
virtual void do_oop(oop* p);
|
||||||
virtual void do_oop(narrowOop* p);
|
virtual void do_oop(narrowOop* p);
|
||||||
virtual const bool do_nmethods() const { return true; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PSParallelCompact();
|
PSParallelCompact();
|
||||||
|
|
|
@ -358,6 +358,7 @@ bool PSScavenge::invoke_no_policy() {
|
||||||
PSPromotionManager* promotion_manager = PSPromotionManager::vm_thread_promotion_manager();
|
PSPromotionManager* promotion_manager = PSPromotionManager::vm_thread_promotion_manager();
|
||||||
{
|
{
|
||||||
// TraceTime("Roots");
|
// TraceTime("Roots");
|
||||||
|
ParallelScavengeHeap::ParStrongRootsScope psrs;
|
||||||
|
|
||||||
GCTaskQueue* q = GCTaskQueue::create();
|
GCTaskQueue* q = GCTaskQueue::create();
|
||||||
|
|
||||||
|
@ -376,6 +377,7 @@ bool PSScavenge::invoke_no_policy() {
|
||||||
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::management));
|
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::management));
|
||||||
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::system_dictionary));
|
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::system_dictionary));
|
||||||
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::jvmti));
|
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::jvmti));
|
||||||
|
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::code_cache));
|
||||||
|
|
||||||
ParallelTaskTerminator terminator(
|
ParallelTaskTerminator terminator(
|
||||||
gc_task_manager()->workers(),
|
gc_task_manager()->workers(),
|
||||||
|
|
|
@ -66,7 +66,7 @@ void ScavengeRootsTask::do_it(GCTaskManager* manager, uint which) {
|
||||||
case threads:
|
case threads:
|
||||||
{
|
{
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
Threads::oops_do(&roots_closure);
|
Threads::oops_do(&roots_closure, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -90,6 +90,14 @@ void ScavengeRootsTask::do_it(GCTaskManager* manager, uint which) {
|
||||||
JvmtiExport::oops_do(&roots_closure);
|
JvmtiExport::oops_do(&roots_closure);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case code_cache:
|
||||||
|
{
|
||||||
|
CodeBlobToOopClosure each_scavengable_code_blob(&roots_closure, /*do_marking=*/ true);
|
||||||
|
CodeCache::scavenge_root_nmethods_do(&each_scavengable_code_blob);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fatal("Unknown root type");
|
fatal("Unknown root type");
|
||||||
}
|
}
|
||||||
|
@ -107,12 +115,13 @@ void ThreadRootsTask::do_it(GCTaskManager* manager, uint which) {
|
||||||
|
|
||||||
PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(which);
|
PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(which);
|
||||||
PSScavengeRootsClosure roots_closure(pm);
|
PSScavengeRootsClosure roots_closure(pm);
|
||||||
|
CodeBlobToOopClosure roots_in_blobs(&roots_closure, /*do_marking=*/ true);
|
||||||
|
|
||||||
if (_java_thread != NULL)
|
if (_java_thread != NULL)
|
||||||
_java_thread->oops_do(&roots_closure);
|
_java_thread->oops_do(&roots_closure, &roots_in_blobs);
|
||||||
|
|
||||||
if (_vm_thread != NULL)
|
if (_vm_thread != NULL)
|
||||||
_vm_thread->oops_do(&roots_closure);
|
_vm_thread->oops_do(&roots_closure, &roots_in_blobs);
|
||||||
|
|
||||||
// Do the real work
|
// Do the real work
|
||||||
pm->drain_stacks(false);
|
pm->drain_stacks(false);
|
||||||
|
|
|
@ -54,7 +54,8 @@ class ScavengeRootsTask : public GCTask {
|
||||||
flat_profiler = 5,
|
flat_profiler = 5,
|
||||||
system_dictionary = 6,
|
system_dictionary = 6,
|
||||||
management = 7,
|
management = 7,
|
||||||
jvmti = 8
|
jvmti = 8,
|
||||||
|
code_cache = 9
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
RootType _root_type;
|
RootType _root_type;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -93,6 +93,7 @@ void MarkSweep::follow_mdo_weak_refs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkSweep::FollowRootClosure MarkSweep::follow_root_closure;
|
MarkSweep::FollowRootClosure MarkSweep::follow_root_closure;
|
||||||
|
CodeBlobToOopClosure MarkSweep::follow_code_root_closure(&MarkSweep::follow_root_closure, /*do_marking=*/ true);
|
||||||
|
|
||||||
void MarkSweep::FollowRootClosure::do_oop(oop* p) { follow_root(p); }
|
void MarkSweep::FollowRootClosure::do_oop(oop* p) { follow_root(p); }
|
||||||
void MarkSweep::FollowRootClosure::do_oop(narrowOop* p) { follow_root(p); }
|
void MarkSweep::FollowRootClosure::do_oop(narrowOop* p) { follow_root(p); }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -58,14 +58,12 @@ class MarkSweep : AllStatic {
|
||||||
public:
|
public:
|
||||||
virtual void do_oop(oop* p);
|
virtual void do_oop(oop* p);
|
||||||
virtual void do_oop(narrowOop* p);
|
virtual void do_oop(narrowOop* p);
|
||||||
virtual const bool do_nmethods() const { return true; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MarkAndPushClosure: public OopClosure {
|
class MarkAndPushClosure: public OopClosure {
|
||||||
public:
|
public:
|
||||||
virtual void do_oop(oop* p);
|
virtual void do_oop(oop* p);
|
||||||
virtual void do_oop(narrowOop* p);
|
virtual void do_oop(narrowOop* p);
|
||||||
virtual const bool do_nmethods() const { return true; }
|
|
||||||
virtual const bool should_remember_mdo() const { return true; }
|
virtual const bool should_remember_mdo() const { return true; }
|
||||||
virtual void remember_mdo(DataLayout* p) { MarkSweep::revisit_mdo(p); }
|
virtual void remember_mdo(DataLayout* p) { MarkSweep::revisit_mdo(p); }
|
||||||
};
|
};
|
||||||
|
@ -173,6 +171,7 @@ class MarkSweep : AllStatic {
|
||||||
public:
|
public:
|
||||||
// Public closures
|
// Public closures
|
||||||
static FollowRootClosure follow_root_closure;
|
static FollowRootClosure follow_root_closure;
|
||||||
|
static CodeBlobToOopClosure follow_code_root_closure; // => follow_root_closure
|
||||||
static MarkAndPushClosure mark_and_push_closure;
|
static MarkAndPushClosure mark_and_push_closure;
|
||||||
static FollowStackClosure follow_stack_closure;
|
static FollowStackClosure follow_stack_closure;
|
||||||
static AdjustPointerClosure adjust_root_pointer_closure;
|
static AdjustPointerClosure adjust_root_pointer_closure;
|
||||||
|
|
|
@ -263,6 +263,14 @@ class CollectedHeap : public CHeapObj {
|
||||||
return p == NULL || is_permanent(p);
|
return p == NULL || is_permanent(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An object is scavengable if its location may move during a scavenge.
|
||||||
|
// (A scavenge is a GC which is not a full GC.)
|
||||||
|
// Currently, this just means it is not perm (and not null).
|
||||||
|
// This could change if we rethink what's in perm-gen.
|
||||||
|
bool is_scavengable(const void *p) const {
|
||||||
|
return !is_in_permanent_or_null(p);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns "TRUE" if "p" is a method oop in the
|
// Returns "TRUE" if "p" is a method oop in the
|
||||||
// current heap, with high probability. This predicate
|
// current heap, with high probability. This predicate
|
||||||
// is not stable, in general.
|
// is not stable, in general.
|
||||||
|
|
|
@ -555,12 +555,14 @@ void DefNewGeneration::collect(bool full,
|
||||||
"save marks have not been newly set.");
|
"save marks have not been newly set.");
|
||||||
|
|
||||||
gch->gen_process_strong_roots(_level,
|
gch->gen_process_strong_roots(_level,
|
||||||
true, // Process younger gens, if any, as
|
true, // Process younger gens, if any,
|
||||||
// strong roots.
|
// as strong roots.
|
||||||
false,// not collecting permanent generation.
|
true, // activate StrongRootsScope
|
||||||
|
false, // not collecting perm generation.
|
||||||
SharedHeap::SO_AllClasses,
|
SharedHeap::SO_AllClasses,
|
||||||
&fsc_with_gc_barrier,
|
&fsc_with_no_gc_barrier,
|
||||||
&fsc_with_no_gc_barrier);
|
true, // walk *all* scavengable nmethods
|
||||||
|
&fsc_with_gc_barrier);
|
||||||
|
|
||||||
// "evacuate followers".
|
// "evacuate followers".
|
||||||
evacuate_followers.do_void();
|
evacuate_followers.do_void();
|
||||||
|
|
|
@ -677,13 +677,23 @@ static AssertIsPermClosure assert_is_perm_closure;
|
||||||
void GenCollectedHeap::
|
void GenCollectedHeap::
|
||||||
gen_process_strong_roots(int level,
|
gen_process_strong_roots(int level,
|
||||||
bool younger_gens_as_roots,
|
bool younger_gens_as_roots,
|
||||||
|
bool activate_scope,
|
||||||
bool collecting_perm_gen,
|
bool collecting_perm_gen,
|
||||||
SharedHeap::ScanningOption so,
|
SharedHeap::ScanningOption so,
|
||||||
OopsInGenClosure* older_gens,
|
OopsInGenClosure* not_older_gens,
|
||||||
OopsInGenClosure* not_older_gens) {
|
bool do_code_roots,
|
||||||
|
OopsInGenClosure* older_gens) {
|
||||||
// General strong roots.
|
// General strong roots.
|
||||||
SharedHeap::process_strong_roots(collecting_perm_gen, so,
|
|
||||||
not_older_gens, older_gens);
|
if (!do_code_roots) {
|
||||||
|
SharedHeap::process_strong_roots(activate_scope, collecting_perm_gen, so,
|
||||||
|
not_older_gens, NULL, older_gens);
|
||||||
|
} else {
|
||||||
|
bool do_code_marking = (activate_scope || nmethod::oops_do_marking_is_active());
|
||||||
|
CodeBlobToOopClosure code_roots(not_older_gens, /*do_marking=*/ do_code_marking);
|
||||||
|
SharedHeap::process_strong_roots(activate_scope, collecting_perm_gen, so,
|
||||||
|
not_older_gens, &code_roots, older_gens);
|
||||||
|
}
|
||||||
|
|
||||||
if (younger_gens_as_roots) {
|
if (younger_gens_as_roots) {
|
||||||
if (!_gen_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) {
|
if (!_gen_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) {
|
||||||
|
@ -706,8 +716,9 @@ gen_process_strong_roots(int level,
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure,
|
void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure,
|
||||||
|
CodeBlobClosure* code_roots,
|
||||||
OopClosure* non_root_closure) {
|
OopClosure* non_root_closure) {
|
||||||
SharedHeap::process_weak_roots(root_closure, non_root_closure);
|
SharedHeap::process_weak_roots(root_closure, code_roots, non_root_closure);
|
||||||
// "Local" "weak" refs
|
// "Local" "weak" refs
|
||||||
for (int i = 0; i < _n_gens; i++) {
|
for (int i = 0; i < _n_gens; i++) {
|
||||||
_gens[i]->ref_processor()->weak_oops_do(root_closure);
|
_gens[i]->ref_processor()->weak_oops_do(root_closure);
|
||||||
|
|
|
@ -408,16 +408,22 @@ public:
|
||||||
// "SO_SystemClasses" to all the "system" classes and loaders;
|
// "SO_SystemClasses" to all the "system" classes and loaders;
|
||||||
// "SO_Symbols_and_Strings" applies the closure to all entries in
|
// "SO_Symbols_and_Strings" applies the closure to all entries in
|
||||||
// SymbolsTable and StringTable.
|
// SymbolsTable and StringTable.
|
||||||
void gen_process_strong_roots(int level, bool younger_gens_as_roots,
|
void gen_process_strong_roots(int level,
|
||||||
|
bool younger_gens_as_roots,
|
||||||
|
// The remaining arguments are in an order
|
||||||
|
// consistent with SharedHeap::process_strong_roots:
|
||||||
|
bool activate_scope,
|
||||||
bool collecting_perm_gen,
|
bool collecting_perm_gen,
|
||||||
SharedHeap::ScanningOption so,
|
SharedHeap::ScanningOption so,
|
||||||
OopsInGenClosure* older_gens,
|
OopsInGenClosure* not_older_gens,
|
||||||
OopsInGenClosure* not_older_gens);
|
bool do_code_roots,
|
||||||
|
OopsInGenClosure* older_gens);
|
||||||
|
|
||||||
// Apply "blk" to all the weak roots of the system. These include
|
// Apply "blk" to all the weak roots of the system. These include
|
||||||
// JNI weak roots, the code cache, system dictionary, symbol table,
|
// JNI weak roots, the code cache, system dictionary, symbol table,
|
||||||
// string table, and referents of reachable weak refs.
|
// string table, and referents of reachable weak refs.
|
||||||
void gen_process_weak_roots(OopClosure* root_closure,
|
void gen_process_weak_roots(OopClosure* root_closure,
|
||||||
|
CodeBlobClosure* code_roots,
|
||||||
OopClosure* non_root_closure);
|
OopClosure* non_root_closure);
|
||||||
|
|
||||||
// Set the saved marks of generations, if that makes sense.
|
// Set the saved marks of generations, if that makes sense.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -244,9 +244,12 @@ void GenMarkSweep::mark_sweep_phase1(int level,
|
||||||
|
|
||||||
gch->gen_process_strong_roots(level,
|
gch->gen_process_strong_roots(level,
|
||||||
false, // Younger gens are not roots.
|
false, // Younger gens are not roots.
|
||||||
|
true, // activate StrongRootsScope
|
||||||
true, // Collecting permanent generation.
|
true, // Collecting permanent generation.
|
||||||
SharedHeap::SO_SystemClasses,
|
SharedHeap::SO_SystemClasses,
|
||||||
&follow_root_closure, &follow_root_closure);
|
&follow_root_closure,
|
||||||
|
true, // walk code active on stacks
|
||||||
|
&follow_root_closure);
|
||||||
|
|
||||||
// Process reference objects found during marking
|
// Process reference objects found during marking
|
||||||
{
|
{
|
||||||
|
@ -338,14 +341,19 @@ void GenMarkSweep::mark_sweep_phase3(int level) {
|
||||||
|
|
||||||
gch->gen_process_strong_roots(level,
|
gch->gen_process_strong_roots(level,
|
||||||
false, // Younger gens are not roots.
|
false, // Younger gens are not roots.
|
||||||
|
true, // activate StrongRootsScope
|
||||||
true, // Collecting permanent generation.
|
true, // Collecting permanent generation.
|
||||||
SharedHeap::SO_AllClasses,
|
SharedHeap::SO_AllClasses,
|
||||||
&adjust_root_pointer_closure,
|
&adjust_root_pointer_closure,
|
||||||
|
false, // do not walk code
|
||||||
&adjust_root_pointer_closure);
|
&adjust_root_pointer_closure);
|
||||||
|
|
||||||
// Now adjust pointers in remaining weak roots. (All of which should
|
// Now adjust pointers in remaining weak roots. (All of which should
|
||||||
// have been cleared if they pointed to non-surviving objects.)
|
// have been cleared if they pointed to non-surviving objects.)
|
||||||
|
CodeBlobToOopClosure adjust_code_pointer_closure(&adjust_pointer_closure,
|
||||||
|
/*do_marking=*/ false);
|
||||||
gch->gen_process_weak_roots(&adjust_root_pointer_closure,
|
gch->gen_process_weak_roots(&adjust_root_pointer_closure,
|
||||||
|
&adjust_code_pointer_closure,
|
||||||
&adjust_pointer_closure);
|
&adjust_pointer_closure);
|
||||||
|
|
||||||
adjust_marks();
|
adjust_marks();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2001 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -46,3 +46,42 @@ void OopClosure::set_must_remember_klasses(bool v) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
MarkingCodeBlobClosure::MarkScope::MarkScope(bool activate)
|
||||||
|
: _active(activate)
|
||||||
|
{
|
||||||
|
if (_active) nmethod::oops_do_marking_prologue();
|
||||||
|
}
|
||||||
|
|
||||||
|
MarkingCodeBlobClosure::MarkScope::~MarkScope() {
|
||||||
|
if (_active) nmethod::oops_do_marking_epilogue();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarkingCodeBlobClosure::do_code_blob(CodeBlob* cb) {
|
||||||
|
if (!cb->is_nmethod()) return;
|
||||||
|
nmethod* nm = (nmethod*) cb;
|
||||||
|
if (!nm->test_set_oops_do_mark()) {
|
||||||
|
NOT_PRODUCT(if (TraceScavenge) nm->print_on(tty, "oops_do, 1st visit\n"));
|
||||||
|
do_newly_marked_nmethod(nm);
|
||||||
|
} else {
|
||||||
|
NOT_PRODUCT(if (TraceScavenge) nm->print_on(tty, "oops_do, skipped on 2nd visit\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeBlobToOopClosure::do_newly_marked_nmethod(nmethod* nm) {
|
||||||
|
nm->oops_do(_cl, /*do_strong_roots_only=*/ true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeBlobToOopClosure::do_code_blob(CodeBlob* cb) {
|
||||||
|
if (!_do_marking) {
|
||||||
|
NOT_PRODUCT(if (TraceScavenge && Verbose && cb->is_nmethod()) ((nmethod*)cb)->print_on(tty, "oops_do, unmarked visit\n"));
|
||||||
|
// This assert won't work, since there are lots of mini-passes
|
||||||
|
// (mostly in debug mode) that co-exist with marking phases.
|
||||||
|
//assert(!(cb->is_nmethod() && ((nmethod*)cb)->test_oops_do_mark()), "found marked nmethod during mark-free phase");
|
||||||
|
cb->oops_do(_cl);
|
||||||
|
} else {
|
||||||
|
MarkingCodeBlobClosure::do_code_blob(cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -24,6 +24,8 @@
|
||||||
|
|
||||||
// The following classes are C++ `closures` for iterating over objects, roots and spaces
|
// The following classes are C++ `closures` for iterating over objects, roots and spaces
|
||||||
|
|
||||||
|
class CodeBlob;
|
||||||
|
class nmethod;
|
||||||
class ReferenceProcessor;
|
class ReferenceProcessor;
|
||||||
class DataLayout;
|
class DataLayout;
|
||||||
|
|
||||||
|
@ -69,9 +71,6 @@ class OopClosure : public Closure {
|
||||||
virtual const bool should_remember_mdo() const { return false; }
|
virtual const bool should_remember_mdo() const { return false; }
|
||||||
virtual void remember_mdo(DataLayout* v) { /* do nothing */ }
|
virtual void remember_mdo(DataLayout* v) { /* do nothing */ }
|
||||||
|
|
||||||
// If "true", invoke on nmethods (when scanning compiled frames).
|
|
||||||
virtual const bool do_nmethods() const { return false; }
|
|
||||||
|
|
||||||
// The methods below control how object iterations invoking this closure
|
// The methods below control how object iterations invoking this closure
|
||||||
// should be performed:
|
// should be performed:
|
||||||
|
|
||||||
|
@ -176,6 +175,51 @@ class CompactibleSpaceClosure : public StackObj {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// CodeBlobClosure is used for iterating through code blobs
|
||||||
|
// in the code cache or on thread stacks
|
||||||
|
|
||||||
|
class CodeBlobClosure : public Closure {
|
||||||
|
public:
|
||||||
|
// Called for each code blob.
|
||||||
|
virtual void do_code_blob(CodeBlob* cb) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MarkingCodeBlobClosure : public CodeBlobClosure {
|
||||||
|
public:
|
||||||
|
// Called for each code blob, but at most once per unique blob.
|
||||||
|
virtual void do_newly_marked_nmethod(nmethod* nm) = 0;
|
||||||
|
|
||||||
|
virtual void do_code_blob(CodeBlob* cb);
|
||||||
|
// = { if (!nmethod(cb)->test_set_oops_do_mark()) do_newly_marked_nmethod(cb); }
|
||||||
|
|
||||||
|
class MarkScope : public StackObj {
|
||||||
|
protected:
|
||||||
|
bool _active;
|
||||||
|
public:
|
||||||
|
MarkScope(bool activate = true);
|
||||||
|
// = { if (active) nmethod::oops_do_marking_prologue(); }
|
||||||
|
~MarkScope();
|
||||||
|
// = { if (active) nmethod::oops_do_marking_epilogue(); }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Applies an oop closure to all ref fields in code blobs
|
||||||
|
// iterated over in an object iteration.
|
||||||
|
class CodeBlobToOopClosure: public MarkingCodeBlobClosure {
|
||||||
|
OopClosure* _cl;
|
||||||
|
bool _do_marking;
|
||||||
|
public:
|
||||||
|
virtual void do_newly_marked_nmethod(nmethod* cb);
|
||||||
|
// = { cb->oops_do(_cl); }
|
||||||
|
virtual void do_code_blob(CodeBlob* cb);
|
||||||
|
// = { if (_do_marking) super::do_code_blob(cb); else cb->oops_do(_cl); }
|
||||||
|
CodeBlobToOopClosure(OopClosure* cl, bool do_marking)
|
||||||
|
: _cl(cl), _do_marking(do_marking) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// MonitorClosure is used for iterating over monitors in the monitors cache
|
// MonitorClosure is used for iterating over monitors in the monitors cache
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -100,12 +100,27 @@ void SharedHeap::change_strong_roots_parity() {
|
||||||
"Not in range.");
|
"Not in range.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedHeap::process_strong_roots(bool collecting_perm_gen,
|
SharedHeap::StrongRootsScope::StrongRootsScope(SharedHeap* outer, bool activate)
|
||||||
|
: MarkScope(activate)
|
||||||
|
{
|
||||||
|
if (_active) {
|
||||||
|
outer->change_strong_roots_parity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedHeap::StrongRootsScope::~StrongRootsScope() {
|
||||||
|
// nothing particular
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedHeap::process_strong_roots(bool activate_scope,
|
||||||
|
bool collecting_perm_gen,
|
||||||
ScanningOption so,
|
ScanningOption so,
|
||||||
OopClosure* roots,
|
OopClosure* roots,
|
||||||
|
CodeBlobClosure* code_roots,
|
||||||
OopsInGenClosure* perm_blk) {
|
OopsInGenClosure* perm_blk) {
|
||||||
|
StrongRootsScope srs(this, activate_scope);
|
||||||
// General strong roots.
|
// General strong roots.
|
||||||
if (n_par_threads() == 0) change_strong_roots_parity();
|
assert(_strong_roots_parity != 0, "must have called prologue code");
|
||||||
if (!_process_strong_tasks->is_task_claimed(SH_PS_Universe_oops_do)) {
|
if (!_process_strong_tasks->is_task_claimed(SH_PS_Universe_oops_do)) {
|
||||||
Universe::oops_do(roots);
|
Universe::oops_do(roots);
|
||||||
ReferenceProcessor::oops_do(roots);
|
ReferenceProcessor::oops_do(roots);
|
||||||
|
@ -117,9 +132,9 @@ void SharedHeap::process_strong_roots(bool collecting_perm_gen,
|
||||||
JNIHandles::oops_do(roots);
|
JNIHandles::oops_do(roots);
|
||||||
// All threads execute this; the individual threads are task groups.
|
// All threads execute this; the individual threads are task groups.
|
||||||
if (ParallelGCThreads > 0) {
|
if (ParallelGCThreads > 0) {
|
||||||
Threads::possibly_parallel_oops_do(roots);
|
Threads::possibly_parallel_oops_do(roots, code_roots);
|
||||||
} else {
|
} else {
|
||||||
Threads::oops_do(roots);
|
Threads::oops_do(roots, code_roots);
|
||||||
}
|
}
|
||||||
if (!_process_strong_tasks-> is_task_claimed(SH_PS_ObjectSynchronizer_oops_do))
|
if (!_process_strong_tasks-> is_task_claimed(SH_PS_ObjectSynchronizer_oops_do))
|
||||||
ObjectSynchronizer::oops_do(roots);
|
ObjectSynchronizer::oops_do(roots);
|
||||||
|
@ -157,10 +172,28 @@ void SharedHeap::process_strong_roots(bool collecting_perm_gen,
|
||||||
|
|
||||||
if (!_process_strong_tasks->is_task_claimed(SH_PS_CodeCache_oops_do)) {
|
if (!_process_strong_tasks->is_task_claimed(SH_PS_CodeCache_oops_do)) {
|
||||||
if (so & SO_CodeCache) {
|
if (so & SO_CodeCache) {
|
||||||
CodeCache::oops_do(roots);
|
// (Currently, CMSCollector uses this to do intermediate-strength collections.)
|
||||||
|
assert(collecting_perm_gen, "scanning all of code cache");
|
||||||
|
assert(code_roots != NULL, "must supply closure for code cache");
|
||||||
|
if (code_roots != NULL) {
|
||||||
|
CodeCache::blobs_do(code_roots);
|
||||||
|
}
|
||||||
|
} else if (so & (SO_SystemClasses|SO_AllClasses)) {
|
||||||
|
if (!collecting_perm_gen) {
|
||||||
|
// If we are collecting from class statics, but we are not going to
|
||||||
|
// visit all of the CodeCache, collect from the non-perm roots if any.
|
||||||
|
// This makes the code cache function temporarily as a source of strong
|
||||||
|
// roots for oops, until the next major collection.
|
||||||
|
//
|
||||||
|
// If collecting_perm_gen is true, we require that this phase will call
|
||||||
|
// CodeCache::do_unloading. This will kill off nmethods with expired
|
||||||
|
// weak references, such as stale invokedynamic targets.
|
||||||
|
CodeCache::scavenge_root_nmethods_do(code_roots);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Verify if the code cache contents are in the perm gen
|
// Verify if the code cache contents are in the perm gen
|
||||||
NOT_PRODUCT(CodeCache::oops_do(&assert_is_perm_closure));
|
NOT_PRODUCT(CodeBlobToOopClosure assert_code_is_perm(&assert_is_perm_closure, /*do_marking=*/ false));
|
||||||
|
NOT_PRODUCT(CodeCache::asserted_non_scavengable_nmethods_do(&assert_code_is_perm));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Roots that should point only into permanent generation.
|
// Roots that should point only into permanent generation.
|
||||||
|
@ -220,11 +253,12 @@ public:
|
||||||
// just skip adjusting any shared entries in the string table.
|
// just skip adjusting any shared entries in the string table.
|
||||||
|
|
||||||
void SharedHeap::process_weak_roots(OopClosure* root_closure,
|
void SharedHeap::process_weak_roots(OopClosure* root_closure,
|
||||||
|
CodeBlobClosure* code_roots,
|
||||||
OopClosure* non_root_closure) {
|
OopClosure* non_root_closure) {
|
||||||
// Global (weak) JNI handles
|
// Global (weak) JNI handles
|
||||||
JNIHandles::weak_oops_do(&always_true, root_closure);
|
JNIHandles::weak_oops_do(&always_true, root_closure);
|
||||||
|
|
||||||
CodeCache::oops_do(non_root_closure);
|
CodeCache::blobs_do(code_roots);
|
||||||
SymbolTable::oops_do(root_closure);
|
SymbolTable::oops_do(root_closure);
|
||||||
if (UseSharedSpaces && !DumpSharedSpaces) {
|
if (UseSharedSpaces && !DumpSharedSpaces) {
|
||||||
SkipAdjustingSharedStrings skip_closure(root_closure);
|
SkipAdjustingSharedStrings skip_closure(root_closure);
|
||||||
|
|
|
@ -165,9 +165,21 @@ public:
|
||||||
// c) to never return a distinguished value (zero) with which such
|
// c) to never return a distinguished value (zero) with which such
|
||||||
// task-claiming variables may be initialized, to indicate "never
|
// task-claiming variables may be initialized, to indicate "never
|
||||||
// claimed".
|
// claimed".
|
||||||
|
private:
|
||||||
void change_strong_roots_parity();
|
void change_strong_roots_parity();
|
||||||
|
public:
|
||||||
int strong_roots_parity() { return _strong_roots_parity; }
|
int strong_roots_parity() { return _strong_roots_parity; }
|
||||||
|
|
||||||
|
// Call these in sequential code around process_strong_roots.
|
||||||
|
// strong_roots_prologue calls change_strong_roots_parity, if
|
||||||
|
// parallel tasks are enabled.
|
||||||
|
class StrongRootsScope : public MarkingCodeBlobClosure::MarkScope {
|
||||||
|
public:
|
||||||
|
StrongRootsScope(SharedHeap* outer, bool activate = true);
|
||||||
|
~StrongRootsScope();
|
||||||
|
};
|
||||||
|
friend class StrongRootsScope;
|
||||||
|
|
||||||
enum ScanningOption {
|
enum ScanningOption {
|
||||||
SO_None = 0x0,
|
SO_None = 0x0,
|
||||||
SO_AllClasses = 0x1,
|
SO_AllClasses = 0x1,
|
||||||
|
@ -198,15 +210,18 @@ public:
|
||||||
// "SO_Symbols" applies the closure to all entries in SymbolsTable;
|
// "SO_Symbols" applies the closure to all entries in SymbolsTable;
|
||||||
// "SO_Strings" applies the closure to all entries in StringTable;
|
// "SO_Strings" applies the closure to all entries in StringTable;
|
||||||
// "SO_CodeCache" applies the closure to all elements of the CodeCache.
|
// "SO_CodeCache" applies the closure to all elements of the CodeCache.
|
||||||
void process_strong_roots(bool collecting_perm_gen,
|
void process_strong_roots(bool activate_scope,
|
||||||
|
bool collecting_perm_gen,
|
||||||
ScanningOption so,
|
ScanningOption so,
|
||||||
OopClosure* roots,
|
OopClosure* roots,
|
||||||
|
CodeBlobClosure* code_roots,
|
||||||
OopsInGenClosure* perm_blk);
|
OopsInGenClosure* perm_blk);
|
||||||
|
|
||||||
// Apply "blk" to all the weak roots of the system. These include
|
// Apply "blk" to all the weak roots of the system. These include
|
||||||
// JNI weak roots, the code cache, system dictionary, symbol table,
|
// JNI weak roots, the code cache, system dictionary, symbol table,
|
||||||
// string table.
|
// string table.
|
||||||
void process_weak_roots(OopClosure* root_closure,
|
void process_weak_roots(OopClosure* root_closure,
|
||||||
|
CodeBlobClosure* code_roots,
|
||||||
OopClosure* non_root_closure);
|
OopClosure* non_root_closure);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue