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
1b662b1ed14eb4ae31d5138a36c433b13d941dc5 jdk7-b69
207f694795c448c17753eff1a2f50363106960c2 jdk7-b70
c5d39b6be65cba0effb5f466ea48fe43764d0e0c jdk7-b71
df4bcd06e1d0ab306efa5a44f24a409dc0c0c742 jdk7-b72
ce74bd35ce948d629a356e168797f44b593b1578 jdk7-b73

View File

@ -45,3 +45,6 @@ c4523c6f82048f420bf0d57c4cd47976753b7d2c jdk7-b67
e1b972ff53cd58f825791f8ed9b2deffd16e768c jdk7-b68
82e6c820c51ac27882b77755d42efefdbf1dcda0 jdk7-b69
175cb3fe615998d1004c6d3fd96e6d2e86b6772d jdk7-b70
4c36e9853dda27bdac5ef4839a610509fbe31d34 jdk7-b71
0d7e03b426df27c21dcc44ffb9178eacd1b04f10 jdk7-b72
3ac6dcf7823205546fbbc3d4ea59f37358d0b0d4 jdk7-b73

View File

@ -38,12 +38,17 @@
<ul>
<li><a href="#introduction">Introduction</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>
<li><a href="#fedora">Fedora Linux</a> </li>
<li><a href="#centos">CentOS Linux</a> </li>
<li><a href="#ubuntu">Ubuntu Linux</a> </li>
<li><a href="#debian">Debian GNU/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>
</li>
<li><a href="#directories">Source Directory Structure</a> </li>
<li><a href="#building">Build Information</a>
<ul>
@ -68,7 +73,6 @@
</li>
<li><a href="#zip">Zip and Unzip</a> </li>
<li><a href="#freetype">FreeType2 Fonts</a> </li>
<li><a href="#jibx">JIBX Libraries</a> </li>
<li>Linux and Solaris:
<ul>
<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.
</blockquote>
<!-- ------------------------------------------------------ -->
<h3><a name="fedora">Fedora 9</a></h3>
<h3><a name="fedora">Fedora</a></h3>
<blockquote>
After installing
<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>
<h4>Fedora 9</h4>
<p>
<blockquote>
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>
<p>
Always a good idea to do a complete Software Update/Refresh
after you get all the packages installed.
<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>
<!-- ------------------------------------------------------ -->
<h3><a name="centos">CentOS 5.2</a></h3>
@ -270,145 +309,146 @@
it's needed.
</blockquote>
<!-- ------------------------------------------------------ -->
<h3><a name="ubuntu">Ubuntu</a></h3>
<h3><a name="debian">Debian</a></h3>
<blockquote>
In addition to needing the Bootstrap JDK and the Binary Plugs,
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>
<h4>Debian 5.0 (Lenny)</h4>
<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>
<ul>
<li>binutils (2.16.1cvs20060117-1ubuntu2.1)</li>
<li>cpp (4:4.0.3-1)</li>
<li>cpp-4.0 (4.0.3-1ubuntu5)</li>
<li>libfreetype6-dev</li>
<li>g++ (4:4.0.3-1)</li>
<li>g++-4.0 (4.0.3-1ubuntu5)</li>
<li>gawk (1:3.1.5-2build1)</li>
<li>gcc (4:4.0.3-1)</li>
<li>gcc-4.0 (4.0.3-1ubuntu5)</li>
<li>libasound2-dev (1.0.10-2ubuntu4)</li>
<li>libc6 (2.3.6-0ubuntu20) to 2.3.6-0ubuntu20.4</li>
<li>libc6-dev (2.3.6-0ubuntu20.4)</li>
<li>libc6-i686 (2.3.6-0ubuntu20) to 2.3.6-0ubuntu20.4</li>
<li>libcupsys2-dev (1.2.2-0ubuntu0.6.06)</li>
<li>libgcrypt11-dev (1.2.2-1)</li>
<li>libgnutls-dev (1.2.9-2ubuntu1.1)</li>
<li>libgnutls12 (1.2.9-2ubuntu1) to 1.2.9-2ubuntu1.1</li>
<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>
<!-- ------------------------------------------------------ -->
<h4>Ubuntu 7.04</h4>
<p>
Using the Synaptic Package Manager, download the following
packages (double indented packages are automatically aquired
due to package dependencies):
<blockquote>
<ul>
<li>build-essential</li>
<ul>
<li>dpkg-dev</li>
<li>g++</li>
<li>g++-4.1</li>
<li>libc6-dev</li>
<li>libstdc++6.4.1-dev</li>
<li>linux-libc-dev</li>
</ul>
<li>gawk</li>
<li>m4</li>
<li>libasound2-dev</li>
<li>libcupsys2-dev</li>
<ul>
<li>libgcrypt11-dev</li>
<li>lgnutls-dev</li>
<li>libgpg-error-dev</li>
<li>liblzo-dev</li>
<li>libopencdk8-dev</li>
<li>libpopt-dev</li>
<li>libtasn1-3-dev</li>
<li>zlib1g-dev</li>
</ul>
<li>sun-java6-jdk</li>
<ul>
<li>java-common</li>
<li>libltdl3</li>
<li>odbcinst1debian1</li>
<li>sun-java6-bin</li>
<li>sun-java6-jre</li>
<li>unixodbc</li>
</ul>
<li>xlibs-dev</li>
<ul>
<li>(many)</li>
</ul>
<li>x11proto-print-dev</li>
<li>libxaw7-dev</li>
<ul>
<li>libxaw-headers</li>
</ul>
<li>libxp-dev</li>
<li>libfreetype6-dev</li>
</ul>
</blockquote>
<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>
<blockquote>
<h4>Ubuntu 8.04</h4>
<p>
<blockquote>
After installing <a href="http://ubuntu.org">Ubuntu</a> 8.04
you need to install several build dependencies.
<p/>
First, you need to enable the universe repository in the
Software Sources application and reload the repository
information. The Software Sources application is available
under the System/Administration menu.
<p/>
The simplest way to install the build dependencies is to
execute the following commands:
<p/>
<code>sudo aptitude build-dep openjdk-6</code>
<p/>
<code>sudo aptitude install openjdk-6-jdk</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>
<h4>Ubuntu 8.10</h4>
<p>
<blockquote>
After installing <a href="http://ubuntu.org">Ubuntu</a> 8.10
you need to install several build dependencies. The simplest
way to do it is to execute the following commands:
<p/>
<code>sudo aptitude build-dep openjdk-6</code>
<p/>
<code>sudo aptitude install openjdk-6-jdk</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>
<h4>Ubuntu 9.04</h4>
<p>
<blockquote>
After installing <a href="http://ubuntu.org">Ubuntu</a> 9.04
you need to install several build dependencies. The simplest
way to do it is to execute the following commands:
<p/>
<code>sudo aptitude build-dep openjdk-6</code>
<p/>
<code>sudo aptitude install openjdk-6-jdk</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="opensuse">OpenSUSE</a></h3>
<blockquote>
<h4>OpenSUSE 11.1</h4>
<p>
<blockquote>
After installing <a href="http://opensuse.org">OpenSUSE</a> 11.1
you need to install several build dependencies.
The simplest way to install the build dependencies is to
execute the following commands:
<p/>
<code>sudo zypper source-install -d java-1_6_0-openjdk</code>
<p/>
<code>sudo zypper install make</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>
<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>
<!-- ------------------------------------------------------ -->
<hr>
<h2><a name="directories">Source Directory Structure</a></h2>
<blockquote>
@ -596,11 +636,6 @@
Install or upgrade the <a href="#freetype">FreeType development
package</a>.
</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>
Install
<a href="#ant">Ant</a>,
@ -669,11 +704,6 @@
<li>
Install the <a href="#xrender">XRender Include files</a>.
</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>
Install
<a href="#ant">Ant</a>,
@ -769,11 +799,6 @@
Install
<a href="#dxsdk">Microsoft DirectX SDK</a>.
</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>
Install
<a href="#ant">Ant</a>,
@ -903,27 +928,6 @@
fine for most JDK developers.
</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>
<blockquote>
<strong><a name="gcc">Linux gcc/binutils</a></strong>
@ -1496,12 +1500,6 @@
The default will refer to
<tt>jdk/src/share/lib/security/cacerts</tt>.
</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>
<dd>
The location of the CUPS header files.

View File

@ -45,3 +45,6 @@ a12ea7c7b497b4ba7830550095ef633bd6f43971 jdk7-b67
5182bcc9c60cac429d1f7988676cec7320752be3 jdk7-b68
8120d308ec4e805c5588b8d9372844d781c4112d jdk7-b69
175bd68779546078dbdb6dacd7f0aced79ed22b1 jdk7-b70
3f1ef7f899ea2aec189c4fb67e5c8fa374437c50 jdk7-b71
c793a31209263fbb867c23c752599d85c21abb73 jdk7-b72
b751c528c55560cf2adeaeef24b39ca1f4d1cbf7 jdk7-b73

View File

