This commit is contained in:
Xiaobin Lu 2009-10-14 12:40:20 -07:00
commit 88d2bc6d8d
1393 changed files with 45972 additions and 38110 deletions

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

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

View 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

View file

@ -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
# Make sure we have the current year
ifndef COPYRIGHT_YEAR
ifdef ALT_COPYRIGHT_YEAR ifdef ALT_COPYRIGHT_YEAR
COPYRIGHT_YEAR = $(ALT_COPYRIGHT_YEAR) COPYRIGHT_YEAR := $(ALT_COPYRIGHT_YEAR)
else else
COPYRIGHT_YEAR = $(shell $(DATE) '+%Y') 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)

View file

@ -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

View file

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

View file

@ -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

View file

@ -113,6 +113,7 @@ _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.
ifndef UNIXCOMMAND_PATH
ifdef ALT_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))
@ -134,11 +135,16 @@ else
endif endif
endif endif
UNIXCOMMAND_PATH:=$(call AltCheckSpaces,UNIXCOMMAND_PATH) UNIXCOMMAND_PATH:=$(call AltCheckSpaces,UNIXCOMMAND_PATH)
export UNIXCOMMAND_PATH
endif
# Get version of MKS or CYGWIN # Get version of MKS or CYGWIN
ifdef USING_CYGWIN ifdef USING_CYGWIN
ifndef CYGWIN_VER
_CYGWIN_VER :=$(shell $(UNAME)) _CYGWIN_VER :=$(shell $(UNAME))
CYGWIN_VER :=$(call GetVersion,$(_CYGWIN_VER)) 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,29 +174,8 @@ 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
ifndef SHORTPROGRAMFILES
ifdef PROGRAMFILES ifdef PROGRAMFILES
xPROGRAMFILES :="$(subst \,/,$(PROGRAMFILES))" xPROGRAMFILES :="$(subst \,/,$(PROGRAMFILES))"
else else
@ -201,120 +186,126 @@ else
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
ifneq ($(word 1,$(SHORTPROGRAMFILES)),$(SHORTPROGRAMFILES))
SHORTPROGRAMFILES :=
endif endif
ifneq ($(word 1,$(_program_files)),$(_program_files)) export SHORTPROGRAMFILES
_program_files:=
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
ifndef SLASH_JAVA
ifdef ALT_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))
@ -327,8 +318,11 @@ else
endif endif
SLASH_JAVA:=$(call AltCheckSpaces,SLASH_JAVA) SLASH_JAVA:=$(call AltCheckSpaces,SLASH_JAVA)
SLASH_JAVA:=$(call AltCheckValue,SLASH_JAVA) SLASH_JAVA:=$(call AltCheckValue,SLASH_JAVA)
export SLASH_JAVA
endif
# JDK_DEVTOOLS_DIR: common path for all the java devtools # JDK_DEVTOOLS_DIR: common path for all the java devtools
ifndef JDK_DEVTOOLS_DIR
ifdef ALT_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))
@ -337,20 +331,26 @@ else
endif endif
JDK_DEVTOOLS_DIR:=$(call AltCheckSpaces,JDK_DEVTOOLS_DIR) JDK_DEVTOOLS_DIR:=$(call AltCheckSpaces,JDK_DEVTOOLS_DIR)
JDK_DEVTOOLS_DIR:=$(call AltCheckValue,JDK_DEVTOOLS_DIR) JDK_DEVTOOLS_DIR:=$(call AltCheckValue,JDK_DEVTOOLS_DIR)
export JDK_DEVTOOLS_DIR
endif
# 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.
ifndef COMPILER_PATH
ifdef ALT_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 endif
COMPILER_PATH :=$(call AltCheckSpaces,COMPILER_PATH) COMPILER_PATH :=$(call AltCheckSpaces,COMPILER_PATH)
export COMPILER_PATH
endif
# 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.
ifndef MSDEVTOOLS_PATH
ifdef ALT_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))
@ -372,17 +372,20 @@ 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 endif
MSDEVTOOLS_PATH:=$(call AltCheckSpaces,MSDEVTOOLS_PATH) MSDEVTOOLS_PATH:=$(call AltCheckSpaces,MSDEVTOOLS_PATH)
export MSDEVTOOLS_PATH
endif
# 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.
ifndef DEVTOOLS_PATH
ifdef ALT_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))
@ -397,6 +400,8 @@ else
endif endif
endif endif
DEVTOOLS_PATH:=$(call AltCheckSpaces,DEVTOOLS_PATH) DEVTOOLS_PATH:=$(call AltCheckSpaces,DEVTOOLS_PATH)
export DEVTOOLS_PATH
endif
# _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,6 +415,7 @@ 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.
ifndef BUILD_JDK_IMPORT_PATH
ifdef ALT_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
@ -417,8 +423,11 @@ else
endif endif
BUILD_JDK_IMPORT_PATH:=$(call AltCheckSpaces,BUILD_JDK_IMPORT_PATH) BUILD_JDK_IMPORT_PATH:=$(call AltCheckSpaces,BUILD_JDK_IMPORT_PATH)
BUILD_JDK_IMPORT_PATH:=$(call AltCheckValue,BUILD_JDK_IMPORT_PATH) BUILD_JDK_IMPORT_PATH:=$(call AltCheckValue,BUILD_JDK_IMPORT_PATH)
export BUILD_JDK_IMPORT_PATH
endif
# JDK_IMPORT_PATH: location of previously built JDK (this version) to import # JDK_IMPORT_PATH: location of previously built JDK (this version) to import
ifndef JDK_IMPORT_PATH
ifdef ALT_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
@ -426,4 +435,6 @@ else
endif endif
JDK_IMPORT_PATH:=$(call AltCheckSpaces,JDK_IMPORT_PATH) JDK_IMPORT_PATH:=$(call AltCheckSpaces,JDK_IMPORT_PATH)
JDK_IMPORT_PATH:=$(call AltCheckValue,JDK_IMPORT_PATH) JDK_IMPORT_PATH:=$(call AltCheckValue,JDK_IMPORT_PATH)
export JDK_IMPORT_PATH
endif