@ -141,12 +141,12 @@ $(CLASSES_JAR):
#----- 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): $(SRC_ZIP_FILES)
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 -@ ) ;
#----- 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.
#
# This code is free software; you can redistribute it and/or modify it
@ -24,22 +24,29 @@
#
# 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_MANIFEST_FILE = $(BUILDTOOLCLASSDIR)/$(PROGRAM)_manifest.mf
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)
@$(prep-target)
$(ECHO) "Main-Class: $(BUILTTOOL_MAINCLASS)" > $@
$(BUILDTOOL_JAR_FILE): $(BUILDTOOL_MANIFEST_FILE) \
$(BUILDTOOL_ALL_FILES:%=$(BUILDTOOL_SOURCE_ROOT)/%)
$(BUILDTOOL_JAR_FILE): $(BUILDTOOL_MANIFEST_FILE) $(BUILDTOOL_SRC_FILES)
@$(prep-target)
@$(MKDIR) -p $(BUILDTOOLCLASSDIR)
$(BOOT_JAVAC_CMD) -d $(BUILDTOOLCLASSDIR) \
@ -49,23 +56,8 @@ $(BUILDTOOL_JAR_FILE): $(BUILDTOOL_MANIFEST_FILE) \
$(JAR_JFLAGS) || $(RM) $@
@$(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::
$(RM) -r $(BUILDTOOLCLASSDIR)/$(PKGDIR)
$(RM) $(BUILDTOOL_MANIFEST_FILE)
$(RM) $(BUILDTOOL_JAR_FILE)
$(RM) -r $(BUILDTOOLCLASSDIR)/$(PKGDIR) \
$(BUILDTOOL_MANIFEST_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.
#
# This code is free software; you can redistribute it and/or modify it
@ -56,11 +56,3 @@ ifndef USE_IMPLICITS
%: %.sh
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.
#
# 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-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
# SUBDIRS_MAKEFLAGS Make settings for a subdir make
# SUBDIRS_MAKEFLAGS-$@ Make settings specific to this target
define SUBDIRS-loop
@$(ECHO) "Begin Processing SUBDIRS: $(SUBDIRS)"
@for i in DUMMY $(SUBDIRS) ; do \
if [ "$$i" != "DUMMY" ] ; then \
$(ECHO) ">>>Recursively making "$$i" "$@" @ `$(DATE)` ..."; \
timing_id="$(TIMING_ID)-`$(BASENAME) $${i}`"; \
$(call TIMING_start,startTime); \
curDir=$(CURRENT_DIRECTORY); \
$(CD) $$i; $(MAKE) $@ TIMING_ID=$${timing_id} \
$(SUBDIRS_MAKEFLAGS) \
$(SUBDIRS_MAKEFLAGS-$@) \
FULL_VERSION=$(FULL_VERSION) \
RELEASE=$(RELEASE) || exit 1; \
$(CD) $${curDir}; \
$(call TIMING_end,startTime,timing_id); \
$(ECHO) "<<<Finished Recursively making "$$i" "$@" @ `$(DATE)`." ; \
$(MAKE) -C $${i} $@ \
$(SUBDIRS_MAKEFLAGS) \
$(SUBDIRS_MAKEFLAGS-$@) \
FULL_VERSION=$(FULL_VERSION) \
RELEASE=$(RELEASE) || exit 1; \
fi ; \
done
@$(ECHO) "Done Processing SUBDIRS: $(SUBDIRS)"
endef
# Given a OTHERSUBDIRS list, cd into them and make them (extra loop define)
# OTHERSUBDIRS_MAKEFLAGS Make settings for a subdir make
define OTHERSUBDIRS-loop
@$(ECHO) "Begin Processing OTHERSUBDIRS: $(OTHERSUBDIRS)"
@for i in DUMMY $(OTHERSUBDIRS) ; do \
if [ "$$i" != "DUMMY" ] ; then \
$(ECHO) ">>>Recursively making "$$i" "$@" @ `$(DATE)` ..."; \
timing_id="$(TIMING_ID)-`$(BASENAME) $${i}`"; \
$(call TIMING_start,startTime); \
curDir=$(CURRENT_DIRECTORY); \
$(CD) $$i; $(MAKE) $@ TIMING_ID=$${timing_id} \
$(OTHERSUBDIRS_MAKEFLAGS) \
FULL_VERSION=$(FULL_VERSION) \
RELEASE=$(RELEASE) || exit 1; \
$(CD) $${curDir}; \
$(call TIMING_end,startTime,timing_id); \
$(ECHO) "<<<Finished Recursively making "$$i" "$@" @ `$(DATE)`." ; \
$(MAKE) -C $${i} $@ \
$(OTHERSUBDIRS_MAKEFLAGS) \
FULL_VERSION=$(FULL_VERSION) \
RELEASE=$(RELEASE) || exit 1; \
fi ; \
done
@$(ECHO) "Done Processing OTHERSUBDIRS: $(OTHERSUBDIRS)"
endef
#
@ -460,46 +367,23 @@ else
VERSION_DEFINES = -DRELEASE='"$(RELEASE)"'
endif
# Note: As a rule, GNU Make rules should not appear in any of the
# Defs*.gmk files. These were added for Kestrel-Solaris and do address
# a TeamWare bug. They should be moved elsewhere for Merlin.
#
# 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
# Prevent the use of many default suffix rules we do not need
.SUFFIXES:
.SUFFIXES: .c .o .h .obj .cpp .hpp .java .class
# Make sure we are all insane
ifdef INSANE
export INSANE
endif
ifdef ALT_COPYRIGHT_YEAR
COPYRIGHT_YEAR = $(ALT_COPYRIGHT_YEAR)
else
COPYRIGHT_YEAR = $(shell $(DATE) '+%Y')
# Make sure we have the current year
ifndef COPYRIGHT_YEAR
ifdef ALT_COPYRIGHT_YEAR
COPYRIGHT_YEAR := $(ALT_COPYRIGHT_YEAR)
else
COPYRIGHT_YEAR := $(shell $(DATE) '+%Y')
endif
export COPYRIGHT_YEAR
endif
# Install of imported file (JDK_IMPORT_PATH, or some other external location)

View File

@ -27,17 +27,6 @@
#
# 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
rules_default_rule: all
@ -162,7 +151,6 @@ JAVA_SOURCE_LIST=$(TEMPDIR)/.classes.list
# Add a java source to the list
define add-java-file
$(ECHO) "$?" >> $(JAVA_SOURCE_LIST)
$(check-conventions)
endef
$(CLASSDESTDIR)/%.class: $(GENSRCDIR)/%.java
@ -197,11 +185,8 @@ JAVAC_PREFER_SOURCE = -Xprefer:source
.compile.classlist : $(JAVA_SOURCE_LIST)
@$(MKDIR) -p $(CLASSDESTDIR)
@if [ `$(CAT) $(JAVA_SOURCE_LIST) | $(WC) -l` -ge 1 ] ; then \
$(ECHO) "# Java sources to be compiled: (listed in file $(JAVA_SOURCE_LIST))"; \
if [ -s $(JAVA_SOURCE_LIST) ] ; then \
$(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); \
fi
@$(java-vm-cleanup)
@ -220,10 +205,7 @@ endif
packages.clean:
ifeq ($(DONT_CLOBBER_CLASSES),false)
ifdef AUTO_FILES_JAVA_DIRS
@for sdir in $(AUTO_FILES_JAVA_DIRS); do \
$(ECHO) "$(RM) -r $(CLASSDESTDIR)/$$sdir"; \
$(RM) -r $(CLASSDESTDIR)/$$sdir; \
done
$(RM) -r $(patsubst %, $(CLASSDESTDIR)/%, $(AUTO_FILES_JAVA_DIRS))
else
$(RM) -r $(CLASSDESTDIR)/$(PKGDIR)
endif
@ -259,15 +241,13 @@ classheaders: classes $(CLASSHDR_DOTFILE)
$(CLASSHDR_DOTFILE): $(CLASSES_export)
$(prep-target)
@$(ECHO) "# Running javah:"
$(JAVAH_CMD) -d $(CLASSHDRDIR)/ \
$(CLASSES.export) $(subst $$,\$$,$(EXPORTED_inner))
@$(java-vm-cleanup)
@$(TOUCH) $@
classheaders.clean:
$(RM) $(CLASSHDR_DOTFILE)
$(RM) -r $(CLASSHDRDIR)
$(RM) -r $(CLASSHDRDIR) $(CLASSHDR_DOTFILE)
else # FILES_export

View File

@ -48,11 +48,17 @@ ifeq ($(PLATFORM), windows)
NMAKE = MFLAGS= MAKEFLAGS= $(COMPILER_PATH)nmake -nologo
# Compiler version and type (Always get word after "Version")
CC_VER := $(shell $(CC) 2>&1 | $(HEAD) -n 1 | $(SED) 's/.*\(Version.*\)/\1/' | $(NAWK) '{print $$2}')
ifndef CC_VER
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...
ifeq ($(ARCH_DATA_MODEL), 32)
LINK_VER := $(shell $(LINK) | $(HEAD) -n 1 | $(NAWK) '{print $$6}')
ifndef LINK_VER
LINK_VER := $(shell $(LINK) | $(HEAD) -n 1 | $(NAWK) '{print $$6}')
export LINK_VER
endif
CC_MAJORVER :=$(call MajorVersion,$(CC_VER))
ifeq ($(CC_MAJORVER), 13)
# This should be: CC_VER=13.10.3077 LINK_VER=7.10.3077
@ -93,7 +99,10 @@ ifeq ($(PLATFORM), windows)
endif
else
# else ARCH_DATA_MODEL is 64
LINK_VER := $(shell $(LINK) | $(HEAD) -n 1 | $(NAWK) '{print $$6}')
ifndef LINK_VER
LINK_VER := $(shell $(LINK) | $(HEAD) -n 1 | $(NAWK) '{print $$6}')
export LINK_VER
endif
CC_MAJORVER :=$(call MajorVersion,$(CC_VER))
CC_MINORVER :=$(call MinorVersion,$(CC_VER))
CC_MICROVER :=$(call MicroVersion,$(CC_VER))

View File

@ -116,7 +116,6 @@ RC = $(UTILS_COMMAND_PATH)rc
RMDIR = $(UTILS_COMMAND_PATH)rmdir
RPM = $(UTILS_COMMAND_PATH)rpm
RPMBUILD = $(UTILS_COMMAND_PATH)rpmbuild
SCCS = $(UTILS_CCS_BIN_PATH)sccs
SED = $(UTILS_COMMAND_PATH)sed
SH = $(UTILS_COMMAND_PATH)sh
SHOWREV = $(UTILS_USR_BIN_PATH)showrev

View File

@ -113,32 +113,38 @@ _system_drive:=$(call CheckValue,_system_drive,C:)
# UNIXCOMMAND_PATH: path to where the most common Unix commands are.
# NOTE: Must end with / so that it could be empty, allowing PATH usage.
ifdef ALT_UNIXCOMMAND_PATH
xALT_UNIXCOMMAND_PATH :="$(subst \,/,$(ALT_UNIXCOMMAND_PATH))"
fxALT_UNIXCOMMAND_PATH :=$(call FullPath,$(xALT_UNIXCOMMAND_PATH))
UNIXCOMMAND_PATH :=$(call PrefixPath,$(fxALT_UNIXCOMMAND_PATH))
else
ifdef USING_CYGWIN
UNIXCOMMAND_PATH :=$(call PrefixPath,/usr/bin)
ifndef UNIXCOMMAND_PATH
ifdef ALT_UNIXCOMMAND_PATH
xALT_UNIXCOMMAND_PATH :="$(subst \,/,$(ALT_UNIXCOMMAND_PATH))"
fxALT_UNIXCOMMAND_PATH :=$(call FullPath,$(xALT_UNIXCOMMAND_PATH))
UNIXCOMMAND_PATH :=$(call PrefixPath,$(fxALT_UNIXCOMMAND_PATH))
else
ifdef ROOTDIR
xROOTDIR :="$(subst \,/,$(ROOTDIR))"
_rootdir :=$(call FullPath,$(xROOTDIR))
ifdef USING_CYGWIN
UNIXCOMMAND_PATH :=$(call PrefixPath,/usr/bin)
else
xROOTDIR :="$(_system_drive)/mksnt"
_rootdir :=$(call FullPath,$(xROOTDIR))
endif
ifneq ($(_rootdir),)
UNIXCOMMAND_PATH :=$(call PrefixPath,$(_rootdir)/mksnt)
ifdef ROOTDIR
xROOTDIR :="$(subst \,/,$(ROOTDIR))"
_rootdir :=$(call FullPath,$(xROOTDIR))
else
xROOTDIR :="$(_system_drive)/mksnt"
_rootdir :=$(call FullPath,$(xROOTDIR))
endif
ifneq ($(_rootdir),)
UNIXCOMMAND_PATH :=$(call PrefixPath,$(_rootdir)/mksnt)
endif
endif
endif
UNIXCOMMAND_PATH:=$(call AltCheckSpaces,UNIXCOMMAND_PATH)
export UNIXCOMMAND_PATH
endif
UNIXCOMMAND_PATH:=$(call AltCheckSpaces,UNIXCOMMAND_PATH)
# Get version of MKS or CYGWIN
ifdef USING_CYGWIN
_CYGWIN_VER :=$(shell $(UNAME))
CYGWIN_VER :=$(call GetVersion,$(_CYGWIN_VER))
ifndef CYGWIN_VER
_CYGWIN_VER :=$(shell $(UNAME))
CYGWIN_VER :=$(call GetVersion,$(_CYGWIN_VER))
export CYGWIN_VER
endif
else # MKS
_MKS_VER :=$(shell $(MKSINFO) 2>&1 | $(GREP) Release | $(TAIL) -1 | $(SED) -e 's@.*\(Release.*\)@\1@')
MKS_VER :=$(call GetVersion,$(_MKS_VER))
@ -168,235 +174,234 @@ endif # MKS
# 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))
# Program Files directory
ifndef SHORTPROGRAMFILES
ifdef PROGRAMFILES
xPROGRAMFILES :="$(subst \,/,$(PROGRAMFILES))"
else
ifdef WINDIR
xWINDIR :="$(subst \,/,$(WINDIR))"
_system_root :=$(call FullPath,$(xWINDIR))
ifeq ($(ARCH_DATA_MODEL), 32)
xPROGRAMFILES :="$(_system_drive)/Program Files"
else
ifdef windir
xWINDIR :="$(subst \,/,$(windir))"
_system_root :=$(call FullPath,$(xWINDIR))
endif
xPROGRAMFILES :="$(_system_drive)/Program Files (x86)"
endif
endif
endif
_system_root:=$(call CheckValue,_system_root,$(_system_drive)/WINNT)
# Program Files directory
ifdef PROGRAMFILES
xPROGRAMFILES :="$(subst \,/,$(PROGRAMFILES))"
else
ifeq ($(ARCH_DATA_MODEL), 32)
xPROGRAMFILES :="$(_system_drive)/Program Files"
SHORTPROGRAMFILES :=$(call FullPath,$(xPROGRAMFILES))
else
xPROGRAMFILES :="$(_system_drive)/Program Files (x86)"
ifdef PROGRAMW6432
xPROGRAMW6432 :="$(subst \,/,$(PROGRAMW6432))"
else
xPROGRAMW6432 :="$(_system_drive)/Program Files"
endif
SHORTPROGRAMFILES :=$(call FullPath,$(xPROGRAMW6432))
endif
endif
ifeq ($(ARCH_DATA_MODEL), 32)
_program_files :=$(call FullPath,$(xPROGRAMFILES))
else
ifdef PROGRAMW6432
xPROGRAMW6432 :="$(subst \,/,$(PROGRAMW6432))"
else
xPROGRAMW6432 :="$(_system_drive)/Program Files"
ifneq ($(word 1,$(SHORTPROGRAMFILES)),$(SHORTPROGRAMFILES))
SHORTPROGRAMFILES :=
endif
_program_files :=$(call FullPath,$(xPROGRAMW6432))
_program_files32 :=$(call FullPath,$(xPROGRAMFILES))
ifneq ($(word 1,$(_program_files32)),$(_program_files32))
_program_files32:=
endif
endif
ifneq ($(word 1,$(_program_files)),$(_program_files))
_program_files:=
export SHORTPROGRAMFILES
endif
# Compilers, SDK, and Visual Studio (MSDEV) [32bit is different from 64bit]
ifeq ($(ARCH_DATA_MODEL), 32)
# Try looking in MSVCDIR or MSVCDir area first (set by vcvars32.bat)
ifdef MSVCDIR
xMSVCDIR :="$(subst \,/,$(MSVCDIR))"
_msvc_dir :=$(call FullPath,$(xMSVCDIR))
else
ifdef MSVCDir
xMSVCDIR :="$(subst \,/,$(MSVCDir))"
_msvc_dir :=$(call FullPath,$(xMSVCDIR))
ifndef SHORTMSVCDIR
# Try looking in MSVCDIR or MSVCDir area first (set by vcvars32.bat)
ifdef MSVCDIR
xMSVCDIR :="$(subst \,/,$(MSVCDIR))"
SHORTMSVCDIR :=$(call FullPath,$(xMSVCDIR))
else
ifneq ($(_program_files),)
xMSVCDIR :="$(_program_files)/Microsoft Visual Studio .NET 2003/Vc7"
_msvc_dir :=$(call FullPath,$(xMSVCDIR))
ifdef MSVCDir
xMSVCDIR :="$(subst \,/,$(MSVCDir))"
SHORTMSVCDIR :=$(call FullPath,$(xMSVCDIR))
else
ifneq ($(SHORTPROGRAMFILES),)
xMSVCDIR :="$(SHORTPROGRAMFILES)/Microsoft Visual Studio .NET 2003/Vc7"
SHORTMSVCDIR :=$(call FullPath,$(xMSVCDIR))
endif
endif
endif
endif
ifneq ($(subst MSDev98,OLDOLDOLD,$(_msvc_dir)),$(_msvc_dir))
_msvc_dir :=
endif
# If we still don't have it, look for VS71COMNTOOLS, setup by installer?
ifeq ($(_msvc_dir),)
ifdef VS71COMNTOOLS # /Common/Tools directory, use ../../Vc7
xVS71COMNTOOLS :="$(subst \,/,$(VS71COMNTOOLS))"
_vs71tools :=$(call FullPath,$(xVS71COMNTOOLS))
ifneq ($(subst MSDev98,OLDOLDOLD,$(SHORTMSVCDIR)),$(SHORTMSVCDIR))
SHORTMSVCDIR :=
endif
ifneq ($(_vs71tools),)
_msvc_dir :=$(_vs71tools)/../../Vc7
# If we still don't have it, look for VS71COMNTOOLS, setup by installer?
ifeq ($(SHORTMSVCDIR),)
ifdef VS71COMNTOOLS # /Common/Tools directory, use ../../Vc7
xVS71COMNTOOLS :="$(subst \,/,$(VS71COMNTOOLS))"
_vs71tools :=$(call FullPath,$(xVS71COMNTOOLS))
endif
ifneq ($(_vs71tools),)
SHORTMSVCDIR :=$(_vs71tools)/../../Vc7
endif
endif
export SHORTMSVCDIR
endif
ifneq ($(_msvc_dir),)
_compiler_bin :=$(_msvc_dir)/Bin
_redist_sdk :=$(_msvc_dir)/../SDK/v1.1/Bin
_ms_sdk :=$(_msvc_dir)/PlatformSDK
ifneq ($(SHORTMSVCDIR),)
SHORTCOMPILERBIN :=$(SHORTMSVCDIR)/Bin
SHORTPSDK :=$(SHORTMSVCDIR)/PlatformSDK
export SHORTCOMPILERBIN
export SHORTPSDK
endif
endif
# The Microsoft Platform SDK installed by itself
ifneq ($(_program_files),)
xPSDK :="$(_program_files)/Microsoft Platform SDK"
_psdk :=$(call FullPath,$(xPSDK))
ifeq ($(_psdk),)
xPSDK :="$(_program_files)/Microsoft SDK"
_psdk :=$(call FullPath,$(xMSSDK))
ifneq ($(SHORTPROGRAMFILES),)
ifndef SHORTPSDK
xPSDK :="$(SHORTPROGRAMFILES)/Microsoft Platform SDK"
SHORTPSDK :=$(call FullPath,$(xPSDK))
ifeq ($(SHORTPSDK),)
xPSDK :="$(SHORTPROGRAMFILES)/Microsoft SDK"
SHORTPSDK :=$(call FullPath,$(xMSSDK))
endif
export SHORTPSDK
endif
endif
# If no SDK found yet, look in other places
ifeq ($(_ms_sdk),)
ifndef SHORTPSDK
ifdef MSSDK
xMSSDK :="$(subst \,/,$(MSSDK))"
_ms_sdk :=$(call FullPath,$(xMSSDK))
xMSSDK :="$(subst \,/,$(MSSDK))"
SHORTPSDK :=$(call FullPath,$(xMSSDK))
else
ifdef MSSdk
xMSSDK :="$(subst \,/,$(MSSdk))"
_ms_sdk :=$(call FullPath,$(xMSSDK))
else
_ms_sdk :=$(_psdk)
xMSSDK :="$(subst \,/,$(MSSdk))"
SHORTPSDK :=$(call FullPath,$(xMSSDK))
endif
endif
export SHORTPSDK
endif
# Compilers for 64bit are from SDK
ifeq ($(ARCH_DATA_MODEL), 64)
xMSSDK61 :="C:/Program Files/Microsoft SDKs/Windows/v6.1/"
MSSDK61 :=$(call FullPath,$(xMSSDK61))
xVS2008 :="C:/Program Files (x86)/Microsoft Visual Studio 9.0/"
_vs2008 :=$(call FullPath,$(xVS2008))
ifneq ($(_vs2008),)
ifeq ($(ARCH), ia64)
_compiler_bin :=$(_vs2008)/VC/Bin/x86_ia64
endif
ifeq ($(ARCH), amd64)
_compiler_bin :=$(_vs2008)/VC/Bin/$(ARCH)
_redist_sdk :=$(MSSDK61)/VC/redist
endif
else
ifneq ($(_ms_sdk),)
ifndef SHORTCOMPILERBIN
xMSSDK61 :="C:/Program Files/Microsoft SDKs/Windows/v6.1/"
MSSDK61 :=$(call FullPath,$(xMSSDK61))
xVS2008 :="C:/Program Files (x86)/Microsoft Visual Studio 9.0/"
_vs2008 :=$(call FullPath,$(xVS2008))
ifneq ($(_vs2008),)
ifeq ($(ARCH), ia64)
_compiler_bin :=$(_ms_sdk)/Bin/Win64
SHORTCOMPILERBIN :=$(_vs2008)/VC/Bin/x86_ia64
endif
ifeq ($(ARCH), amd64)
_compiler_bin :=$(_ms_sdk)/Bin/Win64/x86/$(ARCH)
_redist_sdk :=$(_ms_sdk)/redist/win64/AMD64
SHORTCOMPILERBIN :=$(_vs2008)/VC/Bin/$(ARCH)
endif
else
ifneq ($(SHORTPSDK),)
ifeq ($(ARCH), ia64)
SHORTCOMPILERBIN :=$(SHORTPSDK)/Bin/Win64
endif
ifeq ($(ARCH), amd64)
SHORTCOMPILERBIN :=$(SHORTPSDK)/Bin/Win64/x86/$(ARCH)
endif
endif
endif
export SHORTCOMPILERBIN
endif
endif
# Location on system where jdk installs might be
ifneq ($(_program_files),)
USRJDKINSTANCES_PATH =$(_program_files)/Java
ifneq ($(SHORTPROGRAMFILES),)
USRJDKINSTANCES_PATH =$(SHORTPROGRAMFILES)/Java
else
USRJDKINSTANCES_PATH =$(_system_drive)/
endif
# SLASH_JAVA: location of all network accessable files
ifdef ALT_SLASH_JAVA
xALT_SLASH_JAVA :="$(subst \,/,$(ALT_SLASH_JAVA))"
SLASH_JAVA :=$(call FullPath,$(xALT_SLASH_JAVA))
else
ifdef ALT_JDK_JAVA_DRIVE
SLASH_JAVA =$(JDK_JAVA_DRIVE)
ifndef SLASH_JAVA
ifdef ALT_SLASH_JAVA
xALT_SLASH_JAVA :="$(subst \,/,$(ALT_SLASH_JAVA))"
SLASH_JAVA :=$(call FullPath,$(xALT_SLASH_JAVA))
else
SLASH_JAVA =J:
ifdef ALT_JDK_JAVA_DRIVE
SLASH_JAVA =$(JDK_JAVA_DRIVE)
else
SLASH_JAVA =J:
endif
endif
SLASH_JAVA:=$(call AltCheckSpaces,SLASH_JAVA)
SLASH_JAVA:=$(call AltCheckValue,SLASH_JAVA)
export SLASH_JAVA
endif
SLASH_JAVA:=$(call AltCheckSpaces,SLASH_JAVA)
SLASH_JAVA:=$(call AltCheckValue,SLASH_JAVA)
# JDK_DEVTOOLS_DIR: common path for all the java devtools
ifdef ALT_JDK_DEVTOOLS_DIR
xALT_JDK_DEVTOOLS_DIR :="$(subst \,/,$(ALT_JDK_DEVTOOLS_DIR))"
JDK_DEVTOOLS_DIR :=$(call FullPath,$(xALT_JDK_DEVTOOLS_DIR))
else
JDK_DEVTOOLS_DIR =$(SLASH_JAVA)/devtools
ifndef JDK_DEVTOOLS_DIR
ifdef ALT_JDK_DEVTOOLS_DIR
xALT_JDK_DEVTOOLS_DIR :="$(subst \,/,$(ALT_JDK_DEVTOOLS_DIR))"
JDK_DEVTOOLS_DIR :=$(call FullPath,$(xALT_JDK_DEVTOOLS_DIR))
else
JDK_DEVTOOLS_DIR =$(SLASH_JAVA)/devtools
endif
JDK_DEVTOOLS_DIR:=$(call AltCheckSpaces,JDK_DEVTOOLS_DIR)
JDK_DEVTOOLS_DIR:=$(call AltCheckValue,JDK_DEVTOOLS_DIR)
export JDK_DEVTOOLS_DIR
endif
JDK_DEVTOOLS_DIR:=$(call AltCheckSpaces,JDK_DEVTOOLS_DIR)
JDK_DEVTOOLS_DIR:=$(call AltCheckValue,JDK_DEVTOOLS_DIR)
# COMPILER_PATH: path to where the compiler and tools are installed.
# NOTE: Must end with / so that it could be empty, allowing PATH usage.
ifdef ALT_COMPILER_PATH
xALT_COMPILER_PATH :="$(subst \,/,$(ALT_COMPILER_PATH))"
fxALT_COMPILER_PATH :=$(call FullPath,$(xALT_COMPILER_PATH))
COMPILER_PATH :=$(call PrefixPath,$(fxALT_COMPILER_PATH))
else
COMPILER_PATH :=$(call PrefixPath,$(_compiler_bin))
ifndef COMPILER_PATH
ifdef ALT_COMPILER_PATH
xALT_COMPILER_PATH :="$(subst \,/,$(ALT_COMPILER_PATH))"
fxALT_COMPILER_PATH :=$(call FullPath,$(xALT_COMPILER_PATH))
COMPILER_PATH :=$(call PrefixPath,$(fxALT_COMPILER_PATH))
else
COMPILER_PATH :=$(call PrefixPath,$(SHORTCOMPILERBIN))
endif
COMPILER_PATH :=$(call AltCheckSpaces,COMPILER_PATH)
export COMPILER_PATH
endif
COMPILER_PATH :=$(call AltCheckSpaces,COMPILER_PATH)
# MSDEVTOOLS_PATH: path to where the additional MS Compiler tools are.
# NOTE: Must end with / so that it could be empty, allowing PATH usage.
ifdef ALT_MSDEVTOOLS_PATH
xALT_MSDEVTOOLS_PATH :="$(subst \,/,$(ALT_MSDEVTOOLS_PATH))"
fxALT_MSDEVTOOLS_PATH :=$(call FullPath,$(xALT_MSDEVTOOLS_PATH))
MSDEVTOOLS_PATH :=$(call PrefixPath,$(fxALT_MSDEVTOOLS_PATH))
else
ifeq ($(ARCH_DATA_MODEL), 64)
ifdef MSTOOLS
xMSTOOLS :="$(subst \,/,$(MSTOOLS))"
_ms_tools :=$(call FullPath,$(xMSTOOLS))
else
ifdef Mstools
xMSTOOLS :="$(subst \,/,$(Mstools))"
ifndef MSDEVTOOLS_PATH
ifdef ALT_MSDEVTOOLS_PATH
xALT_MSDEVTOOLS_PATH :="$(subst \,/,$(ALT_MSDEVTOOLS_PATH))"
fxALT_MSDEVTOOLS_PATH :=$(call FullPath,$(xALT_MSDEVTOOLS_PATH))
MSDEVTOOLS_PATH :=$(call PrefixPath,$(fxALT_MSDEVTOOLS_PATH))
else
ifeq ($(ARCH_DATA_MODEL), 64)
ifdef MSTOOLS
xMSTOOLS :="$(subst \,/,$(MSTOOLS))"
_ms_tools :=$(call FullPath,$(xMSTOOLS))
else
_ms_tools :=
ifdef Mstools
xMSTOOLS :="$(subst \,/,$(Mstools))"
_ms_tools :=$(call FullPath,$(xMSTOOLS))
else
_ms_tools :=
endif
endif
ifneq ($(_ms_tools),)
_ms_tools_bin :=$(_ms_tools)/Bin
else
# Assumes compiler bin is .../Bin/win64/x86/AMD64, rc.exe is 3 levels up
_ms_tools_bin :=$(SHORTCOMPILERBIN)/../../..
endif
endif
ifneq ($(_ms_tools),)
_ms_tools_bin :=$(_ms_tools)/Bin
else
# Assumes compiler bin is .../Bin/win64/x86/AMD64, rc.exe is 3 levels up
_ms_tools_bin :=$(_compiler_bin)/../../..
_ms_tools_bin :=$(SHORTCOMPILERBIN)
endif
else
_ms_tools_bin :=$(_compiler_bin)
MSDEVTOOLS_PATH :=$(call PrefixPath,$(_ms_tools_bin))
endif
MSDEVTOOLS_PATH :=$(call PrefixPath,$(_ms_tools_bin))
MSDEVTOOLS_PATH:=$(call AltCheckSpaces,MSDEVTOOLS_PATH)
export MSDEVTOOLS_PATH
endif
MSDEVTOOLS_PATH:=$(call AltCheckSpaces,MSDEVTOOLS_PATH)
# 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.
ifdef ALT_DEVTOOLS_PATH
xALT_DEVTOOLS_PATH :="$(subst \,/,$(ALT_DEVTOOLS_PATH))"
fxALT_DEVTOOLS_PATH :=$(call FullPath,$(xALT_DEVTOOLS_PATH))
DEVTOOLS_PATH :=$(call PrefixPath,$(fxALT_DEVTOOLS_PATH))
else
ifdef USING_CYGWIN
DEVTOOLS_PATH :=$(UNIXCOMMAND_PATH)
ifndef DEVTOOLS_PATH
ifdef ALT_DEVTOOLS_PATH
xALT_DEVTOOLS_PATH :="$(subst \,/,$(ALT_DEVTOOLS_PATH))"
fxALT_DEVTOOLS_PATH :=$(call FullPath,$(xALT_DEVTOOLS_PATH))
DEVTOOLS_PATH :=$(call PrefixPath,$(fxALT_DEVTOOLS_PATH))
else
xDEVTOOLS_PATH :="$(_system_drive)/utils"
fxDEVTOOLS_PATH :=$(call FullPath,$(xDEVTOOLS_PATH))
DEVTOOLS_PATH :=$(call PrefixPath,$(fxDEVTOOLS_PATH))
ifdef USING_CYGWIN
DEVTOOLS_PATH :=$(UNIXCOMMAND_PATH)
else
xDEVTOOLS_PATH :="$(_system_drive)/utils"
fxDEVTOOLS_PATH :=$(call FullPath,$(xDEVTOOLS_PATH))
DEVTOOLS_PATH :=$(call PrefixPath,$(fxDEVTOOLS_PATH))
endif
endif
DEVTOOLS_PATH:=$(call AltCheckSpaces,DEVTOOLS_PATH)
export DEVTOOLS_PATH
endif
DEVTOOLS_PATH:=$(call AltCheckSpaces,DEVTOOLS_PATH)
# _BOOTDIR1: First choice for a Bootstrap JDK, previous released JDK.
# _BOOTDIR2: Second choice
@ -410,20 +415,26 @@ endif
# BUILD_JDK_IMPORT_PATH: location of JDK install trees to import for
# multiple platforms, e.g. windows-i586, solaris-sparc, linux-586, etc.
ifdef ALT_BUILD_JDK_IMPORT_PATH
BUILD_JDK_IMPORT_PATH :=$(call FullPath,$(ALT_BUILD_JDK_IMPORT_PATH))
else
BUILD_JDK_IMPORT_PATH = $(PROMOTED_BUILD_BINARIES)
ifndef BUILD_JDK_IMPORT_PATH
ifdef ALT_BUILD_JDK_IMPORT_PATH
BUILD_JDK_IMPORT_PATH :=$(call FullPath,$(ALT_BUILD_JDK_IMPORT_PATH))
else
BUILD_JDK_IMPORT_PATH = $(PROMOTED_BUILD_BINARIES)
endif
BUILD_JDK_IMPORT_PATH:=$(call AltCheckSpaces,BUILD_JDK_IMPORT_PATH)
BUILD_JDK_IMPORT_PATH:=$(call AltCheckValue,BUILD_JDK_IMPORT_PATH)
export BUILD_JDK_IMPORT_PATH
endif
BUILD_JDK_IMPORT_PATH:=$(call AltCheckSpaces,BUILD_JDK_IMPORT_PATH)
BUILD_JDK_IMPORT_PATH:=$(call AltCheckValue,BUILD_JDK_IMPORT_PATH)
# JDK_IMPORT_PATH: location of previously built JDK (this version) to import
ifdef ALT_JDK_IMPORT_PATH
JDK_IMPORT_PATH :=$(call FullPath,$(ALT_JDK_IMPORT_PATH))
else
JDK_IMPORT_PATH = $(BUILD_JDK_IMPORT_PATH)/$(PLATFORM)-$(ARCH)$(_JDK_IMPORT_VARIANT)
ifndef JDK_IMPORT_PATH
ifdef ALT_JDK_IMPORT_PATH
JDK_IMPORT_PATH :=$(call FullPath,$(ALT_JDK_IMPORT_PATH))
else
JDK_IMPORT_PATH = $(BUILD_JDK_IMPORT_PATH)/$(PLATFORM)-$(ARCH)$(_JDK_IMPORT_VARIANT)
endif
JDK_IMPORT_PATH:=$(call AltCheckSpaces,JDK_IMPORT_PATH)
JDK_IMPORT_PATH:=$(call AltCheckValue,JDK_IMPORT_PATH)
export JDK_IMPORT_PATH
endif
JDK_IMPORT_PATH:=$(call AltCheckSpaces,JDK_IMPORT_PATH)
JDK_IMPORT_PATH:=$(call AltCheckValue,JDK_IMPORT_PATH)

View File

@ -228,12 +228,15 @@ else
endif
# FULL_VERSION is RELEASE and -BUILD_NUMBER if BUILD_NUMBER is set
ifdef BUILD_NUMBER
FULL_VERSION = $(RELEASE)-$(BUILD_NUMBER)
else
BUILD_NUMBER = b00
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)
ifndef FULL_VERSION
ifdef BUILD_NUMBER
FULL_VERSION = $(RELEASE)-$(BUILD_NUMBER)
else
BUILD_NUMBER = b00
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)
endif
export FULL_VERSION
endif
# Promoted build location

View File

@ -84,21 +84,14 @@ PLATFORM_SHARED=done
# REQUIRED_LINUX_VER linux only: required version of linux
# REQUIRED_LINUX_FULLVER linux only: required full version of linux
SYSTEM_UNAME := $(shell uname)
ifndef SYSTEM_UNAME
SYSTEM_UNAME := $(shell uname)
export SYSTEM_UNAME
endif
# Normal boot jdk is previous release, but a hard requirement is a 1.5 boot
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
ifndef VARIANT
VARIANT=OPT
@ -372,14 +365,17 @@ ifeq ($(PLATFORM), windows)
REQUIRED_FREE_SPACE=500000
OS_VENDOR = Microsoft
# How much RAM does this machine have:
MB_OF_MEMORY := $(shell \
if [ -f "C:/cygwin/bin/free.exe" ] ; then \
( C:/cygwin/bin/bash.exe -c "C:/cygwin/bin/free.exe -m" ) | \
grep Mem: | \
sed -e 's@\ \ *@ @g' | cut -d' ' -f2 ; \
else \
echo "512"; \
fi)
ifndef MB_OF_MEMORY
MB_OF_MEMORY := $(shell \
if [ -f "C:/cygwin/bin/free.exe" ] ; then \
( C:/cygwin/bin/bash.exe -c "C:/cygwin/bin/free.exe -m" ) | \
grep Mem: | \
sed -e 's@\ \ *@ @g' | cut -d' ' -f2 ; \
else \
echo "512"; \
fi)
export MB_OF_MEMORY
endif
endif
# Machines with 512Mb or less of real memory are considered low memory
@ -387,30 +383,36 @@ endif
# system swapping during the build.
# If we don't know, assume 512. Subtract 128 from MB for VM MAX.
# Don't set VM max over 1024-128=896.
ifneq ($(MB_OF_MEMORY),)
LOW_MEMORY_MACHINE := $(shell \
if [ $(MB_OF_MEMORY) -le 512 ] ; then \
echo "true"; \
else \
echo "false"; \
fi)
MAX_VM_MEMORY := $(shell \
if [ $(MB_OF_MEMORY) -le 1024 ] ; then \
expr $(MB_OF_MEMORY) '-' 128 ; \
else \
echo "896"; \
fi)
MIN_VM_MEMORY := $(shell \
if [ $(MAX_VM_MEMORY) -le 128 ] ; then \
expr $(MAX_VM_MEMORY) '-' 8 ; \
else \
echo "128"; \
fi)
else
MB_OF_MEMORY := unknown
LOW_MEMORY_MACHINE := true
MAX_VM_MEMORY := 384
MIN_VM_MEMORY := 128
ifndef MAX_VM_MEMORY
ifneq ($(MB_OF_MEMORY),)
LOW_MEMORY_MACHINE := $(shell \
if [ $(MB_OF_MEMORY) -le 512 ] ; then \
echo "true"; \
else \
echo "false"; \
fi)
MAX_VM_MEMORY := $(shell \
if [ $(MB_OF_MEMORY) -le 1024 ] ; then \
expr $(MB_OF_MEMORY) '-' 128 ; \
else \
echo "896"; \
fi)
MIN_VM_MEMORY := $(shell \
if [ $(MAX_VM_MEMORY) -le 128 ] ; then \
expr $(MAX_VM_MEMORY) '-' 8 ; \
else \
echo "128"; \
fi)
else
MB_OF_MEMORY := unknown
LOW_MEMORY_MACHINE := true
MAX_VM_MEMORY := 384
MIN_VM_MEMORY := 128
endif
export MAX_VM_MEMORY
export MIN_VM_MEMORY
export LOW_MEMORY_MACHINE
export MAX_VM_MEMORY
endif
REQUIRED_ZIP_VER = 2.2