View file

@ -228,6 +228,7 @@ 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
ifndef FULL_VERSION
ifdef BUILD_NUMBER ifdef BUILD_NUMBER
FULL_VERSION = $(RELEASE)-$(BUILD_NUMBER) FULL_VERSION = $(RELEASE)-$(BUILD_NUMBER)
else else
@ -235,6 +236,8 @@ else
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 endif
export FULL_VERSION
endif
# Promoted build location # Promoted build location
PROMOTED_RE_AREA = $(SLASH_JAVA)/re/jdk/$(JDK_VERSION)/promoted PROMOTED_RE_AREA = $(SLASH_JAVA)/re/jdk/$(JDK_VERSION)/promoted

View file

@ -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
ifndef SYSTEM_UNAME
SYSTEM_UNAME := $(shell 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,6 +383,7 @@ 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.
ifndef MAX_VM_MEMORY
ifneq ($(MB_OF_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 \
@ -412,6 +409,11 @@ else
MAX_VM_MEMORY := 384 MAX_VM_MEMORY := 384
MIN_VM_MEMORY := 128 MIN_VM_MEMORY := 128
endif endif
export MAX_VM_MEMORY
export MIN_VM_MEMORY
export LOW_MEMORY_MACHINE
export MAX_VM_MEMORY
endif
REQUIRED_ZIP_VER = 2.2 REQUIRED_ZIP_VER = 2.2
REQUIRED_UNZIP_VER = 5.12 REQUIRED_UNZIP_VER = 5.12

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

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

View file

@ -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(); }

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
}

View file

@ -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
}; };

View file

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

View file

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

View file

@ -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);
%} %}

View file

@ -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

View file

@ -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

View file

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

View file

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

View file

@ -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 );
%} %}

View file

@ -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 );
%} %}

View file

@ -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

View file

@ -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

View file

@ -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.

View file

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

View file

@ -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

View file

@ -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

View file

@ -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()) {

View file

@ -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

View file

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

View file

@ -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 {

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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; }

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

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

View file

@ -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; }

View file

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

View file

@ -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(); }

View file

@ -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 ||

View file

@ -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

View file

@ -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()));
} }
} }
} }

View file

@ -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",

View file

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

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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, &notOlder); &notOlder,
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, &notOlder); &notOlder,
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, &notOlder); &notOlder,
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");
} }

View file

@ -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,
&notOlder, // Regular roots &notOlder, // 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);

View file

@ -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

View file

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

View file

@ -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

View file

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

View file

@ -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

View file

@ -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, // no scope; this is parallel code
false, // not collecting perm generation. 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();

View file

@ -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) {

View file

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

View file

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

View file

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

View file

@ -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

View file

@ -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

View file

@ -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.)

View file

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

View file

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

View file

@ -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(),

View file

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

View file

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

View file

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

View file

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

View file

@ -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.

View file

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

View file

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

View file

@ -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.

View file

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

View file

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

View file

@ -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

View file

@ -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

View file

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

View file

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

View file

@ -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