View File

@ -34,8 +34,8 @@ solaris_i586_5.10,\
solaris_x64_5.10,\
linux_i586_2.6,\
linux_x64_2.6,\
windows_i586,\
windows_x64
windows_i586_5.0,\
windows_x64_5.2
# The different build flavors we want
jprt.build.flavors=product,fastdebug

View File

@ -45,3 +45,6 @@ ba313800759b678979434d6da8ed3bf49eb8bea4 jdk7-b65
d07e68298d4e17ebf93d8299e43fcc3ded26472a jdk7-b68
54fd4d9232969ea6cd3d236e5ad276183bb0d423 jdk7-b69
0632c3e615a315ff11e2ab1d64f4d82ff9853461 jdk7-b70
50a95aa4a247f0cbbf66df285a8b1d78ffb153d9 jdk7-b71
a94714c550658fd6741793ef036cb9625dc2ab1a jdk7-b72
faf94d94786b621f8e13cbcc941ca69c6d967c3f jdk7-b73

View File

@ -1,6 +1,6 @@
#!/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.
#
# This code is free software; you can redistribute it and/or modify it

View File

@ -1,6 +1,6 @@
#!/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.
#
# 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.
#
# 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.
#
# 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 {
private static AddressField heapField;
private static AddressField scavengeRootNMethodsField;
private static VirtualConstructor virtualConstructor;
private CodeHeap heap;
@ -49,6 +50,7 @@ public class CodeCache {
Type type = db.lookupType("CodeCache");
heapField = type.getAddressField("_heap");
scavengeRootNMethodsField = type.getAddressField("_scavenge_root_nmethods");
virtualConstructor = new VirtualConstructor(db);
// Add mappings for all possible CodeBlob subclasses
@ -67,6 +69,10 @@ public class CodeCache {
heap = (CodeHeap) VMObjectFactory.newObject(CodeHeap.class, heapField.getValue());
}
public NMethod scavengeRootMethods() {
return (NMethod) VMObjectFactory.newObject(NMethod.class, scavengeRootNMethodsField.getValue());
}
public boolean contains(Address 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 */
private static CIntegerField entryBCIField;
/** 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 */
private static CIntegerField exceptionOffsetField;
private static CIntegerField deoptOffsetField;
@ -87,7 +90,10 @@ public class NMethod extends CodeBlob {
zombieInstructionSizeField = type.getCIntegerField("_zombie_instruction_size");
methodField = type.getOopField("_method");
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");
deoptOffsetField = type.getCIntegerField("_deoptimize_offset");
origPCOffsetField = type.getCIntegerField("_orig_pc_offset");
@ -219,10 +225,19 @@ public class NMethod extends CodeBlob {
return getEntryBCI();
}
public NMethod getLink() {
return (NMethod) VMObjectFactory.newObject(NMethod.class, linkField.getValue(addr));
public NMethod getOSRLink() {
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
deoptimized. Note: native wrappers cannot be deoptimized. */
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.
*
* 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.
*
* 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_MINOR_VER=0
HS_BUILD_NUMBER=01
HS_BUILD_NUMBER=03
JDK_MAJOR_VER=1
JDK_MINOR_VER=7

View File

@ -4676,3 +4676,50 @@ void MacroAssembler::reinit_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(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
};

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
// but not necessarily exactly of type default_type.
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);
if (basic_type != T_OBJECT) {
__ cmp(tmp, tmp2);
@ -2429,7 +2429,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
assert(data->is_BitData(), "need BitData for checkcast");
Register mdo = k_RInfo;
Register data_val = Rtmp1;
jobject2reg(md->encoding(), mdo);
jobject2reg(md->constant_encoding(), mdo);
int mdo_offset_bias = 0;
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,
// so let's do it before loading the class
if (k->is_loaded()) {
jobject2reg(k->encoding(), k_RInfo);
jobject2reg(k->constant_encoding(), k_RInfo);
} else {
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,
// so let's do it before loading the class
if (k->is_loaded()) {
jobject2reg(k->encoding(), k_RInfo);
jobject2reg(k->constant_encoding(), k_RInfo);
} else {
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");
Register mdo = op->mdo()->as_register();
Register tmp1 = op->tmp1()->as_register();
jobject2reg(md->encoding(), mdo);
jobject2reg(md->constant_encoding(), mdo);
int mdo_offset_bias = 0;
if (!Assembler::is_simm13(md->byte_offset_of_slot(data, CounterData::count_offset()) +
data->size_in_bytes())) {
@ -2774,7 +2774,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
if (receiver == NULL) {
Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)) -
mdo_offset_bias);
jobject2reg(known_klass->encoding(), tmp1);
jobject2reg(known_klass->constant_encoding(), tmp1);
__ st_ptr(tmp1, recv_addr);
Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)) -
mdo_offset_bias);

View File

@ -668,7 +668,7 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
__ add(obj.result(), offset.result(), addr);
if (type == objectType) { // Write-barrier needed for Object fields.
pre_barrier(obj.result(), false, NULL);
pre_barrier(addr, false, NULL);
}
if (type == objectType)
@ -896,7 +896,7 @@ void LIRGenerator::do_NewTypeArray(NewTypeArray* x) {
LIR_Opr len = length.result();
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);
__ 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;
MacroAssembler _masm(&cbuf);
Register str1_reg = reg_to_register_object($str1$$reg);
Register str2_reg = reg_to_register_object($str2$$reg);
Register tmp1_reg = reg_to_register_object($tmp1$$reg);
Register tmp2_reg = reg_to_register_object($tmp2$$reg);
Register cnt1_reg = reg_to_register_object($cnt1$$reg);
Register cnt2_reg = reg_to_register_object($cnt2$$reg);
Register result_reg = reg_to_register_object($result$$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();
// 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);
assert(result_reg != str1_reg &&
result_reg != str2_reg &&
result_reg != cnt1_reg &&
result_reg != cnt2_reg ,
"need different registers");
// Compute the minimum of the string lengths(str1_reg) and the
// 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.
// Stash diff in O7 in case we need it for a tie-breaker.
Label Lskip;
// __ subcc(str1_reg, str2_reg, O7); // hoisted
__ sll(str1_reg, exact_log2(sizeof(jchar)), str1_reg); // scale the limit
__ subcc(cnt1_reg, cnt2_reg, O7);
__ sll(cnt1_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit
__ br(Assembler::greater, true, Assembler::pt, Lskip);
// str2 is shorter, so use its count:
__ delayed()->sll(str2_reg, exact_log2(sizeof(jchar)), str1_reg); // scale the limit
// cnt2 is shorter, so use its count:
__ delayed()->sll(cnt2_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit
__ 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
Register limit_reg = str1_reg;
Register chr2_reg = str2_reg;
Register limit_reg = cnt1_reg;
Register chr2_reg = cnt2_reg;
Register chr1_reg = result_reg;
// tmp{12} are the base pointers
// str{12} are the base pointers
// Is the minimum length zero?
__ 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
// Load first characters
__ lduh(tmp1_reg, 0, chr1_reg);
__ lduh(tmp2_reg, 0, chr2_reg);
__ lduh(str1_reg, 0, chr1_reg);
__ lduh(str2_reg, 0, chr2_reg);
// Compare first characters
__ 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
Label LSkip2;
// 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);
__ 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);
__ delayed()->mov(O7, result_reg); // result is difference in lengths
// Shift tmp1_reg and tmp2_reg to the end of the arrays, negate limit
__ add(tmp1_reg, limit_reg, tmp1_reg);
__ add(tmp2_reg, limit_reg, tmp2_reg);
// Shift str1_reg and str2_reg to the end of the arrays, negate limit
__ add(str1_reg, limit_reg, str1_reg);
__ add(str2_reg, limit_reg, str2_reg);
__ neg(chr1_reg, limit_reg); // limit = -(limit-2)
// Compare the rest of the characters
__ lduh(tmp1_reg, limit_reg, chr1_reg);
__ lduh(str1_reg, limit_reg, chr1_reg);
__ bind(Lloop);
// __ lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted
__ lduh(tmp2_reg, limit_reg, chr2_reg);
// __ lduh(str1_reg, limit_reg, chr1_reg); // hoisted
__ lduh(str2_reg, limit_reg, chr2_reg);
__ subcc(chr1_reg, chr2_reg, chr1_reg);
__ br(Assembler::notZero, false, Assembler::pt, Ldone);
assert(chr1_reg == result_reg, "result must be pre-placed");
__ delayed()->inccc(limit_reg, sizeof(jchar));
// annul LDUH if branch is not taken to prevent access past end of string
__ 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.
__ mov(O7, result_reg);
@ -2957,125 +2935,80 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
__ bind(Ldone);
%}
enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{
Label Lword, Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone;
enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result) %{
Label Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone;
MacroAssembler _masm(&cbuf);
Register str1_reg = reg_to_register_object($str1$$reg);
Register str2_reg = reg_to_register_object($str2$$reg);
Register tmp1_reg = reg_to_register_object($tmp1$$reg);
Register tmp2_reg = reg_to_register_object($tmp2$$reg);
Register cnt_reg = reg_to_register_object($cnt$$reg);
Register tmp1_reg = O7;
Register result_reg = reg_to_register_object($result$$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();
assert(result_reg != str1_reg &&
result_reg != str2_reg &&
result_reg != cnt_reg &&
result_reg != tmp1_reg ,
"need different registers");
// load str1 (jchar*) base address into tmp1_reg
__ 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 ?
__ cmp(str1_reg, str2_reg); //same char[] ?
__ brx(Assembler::equal, true, Assembler::pn, Ldone);
__ 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
Register limit_reg = str1_reg;
Register chr2_reg = str2_reg;
Register limit_reg = cnt_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
__ or3(tmp1_reg, tmp2_reg, chr1_reg);
__ andcc(chr1_reg, 0x3, chr1_reg); // notZero means at least one not 4-byte aligned
__ br(Assembler::notZero, false, Assembler::pn, Lchar);
__ delayed()->nop();
__ or3(str1_reg, str2_reg, chr1_reg);
__ andcc(chr1_reg, 0x3, chr1_reg);
// notZero means at least one not 4-byte aligned.
// 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);
__ and3(limit_reg, 0x2, O7); //remember the remainder (either 0 or 2)
__ andn(limit_reg, 0x3, limit_reg);
__ 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);
// Compare char[] arrays aligned to 4 bytes.
__ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg,
chr1_reg, chr2_reg, Ldone);
__ ba(false,Ldone);
__ delayed()->add(G0, 1, result_reg);
// char by char compare
__ bind(Lchar);
__ add(tmp1_reg, limit_reg, tmp1_reg);
__ add(tmp2_reg, limit_reg, tmp2_reg);
__ add(str1_reg, limit_reg, str1_reg);
__ add(str2_reg, limit_reg, str2_reg);
__ neg(limit_reg); //negate count
__ lduh(tmp1_reg, limit_reg, chr1_reg);
__ lduh(str1_reg, limit_reg, chr1_reg);
// Lchar_loop
__ bind(Lchar_loop);
__ lduh(tmp2_reg, limit_reg, chr2_reg);
__ lduh(str2_reg, limit_reg, chr2_reg);
__ cmp(chr1_reg, chr2_reg);
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
__ delayed()->mov(G0, result_reg); //not equal
__ inccc(limit_reg, sizeof(jchar));
// 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
__ delayed()->lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted
__ br(Assembler::notZero, true, Assembler::pt, Lchar_loop);
__ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted
__ add(G0, 1, result_reg); //equal
__ 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;
MacroAssembler _masm(&cbuf);
Register ary1_reg = reg_to_register_object($ary1$$reg);
Register ary2_reg = reg_to_register_object($ary2$$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);
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);
__ 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
// 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);
// renaming registers
Register chr1_reg = tmp2_reg; // for characters in ary1
Register chr2_reg = result_reg; // for characters in ary2
Register chr1_reg = result_reg; // for characters in ary1
Register chr2_reg = tmp2_reg; // for characters in ary2
Register limit_reg = tmp1_reg; // length
// set byte count
__ 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
__ bind(Ldone);
@ -9471,33 +9375,33 @@ instruct clear_array(iRegX cnt, iRegP base, iRegX temp, Universe dummy, flagsReg
ins_pipe(long_memory_op);
%}
instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result,
o7RegI tmp3, flagsReg ccr) %{
match(Set result (StrComp str1 str2));
effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3);
instruct string_compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
o7RegI tmp, flagsReg ccr) %{
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp);
ins_cost(300);
format %{ "String Compare $str1,$str2 -> $result" %}
ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, result) );
format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %}
ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result) );
ins_pipe(long_memory_op);
%}
instruct string_equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result,
o7RegI tmp3, flagsReg ccr) %{
match(Set result (StrEquals str1 str2));
effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3);
instruct string_equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result,
o7RegI tmp, flagsReg ccr) %{
match(Set result (StrEquals (Binary str1 str2) cnt));
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr);
ins_cost(300);
format %{ "String Equals $str1,$str2 -> $result" %}
ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, result) );
format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %}
ins_encode( enc_String_Equals(str1, str2, cnt, result) );
ins_pipe(long_memory_op);
%}
instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result,
flagsReg ccr) %{
instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result,
o7RegI tmp2, flagsReg ccr) %{
match(Set result (AryEq ary1 ary2));
effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr);
ins_cost(300);
format %{ "Array Equals $ary1,$ary2 -> $result" %}
ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result));
format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1,$tmp2" %}
ins_encode( enc_Array_Equals(ary1, ary2, tmp1, result));
ins_pipe(long_memory_op);
%}

View File

@ -8404,6 +8404,319 @@ void MacroAssembler::reinit_heapbase() {
}
#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) {
switch (cond) {
// 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, 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

View File

@ -1638,7 +1638,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
jobject2reg_with_patching(k_RInfo, op->info_for_patch());
} else {
#ifdef _LP64
__ movoop(k_RInfo, k->encoding());
__ movoop(k_RInfo, k->constant_encoding());
#else
k_RInfo = noreg;
#endif // _LP64
@ -1661,7 +1661,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
assert(data != NULL, "need data for checkcast");
assert(data->is_BitData(), "need BitData for checkcast");
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()));
int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant());
__ orl(data_addr, header_bits);
@ -1679,7 +1679,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
#ifdef _LP64
__ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
#else
__ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->encoding());
__ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding());
#endif // _LP64
} else {
__ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
@ -1696,7 +1696,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
#ifdef _LP64
__ cmpptr(k_RInfo, Address(klass_RInfo, k->super_check_offset()));
#else
__ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->encoding());
__ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->constant_encoding());
#endif // _LP64
if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) {
__ jcc(Assembler::notEqual, *stub->entry());
@ -1707,7 +1707,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
#ifdef _LP64
__ cmpptr(klass_RInfo, k_RInfo);
#else
__ cmpoop(klass_RInfo, k->encoding());
__ cmpoop(klass_RInfo, k->constant_encoding());
#endif // _LP64
__ jcc(Assembler::equal, done);
@ -1715,7 +1715,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
#ifdef _LP64
__ push(k_RInfo);
#else
__ pushoop(k->encoding());
__ pushoop(k->constant_encoding());
#endif // _LP64
__ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
__ pop(klass_RInfo);
@ -1763,7 +1763,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
if (!k->is_loaded()) {
jobject2reg_with_patching(k_RInfo, op->info_for_patch());
} else {
LP64_ONLY(__ movoop(k_RInfo, k->encoding()));
LP64_ONLY(__ movoop(k_RInfo, k->constant_encoding()));
}
assert(obj != k_RInfo, "must be different");
@ -1774,7 +1774,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
// get object class
// not a safepoint as obj null check happens earlier
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;
} else {
__ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes()));
@ -1791,14 +1791,14 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
#ifndef _LP64
if (k->is_loaded()) {
// 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);
if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() == k->super_check_offset()) {
// check for self
__ cmpoop(klass_RInfo, k->encoding());
__ cmpoop(klass_RInfo, k->constant_encoding());
__ jcc(Assembler::equal, one);
__ push(klass_RInfo);
__ pushoop(k->encoding());
__ pushoop(k->constant_encoding());
__ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id)));
__ pop(klass_RInfo);
__ 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
// but not necessarily exactly of type default_type.
Label known_ok, halt;
__ movoop(tmp, default_type->encoding());
__ movoop(tmp, default_type->constant_encoding());
if (basic_type != T_OBJECT) {
__ cmpptr(tmp, dst_klass_addr);
__ 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(op->mdo()->is_single_cpu(), "mdo must be allocated");
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()));
__ addl(counter_addr, DataLayout::counter_increment);
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);
if (receiver == NULL) {
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)));
__ addl(data_addr, DataLayout::counter_increment);
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.
*
* 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();
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);
__ 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) {
#ifdef ASSERT
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
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() %{
emit_opcode(cbuf,0x5A);
@ -12718,48 +12266,64 @@ instruct rep_stos(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlag
ins_pipe( pipe_slow );
%}
instruct string_compare(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2,
eAXRegI tmp3, eBXRegI tmp4, eCXRegI result, eFlagsReg cr) %{
match(Set result (StrComp str1 str2));
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
//ins_cost(300);
instruct string_compare(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eBXRegI cnt2,
eAXRegI result, regXD tmp1, regXD tmp2, eFlagsReg cr) %{
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
format %{ "String Compare $str1,$str2 -> $result // KILL EAX, EBX" %}
ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1, $tmp2" %}
ins_encode %{
__ string_compare($str1$$Register, $str2$$Register,
$cnt1$$Register, $cnt2$$Register, $result$$Register,
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
// fast string equals
instruct string_equals(eDIRegP str1, eSIRegP str2, regXD tmp1, regXD tmp2,
eBXRegI tmp3, eCXRegI tmp4, eAXRegI result, eFlagsReg cr) %{
match(Set result (StrEquals str1 str2));
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
instruct string_equals(eDIRegP str1, eSIRegP str2, eCXRegI cnt, eAXRegI result,
regXD tmp1, regXD tmp2, eBXRegI tmp3, eFlagsReg cr) %{
match(Set result (StrEquals (Binary str1 str2) cnt));
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" %}
ins_encode( enc_String_Equals(tmp1, tmp2, str1, str2, tmp3, tmp4, result) );
format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
ins_encode %{
__ char_arrays_equals(false, $str1$$Register, $str2$$Register,
$cnt$$Register, $result$$Register, $tmp3$$Register,
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
instruct string_indexof(eSIRegP str1, eDIRegP str2, regXD tmp1, eAXRegI tmp2,
eCXRegI tmp3, eDXRegI tmp4, eBXRegI result, eFlagsReg cr) %{
instruct string_indexof(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
eBXRegI result, regXD tmp1, eCXRegI tmp2, eFlagsReg cr) %{
predicate(UseSSE42Intrinsics);
match(Set result (StrIndexOf str1 str2));
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, KILL tmp2, KILL tmp3, KILL tmp4, KILL cr);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
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" %}
ins_encode( enc_String_IndexOf(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp2, $tmp1" %}
ins_encode %{
__ string_indexof($str1$$Register, $str2$$Register,
$cnt1$$Register, $cnt2$$Register, $result$$Register,
$tmp1$$XMMRegister, $tmp2$$Register);
%}
ins_pipe( pipe_slow );
%}
// fast array equals
instruct array_equals(eDIRegP ary1, eSIRegP ary2, regXD tmp1, regXD tmp2, eBXRegI tmp3,
eDXRegI tmp4, eAXRegI result, eFlagsReg cr) %{
instruct array_equals(eDIRegP ary1, eSIRegP ary2, eAXRegI result,
regXD tmp1, regXD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr)
%{
match(Set result (AryEq ary1 ary2));
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
//ins_cost(300);
format %{ "Array Equals $ary1,$ary2 -> $result // KILL EBX, EDX" %}
ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, tmp4, result) );
format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
ins_encode %{
__ char_arrays_equals(true, $ary1$$Register, $ary2$$Register,
$tmp3$$Register, $result$$Register, $tmp4$$Register,
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}

View File

@ -683,7 +683,7 @@ void emit_d32_reloc(CodeBuffer& cbuf,
#ifdef ASSERT
if (rspec.reloc()->type() == relocInfo::oop_type &&
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
cbuf.relocate(cbuf.inst_mark(), rspec, format);
@ -721,8 +721,8 @@ void emit_d64_reloc(CodeBuffer& cbuf,
#ifdef ASSERT
if (rspec.reloc()->type() == relocInfo::oop_type &&
d64 != 0 && d64 != (int64_t) Universe::non_oop_word()) {
assert(oop(d64)->is_oop() && oop(d64)->is_perm(),
"cannot embed non-perm oops in code");
assert(oop(d64)->is_oop() && (ScavengeRootsInCode || !oop(d64)->is_scavengable()),
"cannot embed scavengable oops in code");
}
#endif
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()
%{
@ -12096,52 +11654,67 @@ instruct rep_stos(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy,
ins_pipe(pipe_slow);
%}
instruct string_compare(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2,
rax_RegI tmp3, rbx_RegI tmp4, rcx_RegI result, rFlagsReg cr)
instruct string_compare(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rbx_RegI cnt2,
rax_RegI result, regD tmp1, regD tmp2, rFlagsReg cr)
%{
match(Set result (StrComp str1 str2));
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
//ins_cost(300);
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
format %{ "String Compare $str1, $str2 -> $result // XXX KILL RAX, RBX" %}
ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1, $tmp2" %}
ins_encode %{
__ string_compare($str1$$Register, $str2$$Register,
$cnt1$$Register, $cnt2$$Register, $result$$Register,
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
instruct string_indexof(rsi_RegP str1, rdi_RegP str2, regD tmp1, rax_RegI tmp2,
rcx_RegI tmp3, rdx_RegI tmp4, rbx_RegI result, rFlagsReg cr)
instruct string_indexof(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
rbx_RegI result, regD tmp1, rcx_RegI tmp2, rFlagsReg cr)
%{
predicate(UseSSE42Intrinsics);
match(Set result (StrIndexOf str1 str2));
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, KILL tmp2, KILL tmp3, KILL tmp4, KILL cr);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
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" %}
ins_encode( enc_String_IndexOf(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1, $tmp2" %}
ins_encode %{
__ string_indexof($str1$$Register, $str2$$Register,
$cnt1$$Register, $cnt2$$Register, $result$$Register,
$tmp1$$XMMRegister, $tmp2$$Register);
%}
ins_pipe( pipe_slow );
%}
// fast string equals
instruct string_equals(rdi_RegP str1, rsi_RegP str2, regD tmp1, regD tmp2, rbx_RegI tmp3,
rcx_RegI tmp4, rax_RegI result, rFlagsReg cr)
instruct string_equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, rax_RegI result,
regD tmp1, regD tmp2, rbx_RegI tmp3, rFlagsReg cr)
%{
match(Set result (StrEquals str1 str2));
effect(TEMP tmp1, TEMP tmp2, USE_KILL str1, USE_KILL str2, KILL tmp3, KILL tmp4, KILL cr);
match(Set result (StrEquals (Binary str1 str2) cnt));
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" %}
ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, tmp3, tmp4, result) );
format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
ins_encode %{
__ char_arrays_equals(false, $str1$$Register, $str2$$Register,
$cnt$$Register, $result$$Register, $tmp3$$Register,
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
// fast array equals
instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, regD tmp1, regD tmp2, rax_RegI tmp3,
rbx_RegI tmp4, rcx_RegI result, rFlagsReg cr)
instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
regD tmp1, regD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
%{
match(Set result (AryEq ary1 ary2));
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
//ins_cost(300);
format %{ "Array Equals $ary1,$ary2 -> $result // KILL RAX, RBX" %}
ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, tmp3, tmp4, result) );
format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
ins_encode %{
__ char_arrays_equals(true, $ary1$$Register, $ary2$$Register,
$tmp3$$Register, $result$$Register, $tmp4$$Register,
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
%}
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.
*
* 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.
*
* 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
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,"StrIndexOf")==0 )) {
// String.(compareTo/equals/indexOf) take 1 control and 4 memory edges.
return 5;
// String.(compareTo/equals/indexOf) and Arrays.equals
// take 1 control and 1 memory edges.
return 2;
}
// 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) {
case T_ARRAY:
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));
}
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.
*
* 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.
*
* 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;
output()->print("<method %s.%s>", m->holder()->name()->as_utf8(), m->name()->as_utf8());
} else {
output()->print("<object 0x%x>", value->encoding());
output()->print("<object 0x%x>", value->constant_encoding());
}
} 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) {
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) {
ciInstanceKlass* klass = type->as_ClassConstant()->value();
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.
*
* 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);
} else {
// 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 not_taken_count_offset = md->byte_offset_of_slot(data, BranchData::not_taken_offset());
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);
__ cmove(lir_cond(cond),
LIR_OprFact::intConst(taken_count_offset),
@ -1071,7 +1071,7 @@ void LIRGenerator::do_Return(Return* x) {
LIR_OprList* args = new LIR_OprList();
args->append(getThreadPointer());
LIR_Opr meth = new_register(T_OBJECT);
__ oop2reg(method()->encoding(), meth);
__ oop2reg(method()->constant_encoding(), meth);
args->append(meth);
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();
args->append(getThreadPointer());
LIR_Opr meth = new_register(T_OBJECT);
__ oop2reg(method()->encoding(), meth);
__ oop2reg(method()->constant_encoding(), meth);
args->append(meth);
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();
args->append(getThreadPointer());
LIR_Opr meth = new_register(T_OBJECT);
__ oop2reg(method()->encoding(), meth);
__ oop2reg(method()->constant_encoding(), meth);
args->append(meth);
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;
if (method()->is_static()) {
obj = new_register(T_OBJECT);
__ oop2reg(method()->holder()->java_mirror()->encoding(), obj);
__ oop2reg(method()->holder()->java_mirror()->constant_encoding(), obj);
} else {
Local* receiver = x->state()->local_at(0)->as_Local();
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);
__ oop2reg(method()->encoding(), meth);
__ oop2reg(method()->constant_encoding(), meth);
LIR_Opr result = increment_and_return_counter(meth, offset, InvocationCounter::count_increment);
__ cmp(lir_cond_aboveEqual, result, LIR_OprFact::intConst(limit));
CodeStub* overflow = new CounterOverflowStub(info, info->bci());

View File

@ -86,7 +86,7 @@ ValueType* ValueType::join(ValueType* y) const {
jobject ObjectType::encoding() const {
assert(is_constant(), "must be");
return constant_value()->encoding();
return constant_value()->constant_encoding();
}
bool ObjectType::is_loaded() const {

View File

@ -257,7 +257,7 @@ ciMethod* ciEnv::get_method_from_handle(jobject method) {
// ------------------------------------------------------------------
// ciEnv::make_array
ciArray* ciEnv::make_array(GrowableArray<ciObject*>* objects) {
ciArray* ciEnv::make_system_array(GrowableArray<ciObject*>* objects) {
VM_ENTRY_MARK;
int length = objects->length();
objArrayOop a = oopFactory::new_system_objArray(length, THREAD);

View File

@ -339,8 +339,8 @@ public:
// but consider adding to vmSymbols.hpp instead.
// Use this to make a holder for non-perm compile time constants.
// The resulting array is guaranteed to satisfy "has_encoding".
ciArray* make_array(GrowableArray<ciObject*>* objects);
// The resulting array is guaranteed to satisfy "can_be_constant".
ciArray* make_system_array(GrowableArray<ciObject*>* objects);
// converts the ciKlass* representing the holder of a method into a
// 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?
MethodLivenessResult ciMethod::liveness_at_bci(int bci) {
MethodLivenessResult ciMethod::raw_liveness_at_bci(int bci) {
check_is_loaded();
if (_liveness == NULL) {
// Create the liveness analyzer.
@ -336,7 +336,17 @@ MethodLivenessResult ciMethod::liveness_at_bci(int bci) {
_liveness = new (arena) MethodLiveness(arena, this);
_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) {
// Keep all locals live for the user's edification and amusement.
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_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);
// Get the interpreters viewpoint on oop liveness. MethodLiveness is

View File

@ -55,6 +55,7 @@ ciObject::ciObject(oop o) {
}
_klass = NULL;
_ident = 0;
init_flags_from(o);
}
// ------------------------------------------------------------------
@ -69,6 +70,7 @@ ciObject::ciObject(Handle h) {
}
_klass = NULL;
_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
// 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
// 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(has_encoding(), "oop must be NULL or perm");
assert(can_be_constant(), "oop must be NULL or perm");
return handle();
}
// ------------------------------------------------------------------
// ciObject::has_encoding
bool ciObject::has_encoding() {
return handle() == NULL || is_perm();
// ciObject::can_be_constant
bool ciObject::can_be_constant() {
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) {
st->print("<%s", type_string());
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_scavengable() ? "SCAVENGABLE" : "",
(address)this);
}

View File

@ -51,9 +51,10 @@ private:
ciKlass* _klass;
uint _ident;
enum { FLAG_BITS = 1};
enum { FLAG_BITS = 2 };
enum {
PERM_FLAG = 1
PERM_FLAG = 1,
SCAVENGABLE_FLAG = 2
};
protected:
ciObject();
@ -68,8 +69,15 @@ protected:
return JNIHandles::resolve_non_null(_handle);
}
void set_perm() {
_ident |= PERM_FLAG;
void init_flags_from(oop x) {
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.
@ -91,17 +99,27 @@ public:
// A hash value for the convenience of compilers.
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
// making other arrangements for dealing with the oop.
// See ciEnv::make_perm_array
bool has_encoding();
// See ciEnv::make_array
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?
// If so, CollectedHeap::can_elide_permanent_oop_store_barriers is relevant.
// If the answer is false, no guarantees are made.
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
// generated code to represent this oop. This address
// 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
// be registered with the oopRecorder.
jobject encoding();
jobject constant_encoding();
// What kind of ciObject is this?
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.
*
* 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());
assert(keyHandle() == new_object->get_oop(), "must be properly recorded");
init_ident_of(new_object);
if (!keyHandle->is_perm()) {
if (!new_object->is_perm()) {
// Not a perm-space object.
insert_non_perm(bucket, keyHandle(), new_object);
return new_object;
}
new_object->set_perm();
if (len != _ci_objects->length()) {
// creating the new object has recursively entered new objects
// 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
add_to_work_list(succ);
}
lp = lp->parent();
assert(lp != NULL, "nested loop must have parent by now");
Loop* plp = lp->parent();
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.

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.
*
* 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(),
&args, CHECK_(empty));
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());
if (TraceMethodHandles) {
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();
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:
if (Atomic::cmpxchg_ptr(boot_method_oop, ik->adr_bootstrap_method(), NULL) == NULL)
ik->set_bootstrap_method(boot_method_oop);

View File

@ -175,6 +175,8 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
OopClosure* keep_alive,
bool unloading_occurred);
virtual void oops_do(OopClosure* f) = 0;
// (All CodeBlob subtypes other than NMethod currently have
// an empty oops_do() method.
// OopMap for frame
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_nmethods_with_dependencies = 0;
bool CodeCache::_needs_cache_clean = false;
nmethod* CodeCache::_scavenge_root_nmethods = NULL;
CodeBlob* CodeCache::first() {
@ -148,10 +149,7 @@ CodeBlob* CodeCache::allocate(int size) {
}
}
verify_if_often();
if (PrintCodeCache2) { // Need to add a new flag
ResourceMark rm;
tty->print_cr("CodeCache allocation: addr: " INTPTR_FORMAT ", size: 0x%x\n", cb, size);
}
print_trace("allocation", cb, size);
return cb;
}
@ -159,10 +157,7 @@ void CodeCache::free(CodeBlob* cb) {
assert_locked_or_safepoint(CodeCache_lock);
verify_if_often();
if (PrintCodeCache2) { // Need to add a new flag
ResourceMark rm;
tty->print_cr("CodeCache free: addr: " INTPTR_FORMAT ", size: 0x%x\n", cb, cb->size());
}
print_trace("free", cb);
if (cb->is_nmethod() && ((nmethod *)cb)->has_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);
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() {
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();
}
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() {
int nmethodCount = 0;
int runtimeStubCount = 0;

View File

@ -45,8 +45,13 @@ class CodeCache : AllStatic {
static int _number_of_blobs;
static int _number_of_nmethods_with_dependencies;
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 mark_scavenge_root_nmethods() PRODUCT_RETURN;
static void verify_perm_nmethods(CodeBlobClosure* f_or_null) PRODUCT_RETURN;
public:
// Initialization
@ -61,6 +66,7 @@ class CodeCache : AllStatic {
static void flush(); // flushes all CodeBlobs
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(CodeBlobClosure* f); // iterates over all CodeBlobs
static void nmethods_do(void f(nmethod* nm)); // iterates over all nmethods
// Lookup
@ -106,12 +112,24 @@ class CodeCache : AllStatic {
static void do_unloading(BoolObjectClosure* is_alive,
OopClosure* keep_alive,
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
static void print() PRODUCT_RETURN; // prints summary
static void print_internals();
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
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);
// 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_bci(bci);
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.
*
* 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);
for (int j = 0; j < stride; j++) {
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;)
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;
_entry_bci = InvocationEntryBci;
_link = NULL;
_osr_link = NULL;
_scavenge_root_link = NULL;
_scavenge_root_state = 0;
_compiler = NULL;
// We have no exception handler or deopt handler make the
// values something that will never match a pc like the nmethod vtable entry
@ -618,7 +621,7 @@ nmethod::nmethod(
_stack_traversal_mark = 0;
code_buffer->copy_oops_to(this);
debug_only(check_store();)
debug_only(verify_scavenge_root_oops());
CodeCache::commit(this);
VTune::create_nmethod(this);
}
@ -668,10 +671,13 @@ nmethod::nmethod(
debug_only(No_Safepoint_Verifier nsv;)
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;
_entry_bci = InvocationEntryBci;
_link = NULL;
_osr_link = NULL;
_scavenge_root_link = NULL;
_scavenge_root_state = 0;
_compiler = NULL;
// We have no exception handler or deopt handler make the
// values something that will never match a pc like the nmethod vtable entry
@ -703,7 +709,7 @@ nmethod::nmethod(
_stack_traversal_mark = 0;
code_buffer->copy_oops_to(this);
debug_only(check_store();)
debug_only(verify_scavenge_root_oops());
CodeCache::commit(this);
VTune::create_nmethod(this);
}
@ -770,12 +776,15 @@ nmethod::nmethod(
debug_only(No_Safepoint_Verifier nsv;)
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;
_compile_id = compile_id;
_comp_level = comp_level;
_entry_bci = entry_bci;
_link = NULL;
_osr_link = NULL;
_scavenge_root_link = NULL;
_scavenge_root_state = 0;
_compiler = compiler;
_orig_pc_offset = orig_pc_offset;
#ifdef HAVE_DTRACE_H
@ -813,7 +822,10 @@ nmethod::nmethod(
code_buffer->copy_oops_to(this);
debug_info->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);
@ -902,23 +914,30 @@ void nmethod::print_on(outputStream* st, const char* title) const {
if (st != NULL) {
ttyLocker ttyl;
// 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(),
is_osr_method() ? '%' :
method() != NULL &&
is_native_method() ? 'n' : ' ',
title);
tlen, title);
#ifdef TIERED
st->print(" (%d) ", comp_level());
#endif // TIERED
if (WizardMode) st->print(" (" INTPTR_FORMAT ")", this);
if (method() != NULL) {
method()->print_short_name(st);
if (Universe::heap()->is_gc_active() && method() != NULL) {
st->print("(method)");
} else if (method() != NULL) {
method()->print_short_name(st);
if (is_osr_method())
st->print(" @ %d", osr_entry_bci());
if (method()->code_size() > 0)
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() {
assert(is_not_entrant(), "must be a non-entrant method");
set_stack_traversal_mark(NMethodSweeper::traversal_count());
@ -1077,7 +1097,8 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
" unloadable], methodOop(" INTPTR_FORMAT
"), cause(" INTPTR_FORMAT ")",
this, (address)_method, (address)cause);
cause->klass()->print();
if (!Universe::heap()->is_gc_active())
cause->klass()->print();
}
// Unlink the osr method, so we do not look this up again
if (is_osr_method()) {
@ -1109,7 +1130,8 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
// The methodOop is gone at this point
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);
}
@ -1295,6 +1317,10 @@ void nmethod::flush() {
ec = next;
}
if (on_scavenge_root_list()) {
CodeCache::drop_scavenge_root_nmethod(this);
}
((CodeBlob*)(this))->flush();
CodeCache::free(this);
@ -1354,7 +1380,10 @@ bool nmethod::can_unload(BoolObjectClosure* is_alive,
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);
return true;
}
@ -1529,13 +1558,12 @@ void nmethod::do_unloading(BoolObjectClosure* is_alive,
// the (strong) marking phase, and then again when walking
// the code cache contents during the weak roots processing
// phase. The two uses are distinguished by means of the
// do_nmethods() method in the closure "f" below -- which
// answers "yes" in the first case, and "no" in the second
// 'do_strong_roots_only' flag, which is true in the first
// case. We want to walk 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
// 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
assert(!is_zombie() && !is_unloaded(),
"should not call follow on zombie or unloaded nmethod");
@ -1553,7 +1581,7 @@ void nmethod::oops_do(OopClosure* f) {
// Compiled code
f->do_oop((oop*) &_method);
if (!f->do_nmethods()) {
if (!do_strong_roots_only) {
// weak roots processing phase -- update ExceptionCache oops
ExceptionCache* ec = exception_cache();
while(ec != NULL) {
@ -1579,12 +1607,108 @@ void nmethod::oops_do(OopClosure* f) {
}
// Scopes
// This includes oop constants not inlined in the code stream.
for (oop* p = oops_begin(); p < oops_end(); p++) {
if (*p == Universe::non_oop_word()) continue; // skip non-oops
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
// called with a frame corresponding to a Java invoke
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
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() {
// 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();
}
@ -1995,19 +2142,34 @@ void nmethod::verify_scopes() {
// Non-product code
#ifndef PRODUCT
void nmethod::check_store() {
// Make sure all oops in the compiled code are tenured
RelocIterator iter(this);
while (iter.next()) {
if (iter.type() == relocInfo::oop_type) {
oop_Relocation* reloc = iter.oop_reloc();
oop obj = reloc->oop_value();
if (obj != NULL && !obj->is_perm()) {
fatal("must be permanent oop in compiled code");
}
class DebugScavengeRoot: public OopClosure {
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(); }
};
void nmethod::verify_scavenge_root_oops() {
if (!on_scavenge_root_list()) {
// Actually look inside, to verify the claim that it's clean.
DebugScavengeRoot debug_scavenge_root(this);
oops_do(&debug_scavenge_root);
if (!debug_scavenge_root.ok())
fatal("found an unadvertised bad non-perm oop in the code cache");
}
assert(scavenge_root_not_marked(), "");
}
#endif // PRODUCT
@ -2040,6 +2202,7 @@ void nmethod::print() const {
if (is_not_entrant()) tty->print("not_entrant ");
if (is_zombie()) tty->print("zombie ");
if (is_unloaded()) tty->print("unloaded ");
if (on_scavenge_root_list()) tty->print("scavenge_root ");
tty->print_cr("}:");
}
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.
*
* This code is free software; you can redistribute it and/or modify it
@ -125,6 +125,7 @@ class xmlStream;
class nmethod : public CodeBlob {
friend class VMStructs;
friend class NMethodSweeper;
friend class CodeCache; // non-perm oops
private:
// Shared fields for all nmethod's
static int _zombie_instruction_size;
@ -132,7 +133,12 @@ class nmethod : public CodeBlob {
methodOop _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
@ -174,6 +180,8 @@ class nmethod : public CodeBlob {
// used by jvmti to track if an unload event has been posted for this nmethod.
bool _unload_reported;
jbyte _scavenge_root_state;
NOT_PRODUCT(bool _has_debug_info; )
// Nmethod Flushing lock (if non-zero, then the nmethod is not removed)
@ -242,7 +250,6 @@ class nmethod : public CodeBlob {
// helper methods
void* operator new(size_t size, int nmethod_size);
void check_store();
const char* reloc_string_for(u_char* begin, u_char* end);
void make_not_entrant_or_zombie(int state);
@ -406,6 +413,24 @@ class nmethod : public CodeBlob {
int version() const { return flags.version; }
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
long stack_traversal_mark() { return _stack_traversal_mark; }
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; }
address osr_entry() const { assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod"); return _osr_entry_point; }
void invalidate_osr_method();
nmethod* link() const { return _link; }
void set_link(nmethod *n) { _link = n; }
nmethod* osr_link() const { return _osr_link; }
void set_osr_link(nmethod *n) { _osr_link = n; }
// tells whether frames described by this nmethod can 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,
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* 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.
*
* 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.
*
* This code is free software; you can redistribute it and/or modify it

View File

@ -47,20 +47,15 @@ class MarkRefsIntoClosure: public OopsInGenClosure {
private:
const MemRegion _span;
CMSBitMap* _bitMap;
const bool _should_do_nmethods;
protected:
DO_OOP_WORK_DEFN
public:
MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap,
bool should_do_nmethods);
MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* 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); }
bool do_header() { return true; }
virtual const bool do_nmethods() const {
return _should_do_nmethods;
}
Prefetch::style prefetch_style() {
return Prefetch::do_read;
}
@ -73,20 +68,16 @@ class MarkRefsIntoVerifyClosure: public OopsInGenClosure {
const MemRegion _span;
CMSBitMap* _verification_bm;
CMSBitMap* _cms_bm;
const bool _should_do_nmethods;
protected:
DO_OOP_WORK_DEFN
public:
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(narrowOop* 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); }
bool do_header() { return true; }
virtual const bool do_nmethods() const {
return _should_do_nmethods;
}
Prefetch::style prefetch_style() {
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(narrowOop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); }
bool do_header() { return true; }
virtual const bool do_nmethods() const { return true; }
Prefetch::style prefetch_style() {
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(narrowOop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); }
bool do_header() { return true; }
virtual const bool do_nmethods() const { return true; }
// When ScanMarkedObjectsAgainClosure is used,
// it passes [Par_]MarkRefsIntoAndScanClosure to oop_oop_iterate(),
// and this delegation is used.

View File

@ -2852,14 +2852,17 @@ void CMSCollector::verify_after_remark_work_1() {
GenCollectedHeap* gch = GenCollectedHeap::heap();
// 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->gen_process_strong_roots(_cmsGen->level(),
true, // younger gens are roots
true, // activate StrongRootsScope
true, // collecting perm gen
SharedHeap::ScanningOption(roots_scanning_options()),
NULL, &notOlder);
&notOlder,
true, // walk code active on stacks
NULL);
// Now mark from the roots
assert(_revisitStack.isEmpty(), "Should be empty");
@ -2901,13 +2904,16 @@ void CMSCollector::verify_after_remark_work_2() {
// Mark from roots one level into CMS
MarkRefsIntoVerifyClosure notOlder(_span, verification_mark_bm(),
markBitMap(), true /* nmethods */);
markBitMap());
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
gch->gen_process_strong_roots(_cmsGen->level(),
true, // younger gens are roots
true, // activate StrongRootsScope
true, // collecting perm gen
SharedHeap::ScanningOption(roots_scanning_options()),
NULL, &notOlder);
&notOlder,
true, // walk code active on stacks
NULL);
// Now mark from the roots
assert(_revisitStack.isEmpty(), "Should be empty");
@ -3484,8 +3490,10 @@ void CMSCollector::checkpointRootsInitialWork(bool asynch) {
FalseClosure falseClosure;
// In the case of a synchronous collection, we will elide the
// remark step, so it's important to catch all the nmethod oops
// in this step; hence the last argument to the constrcutor below.
MarkRefsIntoClosure notOlder(_span, &_markBitMap, !asynch /* nmethods */);
// in this step.
// 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();
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->gen_process_strong_roots(_cmsGen->level(),
true, // younger gens are roots
true, // activate StrongRootsScope
true, // collecting perm gen
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
@ -5040,9 +5051,15 @@ void CMSParRemarkTask::work(int i) {
_timer.start();
gch->gen_process_strong_roots(_collector->_cmsGen->level(),
false, // yg was scanned above
false, // this is parallel code
true, // collecting perm gen
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();
if (PrintCMSStatistics != 0) {
gclog_or_tty->print_cr(
@ -5423,7 +5440,6 @@ void CMSCollector::do_remark_parallel() {
// Set up for parallel process_strong_roots work.
gch->set_par_threads(n_workers);
gch->change_strong_roots_parity();
// 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 verification code as well as subsequent younger_refs_iterate
@ -5454,8 +5470,10 @@ void CMSCollector::do_remark_parallel() {
if (n_workers > 1) {
// Make refs discovery MT-safe
ReferenceProcessorMTMutator mt(ref_processor(), true);
GenCollectedHeap::StrongRootsScope srs(gch);
workers->run_task(&tsk);
} else {
GenCollectedHeap::StrongRootsScope srs(gch);
tsk.work(0);
}
gch->set_par_threads(0); // 0 ==> non-parallel.
@ -5539,11 +5557,18 @@ void CMSCollector::do_remark_non_parallel() {
verify_work_stacks_empty();
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
GenCollectedHeap::StrongRootsScope srs(gch);
gch->gen_process_strong_roots(_cmsGen->level(),
true, // younger gens as roots
false, // use the local StrongRootsScope
true, // collecting perm gen
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();
// 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!
MarkRefsIntoClosure::MarkRefsIntoClosure(
MemRegion span, CMSBitMap* bitMap, bool should_do_nmethods):
MemRegion span, CMSBitMap* bitMap):
_span(span),
_bitMap(bitMap),
_should_do_nmethods(should_do_nmethods)
_bitMap(bitMap)
{
assert(_ref_processor == NULL, "deliberately left NULL");
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.
MarkRefsIntoVerifyClosure::MarkRefsIntoVerifyClosure(
MemRegion span, CMSBitMap* verification_bm, CMSBitMap* cms_bm,
bool should_do_nmethods):
MemRegion span, CMSBitMap* verification_bm, CMSBitMap* cms_bm):
_span(span),
_verification_bm(verification_bm),
_cms_bm(cms_bm),
_should_do_nmethods(should_do_nmethods) {
_cms_bm(cms_bm)
{
assert(_ref_processor == NULL, "deliberately left NULL");
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)
_nextMarkBitMap->clearAll();
PrintReachableClosure prcl(_nextMarkBitMap);
g1h->process_strong_roots(
g1h->process_strong_roots(true, // activate StrongRootsScope
false, // fake perm gen collection
SharedHeap::SO_AllClasses,
&prcl, // Regular roots
NULL, // do not visit active blobs
&prcl // Perm Gen Roots
);
// The root iteration above "consumed" dirty cards in the perm gen.
@ -852,9 +853,11 @@ void ConcurrentMark::checkpointRootsInitial() {
g1h->set_marking_started();
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,
&notOlder, // Regular roots
NULL, // do not visit active blobs
&older // Perm Gen Roots
);
checkpointRootsInitialPost();
@ -1915,7 +1918,7 @@ void ConcurrentMark::checkpointRootsFinalWork() {
g1h->ensure_parsability(false);
if (ParallelGCThreads > 0) {
g1h->change_strong_roots_parity();
G1CollectedHeap::StrongRootsScope srs(g1h);
// this is remark, so we'll use up all available threads
int active_workers = ParallelGCThreads;
set_phase(active_workers, false);
@ -1932,7 +1935,7 @@ void ConcurrentMark::checkpointRootsFinalWork() {
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
guarantee( satb_mq_set.completed_buffers_num() == 0, "invariant" );
} else {
g1h->change_strong_roots_parity();
G1CollectedHeap::StrongRootsScope srs(g1h);
// this is remark, so we'll use up all available threads
int active_workers = 1;
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.
*
* 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 (!silent) { gclog_or_tty->print("roots "); }
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,
&rootsCl,
&blobsCl,
&rootsCl);
rem_set()->invalidate(perm_gen()->used_region(), false);
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);
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,
&eager_scan_code_roots,
&buf_scan_perm);
// Finish up any enqueued closure apps.
buf_scan_non_heap_roots.done();
@ -4078,7 +4087,8 @@ G1CollectedHeap::scan_scan_only_set(OopsInHeapRegionClosure* oc,
void
G1CollectedHeap::g1_process_weak_roots(OopClosure* 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);
change_strong_roots_parity(); // In preparation for parallel strong roots.
rem_set()->prepare_for_younger_refs_iterate(true);
assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty");
double start_par = os::elapsedTime();
if (ParallelGCThreads > 0) {
// The individual threads will set their evac-failure closures.
StrongRootsScope srs(this);
workers()->run_task(&g1_par_task);
} else {
StrongRootsScope srs(this);
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.
*
* 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();
sh->process_strong_roots(true, // Collecting permanent generation.
sh->process_strong_roots(true, // activeate StrongRootsScope
true, // Collecting permanent generation.
SharedHeap::SO_SystemClasses,
&GenMarkSweep::follow_root_closure,
&GenMarkSweep::follow_code_root_closure,
&GenMarkSweep::follow_root_closure);
// Process reference objects found during marking
@ -286,9 +288,11 @@ void G1MarkSweep::mark_sweep_phase3() {
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,
&GenMarkSweep::adjust_root_pointer_closure,
NULL, // do not touch code cache here
&GenMarkSweep::adjust_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 psScavenge.hpp
pcTasks.cpp codeCache.hpp
pcTasks.cpp collectedHeap.hpp
pcTasks.cpp fprofiler.hpp
pcTasks.cpp jniHandles.hpp
@ -392,6 +393,7 @@ pcTasks.hpp gcTaskManager.hpp
pcTasks.hpp psTasks.hpp
psTasks.cpp cardTableExtension.hpp
psTasks.cpp codeCache.hpp
psTasks.cpp fprofiler.hpp
psTasks.cpp gcTaskManager.hpp
psTasks.cpp iterator.hpp

View File

@ -480,12 +480,14 @@ void ParNewGenTask::work(int i) {
par_scan_state.start_strong_roots();
gch->gen_process_strong_roots(_gen->level(),
true, // Process younger gens, if any,
// as strong roots.
false,// not collecting perm generation.
true, // Process younger gens, if any,
// as strong roots.
false, // no scope; this is parallel code
false, // not collecting perm generation.
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();
// "evacuate followers".
@ -799,15 +801,16 @@ void ParNewGeneration::collect(bool full,
ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set);
int n_workers = workers->total_workers();
gch->set_par_threads(n_workers);
gch->change_strong_roots_parity();
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
// 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
// repeatable measurements of the 1-thread overhead of the parallel code.
if (n_workers > 1) {
GenCollectedHeap::StrongRootsScope srs(gch);
workers->run_task(&tsk);
} else {
GenCollectedHeap::StrongRootsScope srs(gch);
tsk.work(0);
}
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);
}
ParallelScavengeHeap::ParStrongRootsScope::ParStrongRootsScope() {
// nothing particular
}
ParallelScavengeHeap::ParStrongRootsScope::~ParStrongRootsScope() {
// nothing particular
}
#ifndef PRODUCT
void ParallelScavengeHeap::record_gen_tops_before_GC() {
if (ZapUnusedHeapArea) {

View File

@ -234,6 +234,13 @@ class ParallelScavengeHeap : public CollectedHeap {
// Mangle the unused parts of all spaces in the heap
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)

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.
*
* 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::gc_thread_compaction_manager(which);
PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
CodeBlobToOopClosure mark_and_push_in_blobs(&mark_and_push_closure, /*do_marking=*/ true);
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)
_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
cm->drain_marking_stacks(&mark_and_push_closure);
@ -78,7 +79,8 @@ void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) {
case threads:
{
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;
@ -106,6 +108,11 @@ void MarkFromRootsTask::do_it(GCTaskManager* manager, uint which) {
vmSymbols::oops_do(&mark_and_push_closure);
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:
fatal("Unknown root type");
}

View File

@ -92,7 +92,8 @@ class MarkFromRootsTask : public GCTask {
jvmti = 7,
system_dictionary = 8,
vm_symbols = 9,
reference_processing = 10
reference_processing = 10,
code_cache = 11
};
private:
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.
*
* 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.
*
* 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");
// General strong roots.
Universe::oops_do(mark_and_push_closure());
ReferenceProcessor::oops_do(mark_and_push_closure());
JNIHandles::oops_do(mark_and_push_closure()); // Global (strong) JNI handles
Threads::oops_do(mark_and_push_closure());
ObjectSynchronizer::oops_do(mark_and_push_closure());
FlatProfiler::oops_do(mark_and_push_closure());
Management::oops_do(mark_and_push_closure());
JvmtiExport::oops_do(mark_and_push_closure());
SystemDictionary::always_strong_oops_do(mark_and_push_closure());
vmSymbols::oops_do(mark_and_push_closure());
{
ParallelScavengeHeap::ParStrongRootsScope psrs;
Universe::oops_do(mark_and_push_closure());
ReferenceProcessor::oops_do(mark_and_push_closure());
JNIHandles::oops_do(mark_and_push_closure()); // Global (strong) JNI handles
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());
FlatProfiler::oops_do(mark_and_push_closure());
Management::oops_do(mark_and_push_closure());
JvmtiExport::oops_do(mark_and_push_closure());
SystemDictionary::always_strong_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.
follow_stack();
@ -617,7 +623,7 @@ void PSMarkSweep::mark_sweep_phase3() {
Universe::oops_do(adjust_root_pointer_closure());
ReferenceProcessor::oops_do(adjust_root_pointer_closure());
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());
FlatProfiler::oops_do(adjust_root_pointer_closure());
Management::oops_do(adjust_root_pointer_closure());
@ -625,6 +631,7 @@ void PSMarkSweep::mark_sweep_phase3() {
// SO_AllClasses
SystemDictionary::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
// 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);
ParallelScavengeHeap::ParStrongRootsScope psrs;
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::jvmti));
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::vm_symbols));
q->enqueue(new MarkFromRootsTask(MarkFromRootsTask::code_cache));
if (parallel_gc_threads > 1) {
for (uint j = 0; j < parallel_gc_threads; j++) {
@ -2408,7 +2410,7 @@ void PSParallelCompact::adjust_roots() {
Universe::oops_do(adjust_root_pointer_closure());
ReferenceProcessor::oops_do(adjust_root_pointer_closure());
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());
FlatProfiler::oops_do(adjust_root_pointer_closure());
Management::oops_do(adjust_root_pointer_closure());

View File

@ -799,8 +799,7 @@ class PSParallelCompact : AllStatic {
FollowRootClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
virtual const bool do_nmethods() const { return true; }
};
};
class FollowStackClosure: public VoidClosure {
private:
@ -817,6 +816,8 @@ class PSParallelCompact : AllStatic {
AdjustPointerClosure(bool is_root) : _is_root(is_root) { }
virtual void do_oop(oop* 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
@ -1063,7 +1064,6 @@ class PSParallelCompact : AllStatic {
MarkAndPushClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
virtual const bool do_nmethods() const { return true; }
};
PSParallelCompact();

View File

@ -358,6 +358,7 @@ bool PSScavenge::invoke_no_policy() {
PSPromotionManager* promotion_manager = PSPromotionManager::vm_thread_promotion_manager();
{
// TraceTime("Roots");
ParallelScavengeHeap::ParStrongRootsScope psrs;
GCTaskQueue* q = GCTaskQueue::create();
@ -376,6 +377,7 @@ bool PSScavenge::invoke_no_policy() {
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::management));
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::system_dictionary));
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::jvmti));
q->enqueue(new ScavengeRootsTask(ScavengeRootsTask::code_cache));
ParallelTaskTerminator terminator(
gc_task_manager()->workers(),

View File

@ -66,7 +66,7 @@ void ScavengeRootsTask::do_it(GCTaskManager* manager, uint which) {
case threads:
{
ResourceMark rm;
Threads::oops_do(&roots_closure);
Threads::oops_do(&roots_closure, NULL);
}
break;
@ -90,6 +90,14 @@ void ScavengeRootsTask::do_it(GCTaskManager* manager, uint which) {
JvmtiExport::oops_do(&roots_closure);
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:
fatal("Unknown root type");
}
@ -107,12 +115,13 @@ void ThreadRootsTask::do_it(GCTaskManager* manager, uint which) {
PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(which);
PSScavengeRootsClosure roots_closure(pm);
CodeBlobToOopClosure roots_in_blobs(&roots_closure, /*do_marking=*/ true);
if (_java_thread != NULL)
_java_thread->oops_do(&roots_closure);
_java_thread->oops_do(&roots_closure, &roots_in_blobs);
if (_vm_thread != NULL)
_vm_thread->oops_do(&roots_closure);
_vm_thread->oops_do(&roots_closure, &roots_in_blobs);
// Do the real work
pm->drain_stacks(false);

View File

@ -54,7 +54,8 @@ class ScavengeRootsTask : public GCTask {
flat_profiler = 5,
system_dictionary = 6,
management = 7,
jvmti = 8
jvmti = 8,
code_cache = 9
};
private:
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.
*
* 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;
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(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.
*
* This code is free software; you can redistribute it and/or modify it
@ -58,14 +58,12 @@ class MarkSweep : AllStatic {
public:
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
virtual const bool do_nmethods() const { return true; }
};
class MarkAndPushClosure: public OopClosure {
public:
virtual void do_oop(oop* 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 void remember_mdo(DataLayout* p) { MarkSweep::revisit_mdo(p); }
};
@ -173,6 +171,7 @@ class MarkSweep : AllStatic {
public:
// Public closures
static FollowRootClosure follow_root_closure;
static CodeBlobToOopClosure follow_code_root_closure; // => follow_root_closure
static MarkAndPushClosure mark_and_push_closure;
static FollowStackClosure follow_stack_closure;
static AdjustPointerClosure adjust_root_pointer_closure;

View File

@ -263,6 +263,14 @@ class CollectedHeap : public CHeapObj {
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
// current heap, with high probability. This predicate
// is not stable, in general.

View File

@ -555,12 +555,14 @@ void DefNewGeneration::collect(bool full,
"save marks have not been newly set.");
gch->gen_process_strong_roots(_level,
true, // Process younger gens, if any, as
// strong roots.
false,// not collecting permanent generation.
true, // Process younger gens, if any,
// as strong roots.
true, // activate StrongRootsScope
false, // not collecting perm generation.
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.do_void();

View File

@ -677,13 +677,23 @@ static AssertIsPermClosure assert_is_perm_closure;
void GenCollectedHeap::
gen_process_strong_roots(int level,
bool younger_gens_as_roots,
bool activate_scope,
bool collecting_perm_gen,
SharedHeap::ScanningOption so,
OopsInGenClosure* older_gens,
OopsInGenClosure* not_older_gens) {
OopsInGenClosure* not_older_gens,
bool do_code_roots,
OopsInGenClosure* older_gens) {
// 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 (!_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,
CodeBlobClosure* code_roots,
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
for (int i = 0; i < _n_gens; i++) {
_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_Symbols_and_Strings" applies the closure to all entries in
// 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,
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
// JNI weak roots, the code cache, system dictionary, symbol table,
// string table, and referents of reachable weak refs.
void gen_process_weak_roots(OopClosure* root_closure,
CodeBlobClosure* code_roots,
OopClosure* non_root_closure);
// 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.
*
* 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,
false, // Younger gens are not roots.
true, // activate StrongRootsScope
true, // Collecting permanent generation.
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
{
@ -338,14 +341,19 @@ void GenMarkSweep::mark_sweep_phase3(int level) {
gch->gen_process_strong_roots(level,
false, // Younger gens are not roots.
true, // activate StrongRootsScope
true, // Collecting permanent generation.
SharedHeap::SO_AllClasses,
&adjust_root_pointer_closure,
false, // do not walk code
&adjust_root_pointer_closure);
// Now adjust pointers in remaining weak roots. (All of which should
// 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,
&adjust_code_pointer_closure,
&adjust_pointer_closure);
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.
*
* 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
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.
*
* 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
class CodeBlob;
class nmethod;
class ReferenceProcessor;
class DataLayout;
@ -69,9 +71,6 @@ class OopClosure : public Closure {
virtual const bool should_remember_mdo() const { return false; }
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
// 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

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.
*
* 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.");
}
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,
OopClosure* roots,
CodeBlobClosure* code_roots,
OopsInGenClosure* perm_blk) {
StrongRootsScope srs(this, activate_scope);
// 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)) {
Universe::oops_do(roots);
ReferenceProcessor::oops_do(roots);
@ -117,9 +132,9 @@ void SharedHeap::process_strong_roots(bool collecting_perm_gen,
JNIHandles::oops_do(roots);
// All threads execute this; the individual threads are task groups.
if (ParallelGCThreads > 0) {
Threads::possibly_parallel_oops_do(roots);
Threads::possibly_parallel_oops_do(roots, code_roots);
} else {
Threads::oops_do(roots);
Threads::oops_do(roots, code_roots);
}
if (!_process_strong_tasks-> is_task_claimed(SH_PS_ObjectSynchronizer_oops_do))
ObjectSynchronizer::oops_do(roots);
@ -156,11 +171,29 @@ void SharedHeap::process_strong_roots(bool collecting_perm_gen,
}
if (!_process_strong_tasks->is_task_claimed(SH_PS_CodeCache_oops_do)) {
if (so & SO_CodeCache) {
CodeCache::oops_do(roots);
}
if (so & SO_CodeCache) {
// (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
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.
@ -220,11 +253,12 @@ public:
// just skip adjusting any shared entries in the string table.
void SharedHeap::process_weak_roots(OopClosure* root_closure,
CodeBlobClosure* code_roots,
OopClosure* non_root_closure) {
// Global (weak) JNI handles
JNIHandles::weak_oops_do(&always_true, root_closure);
CodeCache::oops_do(non_root_closure);
CodeCache::blobs_do(code_roots);
SymbolTable::oops_do(root_closure);
if (UseSharedSpaces && !DumpSharedSpaces) {
SkipAdjustingSharedStrings skip_closure(root_closure);

View File

@ -165,9 +165,21 @@ public:
// c) to never return a distinguished value (zero) with which such
// task-claiming variables may be initialized, to indicate "never
// claimed".
private:
void change_strong_roots_parity();
public:
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 {
SO_None = 0x0,
SO_AllClasses = 0x1,
@ -198,15 +210,18 @@ public:
// "SO_Symbols" applies the closure to all entries in SymbolsTable;
// "SO_Strings" applies the closure to all entries in StringTable;
// "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,
OopClosure* roots,
CodeBlobClosure* code_roots,
OopsInGenClosure* perm_blk);
// Apply "blk" to all the weak roots of the system. These include
// JNI weak roots, the code cache, system dictionary, symbol table,
// string table.
void process_weak_roots(OopClosure* root_closure,
CodeBlobClosure* code_roots,
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.
*
* 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