This README file contains build instructions for the
+OpenJDK. Building the source code for the OpenJDK
+requires a certain degree of technical expertise.
+
+
!!!!!!!!!!!!!!! THIS IS A MAJOR RE-WRITE of this document. !!!!!!!!!!!!!
+
+
Some Headlines:
+
+
+
The build is now a "configure && make" style build
+
Any GNU make 3.81 or newer should work, except on Windows where 4.0 or newer
+is recommended.
+
The build should scale, i.e. more processors should cause the build to be
+done in less wall-clock time
+
Nested or recursive make invocations have been significantly reduced,
+as has the total fork/exec or spawning of sub processes during the build
+
Windows MKS usage is no longer supported
+
Windows Visual Studio vsvars*.bat and vcvars*.bat files are run
+automatically
+
Ant is no longer used when building the OpenJDK
+
Use of ALT_* environment variables for configuring the build is no longer
+supported
The OpenJDK sources are maintained with the revision control system
+Mercurial. If you are new to
+Mercurial, please see the Beginner Guides or refer to the Mercurial Book.
+The first few chapters of the book provide an excellent overview of Mercurial,
+what it is and how it works.
Once you have all the repositories, keep in mind that each repository is its
+own independent repository. You can also re-run ./get_source.sh anytime to
+pull over all the latest changesets in all the repositories. This set of
+nested repositories has been given the term "forest" and there are various
+ways to apply the same hg command to each of the repositories. For
+example, the script make/scripts/hgforest.sh can be used to repeat the
+same hg command on every repository, e.g.
+
+
cd YourOpenJDK
+ bash ./make/scripts/hgforest.sh status
+
+
+
+
+
Repositories
+
+
The set of repositories and what they contain:
+
+
+
. (root) contains common configure and makefile logic
+
hotspot contains source code and make files for building the OpenJDK
+Hotspot Virtual Machine
+
langtools contains source code for the OpenJDK javac and language tools
+
jdk contains source code and make files for building the OpenJDK runtime
+libraries and misc files
+
jaxp contains source code for the OpenJDK JAXP functionality
+
jaxws contains source code for the OpenJDK JAX-WS functionality
+
corba contains source code for the OpenJDK Corba functionality
+
nashorn contains source code for the OpenJDK JavaScript implementation
+
+
+
Repository Source Guidelines
+
+
There are some very basic guidelines:
+
+
+
Use of whitespace in source files (.java, .c, .h, .cpp, and .hpp files) is
+restricted. No TABs, no trailing whitespace on lines, and files should not
+terminate in more than one blank line.
+
Files with execute permissions should not be added to the source
+repositories.
+
All generated files need to be kept isolated from the files maintained or
+managed by the source control system. The standard area for generated files
+is the top level build/ directory.
+
The default build process should be to build the product and nothing else,
+in one form, e.g. a product (optimized), debug (non-optimized, -g plus
+assert logic), or fastdebug (optimized, -g plus assert logic).
+
The .hgignore file in each repository must exist and should include
+^build/, ^dist/ and optionally any nbproject/private directories. It
+should NEVER include anything in the src/ or test/ or any managed
+directory area of a repository.
+
Directory names and file names should never contain blanks or non-printing
+characters.
+
Generated source or binary files should NEVER be added to the repository
+(that includes javah output). There are some exceptions to this rule, in
+particular with some of the generated configure scripts.
+
Files not needed for typical building or testing of the repository should
+not be added to the repository.
+
+
+
+
+
+
+
Building
+
+
The very first step in building the OpenJDK is making sure the system itself
+has everything it needs to do OpenJDK builds. Once a system is setup, it
+generally doesn't need to be done again.
+
+
Building the OpenJDK is now done with running a configure script which will
+try and find and verify you have everything you need, followed by running
+make, e.g.
- This README file contains build instructions for the
- OpenJDK.
- Building the source code for the
- OpenJDK
- requires
- a certain degree of technical expertise.
-
-
-
!!!!!!!!!!!!!!! THIS IS A MAJOR RE-WRITE of this document. !!!!!!!!!!!!!
-
- Some Headlines:
-
-
- The build is now a "configure && make" style build
-
-
- Any GNU make 3.81 or newer should work, except on
- Windows where 4.0 or newer is recommended.
-
-
- The build should scale, i.e. more processors should
- cause the build to be done in less wall-clock time
-
-
- Nested or recursive make invocations have been significantly
- reduced, as has the total fork/exec or spawning
- of sub processes during the build
-
-
- Windows MKS usage is no longer supported
-
-
- Windows Visual Studio vsvars*.bat and
- vcvars*.bat files are run automatically
-
-
- Ant is no longer used when building the OpenJDK
-
-
- Use of ALT_* environment variables for configuring the
- build is no longer supported
-
- The OpenJDK sources are maintained with the revision control system
- Mercurial.
- If you are new to Mercurial, please see the
-
- Beginner Guides
- or refer to the
- Mercurial Book.
- The first few chapters of the book provide an excellent overview of
- Mercurial, what it is and how it works.
-
- For using Mercurial with the OpenJDK refer to the
-
- Developer Guide: Installing and Configuring Mercurial
- section for more information.
-
-
- Once you have all the repositories, keep in mind that each
- repository is its own independent repository.
- You can also re-run ./get_source.sh anytime to
- pull over all the latest changesets in all the repositories.
- This set of nested repositories has been given the term
- "forest" and there are various ways to apply the same
- hg command to each of the repositories.
- For example, the script make/scripts/hgforest.sh
- can be used to repeat the same hg
- command on every repository, e.g.
-
-
- cd YourOpenJDK
-
- bash ./make/scripts/hgforest.sh status
-
-
- Use of whitespace in source files
- (.java, .c, .h, .cpp, and .hpp files)
- is restricted.
- No TABs, no trailing whitespace on lines, and files
- should not terminate in more than one blank line.
-
-
- Files with execute permissions should not be added
- to the source repositories.
-
-
- All generated files need to be kept isolated from
- the files
- maintained or managed by the source control system.
- The standard area for generated files is the top level
- build/ directory.
-
-
- The default build process should be to build the product
- and nothing else, in one form, e.g. a product (optimized),
- debug (non-optimized, -g plus assert logic), or
- fastdebug (optimized, -g plus assert logic).
-
-
- The .hgignore file in each repository
- must exist and should
- include ^build/, ^dist/ and
- optionally any
- nbproject/private directories.
- It should NEVER include
- anything in the
- src/ or test/
- or any managed directory area of a repository.
-
-
- Directory names and file names should never contain
- blanks or
- non-printing characters.
-
-
- Generated source or binary files should NEVER be added to
- the repository (that includes javah output).
- There are some exceptions to this rule, in particular
- with some of the generated configure scripts.
-
-
- Files not needed for typical building
- or testing of the repository
- should not be added to the repository.
-
- The very first step in building the OpenJDK is making sure the
- system itself has everything it needs to do OpenJDK builds.
- Once a system is setup, it generally doesn't need to be done again.
-
- Building the OpenJDK is now done with running a
- configure
- script which will try and find and verify you have everything
- you need, followed by running
- make, e.g.
-
-
-
- bash ./configure
- make all
-
-
-
- Where possible the configure script will attempt to located the
- various components in the default locations or via component
- specific variable settings.
- When the normal defaults fail or components cannot be found,
- additional configure options may be necessary to help configure
- find the necessary tools for the build, or you may need to
- re-visit the setup of your system due to missing software
- packages.
-
- NOTE: The configure script
- file does not have
- execute permissions and will need to be explicitly run with
- bash,
- see the source guidelines.
-
-
-
-
- Before even attempting to use a system to build the OpenJDK
- there are some very basic system setups needed.
- For all systems:
-
-
- Be sure the GNU make utility is version 3.81 (4.0 on
- windows) or newer, e.g. run "make -version"
-
-
- Install a
- Bootstrap JDK.
- All OpenJDK builds require access to a previously released
- JDK called the bootstrap JDK or boot JDK.
- The general rule is that the bootstrap JDK
- must be an instance of the previous major
- release of the JDK. In addition, there may be
- a requirement to use a release at or beyond a
- particular update level.
-
-
- Building JDK 9 requires JDK 8. JDK 9
- developers should not use JDK 9 as the boot
- JDK, to ensure that JDK 9 dependencies are
- not introduced into the parts of the system
- that are built with JDK 8.
-
-
- The JDK 8 binaries can be downloaded from Oracle's
- JDK 8 download site.
- For build performance reasons it
- is very important that this bootstrap JDK be made available
- on the local disk of the machine doing the build.
- You should add its bin directory
- to the PATH environment variable.
- If configure has any issues finding this JDK, you may
- need to use the configure option
- --with-boot-jdk.
-
-
- Ensure that GNU make, the Bootstrap JDK,
- and the compilers are all
- in your PATH environment variable
-
- With Linux, try and favor the system packages over
- building your own
- or getting packages from other areas.
- Most Linux builds should be possible with the system's
- available packages.
-
- Note that some Linux systems have a habit of pre-populating
- your environment variables for you, for example JAVA_HOME
- might get pre-defined for you to refer to the JDK installed on
- your Linux system.
- You will need to unset JAVA_HOME.
- It's a good idea to run env and verify the
- environment variables you are getting from the default system
- settings make sense for building the OpenJDK.
-
-
- At a minimum, the
-
- Studio 12 Update 1 Compilers
- (containing version 5.10 of the C and C++ compilers) is required,
- including specific patches.
-
- The Solaris SPARC patch list is:
-
-
- 118683-05: SunOS 5.10: Patch for profiling libraries and assembler
-
-
- 119963-21: SunOS 5.10: Shared library patch for C++
-
- 141858-06: Sun Studio 12 Update 1_x86: Sun Compiler Common patch for x86 backend
-
-
- 128229-09: Sun Studio 12 Update 1_x86: Patch for C++ Compiler
-
-
- 142363-05: Sun Studio 12 Update 1_x86: Patch for C Compiler
-
-
- 142368-01: Sun Studio 12.1_x86: Patch for Performance Analyzer Tools
-
-
-
- Place the bin directory in PATH.
-
- The Oracle Solaris Studio Express compilers at:
-
- Oracle Solaris Studio Express Download site
- are also an option, although these compilers have not
- been extensively used yet.
-
- Building on Windows requires a Unix-like environment, notably a
- Unix-like shell.
- There are several such environments available of which
- Cygwin and
- MinGW/MSYS are
- currently supported for
- the OpenJDK build. One of the differences of these
- systems from standard Windows tools is the way
- they handle Windows path names, particularly path names which contain
- spaces, backslashes as path separators and possibly drive letters.
- Depending
- on the use case and the specifics of each environment these path
- problems can
- be solved by a combination of quoting whole paths, translating
- backslashes to
- forward slashes, escaping backslashes with additional backslashes and
- translating the path names to their
-
- "8.3" version.
-
-
- CYGWIN is an open source, Linux-like environment which tries to emulate
- a complete POSIX layer on Windows. It tries to be smart about path names
- and can usually handle all kinds of paths if they are correctly quoted
- or escaped although internally it maps drive letters <drive>:
- to a virtual directory /cygdrive/<drive>.
-
- You can always use the cygpath utility to map pathnames with spaces
- or the backslash character into the C:/ style of pathname
- (called 'mixed'), e.g. cygpath -s -m "path".
-
-
- Note that the use of CYGWIN creates a unique problem with regards to
- setting PATH. Normally on Windows
- the PATH variable contains directories
- separated with the ";" character (Solaris and Linux use ":").
- With CYGWIN, it uses ":", but that means that paths like "C:/path"
- cannot be placed in the CYGWIN version of PATH and
- instead CYGWIN uses something like /cygdrive/c/path
- which CYGWIN understands, but only CYGWIN understands.
-
-
- The OpenJDK build requires CYGWIN version 1.7.16 or newer.
- Information about CYGWIN can
- be obtained from the CYGWIN website at
- www.cygwin.com.
-
-
- By default CYGWIN doesn't install all the tools required for building
- the OpenJDK.
- Along with the default installation, you need to install
- the following tools.
-
-
-
-
-
Binary Name
-
Category
-
Package
-
Description
-
-
-
-
-
ar.exe
-
Devel
-
binutils
-
- The GNU assembler, linker and binary utilities
-
-
-
-
make.exe
-
Devel
-
make
-
- The GNU version of the 'make' utility built for CYGWIN
-
-
-
-
m4.exe
-
Interpreters
-
m4
-
- GNU implementation of the traditional Unix macro
- processor
-
-
-
-
cpio.exe
-
Utils
-
cpio
-
- A program to manage archives of files
-
-
-
-
gawk.exe
-
Utils
-
awk
-
- Pattern-directed scanning and processing language
-
-
-
-
file.exe
-
Utils
-
file
-
- Determines file type using 'magic' numbers
-
-
-
-
zip.exe
-
Archive
-
zip
-
- Package and compress (archive) files
-
-
-
-
unzip.exe
-
Archive
-
unzip
-
- Extract compressed files in a ZIP archive
-
-
-
-
free.exe
-
System
-
procps
-
- Display amount of free and used memory in the system
-
-
-
-
-
- Note that the CYGWIN software can conflict with other non-CYGWIN
- software on your Windows system.
- CYGWIN provides a
- FAQ for
- known issues and problems, of particular interest is the
- section on
-
- BLODA (applications that interfere with CYGWIN).
-
- MinGW ("Minimalist GNU for Windows") is a collection of free Windows
- specific header files and import libraries combined with GNU toolsets that
- allow one to produce native Windows programs that do not rely on any
- 3rd-party C runtime DLLs. MSYS is a supplement to MinGW which allows building
- applications and programs which rely on traditional UNIX tools to
- be present. Among others this includes tools like bash
- and make.
- See MinGW/MSYS
- for more information.
-
- Like Cygwin, MinGW/MSYS can handle different types of path formats. They
- are internally converted to paths with forward slashes and drive letters
- <drive>: replaced by a virtual
- directory /<drive>. Additionally, MSYS automatically
- detects binaries compiled for the MSYS environment and feeds them with the
- internal, Unix-style path names. If native Windows applications are called
- from within MSYS programs their path arguments are automatically converted
- back to Windows style path names with drive letters and backslashes as
- path separators. This may cause problems for Windows applications which
- use forward slashes as parameter separator (e.g. cl /nologo /I)
- because MSYS may wrongly
- replace such parameters by drive letters.
-
-
- In addition to the tools which will be installed
- by default, you have
- to manually install the
- msys-zip and
- msys-unzip packages.
- This can be easily done with the MinGW command line installer:
-
- The 32-bit and 64-bit OpenJDK Windows build requires
- Microsoft Visual Studio C++ 2013 (VS2013) Professional
- Edition or Express compiler.
- The compiler and other tools are expected to reside
- in the location defined by the variable
- VS120COMNTOOLS which
- is set by the Microsoft Visual Studio installer.
-
-
- Only the C++ part of VS2013 is needed.
- Try to let the installation go to the default
- install directory.
- Always reboot your system after installing VS2013.
- The system environment variable VS120COMNTOOLS
- should be
- set in your environment.
-
-
- Make sure that TMP and TEMP are also set
- in the environment
- and refer to Windows paths that exist,
- like C:\temp,
- not /tmp, not /cygdrive/c/temp,
- and not C:/temp.
- C:\temp is just an example,
- it is assumed that this area is
- private to the user, so by default
- after installs you should
- see a unique user path in these variables.
-
- The basic invocation of the configure script
- looks like:
-
- bash ./configure [options]
-
- This will create an output directory containing the
- "configuration" and setup an area for the build result.
- This directory typically looks like:
-
- build/linux-x64-normal-server-release
-
- configure will try to figure out what system you are running on
- and where all necessary build components are.
- If you have all prerequisites for building installed,
- it should find everything.
- If it fails to detect any component automatically,
- it will exit and inform you about the problem.
- When this happens, read more below in
- the configure options.
-
- Complete details on all the OpenJDK configure options can
- be seen with:
-
- bash ./configure --help=short
-
- Use -help to see all the configure options
- available.
-
- You can generate any number of different configurations,
- e.g. debug, release, 32, 64, etc.
-
- Some of the more commonly used configure options are:
-
-
-
-
-
OpenJDK Configure Option
-
Description
-
-
-
-
-
--enable-debug
-
- set the debug level to fastdebug (this is a shorthand for
- --with-debug-level=fastdebug)
-
-
-
-
--with-alsa=path
-
- select the location of the
- Advanced Linux Sound Architecture (ALSA)
-
- Version 0.9.1 or newer of the ALSA files are
- required for building the OpenJDK on Linux.
- These Linux files are usually available from an "alsa"
- of "libasound"
- development package,
- and it's highly recommended that you try and use
- the package provided by the particular version of Linux that
- you are using.
-
- provide the JVM options to be used to run the
- Bootstrap JDK
-
-
-
-
--with-cacerts=path
-
- select the path to the cacerts file.
-
- See
- http://en.wikipedia.org/wiki/Certificate_Authority
- for a better understanding of the Certificate Authority (CA).
- A certificates file named "cacerts"
- represents a system-wide keystore with CA certificates.
- In JDK and JRE
- binary bundles, the "cacerts" file contains root CA certificates from
- several public CAs (e.g., VeriSign, Thawte, and Baltimore).
- The source contain a cacerts file
- without CA root certificates.
- Formal JDK builders will need to secure
- permission from each public CA and include the certificates into their
- own custom cacerts file.
- Failure to provide a populated cacerts file
- will result in verification errors of a certificate chain during runtime.
- By default an empty cacerts file is provided and that should be
- fine for most JDK developers.
-
-
-
-
--with-cups=path
-
- select the CUPS install location
-
- The
- Common UNIX Printing System (CUPS) Headers
- are required for building the
- OpenJDK on Solaris and Linux.
- The Solaris header files can be obtained by installing
- the package SFWcups from the Solaris Software
- Companion CD/DVD, these often will be installed into the
- directory /opt/sfw/cups.
-
- The CUPS header files can always be downloaded from
- www.cups.org.
-
-
-
-
--with-cups-include=path
-
- select the CUPS include directory location
-
-
-
-
--with-debug-level=level
-
- select the debug information level of release,
- fastdebug, or slowdebug
-
-
-
-
--with-dev-kit=path
-
- select location of the compiler install or
- developer install location
-
-
-
-
--with-freetype=path
-
- select the freetype files to use.
-
- Expecting the
- freetype libraries under
- lib/ and the
- headers under include/.
-
- Version 2.3 or newer of FreeType is required.
- On Unix systems required files can be available as part of your
- distribution (while you still may need to upgrade them).
- Note that you need development version of package that
- includes both the FreeType library and header files.
-
- You can always download latest FreeType version from the
- FreeType website.
-
- Building the freetype 2 libraries from scratch is also possible,
- however on Windows refer to the
-
- Windows FreeType DLL build instructions.
-
- Note that by default FreeType is built with byte code hinting
- support disabled due to licensing restrictions.
- In this case, text appearance and metrics are expected to
- differ from Sun's official JDK build.
- See
-
- the SourceForge FreeType2 Home Page
-
- for more information.
-
-
-
-
--with-import-hotspot=path
-
- select the location to find hotspot
- binaries from a previous build to avoid building
- hotspot
-
-
-
-
--with-target-bits=arg
-
- select 32 or 64 bit build
-
-
-
-
--with-jvm-variants=variants
-
- select the JVM variants to build from, comma
- separated list that can include:
- server, client, kernel, zero and zeroshark
-
-
-
-
--with-memory-size=size
-
- select the RAM size that GNU make will think
- this system has
-
- select the msvcr100.dll
- file to include in the
- Windows builds (C/C++ runtime library for
- Visual Studio).
-
- This is usually picked up automatically
- from the redist
- directories of Visual Studio 2013.
-
-
-
-
--with-num-cores=cores
-
- select the number of cores to use (processor
- count or CPU count)
-
-
-
-
--with-x=path
-
- select the location of the X11 and xrender files.
-
- The
- XRender Extension Headers
- are required for building the
- OpenJDK on Solaris and Linux.
-
- The Linux header files are usually available from a "Xrender"
- development package, it's recommended that you try and use
- the package provided by the particular distribution of Linux that
- you are using.
-
- The Solaris XRender header files is
- included with the other X11 header files
- in the package SFWxwinc
- on new enough versions of
- Solaris and will be installed in
- /usr/X11/include/X11/extensions/Xrender.h or
- /usr/openwin/share/include/X11/extensions/Xrender.h
-
- The basic invocation of the make utility
- looks like:
-
- make all
-
- This will start the build to the output directory containing the
- "configuration" that was created by the configure
- script. Run make help for more information on
- the available targets.
-
- There are some of the make targets that
- are of general interest:
-
-
-
-
Make Target
-
Description
-
-
-
-
-
empty
-
build everything but no images
-
-
-
all
-
build everything including images
-
-
-
all-conf
-
build all configurations
-
-
-
images
-
create complete j2sdk and j2re images
-
-
-
install
-
install the generated images locally,
- typically in /usr/local
-
-
-
clean
-
remove all files generated by make,
- but not those generated by configure
-
-
-
dist-clean
-
remove all files generated by both
- and configure (basically killing the configuration)
-
-
-
help
-
give some help on using make,
- including some interesting make targets
- When the build is completed, you should see the generated
- binaries and associated files in the j2sdk-image
- directory in the output directory.
- In particular, the
- build/*/images/j2sdk-image/bin
- directory should contain executables for the
- OpenJDK tools and utilities for that configuration.
- The testing tool jtreg will be needed
- and can be found at:
-
- the jtreg site.
- The provided regression tests in the repositories
- can be run with the command:
-
- cd test && make PRODUCT_HOME=`pwd`/../build/*/images/j2sdk-image all
-
- Q: The generated-configure.sh file looks horrible!
- How are you going to edit it?
-
- A: The generated-configure.sh file is generated (think
- "compiled") by the autoconf tools. The source code is
- in configure.ac and various .m4 files in common/autoconf,
- which are much more readable.
-
-
-
- Q:
- Why is the generated-configure.sh file checked in,
- if it is generated?
-
- A:
- If it was not generated, every user would need to have the autoconf
- tools installed, and re-generate the configure file
- as the first step.
- Our goal is to minimize the work needed to be done by the user
- to start building OpenJDK, and to minimize
- the number of external dependencies required.
-
-
-
- Q:
- Do you require a specific version of autoconf for regenerating
- generated-configure.sh?
-
- A:
- Yes, version 2.69 is required and should be easy
- enough to aquire on all supported operating
- systems. The reason for this is to avoid
- large spurious changes in generated-configure.sh.
-
-
-
- Q:
- How do you regenerate generated-configure.sh
- after making changes to the input files?
-
- A:
- Regnerating generated-configure.sh
- should always be done using the
- script common/autoconf/autogen.sh to
- ensure that the correct files get updated. This
- script should also be run after mercurial tries to
- merge generated-configure.sh as a
- merge of the generated file is not guaranteed to
- be correct.
-
-
-
- Q:
- What are the files in common/makefiles/support/* for?
- They look like gibberish.
-
- A:
- They are a somewhat ugly hack to compensate for command line length
- limitations on certain platforms (Windows, Solaris).
- Due to a combination of limitations in make and the shell,
- command lines containing too many files will not work properly.
- These
- helper files are part of an elaborate hack that will compress the
- command line in the makefile and then uncompress it safely.
- We're
- not proud of it, but it does fix the problem.
- If you have any better suggestions, we're all ears! :-)
-
-
-
- Q:
- I want to see the output of the commands that make runs,
- like in the old build. How do I do that?
-
- A:
- You specify the LOG variable to make. There are
- several log levels:
-
-
-
-
- warn — Default and very quiet.
-
-
- info — Shows more progress information
- than warn.
-
-
- debug — Echos all command lines and
- prints all macro calls for compilation definitions.
-
-
- trace — Echos all $(shell) command
- lines as well.
-
-
-
-
-
- Q:
- When do I have to re-run configure?
-
- A:
- Normally you will run configure only once for creating a
- configuration.
- You need to re-run configuration only if you want to change any
- configuration options,
- or if you pull down changes to the configure script.
-
-
-
- Q:
- I have added a new source file. Do I need to modify the makefiles?
-
- A:
- Normally, no. If you want to create e.g. a new native
- library,
- you will need to modify the makefiles. But for normal file
- additions or removals, no changes are needed. There are certan
- exceptions for some native libraries where the source files are spread
- over many directories which also contain sources for other
- libraries. In these cases it was simply easier to create include lists
- rather than excludes.
-
-
-
- Q:
- When I run configure --help, I see many strange options,
- like --dvidir. What is this?
-
- A:
- Configure provides a slew of options by default, to all projects
- that use autoconf. Most of them are not used in OpenJDK,
- so you can safely ignore them. To list only OpenJDK specific features,
- use configure --help=short instead.
-
-
-
- Q:
- configure provides OpenJDK-specific features such as
- --with-builddeps-server that are not
- described in this document. What about those?
-
- A:
- Try them out if you like! But be aware that most of these are
- experimental features.
- Many of them don't do anything at all at the moment; the option
- is just a placeholder. Others depend on
- pieces of code or infrastructure that is currently
- not ready for prime time.
-
-
-
- Q:
- How will you make sure you don't break anything?
-
- A:
- We have a script that compares the result of the new build system
- with the result of the old. For most part, we aim for (and achieve)
- byte-by-byte identical output. There are however technical issues
- with e.g. native binaries, which might differ in a byte-by-byte
- comparison, even
- when building twice with the old build system.
- For these, we compare relevant aspects
- (e.g. the symbol table and file size).
- Note that we still don't have 100%
- equivalence, but we're close.
-
-
-
- Q:
- I noticed this thing X in the build that looks very broken by design.
- Why don't you fix it?
-
- A:
- Our goal is to produce a build output that is as close as
- technically possible to the old build output.
- If things were weird in the old build,
- they will be weird in the new build.
- Often, things were weird before due to obscurity,
- but in the new build system the weird stuff comes up to the surface.
- The plan is to attack these things at a later stage,
- after the new build system is established.
-
-
-
- Q:
- The code in the new build system is not that well-structured.
- Will you fix this?
-
- A:
- Yes! The new build system has grown bit by bit as we converted
- the old system. When all of the old build system is converted,
- we can take a step back and clean up the structure of the new build
- system. Some of this we plan to do before replacing the old build
- system and some will need to wait until after.
-
-
-
- Q:
- Is anything able to use the results of the new build's default make target?
-
- A:
- Yes, this is the minimal (or roughly minimal)
- set of compiled output needed for a developer to actually
- execute the newly built JDK. The idea is that in an incremental
- development fashion, when doing a normal make,
- you should only spend time recompiling what's changed
- (making it purely incremental) and only do the work that's
- needed to actually run and test your code.
- The packaging stuff that is part of the images
- target is not needed for a normal developer who wants to
- test his new code. Even if it's quite fast, it's still unnecessary.
- We're targeting sub-second incremental rebuilds! ;-)
- (Or, well, at least single-digit seconds...)
-
-
-
- Q:
- I usually set a specific environment variable when building,
- but I can't find the equivalent in the new build.
- What should I do?
-
- A:
- It might very well be that we have neglected to add support for
- an option that was actually used from outside the build system.
- Email us and we will add support for it!
-
Building OpenJDK requires a lot of horsepower.
- Some of the build tools can be adjusted to utilize more or less
- of resources such as
- parallel threads and memory.
- The configure script analyzes your system and selects reasonable
- values for such options based on your hardware.
- If you encounter resource problems, such as out of memory conditions,
- you can modify the detected values with:
-
-
-
- --with-num-cores
- —
- number of cores in the build system,
- e.g. --with-num-cores=8
-
-
- --with-memory-size
- — memory (in MB) available in the build system,
- e.g. --with-memory-size=1024
-
-
-
-
It might also be necessary to specify the JVM arguments passed
- to the Bootstrap JDK, using e.g.
- --with-boot-jdk-jvmargs="-Xmx8G -enableassertions".
- Doing this will override the default JVM arguments
- passed to the Bootstrap JDK.
-
-
-
One of the top goals of the new build system is to improve the
- build performance and decrease the time needed to build. This will
- soon also apply to the java compilation when the Smart Javac wrapper
- is fully supported.
-
-
At the end of a successful execution of configure,
- you will get a performance summary,
- indicating how well the build will perform. Here you will
- also get performance hints.
- If you want to build fast, pay attention to those!
-
-
Building with ccache
-
-
The OpenJDK build supports building with ccache
- when using gcc or clang. Using ccache can
- radically speed up compilation of native code if
- you often rebuild the same sources. Your milage
- may vary however so we recommend evaluating it for
- yourself. To enable it, make sure it's on the path
- and configure with --enable-ccache.
-
-
Building on local disk
-
-
If you are using network shares, e.g. via NFS, for your source code,
- make sure the build directory is situated on local disk.
- The performance
- penalty is extremely high for building on a network share,
- close to unusable.
-
-
Building only one JVM
-
-
The old build builds multiple JVMs on 32-bit systems (client and
- server; and on Windows kernel as well). In the new build we have
- changed this default to only build server when it's available. This
- improves build times for those not interested in multiple JVMs. To
- mimic the old behavior on platforms that support it,
- use --with-jvm-variants=client,server.
-
-
Selecting the number of cores to build on
-
-
By default, configure will analyze your machine and run the make
- process in parallel with as many threads as you have cores. This
- behavior can be overridden, either "permanently" (on a configure
- basis) using --with-num-cores=N or for a single build
- only (on a make basis), using make JOBS=N.
-
-
If you want to make a slower build just this time, to save some CPU
- power for other processes, you can run
- e.g. make JOBS=2. This will force the makefiles
- to only run 2 parallel processes, or even make JOBS=1
- which will disable parallelism.
-
-
If you want to have it the other way round, namely having slow
- builds default and override with fast if you're
- impatient, you should call configure with
- --with-num-cores=2, making 2 the default.
- If you want to run with more
- cores, run make JOBS=8
- If the build fails (and it's not due to a compilation error in
- a source file you've changed), the first thing you should do
- is to re-run the build with more verbosity.
- Do this by adding LOG=debug to your make command line.
-
- The build log (with both stdout and stderr intermingled,
- basically the same as you see on your console) can be found as
- build.log in your build directory.
-
- You can ask for help on build problems with the new build system
- on either the
-
- build-dev
- or the
-
- build-infra-dev
- mailing lists. Please include the relevant parts
- of the build log.
-
- A build can fail for any number of reasons.
- Most failures
- are a result of trying to build in an environment in which all the
- pre-build requirements have not been met.
- The first step in
- troubleshooting a build failure is to recheck that you have satisfied
- all the pre-build requirements for your platform.
- Scanning the configure log is a good first step, making
- sure that what it found makes sense for your system.
- Look for strange error messages or any difficulties that
- configure had in finding things.
-
- Some of the more common problems with builds are briefly
- described
- below, with suggestions for remedies.
-
-
- Corrupted Bundles on Windows:
-
- Some virus scanning software has been known to
- corrupt the
- downloading of zip bundles.
- It may be necessary to disable the 'on access' or
- 'real time'
- virus scanning features to prevent this corruption.
- This type of "real time" virus scanning can also
- slow down the
- build process significantly.
- Temporarily disabling the feature, or excluding the build
- output directory may be necessary to get correct and
- faster builds.
-
-
-
- Slow Builds:
-
- If your build machine seems to be overloaded from too many
- simultaneous C++ compiles, try setting the
- JOBS=1 on the make command line.
- Then try increasing the count slowly to an acceptable
- level for your system. Also:
-
- Creating the javadocs can be very slow,
- if you are running
- javadoc, consider skipping that step.
-
- Faster CPUs, more RAM, and a faster DISK usually helps.
- The VM build tends to be CPU intensive
- (many C++ compiles),
- and the rest of the JDK will often be disk intensive.
-
- Faster compiles are possible using a tool called
- ccache.
-
-
-
-
- File time issues:
-
- If you see warnings that refer to file time stamps, e.g.
-
- Warning message:
- File `xxx' has modification time in
- the future.
-
- Warning message: Clock skew detected.
- Your build may
- be incomplete.
-
- These warnings can occur when the clock on the build
- machine is out of
- sync with the timestamps on the source files.
- Other errors, apparently
- unrelated but in fact caused by the clock skew,
- can occur along with
- the clock skew warnings.
- These secondary errors may tend to obscure the
- fact that the true root cause of the problem
- is an out-of-sync clock.
-
- If you see these warnings, reset the clock on the
- build
- machine, run "gmake clobber"
- or delete the directory
- containing the build output, and restart the
- build from the beginning.
-
-
-
- Error message:
- Trouble writing out table to disk
-
- Increase the amount of swap space on your build machine.
- This could be caused by overloading the system and
- it may be necessary to use:
-
- make JOBS=1
-
- to reduce the load on the system.
-
-
-
- Error Message:
- libstdc++ not found:
-
- This is caused by a missing libstdc++.a library.
- This is installed as part of a specific package
- (e.g. libstdc++.so.devel.386).
- By default some 64-bit Linux versions (e.g. Fedora)
- only install the 64-bit version of the libstdc++ package.
- Various parts of the JDK build require a static
- link of the C++ runtime libraries to allow for maximum
- portability of the built images.
-
-
-
- Linux Error Message:
- cannot restore segment prot after reloc
-
- This is probably an issue with SELinux (See
-
- http://en.wikipedia.org/wiki/SELinux).
- Parts of the VM is built without the -fPIC for
- performance reasons.
-
- To completely disable SELinux:
-
-
$ su root
-
# system-config-securitylevel
-
In the window that appears, select the SELinux tab
-
Disable SELinux
-
-
- Alternatively, instead of completely disabling it you could
- disable just this one check.
-
-
Select System->Administration->SELinux Management
-
In the SELinux Management Tool which appears,
- select "Boolean" from the menu on the left
-
Expand the "Memory Protection" group
-
Check the first item, labeled
- "Allow all unconfined executables to use
- libraries requiring text relocation ..."
-
-
-
-
- Windows Error Messages:
-
- *** fatal error - couldn't allocate heap, ...
-
- rm fails with "Directory not empty"
-
- unzip fails with "cannot create ... Permission denied"
-
- unzip fails with "cannot create ... Error 50"
-
-
- Try rebooting the system, or there could be some kind of
- issue with the disk or disk partition being used.
- Sometimes it comes with a "Permission Denied" message.
-
-
- The Makefiles in the OpenJDK are only valid when used with the
- GNU version of the utility command make
- (usually called gmake on Solaris).
- A few notes about using GNU make:
-
-
- You need GNU make version 3.81 or newer. On Windows 4.0 or
- newer is recommended.
- If the GNU make utility on your systems is not of a suitable
- version see "Building GNU make".
-
-
- Place the location of the GNU make binary in the
- PATH.
-
-
- Solaris:
- Do NOT use /usr/bin/make on Solaris.
- If your Solaris system has the software
- from the Solaris Developer Companion CD installed,
- you should try and use gmake
- which will be located in either the
- /usr/bin, /opt/sfw/bin or
- /usr/sfw/bin directory.
-
-
- Windows:
- Make sure you start your build inside a bash shell.
-
-
- Mac OS X:
- The XCode "command line tools" must be installed on your Mac.
-
- First step is to get the GNU make 3.81 or newer source from
-
- ftp.gnu.org/pub/gnu/make/.
- Building is a little different depending on the OS but is
- basically done with:
-
- This file often describes specific requirements for what we
- call the
- "minimum build environments" (MBE) for this
- specific release of the JDK.
- What is listed below is what the Oracle Release
- Engineering Team will use to build the Oracle JDK product.
- Building with the MBE will hopefully generate the most compatible
- bits that install on, and run correctly on, the most variations
- of the same base OS and hardware architecture.
- In some cases, these represent what is often called the
- least common denominator, but each Operating System has different
- aspects to it.
-
- In all cases, the Bootstrap JDK version minimum is critical,
- we cannot guarantee builds will work with older Bootstrap JDK's.
- Also in all cases, more RAM and more processors is better,
- the minimums listed below are simply recommendations.
-
- With Solaris and Mac OS X, the version listed below is the
- oldest release we can guarantee builds and works, and the
- specific version of the compilers used could be critical.
-
- With Windows the critical aspect is the Visual Studio compiler
- used, which due to it's runtime, generally dictates what Windows
- systems can do the builds and where the resulting bits can
- be used.
- NOTE: We expect a change here off these older Windows OS releases
- and to a 'less older' one, probably Windows 2008R2 X64.
-
- With Linux, it was just a matter of picking a
- stable distribution that is a good representative for Linux
- in general.
- NOTE: We expect a change here from Fedora 9 to something else,
- but it has not been completely determined yet, possibly
- Ubuntu 12.04 X64, unbiased community feedback would be welcome on
- what a good choice would be here.
-
- It is understood that most developers will NOT be using these
- specific versions, and in fact creating these specific versions
- may be difficult due to the age of some of this software.
- It is expected that developers are more often using the more
- recent releases and distributions of these operating systems.
-
- Compilation problems with newer or different C/C++ compilers is a
- common problem.
- Similarly, compilation problems related to changes to the
- /usr/include or system header files is also a
- common problem with older, newer, or unreleased OS versions.
- Please report these types of problems as bugs so that they
- can be dealt with accordingly.
-
-
-
-
-
Base OS and Architecture
-
OS
-
C/C++ Compiler
-
Bootstrap JDK
-
Processors
-
RAM Minimum
-
DISK Needs
-
-
-
-
-
Linux X86 (32-bit) and X64 (64-bit)
-
Oracle Enterprise Linux 6.4
-
gcc 4.8.2
-
JDK 8
-
2 or more
-
1 GB
-
6 GB
-
-
-
Solaris SPARCV9 (64-bit)
-
Solaris 10 Update 10
-
Studio 12 Update 3 + patches
-
JDK 8
-
4 or more
-
4 GB
-
8 GB
-
-
-
Solaris X64 (64-bit)
-
Solaris 10 Update 10
-
Studio 12 Update 3 + patches
-
JDK 8
-
4 or more
-
4 GB
-
8 GB
-
-
-
Windows X86 (32-bit)
-
Windows Server 2012 R2 x64
-
Microsoft Visual Studio C++ 2013 Professional Edition
-
JDK 8
-
2 or more
-
2 GB
-
6 GB
-
-
-
Windows X64 (64-bit)
-
Windows Server 2012 R2 x64
-
Microsoft Visual Studio C++ 2013 Professional Edition
- After installing the latest
- Fedora
- you need to install several build dependencies.
- The simplest way to do it is to execute the
- following commands as user root:
-
- After installing
- CentOS 5.5
- you need to make sure you have
- the following Development bundles installed:
-
-
-
Development Libraries
-
Development Tools
-
Java Development
-
X Software Development (Including XFree86-devel)
-
-
-
- Plus the following packages:
-
-
-
cups devel: Cups Development Package
-
alsa devel: Alsa Development Package
-
Xi devel: libXi.so Development Package
-
-
-
- The freetype 2.3 packages don't seem to be available,
- but the freetype 2.3 sources can be downloaded, built,
- and installed easily enough from
-
- the freetype site.
- Build and install with something like:
-
- bash ./configure
-
- make
-
- sudo -u root make install
-
-
- Mercurial packages could not be found easily, but a Google
- search should find ones, and they usually include Python if
- it's needed.
-
- After installing Debian 5
- you need to install several build dependencies.
- The simplest way to install the build dependencies is to
- execute the following commands as user root:
-
- After installing OpenSUSE 11.1
- you need to install several build dependencies.
- The simplest way to install the build dependencies is to
- execute the following commands:
-
- After installing Mandriva
- 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 root:
-
- urpmi java-1.7.0-openjdk-devel make gcc gcc-c++
- freetype-devel zip unzip libcups2-devel libxrender1-devel
- libalsa2-devel libstc++-static-devel libxtst6-devel
- libxi-devel
-
-
- In addition, it is necessary to set a few environment
- variables for the build:
-
- After installing OpenSolaris 2009.06
- you need to install several build dependencies.
- The simplest way to install the build dependencies is to
- execute the following commands:
-
End of OpenJDK README-builds.html document. Please come again!
-
+
-
+
System Setup
+
+
Before even attempting to use a system to build the OpenJDK there are some very
+basic system setups needed. For all systems:
+
+
+
Be sure the GNU make utility is version 3.81 (4.0 on windows) or newer, e.g.
+run "make -version"
+
+
+
Install a Bootstrap JDK. All OpenJDK builds require access to a previously
+released JDK called the bootstrap JDK or boot JDK. The general rule is
+that the bootstrap JDK must be an instance of the previous major release of
+the JDK. In addition, there may be a requirement to use a release at or
+beyond a particular update level.
+
+
Building JDK 9 requires JDK 8. JDK 9 developers should not use JDK 9 as
+the boot JDK, to ensure that JDK 9 dependencies are not introduced into the
+parts of the system that are built with JDK 8.
+
+
The JDK 8 binaries can be downloaded from Oracle's JDK 8 download
+site.
+For build performance reasons it is very important that this bootstrap JDK
+be made available on the local disk of the machine doing the build. You
+should add its bin directory to the PATH environment variable. If
+configure has any issues finding this JDK, you may need to use the
+configure option --with-boot-jdk.
+
Ensure that GNU make, the Bootstrap JDK, and the compilers are all in your
+PATH environment variable.
Install XCode 4.5.2 and also
+install the "Command line tools" found under the preferences pane
+"Downloads"
+
+
+
+
+
Linux
+
+
With Linux, try and favor the system packages over building your own or getting
+packages from other areas. Most Linux builds should be possible with the
+system's available packages.
+
+
Note that some Linux systems have a habit of pre-populating your environment
+variables for you, for example JAVA_HOME might get pre-defined for you to
+refer to the JDK installed on your Linux system. You will need to unset
+JAVA_HOME. It's a good idea to run env and verify the environment variables
+you are getting from the default system settings make sense for building the
+OpenJDK.
+
+
+
+
Solaris
+
+
+
+
Studio Compilers
+
+
At a minimum, the Studio 12 Update 1 Compilers (containing
+version 5.10 of the C and C++ compilers) is required, including specific
+patches.
+
+
The Solaris SPARC patch list is:
+
+
+
118683-05: SunOS 5.10: Patch for profiling libraries and assembler
+
119963-21: SunOS 5.10: Shared library patch for C++
Building on Windows requires a Unix-like environment, notably a Unix-like
+shell. There are several such environments available of which
+Cygwin and
+MinGW/MSYS are currently supported for the
+OpenJDK build. One of the differences of these systems from standard Windows
+tools is the way they handle Windows path names, particularly path names which
+contain spaces, backslashes as path separators and possibly drive letters.
+Depending on the use case and the specifics of each environment these path
+problems can be solved by a combination of quoting whole paths, translating
+backslashes to forward slashes, escaping backslashes with additional
+backslashes and translating the path names to their "8.3"
+version.
+
+
+
+
CYGWIN
+
+
CYGWIN is an open source, Linux-like environment which tries to emulate a
+complete POSIX layer on Windows. It tries to be smart about path names and can
+usually handle all kinds of paths if they are correctly quoted or escaped
+although internally it maps drive letters <drive>: to a virtual directory
+/cygdrive/<drive>.
+
+
You can always use the cygpath utility to map pathnames with spaces or the
+backslash character into the C:/ style of pathname (called 'mixed'), e.g.
+cygpath -s -m "<path>".
+
+
Note that the use of CYGWIN creates a unique problem with regards to setting
+PATH. Normally on Windows the PATH variable contains directories
+separated with the ";" character (Solaris and Linux use ":"). With CYGWIN, it
+uses ":", but that means that paths like "C:/path" cannot be placed in the
+CYGWIN version of PATH and instead CYGWIN uses something like
+/cygdrive/c/path which CYGWIN understands, but only CYGWIN understands.
+
+
The OpenJDK build requires CYGWIN version 1.7.16 or newer. Information about
+CYGWIN can be obtained from the CYGWIN website at
+www.cygwin.com.
+
+
By default CYGWIN doesn't install all the tools required for building the
+OpenJDK. Along with the default installation, you need to install the following
+tools.
+
+
+
+
+
+
Binary Name
+
Category
+
Package
+
Description
+
+
+
+
+
ar.exe
+
Devel
+
binutils
+
The GNU assembler, linker and binary utilities
+
+
+
make.exe
+
Devel
+
make
+
The GNU version of the 'make' utility built for CYGWIN
+
+
+
m4.exe
+
Interpreters
+
m4
+
GNU implementation of the traditional Unix macro processor
+
+
+
cpio.exe
+
Utils
+
cpio
+
A program to manage archives of files
+
+
+
gawk.exe
+
Utils
+
awk
+
Pattern-directed scanning and processing language
+
+
+
file.exe
+
Utils
+
file
+
Determines file type using 'magic' numbers
+
+
+
zip.exe
+
Archive
+
zip
+
Package and compress (archive) files
+
+
+
unzip.exe
+
Archive
+
unzip
+
Extract compressed files in a ZIP archive
+
+
+
free.exe
+
System
+
procps
+
Display amount of free and used memory in the system
+
+
+
+
+
+
Note that the CYGWIN software can conflict with other non-CYGWIN software on
+your Windows system. CYGWIN provides a FAQ for known issues and problems, of particular interest is the
+section on BLODA (applications that interfere with
+CYGWIN).
+
+
+
+
MinGW/MSYS
+
+
MinGW ("Minimalist GNU for Windows") is a collection of free Windows specific
+header files and import libraries combined with GNU toolsets that allow one to
+produce native Windows programs that do not rely on any 3rd-party C runtime
+DLLs. MSYS is a supplement to MinGW which allows building applications and
+programs which rely on traditional UNIX tools to be present. Among others this
+includes tools like bash and make. See MinGW/MSYS for more information.
+
+
Like Cygwin, MinGW/MSYS can handle different types of path formats. They are
+internally converted to paths with forward slashes and drive letters
+<drive>: replaced by a virtual directory /<drive>. Additionally, MSYS
+automatically detects binaries compiled for the MSYS environment and feeds them
+with the internal, Unix-style path names. If native Windows applications are
+called from within MSYS programs their path arguments are automatically
+converted back to Windows style path names with drive letters and backslashes
+as path separators. This may cause problems for Windows applications which use
+forward slashes as parameter separator (e.g. cl /nologo /I) because MSYS may
+wrongly replace such parameters by drive letters.
+
+
In addition to the tools which will be installed by default, you have to
+manually install the msys-zip and msys-unzip packages. This can be easily
+done with the MinGW command line installer:
The 32-bit and 64-bit OpenJDK Windows build requires Microsoft Visual Studio
+C++ 2013 (VS2013) Professional Edition or Express compiler. The compiler and
+other tools are expected to reside in the location defined by the variable
+VS120COMNTOOLS which is set by the Microsoft Visual Studio installer.
+
+
Only the C++ part of VS2013 is needed. Try to let the installation go to the
+default install directory. Always reboot your system after installing VS2013.
+The system environment variable VS120COMNTOOLS should be set in your
+environment.
+
+
Make sure that TMP and TEMP are also set in the environment and refer to
+Windows paths that exist, like C:\temp, not /tmp, not /cygdrive/c/temp,
+and not C:/temp. C:\temp is just an example, it is assumed that this area
+is private to the user, so by default after installs you should see a unique
+user path in these variables.
+
+
+
+
Mac OS X
+
+
Make sure you get the right XCode version.
+
+
+
+
+
+
Configure
+
+
The basic invocation of the configure script looks like:
+
+
+
bash ./configure [options]
+
+
+
This will create an output directory containing the "configuration" and setup
+an area for the build result. This directory typically looks like:
+
+
+
build/linux-x64-normal-server-release
+
+
+
configure will try to figure out what system you are running on and where all
+necessary build components are. If you have all prerequisites for building
+installed, it should find everything. If it fails to detect any component
+automatically, it will exit and inform you about the problem. When this
+happens, read more below in the configure options.
+
+
Some examples:
+
+
+
Windows 32bit build with freetype specified:
+ bash ./configure --with-freetype=/cygdrive/c/freetype-i586 --with-target-
+bits=32
Complete details on all the OpenJDK configure options can be seen with:
+
+
+
bash ./configure --help=short
+
+
+
Use -help to see all the configure options available. You can generate any
+number of different configurations, e.g. debug, release, 32, 64, etc.
+
+
Some of the more commonly used configure options are:
+
+
+
--enable-debug
+ set the debug level to fastdebug (this is a shorthand for --with-debug-
+ level=fastdebug)
+
+
+
+
+
+
--with-alsa=path
+ select the location of the Advanced Linux Sound Architecture (ALSA)
+
+
Version 0.9.1 or newer of the ALSA files are required for building the
+ OpenJDK on Linux. These Linux files are usually available from an "alsa" of
+ "libasound" development package, and it's highly recommended that you try
+ and use the package provided by the particular version of Linux that you are
+ using.
--with-boot-jdk-jvmargs="args"
+ provide the JVM options to be used to run the Bootstrap JDK
+
+
--with-cacerts=path
+ select the path to the cacerts file.
+
+
See Certificate Authority on Wikipedia for a better understanding of the Certificate
+ Authority (CA). A certificates file named "cacerts" represents a system-wide
+ keystore with CA certificates. In JDK and JRE binary bundles, the "cacerts"
+ file contains root CA certificates from several public CAs (e.g., VeriSign,
+ Thawte, and Baltimore). The source contain a cacerts file without CA root
+ certificates. Formal JDK builders will need to secure permission from each
+ public CA and include the certificates into their own custom cacerts file.
+ Failure to provide a populated cacerts file will result in verification
+ errors of a certificate chain during runtime. By default an empty cacerts
+ file is provided and that should be fine for most JDK developers.
+
+
+
+
+
+
--with-cups=path
+ select the CUPS install location
+
+
The Common UNIX Printing System (CUPS) Headers are required for building the
+ OpenJDK on Solaris and Linux. The Solaris header files can be obtained by
+ installing the package SFWcups from the Solaris Software Companion
+ CD/DVD, these often will be installed into the directory /opt/sfw/cups.
+
+
The CUPS header files can always be downloaded from
+ www.cups.org.
+
+
--with-cups-include=path
+ select the CUPS include directory location
+
+
--with-debug-level=level
+ select the debug information level of release, fastdebug, or slowdebug
+
+
--with-dev-kit=path
+ select location of the compiler install or developer install location
+
+
+
+
+
+
--with-freetype=path
+ select the freetype files to use.
+
+
Expecting the freetype libraries under lib/ and the headers under
+ include/.
+
+
Version 2.3 or newer of FreeType is required. On Unix systems required files
+ can be available as part of your distribution (while you still may need to
+ upgrade them). Note that you need development version of package that
+ includes both the FreeType library and header files.
Note that by default FreeType is built with byte code hinting support
+ disabled due to licensing restrictions. In this case, text appearance and
+ metrics are expected to differ from Sun's official JDK build. See the
+ SourceForge FreeType2 Home Page
+ for more information.
+
+
--with-import-hotspot=path
+ select the location to find hotspot binaries from a previous build to avoid
+ building hotspot
+
+
--with-target-bits=arg
+ select 32 or 64 bit build
+
+
--with-jvm-variants=variants
+ select the JVM variants to build from, comma separated list that can
+ include: server, client, kernel, zero and zeroshark
+
+
--with-memory-size=size
+ select the RAM size that GNU make will think this system has
+
+
--with-msvcr-dll=path
+ select the msvcr100.dll file to include in the Windows builds (C/C++
+ runtime library for Visual Studio).
+
+
This is usually picked up automatically from the redist directories of
+ Visual Studio 2013.
+
+
--with-num-cores=cores
+ select the number of cores to use (processor count or CPU count)
+
+
+
+
+
+
--with-x=path
+ select the location of the X11 and xrender files.
+
+
The XRender Extension Headers are required for building the OpenJDK on
+ Solaris and Linux. The Linux header files are usually available from a
+ "Xrender" development package, it's recommended that you try and use the
+ package provided by the particular distribution of Linux that you are using.
+ The Solaris XRender header files is included with the other X11 header files
+ in the package SFWxwinc on new enough versions of Solaris and will be
+ installed in /usr/X11/include/X11/extensions/Xrender.h or
+ /usr/openwin/share/include/X11/extensions/Xrender.h
+
+
+
+
+
+
+
Make
+
+
The basic invocation of the make utility looks like:
+
+
+
make all
+
+
+
This will start the build to the output directory containing the
+"configuration" that was created by the configure script. Run make help for
+more information on the available targets.
+
+
There are some of the make targets that are of general interest:
+
+
+
empty
+ build everything but no images
+
+
all
+ build everything including images
+
+
all-conf
+ build all configurations
+
+
images
+ create complete j2sdk and j2re images
+
+
install
+ install the generated images locally, typically in /usr/local
+
+
clean
+ remove all files generated by make, but not those generated by configure
+
+
dist-clean
+ remove all files generated by both and configure (basically killing the
+ configuration)
+
+
help
+ give some help on using make, including some interesting make targets
+
+
+
+
+
+
+
Testing
+
+
When the build is completed, you should see the generated binaries and
+associated files in the j2sdk-image directory in the output directory. In
+particular, the build/*/images/j2sdk-image/bin directory should contain
+executables for the OpenJDK tools and utilities for that configuration. The
+testing tool jtreg will be needed and can be found at: the jtreg
+site. The provided regression tests in the
+repositories can be run with the command:
+
+
+
cd test && make PRODUCT_HOME=`pwd`/../build/*/images/j2sdk-image all
+
+
+
+
+
+
+
Appendix A: Hints and Tips
+
+
+
+
FAQ
+
+
Q: The generated-configure.sh file looks horrible! How are you going to
+edit it?
+A: The generated-configure.sh file is generated (think "compiled") by the
+autoconf tools. The source code is in configure.ac and various .m4 files in
+common/autoconf, which are much more readable.
+
+
Q: Why is the generated-configure.sh file checked in, if it is
+generated?
+A: If it was not generated, every user would need to have the autoconf
+tools installed, and re-generate the configure file as the first step. Our
+goal is to minimize the work needed to be done by the user to start building
+OpenJDK, and to minimize the number of external dependencies required.
+
+
Q: Do you require a specific version of autoconf for regenerating
+generated-configure.sh?
+A: Yes, version 2.69 is required and should be easy enough to aquire on all
+supported operating systems. The reason for this is to avoid large spurious
+changes in generated-configure.sh.
+
+
Q: How do you regenerate generated-configure.sh after making changes to
+the input files?
+A: Regnerating generated-configure.sh should always be done using the
+script common/autoconf/autogen.sh to ensure that the correct files get
+updated. This script should also be run after mercurial tries to merge
+generated-configure.sh as a merge of the generated file is not guaranteed to
+be correct.
+
+
Q: What are the files in common/makefiles/support/* for? They look like
+gibberish.
+A: They are a somewhat ugly hack to compensate for command line length
+limitations on certain platforms (Windows, Solaris). Due to a combination of
+limitations in make and the shell, command lines containing too many files will
+not work properly. These helper files are part of an elaborate hack that will
+compress the command line in the makefile and then uncompress it safely. We're
+not proud of it, but it does fix the problem. If you have any better
+suggestions, we're all ears! :-)
+
+
Q: I want to see the output of the commands that make runs, like in the old
+build. How do I do that?
+A: You specify the LOG variable to make. There are several log levels:
+
+
+
warn -- Default and very quiet.
+
info -- Shows more progress information than warn.
+
debug -- Echos all command lines and prints all macro calls for
+compilation definitions.
+
trace -- Echos all $(shell) command lines as well.
+
+
+
Q: When do I have to re-run configure?
+A: Normally you will run configure only once for creating a
+configuration. You need to re-run configuration only if you want to change any
+configuration options, or if you pull down changes to the configure script.
+
+
Q: I have added a new source file. Do I need to modify the makefiles?
+A: Normally, no. If you want to create e.g. a new native library, you will
+need to modify the makefiles. But for normal file additions or removals, no
+changes are needed. There are certan exceptions for some native libraries where
+the source files are spread over many directories which also contain sources
+for other libraries. In these cases it was simply easier to create include
+lists rather than excludes.
+
+
Q: When I run configure --help, I see many strange options, like
+--dvidir. What is this?
+A: Configure provides a slew of options by default, to all projects that
+use autoconf. Most of them are not used in OpenJDK, so you can safely ignore
+them. To list only OpenJDK specific features, use configure --help=short
+instead.
+
+
Q:configure provides OpenJDK-specific features such as --with-
+builddeps-server that are not described in this document. What about those?
+A: Try them out if you like! But be aware that most of these are
+experimental features. Many of them don't do anything at all at the moment; the
+option is just a placeholder. Others depend on pieces of code or infrastructure
+that is currently not ready for prime time.
+
+
Q: How will you make sure you don't break anything?
+A: We have a script that compares the result of the new build system with
+the result of the old. For most part, we aim for (and achieve) byte-by-byte
+identical output. There are however technical issues with e.g. native binaries,
+which might differ in a byte-by-byte comparison, even when building twice with
+the old build system. For these, we compare relevant aspects (e.g. the symbol
+table and file size). Note that we still don't have 100% equivalence, but we're
+close.
+
+
Q: I noticed this thing X in the build that looks very broken by design.
+Why don't you fix it?
+A: Our goal is to produce a build output that is as close as technically
+possible to the old build output. If things were weird in the old build, they
+will be weird in the new build. Often, things were weird before due to
+obscurity, but in the new build system the weird stuff comes up to the surface.
+The plan is to attack these things at a later stage, after the new build system
+is established.
+
+
Q: The code in the new build system is not that well-structured. Will you
+fix this?
+A: Yes! The new build system has grown bit by bit as we converted the old
+system. When all of the old build system is converted, we can take a step back
+and clean up the structure of the new build system. Some of this we plan to do
+before replacing the old build system and some will need to wait until after.
+
+
Q: Is anything able to use the results of the new build's default make
+target?
+A: Yes, this is the minimal (or roughly minimal) set of compiled output
+needed for a developer to actually execute the newly built JDK. The idea is
+that in an incremental development fashion, when doing a normal make, you
+should only spend time recompiling what's changed (making it purely
+incremental) and only do the work that's needed to actually run and test your
+code. The packaging stuff that is part of the images target is not needed for
+a normal developer who wants to test his new code. Even if it's quite fast,
+it's still unnecessary. We're targeting sub-second incremental rebuilds! ;-)
+(Or, well, at least single-digit seconds...)
+
+
Q: I usually set a specific environment variable when building, but I can't
+find the equivalent in the new build. What should I do?
+A: It might very well be that we have neglected to add support for an
+option that was actually used from outside the build system. Email us and we
+will add support for it!
+
+
+
+
Build Performance Tips
+
+
Building OpenJDK requires a lot of horsepower. Some of the build tools can be
+adjusted to utilize more or less of resources such as parallel threads and
+memory. The configure script analyzes your system and selects reasonable
+values for such options based on your hardware. If you encounter resource
+problems, such as out of memory conditions, you can modify the detected values
+with:
+
+
+
--with-num-cores -- number of cores in the build system, e.g.
+--with-num-cores=8
+
--with-memory-size -- memory (in MB) available in the build system,
+e.g. --with-memory-size=1024
+
+
+
It might also be necessary to specify the JVM arguments passed to the Bootstrap
+JDK, using e.g. --with-boot-jdk-jvmargs="-Xmx8G -enableassertions". Doing
+this will override the default JVM arguments passed to the Bootstrap JDK.
+
+
One of the top goals of the new build system is to improve the build
+performance and decrease the time needed to build. This will soon also apply to
+the java compilation when the Smart Javac wrapper is fully supported.
+
+
At the end of a successful execution of configure, you will get a performance
+summary, indicating how well the build will perform. Here you will also get
+performance hints. If you want to build fast, pay attention to those!
+
+
Building with ccache
+
+
The OpenJDK build supports building with ccache when using gcc or clang. Using
+ccache can radically speed up compilation of native code if you often rebuild
+the same sources. Your milage may vary however so we recommend evaluating it
+for yourself. To enable it, make sure it's on the path and configure with
+--enable-ccache.
+
+
Building on local disk
+
+
If you are using network shares, e.g. via NFS, for your source code, make sure
+the build directory is situated on local disk. The performance penalty is
+extremely high for building on a network share, close to unusable.
+
+
Building only one JVM
+
+
The old build builds multiple JVMs on 32-bit systems (client and server; and on
+Windows kernel as well). In the new build we have changed this default to only
+build server when it's available. This improves build times for those not
+interested in multiple JVMs. To mimic the old behavior on platforms that
+support it, use --with-jvm-variants=client,server.
+
+
Selecting the number of cores to build on
+
+
By default, configure will analyze your machine and run the make process in
+parallel with as many threads as you have cores. This behavior can be
+overridden, either "permanently" (on a configure basis) using
+--with-num-cores=N or for a single build only (on a make basis), using
+make JOBS=N.
+
+
If you want to make a slower build just this time, to save some CPU power for
+other processes, you can run e.g. make JOBS=2. This will force the makefiles
+to only run 2 parallel processes, or even make JOBS=1 which will disable
+parallelism.
+
+
If you want to have it the other way round, namely having slow builds default
+and override with fast if you're impatient, you should call configure with
+--with-num-cores=2, making 2 the default. If you want to run with more cores,
+run make JOBS=8
+
+
+
+
Troubleshooting
+
+
Solving build problems
+
+
If the build fails (and it's not due to a compilation error in a source file
+you've changed), the first thing you should do is to re-run the build with more
+verbosity. Do this by adding LOG=debug to your make command line.
+
+
The build log (with both stdout and stderr intermingled, basically the same as
+you see on your console) can be found as build.log in your build directory.
+
+
You can ask for help on build problems with the new build system on either the
+build-dev or the
+build-infra-dev
+mailing lists. Please include the relevant parts of the build log.
+
+
A build can fail for any number of reasons. Most failures are a result of
+trying to build in an environment in which all the pre-build requirements have
+not been met. The first step in troubleshooting a build failure is to recheck
+that you have satisfied all the pre-build requirements for your platform.
+Scanning the configure log is a good first step, making sure that what it
+found makes sense for your system. Look for strange error messages or any
+difficulties that configure had in finding things.
+
+
Some of the more common problems with builds are briefly described below, with
+suggestions for remedies.
+
+
+
Corrupted Bundles on Windows:
+Some virus scanning software has been known to corrupt the downloading of
+zip bundles. It may be necessary to disable the 'on access' or 'real time'
+virus scanning features to prevent this corruption. This type of 'real time'
+virus scanning can also slow down the build process significantly.
+Temporarily disabling the feature, or excluding the build output directory
+may be necessary to get correct and faster builds.
+
Slow Builds:
+If your build machine seems to be overloaded from too many simultaneous C++
+compiles, try setting the JOBS=1 on the make command line. Then try
+increasing the count slowly to an acceptable level for your system. Also:
+
+
Creating the javadocs can be very slow, if you are running javadoc, consider
+skipping that step.
+
+
Faster CPUs, more RAM, and a faster DISK usually helps. The VM build tends
+to be CPU intensive (many C++ compiles), and the rest of the JDK will often
+be disk intensive.
+
+
Faster compiles are possible using a tool called
+ccache.
+
File time issues:
+If you see warnings that refer to file time stamps, e.g.
+
+
+
Warning message:File 'xxx' has modification time in the future.
+Warning message:Clock skew detected. Your build may be incomplete.
+
+
+
These warnings can occur when the clock on the build machine is out of sync
+with the timestamps on the source files. Other errors, apparently unrelated
+but in fact caused by the clock skew, can occur along with the clock skew
+warnings. These secondary errors may tend to obscure the fact that the true
+root cause of the problem is an out-of-sync clock.
+
+
If you see these warnings, reset the clock on the build machine, run
+"gmake clobber" or delete the directory containing the build output, and
+restart the build from the beginning.
+
Error message: Trouble writing out table to disk
+Increase the amount of swap space on your build machine. This could be
+caused by overloading the system and it may be necessary to use:
+
+
+
make JOBS=1
+
+
+
to reduce the load on the system.
+
Error Message: libstdc++ not found:
+This is caused by a missing libstdc++.a library. This is installed as part
+of a specific package (e.g. libstdc++.so.devel.386). By default some 64-bit
+Linux versions (e.g. Fedora) only install the 64-bit version of the
+libstdc++ package. Various parts of the JDK build require a static link of
+the C++ runtime libraries to allow for maximum portability of the built
+images.
+
Linux Error Message: cannot restore segment prot after reloc
+This is probably an issue with SELinux (See SELinux on
+Wikipedia). Parts of the VM is built
+without the -fPIC for performance reasons.
+
+
To completely disable SELinux:
+
+
+
$ su root
+
# system-config-securitylevel
+
In the window that appears, select the SELinux tab
+
Disable SELinux
+
+
+
Alternatively, instead of completely disabling it you could disable just
+this one check.
+
+
+
Select System->Administration->SELinux Management
+
In the SELinux Management Tool which appears, select "Boolean" from the
+menu on the left
+
Expand the "Memory Protection" group
+
Check the first item, labeled "Allow all unconfined executables to use
+libraries requiring text relocation ..."
+
+
Windows Error Messages:
+*** fatal error - couldn't allocate heap, ...
+rm fails with "Directory not empty"
+unzip fails with "cannot create ... Permission denied"
+unzip fails with "cannot create ... Error 50"
Windows Error Message: spawn failed
+Try rebooting the system, or there could be some kind of issue with the disk
+or disk partition being used. Sometimes it comes with a "Permission Denied"
+message.
+
+
+
+
+
+
+
Appendix B: GNU make
+
+
The Makefiles in the OpenJDK are only valid when used with the GNU version of
+the utility command make (usually called gmake on Solaris). A few notes
+about using GNU make:
+
+
+
You need GNU make version 3.81 or newer. On Windows 4.0 or newer is
+recommended. If the GNU make utility on your systems is not of a suitable
+version, see "Building GNU make".
+
Place the location of the GNU make binary in the PATH.
+
Solaris: Do NOT use /usr/bin/make on Solaris. If your Solaris system
+has the software from the Solaris Developer Companion CD installed, you
+should try and use gmake which will be located in either the /usr/bin,
+/opt/sfw/bin or /usr/sfw/bin directory.
+
Windows: Make sure you start your build inside a bash shell.
+
Mac OS X: The XCode "command line tools" must be installed on your Mac.
+
+
+
Information on GNU make, and access to ftp download sites, are available on the
+GNU make web site . The latest
+source to GNU make is available at
+ftp.gnu.org/pub/gnu/make/.
+
+
+
+
Building GNU make
+
+
First step is to get the GNU make 3.81 or newer source from
+ftp.gnu.org/pub/gnu/make/. Building is a
+little different depending on the OS but is basically done with:
+
+
bash ./configure
+ make
+
+
+
+
+
+
+
Appendix C: Build Environments
+
+
Minimum Build Environments
+
+
This file often describes specific requirements for what we call the "minimum
+build environments" (MBE) for this specific release of the JDK. What is listed
+below is what the Oracle Release Engineering Team will use to build the Oracle
+JDK product. Building with the MBE will hopefully generate the most compatible
+bits that install on, and run correctly on, the most variations of the same
+base OS and hardware architecture. In some cases, these represent what is often
+called the least common denominator, but each Operating System has different
+aspects to it.
+
+
In all cases, the Bootstrap JDK version minimum is critical, we cannot
+guarantee builds will work with older Bootstrap JDK's. Also in all cases, more
+RAM and more processors is better, the minimums listed below are simply
+recommendations.
+
+
With Solaris and Mac OS X, the version listed below is the oldest release we
+can guarantee builds and works, and the specific version of the compilers used
+could be critical.
+
+
With Windows the critical aspect is the Visual Studio compiler used, which due
+to it's runtime, generally dictates what Windows systems can do the builds and
+where the resulting bits can be used.
+
+
NOTE: We expect a change here off these older Windows OS releases and to a
+'less older' one, probably Windows 2008R2 X64.
+
+
With Linux, it was just a matter of picking a stable distribution that is a
+good representative for Linux in general.
+
+
NOTE: We expect a change here from Fedora 9 to something else, but it has not
+been completely determined yet, possibly Ubuntu 12.04 X64, unbiased community
+feedback would be welcome on what a good choice would be here.
+
+
It is understood that most developers will NOT be using these specific
+versions, and in fact creating these specific versions may be difficult due to
+the age of some of this software. It is expected that developers are more often
+using the more recent releases and distributions of these operating systems.
+
+
Compilation problems with newer or different C/C++ compilers is a common
+problem. Similarly, compilation problems related to changes to the
+/usr/include or system header files is also a common problem with older,
+newer, or unreleased OS versions. Please report these types of problems as bugs
+so that they can be dealt with accordingly.
+
+
+
+
+
+
Base OS and Architecture
+
OS
+
C/C++ Compiler
+
Bootstrap JDK
+
Processors
+
RAM Minimum
+
DISK Needs
+
+
+
+
+
Linux X86 (32-bit) and X64 (64-bit)
+
Oracle Enterprise Linux 6.4
+
gcc 4.8.2
+
JDK 8
+
2 or more
+
1 GB
+
6 GB
+
+
+
Solaris SPARCV9 (64-bit)
+
Solaris 10 Update 10
+
Studio 12 Update 3 + patches
+
JDK 8
+
4 or more
+
4 GB
+
8 GB
+
+
+
Solaris X64 (64-bit)
+
Solaris 10 Update 10
+
Studio 12 Update 3 + patches
+
JDK 8
+
4 or more
+
4 GB
+
8 GB
+
+
+
Windows X86 (32-bit)
+
Windows Server 2012 R2 x64
+
Microsoft Visual Studio C++ 2013 Professional Edition
+
JDK 8
+
2 or more
+
2 GB
+
6 GB
+
+
+
Windows X64 (64-bit)
+
Windows Server 2012 R2 x64
+
Microsoft Visual Studio C++ 2013 Professional Edition
+
JDK 8
+
2 or more
+
2 GB
+
6 GB
+
+
+
Mac OS X X64 (64-bit)
+
Mac OS X 10.9 "Mavericks"
+
XCode 5.1.1 or newer
+
JDK 8
+
2 or more
+
4 GB
+
6 GB
+
+
+
+
+
+
+
+
+
+
Specific Developer Build Environments
+
+
We won't be listing all the possible environments, but we will try to provide
+what information we have available to us.
+
+
NOTE: The community can help out by updating this part of the document.
+
+
Fedora
+
+
After installing the latest Fedora you need to
+install several build dependencies. The simplest way to do it is to execute the
+following commands as user root:
After installing CentOS 5.5 you need to make sure you
+have the following Development bundles installed:
+
+
+
Development Libraries
+
Development Tools
+
Java Development
+
X Software Development (Including XFree86-devel)
+
+
+
Plus the following packages:
+
+
+
cups devel: Cups Development Package
+
alsa devel: Alsa Development Package
+
Xi devel: libXi.so Development Package
+
+
+
The freetype 2.3 packages don't seem to be available, but the freetype 2.3
+sources can be downloaded, built, and installed easily enough from the
+freetype site. Build and install
+with something like:
+
+
bash ./configure
+ make
+ sudo -u root make install
+
+
+
Mercurial packages could not be found easily, but a Google search should find
+ones, and they usually include Python if it's needed.
+
+
Debian 5.0 (Lenny)
+
+
After installing Debian 5 you need to install several
+build dependencies. The simplest way to install the build dependencies is to
+execute the following commands as user root:
After installing OpenSUSE 11.1 you need to install
+several build dependencies. The simplest way to install the build dependencies
+is to execute the following commands:
Finally, you need to unset the JAVA_HOME environment variable:
+
+
export -n JAVA_HOME`
+
+
+
Mandriva Linux One 2009 Spring
+
+
After installing Mandriva 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 root:
+
+
urpmi java-1.7.0-openjdk-devel make gcc gcc-c++ freetype-devel zip unzip
+ libcups2-devel libxrender1-devel libalsa2-devel libstc++-static-devel
+ libxtst6-devel libxi-devel
+
+
+
In addition, it is necessary to set a few environment variables for the build:
After installing OpenSolaris 2009.06 you need to
+install several build dependencies. The simplest way to install the build
+dependencies is to execute the following commands:
+
diff --git a/README-builds.md b/README-builds.md
new file mode 100644
index 00000000000..21367477890
--- /dev/null
+++ b/README-builds.md
@@ -0,0 +1,1263 @@
+
+# OpenJDK Build README
+
+*****
+
+
+## Introduction
+
+This README file contains build instructions for the
+[OpenJDK](http://openjdk.java.net). Building the source code for the OpenJDK
+requires a certain degree of technical expertise.
+
+### !!!!!!!!!!!!!!! THIS IS A MAJOR RE-WRITE of this document. !!!!!!!!!!!!!
+
+Some Headlines:
+
+ * The build is now a "`configure && make`" style build
+ * Any GNU make 3.81 or newer should work, except on Windows where 4.0 or newer
+ is recommended.
+ * The build should scale, i.e. more processors should cause the build to be
+ done in less wall-clock time
+ * Nested or recursive make invocations have been significantly reduced,
+ as has the total fork/exec or spawning of sub processes during the build
+ * Windows MKS usage is no longer supported
+ * Windows Visual Studio `vsvars*.bat` and `vcvars*.bat` files are run
+ automatically
+ * Ant is no longer used when building the OpenJDK
+ * Use of ALT_* environment variables for configuring the build is no longer
+ supported
+
+*****
+
+## Contents
+
+ * [Introduction](#introduction)
+ * [Use of Mercurial](#hg)
+ * [Getting the Source](#get_source)
+ * [Repositories](#repositories)
+ * [Building](#building)
+ * [System Setup](#setup)
+ * [Linux](#linux)
+ * [Solaris](#solaris)
+ * [Mac OS X](#macosx)
+ * [Windows](#windows)
+ * [Configure](#configure)
+ * [Make](#make)
+ * [Testing](#testing)
+
+*****
+
+ * [Appendix A: Hints and Tips](#hints)
+ * [FAQ](#faq)
+ * [Build Performance Tips](#performance)
+ * [Troubleshooting](#troubleshooting)
+ * [Appendix B: GNU Make Information](#gmake)
+ * [Appendix C: Build Environments](#buildenvironments)
+
+*****
+
+
+## Use of Mercurial
+
+The OpenJDK sources are maintained with the revision control system
+[Mercurial](http://mercurial.selenic.com/wiki/Mercurial). If you are new to
+Mercurial, please see the [Beginner Guides](http://mercurial.selenic.com/wiki/
+BeginnersGuides) or refer to the [Mercurial Book](http://hgbook.red-bean.com/).
+The first few chapters of the book provide an excellent overview of Mercurial,
+what it is and how it works.
+
+For using Mercurial with the OpenJDK refer to the [Developer Guide: Installing
+and Configuring Mercurial](http://openjdk.java.net/guide/
+repositories.html#installConfig) section for more information.
+
+
+### Getting the Source
+
+To get the entire set of OpenJDK Mercurial repositories use the script
+`get_source.sh` located in the root repository:
+
+ hg clone http://hg.openjdk.java.net/jdk9/jdk9 YourOpenJDK
+ cd YourOpenJDK
+ bash ./get_source.sh
+
+Once you have all the repositories, keep in mind that each repository is its
+own independent repository. You can also re-run `./get_source.sh` anytime to
+pull over all the latest changesets in all the repositories. This set of
+nested repositories has been given the term "forest" and there are various
+ways to apply the same `hg` command to each of the repositories. For
+example, the script `make/scripts/hgforest.sh` can be used to repeat the
+same `hg` command on every repository, e.g.
+
+ cd YourOpenJDK
+ bash ./make/scripts/hgforest.sh status
+
+
+### Repositories
+
+The set of repositories and what they contain:
+
+ * **. (root)** contains common configure and makefile logic
+ * **hotspot** contains source code and make files for building the OpenJDK
+ Hotspot Virtual Machine
+ * **langtools** contains source code for the OpenJDK javac and language tools
+ * **jdk** contains source code and make files for building the OpenJDK runtime
+ libraries and misc files
+ * **jaxp** contains source code for the OpenJDK JAXP functionality
+ * **jaxws** contains source code for the OpenJDK JAX-WS functionality
+ * **corba** contains source code for the OpenJDK Corba functionality
+ * **nashorn** contains source code for the OpenJDK JavaScript implementation
+
+### Repository Source Guidelines
+
+There are some very basic guidelines:
+
+ * Use of whitespace in source files (.java, .c, .h, .cpp, and .hpp files) is
+ restricted. No TABs, no trailing whitespace on lines, and files should not
+ terminate in more than one blank line.
+ * Files with execute permissions should not be added to the source
+ repositories.
+ * All generated files need to be kept isolated from the files maintained or
+ managed by the source control system. The standard area for generated files
+ is the top level `build/` directory.
+ * The default build process should be to build the product and nothing else,
+ in one form, e.g. a product (optimized), debug (non-optimized, -g plus
+ assert logic), or fastdebug (optimized, -g plus assert logic).
+ * The `.hgignore` file in each repository must exist and should include
+ `^build/`, `^dist/` and optionally any `nbproject/private` directories. **It
+ should NEVER** include anything in the `src/` or `test/` or any managed
+ directory area of a repository.
+ * Directory names and file names should never contain blanks or non-printing
+ characters.
+ * Generated source or binary files should NEVER be added to the repository
+ (that includes `javah` output). There are some exceptions to this rule, in
+ particular with some of the generated configure scripts.
+ * Files not needed for typical building or testing of the repository should
+ not be added to the repository.
+
+*****
+
+
+## Building
+
+The very first step in building the OpenJDK is making sure the system itself
+has everything it needs to do OpenJDK builds. Once a system is setup, it
+generally doesn't need to be done again.
+
+Building the OpenJDK is now done with running a `configure` script which will
+try and find and verify you have everything you need, followed by running
+`make`, e.g.
+
+> **`bash ./configure`**
+> **`make all`**
+
+Where possible the `configure` script will attempt to located the various
+components in the default locations or via component specific variable
+settings. When the normal defaults fail or components cannot be found,
+additional `configure` options may be necessary to help `configure` find the
+necessary tools for the build, or you may need to re-visit the setup of your
+system due to missing software packages.
+
+**NOTE:** The `configure` script file does not have execute permissions and
+will need to be explicitly run with `bash`, see the source guidelines.
+
+*****
+
+
+### System Setup
+
+Before even attempting to use a system to build the OpenJDK there are some very
+basic system setups needed. For all systems:
+
+ * Be sure the GNU make utility is version 3.81 (4.0 on windows) or newer, e.g.
+ run "`make -version`"
+
+
+ * Install a Bootstrap JDK. All OpenJDK builds require access to a previously
+ released JDK called the _bootstrap JDK_ or _boot JDK._ The general rule is
+ that the bootstrap JDK must be an instance of the previous major release of
+ the JDK. In addition, there may be a requirement to use a release at or
+ beyond a particular update level.
+
+ **_Building JDK 9 requires JDK 8. JDK 9 developers should not use JDK 9 as
+ the boot JDK, to ensure that JDK 9 dependencies are not introduced into the
+ parts of the system that are built with JDK 8._**
+
+ The JDK 8 binaries can be downloaded from Oracle's [JDK 8 download
+ site](http://www.oracle.com/technetwork/java/javase/downloads/index.html).
+ For build performance reasons it is very important that this bootstrap JDK
+ be made available on the local disk of the machine doing the build. You
+ should add its `bin` directory to the `PATH` environment variable. If
+ `configure` has any issues finding this JDK, you may need to use the
+ `configure` option `--with-boot-jdk`.
+
+ * Ensure that GNU make, the Bootstrap JDK, and the compilers are all in your
+ PATH environment variable.
+
+And for specific systems:
+
+ * **Linux**
+
+ Install all the software development packages needed including
+ [alsa](#alsa), [freetype](#freetype), [cups](#cups), and
+ [xrender](#xrender). See [specific system packages](#SDBE).
+
+ * **Solaris**
+
+ Install all the software development packages needed including [Studio
+ Compilers](#studio), [freetype](#freetype), [cups](#cups), and
+ [xrender](#xrender). See [specific system packages](#SDBE).
+
+ * **Windows**
+
+ * Install one of [CYGWIN](#cygwin) or [MinGW/MSYS](#msys)
+ * Install [Visual Studio 2013](#vs2013)
+
+ * **Mac OS X**
+
+ Install [XCode 4.5.2](https://developer.apple.com/xcode/) and also
+ install the "Command line tools" found under the preferences pane
+ "Downloads"
+
+
+#### Linux
+
+With Linux, try and favor the system packages over building your own or getting
+packages from other areas. Most Linux builds should be possible with the
+system's available packages.
+
+Note that some Linux systems have a habit of pre-populating your environment
+variables for you, for example `JAVA_HOME` might get pre-defined for you to
+refer to the JDK installed on your Linux system. You will need to unset
+`JAVA_HOME`. It's a good idea to run `env` and verify the environment variables
+you are getting from the default system settings make sense for building the
+OpenJDK.
+
+
+#### Solaris
+
+
+##### Studio Compilers
+
+At a minimum, the [Studio 12 Update 1 Compilers](http://www.oracle.com/
+technetwork/server-storage/solarisstudio/downloads/index.htm) (containing
+version 5.10 of the C and C++ compilers) is required, including specific
+patches.
+
+The Solaris SPARC patch list is:
+
+ * 118683-05: SunOS 5.10: Patch for profiling libraries and assembler
+ * 119963-21: SunOS 5.10: Shared library patch for C++
+ * 120753-08: SunOS 5.10: Microtasking libraries (libmtsk) patch
+ * 128228-09: Sun Studio 12 Update 1: Patch for Sun C++ Compiler
+ * 141860-03: Sun Studio 12 Update 1: Patch for Compiler Common patch for Sun C
+ C++ F77 F95
+ * 141861-05: Sun Studio 12 Update 1: Patch for Sun C Compiler
+ * 142371-01: Sun Studio 12.1 Update 1: Patch for dbx
+ * 143384-02: Sun Studio 12 Update 1: Patch for debuginfo handling
+ * 143385-02: Sun Studio 12 Update 1: Patch for Compiler Common patch for Sun C
+ C++ F77 F95
+ * 142369-01: Sun Studio 12.1: Patch for Performance Analyzer Tools
+
+The Solaris X86 patch list is:
+
+ * 119961-07: SunOS 5.10_x86, x64, Patch for profiling libraries and assembler
+ * 119964-21: SunOS 5.10_x86: Shared library patch for C++\_x86
+ * 120754-08: SunOS 5.10_x86: Microtasking libraries (libmtsk) patch
+ * 141858-06: Sun Studio 12 Update 1_x86: Sun Compiler Common patch for x86
+ backend
+ * 128229-09: Sun Studio 12 Update 1_x86: Patch for C++ Compiler
+ * 142363-05: Sun Studio 12 Update 1_x86: Patch for C Compiler
+ * 142368-01: Sun Studio 12.1_x86: Patch for Performance Analyzer Tools
+
+Place the `bin` directory in `PATH`.
+
+The Oracle Solaris Studio Express compilers at: [Oracle Solaris Studio Express
+Download site](http://www.oracle.com/technetwork/server-storage/solarisstudio/
+downloads/index-jsp-142582.html) are also an option, although these compilers
+have not been extensively used yet.
+
+
+#### Windows
+
+##### Windows Unix Toolkit
+
+Building on Windows requires a Unix-like environment, notably a Unix-like
+shell. There are several such environments available of which
+[Cygwin](http://www.cygwin.com/) and
+[MinGW/MSYS](http://www.mingw.org/wiki/MSYS) are currently supported for the
+OpenJDK build. One of the differences of these systems from standard Windows
+tools is the way they handle Windows path names, particularly path names which
+contain spaces, backslashes as path separators and possibly drive letters.
+Depending on the use case and the specifics of each environment these path
+problems can be solved by a combination of quoting whole paths, translating
+backslashes to forward slashes, escaping backslashes with additional
+backslashes and translating the path names to their ["8.3"
+version](http://en.wikipedia.org/wiki/8.3_filename).
+
+
+###### CYGWIN
+
+CYGWIN is an open source, Linux-like environment which tries to emulate a
+complete POSIX layer on Windows. It tries to be smart about path names and can
+usually handle all kinds of paths if they are correctly quoted or escaped
+although internally it maps drive letters `:` to a virtual directory
+`/cygdrive/`.
+
+You can always use the `cygpath` utility to map pathnames with spaces or the
+backslash character into the `C:/` style of pathname (called 'mixed'), e.g.
+`cygpath -s -m ""`.
+
+Note that the use of CYGWIN creates a unique problem with regards to setting
+[`PATH`](#path). Normally on Windows the `PATH` variable contains directories
+separated with the ";" character (Solaris and Linux use ":"). With CYGWIN, it
+uses ":", but that means that paths like "C:/path" cannot be placed in the
+CYGWIN version of `PATH` and instead CYGWIN uses something like
+`/cygdrive/c/path` which CYGWIN understands, but only CYGWIN understands.
+
+The OpenJDK build requires CYGWIN version 1.7.16 or newer. Information about
+CYGWIN can be obtained from the CYGWIN website at
+[www.cygwin.com](http://www.cygwin.com).
+
+By default CYGWIN doesn't install all the tools required for building the
+OpenJDK. Along with the default installation, you need to install the following
+tools.
+
+>
+
+
+
Binary Name
+
Category
+
Package
+
Description
+
+
+
+
+
ar.exe
+
Devel
+
binutils
+
The GNU assembler, linker and binary utilities
+
+
+
make.exe
+
Devel
+
make
+
The GNU version of the 'make' utility built for CYGWIN
+
+
+
m4.exe
+
Interpreters
+
m4
+
GNU implementation of the traditional Unix macro processor
+
+
+
cpio.exe
+
Utils
+
cpio
+
A program to manage archives of files
+
+
+
gawk.exe
+
Utils
+
awk
+
Pattern-directed scanning and processing language
+
+
+
file.exe
+
Utils
+
file
+
Determines file type using 'magic' numbers
+
+
+
zip.exe
+
Archive
+
zip
+
Package and compress (archive) files
+
+
+
unzip.exe
+
Archive
+
unzip
+
Extract compressed files in a ZIP archive
+
+
+
free.exe
+
System
+
procps
+
Display amount of free and used memory in the system
+
+
+
+
+Note that the CYGWIN software can conflict with other non-CYGWIN software on
+your Windows system. CYGWIN provides a [FAQ](http://cygwin.com/faq/
+faq.using.html) for known issues and problems, of particular interest is the
+section on [BLODA (applications that interfere with
+CYGWIN)](http://cygwin.com/faq/faq.using.html#faq.using.bloda).
+
+
+###### MinGW/MSYS
+
+MinGW ("Minimalist GNU for Windows") is a collection of free Windows specific
+header files and import libraries combined with GNU toolsets that allow one to
+produce native Windows programs that do not rely on any 3rd-party C runtime
+DLLs. MSYS is a supplement to MinGW which allows building applications and
+programs which rely on traditional UNIX tools to be present. Among others this
+includes tools like `bash` and `make`. See [MinGW/MSYS](http://www.mingw.org/
+wiki/MSYS) for more information.
+
+Like Cygwin, MinGW/MSYS can handle different types of path formats. They are
+internally converted to paths with forward slashes and drive letters
+`:` replaced by a virtual directory `/`. Additionally, MSYS
+automatically detects binaries compiled for the MSYS environment and feeds them
+with the internal, Unix-style path names. If native Windows applications are
+called from within MSYS programs their path arguments are automatically
+converted back to Windows style path names with drive letters and backslashes
+as path separators. This may cause problems for Windows applications which use
+forward slashes as parameter separator (e.g. `cl /nologo /I`) because MSYS may
+wrongly [replace such parameters by drive letters](http://mingw.org/wiki/
+Posix_path_conversion).
+
+In addition to the tools which will be installed by default, you have to
+manually install the `msys-zip` and `msys-unzip` packages. This can be easily
+done with the MinGW command line installer:
+
+ mingw-get.exe install msys-zip
+ mingw-get.exe install msys-unzip
+
+
+##### Visual Studio 2013 Compilers
+
+The 32-bit and 64-bit OpenJDK Windows build requires Microsoft Visual Studio
+C++ 2013 (VS2013) Professional Edition or Express compiler. The compiler and
+other tools are expected to reside in the location defined by the variable
+`VS120COMNTOOLS` which is set by the Microsoft Visual Studio installer.
+
+Only the C++ part of VS2013 is needed. Try to let the installation go to the
+default install directory. Always reboot your system after installing VS2013.
+The system environment variable VS120COMNTOOLS should be set in your
+environment.
+
+Make sure that TMP and TEMP are also set in the environment and refer to
+Windows paths that exist, like `C:\temp`, not `/tmp`, not `/cygdrive/c/temp`,
+and not `C:/temp`. `C:\temp` is just an example, it is assumed that this area
+is private to the user, so by default after installs you should see a unique
+user path in these variables.
+
+
+#### Mac OS X
+
+Make sure you get the right XCode version.
+
+*****
+
+
+### Configure
+
+The basic invocation of the `configure` script looks like:
+
+> **`bash ./configure [options]`**
+
+This will create an output directory containing the "configuration" and setup
+an area for the build result. This directory typically looks like:
+
+> **`build/linux-x64-normal-server-release`**
+
+`configure` will try to figure out what system you are running on and where all
+necessary build components are. If you have all prerequisites for building
+installed, it should find everything. If it fails to detect any component
+automatically, it will exit and inform you about the problem. When this
+happens, read more below in [the `configure` options](#configureoptions).
+
+Some examples:
+
+> **Windows 32bit build with freetype specified:**
+> `bash ./configure --with-freetype=/cygdrive/c/freetype-i586 --with-target-
+bits=32`
+
+> **Debug 64bit Build:**
+> `bash ./configure --enable-debug --with-target-bits=64`
+
+
+#### Configure Options
+
+Complete details on all the OpenJDK `configure` options can be seen with:
+
+> **`bash ./configure --help=short`**
+
+Use `-help` to see all the `configure` options available. You can generate any
+number of different configurations, e.g. debug, release, 32, 64, etc.
+
+Some of the more commonly used `configure` options are:
+
+> **`--enable-debug`**
+> set the debug level to fastdebug (this is a shorthand for `--with-debug-
+ level=fastdebug`)
+
+
+> **`--with-alsa=`**_path_
+> select the location of the Advanced Linux Sound Architecture (ALSA)
+
+> Version 0.9.1 or newer of the ALSA files are required for building the
+ OpenJDK on Linux. These Linux files are usually available from an "alsa" of
+ "libasound" development package, and it's highly recommended that you try
+ and use the package provided by the particular version of Linux that you are
+ using.
+
+> **`--with-boot-jdk=`**_path_
+> select the [Bootstrap JDK](#bootjdk)
+
+> **`--with-boot-jdk-jvmargs=`**"_args_"
+> provide the JVM options to be used to run the [Bootstrap JDK](#bootjdk)
+
+> **`--with-cacerts=`**_path_
+> select the path to the cacerts file.
+
+> See [Certificate Authority on Wikipedia](http://en.wikipedia.org/wiki/
+ Certificate_Authority) for a better understanding of the Certificate
+ Authority (CA). A certificates file named "cacerts" represents a system-wide
+ keystore with CA certificates. In JDK and JRE binary bundles, the "cacerts"
+ file contains root CA certificates from several public CAs (e.g., VeriSign,
+ Thawte, and Baltimore). The source contain a cacerts file without CA root
+ certificates. Formal JDK builders will need to secure permission from each
+ public CA and include the certificates into their own custom cacerts file.
+ Failure to provide a populated cacerts file will result in verification
+ errors of a certificate chain during runtime. By default an empty cacerts
+ file is provided and that should be fine for most JDK developers.
+
+
+> **`--with-cups=`**_path_
+> select the CUPS install location
+
+> The Common UNIX Printing System (CUPS) Headers are required for building the
+ OpenJDK on Solaris and Linux. The Solaris header files can be obtained by
+ installing the package **SFWcups** from the Solaris Software Companion
+ CD/DVD, these often will be installed into the directory `/opt/sfw/cups`.
+
+> The CUPS header files can always be downloaded from
+ [www.cups.org](http://www.cups.org).
+
+> **`--with-cups-include=`**_path_
+> select the CUPS include directory location
+
+> **`--with-debug-level=`**_level_
+> select the debug information level of release, fastdebug, or slowdebug
+
+> **`--with-dev-kit=`**_path_
+> select location of the compiler install or developer install location
+
+
+> **`--with-freetype=`**_path_
+> select the freetype files to use.
+
+> Expecting the freetype libraries under `lib/` and the headers under
+ `include/`.
+
+> Version 2.3 or newer of FreeType is required. On Unix systems required files
+ can be available as part of your distribution (while you still may need to
+ upgrade them). Note that you need development version of package that
+ includes both the FreeType library and header files.
+
+> You can always download latest FreeType version from the [FreeType
+ website](http://www.freetype.org). Building the freetype 2 libraries from
+ scratch is also possible, however on Windows refer to the [Windows FreeType
+ DLL build instructions](http://freetype.freedesktop.org/wiki/FreeType_DLL).
+
+> Note that by default FreeType is built with byte code hinting support
+ disabled due to licensing restrictions. In this case, text appearance and
+ metrics are expected to differ from Sun's official JDK build. See the
+ [SourceForge FreeType2 Home Page](http://freetype.sourceforge.net/freetype2)
+ for more information.
+
+> **`--with-import-hotspot=`**_path_
+> select the location to find hotspot binaries from a previous build to avoid
+ building hotspot
+
+> **`--with-target-bits=`**_arg_
+> select 32 or 64 bit build
+
+> **`--with-jvm-variants=`**_variants_
+> select the JVM variants to build from, comma separated list that can
+ include: server, client, kernel, zero and zeroshark
+
+> **`--with-memory-size=`**_size_
+> select the RAM size that GNU make will think this system has
+
+> **`--with-msvcr-dll=`**_path_
+> select the `msvcr100.dll` file to include in the Windows builds (C/C++
+ runtime library for Visual Studio).
+
+> This is usually picked up automatically from the redist directories of
+ Visual Studio 2013.
+
+> **`--with-num-cores=`**_cores_
+> select the number of cores to use (processor count or CPU count)
+
+
+> **`--with-x=`**_path_
+> select the location of the X11 and xrender files.
+
+> The XRender Extension Headers are required for building the OpenJDK on
+ Solaris and Linux. The Linux header files are usually available from a
+ "Xrender" development package, it's recommended that you try and use the
+ package provided by the particular distribution of Linux that you are using.
+ The Solaris XRender header files is included with the other X11 header files
+ in the package **SFWxwinc** on new enough versions of Solaris and will be
+ installed in `/usr/X11/include/X11/extensions/Xrender.h` or
+ `/usr/openwin/share/include/X11/extensions/Xrender.h`
+
+*****
+
+
+### Make
+
+The basic invocation of the `make` utility looks like:
+
+> **`make all`**
+
+This will start the build to the output directory containing the
+"configuration" that was created by the `configure` script. Run `make help` for
+more information on the available targets.
+
+There are some of the make targets that are of general interest:
+
+> _empty_
+> build everything but no images
+
+> **`all`**
+> build everything including images
+
+> **`all-conf`**
+> build all configurations
+
+> **`images`**
+> create complete j2sdk and j2re images
+
+> **`install`**
+> install the generated images locally, typically in `/usr/local`
+
+> **`clean`**
+> remove all files generated by make, but not those generated by `configure`
+
+> **`dist-clean`**
+> remove all files generated by both and `configure` (basically killing the
+ configuration)
+
+> **`help`**
+> give some help on using `make`, including some interesting make targets
+
+*****
+
+
+## Testing
+
+When the build is completed, you should see the generated binaries and
+associated files in the `j2sdk-image` directory in the output directory. In
+particular, the `build/*/images/j2sdk-image/bin` directory should contain
+executables for the OpenJDK tools and utilities for that configuration. The
+testing tool `jtreg` will be needed and can be found at: [the jtreg
+site](http://openjdk.java.net/jtreg/). The provided regression tests in the
+repositories can be run with the command:
+
+> **``cd test && make PRODUCT_HOME=`pwd`/../build/*/images/j2sdk-image all``**
+
+*****
+
+
+## Appendix A: Hints and Tips
+
+
+### FAQ
+
+**Q:** The `generated-configure.sh` file looks horrible! How are you going to
+edit it?
+**A:** The `generated-configure.sh` file is generated (think "compiled") by the
+autoconf tools. The source code is in `configure.ac` and various .m4 files in
+common/autoconf, which are much more readable.
+
+**Q:** Why is the `generated-configure.sh` file checked in, if it is
+generated?
+**A:** If it was not generated, every user would need to have the autoconf
+tools installed, and re-generate the `configure` file as the first step. Our
+goal is to minimize the work needed to be done by the user to start building
+OpenJDK, and to minimize the number of external dependencies required.
+
+**Q:** Do you require a specific version of autoconf for regenerating
+`generated-configure.sh`?
+**A:** Yes, version 2.69 is required and should be easy enough to aquire on all
+supported operating systems. The reason for this is to avoid large spurious
+changes in `generated-configure.sh`.
+
+**Q:** How do you regenerate `generated-configure.sh` after making changes to
+the input files?
+**A:** Regnerating `generated-configure.sh` should always be done using the
+script `common/autoconf/autogen.sh` to ensure that the correct files get
+updated. This script should also be run after mercurial tries to merge
+`generated-configure.sh` as a merge of the generated file is not guaranteed to
+be correct.
+
+**Q:** What are the files in `common/makefiles/support/*` for? They look like
+gibberish.
+**A:** They are a somewhat ugly hack to compensate for command line length
+limitations on certain platforms (Windows, Solaris). Due to a combination of
+limitations in make and the shell, command lines containing too many files will
+not work properly. These helper files are part of an elaborate hack that will
+compress the command line in the makefile and then uncompress it safely. We're
+not proud of it, but it does fix the problem. If you have any better
+suggestions, we're all ears! :-)
+
+**Q:** I want to see the output of the commands that make runs, like in the old
+build. How do I do that?
+**A:** You specify the `LOG` variable to make. There are several log levels:
+
+ * **`warn`** -- Default and very quiet.
+ * **`info`** -- Shows more progress information than warn.
+ * **`debug`** -- Echos all command lines and prints all macro calls for
+ compilation definitions.
+ * **`trace`** -- Echos all $(shell) command lines as well.
+
+**Q:** When do I have to re-run `configure`?
+**A:** Normally you will run `configure` only once for creating a
+configuration. You need to re-run configuration only if you want to change any
+configuration options, or if you pull down changes to the `configure` script.
+
+**Q:** I have added a new source file. Do I need to modify the makefiles?
+**A:** Normally, no. If you want to create e.g. a new native library, you will
+need to modify the makefiles. But for normal file additions or removals, no
+changes are needed. There are certan exceptions for some native libraries where
+the source files are spread over many directories which also contain sources
+for other libraries. In these cases it was simply easier to create include
+lists rather than excludes.
+
+**Q:** When I run `configure --help`, I see many strange options, like
+`--dvidir`. What is this?
+**A:** Configure provides a slew of options by default, to all projects that
+use autoconf. Most of them are not used in OpenJDK, so you can safely ignore
+them. To list only OpenJDK specific features, use `configure --help=short`
+instead.
+
+**Q:** `configure` provides OpenJDK-specific features such as `--with-
+builddeps-server` that are not described in this document. What about those?
+**A:** Try them out if you like! But be aware that most of these are
+experimental features. Many of them don't do anything at all at the moment; the
+option is just a placeholder. Others depend on pieces of code or infrastructure
+that is currently not ready for prime time.
+
+**Q:** How will you make sure you don't break anything?
+**A:** We have a script that compares the result of the new build system with
+the result of the old. For most part, we aim for (and achieve) byte-by-byte
+identical output. There are however technical issues with e.g. native binaries,
+which might differ in a byte-by-byte comparison, even when building twice with
+the old build system. For these, we compare relevant aspects (e.g. the symbol
+table and file size). Note that we still don't have 100% equivalence, but we're
+close.
+
+**Q:** I noticed this thing X in the build that looks very broken by design.
+Why don't you fix it?
+**A:** Our goal is to produce a build output that is as close as technically
+possible to the old build output. If things were weird in the old build, they
+will be weird in the new build. Often, things were weird before due to
+obscurity, but in the new build system the weird stuff comes up to the surface.
+The plan is to attack these things at a later stage, after the new build system
+is established.
+
+**Q:** The code in the new build system is not that well-structured. Will you
+fix this?
+**A:** Yes! The new build system has grown bit by bit as we converted the old
+system. When all of the old build system is converted, we can take a step back
+and clean up the structure of the new build system. Some of this we plan to do
+before replacing the old build system and some will need to wait until after.
+
+**Q:** Is anything able to use the results of the new build's default make
+target?
+**A:** Yes, this is the minimal (or roughly minimal) set of compiled output
+needed for a developer to actually execute the newly built JDK. The idea is
+that in an incremental development fashion, when doing a normal make, you
+should only spend time recompiling what's changed (making it purely
+incremental) and only do the work that's needed to actually run and test your
+code. The packaging stuff that is part of the `images` target is not needed for
+a normal developer who wants to test his new code. Even if it's quite fast,
+it's still unnecessary. We're targeting sub-second incremental rebuilds! ;-)
+(Or, well, at least single-digit seconds...)
+
+**Q:** I usually set a specific environment variable when building, but I can't
+find the equivalent in the new build. What should I do?
+**A:** It might very well be that we have neglected to add support for an
+option that was actually used from outside the build system. Email us and we
+will add support for it!
+
+
+### Build Performance Tips
+
+Building OpenJDK requires a lot of horsepower. Some of the build tools can be
+adjusted to utilize more or less of resources such as parallel threads and
+memory. The `configure` script analyzes your system and selects reasonable
+values for such options based on your hardware. If you encounter resource
+problems, such as out of memory conditions, you can modify the detected values
+with:
+
+ * **`--with-num-cores`** -- number of cores in the build system, e.g.
+ `--with-num-cores=8`
+ * **`--with-memory-size`** -- memory (in MB) available in the build system,
+ e.g. `--with-memory-size=1024`
+
+It might also be necessary to specify the JVM arguments passed to the Bootstrap
+JDK, using e.g. `--with-boot-jdk-jvmargs="-Xmx8G -enableassertions"`. Doing
+this will override the default JVM arguments passed to the Bootstrap JDK.
+
+One of the top goals of the new build system is to improve the build
+performance and decrease the time needed to build. This will soon also apply to
+the java compilation when the Smart Javac wrapper is fully supported.
+
+At the end of a successful execution of `configure`, you will get a performance
+summary, indicating how well the build will perform. Here you will also get
+performance hints. If you want to build fast, pay attention to those!
+
+#### Building with ccache
+
+The OpenJDK build supports building with ccache when using gcc or clang. Using
+ccache can radically speed up compilation of native code if you often rebuild
+the same sources. Your milage may vary however so we recommend evaluating it
+for yourself. To enable it, make sure it's on the path and configure with
+`--enable-ccache`.
+
+#### Building on local disk
+
+If you are using network shares, e.g. via NFS, for your source code, make sure
+the build directory is situated on local disk. The performance penalty is
+extremely high for building on a network share, close to unusable.
+
+#### Building only one JVM
+
+The old build builds multiple JVMs on 32-bit systems (client and server; and on
+Windows kernel as well). In the new build we have changed this default to only
+build server when it's available. This improves build times for those not
+interested in multiple JVMs. To mimic the old behavior on platforms that
+support it, use `--with-jvm-variants=client,server`.
+
+#### Selecting the number of cores to build on
+
+By default, `configure` will analyze your machine and run the make process in
+parallel with as many threads as you have cores. This behavior can be
+overridden, either "permanently" (on a `configure` basis) using
+`--with-num-cores=N` or for a single build only (on a make basis), using
+`make JOBS=N`.
+
+If you want to make a slower build just this time, to save some CPU power for
+other processes, you can run e.g. `make JOBS=2`. This will force the makefiles
+to only run 2 parallel processes, or even `make JOBS=1` which will disable
+parallelism.
+
+If you want to have it the other way round, namely having slow builds default
+and override with fast if you're impatient, you should call `configure` with
+`--with-num-cores=2`, making 2 the default. If you want to run with more cores,
+run `make JOBS=8`
+
+
+### Troubleshooting
+
+#### Solving build problems
+
+If the build fails (and it's not due to a compilation error in a source file
+you've changed), the first thing you should do is to re-run the build with more
+verbosity. Do this by adding `LOG=debug` to your make command line.
+
+The build log (with both stdout and stderr intermingled, basically the same as
+you see on your console) can be found as `build.log` in your build directory.
+
+You can ask for help on build problems with the new build system on either the
+[build-dev](http://mail.openjdk.java.net/mailman/listinfo/build-dev) or the
+[build-infra-dev](http://mail.openjdk.java.net/mailman/listinfo/build-infra-dev)
+mailing lists. Please include the relevant parts of the build log.
+
+A build can fail for any number of reasons. Most failures are a result of
+trying to build in an environment in which all the pre-build requirements have
+not been met. The first step in troubleshooting a build failure is to recheck
+that you have satisfied all the pre-build requirements for your platform.
+Scanning the `configure` log is a good first step, making sure that what it
+found makes sense for your system. Look for strange error messages or any
+difficulties that `configure` had in finding things.
+
+Some of the more common problems with builds are briefly described below, with
+suggestions for remedies.
+
+ * **Corrupted Bundles on Windows:**
+ Some virus scanning software has been known to corrupt the downloading of
+ zip bundles. It may be necessary to disable the 'on access' or 'real time'
+ virus scanning features to prevent this corruption. This type of 'real time'
+ virus scanning can also slow down the build process significantly.
+ Temporarily disabling the feature, or excluding the build output directory
+ may be necessary to get correct and faster builds.
+
+ * **Slow Builds:**
+ If your build machine seems to be overloaded from too many simultaneous C++
+ compiles, try setting the `JOBS=1` on the `make` command line. Then try
+ increasing the count slowly to an acceptable level for your system. Also:
+
+ Creating the javadocs can be very slow, if you are running javadoc, consider
+ skipping that step.
+
+ Faster CPUs, more RAM, and a faster DISK usually helps. The VM build tends
+ to be CPU intensive (many C++ compiles), and the rest of the JDK will often
+ be disk intensive.
+
+ Faster compiles are possible using a tool called
+ [ccache](http://ccache.samba.org/).
+
+ * **File time issues:**
+ If you see warnings that refer to file time stamps, e.g.
+
+ > _Warning message:_ ` File 'xxx' has modification time in the future.`
+ > _Warning message:_ ` Clock skew detected. Your build may be incomplete.`
+
+ These warnings can occur when the clock on the build machine is out of sync
+ with the timestamps on the source files. Other errors, apparently unrelated
+ but in fact caused by the clock skew, can occur along with the clock skew
+ warnings. These secondary errors may tend to obscure the fact that the true
+ root cause of the problem is an out-of-sync clock.
+
+ If you see these warnings, reset the clock on the build machine, run
+ "`gmake clobber`" or delete the directory containing the build output, and
+ restart the build from the beginning.
+
+ * **Error message: `Trouble writing out table to disk`**
+ Increase the amount of swap space on your build machine. This could be
+ caused by overloading the system and it may be necessary to use:
+
+ > `make JOBS=1`
+
+ to reduce the load on the system.
+
+ * **Error Message: `libstdc++ not found`:**
+ This is caused by a missing libstdc++.a library. This is installed as part
+ of a specific package (e.g. libstdc++.so.devel.386). By default some 64-bit
+ Linux versions (e.g. Fedora) only install the 64-bit version of the
+ libstdc++ package. Various parts of the JDK build require a static link of
+ the C++ runtime libraries to allow for maximum portability of the built
+ images.
+
+ * **Linux Error Message: `cannot restore segment prot after reloc`**
+ This is probably an issue with SELinux (See [SELinux on
+ Wikipedia](http://en.wikipedia.org/wiki/SELinux)). Parts of the VM is built
+ without the `-fPIC` for performance reasons.
+
+ To completely disable SELinux:
+
+ 1. `$ su root`
+ 2. `# system-config-securitylevel`
+ 3. `In the window that appears, select the SELinux tab`
+ 4. `Disable SELinux`
+
+ Alternatively, instead of completely disabling it you could disable just
+ this one check.
+
+ 1. Select System->Administration->SELinux Management
+ 2. In the SELinux Management Tool which appears, select "Boolean" from the
+ menu on the left
+ 3. Expand the "Memory Protection" group
+ 4. Check the first item, labeled "Allow all unconfined executables to use
+ libraries requiring text relocation ..."
+
+ * **Windows Error Messages:**
+ `*** fatal error - couldn't allocate heap, ... `
+ `rm fails with "Directory not empty"`
+ `unzip fails with "cannot create ... Permission denied"`
+ `unzip fails with "cannot create ... Error 50"`
+
+ The CYGWIN software can conflict with other non-CYGWIN software. See the
+ CYGWIN FAQ section on [BLODA (applications that interfere with
+ CYGWIN)](http://cygwin.com/faq/faq.using.html#faq.using.bloda).
+
+ * **Windows Error Message: `spawn failed`**
+ Try rebooting the system, or there could be some kind of issue with the disk
+ or disk partition being used. Sometimes it comes with a "Permission Denied"
+ message.
+
+*****
+
+
+## Appendix B: GNU make
+
+The Makefiles in the OpenJDK are only valid when used with the GNU version of
+the utility command `make` (usually called `gmake` on Solaris). A few notes
+about using GNU make:
+
+ * You need GNU make version 3.81 or newer. On Windows 4.0 or newer is
+ recommended. If the GNU make utility on your systems is not of a suitable
+ version, see "[Building GNU make](#buildgmake)".
+ * Place the location of the GNU make binary in the `PATH`.
+ * **Solaris:** Do NOT use `/usr/bin/make` on Solaris. If your Solaris system
+ has the software from the Solaris Developer Companion CD installed, you
+ should try and use `gmake` which will be located in either the `/usr/bin`,
+ `/opt/sfw/bin` or `/usr/sfw/bin` directory.
+ * **Windows:** Make sure you start your build inside a bash shell.
+ * **Mac OS X:** The XCode "command line tools" must be installed on your Mac.
+
+Information on GNU make, and access to ftp download sites, are available on the
+[GNU make web site ](http://www.gnu.org/software/make/make.html). The latest
+source to GNU make is available at
+[ftp.gnu.org/pub/gnu/make/](http://ftp.gnu.org/pub/gnu/make/).
+
+
+### Building GNU make
+
+First step is to get the GNU make 3.81 or newer source from
+[ftp.gnu.org/pub/gnu/make/](http://ftp.gnu.org/pub/gnu/make/). Building is a
+little different depending on the OS but is basically done with:
+
+ bash ./configure
+ make
+
+*****
+
+
+## Appendix C: Build Environments
+
+### Minimum Build Environments
+
+This file often describes specific requirements for what we call the "minimum
+build environments" (MBE) for this specific release of the JDK. What is listed
+below is what the Oracle Release Engineering Team will use to build the Oracle
+JDK product. Building with the MBE will hopefully generate the most compatible
+bits that install on, and run correctly on, the most variations of the same
+base OS and hardware architecture. In some cases, these represent what is often
+called the least common denominator, but each Operating System has different
+aspects to it.
+
+In all cases, the Bootstrap JDK version minimum is critical, we cannot
+guarantee builds will work with older Bootstrap JDK's. Also in all cases, more
+RAM and more processors is better, the minimums listed below are simply
+recommendations.
+
+With Solaris and Mac OS X, the version listed below is the oldest release we
+can guarantee builds and works, and the specific version of the compilers used
+could be critical.
+
+With Windows the critical aspect is the Visual Studio compiler used, which due
+to it's runtime, generally dictates what Windows systems can do the builds and
+where the resulting bits can be used.
+
+**NOTE: We expect a change here off these older Windows OS releases and to a
+'less older' one, probably Windows 2008R2 X64.**
+
+With Linux, it was just a matter of picking a stable distribution that is a
+good representative for Linux in general.
+
+**NOTE: We expect a change here from Fedora 9 to something else, but it has not
+been completely determined yet, possibly Ubuntu 12.04 X64, unbiased community
+feedback would be welcome on what a good choice would be here.**
+
+It is understood that most developers will NOT be using these specific
+versions, and in fact creating these specific versions may be difficult due to
+the age of some of this software. It is expected that developers are more often
+using the more recent releases and distributions of these operating systems.
+
+Compilation problems with newer or different C/C++ compilers is a common
+problem. Similarly, compilation problems related to changes to the
+`/usr/include` or system header files is also a common problem with older,
+newer, or unreleased OS versions. Please report these types of problems as bugs
+so that they can be dealt with accordingly.
+
+>
+
+
+
Base OS and Architecture
+
OS
+
C/C++ Compiler
+
Bootstrap JDK
+
Processors
+
RAM Minimum
+
DISK Needs
+
+
+
+
+
Linux X86 (32-bit) and X64 (64-bit)
+
Oracle Enterprise Linux 6.4
+
gcc 4.8.2
+
JDK 8
+
2 or more
+
1 GB
+
6 GB
+
+
+
Solaris SPARCV9 (64-bit)
+
Solaris 10 Update 10
+
Studio 12 Update 3 + patches
+
JDK 8
+
4 or more
+
4 GB
+
8 GB
+
+
+
Solaris X64 (64-bit)
+
Solaris 10 Update 10
+
Studio 12 Update 3 + patches
+
JDK 8
+
4 or more
+
4 GB
+
8 GB
+
+
+
Windows X86 (32-bit)
+
Windows Server 2012 R2 x64
+
Microsoft Visual Studio C++ 2013 Professional Edition
+
JDK 8
+
2 or more
+
2 GB
+
6 GB
+
+
+
Windows X64 (64-bit)
+
Windows Server 2012 R2 x64
+
Microsoft Visual Studio C++ 2013 Professional Edition
+
JDK 8
+
2 or more
+
2 GB
+
6 GB
+
+
+
Mac OS X X64 (64-bit)
+
Mac OS X 10.9 "Mavericks"
+
XCode 5.1.1 or newer
+
JDK 8
+
2 or more
+
4 GB
+
6 GB
+
+
+
+
+*****
+
+
+### Specific Developer Build Environments
+
+We won't be listing all the possible environments, but we will try to provide
+what information we have available to us.
+
+**NOTE: The community can help out by updating this part of the document.**
+
+#### Fedora
+
+After installing the latest [Fedora](http://fedoraproject.org) you need to
+install several build dependencies. The simplest way to do it is to execute the
+following commands as user `root`:
+
+ yum-builddep java-1.7.0-openjdk
+ yum install gcc gcc-c++
+
+In addition, it's necessary to set a few environment variables for the build:
+
+ export LANG=C
+ export PATH="/usr/lib/jvm/java-openjdk/bin:${PATH}"
+
+#### CentOS 5.5
+
+After installing [CentOS 5.5](http://www.centos.org/) you need to make sure you
+have the following Development bundles installed:
+
+ * Development Libraries
+ * Development Tools
+ * Java Development
+ * X Software Development (Including XFree86-devel)
+
+Plus the following packages:
+
+ * cups devel: Cups Development Package
+ * alsa devel: Alsa Development Package
+ * Xi devel: libXi.so Development Package
+
+The freetype 2.3 packages don't seem to be available, but the freetype 2.3
+sources can be downloaded, built, and installed easily enough from [the
+freetype site](http://downloads.sourceforge.net/freetype). Build and install
+with something like:
+
+ bash ./configure
+ make
+ sudo -u root make install
+
+Mercurial packages could not be found easily, but a Google search should find
+ones, and they usually include Python if it's needed.
+
+#### Debian 5.0 (Lenny)
+
+After installing [Debian](http://debian.org) 5 you need to install several
+build dependencies. The simplest way to install the build dependencies is to
+execute the following commands as user `root`:
+
+ aptitude build-dep openjdk-7
+ aptitude install openjdk-7-jdk libmotif-dev
+
+In addition, it's necessary to set a few environment variables for the build:
+
+ export LANG=C
+ export PATH="/usr/lib/jvm/java-7-openjdk/bin:${PATH}"
+
+#### Ubuntu 12.04
+
+After installing [Ubuntu](http://ubuntu.org) 12.04 you need to install several
+build dependencies. The simplest way to do it is to execute the following
+commands:
+
+ sudo aptitude build-dep openjdk-7
+ sudo aptitude install openjdk-7-jdk
+
+In addition, it's necessary to set a few environment variables for the build:
+
+ export LANG=C
+ export PATH="/usr/lib/jvm/java-7-openjdk/bin:${PATH}"
+
+#### OpenSUSE 11.1
+
+After installing [OpenSUSE](http://opensuse.org) 11.1 you need to install
+several build dependencies. The simplest way to install the build dependencies
+is to execute the following commands:
+
+ sudo zypper source-install -d java-1_7_0-openjdk
+ sudo zypper install make
+
+In addition, it is necessary to set a few environment variables for the build:
+
+ export LANG=C
+ export PATH="/usr/lib/jvm/java-1.7.0-openjdk/bin:$[PATH}"
+
+Finally, you need to unset the `JAVA_HOME` environment variable:
+
+ export -n JAVA_HOME`
+
+#### Mandriva Linux One 2009 Spring
+
+After installing [Mandriva](http://mandriva.org) 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 `root`:
+
+ urpmi java-1.7.0-openjdk-devel make gcc gcc-c++ freetype-devel zip unzip
+ libcups2-devel libxrender1-devel libalsa2-devel libstc++-static-devel
+ libxtst6-devel libxi-devel
+
+In addition, it is necessary to set a few environment variables for the build:
+
+ export LANG=C
+ export PATH="/usr/lib/jvm/java-1.7.0-openjdk/bin:${PATH}"
+
+#### OpenSolaris 2009.06
+
+After installing [OpenSolaris](http://opensolaris.org) 2009.06 you need to
+install several build dependencies. The simplest way to install the build
+dependencies is to execute the following commands:
+
+ pfexec pkg install SUNWgmake SUNWj7dev sunstudioexpress SUNWcups SUNWzip
+ SUNWunzip SUNWxwhl SUNWxorg-headers SUNWaudh SUNWfreetype2
+
+In addition, it is necessary to set a few environment variables for the build:
+
+ export LANG=C
+ export PATH="/opt/SunStudioExpress/bin:${PATH}"
+
+*****
+
+End of the OpenJDK build README document.
+
+Please come again!
diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4
index a5d5797f584..fa15ac3bf9f 100644
--- a/common/autoconf/basics.m4
+++ b/common/autoconf/basics.m4
@@ -410,6 +410,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS],
BASIC_REQUIRE_PROGS(NAWK, [nawk gawk awk])
BASIC_REQUIRE_PROGS(PRINTF, printf)
BASIC_REQUIRE_PROGS(RM, rm)
+ BASIC_REQUIRE_PROGS(RMDIR, rmdir)
BASIC_REQUIRE_PROGS(SH, sh)
BASIC_REQUIRE_PROGS(SORT, sort)
BASIC_REQUIRE_PROGS(TAIL, tail)
diff --git a/common/autoconf/boot-jdk.m4 b/common/autoconf/boot-jdk.m4
index 35f5d63d39b..524103eb013 100644
--- a/common/autoconf/boot-jdk.m4
+++ b/common/autoconf/boot-jdk.m4
@@ -305,6 +305,16 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK],
BOOT_JDK_SOURCETARGET="-source 8 -target 8"
AC_SUBST(BOOT_JDK_SOURCETARGET)
AC_SUBST(JAVAC_FLAGS)
+
+ # Check if the boot jdk is 32 or 64 bit
+ if "$JAVA" -d64 -version > /dev/null 2>&1; then
+ BOOT_JDK_BITS="64"
+ else
+ BOOT_JDK_BITS="32"
+ fi
+ AC_MSG_CHECKING([if Boot JDK is 32 or 64 bits])
+ AC_MSG_RESULT([$BOOT_JDK_BITS])
+ AC_SUBST(BOOT_JDK_BITS)
])
AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS],
@@ -341,7 +351,7 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS],
# Maximum amount of heap memory.
# Maximum stack size.
JVM_MAX_HEAP=`expr $MEMORY_SIZE / 2`
- if test "x$BUILD_NUM_BITS" = x32; then
+ if test "x$BOOT_JDK_BITS" = "x32"; then
if test "$JVM_MAX_HEAP" -gt "1100"; then
JVM_MAX_HEAP=1100
elif test "$JVM_MAX_HEAP" -lt "512"; then
@@ -349,10 +359,7 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS],
fi
STACK_SIZE=768
else
- # Running Javac on a JVM on a 64-bit machine, takes more space since 64-bit
- # pointers are used. Apparently, we need to increase the heap and stack
- # space for the jvm. More specifically, when running javac to build huge
- # jdk batch
+ # Running a 64 bit JVM allows for and requires a bigger heap
if test "$JVM_MAX_HEAP" -gt "1600"; then
JVM_MAX_HEAP=1600
elif test "$JVM_MAX_HEAP" -lt "512"; then
diff --git a/common/autoconf/build-performance.m4 b/common/autoconf/build-performance.m4
index b5911b789a7..e2fa4f566cf 100644
--- a/common/autoconf/build-performance.m4
+++ b/common/autoconf/build-performance.m4
@@ -328,12 +328,23 @@ AC_DEFUN_ONCE([BPERF_SETUP_SMART_JAVAC],
AC_ARG_ENABLE([sjavac], [AS_HELP_STRING([--enable-sjavac],
[use sjavac to do fast incremental compiles @<:@disabled@:>@])],
- [ENABLE_SJAVAC="${enableval}"], [ENABLE_SJAVAC='no'])
+ [ENABLE_SJAVAC="${enableval}"], [ENABLE_SJAVAC="no"])
if test "x$JVM_ARG_OK" = "xfalse"; then
AC_MSG_WARN([Could not set -Xms${MS_VALUE}M -Xmx${MX_VALUE}M, disabling sjavac])
- ENABLE_SJAVAC=no;
+ ENABLE_SJAVAC="no"
fi
AC_MSG_CHECKING([whether to use sjavac])
AC_MSG_RESULT([$ENABLE_SJAVAC])
AC_SUBST(ENABLE_SJAVAC)
+
+ AC_ARG_ENABLE([javac-server], [AS_HELP_STRING([--enable-javac-server],
+ [use only the server part of sjavac for faster javac compiles @<:@disabled@:>@])],
+ [ENABLE_JAVAC_SERVER="${enableval}"], [ENABLE_JAVAC_SERVER="no"])
+ if test "x$JVM_ARG_OK" = "xfalse"; then
+ AC_MSG_WARN([Could not set -Xms${MS_VALUE}M -Xmx${MX_VALUE}M, disabling javac server])
+ ENABLE_JAVAC_SERVER="no"
+ fi
+ AC_MSG_CHECKING([whether to use javac server])
+ AC_MSG_RESULT([$ENABLE_JAVAC_SERVER])
+ AC_SUBST(ENABLE_JAVAC_SERVER)
])
diff --git a/common/autoconf/compare.sh.in b/common/autoconf/compare.sh.in
index 3e426776535..b7bf2b4cecb 100644
--- a/common/autoconf/compare.sh.in
+++ b/common/autoconf/compare.sh.in
@@ -66,7 +66,7 @@ export STRIP="@STRIP@ @STRIPFLAGS@"
export TEE="@TEE@"
export UNIQ="@UNIQ@"
export UNPACK200="@FIXPATH@ @BOOT_JDK@/bin/unpack200"
-export UNZIP="@UNZIP@"
+export UNARCHIVE="@UNZIP@ -q"
export SRC_ROOT="@TOPDIR@"
export OUTPUT_ROOT="@OUTPUT_ROOT@"
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index ac326867966..47d1b441dff 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -632,6 +632,7 @@ LIBOBJS
CFLAGS_CCACHE
CCACHE
USE_PRECOMPILED_HEADER
+ENABLE_JAVAC_SERVER
ENABLE_SJAVAC
SJAVAC_SERVER_JAVA_FLAGS
SJAVAC_SERVER_JAVA
@@ -815,6 +816,7 @@ JAXWS_TOPDIR
JAXP_TOPDIR
CORBA_TOPDIR
LANGTOOLS_TOPDIR
+BOOT_JDK_BITS
JAVAC_FLAGS
BOOT_JDK_SOURCETARGET
JARSIGNER
@@ -968,6 +970,7 @@ TAR
TAIL
SORT
SH
+RMDIR
RM
PRINTF
NAWK
@@ -1115,6 +1118,7 @@ with_jobs
with_boot_jdk_jvmargs
with_sjavac_server_java
enable_sjavac
+enable_javac_server
enable_precompiled_headers
enable_ccache
with_ccache_dir
@@ -1146,6 +1150,7 @@ MV
NAWK
PRINTF
RM
+RMDIR
SH
SORT
TAIL
@@ -1864,6 +1869,8 @@ Optional Features:
--with-freetype, disabled otherwise]
--enable-sjavac use sjavac to do fast incremental compiles
[disabled]
+ --enable-javac-server use only the server part of sjavac for faster javac
+ compiles [disabled]
--disable-precompiled-headers
disable using precompiled headers when compiling C++
[enabled]
@@ -2025,6 +2032,7 @@ Some influential environment variables:
NAWK Override default value for NAWK
PRINTF Override default value for PRINTF
RM Override default value for RM
+ RMDIR Override default value for RMDIR
SH Override default value for SH
SORT Override default value for SORT
TAIL Override default value for TAIL
@@ -4587,7 +4595,7 @@ VS_SDK_PLATFORM_NAME_2013=
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1444643341
+DATE_WHEN_GENERATED=1445964676
###############################################################################
#
@@ -9511,6 +9519,209 @@ $as_echo "$tool_specified" >&6; }
+ # Publish this variable in the help.
+
+
+ if [ -z "${RMDIR+x}" ]; then
+ # The variable is not set by user, try to locate tool using the code snippet
+ for ac_prog in rmdir
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_RMDIR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $RMDIR in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_RMDIR="$RMDIR" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_RMDIR="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+RMDIR=$ac_cv_path_RMDIR
+if test -n "$RMDIR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RMDIR" >&5
+$as_echo "$RMDIR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$RMDIR" && break
+done
+
+ else
+ # The variable is set, but is it from the command line or the environment?
+
+ # Try to remove the string !RMDIR! from our list.
+ try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!RMDIR!/}
+ if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then
+ # If it failed, the variable was not from the command line. Ignore it,
+ # but warn the user (except for BASH, which is always set by the calling BASH).
+ if test "xRMDIR" != xBASH; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of RMDIR from the environment. Use command line variables instead." >&5
+$as_echo "$as_me: WARNING: Ignoring value of RMDIR from the environment. Use command line variables instead." >&2;}
+ fi
+ # Try to locate tool using the code snippet
+ for ac_prog in rmdir
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_RMDIR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $RMDIR in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_RMDIR="$RMDIR" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_RMDIR="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+RMDIR=$ac_cv_path_RMDIR
+if test -n "$RMDIR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RMDIR" >&5
+$as_echo "$RMDIR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$RMDIR" && break
+done
+
+ else
+ # If it succeeded, then it was overridden by the user. We will use it
+ # for the tool.
+
+ # First remove it from the list of overridden variables, so we can test
+ # for unknown variables in the end.
+ CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var"
+
+ # Check if we try to supply an empty value
+ if test "x$RMDIR" = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Setting user supplied tool RMDIR= (no value)" >&5
+$as_echo "$as_me: Setting user supplied tool RMDIR= (no value)" >&6;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for RMDIR" >&5
+$as_echo_n "checking for RMDIR... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
+$as_echo "disabled" >&6; }
+ else
+ # Check if the provided tool contains a complete path.
+ tool_specified="$RMDIR"
+ tool_basename="${tool_specified##*/}"
+ if test "x$tool_basename" = "x$tool_specified"; then
+ # A command without a complete path is provided, search $PATH.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool RMDIR=$tool_basename" >&5
+$as_echo "$as_me: Will search for user supplied tool RMDIR=$tool_basename" >&6;}
+ # Extract the first word of "$tool_basename", so it can be a program name with args.
+set dummy $tool_basename; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_RMDIR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $RMDIR in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_RMDIR="$RMDIR" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_RMDIR="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+RMDIR=$ac_cv_path_RMDIR
+if test -n "$RMDIR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RMDIR" >&5
+$as_echo "$RMDIR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "x$RMDIR" = x; then
+ as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5
+ fi
+ else
+ # Otherwise we believe it is a complete path. Use it as it is.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool RMDIR=$tool_specified" >&5
+$as_echo "$as_me: Will use user supplied tool RMDIR=$tool_specified" >&6;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for RMDIR" >&5
+$as_echo_n "checking for RMDIR... " >&6; }
+ if test ! -x "$tool_specified"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+ as_fn_error $? "User supplied tool RMDIR=$tool_specified does not exist or is not executable" "$LINENO" 5
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5
+$as_echo "$tool_specified" >&6; }
+ fi
+ fi
+ fi
+ fi
+
+
+
+ if test "x$RMDIR" = x; then
+ as_fn_error $? "Could not find required tool for RMDIR" "$LINENO" 5
+ fi
+
+
+
+
+
# Publish this variable in the help.
@@ -26920,6 +27131,18 @@ $as_echo "$tool_specified" >&6; }
+ # Check if the boot jdk is 32 or 64 bit
+ if "$JAVA" -d64 -version > /dev/null 2>&1; then
+ BOOT_JDK_BITS="64"
+ else
+ BOOT_JDK_BITS="32"
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Boot JDK is 32 or 64 bits" >&5
+$as_echo_n "checking if Boot JDK is 32 or 64 bits... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BOOT_JDK_BITS" >&5
+$as_echo "$BOOT_JDK_BITS" >&6; }
+
+
###############################################################################
#
@@ -53099,7 +53322,7 @@ $as_echo_n "checking flags for boot jdk java command for big workloads... " >&6;
# Maximum amount of heap memory.
# Maximum stack size.
JVM_MAX_HEAP=`expr $MEMORY_SIZE / 2`
- if test "x$BUILD_NUM_BITS" = x32; then
+ if test "x$BOOT_JDK_BITS" = "x32"; then
if test "$JVM_MAX_HEAP" -gt "1100"; then
JVM_MAX_HEAP=1100
elif test "$JVM_MAX_HEAP" -lt "512"; then
@@ -53107,10 +53330,7 @@ $as_echo_n "checking flags for boot jdk java command for big workloads... " >&6;
fi
STACK_SIZE=768
else
- # Running Javac on a JVM on a 64-bit machine, takes more space since 64-bit
- # pointers are used. Apparently, we need to increase the heap and stack
- # space for the jvm. More specifically, when running javac to build huge
- # jdk batch
+ # Running a 64 bit JVM allows for and requires a bigger heap
if test "$JVM_MAX_HEAP" -gt "1600"; then
JVM_MAX_HEAP=1600
elif test "$JVM_MAX_HEAP" -lt "512"; then
@@ -53299,13 +53519,13 @@ fi
if test "${enable_sjavac+set}" = set; then :
enableval=$enable_sjavac; ENABLE_SJAVAC="${enableval}"
else
- ENABLE_SJAVAC='no'
+ ENABLE_SJAVAC="no"
fi
if test "x$JVM_ARG_OK" = "xfalse"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not set -Xms${MS_VALUE}M -Xmx${MX_VALUE}M, disabling sjavac" >&5
$as_echo "$as_me: WARNING: Could not set -Xms${MS_VALUE}M -Xmx${MX_VALUE}M, disabling sjavac" >&2;}
- ENABLE_SJAVAC=no;
+ ENABLE_SJAVAC="no"
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use sjavac" >&5
$as_echo_n "checking whether to use sjavac... " >&6; }
@@ -53313,6 +53533,24 @@ $as_echo_n "checking whether to use sjavac... " >&6; }
$as_echo "$ENABLE_SJAVAC" >&6; }
+ # Check whether --enable-javac-server was given.
+if test "${enable_javac_server+set}" = set; then :
+ enableval=$enable_javac_server; ENABLE_JAVAC_SERVER="${enableval}"
+else
+ ENABLE_JAVAC_SERVER="no"
+fi
+
+ if test "x$JVM_ARG_OK" = "xfalse"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not set -Xms${MS_VALUE}M -Xmx${MX_VALUE}M, disabling javac server" >&5
+$as_echo "$as_me: WARNING: Could not set -Xms${MS_VALUE}M -Xmx${MX_VALUE}M, disabling javac server" >&2;}
+ ENABLE_JAVAC_SERVER="no"
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use javac server" >&5
+$as_echo_n "checking whether to use javac server... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ENABLE_JAVAC_SERVER" >&5
+$as_echo "$ENABLE_JAVAC_SERVER" >&6; }
+
+
# Can the C/C++ compiler use precompiled headers?
diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in
index 4b6983a54a3..8731756c772 100644
--- a/common/autoconf/spec.gmk.in
+++ b/common/autoconf/spec.gmk.in
@@ -245,6 +245,7 @@ MEMORY_SIZE:=@MEMORY_SIZE@
# Enable sjavac support = use a javac server,
# multi core javac compilation and dependency tracking.
ENABLE_SJAVAC:=@ENABLE_SJAVAC@
+ENABLE_JAVAC_SERVER:=@ENABLE_JAVAC_SERVER@
# Store sjavac server synchronization files here, and
# the sjavac server log files.
SJAVAC_SERVER_DIR=$(MAKESUPPORT_OUTPUTDIR)/javacservers
@@ -504,6 +505,7 @@ PATCH:=@PATCH@
PRINTF:=@PRINTF@
PWD:=@THEPWDCMD@
RM:=@RM@
+RMDIR:=@RMDIR@
SED:=@SED@
SH:=@SH@
SORT:=@SORT@
diff --git a/common/bin/compare.sh b/common/bin/compare.sh
index 77d51c41df0..7952b2b6abb 100644
--- a/common/bin/compare.sh
+++ b/common/bin/compare.sh
@@ -51,8 +51,6 @@ else
STAT_PRINT_SIZE="-c %s"
fi
-UNARCHIVE="$UNZIP -q"
-
COMPARE_EXCEPTIONS_INCLUDE="$SRC_ROOT/common/bin/compare_exceptions.sh.incl"
if [ ! -e "$COMPARE_EXCEPTIONS_INCLUDE" ]; then
echo "Error: Cannot locate the exceptions file, it should have been here: $COMPARE_EXCEPTIONS_INCLUDE"
diff --git a/common/bin/update-build-readme.sh b/common/bin/update-build-readme.sh
new file mode 100644
index 00000000000..9d1968a4c60
--- /dev/null
+++ b/common/bin/update-build-readme.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+# Get an absolute path to this script, since that determines the top-level
+# directory.
+this_script_dir=`dirname $0`
+TOPDIR=`cd $this_script_dir/../.. > /dev/null && pwd`
+
+GREP=grep
+MD_FILE=$TOPDIR/README-builds.md
+HTML_FILE=$TOPDIR/README-builds.html
+
+# Locate the markdown processor tool and check that it is the correct version.
+locate_markdown_processor() {
+ if [ -z "$MARKDOWN" ]; then
+ MARKDOWN=`which markdown 2> /dev/null`
+ if [ -z "$MARKDOWN" ]; then
+ echo "Error: Cannot locate markdown processor" 1>&2
+ exit 1
+ fi
+ fi
+
+ # Test version
+ MARKDOWN_VERSION=`$MARKDOWN -version | $GREP version`
+ if [ "x$MARKDOWN_VERSION" != "xThis is Markdown, version 1.0.1." ]; then
+ echo "Error: Expected markdown version 1.0.1." 1>&2
+ echo "Actual version found: $MARKDOWN_VERSION" 1>&2
+ echo "Download markdown here: https://daringfireball.net/projects/markdown/" 1>&2
+ exit 1
+ fi
+
+}
+
+# Verify that the source markdown file looks sound.
+verify_source_code() {
+ TOO_LONG_LINES=`$GREP -E -e '^.{80}.+$' $MD_FILE`
+ if [ "x$TOO_LONG_LINES" != x ]; then
+ echo "Warning: The following lines are longer than 80 characters:"
+ $GREP -E -e '^.{80}.+$' $MD_FILE
+ fi
+}
+
+# Convert the markdown file to html format.
+process_source() {
+ echo "Generating html file from markdown"
+ cat > $HTML_FILE << END
+
+
+ OpenJDK Build README
+
+
+END
+ markdown $MD_FILE >> $HTML_FILE
+ cat >> $HTML_FILE <
+
+END
+ echo "Done"
+}
+
+locate_markdown_processor
+verify_source_code
+process_source
diff --git a/corba/.hgtags b/corba/.hgtags
index 05ed676d17e..18dffcd5e71 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -330,3 +330,4 @@ df70bb200356fec686681f0295c50cc3ed43c3b3 jdk9-b84
3ec06af1368924469f7ce60a00324bac55eaeecc jdk9-b85
0a3f0d25c201b40575a7c3920fce4d6f4d3ae310 jdk9-b86
a5c40ac9b916ff44d512ee764fa919ed2097e149 jdk9-b87
+00f48ecbc09915f793d9e5ad74ab0b25f2549bf5 jdk9-b88
diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java
index 0c3ff08a7ad..c9d6320f65a 100644
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java
@@ -567,6 +567,11 @@ public class IIOPInputStream
// XXX I18N, logging needed.
throw new NotActiveException("defaultReadObjectDelegate");
+ if (!currentClassDesc.forClass().isAssignableFrom(
+ currentObject.getClass())) {
+ throw new IOException("Object Type mismatch");
+ }
+
// The array will be null unless fields were retrieved
// remotely because of a serializable version difference.
// Bug fix for 4365188. See the definition of
@@ -1063,6 +1068,9 @@ public class IIOPInputStream
int spBase = spClass; // current top of stack
+ if (currentClass.getName().equals("java.lang.String")) {
+ return this.readUTF();
+ }
/* The object's classes should be processed from supertype to subtype
* Push all the clases of the current object onto a stack.
* Note that only the serializable classes are represented
@@ -2257,6 +2265,27 @@ public class IIOPInputStream
try {
Class fieldCl = fields[i].getClazz();
+ if ((objectValue != null)
+ && (!fieldCl.isAssignableFrom(
+ objectValue.getClass()))) {
+ throw new IllegalArgumentException("Field mismatch");
+ }
+ Field classField = null;
+ try {
+ classField = cl.getDeclaredField(fields[i].getName());
+ } catch (NoSuchFieldException nsfEx) {
+ throw new IllegalArgumentException(nsfEx);
+ } catch (SecurityException secEx) {
+ throw new IllegalArgumentException(secEx.getCause());
+ }
+ Class> declaredFieldClass = classField.getType();
+
+ // check input field type is a declared field type
+ // input field is a subclass of the declared field
+ if (!declaredFieldClass.isAssignableFrom(fieldCl)) {
+ throw new IllegalArgumentException(
+ "Field Type mismatch");
+ }
if (objectValue != null && !fieldCl.isInstance(objectValue)) {
throw new IllegalArgumentException();
}
diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPOutputStream.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPOutputStream.java
index 1ca9e118cfd..a8fcb186c8b 100644
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPOutputStream.java
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPOutputStream.java
@@ -559,6 +559,10 @@ public class IIOPOutputStream
* Push all the clases of the current object onto a stack.
* Remember the stack pointer where this set of classes is being pushed.
*/
+ if (currentClassDesc.forClass().getName().equals("java.lang.String")) {
+ this.writeUTF((String)obj);
+ return;
+ }
int stackMark = classDescStack.size();
try {
ObjectStreamClass next;
diff --git a/corba/src/jdk.rmic/share/classes/sun/rmi/rmic/iiop/StubGenerator.java b/corba/src/jdk.rmic/share/classes/sun/rmi/rmic/iiop/StubGenerator.java
index 0d41c1edb90..bceb86cf774 100644
--- a/corba/src/jdk.rmic/share/classes/sun/rmi/rmic/iiop/StubGenerator.java
+++ b/corba/src/jdk.rmic/share/classes/sun/rmi/rmic/iiop/StubGenerator.java
@@ -446,6 +446,9 @@ public class StubGenerator extends sun.rmi.rmic.iiop.Generator {
if (emitPermissionCheck) {
// produce the following generated code for example
+ //
+ // private transient boolean _instantiated = false;
+ //
// private static Void checkPermission() {
// SecurityManager sm = System.getSecurityManager();
// if (sm != null) {
@@ -460,11 +463,21 @@ public class StubGenerator extends sun.rmi.rmic.iiop.Generator {
//
// public _XXXXX_Stub() {
// this(checkPermission());
+ // _instantiated = true;
+ // }
+ //
+ // private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {
+ // checkPermission();
+ // s.defaultReadObject();
+ // _instantiated = true;
// }
//
// where XXXXX is the name of the remote interface
p.pln();
+ p.plnI("private transient boolean _instantiated = false;");
+ p.pln();
+ p.pO();
p.plnI("private static Void checkPermission() {");
p.plnI("SecurityManager sm = System.getSecurityManager();");
p.pln("if (sm != null) {");
@@ -481,13 +494,23 @@ public class StubGenerator extends sun.rmi.rmic.iiop.Generator {
p.pO();
p.pI();
- p.pln("private " + currentClass + "(Void ignore) { }");
+ p.plnI("private " + currentClass + "(Void ignore) { }");
p.pln();
+ p.pO();
p.plnI("public " + currentClass + "() { ");
p.pln("this(checkPermission());");
+ p.pln("_instantiated = true;");
p.pOln("}");
p.pln();
+ p.plnI("private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException {");
+ p.plnI("checkPermission();");
+ p.pO();
+ p.pln("s.defaultReadObject();");
+ p.pln("_instantiated = true;");
+ p.pOln("}");
+ p.pln();
+ //p.pO();
}
if (!emitPermissionCheck) {
@@ -894,6 +917,7 @@ public class StubGenerator extends sun.rmi.rmic.iiop.Generator {
String paramNames[] = method.getArgumentNames();
Type returnType = method.getReturnType();
ValueType[] exceptions = getStubExceptions(method,false);
+ boolean hasIOException = false;
addNamesInUse(method);
addNameInUse("_type_ids");
@@ -921,6 +945,13 @@ public class StubGenerator extends sun.rmi.rmic.iiop.Generator {
p.plnI(" {");
// Now create the method body...
+ if (emitPermissionCheck) {
+ p.pln("if ((System.getSecurityManager() != null) && (!_instantiated)) {");
+ p.plnI(" throw new java.io.IOError(new java.io.IOException(\"InvalidObject \"));");
+ p.pOln("}");
+ p.pln();
+ }
+
if (localStubs) {
writeLocalStubMethodBody(p,method,theType);
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index e1a9f80ec13..57ffaf65cc0 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -490,3 +490,4 @@ e9e63d93bbfe2c6c23447e2c1f5cc71c98671cba jdk9-b79
03845376ea9dbf9690b6a9cfb4ed63f8cc0541c0 jdk9-b85
1ae4191359d811a51512f17dca80ffe79837a5ff jdk9-b86
d7ffd16382fe7071181b967932b47cff6d1312e1 jdk9-b87
+bc48b669bc6610fac97e16593050c0f559cf6945 jdk9-b88
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMapSet.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMapSet.java
index c8b771d8aaf..ca0b982a48a 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMapSet.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMapSet.java
@@ -67,9 +67,6 @@ public class ImmutableOopMapSet extends VMObject {
}
}
- public void visitValueLocation(Address valueAddr) {
- }
-
public void visitNarrowOopLocation(Address narrowOopAddr) {
addressVisitor.visitCompOopAddress(narrowOopAddr);
}
@@ -216,9 +213,9 @@ public class ImmutableOopMapSet extends VMObject {
}
}
- // We want narow oop, value and oop oop_types
- OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[]{
- OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE
+ // We want narow oop and oop oop_types
+ OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[] {
+ OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE
};
{
@@ -231,8 +228,6 @@ public class ImmutableOopMapSet extends VMObject {
// to detect in the debugging system
// assert(Universe::is_heap_or_null(*loc), "found non oop pointer");
visitor.visitOopLocation(loc);
- } else if (omv.getType() == OopMapValue.OopTypes.VALUE_VALUE) {
- visitor.visitValueLocation(loc);
} else if (omv.getType() == OopMapValue.OopTypes.NARROWOOP_VALUE) {
visitor.visitNarrowOopLocation(loc);
}
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapValue.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapValue.java
index 2fa04b9741f..3d6e125ff45 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapValue.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapValue.java
@@ -49,7 +49,6 @@ public class OopMapValue {
// Types of OopValues
static int UNUSED_VALUE;
static int OOP_VALUE;
- static int VALUE_VALUE;
static int NARROWOOP_VALUE;
static int CALLEE_SAVED_VALUE;
static int DERIVED_OOP_VALUE;
@@ -73,7 +72,6 @@ public class OopMapValue {
REGISTER_MASK_IN_PLACE = db.lookupIntConstant("OopMapValue::register_mask_in_place").intValue();
UNUSED_VALUE = db.lookupIntConstant("OopMapValue::unused_value").intValue();
OOP_VALUE = db.lookupIntConstant("OopMapValue::oop_value").intValue();
- VALUE_VALUE = db.lookupIntConstant("OopMapValue::value_value").intValue();
NARROWOOP_VALUE = db.lookupIntConstant("OopMapValue::narrowoop_value").intValue();
CALLEE_SAVED_VALUE = db.lookupIntConstant("OopMapValue::callee_saved_value").intValue();
DERIVED_OOP_VALUE = db.lookupIntConstant("OopMapValue::derived_oop_value").intValue();
@@ -82,7 +80,6 @@ public class OopMapValue {
public static abstract class OopTypes {
public static final OopTypes UNUSED_VALUE = new OopTypes() { int getValue() { return OopMapValue.UNUSED_VALUE; }};
public static final OopTypes OOP_VALUE = new OopTypes() { int getValue() { return OopMapValue.OOP_VALUE; }};
- public static final OopTypes VALUE_VALUE = new OopTypes() { int getValue() { return OopMapValue.VALUE_VALUE; }};
public static final OopTypes NARROWOOP_VALUE = new OopTypes() { int getValue() { return OopMapValue.NARROWOOP_VALUE; }};
public static final OopTypes CALLEE_SAVED_VALUE = new OopTypes() { int getValue() { return OopMapValue.CALLEE_SAVED_VALUE; }};
public static final OopTypes DERIVED_OOP_VALUE = new OopTypes() { int getValue() { return OopMapValue.DERIVED_OOP_VALUE; }};
@@ -105,7 +102,6 @@ public class OopMapValue {
// Querying
public boolean isOop() { return (getValue() & TYPE_MASK_IN_PLACE) == OOP_VALUE; }
- public boolean isValue() { return (getValue() & TYPE_MASK_IN_PLACE) == VALUE_VALUE; }
public boolean isNarrowOop() { return (getValue() & TYPE_MASK_IN_PLACE) == NARROWOOP_VALUE; }
public boolean isCalleeSaved() { return (getValue() & TYPE_MASK_IN_PLACE) == CALLEE_SAVED_VALUE; }
public boolean isDerivedOop() { return (getValue() & TYPE_MASK_IN_PLACE) == DERIVED_OOP_VALUE; }
@@ -117,7 +113,6 @@ public class OopMapValue {
int which = (getValue() & TYPE_MASK_IN_PLACE);
if (which == UNUSED_VALUE) return OopTypes.UNUSED_VALUE;
else if (which == OOP_VALUE) return OopTypes.OOP_VALUE;
- else if (which == VALUE_VALUE) return OopTypes.VALUE_VALUE;
else if (which == NARROWOOP_VALUE) return OopTypes.NARROWOOP_VALUE;
else if (which == CALLEE_SAVED_VALUE) return OopTypes.CALLEE_SAVED_VALUE;
else if (which == DERIVED_OOP_VALUE) return OopTypes.DERIVED_OOP_VALUE;
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapVisitor.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapVisitor.java
index 6153fba3d25..3170b24837e 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapVisitor.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapVisitor.java
@@ -31,6 +31,5 @@ import sun.jvm.hotspot.debugger.*;
public interface OopMapVisitor {
public void visitOopLocation(Address oopAddr);
public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr);
- public void visitValueLocation(Address valueAddr);
public void visitNarrowOopLocation(Address narrowOopAddr);
}
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java
index 2bde98074ff..75e4372b0e5 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -52,21 +52,19 @@ public class Method extends Metadata {
}
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
- Type type = db.lookupType("Method");
+ type = db.lookupType("Method");
constMethod = type.getAddressField("_constMethod");
methodData = type.getAddressField("_method_data");
methodCounters = type.getAddressField("_method_counters");
- methodSize = new CIntField(type.getCIntegerField("_method_size"), 0);
accessFlags = new CIntField(type.getCIntegerField("_access_flags"), 0);
code = type.getAddressField("_code");
vtableIndex = new CIntField(type.getCIntegerField("_vtable_index"), 0);
- bytecodeOffset = type.getSize();
/*
- interpreterEntry = type.getAddressField("_interpreter_entry");
fromCompiledCodeEntryPoint = type.getAddressField("_from_compiled_code_entry_point");
-
+ interpreterEntry = type.getAddressField("_from_interpreted_entry");
*/
+
objectInitializerName = null;
classInitializerName = null;
}
@@ -77,16 +75,22 @@ public class Method extends Metadata {
public boolean isMethod() { return true; }
+ // Not a Method field, used to keep type.
+ private static Type type;
+
// Fields
private static AddressField constMethod;
private static AddressField methodData;
private static AddressField methodCounters;
- private static CIntField methodSize;
private static CIntField accessFlags;
private static CIntField vtableIndex;
- private static long bytecodeOffset;
private static AddressField code;
+ /*
+ private static AddressCField fromCompiledCodeEntryPoint;
+ private static AddressField interpreterEntry;
+ */
+
// constant method names - ,
// Initialized lazily to avoid initialization ordering dependencies between Method and SymbolTable
@@ -106,11 +110,6 @@ public class Method extends Metadata {
}
- /*
- private static AddressCField interpreterEntry;
- private static AddressCField fromCompiledCodeEntryPoint;
- */
-
// Accessors for declared fields
public ConstMethod getConstMethod() {
Address addr = constMethod.getValue(getAddress());
@@ -128,7 +127,6 @@ public class Method extends Metadata {
return (MethodCounters) VMObjectFactory.newObject(MethodCounters.class, addr);
}
/** WARNING: this is in words, not useful in this system; use getObjectSize() instead */
- public long getMethodSize() { return methodSize.getValue(this); }
public long getMaxStack() { return getConstMethod().getMaxStack(); }
public long getMaxLocals() { return getConstMethod().getMaxLocals(); }
public long getSizeOfParameters() { return getConstMethod().getSizeOfParameters(); }
@@ -265,7 +263,7 @@ public class Method extends Metadata {
}
public long getSize() {
- return getMethodSize();
+ return type.getSize() + (isNative() ? 2: 0);
}
public void printValueOn(PrintStream tty) {
@@ -273,7 +271,6 @@ public class Method extends Metadata {
}
public void iterateFields(MetadataVisitor visitor) {
- visitor.doCInt(methodSize, true);
visitor.doCInt(accessFlags, true);
}
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java
index b1ee998dcd2..ab536d20f5d 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java
@@ -536,9 +536,6 @@ public abstract class Frame implements Cloneable {
}
}
- public void visitValueLocation(Address valueAddr) {
- }
-
public void visitNarrowOopLocation(Address compOopAddr) {
addressVisitor.visitCompOopAddress(compOopAddr);
}
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java
index 9f4c2d2e3b8..342a96d6e36 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java
@@ -1220,9 +1220,6 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE);
buf.append(omvIterator.iterate(oms, "NarrowOops:", false));
- oms = new OopMapStream(map, OopMapValue.OopTypes.VALUE_VALUE);
- buf.append(omvIterator.iterate(oms, "Values:", false));
-
oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE);
buf.append(omvIterator.iterate(oms, "Callee saved:", true));
diff --git a/hotspot/make/bsd/makefiles/compiler1.make b/hotspot/make/bsd/makefiles/compiler1.make
index 0057814a087..d303bfc1ca4 100644
--- a/hotspot/make/bsd/makefiles/compiler1.make
+++ b/hotspot/make/bsd/makefiles/compiler1.make
@@ -28,4 +28,7 @@ TYPE=COMPILER1
VM_SUBDIR = client
+# We don't support the JVMCI in a client VM.
+INCLUDE_JVMCI := false
+
CFLAGS += -DCOMPILER1
diff --git a/hotspot/make/bsd/makefiles/gcc.make b/hotspot/make/bsd/makefiles/gcc.make
index 6844d6169ae..21876523ee1 100644
--- a/hotspot/make/bsd/makefiles/gcc.make
+++ b/hotspot/make/bsd/makefiles/gcc.make
@@ -149,6 +149,7 @@ ifeq ($(USE_CLANG), true)
PCH_FLAG/sharedRuntimeTrig.o = $(PCH_FLAG/NO_PCH)
PCH_FLAG/sharedRuntimeTrans.o = $(PCH_FLAG/NO_PCH)
PCH_FLAG/unsafe.o = $(PCH_FLAG/NO_PCH)
+ PCH_FLAG/jvmciCompilerToVM.o = $(PCH_FLAG/NO_PCH)
endif
else # ($(USE_CLANG), true)
@@ -313,10 +314,11 @@ endif
# Work around some compiler bugs.
ifeq ($(USE_CLANG), true)
- # Clang <= 6.1
+ # Clang < 6 | <= 6.1 | <= 7.0
ifeq ($(shell expr \
$(CC_VER_MAJOR) \< 6 \| \
- \( $(CC_VER_MAJOR) = 6 \& $(CC_VER_MINOR) \<= 1 \) \
+ \( $(CC_VER_MAJOR) = 6 \& $(CC_VER_MINOR) \<= 1 \) \| \
+ \( $(CC_VER_MAJOR) = 7 \& $(CC_VER_MINOR) \<= 0 \) \
), 1)
OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
OPT_CFLAGS/unsafe.o += -O1
diff --git a/hotspot/make/bsd/makefiles/jsig.make b/hotspot/make/bsd/makefiles/jsig.make
index 8c0c1b8a5e5..6a9cebbb337 100644
--- a/hotspot/make/bsd/makefiles/jsig.make
+++ b/hotspot/make/bsd/makefiles/jsig.make
@@ -62,7 +62,7 @@ endif
$(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE)
@echo $(LOG_INFO) Making signal interposition lib...
$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
- $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) -o $@ $<
+ $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(EXTRA_CFLAGS) -o $@ $<
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
ifeq ($(OS_VENDOR), Darwin)
$(DSYMUTIL) $@
diff --git a/hotspot/make/bsd/makefiles/minimal1.make b/hotspot/make/bsd/makefiles/minimal1.make
index 03845fd12b7..d453e789877 100644
--- a/hotspot/make/bsd/makefiles/minimal1.make
+++ b/hotspot/make/bsd/makefiles/minimal1.make
@@ -38,6 +38,7 @@ INCLUDE_ALL_GCS := false
INCLUDE_NMT := false
INCLUDE_TRACE := false
INCLUDE_CDS := false
+INCLUDE_JVMCI := false
CXXFLAGS += -DMINIMAL_JVM -DCOMPILER1 -DVMTYPE=\"Minimal\"
CFLAGS += -DMINIMAL_JVM -DCOMPILER1 -DVMTYPE=\"Minimal\"
diff --git a/hotspot/make/excludeSrc.make b/hotspot/make/excludeSrc.make
index 0bc759f25b7..dac7372c6fc 100644
--- a/hotspot/make/excludeSrc.make
+++ b/hotspot/make/excludeSrc.make
@@ -106,6 +106,25 @@ ifeq ($(INCLUDE_NMT), false)
memTracker.cpp nmtDCmd.cpp mallocSiteTable.cpp
endif
+ifneq (,$(findstring $(Platform_arch_model), x86_64, sparc))
+ # JVMCI is supported only on x86_64 and SPARC.
+else
+ INCLUDE_JVMCI := false
+endif
+
+ifeq ($(INCLUDE_JVMCI), false)
+ CXXFLAGS += -DINCLUDE_JVMCI=0
+ CFLAGS += -DINCLUDE_JVMCI=0
+
+ jvmci_dir := $(HS_COMMON_SRC)/share/vm/jvmci
+ jvmci_dir_alt := $(HS_ALT_SRC)/share/vm/jvmci
+ jvmci_exclude := $(notdir $(wildcard $(jvmci_dir)/*.cpp)) \
+ $(notdir $(wildcard $(jvmci_dir_alt)/*.cpp))
+ Src_Files_EXCLUDE += $(jvmci_exclude) \
+ jvmciCodeInstaller_aarch64.cpp jvmciCodeInstaller_ppc.cpp jvmciCodeInstaller_sparc.cpp \
+ jvmciCodeInstaller_x86.cpp
+endif
+
-include $(HS_ALT_MAKE)/excludeSrc.make
.PHONY: $(HS_ALT_MAKE)/excludeSrc.make
diff --git a/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk b/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk
new file mode 100644
index 00000000000..15c55012cc8
--- /dev/null
+++ b/hotspot/make/gensrc/Gensrc-jdk.vm.ci.gmk
@@ -0,0 +1,122 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+include JavaCompilation.gmk
+include SetupJavaCompilers.gmk
+
+GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.vm.ci
+SRC_DIR := $(HOTSPOT_TOPDIR)/src/jdk.vm.ci/share/classes
+
+################################################################################
+# Compile the annotation processor
+
+$(eval $(call SetupJavaCompilation, BUILD_JVMCI_OPTIONS, \
+ SETUP := GENERATE_OLDBYTECODE, \
+ SRC := $(SRC_DIR)/jdk.vm.ci.options/src \
+ $(SRC_DIR)/jdk.vm.ci.options.processor/src \
+ $(SRC_DIR)/jdk.vm.ci.inittimer/src, \
+ BIN := $(BUILDTOOLS_OUTPUTDIR)/jvmci_options, \
+ JAR := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.ci.options.jar, \
+))
+
+$(eval $(call SetupJavaCompilation, BUILD_JVMCI_SERVICE, \
+ SETUP := GENERATE_OLDBYTECODE, \
+ SRC := $(SRC_DIR)/jdk.vm.ci.service/src \
+ $(SRC_DIR)/jdk.vm.ci.service.processor/src, \
+ BIN := $(BUILDTOOLS_OUTPUTDIR)/jvmci_service, \
+ JAR := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.ci.service.jar, \
+))
+
+################################################################################
+
+PROC_SRC_SUBDIRS := \
+ jdk.vm.ci.compiler \
+ jdk.vm.ci.hotspot \
+ jdk.vm.ci.hotspot.amd64 \
+ jdk.vm.ci.hotspot.sparc \
+ #
+
+PROC_SRC_DIRS := $(patsubst %, $(SRC_DIR)/%/src, $(PROC_SRC_SUBDIRS))
+
+PROC_SRCS := $(filter %.java, $(call CacheFind, $(PROC_SRC_DIRS)))
+
+ALL_SRC_DIRS := $(wildcard $(SRC_DIR)/*/src)
+SOURCEPATH := $(call PathList, $(ALL_SRC_DIRS))
+PROCESSOR_PATH := $(call PathList, \
+ $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.ci.options.jar \
+ $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.ci.service.jar)
+
+$(GENSRC_DIR)/_gensrc_proc_done: $(PROC_SRCS) \
+ $(BUILD_JVMCI_OPTIONS) $(BUILD_JVMCI_SERVICE)
+ $(MKDIR) -p $(@D)
+ $(eval $(call ListPathsSafely,PROC_SRCS,$(@D)/_gensrc_proc_files))
+ $(JAVA_SMALL) $(NEW_JAVAC) \
+ -XDignore.symbol.file \
+ -sourcepath $(SOURCEPATH) \
+ -implicit:none \
+ -proc:only \
+ -processorpath $(PROCESSOR_PATH) \
+ -d $(GENSRC_DIR) \
+ -s $(GENSRC_DIR) \
+ @$(@D)/_gensrc_proc_files
+ $(TOUCH) $@
+
+TARGETS += $(GENSRC_DIR)/_gensrc_proc_done
+
+################################################################################
+
+$(GENSRC_DIR)/META-INF/services/jdk.vm.ci.options.OptionDescriptors: \
+ $(GENSRC_DIR)/_gensrc_proc_done
+ $(MKDIR) -p $(@D)
+ ($(CD) $(GENSRC_DIR)/META-INF/jvmci.options && \
+ $(RM) -f $@; \
+ for i in $$(ls); do \
+ echo $${i}_OptionDescriptors >> $@; \
+ done)
+
+TARGETS += $(GENSRC_DIR)/META-INF/services/jdk.vm.ci.options.OptionDescriptors
+
+################################################################################
+
+$(GENSRC_DIR)/_providers_converted: $(GENSRC_DIR)/_gensrc_proc_done
+ $(MKDIR) -p $(GENSRC_DIR)/META-INF/services
+ ($(CD) $(GENSRC_DIR)/META-INF/jvmci.providers && \
+ for i in $$($(LS)); do \
+ c=$$($(CAT) $$i | $(TR) -d '\n\r'); \
+ $(ECHO) $$i >> $(GENSRC_DIR)/META-INF/services/$$c; \
+ done)
+ $(TOUCH) $@
+
+TARGETS += $(GENSRC_DIR)/_providers_converted
+
+################################################################################
+
+all: $(TARGETS)
+
+.PHONY: default all
diff --git a/hotspot/make/linux/makefiles/compiler1.make b/hotspot/make/linux/makefiles/compiler1.make
index 0057814a087..d303bfc1ca4 100644
--- a/hotspot/make/linux/makefiles/compiler1.make
+++ b/hotspot/make/linux/makefiles/compiler1.make
@@ -28,4 +28,7 @@ TYPE=COMPILER1
VM_SUBDIR = client
+# We don't support the JVMCI in a client VM.
+INCLUDE_JVMCI := false
+
CFLAGS += -DCOMPILER1
diff --git a/hotspot/make/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make
index 85aa5c33ded..b69a8b6a1e7 100644
--- a/hotspot/make/linux/makefiles/gcc.make
+++ b/hotspot/make/linux/makefiles/gcc.make
@@ -213,12 +213,16 @@ ifeq ($(USE_CLANG),)
# Since GCC 4.3, -Wconversion has changed its meanings to warn these implicit
# conversions which might affect the values. Only enable it in earlier versions.
ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0"
+ # GCC < 4.3
WARNING_FLAGS += -Wconversion
endif
ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& \( $(CC_VER_MINOR) \>= 8 \) \))" "1"
+ # GCC >= 4.8
# This flag is only known since GCC 4.3. Gcc 4.8 contains a fix so that with templates no
# warnings are issued: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11856
WARNING_FLAGS += -Wtype-limits
+ # GCC < 4.8 don't accept this flag for C++.
+ WARNING_FLAGS += -Wno-format-zero-length
endif
endif
diff --git a/hotspot/make/linux/makefiles/minimal1.make b/hotspot/make/linux/makefiles/minimal1.make
index 03845fd12b7..d453e789877 100644
--- a/hotspot/make/linux/makefiles/minimal1.make
+++ b/hotspot/make/linux/makefiles/minimal1.make
@@ -38,6 +38,7 @@ INCLUDE_ALL_GCS := false
INCLUDE_NMT := false
INCLUDE_TRACE := false
INCLUDE_CDS := false
+INCLUDE_JVMCI := false
CXXFLAGS += -DMINIMAL_JVM -DCOMPILER1 -DVMTYPE=\"Minimal\"
CFLAGS += -DMINIMAL_JVM -DCOMPILER1 -DVMTYPE=\"Minimal\"
diff --git a/hotspot/make/solaris/makefiles/compiler1.make b/hotspot/make/solaris/makefiles/compiler1.make
index 0057814a087..d303bfc1ca4 100644
--- a/hotspot/make/solaris/makefiles/compiler1.make
+++ b/hotspot/make/solaris/makefiles/compiler1.make
@@ -28,4 +28,7 @@ TYPE=COMPILER1
VM_SUBDIR = client
+# We don't support the JVMCI in a client VM.
+INCLUDE_JVMCI := false
+
CFLAGS += -DCOMPILER1
diff --git a/hotspot/make/windows/build_vm_def.sh b/hotspot/make/windows/build_vm_def.sh
index 3d905198cb6..05298eaa3f3 100644
--- a/hotspot/make/windows/build_vm_def.sh
+++ b/hotspot/make/windows/build_vm_def.sh
@@ -52,6 +52,7 @@ UNIQ="$MKS_HOME/uniq.exe"
CAT="$MKS_HOME/cat.exe"
RM="$MKS_HOME/rm.exe"
DUMPBIN="link.exe /dump"
+export VS_UNICODE_OUTPUT=
if [ "$1" = "-nosa" ]; then
echo EXPORTS > vm.def
diff --git a/hotspot/make/windows/create_obj_files.sh b/hotspot/make/windows/create_obj_files.sh
index e99ca829e6d..1bdf4d8c7a0 100644
--- a/hotspot/make/windows/create_obj_files.sh
+++ b/hotspot/make/windows/create_obj_files.sh
@@ -111,6 +111,7 @@ esac
COMPILER2_SPECIFIC_FILES="opto libadt bcEscapeAnalyzer.cpp c2_* runtime_*"
COMPILER1_SPECIFIC_FILES="c1_*"
+JVMCI_SPECIFIC_FILES="*jvmci* *JVMCI*"
SHARK_SPECIFIC_FILES="shark"
ZERO_SPECIFIC_FILES="zero"
@@ -119,11 +120,11 @@ Src_Files_EXCLUDE="jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp"
# Exclude per type.
case "${TYPE}" in
- "compiler1") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;;
+ "compiler1") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER2_SPECIFIC_FILES} ${JVMCI_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;;
"compiler2") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES}" ;;
"tiered") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES}" ;;
- "zero") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${COMPILER2_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;;
- "shark") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES}" ;;
+ "zero") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${COMPILER2_SPECIFIC_FILES} ${JVMCI_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;;
+ "shark") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${COMPILER2_SPECIFIC_FILES} ${JVMCI_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES}" ;;
esac
# Special handling of arch model.
diff --git a/hotspot/make/windows/makefiles/compile.make b/hotspot/make/windows/makefiles/compile.make
index 0ca02a18a96..aa1063d6eb1 100644
--- a/hotspot/make/windows/makefiles/compile.make
+++ b/hotspot/make/windows/makefiles/compile.make
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@ CXX=cl.exe
# /nologo Supress copyright message at every cl.exe startup
# /W3 Warning level 3
# /Zi Include debugging information
+# /d2Zi+ Extended debugging symbols for optimized code (/Zo in VS2013 Update 3 and later)
# /WX Treat any warning error as a fatal error
# /MD Use dynamic multi-threaded runtime (msvcrt.dll or msvc*NN.dll)
# /MTd Use static multi-threaded runtime debug versions
@@ -57,7 +58,7 @@ CXX_FLAGS=$(EXTRA_CFLAGS) /nologo /W3 /WX
# Let's add debug information when Full Debug Symbols is enabled
!if "$(ENABLE_FULL_DEBUG_SYMBOLS)" == "1"
-CXX_FLAGS=$(CXX_FLAGS) /Zi
+CXX_FLAGS=$(CXX_FLAGS) /Zi /d2Zi+
!endif
# Based on BUILDARCH we add some flags and select the default compiler name
diff --git a/hotspot/make/windows/makefiles/projectcreator.make b/hotspot/make/windows/makefiles/projectcreator.make
index 6947402a0a9..180851d835e 100644
--- a/hotspot/make/windows/makefiles/projectcreator.make
+++ b/hotspot/make/windows/makefiles/projectcreator.make
@@ -145,6 +145,10 @@ ProjectCreatorIDEOptionsIgnoreCompiler1=\
-ignorePath_TARGET tiered \
-ignorePath_TARGET c1_
+ProjectCreatorIDEOptionsIgnoreJVMCI=\
+ -ignorePath_TARGET src/share/vm/jvmci \
+ -ignorePath_TARGET vm/jvmci
+
ProjectCreatorIDEOptionsIgnoreCompiler2=\
-ignorePath_TARGET compiler2 \
-ignorePath_TARGET tiered \
@@ -165,6 +169,8 @@ ProjectCreatorIDEOptionsIgnoreCompiler2=\
##################################################
ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \
-define_compiler1 COMPILER1 \
+ -define_compiler1 INCLUDE_JVMCI=0 \
+$(ProjectCreatorIDEOptionsIgnoreJVMCI:TARGET=compiler1) \
$(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=compiler1)
##################################################
diff --git a/hotspot/make/windows/makefiles/vm.make b/hotspot/make/windows/makefiles/vm.make
index 65fbf2a0ae7..9381c5b097d 100644
--- a/hotspot/make/windows/makefiles/vm.make
+++ b/hotspot/make/windows/makefiles/vm.make
@@ -40,7 +40,7 @@ CXX_FLAGS=$(CXX_FLAGS) /homeparams
!endif
!if "$(Variant)" == "compiler1"
-CXX_FLAGS=$(CXX_FLAGS) /D "COMPILER1"
+CXX_FLAGS=$(CXX_FLAGS) /D "COMPILER1" /D INCLUDE_JVMCI=0
!endif
!if "$(Variant)" == "compiler2"
@@ -152,6 +152,7 @@ VM_PATH=$(VM_PATH);../generated/adfiles
VM_PATH=$(VM_PATH);../generated/jvmtifiles
VM_PATH=$(VM_PATH);../generated/tracefiles
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/c1
+VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/jvmci
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/compiler
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/code
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/interpreter
@@ -163,6 +164,7 @@ VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/gc/serial
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/gc/cms
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/gc/g1
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/asm
+VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/logging
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/memory
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/oops
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/prims
@@ -232,6 +234,9 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi
{$(COMMONSRC)\share\vm\classfile}.cpp.obj::
$(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
+{$(COMMONSRC)\share\vm\jvmci}.cpp.obj::
+ $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
+
{$(COMMONSRC)\share\vm\gc\parallel}.cpp.obj::
$(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
@@ -250,6 +255,9 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi
{$(COMMONSRC)\share\vm\asm}.cpp.obj::
$(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
+{$(COMMONSRC)\share\vm\logging}.cpp.obj::
+ $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
+
{$(COMMONSRC)\share\vm\memory}.cpp.obj::
$(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
@@ -330,6 +338,9 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi
{$(ALTSRC)\share\vm\asm}.cpp.obj::
$(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
+{$(ALTSRC)\share\vm\logging}.cpp.obj::
+ $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
+
{$(ALTSRC)\share\vm\memory}.cpp.obj::
$(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad
index eb42df45806..dabc578fe08 100644
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad
@@ -1039,6 +1039,7 @@ class HandlerImpl {
bool leading_membar(const MemBarNode *barrier);
bool is_card_mark_membar(const MemBarNode *barrier);
+ bool is_CAS(int opcode);
MemBarNode *leading_to_normal(MemBarNode *leading);
MemBarNode *normal_to_leading(const MemBarNode *barrier);
@@ -1057,6 +1058,9 @@ class HandlerImpl {
bool unnecessary_volatile(const Node *barrier);
bool needs_releasing_store(const Node *store);
+ // predicate controlling translation of CompareAndSwapX
+ bool needs_acquiring_load_exclusive(const Node *load);
+
// predicate controlling translation of StoreCM
bool unnecessary_storestore(const Node *storecm);
%}
@@ -1088,15 +1092,58 @@ source %{
// str
// dmb ish
//
+ // We can also use ldaxr and stlxr to implement compare and swap CAS
+ // sequences. These are normally translated to an instruction
+ // sequence like the following
+ //
+ // dmb ish
+ // retry:
+ // ldxr rval raddr
+ // cmp rval rold
+ // b.ne done
+ // stlxr rval, rnew, rold
+ // cbnz rval retry
+ // done:
+ // cset r0, eq
+ // dmb ishld
+ //
+ // Note that the exclusive store is already using an stlxr
+ // instruction. That is required to ensure visibility to other
+ // threads of the exclusive write (assuming it succeeds) before that
+ // of any subsequent writes.
+ //
+ // The following instruction sequence is an improvement on the above
+ //
+ // retry:
+ // ldaxr rval raddr
+ // cmp rval rold
+ // b.ne done
+ // stlxr rval, rnew, rold
+ // cbnz rval retry
+ // done:
+ // cset r0, eq
+ //
+ // We don't need the leading dmb ish since the stlxr guarantees
+ // visibility of prior writes in the case that the swap is
+ // successful. Crucially we don't have to worry about the case where
+ // the swap is not successful since no valid program should be
+ // relying on visibility of prior changes by the attempting thread
+ // in the case where the CAS fails.
+ //
+ // Similarly, we don't need the trailing dmb ishld if we substitute
+ // an ldaxr instruction since that will provide all the guarantees we
+ // require regarding observation of changes made by other threads
+ // before any change to the CAS address observed by the load.
+ //
// In order to generate the desired instruction sequence we need to
// be able to identify specific 'signature' ideal graph node
// sequences which i) occur as a translation of a volatile reads or
- // writes and ii) do not occur through any other translation or
- // graph transformation. We can then provide alternative aldc
- // matching rules which translate these node sequences to the
- // desired machine code sequences. Selection of the alternative
- // rules can be implemented by predicates which identify the
- // relevant node sequences.
+ // writes or CAS operations and ii) do not occur through any other
+ // translation or graph transformation. We can then provide
+ // alternative aldc matching rules which translate these node
+ // sequences to the desired machine code sequences. Selection of the
+ // alternative rules can be implemented by predicates which identify
+ // the relevant node sequences.
//
// The ideal graph generator translates a volatile read to the node
// sequence
@@ -1163,6 +1210,15 @@ source %{
// get if it is fed and feeds a cpuorder membar and if its feed
// membar also feeds an acquiring load.
//
+ // Finally an inlined (Unsafe) CAS operation is translated to the
+ // following ideal graph
+ //
+ // MemBarRelease
+ // MemBarCPUOrder
+ // CompareAndSwapX {CardMark}-optional
+ // MemBarCPUOrder
+ // MemBarAcquire
+ //
// So, where we can identify these volatile read and write
// signatures we can choose to plant either of the above two code
// sequences. For a volatile read we can simply plant a normal
@@ -1177,6 +1233,14 @@ source %{
// and MemBarVolatile and instead plant a simple stlr
// instruction.
//
+ // when we recognise a CAS signature we can choose to plant a dmb
+ // ish as a translation for the MemBarRelease, the conventional
+ // macro-instruction sequence for the CompareAndSwap node (which
+ // uses ldxr) and then a dmb ishld for the MemBarAcquire.
+ // Alternatively, we can elide generation of the dmb instructions
+ // and plant the alternative CompareAndSwap macro-instruction
+ // sequence (which uses ldaxr).
+ //
// Of course, the above only applies when we see these signature
// configurations. We still want to plant dmb instructions in any
// other cases where we may see a MemBarAcquire, MemBarRelease or
@@ -1194,7 +1258,8 @@ source %{
// relevant dmb instructions.
//
- // graph traversal helpers used for volatile put/get optimization
+ // graph traversal helpers used for volatile put/get and CAS
+ // optimization
// 1) general purpose helpers
@@ -1220,16 +1285,19 @@ source %{
return NULL;
}
- if (!ctl || !mem || !ctl->is_Proj() || !mem->is_Proj())
+ if (!ctl || !mem || !ctl->is_Proj() || !mem->is_Proj()) {
return NULL;
+ }
membar = ctl->lookup(0);
- if (!membar || !membar->is_MemBar())
+ if (!membar || !membar->is_MemBar()) {
return NULL;
+ }
- if (mem->lookup(0) != membar)
+ if (mem->lookup(0) != membar) {
return NULL;
+ }
return membar->as_MemBar();
}
@@ -1259,8 +1327,9 @@ source %{
}
}
- if (child == NULL)
+ if (child == NULL) {
return NULL;
+ }
for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
x = mem->fast_out(i);
@@ -1283,15 +1352,18 @@ source %{
{
int opcode = barrier->Opcode();
// if this is a release membar we are ok
- if (opcode == Op_MemBarRelease)
+ if (opcode == Op_MemBarRelease) {
return true;
+ }
// if its a cpuorder membar . . .
- if (opcode != Op_MemBarCPUOrder)
+ if (opcode != Op_MemBarCPUOrder) {
return false;
+ }
// then the parent has to be a release membar
MemBarNode *parent = parent_membar(barrier);
- if (!parent)
+ if (!parent) {
return false;
+ }
opcode = parent->Opcode();
return opcode == Op_MemBarRelease;
}
@@ -1314,11 +1386,13 @@ source %{
bool is_card_mark_membar(const MemBarNode *barrier)
{
- if (!UseG1GC && !(UseConcMarkSweepGC && UseCondCardMark))
+ if (!UseG1GC && !(UseConcMarkSweepGC && UseCondCardMark)) {
return false;
+ }
- if (barrier->Opcode() != Op_MemBarVolatile)
+ if (barrier->Opcode() != Op_MemBarVolatile) {
return false;
+ }
ProjNode *mem = barrier->proj_out(TypeFunc::Memory);
@@ -1333,8 +1407,8 @@ source %{
}
- // 3) helper predicates to traverse volatile put graphs which may
- // contain GC barrier subgraphs
+ // 3) helper predicates to traverse volatile put or CAS graphs which
+ // may contain GC barrier subgraphs
// Preamble
// --------
@@ -1404,8 +1478,7 @@ source %{
// currently being unmarked in which case the volatile put graph
// will look slightly different
//
- // MemBarRelease
- // MemBarCPUOrder___________________________________________
+ // MemBarRelease____________________________________________
// || \\ Ctl \ Ctl \ \\ Mem \
// || StoreN/P[mo_release] CastP2X If LoadB |
// | \ / \ |
@@ -1419,7 +1492,7 @@ source %{
// memory flow includes the following subgraph:
//
// MemBarRelease
- // MemBarCPUOrder
+ // {MemBarCPUOrder}
// | \ . . .
// | StoreX[mo_release] . . .
// | /
@@ -1431,8 +1504,48 @@ source %{
// detected starting from any candidate MemBarRelease,
// StoreX[mo_release] or MemBarVolatile.
//
+ // A simple variation on this normal case occurs for an unsafe CAS
+ // operation. The basic graph for a non-object CAS is
+ //
+ // MemBarRelease
+ // ||
+ // MemBarCPUOrder
+ // || \\ . . .
+ // || CompareAndSwapX
+ // || |
+ // || SCMemProj
+ // | \ /
+ // | MergeMem
+ // | /
+ // MemBarCPUOrder
+ // ||
+ // MemBarAcquire
+ //
+ // The same basic variations on this arrangement (mutatis mutandis)
+ // occur when a card mark is introduced. i.e. we se the same basic
+ // shape but the StoreP/N is replaced with CompareAndSawpP/N and the
+ // tail of the graph is a pair comprising a MemBarCPUOrder +
+ // MemBarAcquire.
+ //
+ // So, in the case of a CAS the normal graph has the variant form
+ //
+ // MemBarRelease
+ // MemBarCPUOrder
+ // | \ . . .
+ // | CompareAndSwapX . . .
+ // | |
+ // | SCMemProj
+ // | / . . .
+ // MergeMem
+ // |
+ // MemBarCPUOrder
+ // MemBarAcquire
+ //
+ // This graph can also easily be detected starting from any
+ // candidate MemBarRelease, CompareAndSwapX or MemBarAcquire.
+ //
// the code below uses two helper predicates, leading_to_normal and
- // normal_to_leading to identify this configuration, one validating
+ // normal_to_leading to identify these normal graphs, one validating
// the layout starting from the top membar and searching down and
// the other validating the layout starting from the lower membar
// and searching up.
@@ -1450,7 +1563,9 @@ source %{
// they are only inserted for object puts. This significantly
// complicates the task of identifying whether a MemBarRelease,
// StoreX[mo_release] or MemBarVolatile forms part of a volatile put
- // when using these GC configurations (see below).
+ // when using these GC configurations (see below). It adds similar
+ // complexity to the task of identifying whether a MemBarRelease,
+ // CompareAndSwapX or MemBarAcquire forms part of a CAS.
//
// In both cases the post-write subtree includes an auxiliary
// MemBarVolatile (StoreLoad barrier) separating the object put and
@@ -1489,7 +1604,8 @@ source %{
// (LoadB) from the card. Ctl and Mem are fed to the If via an
// intervening StoreLoad barrier (MemBarVolatile).
//
- // So, with CMS we may see a node graph which looks like this
+ // So, with CMS we may see a node graph for a volatile object store
+ // which looks like this
//
// MemBarRelease
// MemBarCPUOrder_(leading)__________________
@@ -1524,6 +1640,55 @@ source %{
// from the StoreCM into the trailing membar (n.b. the latter
// proceeds via a Phi associated with the If region).
//
+ // The graph for a CAS varies slightly, the obvious difference being
+ // that the StoreN/P node is replaced by a CompareAndSwapP/N node
+ // and the trailing MemBarVolatile by a MemBarCPUOrder +
+ // MemBarAcquire pair. The other important difference is that the
+ // CompareAndSwap node's SCMemProj is not merged into the card mark
+ // membar - it still feeds the trailing MergeMem. This also means
+ // that the card mark membar receives its Mem feed directly from the
+ // leading membar rather than via a MergeMem.
+ //
+ // MemBarRelease
+ // MemBarCPUOrder__(leading)_________________________
+ // || \\ C \
+ // MemBarVolatile (card mark) CompareAndSwapN/P CastP2X
+ // C | || M | |
+ // | LoadB | ______/|
+ // | | | / |
+ // | Cmp | / SCMemProj
+ // | / | / |
+ // If | / /
+ // | \ | / /
+ // IfFalse IfTrue | / /
+ // \ / \ |/ prec /
+ // \ / StoreCM /
+ // \ / | /
+ // Region . . . /
+ // | \ /
+ // | . . . \ / Bot
+ // | MergeMem
+ // | |
+ // MemBarCPUOrder
+ // MemBarAcquire (trailing)
+ //
+ // This has a slightly different memory subgraph to the one seen
+ // previously but the core of it is the same as for the CAS normal
+ // sungraph
+ //
+ // MemBarRelease
+ // MemBarCPUOrder____
+ // || \ . . .
+ // MemBarVolatile CompareAndSwapX . . .
+ // | \ |
+ // . . . SCMemProj
+ // | / . . .
+ // MergeMem
+ // |
+ // MemBarCPUOrder
+ // MemBarAcquire
+ //
+ //
// G1 is quite a lot more complicated. The nodes inserted on behalf
// of G1 may comprise: a pre-write graph which adds the old value to
// the SATB queue; the releasing store itself; and, finally, a
@@ -1575,12 +1740,16 @@ source %{
// n.b. the LoadB in this subgraph is not the card read -- it's a
// read of the SATB queue active flag.
//
+ // Once again the CAS graph is a minor variant on the above with the
+ // expected substitutions of CompareAndSawpX for StoreN/P and
+ // MemBarCPUOrder + MemBarAcquire for trailing MemBarVolatile.
+ //
// The G1 post-write subtree is also optional, this time when the
// new value being written is either null or can be identified as a
// newly allocated (young gen) object with no intervening control
// flow. The latter cannot happen but the former may, in which case
- // the card mark membar is omitted and the memory feeds from the
- // leading membar and the StoreN/P are merged direct into the
+ // the card mark membar is omitted and the memory feeds form the
+ // leading membar and the SToreN/P are merged direct into the
// trailing membar as per the normal subgraph. So, the only special
// case which arises is when the post-write subgraph is generated.
//
@@ -1668,47 +1837,84 @@ source %{
// value check has been elided the total number of Phis is 2
// otherwise it is 3.
//
+ // The CAS graph when using G1GC also includes a pre-write subgraph
+ // and an optional post-write subgraph. Teh sam evarioations are
+ // introduced as for CMS with conditional card marking i.e. the
+ // StoreP/N is swapped for a CompareAndSwapP/N, the tariling
+ // MemBarVolatile for a MemBarCPUOrder + MemBarAcquire pair and the
+ // Mem feed from the CompareAndSwapP/N includes a precedence
+ // dependency feed to the StoreCM and a feed via an SCMemProj to the
+ // trailing membar. So, as before the configuration includes the
+ // normal CAS graph as a subgraph of the memory flow.
+ //
// So, the upshot is that in all cases the volatile put graph will
// include a *normal* memory subgraph betwen the leading membar and
- // its child membar. When that child is not a card mark membar then
- // it marks the end of a volatile put subgraph. If the child is a
- // card mark membar then the normal subgraph will form part of a
- // volatile put subgraph if and only if the child feeds an
- // AliasIdxBot Mem feed to a trailing barrier via a MergeMem. That
- // feed is either direct (for CMS) or via 2 or 3 Phi nodes merging
- // the leading barrier memory flow (for G1).
+ // its child membar, either a volatile put graph (including a
+ // releasing StoreX) or a CAS graph (including a CompareAndSwapX).
+ // When that child is not a card mark membar then it marks the end
+ // of the volatile put or CAS subgraph. If the child is a card mark
+ // membar then the normal subgraph will form part of a volatile put
+ // subgraph if and only if the child feeds an AliasIdxBot Mem feed
+ // to a trailing barrier via a MergeMem. That feed is either direct
+ // (for CMS) or via 2 or 3 Phi nodes merging the leading barrier
+ // memory flow (for G1).
//
// The predicates controlling generation of instructions for store
// and barrier nodes employ a few simple helper functions (described
- // below) which identify the presence or absence of these subgraph
- // configurations and provide a means of traversing from one node in
- // the subgraph to another.
+ // below) which identify the presence or absence of all these
+ // subgraph configurations and provide a means of traversing from
+ // one node in the subgraph to another.
+
+ // is_CAS(int opcode)
+ //
+ // return true if opcode is one of the possible CompareAndSwapX
+ // values otherwise false.
+
+ bool is_CAS(int opcode)
+ {
+ return (opcode == Op_CompareAndSwapI ||
+ opcode == Op_CompareAndSwapL ||
+ opcode == Op_CompareAndSwapN ||
+ opcode == Op_CompareAndSwapP);
+ }
// leading_to_normal
//
- //graph traversal helper which detects the normal case Mem feed
- // from a release membar (or, optionally, its cpuorder child) to a
- // dependent volatile membar i.e. it ensures that the following Mem
- // flow subgraph is present.
+ //graph traversal helper which detects the normal case Mem feed from
+ // a release membar (or, optionally, its cpuorder child) to a
+ // dependent volatile membar i.e. it ensures that one or other of
+ // the following Mem flow subgraph is present.
//
// MemBarRelease
- // MemBarCPUOrder
+ // MemBarCPUOrder {leading}
// | \ . . .
// | StoreN/P[mo_release] . . .
// | /
// MergeMem
// |
- // MemBarVolatile
+ // MemBarVolatile {trailing or card mark}
//
- // if the correct configuration is present returns the volatile
+ // MemBarRelease
+ // MemBarCPUOrder {leading}
+ // | \ . . .
+ // | CompareAndSwapX . . .
+ // |
+ // . . . SCMemProj
+ // \ |
+ // | MergeMem
+ // | /
+ // MemBarCPUOrder
+ // MemBarAcquire {trailing}
+ //
+ // if the correct configuration is present returns the trailing
// membar otherwise NULL.
//
// the input membar is expected to be either a cpuorder membar or a
// release membar. in the latter case it should not have a cpu membar
// child.
//
- // the returned membar may be a card mark membar rather than a
- // trailing membar.
+ // the returned value may be a card mark or trailing membar
+ //
MemBarNode *leading_to_normal(MemBarNode *leading)
{
@@ -1719,54 +1925,103 @@ source %{
// check the mem flow
ProjNode *mem = leading->proj_out(TypeFunc::Memory);
- if (!mem)
+ if (!mem) {
return NULL;
+ }
Node *x = NULL;
StoreNode * st = NULL;
+ LoadStoreNode *cas = NULL;
MergeMemNode *mm = NULL;
for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
x = mem->fast_out(i);
if (x->is_MergeMem()) {
- if (mm != NULL)
+ if (mm != NULL) {
return NULL;
+ }
// two merge mems is one too many
mm = x->as_MergeMem();
} else if (x->is_Store() && x->as_Store()->is_release() && x->Opcode() != Op_StoreCM) {
- // two releasing stores is one too many
- if (st != NULL)
+ // two releasing stores/CAS nodes is one too many
+ if (st != NULL || cas != NULL) {
return NULL;
+ }
st = x->as_Store();
+ } else if (is_CAS(x->Opcode())) {
+ if (st != NULL || cas != NULL) {
+ return NULL;
+ }
+ cas = x->as_LoadStore();
}
}
- if (!mm || !st)
+ // must have a store or a cas
+ if (!st && !cas) {
return NULL;
+ }
- bool found = false;
- // ensure the store feeds the merge
- for (DUIterator_Fast imax, i = st->fast_outs(imax); i < imax; i++) {
- if (st->fast_out(i) == mm) {
- found = true;
- break;
+ // must have a merge if we also have st
+ if (st && !mm) {
+ return NULL;
+ }
+
+ Node *y = NULL;
+ if (cas) {
+ // look for an SCMemProj
+ for (DUIterator_Fast imax, i = cas->fast_outs(imax); i < imax; i++) {
+ x = cas->fast_out(i);
+ if (x->is_Proj()) {
+ y = x;
+ break;
+ }
+ }
+ if (y == NULL) {
+ return NULL;
+ }
+ // the proj must feed a MergeMem
+ for (DUIterator_Fast imax, i = y->fast_outs(imax); i < imax; i++) {
+ x = y->fast_out(i);
+ if (x->is_MergeMem()) {
+ mm = x->as_MergeMem();
+ break;
+ }
+ }
+ if (mm == NULL)
+ return NULL;
+ } else {
+ // ensure the store feeds the existing mergemem;
+ for (DUIterator_Fast imax, i = st->fast_outs(imax); i < imax; i++) {
+ if (st->fast_out(i) == mm) {
+ y = st;
+ break;
+ }
+ }
+ if (y == NULL) {
+ return NULL;
}
}
- if (!found)
- return NULL;
-
- MemBarNode *mbvol = NULL;
- // ensure the merge feeds a volatile membar
+ MemBarNode *mbar = NULL;
+ // ensure the merge feeds to the expected type of membar
for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
x = mm->fast_out(i);
- if (x->is_MemBar() && x->Opcode() == Op_MemBarVolatile) {
- mbvol = x->as_MemBar();
+ if (x->is_MemBar()) {
+ int opcode = x->Opcode();
+ if (opcode == Op_MemBarVolatile && st) {
+ mbar = x->as_MemBar();
+ } else if (cas && opcode == Op_MemBarCPUOrder) {
+ MemBarNode *y = x->as_MemBar();
+ y = child_membar(y);
+ if (y != NULL && y->Opcode() == Op_MemBarAcquire) {
+ mbar = y;
+ }
+ }
break;
}
}
- return mbvol;
+ return mbar;
}
// normal_to_leading
@@ -1774,7 +2029,7 @@ source %{
// graph traversal helper which detects the normal case Mem feed
// from either a card mark or a trailing membar to a preceding
// release membar (optionally its cpuorder child) i.e. it ensures
- // that the following Mem flow subgraph is present.
+ // that one or other of the following Mem flow subgraphs is present.
//
// MemBarRelease
// MemBarCPUOrder {leading}
@@ -1783,7 +2038,19 @@ source %{
// | /
// MergeMem
// |
- // MemBarVolatile
+ // MemBarVolatile {card mark or trailing}
+ //
+ // MemBarRelease
+ // MemBarCPUOrder {leading}
+ // | \ . . .
+ // | CompareAndSwapX . . .
+ // |
+ // . . . SCMemProj
+ // \ |
+ // | MergeMem
+ // | /
+ // MemBarCPUOrder
+ // MemBarAcquire {trailing}
//
// this predicate checks for the same flow as the previous predicate
// but starting from the bottom rather than the top.
@@ -1797,51 +2064,116 @@ source %{
MemBarNode *normal_to_leading(const MemBarNode *barrier)
{
// input must be a volatile membar
- assert(barrier->Opcode() == Op_MemBarVolatile, "expecting a volatile membar");
+ assert((barrier->Opcode() == Op_MemBarVolatile ||
+ barrier->Opcode() == Op_MemBarAcquire),
+ "expecting a volatile or an acquire membar");
Node *x;
+ bool is_cas = barrier->Opcode() == Op_MemBarAcquire;
+
+ // if we have an acquire membar then it must be fed via a CPUOrder
+ // membar
+
+ if (is_cas) {
+ // skip to parent barrier which must be a cpuorder
+ x = parent_membar(barrier);
+ if (x->Opcode() != Op_MemBarCPUOrder)
+ return NULL;
+ } else {
+ // start from the supplied barrier
+ x = (Node *)barrier;
+ }
// the Mem feed to the membar should be a merge
- x = barrier->in(TypeFunc::Memory);
+ x = x ->in(TypeFunc::Memory);
if (!x->is_MergeMem())
return NULL;
MergeMemNode *mm = x->as_MergeMem();
- // the AliasIdxBot slice should be another MemBar projection
- x = mm->in(Compile::AliasIdxBot);
+ if (is_cas) {
+ // the merge should be fed from the CAS via an SCMemProj node
+ x = NULL;
+ for (uint idx = 1; idx < mm->req(); idx++) {
+ if (mm->in(idx)->Opcode() == Op_SCMemProj) {
+ x = mm->in(idx);
+ break;
+ }
+ }
+ if (x == NULL) {
+ return NULL;
+ }
+ // check for a CAS feeding this proj
+ x = x->in(0);
+ int opcode = x->Opcode();
+ if (!is_CAS(opcode)) {
+ return NULL;
+ }
+ // the CAS should get its mem feed from the leading membar
+ x = x->in(MemNode::Memory);
+ } else {
+ // the merge should get its Bottom mem feed from the leading membar
+ x = mm->in(Compile::AliasIdxBot);
+ }
+
// ensure this is a non control projection
- if (!x->is_Proj() || x->is_CFG())
+ if (!x->is_Proj() || x->is_CFG()) {
return NULL;
+ }
// if it is fed by a membar that's the one we want
x = x->in(0);
- if (!x->is_MemBar())
+ if (!x->is_MemBar()) {
return NULL;
+ }
MemBarNode *leading = x->as_MemBar();
// reject invalid candidates
- if (!leading_membar(leading))
+ if (!leading_membar(leading)) {
return NULL;
+ }
- // ok, we have a leading ReleaseMembar, now for the sanity clauses
+ // ok, we have a leading membar, now for the sanity clauses
- // the leading membar must feed Mem to a releasing store
+ // the leading membar must feed Mem to a releasing store or CAS
ProjNode *mem = leading->proj_out(TypeFunc::Memory);
StoreNode *st = NULL;
+ LoadStoreNode *cas = NULL;
for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
x = mem->fast_out(i);
if (x->is_Store() && x->as_Store()->is_release() && x->Opcode() != Op_StoreCM) {
+ // two stores or CASes is one too many
+ if (st != NULL || cas != NULL) {
+ return NULL;
+ }
st = x->as_Store();
- break;
+ } else if (is_CAS(x->Opcode())) {
+ if (st != NULL || cas != NULL) {
+ return NULL;
+ }
+ cas = x->as_LoadStore();
}
}
- if (st == NULL)
- return NULL;
- // the releasing store has to feed the same merge
- for (DUIterator_Fast imax, i = st->fast_outs(imax); i < imax; i++) {
- if (st->fast_out(i) == mm)
- return leading;
+ // we should not have both a store and a cas
+ if (st == NULL & cas == NULL) {
+ return NULL;
+ }
+
+ if (st == NULL) {
+ // nothing more to check
+ return leading;
+ } else {
+ // we should not have a store if we started from an acquire
+ if (is_cas) {
+ return NULL;
+ }
+
+ // the store should feed the merge we used to get here
+ for (DUIterator_Fast imax, i = st->fast_outs(imax); i < imax; i++) {
+ if (st->fast_out(i) == mm) {
+ return leading;
+ }
+ }
}
return NULL;
@@ -1865,8 +2197,8 @@ source %{
// Bot | /
// MergeMem
// |
- // MemBarVolatile (trailing)
- //
+ // |
+ // MemBarVolatile {trailing}
//
// 2)
// MemBarRelease/CPUOrder (leading)
@@ -1884,7 +2216,8 @@ source %{
// Bot | /
// MergeMem
// |
- // MemBarVolatile (trailing)
+ // MemBarVolatile {trailing}
+ //
//
// 3)
// MemBarRelease/CPUOrder (leading)
@@ -1905,7 +2238,8 @@ source %{
// Bot | /
// MergeMem
// |
- // MemBarVolatile (trailing)
+ // |
+ // MemBarVolatile {trailing}
//
// configuration 1 is only valid if UseConcMarkSweepGC &&
// UseCondCardMark
@@ -1955,8 +2289,9 @@ source %{
break;
}
}
- if (!phi)
+ if (!phi) {
return NULL;
+ }
// look for another merge below this phi
feed = phi;
} else {
@@ -1969,7 +2304,7 @@ source %{
assert(mm->as_MergeMem()->in(Compile::AliasIdxBot) == feed, "expecting membar to feed AliasIdxBot slice to Merge");
MemBarNode *trailing = NULL;
- // be sure we have a volatile membar below the merge
+ // be sure we have a trailing membar the merge
for (DUIterator_Fast imax, i = mm->fast_outs(imax); i < imax; i++) {
x = mm->fast_out(i);
if (x->is_MemBar() && x->Opcode() == Op_MemBarVolatile) {
@@ -1984,24 +2319,32 @@ source %{
// trailing_to_card_mark
//
// graph traversal helper which detects extra, non-normal Mem feed
- // from a trailing membar to a preceding card mark volatile membar
- // i.e. it identifies whether one of the three possible extra GC
- // post-write Mem flow subgraphs is present
+ // from a trailing volatile membar to a preceding card mark volatile
+ // membar i.e. it identifies whether one of the three possible extra
+ // GC post-write Mem flow subgraphs is present
//
// this predicate checks for the same flow as the previous predicate
// but starting from the bottom rather than the top.
//
- // if the configurationis present returns the card mark membar
+ // if the configuration is present returns the card mark membar
// otherwise NULL
+ //
+ // n.b. the supplied membar is expected to be a trailing
+ // MemBarVolatile i.e. the caller must ensure the input node has the
+ // correct opcode
MemBarNode *trailing_to_card_mark(const MemBarNode *trailing)
{
- assert(!is_card_mark_membar(trailing), "not expecting a card mark membar");
+ assert(trailing->Opcode() == Op_MemBarVolatile,
+ "expecting a volatile membar");
+ assert(!is_card_mark_membar(trailing),
+ "not expecting a card mark membar");
- Node *x = trailing->in(TypeFunc::Memory);
// the Mem feed to the membar should be a merge
- if (!x->is_MergeMem())
+ Node *x = trailing->in(TypeFunc::Memory);
+ if (!x->is_MergeMem()) {
return NULL;
+ }
MergeMemNode *mm = x->as_MergeMem();
@@ -2054,13 +2397,15 @@ source %{
}
// the proj has to come from the card mark membar
x = x->in(0);
- if (!x->is_MemBar())
+ if (!x->is_MemBar()) {
return NULL;
+ }
MemBarNode *card_mark_membar = x->as_MemBar();
- if (!is_card_mark_membar(card_mark_membar))
+ if (!is_card_mark_membar(card_mark_membar)) {
return NULL;
+ }
return card_mark_membar;
}
@@ -2068,7 +2413,7 @@ source %{
// trailing_to_leading
//
// graph traversal helper which checks the Mem flow up the graph
- // from a (non-card mark) volatile membar attempting to locate and
+ // from a (non-card mark) trailing membar attempting to locate and
// return an associated leading membar. it first looks for a
// subgraph in the normal configuration (relying on helper
// normal_to_leading). failing that it then looks for one of the
@@ -2081,22 +2426,35 @@ source %{
// if the configuration is valid returns the cpuorder member for
// preference or when absent the release membar otherwise NULL.
//
- // n.b. the input membar is expected to be a volatile membar but
- // must *not* be a card mark membar.
+ // n.b. the input membar is expected to be either a volatile or
+ // acquire membar but in the former case must *not* be a card mark
+ // membar.
MemBarNode *trailing_to_leading(const MemBarNode *trailing)
{
- assert(!is_card_mark_membar(trailing), "not expecting a card mark membar");
+ assert((trailing->Opcode() == Op_MemBarAcquire ||
+ trailing->Opcode() == Op_MemBarVolatile),
+ "expecting an acquire or volatile membar");
+ assert((trailing->Opcode() != Op_MemBarVolatile ||
+ !is_card_mark_membar(trailing)),
+ "not expecting a card mark membar");
MemBarNode *leading = normal_to_leading(trailing);
- if (leading)
+ if (leading) {
return leading;
+ }
+
+ // nothing more to do if this is an acquire
+ if (trailing->Opcode() == Op_MemBarAcquire) {
+ return NULL;
+ }
MemBarNode *card_mark_membar = trailing_to_card_mark(trailing);
- if (!card_mark_membar)
+ if (!card_mark_membar) {
return NULL;
+ }
return normal_to_leading(card_mark_membar);
}
@@ -2105,10 +2463,12 @@ source %{
bool unnecessary_acquire(const Node *barrier)
{
- // assert barrier->is_MemBar();
- if (UseBarriersForVolatile)
+ assert(barrier->is_MemBar(), "expecting a membar");
+
+ if (UseBarriersForVolatile) {
// we need to plant a dmb
return false;
+ }
// a volatile read derived from bytecode (or also from an inlined
// SHA field read via LibraryCallKit::load_field_from_object)
@@ -2140,8 +2500,9 @@ bool unnecessary_acquire(const Node *barrier)
//
// where * tags node we were passed
// and |k means input k
- if (x->is_DecodeNarrowPtr())
+ if (x->is_DecodeNarrowPtr()) {
x = x->in(1);
+ }
return (x->is_Load() && x->as_Load()->is_acquire());
}
@@ -2167,8 +2528,9 @@ bool unnecessary_acquire(const Node *barrier)
return false;
ctl = parent->proj_out(TypeFunc::Control);
mem = parent->proj_out(TypeFunc::Memory);
- if (!ctl || !mem)
+ if (!ctl || !mem) {
return false;
+ }
// ensure the proj nodes both feed a LoadX[mo_acquire]
LoadNode *ld = NULL;
for (DUIterator_Fast imax, i = ctl->fast_outs(imax); i < imax; i++) {
@@ -2180,38 +2542,46 @@ bool unnecessary_acquire(const Node *barrier)
}
}
// it must be an acquiring load
- if (! ld || ! ld->is_acquire())
- return false;
- for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
- x = mem->fast_out(i);
- // if we see the same load we drop it and stop searching
- if (x == ld) {
- ld = NULL;
- break;
+ if (ld && ld->is_acquire()) {
+
+ for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {
+ x = mem->fast_out(i);
+ // if we see the same load we drop it and stop searching
+ if (x == ld) {
+ ld = NULL;
+ break;
+ }
+ }
+ // we must have dropped the load
+ if (ld == NULL) {
+ // check for a child cpuorder membar
+ MemBarNode *child = child_membar(barrier->as_MemBar());
+ if (child && child->Opcode() == Op_MemBarCPUOrder)
+ return true;
}
}
- // we must have dropped the load
- if (ld)
- return false;
- // check for a child cpuorder membar
- MemBarNode *child = child_membar(barrier->as_MemBar());
- if (!child || child->Opcode() != Op_MemBarCPUOrder)
- return false;
- return true;
+ // final option for unnecessary mebar is that it is a trailing node
+ // belonging to a CAS
+
+ MemBarNode *leading = trailing_to_leading(barrier->as_MemBar());
+
+ return leading != NULL;
}
bool needs_acquiring_load(const Node *n)
{
- // assert n->is_Load();
- if (UseBarriersForVolatile)
+ assert(n->is_Load(), "expecting a load");
+ if (UseBarriersForVolatile) {
// we use a normal load and a dmb
return false;
+ }
LoadNode *ld = n->as_Load();
- if (!ld->is_acquire())
+ if (!ld->is_acquire()) {
return false;
+ }
// check if this load is feeding an acquire membar
//
@@ -2261,20 +2631,23 @@ bool needs_acquiring_load(const Node *n)
membar = parent_membar(ld);
- if (!membar || !membar->Opcode() == Op_MemBarCPUOrder)
+ if (!membar || !membar->Opcode() == Op_MemBarCPUOrder) {
return false;
+ }
// ensure that there is a CPUOrder->Acquire->CPUOrder membar chain
membar = child_membar(membar);
- if (!membar || !membar->Opcode() == Op_MemBarAcquire)
+ if (!membar || !membar->Opcode() == Op_MemBarAcquire) {
return false;
+ }
membar = child_membar(membar);
- if (!membar || !membar->Opcode() == Op_MemBarCPUOrder)
+ if (!membar || !membar->Opcode() == Op_MemBarCPUOrder) {
return false;
+ }
return true;
}
@@ -2285,9 +2658,10 @@ bool unnecessary_release(const Node *n)
n->Opcode() == Op_MemBarRelease),
"expecting a release membar");
- if (UseBarriersForVolatile)
+ if (UseBarriersForVolatile) {
// we need to plant a dmb
return false;
+ }
// if there is a dependent CPUOrder barrier then use that as the
// leading
@@ -2303,12 +2677,14 @@ bool unnecessary_release(const Node *n)
// must start with a normal feed
MemBarNode *child_barrier = leading_to_normal(barrier);
- if (!child_barrier)
+ if (!child_barrier) {
return false;
+ }
- if (!is_card_mark_membar(child_barrier))
+ if (!is_card_mark_membar(child_barrier)) {
// this is the trailing membar and we are done
return true;
+ }
// must be sure this card mark feeds a trailing membar
MemBarNode *trailing = card_mark_to_trailing(child_barrier);
@@ -2318,17 +2694,19 @@ bool unnecessary_release(const Node *n)
bool unnecessary_volatile(const Node *n)
{
// assert n->is_MemBar();
- if (UseBarriersForVolatile)
+ if (UseBarriersForVolatile) {
// we need to plant a dmb
return false;
+ }
MemBarNode *mbvol = n->as_MemBar();
// first we check if this is part of a card mark. if so then we have
// to generate a StoreLoad barrier
- if (is_card_mark_membar(mbvol))
+ if (is_card_mark_membar(mbvol)) {
return false;
+ }
// ok, if it's not a card mark then we still need to check if it is
// a trailing membar of a volatile put hgraph.
@@ -2341,29 +2719,33 @@ bool unnecessary_volatile(const Node *n)
bool needs_releasing_store(const Node *n)
{
// assert n->is_Store();
- if (UseBarriersForVolatile)
+ if (UseBarriersForVolatile) {
// we use a normal store and dmb combination
return false;
+ }
StoreNode *st = n->as_Store();
// the store must be marked as releasing
- if (!st->is_release())
+ if (!st->is_release()) {
return false;
+ }
// the store must be fed by a membar
Node *x = st->lookup(StoreNode::Memory);
- if (! x || !x->is_Proj())
+ if (! x || !x->is_Proj()) {
return false;
+ }
ProjNode *proj = x->as_Proj();
x = proj->lookup(0);
- if (!x || !x->is_MemBar())
+ if (!x || !x->is_MemBar()) {
return false;
+ }
MemBarNode *barrier = x->as_MemBar();
@@ -2372,24 +2754,76 @@ bool needs_releasing_store(const Node *n)
// volatile put graph.
// reject invalid candidates
- if (!leading_membar(barrier))
+ if (!leading_membar(barrier)) {
return false;
+ }
// does this lead a normal subgraph?
MemBarNode *mbvol = leading_to_normal(barrier);
- if (!mbvol)
+ if (!mbvol) {
return false;
+ }
// all done unless this is a card mark
- if (!is_card_mark_membar(mbvol))
+ if (!is_card_mark_membar(mbvol)) {
return true;
+ }
// we found a card mark -- just make sure we have a trailing barrier
return (card_mark_to_trailing(mbvol) != NULL);
}
+// predicate controlling translation of CAS
+//
+// returns true if CAS needs to use an acquiring load otherwise false
+
+bool needs_acquiring_load_exclusive(const Node *n)
+{
+ assert(is_CAS(n->Opcode()), "expecting a compare and swap");
+ if (UseBarriersForVolatile) {
+ return false;
+ }
+
+ // CAS nodes only ought to turn up in inlined unsafe CAS operations
+#ifdef ASSERT
+ LoadStoreNode *st = n->as_LoadStore();
+
+ // the store must be fed by a membar
+
+ Node *x = st->lookup(StoreNode::Memory);
+
+ assert (x && x->is_Proj(), "CAS not fed by memory proj!");
+
+ ProjNode *proj = x->as_Proj();
+
+ x = proj->lookup(0);
+
+ assert (x && x->is_MemBar(), "CAS not fed by membar!");
+
+ MemBarNode *barrier = x->as_MemBar();
+
+ // the barrier must be a cpuorder mmebar fed by a release membar
+
+ assert(barrier->Opcode() == Op_MemBarCPUOrder,
+ "CAS not fed by cpuorder membar!");
+
+ MemBarNode *b = parent_membar(barrier);
+ assert ((b != NULL && b->Opcode() == Op_MemBarRelease),
+ "CAS not fed by cpuorder+release membar pair!");
+
+ // does this lead a normal subgraph?
+ MemBarNode *mbar = leading_to_normal(barrier);
+
+ assert(mbar != NULL, "CAS not embedded in normal graph!");
+
+ assert(mbar->Opcode() == Op_MemBarAcquire, "trailing membar should be an acquire");
+#endif // ASSERT
+ // so we can just return true here
+ return true;
+}
+
// predicate controlling translation of StoreCM
//
// returns true if a StoreStore must precede the card write otherwise
@@ -2403,14 +2837,16 @@ bool unnecessary_storestore(const Node *storecm)
// and the associated card mark when we are using CMS without
// conditional card marking
- if (!UseConcMarkSweepGC || UseCondCardMark)
+ if (!UseConcMarkSweepGC || UseCondCardMark) {
return true;
+ }
// if we are implementing volatile puts using barriers then the
// object put as an str so we must insert the dmb ishst
- if (UseBarriersForVolatile)
+ if (UseBarriersForVolatile) {
return false;
+ }
// we can omit the dmb ishst if this StoreCM is part of a volatile
// put because in thta case the put will be implemented by stlr
@@ -2422,19 +2858,22 @@ bool unnecessary_storestore(const Node *storecm)
Node *x = storecm->in(StoreNode::Memory);
- if (!x->is_Proj())
+ if (!x->is_Proj()) {
return false;
+ }
x = x->in(0);
- if (!x->is_MemBar())
+ if (!x->is_MemBar()) {
return false;
+ }
MemBarNode *leading = x->as_MemBar();
// reject invalid candidates
- if (!leading_membar(leading))
+ if (!leading_membar(leading)) {
return false;
+ }
// we can omit the StoreStore if it is the head of a normal subgraph
return (leading_to_normal(leading) != NULL);
@@ -3024,6 +3463,10 @@ const bool Matcher::match_rule_supported(int opcode) {
return true; // Per default match rules are supported.
}
+const int Matcher::float_pressure(int default_pressure_threshold) {
+ return default_pressure_threshold;
+}
+
int Matcher::regnum_to_fpu_offset(int regnum)
{
Unimplemented();
@@ -8365,9 +8808,13 @@ instruct storeIConditional(indirect mem, iRegINoSp oldval, iRegINoSp newval, rFl
// XXX No flag versions for CompareAndSwap{I,L,P,N} because matcher
// can't match them
+// standard CompareAndSwapX when we are using barriers
+// these have higher priority than the rules selected by a predicate
+
instruct compareAndSwapI(iRegINoSp res, indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr) %{
match(Set res (CompareAndSwapI mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
effect(KILL cr);
@@ -8385,6 +8832,7 @@ instruct compareAndSwapI(iRegINoSp res, indirect mem, iRegINoSp oldval, iRegINoS
instruct compareAndSwapL(iRegINoSp res, indirect mem, iRegLNoSp oldval, iRegLNoSp newval, rFlagsReg cr) %{
match(Set res (CompareAndSwapL mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
effect(KILL cr);
@@ -8402,6 +8850,7 @@ instruct compareAndSwapL(iRegINoSp res, indirect mem, iRegLNoSp oldval, iRegLNoS
instruct compareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
match(Set res (CompareAndSwapP mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
effect(KILL cr);
@@ -8419,6 +8868,7 @@ instruct compareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval
instruct compareAndSwapN(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegNNoSp newval, rFlagsReg cr) %{
match(Set res (CompareAndSwapN mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
effect(KILL cr);
@@ -8433,6 +8883,84 @@ instruct compareAndSwapN(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegNNoS
ins_pipe(pipe_slow);
%}
+// alternative CompareAndSwapX when we are eliding barriers
+
+instruct compareAndSwapIAcq(iRegINoSp res, indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr) %{
+
+ predicate(needs_acquiring_load_exclusive(n));
+ match(Set res (CompareAndSwapI mem (Binary oldval newval)));
+ ins_cost(VOLATILE_REF_COST);
+
+ effect(KILL cr);
+
+ format %{
+ "cmpxchgw_acq $mem, $oldval, $newval\t# (int) if $mem == $oldval then $mem <-- $newval"
+ "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)"
+ %}
+
+ ins_encode(aarch64_enc_cmpxchgw_acq(mem, oldval, newval),
+ aarch64_enc_cset_eq(res));
+
+ ins_pipe(pipe_slow);
+%}
+
+instruct compareAndSwapLAcq(iRegINoSp res, indirect mem, iRegLNoSp oldval, iRegLNoSp newval, rFlagsReg cr) %{
+
+ predicate(needs_acquiring_load_exclusive(n));
+ match(Set res (CompareAndSwapL mem (Binary oldval newval)));
+ ins_cost(VOLATILE_REF_COST);
+
+ effect(KILL cr);
+
+ format %{
+ "cmpxchg_acq $mem, $oldval, $newval\t# (long) if $mem == $oldval then $mem <-- $newval"
+ "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)"
+ %}
+
+ ins_encode(aarch64_enc_cmpxchg_acq(mem, oldval, newval),
+ aarch64_enc_cset_eq(res));
+
+ ins_pipe(pipe_slow);
+%}
+
+instruct compareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
+
+ predicate(needs_acquiring_load_exclusive(n));
+ match(Set res (CompareAndSwapP mem (Binary oldval newval)));
+ ins_cost(VOLATILE_REF_COST);
+
+ effect(KILL cr);
+
+ format %{
+ "cmpxchg_acq $mem, $oldval, $newval\t# (ptr) if $mem == $oldval then $mem <-- $newval"
+ "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)"
+ %}
+
+ ins_encode(aarch64_enc_cmpxchg_acq(mem, oldval, newval),
+ aarch64_enc_cset_eq(res));
+
+ ins_pipe(pipe_slow);
+%}
+
+instruct compareAndSwapNAcq(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegNNoSp newval, rFlagsReg cr) %{
+
+ predicate(needs_acquiring_load_exclusive(n));
+ match(Set res (CompareAndSwapN mem (Binary oldval newval)));
+ ins_cost(VOLATILE_REF_COST);
+
+ effect(KILL cr);
+
+ format %{
+ "cmpxchgw_acq $mem, $oldval, $newval\t# (narrow oop) if $mem == $oldval then $mem <-- $newval"
+ "cset $res, EQ\t# $res <-- (EQ ? 1 : 0)"
+ %}
+
+ ins_encode(aarch64_enc_cmpxchgw_acq(mem, oldval, newval),
+ aarch64_enc_cset_eq(res));
+
+ ins_pipe(pipe_slow);
+%}
+
instruct get_and_setI(indirect mem, iRegINoSp newv, iRegI prev) %{
match(Set prev (GetAndSetI mem newv));
@@ -13286,6 +13814,25 @@ instruct cmpP_imm0_branch(cmpOp cmp, iRegP op1, immP0 op2, label labl, rFlagsReg
ins_pipe(pipe_cmp_branch);
%}
+instruct cmpP_narrowOop_imm0_branch(cmpOp cmp, iRegN oop, immP0 zero, label labl, rFlagsReg cr) %{
+ match(If cmp (CmpP (DecodeN oop) zero));
+ predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
+ || n->in(1)->as_Bool()->_test._test == BoolTest::eq);
+ effect(USE labl);
+
+ ins_cost(BRANCH_COST);
+ format %{ "cb$cmp $oop, $labl" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
+ if (cond == Assembler::EQ)
+ __ cbzw($oop$$Register, *L);
+ else
+ __ cbnzw($oop$$Register, *L);
+ %}
+ ins_pipe(pipe_cmp_branch);
+%}
+
// Conditional Far Branch
// Conditional Far Branch Unsigned
// TODO: fixme
@@ -14662,6 +15209,102 @@ instruct vdiv2D(vecX dst, vecX src1, vecX src2)
ins_pipe(pipe_class_default);
%}
+// --------------------------------- SQRT -------------------------------------
+
+instruct vsqrt2D(vecX dst, vecX src)
+%{
+ predicate(n->as_Vector()->length() == 2);
+ match(Set dst (SqrtVD src));
+ format %{ "fsqrt $dst, $src\t# vector (2D)" %}
+ ins_encode %{
+ __ fsqrt(as_FloatRegister($dst$$reg), __ T2D,
+ as_FloatRegister($src$$reg));
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+// --------------------------------- ABS --------------------------------------
+
+instruct vabs2F(vecD dst, vecD src)
+%{
+ predicate(n->as_Vector()->length() == 2);
+ match(Set dst (AbsVF src));
+ ins_cost(INSN_COST * 3);
+ format %{ "fabs $dst,$src\t# vector (2S)" %}
+ ins_encode %{
+ __ fabs(as_FloatRegister($dst$$reg), __ T2S,
+ as_FloatRegister($src$$reg));
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+instruct vabs4F(vecX dst, vecX src)
+%{
+ predicate(n->as_Vector()->length() == 4);
+ match(Set dst (AbsVF src));
+ ins_cost(INSN_COST * 3);
+ format %{ "fabs $dst,$src\t# vector (4S)" %}
+ ins_encode %{
+ __ fabs(as_FloatRegister($dst$$reg), __ T4S,
+ as_FloatRegister($src$$reg));
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+instruct vabs2D(vecX dst, vecX src)
+%{
+ predicate(n->as_Vector()->length() == 2);
+ match(Set dst (AbsVD src));
+ ins_cost(INSN_COST * 3);
+ format %{ "fabs $dst,$src\t# vector (2D)" %}
+ ins_encode %{
+ __ fabs(as_FloatRegister($dst$$reg), __ T2D,
+ as_FloatRegister($src$$reg));
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+// --------------------------------- NEG --------------------------------------
+
+instruct vneg2F(vecD dst, vecD src)
+%{
+ predicate(n->as_Vector()->length() == 2);
+ match(Set dst (NegVF src));
+ ins_cost(INSN_COST * 3);
+ format %{ "fneg $dst,$src\t# vector (2S)" %}
+ ins_encode %{
+ __ fneg(as_FloatRegister($dst$$reg), __ T2S,
+ as_FloatRegister($src$$reg));
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+instruct vneg4F(vecX dst, vecX src)
+%{
+ predicate(n->as_Vector()->length() == 4);
+ match(Set dst (NegVF src));
+ ins_cost(INSN_COST * 3);
+ format %{ "fneg $dst,$src\t# vector (4S)" %}
+ ins_encode %{
+ __ fneg(as_FloatRegister($dst$$reg), __ T4S,
+ as_FloatRegister($src$$reg));
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+instruct vneg2D(vecX dst, vecX src)
+%{
+ predicate(n->as_Vector()->length() == 2);
+ match(Set dst (NegVD src));
+ ins_cost(INSN_COST * 3);
+ format %{ "fneg $dst,$src\t# vector (2D)" %}
+ ins_encode %{
+ __ fneg(as_FloatRegister($dst$$reg), __ T2D,
+ as_FloatRegister($src$$reg));
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
// --------------------------------- AND --------------------------------------
instruct vand8B(vecD dst, vecD src1, vecD src2)
diff --git a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp
index f1678f7aa1a..dcd99c341ce 100644
--- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp
@@ -2311,6 +2311,12 @@ public:
#define MSG "invalid arrangement"
+#define ASSERTION (T == T2S || T == T4S || T == T2D)
+ INSN(fsqrt, 1, 0b11111);
+ INSN(fabs, 0, 0b01111);
+ INSN(fneg, 1, 0b01111);
+#undef ASSERTION
+
#define ASSERTION (T == T8B || T == T16B || T == T4H || T == T8H || T == T2S || T == T4S)
INSN(rev64, 0, 0b00000);
#undef ASSERTION
diff --git a/hotspot/src/cpu/aarch64/vm/c2_globals_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/c2_globals_aarch64.hpp
index 3aad200efe2..7ab673f2151 100644
--- a/hotspot/src/cpu/aarch64/vm/c2_globals_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/c2_globals_aarch64.hpp
@@ -68,10 +68,11 @@ define_pd_global(intx, RegisterCostAreaRatio, 16000);
// Peephole and CISC spilling both break the graph, and so makes the
// scheduler sick.
-define_pd_global(bool, OptoPeephole, true);
+define_pd_global(bool, OptoPeephole, false);
define_pd_global(bool, UseCISCSpill, true);
define_pd_global(bool, OptoScheduling, false);
define_pd_global(bool, OptoBundling, false);
+define_pd_global(bool, OptoRegScheduling, false);
define_pd_global(intx, ReservedCodeCacheSize, 48*M);
define_pd_global(intx, NonProfiledCodeHeapSize, 21*M);
diff --git a/hotspot/src/cpu/aarch64/vm/compiledIC_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/compiledIC_aarch64.cpp
index b30a4a6df10..103b936b5b4 100644
--- a/hotspot/src/cpu/aarch64/vm/compiledIC_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/compiledIC_aarch64.cpp
@@ -51,13 +51,15 @@ bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) {
// ----------------------------------------------------------------------------
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
// Stub is fixed up when the corresponding call is converted from
// calling compiled code to calling interpreted code.
// mov rmethod, 0
// jmp -4 # to self
- address mark = cbuf.insts_mark(); // Get mark within main instrs section.
+ if (mark == NULL) {
+ mark = cbuf.insts_mark(); // Get mark within main instrs section.
+ }
// Note that the code buffer's insts_mark is always relative to insts.
// That's why we must use the macroassembler to generate a stub.
diff --git a/hotspot/src/cpu/aarch64/vm/cppInterpreterGenerator_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/cppInterpreterGenerator_aarch64.hpp
index a8d1f94fca1..662d2849efc 100644
--- a/hotspot/src/cpu/aarch64/vm/cppInterpreterGenerator_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/cppInterpreterGenerator_aarch64.hpp
@@ -30,5 +30,6 @@
void generate_more_monitors();
void generate_deopt_handling();
+ void lock_method(void);
#endif // CPU_AARCH64_VM_CPPINTERPRETERGENERATOR_AARCH64_HPP
diff --git a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
index 8207dc9fa4e..e770da27179 100644
--- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
@@ -55,10 +55,17 @@ define_pd_global(intx, CodeEntryAlignment, 16);
define_pd_global(intx, OptoLoopAlignment, 16);
define_pd_global(intx, InlineFrequencyCount, 100);
-define_pd_global(intx, StackYellowPages, 2);
-define_pd_global(intx, StackRedPages, 1);
+#define DEFAULT_STACK_YELLOW_PAGES (2)
+#define DEFAULT_STACK_RED_PAGES (1)
+#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
-define_pd_global(intx, StackShadowPages, 4 DEBUG_ONLY(+5));
+#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
+#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
+#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
+
+define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
+define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
+define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
diff --git a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp
index 8f0f543ae9d..8fe6b38f0c0 100644
--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp
@@ -42,6 +42,11 @@
// Implementation of InterpreterMacroAssembler
+void InterpreterMacroAssembler::jump_to_entry(address entry) {
+ assert(entry, "Entry must have been generated by now");
+ b(entry);
+}
+
#ifndef CC_INTERP
void InterpreterMacroAssembler::check_and_handle_popframe(Register java_thread) {
@@ -1542,14 +1547,14 @@ void InterpreterMacroAssembler::profile_arguments_type(Register mdp, Register ca
if (MethodData::profile_arguments()) {
Label done;
int off_to_args = in_bytes(TypeEntriesAtCall::args_data_offset());
- add(mdp, mdp, off_to_args);
for (int i = 0; i < TypeProfileArgsLimit; i++) {
if (i > 0 || MethodData::profile_return()) {
// If return value type is profiled we may have no argument to profile
- ldr(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
+ ldr(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())));
sub(tmp, tmp, i*TypeStackSlotEntries::per_arg_count());
cmp(tmp, TypeStackSlotEntries::per_arg_count());
+ add(rscratch1, mdp, off_to_args);
br(Assembler::LT, done);
}
ldr(tmp, Address(callee, Method::const_offset()));
@@ -1557,26 +1562,27 @@ void InterpreterMacroAssembler::profile_arguments_type(Register mdp, Register ca
// stack offset o (zero based) from the start of the argument
// list, for n arguments translates into offset n - o - 1 from
// the end of the argument list
- ldr(rscratch1, Address(mdp, in_bytes(TypeEntriesAtCall::stack_slot_offset(i))-off_to_args));
+ ldr(rscratch1, Address(mdp, in_bytes(TypeEntriesAtCall::stack_slot_offset(i))));
sub(tmp, tmp, rscratch1);
sub(tmp, tmp, 1);
Address arg_addr = argument_address(tmp);
ldr(tmp, arg_addr);
- Address mdo_arg_addr(mdp, in_bytes(TypeEntriesAtCall::argument_type_offset(i))-off_to_args);
+ Address mdo_arg_addr(mdp, in_bytes(TypeEntriesAtCall::argument_type_offset(i)));
profile_obj_type(tmp, mdo_arg_addr);
int to_add = in_bytes(TypeStackSlotEntries::per_arg_size());
- add(mdp, mdp, to_add);
off_to_args += to_add;
}
if (MethodData::profile_return()) {
- ldr(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
+ ldr(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())));
sub(tmp, tmp, TypeProfileArgsLimit*TypeStackSlotEntries::per_arg_count());
}
+ add(rscratch1, mdp, off_to_args);
bind(done);
+ mov(mdp, rscratch1);
if (MethodData::profile_return()) {
// We're right after the type profile for the last
diff --git a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp
index 7d30ee0d16e..5cdfdecf2d3 100644
--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp
@@ -66,6 +66,8 @@ class InterpreterMacroAssembler: public MacroAssembler {
void load_earlyret_value(TosState state);
+ void jump_to_entry(address entry);
+
#ifdef CC_INTERP
void save_bcp() { /* not needed in c++ interpreter and harmless */ }
void restore_bcp() { /* not needed in c++ interpreter and harmless */ }
diff --git a/hotspot/src/cpu/aarch64/vm/interpreterGenerator_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/interpreterGenerator_aarch64.hpp
index ffff3a20826..3d886570a5a 100644
--- a/hotspot/src/cpu/aarch64/vm/interpreterGenerator_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/interpreterGenerator_aarch64.hpp
@@ -41,14 +41,13 @@ private:
address generate_native_entry(bool synchronized);
address generate_abstract_entry(void);
address generate_math_entry(AbstractInterpreter::MethodKind kind);
- address generate_jump_to_normal_entry(void);
- address generate_accessor_entry(void) { return generate_jump_to_normal_entry(); }
- address generate_empty_entry(void) { return generate_jump_to_normal_entry(); }
+ address generate_accessor_entry(void) { return NULL; }
+ address generate_empty_entry(void) { return NULL; }
void generate_transcendental_entry(AbstractInterpreter::MethodKind kind, int fpargs);
address generate_Reference_get_entry();
address generate_CRC32_update_entry();
address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind);
- void lock_method(void);
+ address generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return NULL; }
void generate_stack_overflow_check(void);
void generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue);
diff --git a/hotspot/src/cpu/aarch64/vm/interpreter_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/interpreter_aarch64.cpp
index dd078da8f51..96a967fb961 100644
--- a/hotspot/src/cpu/aarch64/vm/interpreter_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/interpreter_aarch64.cpp
@@ -236,17 +236,6 @@ void InterpreterGenerator::generate_transcendental_entry(AbstractInterpreter::Me
__ blrt(rscratch1, gpargs, fpargs, rtype);
}
-// Jump into normal path for accessor and empty entry to jump to normal entry
-// The "fast" optimization don't update compilation count therefore can disable inlining
-// for these functions that should be inlined.
-address InterpreterGenerator::generate_jump_to_normal_entry(void) {
- address entry_point = __ pc();
-
- assert(Interpreter::entry_for_kind(Interpreter::zerolocals) != NULL, "should already be generated");
- __ b(Interpreter::entry_for_kind(Interpreter::zerolocals));
- return entry_point;
-}
-
// Abstract method entry
// Attempt to execute abstract method. Throw exception
address InterpreterGenerator::generate_abstract_entry(void) {
diff --git a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp
new file mode 100644
index 00000000000..c9467bfb23c
--- /dev/null
+++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "vmreg_aarch64.inline.hpp"
+
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+ Unimplemented();
+ return 0;
+}
+
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
+ Unimplemented();
+}
+
+// convert JVMCI register indices (as used in oop maps) to HotSpot registers
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg) {
+ return NULL;
+}
+
+bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) {
+ return false;
+}
diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
index e423476065f..a827da7a5be 100644
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
@@ -1709,6 +1709,20 @@ int MacroAssembler::corrected_idivq(Register result, Register ra, Register rb,
return idivq_offset;
}
+void MacroAssembler::membar(Membar_mask_bits order_constraint) {
+ address prev = pc() - NativeMembar::instruction_size;
+ if (prev == code()->last_membar()) {
+ NativeMembar *bar = NativeMembar_at(prev);
+ // We are merging two memory barrier instructions. On AArch64 we
+ // can do this simply by ORing them together.
+ bar->set_kind(bar->get_kind() | order_constraint);
+ BLOCK_COMMENT("merged membar");
+ } else {
+ code()->set_last_membar(pc());
+ dmb(Assembler::barrier(order_constraint));
+ }
+}
+
// MacroAssembler routines found actually to be needed
void MacroAssembler::push(Register src)
@@ -2238,7 +2252,7 @@ void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[])
ttyLocker ttyl;
::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n",
msg);
- assert(false, err_msg("DEBUG MESSAGE: %s", msg));
+ assert(false, "DEBUG MESSAGE: %s", msg);
}
}
@@ -2286,18 +2300,30 @@ void MacroAssembler::c_stub_prolog(int gp_arg_count, int fp_arg_count, int ret_t
}
#endif
-void MacroAssembler::push_CPU_state() {
- push(0x3fffffff, sp); // integer registers except lr & sp
+void MacroAssembler::push_CPU_state(bool save_vectors) {
+ push(0x3fffffff, sp); // integer registers except lr & sp
+ if (!save_vectors) {
for (int i = 30; i >= 0; i -= 2)
stpd(as_FloatRegister(i), as_FloatRegister(i+1),
Address(pre(sp, -2 * wordSize)));
+ } else {
+ for (int i = 30; i >= 0; i -= 2)
+ stpq(as_FloatRegister(i), as_FloatRegister(i+1),
+ Address(pre(sp, -4 * wordSize)));
+ }
}
-void MacroAssembler::pop_CPU_state() {
- for (int i = 0; i < 32; i += 2)
- ldpd(as_FloatRegister(i), as_FloatRegister(i+1),
- Address(post(sp, 2 * wordSize)));
+void MacroAssembler::pop_CPU_state(bool restore_vectors) {
+ if (!restore_vectors) {
+ for (int i = 0; i < 32; i += 2)
+ ldpd(as_FloatRegister(i), as_FloatRegister(i+1),
+ Address(post(sp, 2 * wordSize)));
+ } else {
+ for (int i = 0; i < 32; i += 2)
+ ldpq(as_FloatRegister(i), as_FloatRegister(i+1),
+ Address(post(sp, 4 * wordSize)));
+ }
pop(0x3fffffff, sp); // integer registers except lr & sp
}
@@ -3027,6 +3053,24 @@ SkipIfEqual::~SkipIfEqual() {
_masm->bind(_label);
}
+void MacroAssembler::addptr(const Address &dst, int32_t src) {
+ Address adr;
+ switch(dst.getMode()) {
+ case Address::base_plus_offset:
+ // This is the expected mode, although we allow all the other
+ // forms below.
+ adr = form_address(rscratch2, dst.base(), dst.offset(), LogBytesPerWord);
+ break;
+ default:
+ lea(rscratch2, dst);
+ adr = Address(rscratch2);
+ break;
+ }
+ ldr(rscratch1, adr);
+ add(rscratch1, rscratch1, src);
+ str(rscratch1, adr);
+}
+
void MacroAssembler::cmpptr(Register src1, Address src2) {
unsigned long offset;
adrp(rscratch1, src2, offset);
@@ -3063,11 +3107,15 @@ void MacroAssembler::store_check(Register obj) {
if (UseCondCardMark) {
Label L_already_dirty;
+ membar(StoreLoad);
ldrb(rscratch2, Address(obj, rscratch1));
cbz(rscratch2, L_already_dirty);
strb(zr, Address(obj, rscratch1));
bind(L_already_dirty);
} else {
+ if (UseConcMarkSweepGC && CMSPrecleaningEnabled) {
+ membar(StoreStore);
+ }
strb(zr, Address(obj, rscratch1));
}
}
diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
index 1fbba6f9b18..563a24a1238 100644
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
@@ -152,6 +152,13 @@ class MacroAssembler: public Assembler {
strw(scratch, a);
}
+ void bind(Label& L) {
+ Assembler::bind(L);
+ code()->clear_last_membar();
+ }
+
+ void membar(Membar_mask_bits order_constraint);
+
// Frame creation and destruction shared between JITs.
void build_frame(int framesize);
void remove_frame(int framesize);
@@ -777,8 +784,8 @@ public:
DEBUG_ONLY(void verify_heapbase(const char* msg);)
- void push_CPU_state();
- void pop_CPU_state() ;
+ void push_CPU_state(bool save_vectors = false);
+ void pop_CPU_state(bool restore_vectors = false) ;
// Round up to a power of two
void round_to(Register reg, int modulus);
@@ -908,13 +915,7 @@ public:
// Arithmetics
- void addptr(Address dst, int32_t src) {
- lea(rscratch2, dst);
- ldr(rscratch1, Address(rscratch2));
- add(rscratch1, rscratch1, src);
- str(rscratch1, Address(rscratch2));
- }
-
+ void addptr(const Address &dst, int32_t src);
void cmpptr(Register src1, Address src2);
// Various forms of CAS
diff --git a/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp
index cf2563f8623..ba8c3cc31b9 100644
--- a/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp
@@ -50,7 +50,7 @@ void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_
#ifdef ASSERT
static int check_nonzero(const char* xname, int x) {
- assert(x != 0, err_msg("%s should be nonzero", xname));
+ assert(x != 0, "%s should be nonzero", xname);
return x;
}
#define NONZERO(x) check_nonzero(#x, x)
@@ -407,7 +407,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
}
default:
- fatal(err_msg_res("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid)));
+ fatal("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid));
break;
}
diff --git a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp
index 457cfbc941a..60e26e08270 100644
--- a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp
@@ -101,6 +101,12 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC {
static bool maybe_cpool_ref(address instr) {
return is_adrp_at(instr) || is_ldr_literal_at(instr);
}
+
+ bool is_Membar() {
+ unsigned int insn = uint_at(0);
+ return Instruction_aarch64::extract(insn, 31, 12) == 0b11010101000000110011 &&
+ Instruction_aarch64::extract(insn, 7, 0) == 0b10111111;
+ }
};
inline NativeInstruction* nativeInstruction_at(address address) {
@@ -487,4 +493,15 @@ inline NativeCallTrampolineStub* nativeCallTrampolineStub_at(address addr) {
return (NativeCallTrampolineStub*)addr;
}
+class NativeMembar : public NativeInstruction {
+public:
+ unsigned int get_kind() { return Instruction_aarch64::extract(uint_at(0), 11, 8); }
+ void set_kind(int order_kind) { Instruction_aarch64::patch(addr_at(0), 11, 8, order_kind); }
+};
+
+inline NativeMembar *NativeMembar_at(address addr) {
+ assert(nativeInstruction_at(addr)->is_Membar(), "no membar found");
+ return (NativeMembar*)addr;
+}
+
#endif // CPU_AARCH64_VM_NATIVEINST_AARCH64_HPP
diff --git a/hotspot/src/cpu/aarch64/vm/relocInfo_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/relocInfo_aarch64.cpp
index e9819bd13c5..3ab4f0b7b2c 100644
--- a/hotspot/src/cpu/aarch64/vm/relocInfo_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/relocInfo_aarch64.cpp
@@ -102,12 +102,5 @@ void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffe
}
}
-void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
- if (NativeInstruction::maybe_cpool_ref(addr())) {
- address old_addr = old_addr_for(addr(), src, dest);
- MacroAssembler::pd_patch_instruction(addr(), MacroAssembler::target_addr_for_insn(old_addr));
- }
-}
-
void metadata_Relocation::pd_fix_value(address x) {
}
diff --git a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp
index f18563b84bb..7f6487a37aa 100644
--- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp
@@ -75,8 +75,8 @@ class SimpleRuntimeFrame {
// FIXME -- this is used by C1
class RegisterSaver {
public:
- static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words);
- static void restore_live_registers(MacroAssembler* masm);
+ static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors = false);
+ static void restore_live_registers(MacroAssembler* masm, bool restore_vectors = false);
// Offsets into the register save area
// Used by deoptimization when it is managing result register
@@ -108,7 +108,17 @@ class RegisterSaver {
};
-OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words) {
+OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) {
+#ifdef COMPILER2
+ if (save_vectors) {
+ // Save upper half of vector registers
+ int vect_words = 32 * 8 / wordSize;
+ additional_frame_words += vect_words;
+ }
+#else
+ assert(!save_vectors, "vectors are generated only by C2");
+#endif
+
int frame_size_in_bytes = round_to(additional_frame_words*wordSize +
reg_save_size*BytesPerInt, 16);
// OopMap frame size is in compiler stack slots (jint's) not bytes or words
@@ -122,7 +132,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
// Save registers, fpu state, and flags.
__ enter();
- __ push_CPU_state();
+ __ push_CPU_state(save_vectors);
// Set an oopmap for the call site. This oopmap will map all
// oop-registers and debug-info registers as callee-saved. This
@@ -139,14 +149,14 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
// register slots are 8 bytes
// wide, 32 floating-point
// registers
- oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset),
+ oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset + additional_frame_slots),
r->as_VMReg());
}
}
for (int i = 0; i < FloatRegisterImpl::number_of_registers; i++) {
FloatRegister r = as_FloatRegister(i);
- int sp_offset = 2 * i;
+ int sp_offset = save_vectors ? (4 * i) : (2 * i);
oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset),
r->as_VMReg());
}
@@ -154,8 +164,11 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
return oop_map;
}
-void RegisterSaver::restore_live_registers(MacroAssembler* masm) {
- __ pop_CPU_state();
+void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) {
+#ifndef COMPILER2
+ assert(!restore_vectors, "vectors are generated only by C2");
+#endif
+ __ pop_CPU_state(restore_vectors);
__ leave();
}
@@ -177,9 +190,9 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm) {
}
// Is vector's size (in bytes) bigger than a size saved by default?
-// 16 bytes XMM registers are saved by default using fxsave/fxrstor instructions.
+// 8 bytes vector registers are saved by default on AArch64.
bool SharedRuntime::is_wide_vector(int size) {
- return size > 16;
+ return size > 8;
}
// The java_calling_convention describes stack locations as ideal slots on
// a frame with no abi restrictions. Since we must observe abi restrictions
@@ -460,11 +473,11 @@ static void gen_c2i_adapter(MacroAssembler *masm,
}
-static void gen_i2c_adapter(MacroAssembler *masm,
- int total_args_passed,
- int comp_args_on_stack,
- const BasicType *sig_bt,
- const VMRegPair *regs) {
+void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
+ int total_args_passed,
+ int comp_args_on_stack,
+ const BasicType *sig_bt,
+ const VMRegPair *regs) {
// Note: r13 contains the senderSP on entry. We must preserve it since
// we may do a i2c -> c2i transition if we lose a race where compiled
@@ -1146,7 +1159,7 @@ static void rt_call(MacroAssembler* masm, address dest, int gpargs, int fpargs,
assert((unsigned)gpargs < 256, "eek!");
assert((unsigned)fpargs < 32, "eek!");
__ lea(rscratch1, RuntimeAddress(dest));
- __ mov(rscratch2, (gpargs << 6) | (fpargs << 2) | type);
+ if (UseBuiltinSim) __ mov(rscratch2, (gpargs << 6) | (fpargs << 2) | type);
__ blrt(rscratch1, rscratch2);
__ maybe_isb();
}
@@ -1194,7 +1207,7 @@ static void gen_special_dispatch(MacroAssembler* masm,
} else if (iid == vmIntrinsics::_invokeBasic) {
has_receiver = true;
} else {
- fatal(err_msg_res("unexpected intrinsic id %d", iid));
+ fatal("unexpected intrinsic id %d", iid);
}
if (member_reg != noreg) {
@@ -1521,14 +1534,13 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
int vep_offset = ((intptr_t)__ pc()) - start;
- // Generate stack overflow check
-
// If we have to make this method not-entrant we'll overwrite its
// first instruction with a jump. For this action to be legal we
// must ensure that this first instruction is a B, BL, NOP, BKPT,
// SVC, HVC, or SMC. Make it a NOP.
__ nop();
+ // Generate stack overflow check
if (UseStackBanging) {
__ bang_stack_with_offset(StackShadowPages*os::vm_page_size());
} else {
@@ -1709,23 +1721,20 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// need to spill before we call out
int c_arg = total_c_args - total_in_args;
- // Pre-load a static method's oop into r20. Used both by locking code and
- // the normal JNI call code.
+ // Pre-load a static method's oop into c_rarg1.
if (method->is_static() && !is_critical_native) {
// load oop into a register
- __ movoop(oop_handle_reg,
+ __ movoop(c_rarg1,
JNIHandles::make_local(method->method_holder()->java_mirror()),
/*immediate*/true);
// Now handlize the static class mirror it's known not-null.
- __ str(oop_handle_reg, Address(sp, klass_offset));
+ __ str(c_rarg1, Address(sp, klass_offset));
map->set_oop(VMRegImpl::stack2reg(klass_slot_offset));
// Now get the handle
- __ lea(oop_handle_reg, Address(sp, klass_offset));
- // store the klass handle as second argument
- __ mov(c_rarg1, oop_handle_reg);
+ __ lea(c_rarg1, Address(sp, klass_offset));
// and protect the arg if we must spill
c_arg--;
}
@@ -1740,19 +1749,13 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ set_last_Java_frame(sp, noreg, (address)the_pc, rscratch1);
-
- // We have all of the arguments setup at this point. We must not touch any register
- // argument registers at this point (what if we save/restore them there are no oop?
-
+ Label dtrace_method_entry, dtrace_method_entry_done;
{
- SkipIfEqual skip(masm, &DTraceMethodProbes, false);
- // protect the args we've loaded
- save_args(masm, total_c_args, c_arg, out_regs);
- __ mov_metadata(c_rarg1, method());
- __ call_VM_leaf(
- CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry),
- rthread, c_rarg1);
- restore_args(masm, total_c_args, c_arg, out_regs);
+ unsigned long offset;
+ __ adrp(rscratch1, ExternalAddress((address)&DTraceMethodProbes), offset);
+ __ ldrb(rscratch1, Address(rscratch1, offset));
+ __ cbnzw(rscratch1, dtrace_method_entry);
+ __ bind(dtrace_method_entry_done);
}
// RedefineClasses() tracing support for obsolete method entry
@@ -1782,7 +1785,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
if (method->is_synchronized()) {
assert(!is_critical_native, "unhandled");
-
const int mark_word_offset = BasicLock::displaced_header_offset_in_bytes();
// Get the handle (the 2nd argument)
@@ -1838,7 +1840,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Finally just about ready to make the JNI call
-
// get JNIEnv* which is first argument to native
if (!is_critical_native) {
__ lea(c_rarg0, Address(rthread, in_bytes(JavaThread::jni_environment_offset())));
@@ -1879,9 +1880,9 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Unpack native results.
switch (ret_type) {
- case T_BOOLEAN: __ ubfx(r0, r0, 0, 8); break;
+ case T_BOOLEAN: __ ubfx(r0, r0, 0, 8); break;
case T_CHAR : __ ubfx(r0, r0, 0, 16); break;
- case T_BYTE : __ sbfx(r0, r0, 0, 8); break;
+ case T_BYTE : __ sbfx(r0, r0, 0, 8); break;
case T_SHORT : __ sbfx(r0, r0, 0, 16); break;
case T_INT : __ sbfx(r0, r0, 0, 32); break;
case T_DOUBLE :
@@ -1904,14 +1905,17 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Thread A is resumed to finish this native method, but doesn't block here since it
// didn't see any synchronization is progress, and escapes.
__ mov(rscratch1, _thread_in_native_trans);
- __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
- __ stlrw(rscratch1, rscratch2);
if(os::is_MP()) {
if (UseMembar) {
+ __ strw(rscratch1, Address(rthread, JavaThread::thread_state_offset()));
+
// Force this write out before the read below
__ dmb(Assembler::SY);
} else {
+ __ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
+ __ stlrw(rscratch1, rscratch2);
+
// Write serialization page so VM thread can do a pseudo remote membar.
// We use the current thread pointer to calculate a thread specific
// offset to write to within the page. This minimizes bus traffic
@@ -1920,54 +1924,23 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
}
}
- Label after_transition;
-
// check for safepoint operation in progress and/or pending suspend requests
+ Label safepoint_in_progress, safepoint_in_progress_done;
{
- Label Continue;
-
- { unsigned long offset;
- __ adrp(rscratch1,
- ExternalAddress((address)SafepointSynchronize::address_of_state()),
- offset);
- __ ldrw(rscratch1, Address(rscratch1, offset));
- }
- __ cmpw(rscratch1, SafepointSynchronize::_not_synchronized);
-
- Label L;
- __ br(Assembler::NE, L);
+ assert(SafepointSynchronize::_not_synchronized == 0, "fix this code");
+ unsigned long offset;
+ __ adrp(rscratch1,
+ ExternalAddress((address)SafepointSynchronize::address_of_state()),
+ offset);
+ __ ldrw(rscratch1, Address(rscratch1, offset));
+ __ cbnzw(rscratch1, safepoint_in_progress);
__ ldrw(rscratch1, Address(rthread, JavaThread::suspend_flags_offset()));
- __ cbz(rscratch1, Continue);
- __ bind(L);
-
- // Don't use call_VM as it will see a possible pending exception and forward it
- // and never return here preventing us from clearing _last_native_pc down below.
- //
- save_native_result(masm, ret_type, stack_slots);
- __ mov(c_rarg0, rthread);
-#ifndef PRODUCT
- assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area");
-#endif
- if (!is_critical_native) {
- __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)));
- } else {
- __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans_and_transition)));
- }
- __ blrt(rscratch1, 1, 0, 1);
- __ maybe_isb();
- // Restore any method result value
- restore_native_result(masm, ret_type, stack_slots);
-
- if (is_critical_native) {
- // The call above performed the transition to thread_in_Java so
- // skip the transition logic below.
- __ b(after_transition);
- }
-
- __ bind(Continue);
+ __ cbnzw(rscratch1, safepoint_in_progress);
+ __ bind(safepoint_in_progress_done);
}
// change thread state
+ Label after_transition;
__ mov(rscratch1, _thread_in_Java);
__ lea(rscratch2, Address(rthread, JavaThread::thread_state_offset()));
__ stlrw(rscratch1, rscratch2);
@@ -2024,16 +1997,15 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
}
__ bind(done);
-
}
+
+ Label dtrace_method_exit, dtrace_method_exit_done;
{
- SkipIfEqual skip(masm, &DTraceMethodProbes, false);
- save_native_result(masm, ret_type, stack_slots);
- __ mov_metadata(c_rarg1, method());
- __ call_VM_leaf(
- CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit),
- rthread, c_rarg1);
- restore_native_result(masm, ret_type, stack_slots);
+ unsigned long offset;
+ __ adrp(rscratch1, ExternalAddress((address)&DTraceMethodProbes), offset);
+ __ ldrb(rscratch1, Address(rscratch1, offset));
+ __ cbnzw(rscratch1, dtrace_method_exit);
+ __ bind(dtrace_method_exit_done);
}
__ reset_last_Java_frame(false, true);
@@ -2082,7 +2054,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// Slow path locking & unlocking
if (method->is_synchronized()) {
- // BEGIN Slow path lock
+ __ block_comment("Slow path lock {");
__ bind(slow_path_lock);
// has last_Java_frame setup. No exceptions so do vanilla call not call_VM
@@ -2109,9 +2081,9 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
#endif
__ b(lock_done);
- // END Slow path lock
+ __ block_comment("} Slow path lock");
- // BEGIN Slow path unlock
+ __ block_comment("Slow path unlock {");
__ bind(slow_path_unlock);
// If we haven't already saved the native result we must save it now as xmm registers
@@ -2149,7 +2121,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
}
__ b(unlock_done);
- // END Slow path unlock
+ __ block_comment("} Slow path unlock");
} // synchronized
@@ -2162,6 +2134,69 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
// and continue
__ b(reguard_done);
+ // SLOW PATH safepoint
+ {
+ __ block_comment("safepoint {");
+ __ bind(safepoint_in_progress);
+
+ // Don't use call_VM as it will see a possible pending exception and forward it
+ // and never return here preventing us from clearing _last_native_pc down below.
+ //
+ save_native_result(masm, ret_type, stack_slots);
+ __ mov(c_rarg0, rthread);
+#ifndef PRODUCT
+ assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area");
+#endif
+ if (!is_critical_native) {
+ __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)));
+ } else {
+ __ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans_and_transition)));
+ }
+ __ blrt(rscratch1, 1, 0, 1);
+ __ maybe_isb();
+ // Restore any method result value
+ restore_native_result(masm, ret_type, stack_slots);
+
+ if (is_critical_native) {
+ // The call above performed the transition to thread_in_Java so
+ // skip the transition logic above.
+ __ b(after_transition);
+ }
+
+ __ b(safepoint_in_progress_done);
+ __ block_comment("} safepoint");
+ }
+
+ // SLOW PATH dtrace support
+ {
+ __ block_comment("dtrace entry {");
+ __ bind(dtrace_method_entry);
+
+ // We have all of the arguments setup at this point. We must not touch any register
+ // argument registers at this point (what if we save/restore them there are no oop?
+
+ save_args(masm, total_c_args, c_arg, out_regs);
+ __ mov_metadata(c_rarg1, method());
+ __ call_VM_leaf(
+ CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry),
+ rthread, c_rarg1);
+ restore_args(masm, total_c_args, c_arg, out_regs);
+ __ b(dtrace_method_entry_done);
+ __ block_comment("} dtrace entry");
+ }
+
+ {
+ __ block_comment("dtrace exit {");
+ __ bind(dtrace_method_exit);
+ save_native_result(masm, ret_type, stack_slots);
+ __ mov_metadata(c_rarg1, method());
+ __ call_VM_leaf(
+ CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit),
+ rthread, c_rarg1);
+ restore_native_result(masm, ret_type, stack_slots);
+ __ b(dtrace_method_exit_done);
+ __ block_comment("} dtrace exit");
+ }
__ flush();
@@ -2742,7 +2777,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP);
// Save registers, fpu state, and flags
- map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words);
+ map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_vectors);
// The following is basically a call_VM. However, we need the precise
// address of the call in order to generate an oopmap. Hence, we do all the
@@ -2793,7 +2828,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
__ bind(noException);
// Normal exit, restore registers and exit.
- RegisterSaver::restore_live_registers(masm);
+ RegisterSaver::restore_live_registers(masm, save_vectors);
__ ret(lr);
diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
index 56799453938..2eb119125f2 100644
--- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
@@ -746,6 +746,9 @@ class StubGenerator: public StubCodeGenerator {
const Register count = end; // 'end' register contains bytes count now
__ mov(scratch, (address)ct->byte_map_base);
__ add(start, start, scratch);
+ if (UseConcMarkSweepGC) {
+ __ membar(__ StoreStore);
+ }
__ BIND(L_loop);
__ strb(zr, Address(start, count));
__ subs(count, count, 1);
@@ -2395,6 +2398,274 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
+ /***
+ * Arguments:
+ *
+ * Inputs:
+ * c_rarg0 - int adler
+ * c_rarg1 - byte* buff
+ * c_rarg2 - int len
+ *
+ * Output:
+ * c_rarg0 - int adler result
+ */
+ address generate_updateBytesAdler32() {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "updateBytesAdler32");
+ address start = __ pc();
+
+ Label L_simple_by1_loop, L_nmax, L_nmax_loop, L_by16, L_by16_loop, L_by1_loop, L_do_mod, L_combine, L_by1;
+
+ // Aliases
+ Register adler = c_rarg0;
+ Register s1 = c_rarg0;
+ Register s2 = c_rarg3;
+ Register buff = c_rarg1;
+ Register len = c_rarg2;
+ Register nmax = r4;
+ Register base = r5;
+ Register count = r6;
+ Register temp0 = rscratch1;
+ Register temp1 = rscratch2;
+ Register temp2 = r7;
+
+ // Max number of bytes we can process before having to take the mod
+ // 0x15B0 is 5552 in decimal, the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+ unsigned long BASE = 0xfff1;
+ unsigned long NMAX = 0x15B0;
+
+ __ mov(base, BASE);
+ __ mov(nmax, NMAX);
+
+ // s1 is initialized to the lower 16 bits of adler
+ // s2 is initialized to the upper 16 bits of adler
+ __ ubfx(s2, adler, 16, 16); // s2 = ((adler >> 16) & 0xffff)
+ __ uxth(s1, adler); // s1 = (adler & 0xffff)
+
+ // The pipelined loop needs at least 16 elements for 1 iteration
+ // It does check this, but it is more effective to skip to the cleanup loop
+ __ cmp(len, 16);
+ __ br(Assembler::HS, L_nmax);
+ __ cbz(len, L_combine);
+
+ __ bind(L_simple_by1_loop);
+ __ ldrb(temp0, Address(__ post(buff, 1)));
+ __ add(s1, s1, temp0);
+ __ add(s2, s2, s1);
+ __ subs(len, len, 1);
+ __ br(Assembler::HI, L_simple_by1_loop);
+
+ // s1 = s1 % BASE
+ __ subs(temp0, s1, base);
+ __ csel(s1, temp0, s1, Assembler::HS);
+
+ // s2 = s2 % BASE
+ __ lsr(temp0, s2, 16);
+ __ lsl(temp1, temp0, 4);
+ __ sub(temp1, temp1, temp0);
+ __ add(s2, temp1, s2, ext::uxth);
+
+ __ subs(temp0, s2, base);
+ __ csel(s2, temp0, s2, Assembler::HS);
+
+ __ b(L_combine);
+
+ __ bind(L_nmax);
+ __ subs(len, len, nmax);
+ __ sub(count, nmax, 16);
+ __ br(Assembler::LO, L_by16);
+
+ __ bind(L_nmax_loop);
+
+ __ ldp(temp0, temp1, Address(__ post(buff, 16)));
+
+ __ add(s1, s1, temp0, ext::uxtb);
+ __ ubfx(temp2, temp0, 8, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp0, 16, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp0, 24, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp0, 32, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp0, 40, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp0, 48, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp0, Assembler::LSR, 56);
+ __ add(s2, s2, s1);
+
+ __ add(s1, s1, temp1, ext::uxtb);
+ __ ubfx(temp2, temp1, 8, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp1, 16, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp1, 24, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp1, 32, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp1, 40, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp1, 48, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp1, Assembler::LSR, 56);
+ __ add(s2, s2, s1);
+
+ __ subs(count, count, 16);
+ __ br(Assembler::HS, L_nmax_loop);
+
+ // s1 = s1 % BASE
+ __ lsr(temp0, s1, 16);
+ __ lsl(temp1, temp0, 4);
+ __ sub(temp1, temp1, temp0);
+ __ add(temp1, temp1, s1, ext::uxth);
+
+ __ lsr(temp0, temp1, 16);
+ __ lsl(s1, temp0, 4);
+ __ sub(s1, s1, temp0);
+ __ add(s1, s1, temp1, ext:: uxth);
+
+ __ subs(temp0, s1, base);
+ __ csel(s1, temp0, s1, Assembler::HS);
+
+ // s2 = s2 % BASE
+ __ lsr(temp0, s2, 16);
+ __ lsl(temp1, temp0, 4);
+ __ sub(temp1, temp1, temp0);
+ __ add(temp1, temp1, s2, ext::uxth);
+
+ __ lsr(temp0, temp1, 16);
+ __ lsl(s2, temp0, 4);
+ __ sub(s2, s2, temp0);
+ __ add(s2, s2, temp1, ext:: uxth);
+
+ __ subs(temp0, s2, base);
+ __ csel(s2, temp0, s2, Assembler::HS);
+
+ __ subs(len, len, nmax);
+ __ sub(count, nmax, 16);
+ __ br(Assembler::HS, L_nmax_loop);
+
+ __ bind(L_by16);
+ __ adds(len, len, count);
+ __ br(Assembler::LO, L_by1);
+
+ __ bind(L_by16_loop);
+
+ __ ldp(temp0, temp1, Address(__ post(buff, 16)));
+
+ __ add(s1, s1, temp0, ext::uxtb);
+ __ ubfx(temp2, temp0, 8, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp0, 16, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp0, 24, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp0, 32, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp0, 40, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp0, 48, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp0, Assembler::LSR, 56);
+ __ add(s2, s2, s1);
+
+ __ add(s1, s1, temp1, ext::uxtb);
+ __ ubfx(temp2, temp1, 8, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp1, 16, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp1, 24, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp1, 32, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp1, 40, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ ubfx(temp2, temp1, 48, 8);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp2);
+ __ add(s2, s2, s1);
+ __ add(s1, s1, temp1, Assembler::LSR, 56);
+ __ add(s2, s2, s1);
+
+ __ subs(len, len, 16);
+ __ br(Assembler::HS, L_by16_loop);
+
+ __ bind(L_by1);
+ __ adds(len, len, 15);
+ __ br(Assembler::LO, L_do_mod);
+
+ __ bind(L_by1_loop);
+ __ ldrb(temp0, Address(__ post(buff, 1)));
+ __ add(s1, temp0, s1);
+ __ add(s2, s2, s1);
+ __ subs(len, len, 1);
+ __ br(Assembler::HS, L_by1_loop);
+
+ __ bind(L_do_mod);
+ // s1 = s1 % BASE
+ __ lsr(temp0, s1, 16);
+ __ lsl(temp1, temp0, 4);
+ __ sub(temp1, temp1, temp0);
+ __ add(temp1, temp1, s1, ext::uxth);
+
+ __ lsr(temp0, temp1, 16);
+ __ lsl(s1, temp0, 4);
+ __ sub(s1, s1, temp0);
+ __ add(s1, s1, temp1, ext:: uxth);
+
+ __ subs(temp0, s1, base);
+ __ csel(s1, temp0, s1, Assembler::HS);
+
+ // s2 = s2 % BASE
+ __ lsr(temp0, s2, 16);
+ __ lsl(temp1, temp0, 4);
+ __ sub(temp1, temp1, temp0);
+ __ add(temp1, temp1, s2, ext::uxth);
+
+ __ lsr(temp0, temp1, 16);
+ __ lsl(s2, temp0, 4);
+ __ sub(s2, s2, temp0);
+ __ add(s2, s2, temp1, ext:: uxth);
+
+ __ subs(temp0, s2, base);
+ __ csel(s2, temp0, s2, Assembler::HS);
+
+ // Combine lower bits and higher bits
+ __ bind(L_combine);
+ __ orr(s1, s1, s2, Assembler::LSL, 16); // adler = s1 | (s2 << 16)
+
+ __ ret(lr);
+
+ return start;
+ }
+
/**
* Arguments:
*
@@ -3613,6 +3884,11 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C();
}
+ // generate Adler32 intrinsics code
+ if (UseAdler32Intrinsics) {
+ StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32();
+ }
+
// Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc,
diff --git a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp
index da9e973d83e..fb339033869 100644
--- a/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/templateInterpreter_aarch64.cpp
@@ -535,7 +535,7 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
// r0
// c_rarg0, c_rarg1, c_rarg2, c_rarg3, ...(param regs)
// rscratch1, rscratch2 (scratch regs)
-void InterpreterGenerator::lock_method(void) {
+void TemplateInterpreterGenerator::lock_method() {
// synchronize method
const Address access_flags(rmethod, Method::access_flags_offset());
const Address monitor_block_top(
@@ -721,8 +721,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// generate a vanilla interpreter entry as the slow path
__ bind(slow_path);
- (void) generate_normal_entry(false);
-
+ __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals));
return entry;
}
#endif // INCLUDE_ALL_GCS
@@ -779,12 +778,10 @@ address InterpreterGenerator::generate_CRC32_update_entry() {
// generate a vanilla native entry as the slow path
__ bind(slow_path);
-
- (void) generate_native_entry(false);
-
+ __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native));
return entry;
}
- return generate_native_entry(false);
+ return NULL;
}
/**
@@ -841,12 +838,10 @@ address InterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpret
// generate a vanilla native entry as the slow path
__ bind(slow_path);
-
- (void) generate_native_entry(false);
-
+ __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native));
return entry;
}
- return generate_native_entry(false);
+ return NULL;
}
void InterpreterGenerator::bang_stack_shadow_pages(bool native_call) {
diff --git a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp
index daf6163142f..37c0e5bbb63 100644
--- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp
@@ -178,9 +178,8 @@ void VM_Version::get_processor_features() {
warning("UseCRC32 specified, but not supported on this CPU");
}
- if (UseAdler32Intrinsics) {
- warning("Adler32Intrinsics not available on this CPU.");
- FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
+ if (FLAG_IS_DEFAULT(UseAdler32Intrinsics)) {
+ FLAG_SET_DEFAULT(UseAdler32Intrinsics, true);
}
if (auxv & HWCAP_AES) {
diff --git a/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp
index d797ef6eb8c..d41e391b4bc 100644
--- a/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp
+++ b/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp
@@ -60,6 +60,7 @@ define_pd_global(intx, LoopUnrollLimit, 60);
define_pd_global(bool, OptoPeephole, false);
define_pd_global(bool, UseCISCSpill, false);
define_pd_global(bool, OptoBundling, false);
+define_pd_global(bool, OptoRegScheduling, false);
// GL:
// Detected a problem with unscaled compressed oops and
// narrow_oop_use_complex_address() == false.
diff --git a/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp b/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp
index 762a329e259..41b5125f06e 100644
--- a/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp
@@ -94,10 +94,12 @@ bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) {
const int IC_pos_in_java_to_interp_stub = 8;
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark/* = NULL*/) {
#ifdef COMPILER2
- // Get the mark within main instrs section which is set to the address of the call.
- address call_addr = cbuf.insts_mark();
+ if (mark == NULL) {
+ // Get the mark within main instrs section which is set to the address of the call.
+ mark = cbuf.insts_mark();
+ }
// Note that the code buffer's insts_mark is always relative to insts.
// That's why we must use the macroassembler to generate a stub.
@@ -117,7 +119,7 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
// Create a static stub relocation which relates this stub
// with the call instruction at insts_call_instruction_offset in the
// instructions code-section.
- __ relocate(static_stub_Relocation::spec(call_addr));
+ __ relocate(static_stub_Relocation::spec(mark));
const int stub_start_offset = __ offset();
// Now, create the stub's code:
diff --git a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp
index 238f50ee3d4..fac126363a0 100644
--- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp
+++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp
@@ -41,6 +41,18 @@ define_pd_global(bool, ImplicitNullChecks, true); // Generate code for impli
define_pd_global(bool, TrapBasedNullChecks, true);
define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs passed to check cast.
+#define DEFAULT_STACK_YELLOW_PAGES (6)
+#define DEFAULT_STACK_RED_PAGES (1)
+#define DEFAULT_STACK_SHADOW_PAGES (6 DEBUG_ONLY(+2))
+
+#define MIN_STACK_YELLOW_PAGES (1)
+#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
+#define MIN_STACK_SHADOW_PAGES (1)
+
+define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
+define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
+define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
+
// Use large code-entry alignment.
define_pd_global(intx, CodeEntryAlignment, 128);
define_pd_global(intx, OptoLoopAlignment, 16);
diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp
index f32d8e590c1..be9c8da7124 100644
--- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp
+++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp
@@ -46,7 +46,7 @@ void InterpreterMacroAssembler::null_check_throw(Register a, int offset, Registe
MacroAssembler::null_check_throw(a, offset, temp_reg, exception_entry);
}
-void InterpreterMacroAssembler::branch_to_entry(address entry, Register Rscratch) {
+void InterpreterMacroAssembler::jump_to_entry(address entry, Register Rscratch) {
assert(entry, "Entry must have been generated by now");
if (is_within_range_of_b(entry, pc())) {
b(entry);
diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp
index 571f87e45cd..9692e65225c 100644
--- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp
+++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp
@@ -39,7 +39,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
void null_check_throw(Register a, int offset, Register temp_reg);
- void branch_to_entry(address entry, Register Rscratch);
+ void jump_to_entry(address entry, Register Rscratch);
// Handy address generation macros.
#define thread_(field_name) in_bytes(JavaThread::field_name ## _offset()), R16_thread
diff --git a/hotspot/src/cpu/ppc/vm/interpreterGenerator_ppc.hpp b/hotspot/src/cpu/ppc/vm/interpreterGenerator_ppc.hpp
index 29cac0e2c89..02a6931b662 100644
--- a/hotspot/src/cpu/ppc/vm/interpreterGenerator_ppc.hpp
+++ b/hotspot/src/cpu/ppc/vm/interpreterGenerator_ppc.hpp
@@ -31,12 +31,12 @@
private:
address generate_abstract_entry(void);
- address generate_jump_to_normal_entry(void);
- address generate_accessor_entry(void) { return generate_jump_to_normal_entry(); }
- address generate_empty_entry(void) { return generate_jump_to_normal_entry(); }
+ address generate_accessor_entry(void) { return NULL; }
+ address generate_empty_entry(void) { return NULL; }
address generate_Reference_get_entry(void);
address generate_CRC32_update_entry();
address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind);
+ address generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return NULL; }
#endif // CPU_PPC_VM_INTERPRETERGENERATOR_PPC_HPP
diff --git a/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp b/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp
index 7f301e255b0..08e4a4fc54f 100644
--- a/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp
@@ -427,18 +427,6 @@ address AbstractInterpreterGenerator::generate_result_handler_for(BasicType type
return entry;
}
-// Call an accessor method (assuming it is resolved, otherwise drop into
-// vanilla (slow path) entry.
-address InterpreterGenerator::generate_jump_to_normal_entry(void) {
- address entry = __ pc();
- address normal_entry = Interpreter::entry_for_kind(Interpreter::zerolocals);
- assert(normal_entry != NULL, "should already be generated.");
- __ branch_to_entry(normal_entry, R11_scratch1);
- __ flush();
-
- return entry;
-}
-
// Abstract method entry.
//
address InterpreterGenerator::generate_abstract_entry(void) {
@@ -529,13 +517,13 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// regular method entry code to generate the NPE.
//
- address entry = __ pc();
-
- const int referent_offset = java_lang_ref_Reference::referent_offset;
- guarantee(referent_offset > 0, "referent offset not initialized");
-
if (UseG1GC) {
- Label slow_path;
+ address entry = __ pc();
+
+ const int referent_offset = java_lang_ref_Reference::referent_offset;
+ guarantee(referent_offset > 0, "referent offset not initialized");
+
+ Label slow_path;
// Debugging not possible, so can't use __ skip_if_jvmti_mode(slow_path, GR31_SCRATCH);
@@ -577,13 +565,11 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// Generate regular method entry.
__ bind(slow_path);
- __ branch_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals), R11_scratch1);
- __ flush();
-
+ __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals), R11_scratch1);
return entry;
- } else {
- return generate_jump_to_normal_entry();
}
+
+ return NULL;
}
void Deoptimization::unwind_callee_save_values(frame* f, vframeArray* vframe_array) {
diff --git a/hotspot/src/cpu/ppc/vm/jvmciCodeInstaller_ppc.cpp b/hotspot/src/cpu/ppc/vm/jvmciCodeInstaller_ppc.cpp
new file mode 100644
index 00000000000..cab965e3cc9
--- /dev/null
+++ b/hotspot/src/cpu/ppc/vm/jvmciCodeInstaller_ppc.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "vmreg_ppc.inline.hpp"
+
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+ Unimplemented();
+ return 0;
+}
+
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+ Unimplemented();
+}
+
+void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
+ Unimplemented();
+}
+
+// convert JVMCI register indices (as used in oop maps) to HotSpot registers
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg) {
+ return NULL;
+}
+
+bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) {
+ return false;
+}
diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp
index 703818d0a51..3310f37f57a 100644
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp
@@ -594,13 +594,6 @@ void MacroAssembler::bxx64_patchable(address dest, relocInfo::relocType rt, bool
"can't identify emitted call");
} else {
// variant 1:
-#if defined(ABI_ELFv2)
- nop();
- calculate_address_from_global_toc(R12, dest, true, true, false);
- mtctr(R12);
- nop();
- nop();
-#else
mr(R0, R11); // spill R11 -> R0.
// Load the destination address into CTR,
@@ -610,7 +603,6 @@ void MacroAssembler::bxx64_patchable(address dest, relocInfo::relocType rt, bool
mtctr(R11);
mr(R11, R0); // spill R11 <- R0.
nop();
-#endif
// do the call/jump
if (link) {
@@ -4292,7 +4284,7 @@ const char* stop_types[] = {
static void stop_on_request(int tp, const char* msg) {
tty->print("PPC assembly code requires stop: (%s) %s\n", stop_types[tp%/*stop_end*/4], msg);
- guarantee(false, err_msg("PPC assembly code requires stop: %s", msg));
+ guarantee(false, "PPC assembly code requires stop: %s", msg);
}
// Call a C-function that prints output.
diff --git a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp
index 5c9d2f1622a..980c043f9e7 100644
--- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp
@@ -60,7 +60,7 @@ void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_
#ifdef ASSERT
static int check_nonzero(const char* xname, int x) {
- assert(x != 0, err_msg("%s should be nonzero", xname));
+ assert(x != 0, "%s should be nonzero", xname);
return x;
}
#define NONZERO(x) check_nonzero(#x, x)
@@ -434,7 +434,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
}
default:
- fatal(err_msg_res("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid)));
+ fatal("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid));
break;
}
diff --git a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp
index 6a8b9a479af..ecca49af2ef 100644
--- a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp
@@ -149,7 +149,7 @@ void NativeCall::verify() {
if (!NativeCall::is_call_at(addr)) {
tty->print_cr("not a NativeCall at " PTR_FORMAT, p2i(addr));
// TODO: PPC port: Disassembler::decode(addr - 20, addr + 20, tty);
- fatal(err_msg("not a NativeCall at " PTR_FORMAT, p2i(addr)));
+ fatal("not a NativeCall at " PTR_FORMAT, p2i(addr));
}
}
#endif // ASSERT
@@ -162,7 +162,7 @@ void NativeFarCall::verify() {
if (!NativeFarCall::is_far_call_at(addr)) {
tty->print_cr("not a NativeFarCall at " PTR_FORMAT, p2i(addr));
// TODO: PPC port: Disassembler::decode(addr, 20, 20, tty);
- fatal(err_msg("not a NativeFarCall at " PTR_FORMAT, p2i(addr)));
+ fatal("not a NativeFarCall at " PTR_FORMAT, p2i(addr));
}
}
#endif // ASSERT
@@ -308,7 +308,7 @@ void NativeMovConstReg::verify() {
! MacroAssembler::is_bl(*((int*) addr))) {
tty->print_cr("not a NativeMovConstReg at " PTR_FORMAT, p2i(addr));
// TODO: PPC port: Disassembler::decode(addr, 20, 20, tty);
- fatal(err_msg("not a NativeMovConstReg at " PTR_FORMAT, p2i(addr)));
+ fatal("not a NativeMovConstReg at " PTR_FORMAT, p2i(addr));
}
}
}
@@ -346,7 +346,7 @@ void NativeJump::verify() {
if (!NativeJump::is_jump_at(addr)) {
tty->print_cr("not a NativeJump at " PTR_FORMAT, p2i(addr));
// TODO: PPC port: Disassembler::decode(addr, 20, 20, tty);
- fatal(err_msg("not a NativeJump at " PTR_FORMAT, p2i(addr)));
+ fatal("not a NativeJump at " PTR_FORMAT, p2i(addr));
}
}
#endif // ASSERT
diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad
index 5e0e977e287..d5f6486056b 100644
--- a/hotspot/src/cpu/ppc/vm/ppc.ad
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad
@@ -2064,6 +2064,10 @@ const bool Matcher::match_rule_supported(int opcode) {
return true; // Per default match rules are supported.
}
+const int Matcher::float_pressure(int default_pressure_threshold) {
+ return default_pressure_threshold;
+}
+
int Matcher::regnum_to_fpu_offset(int regnum) {
// No user for this method?
Unimplemented();
diff --git a/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp b/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp
index 69dc0551f7b..f075c714748 100644
--- a/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/relocInfo_ppc.cpp
@@ -125,8 +125,5 @@ address Relocation::pd_get_address_from_code() {
void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
}
-void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
-}
-
void metadata_Relocation::pd_fix_value(address x) {
}
diff --git a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp
index f3b02e0bf9f..e6853776063 100644
--- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp
@@ -475,9 +475,8 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm, int frame_siz
// Is vector's size (in bytes) bigger than a size saved by default?
bool SharedRuntime::is_wide_vector(int size) {
- ResourceMark rm;
// Note, MaxVectorSize == 8 on PPC64.
- assert(size <= 8, err_msg_res("%d bytes vectors are not supported", size));
+ assert(size <= 8, "%d bytes vectors are not supported", size);
return size > 8;
}
#ifdef COMPILER2
@@ -957,11 +956,11 @@ static address gen_c2i_adapter(MacroAssembler *masm,
return c2i_entrypoint;
}
-static void gen_i2c_adapter(MacroAssembler *masm,
- int total_args_passed,
- int comp_args_on_stack,
- const BasicType *sig_bt,
- const VMRegPair *regs) {
+void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
+ int total_args_passed,
+ int comp_args_on_stack,
+ const BasicType *sig_bt,
+ const VMRegPair *regs) {
// Load method's entry-point from method.
__ ld(R12_scratch2, in_bytes(Method::from_compiled_offset()), R19_method);
@@ -1631,7 +1630,7 @@ static void gen_special_dispatch(MacroAssembler* masm,
} else if (iid == vmIntrinsics::_invokeBasic) {
has_receiver = true;
} else {
- fatal(err_msg_res("unexpected intrinsic id %d", iid));
+ fatal("unexpected intrinsic id %d", iid);
}
if (member_reg != noreg) {
diff --git a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp
index 8809e163067..1f0d252229d 100644
--- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp
@@ -841,7 +841,7 @@ class StubGenerator: public StubCodeGenerator {
// Only called by MacroAssembler::verify_oop
static void verify_oop_helper(const char* message, oop o) {
if (!o->is_oop_or_null()) {
- fatal(message);
+ fatal("%s", message);
}
++ StubRoutines::_verify_oop_count;
}
diff --git a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp
index b6d8e26b18d..361e637d253 100644
--- a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp
@@ -620,7 +620,7 @@ inline bool math_entry_available(AbstractInterpreter::MethodKind kind) {
address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) {
if (!math_entry_available(kind)) {
NOT_PRODUCT(__ should_not_reach_here();)
- return Interpreter::entry_for_kind(Interpreter::zerolocals);
+ return NULL;
}
address entry = __ pc();
@@ -1126,14 +1126,6 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {
generate_fixed_frame(false, Rsize_of_parameters, Rsize_of_locals);
-#ifdef FAST_DISPATCH
- __ unimplemented("Fast dispatch in generate_normal_entry");
-#if 0
- __ set((intptr_t)Interpreter::dispatch_table(), IdispatchTables);
- // Set bytecode dispatch table base.
-#endif
-#endif
-
// --------------------------------------------------------------------------
// Zero out non-parameter locals.
// Note: *Always* zero out non-parameter locals as Sparc does. It's not
@@ -1266,9 +1258,8 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {
* int java.util.zip.CRC32.update(int crc, int b)
*/
address InterpreterGenerator::generate_CRC32_update_entry() {
- address start = __ pc(); // Remember stub start address (is rtn value).
-
if (UseCRC32Intrinsics) {
+ address start = __ pc(); // Remember stub start address (is rtn value).
Label slow_path;
// Safepoint check
@@ -1313,11 +1304,11 @@ address InterpreterGenerator::generate_CRC32_update_entry() {
// Generate a vanilla native entry as the slow path.
BLOCK_COMMENT("} CRC32_update");
BIND(slow_path);
+ __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native), R11_scratch1);
+ return start;
}
- (void) generate_native_entry(false);
-
- return start;
+ return NULL;
}
// CRC32 Intrinsics.
@@ -1327,9 +1318,8 @@ address InterpreterGenerator::generate_CRC32_update_entry() {
* int java.util.zip.CRC32.updateByteBuffer(int crc, long* buf, int off, int len)
*/
address InterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) {
- address start = __ pc(); // Remember stub start address (is rtn value).
-
if (UseCRC32Intrinsics) {
+ address start = __ pc(); // Remember stub start address (is rtn value).
Label slow_path;
// Safepoint check
@@ -1406,11 +1396,11 @@ address InterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpret
// Generate a vanilla native entry as the slow path.
BLOCK_COMMENT("} CRC32_updateBytes(Buffer)");
BIND(slow_path);
+ __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native), R11_scratch1);
+ return start;
}
- (void) generate_native_entry(false);
-
- return start;
+ return NULL;
}
// These should never be compiled since the interpreter will prefer
diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp
index 42ed9b6b992..d4fd95ebce1 100644
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp
@@ -389,7 +389,7 @@ class Assembler : public AbstractAssembler {
static void assert_signed_range(intptr_t x, int nbits) {
assert(nbits == 32 || (-(1 << nbits-1) <= x && x < ( 1 << nbits-1)),
- err_msg("value out of range: x=" INTPTR_FORMAT ", nbits=%d", x, nbits));
+ "value out of range: x=" INTPTR_FORMAT ", nbits=%d", x, nbits);
}
static void assert_signed_word_disp_range(intptr_t x, int nbits) {
diff --git a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp
index 3fc18fa4dd0..39592b6e0eb 100644
--- a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp
@@ -64,6 +64,7 @@ define_pd_global(bool, OptoPeephole, false);
define_pd_global(bool, UseCISCSpill, false);
define_pd_global(bool, OptoBundling, false);
define_pd_global(bool, OptoScheduling, true);
+define_pd_global(bool, OptoRegScheduling, false);
#ifdef _LP64
// We need to make sure that all generated code is within
diff --git a/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp b/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp
index b6021917710..d56af1661b1 100644
--- a/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp
@@ -53,14 +53,15 @@ bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) {
// ----------------------------------------------------------------------------
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
-#ifdef COMPILER2
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
// Stub is fixed up when the corresponding call is converted from calling
// compiled code to calling interpreted code.
// set (empty), G5
// jmp -1
- address mark = cbuf.insts_mark(); // Get mark within main instrs section.
+ if (mark == NULL) {
+ mark = cbuf.insts_mark(); // Get mark within main instrs section.
+ }
MacroAssembler _masm(&cbuf);
@@ -80,12 +81,11 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
__ delayed()->nop();
+ assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size");
+
// Update current stubs pointer and restore code_end.
__ end_a_stub();
return base;
-#else
- ShouldNotReachHere();
-#endif
}
#undef __
diff --git a/hotspot/src/cpu/sparc/vm/cppInterpreterGenerator_sparc.hpp b/hotspot/src/cpu/sparc/vm/cppInterpreterGenerator_sparc.hpp
index 2dc68c74f63..70d7000b3c8 100644
--- a/hotspot/src/cpu/sparc/vm/cppInterpreterGenerator_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/cppInterpreterGenerator_sparc.hpp
@@ -31,6 +31,7 @@
void generate_more_monitors();
void generate_deopt_handling();
+ void lock_method(void);
void adjust_callers_stack(Register args);
void generate_compute_interpreter_state(const Register state,
const Register prev_state,
diff --git a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp
index 4a84b6c3387..8fd601277c7 100644
--- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp
@@ -468,7 +468,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// If G1 is not enabled then attempt to go through the accessor entry point
// Reference.get is an accessor
- return generate_jump_to_normal_entry();
+ return NULL;
}
//
@@ -1164,7 +1164,7 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
}
// Find preallocated monitor and lock method (C++ interpreter)
//
-void InterpreterGenerator::lock_method(void) {
+void CppInterpreterGenerator::lock_method() {
// Lock the current method.
// Destroys registers L2_scratch, L3_scratch, O0
//
diff --git a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp
index 9446fdbc2c7..36f660b554b 100644
--- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp
@@ -52,19 +52,27 @@ define_pd_global(intx, OptoLoopAlignment, 16); // = 4*wordSize
define_pd_global(intx, InlineFrequencyCount, 50); // we can use more inlining on the SPARC
define_pd_global(intx, InlineSmallCode, 1500);
+#define DEFAULT_STACK_YELLOW_PAGES (2)
+#define DEFAULT_STACK_RED_PAGES (1)
+
#ifdef _LP64
// Stack slots are 2X larger in LP64 than in the 32 bit VM.
define_pd_global(intx, ThreadStackSize, 1024);
define_pd_global(intx, VMThreadStackSize, 1024);
-define_pd_global(intx, StackShadowPages, 10 DEBUG_ONLY(+1));
+#define DEFAULT_STACK_SHADOW_PAGES (10 DEBUG_ONLY(+1))
#else
define_pd_global(intx, ThreadStackSize, 512);
define_pd_global(intx, VMThreadStackSize, 512);
-define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1));
-#endif
+#define DEFAULT_STACK_SHADOW_PAGES (3 DEBUG_ONLY(+1))
+#endif // _LP64
-define_pd_global(intx, StackYellowPages, 2);
-define_pd_global(intx, StackRedPages, 1);
+#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
+#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
+#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
+
+define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
+define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
+define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
@@ -82,6 +90,7 @@ define_pd_global(uintx, TypeProfileLevel, 111);
\
product(intx, UseVIS, 99, \
"Highest supported VIS instructions set on Sparc") \
+ range(0, 99) \
\
product(bool, UseCBCond, false, \
"Use compare and branch instruction on SPARC") \
@@ -91,12 +100,14 @@ define_pd_global(uintx, TypeProfileLevel, 111);
\
product(intx, BlockZeroingLowLimit, 2048, \
"Minimum size in bytes when block zeroing will be used") \
+ range(1, max_jint) \
\
product(bool, UseBlockCopy, false, \
"Use special cpu instructions for block copy") \
\
product(intx, BlockCopyLowLimit, 2048, \
"Minimum size in bytes when block copy will be used") \
+ range(1, max_jint) \
\
develop(bool, UseV8InstrsOnly, false, \
"Use SPARC-V8 Compliant instruction subset") \
@@ -108,9 +119,11 @@ define_pd_global(uintx, TypeProfileLevel, 111);
"Do not use swap instructions, but only CAS (in a loop) on SPARC")\
\
product(uintx, ArraycopySrcPrefetchDistance, 0, \
- "Distance to prefetch source array in arracopy") \
+ "Distance to prefetch source array in arraycopy") \
+ constraint(ArraycopySrcPrefetchDistanceConstraintFunc, AfterErgo) \
\
product(uintx, ArraycopyDstPrefetchDistance, 0, \
- "Distance to prefetch destination array in arracopy") \
+ "Distance to prefetch destination array in arraycopy") \
+ constraint(ArraycopyDstPrefetchDistanceConstraintFunc, AfterErgo) \
#endif // CPU_SPARC_VM_GLOBALS_SPARC_HPP
diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp
index e69dba4d531..b53156f1393 100644
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp
@@ -59,6 +59,13 @@ const Address InterpreterMacroAssembler::d_tmp(FP, (frame::interpreter_frame_d_s
#endif // CC_INTERP
+void InterpreterMacroAssembler::jump_to_entry(address entry) {
+ assert(entry, "Entry must have been generated by now");
+ AddressLiteral al(entry);
+ jump_to(al, G3_scratch);
+ delayed()->nop();
+}
+
void InterpreterMacroAssembler::compute_extra_locals_size_in_bytes(Register args_size, Register locals_size, Register delta) {
// Note: this algorithm is also used by C1's OSR entry sequence.
// Any changes should also be applied to CodeEmitter::emit_osr_entry().
@@ -1643,26 +1650,73 @@ void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
bind(skip_receiver_profile);
// The method data pointer needs to be updated to reflect the new target.
+#if INCLUDE_JVMCI
+ if (MethodProfileWidth == 0) {
+ update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size()));
+ }
+#else
update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size()));
- bind (profile_continue);
+#endif
+ bind(profile_continue);
}
}
-void InterpreterMacroAssembler::record_klass_in_profile_helper(
- Register receiver, Register scratch,
- int start_row, Label& done, bool is_virtual_call) {
+#if INCLUDE_JVMCI
+void InterpreterMacroAssembler::profile_called_method(Register method, Register scratch) {
+ assert_different_registers(method, scratch);
+ if (ProfileInterpreter && MethodProfileWidth > 0) {
+ Label profile_continue;
+
+ // If no method data exists, go to profile_continue.
+ test_method_data_pointer(profile_continue);
+
+ Label done;
+ record_item_in_profile_helper(method, scratch, 0, done, MethodProfileWidth,
+ &VirtualCallData::method_offset, &VirtualCallData::method_count_offset, in_bytes(VirtualCallData::nonprofiled_receiver_count_offset()));
+ bind(done);
+
+ update_mdp_by_constant(in_bytes(VirtualCallData::virtual_call_data_size()));
+ bind(profile_continue);
+ }
+}
+#endif // INCLUDE_JVMCI
+
+void InterpreterMacroAssembler::record_klass_in_profile_helper(Register receiver, Register scratch,
+ Label& done, bool is_virtual_call) {
if (TypeProfileWidth == 0) {
if (is_virtual_call) {
increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch);
}
- return;
- }
+#if INCLUDE_JVMCI
+ else if (EnableJVMCI) {
+ increment_mdp_data_at(in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset()), scratch);
+ }
+#endif
+ } else {
+ int non_profiled_offset = -1;
+ if (is_virtual_call) {
+ non_profiled_offset = in_bytes(CounterData::count_offset());
+ }
+#if INCLUDE_JVMCI
+ else if (EnableJVMCI) {
+ non_profiled_offset = in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset());
+ }
+#endif
- int last_row = VirtualCallData::row_limit() - 1;
+ record_item_in_profile_helper(receiver, scratch, 0, done, TypeProfileWidth,
+ &VirtualCallData::receiver_offset, &VirtualCallData::receiver_count_offset, non_profiled_offset);
+ }
+}
+
+void InterpreterMacroAssembler::record_item_in_profile_helper(Register item,
+ Register scratch, int start_row, Label& done, int total_rows,
+ OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
+ int non_profiled_offset) {
+ int last_row = total_rows - 1;
assert(start_row <= last_row, "must be work left to do");
- // Test this row for both the receiver and for null.
+ // Test this row for both the item and for null.
// Take any of three different outcomes:
- // 1. found receiver => increment count and goto done
+ // 1. found item => increment count and goto done
// 2. found null => keep looking for case 1, maybe allocate this cell
// 3. found something else => keep looking for cases 1 and 2
// Case 3 is handled by a recursive call.
@@ -1670,28 +1724,28 @@ void InterpreterMacroAssembler::record_klass_in_profile_helper(
Label next_test;
bool test_for_null_also = (row == start_row);
- // See if the receiver is receiver[n].
- int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row));
- test_mdp_data_at(recvr_offset, receiver, next_test, scratch);
+ // See if the item is item[n].
+ int item_offset = in_bytes(item_offset_fn(row));
+ test_mdp_data_at(item_offset, item, next_test, scratch);
// delayed()->tst(scratch);
- // The receiver is receiver[n]. Increment count[n].
- int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row));
+ // The receiver is item[n]. Increment count[n].
+ int count_offset = in_bytes(item_count_offset_fn(row));
increment_mdp_data_at(count_offset, scratch);
ba_short(done);
bind(next_test);
if (test_for_null_also) {
Label found_null;
- // Failed the equality check on receiver[n]... Test for null.
+ // Failed the equality check on item[n]... Test for null.
if (start_row == last_row) {
// The only thing left to do is handle the null case.
- if (is_virtual_call) {
+ if (non_profiled_offset >= 0) {
brx(Assembler::zero, false, Assembler::pn, found_null);
delayed()->nop();
- // Receiver did not match any saved receiver and there is no empty row for it.
+ // Item did not match any saved item and there is no empty row for it.
// Increment total counter to indicate polymorphic case.
- increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch);
+ increment_mdp_data_at(non_profiled_offset, scratch);
ba_short(done);
bind(found_null);
} else {
@@ -1705,21 +1759,22 @@ void InterpreterMacroAssembler::record_klass_in_profile_helper(
delayed()->nop();
// Put all the "Case 3" tests here.
- record_klass_in_profile_helper(receiver, scratch, start_row + 1, done, is_virtual_call);
+ record_item_in_profile_helper(item, scratch, start_row + 1, done, total_rows,
+ item_offset_fn, item_count_offset_fn, non_profiled_offset);
- // Found a null. Keep searching for a matching receiver,
+ // Found a null. Keep searching for a matching item,
// but remember that this is an empty (unused) slot.
bind(found_null);
}
}
- // In the fall-through case, we found no matching receiver, but we
- // observed the receiver[start_row] is NULL.
+ // In the fall-through case, we found no matching item, but we
+ // observed the item[start_row] is NULL.
- // Fill in the receiver field and increment the count.
- int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row));
- set_mdp_data_at(recvr_offset, receiver);
- int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row));
+ // Fill in the item field and increment the count.
+ int item_offset = in_bytes(item_offset_fn(start_row));
+ set_mdp_data_at(item_offset, item);
+ int count_offset = in_bytes(item_count_offset_fn(start_row));
mov(DataLayout::counter_increment, scratch);
set_mdp_data_at(count_offset, scratch);
if (start_row > 0) {
@@ -1732,7 +1787,7 @@ void InterpreterMacroAssembler::record_klass_in_profile(Register receiver,
assert(ProfileInterpreter, "must be profiling");
Label done;
- record_klass_in_profile_helper(receiver, scratch, 0, done, is_virtual_call);
+ record_klass_in_profile_helper(receiver, scratch, done, is_virtual_call);
bind (done);
}
@@ -1788,7 +1843,7 @@ void InterpreterMacroAssembler::profile_null_seen(Register scratch) {
// The method data pointer needs to be updated.
int mdp_delta = in_bytes(BitData::bit_data_size());
if (TypeProfileCasts) {
- mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size());
+ mdp_delta = in_bytes(ReceiverTypeData::receiver_type_data_size());
}
update_mdp_by_constant(mdp_delta);
@@ -1806,7 +1861,7 @@ void InterpreterMacroAssembler::profile_typecheck(Register klass,
int mdp_delta = in_bytes(BitData::bit_data_size());
if (TypeProfileCasts) {
- mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size());
+ mdp_delta = in_bytes(ReceiverTypeData::receiver_type_data_size());
// Record the object type.
record_klass_in_profile(klass, scratch, false);
@@ -1828,7 +1883,7 @@ void InterpreterMacroAssembler::profile_typecheck_failed(Register scratch) {
int count_offset = in_bytes(CounterData::count_offset());
// Back up the address, since we have already bumped the mdp.
- count_offset -= in_bytes(VirtualCallData::virtual_call_data_size());
+ count_offset -= in_bytes(ReceiverTypeData::receiver_type_data_size());
// *Decrement* the counter. We expect to see zero or small negatives.
increment_mdp_data_at(count_offset, scratch, true);
diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp
index 042cccd2ec2..b944bf089c3 100644
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp
@@ -30,6 +30,8 @@
// This file specializes the assember with interpreter-specific macros
+typedef ByteSize (*OffsetFunction)(uint);
+
REGISTER_DECLARATION( Register, Otos_i , O0); // tos for ints, etc
REGISTER_DECLARATION( Register, Otos_l , O0); // for longs
REGISTER_DECLARATION( Register, Otos_l1, O0); // for 1st part of longs
@@ -80,6 +82,8 @@ class InterpreterMacroAssembler: public MacroAssembler {
InterpreterMacroAssembler(CodeBuffer* c)
: MacroAssembler(c) {}
+ void jump_to_entry(address entry);
+
#ifndef CC_INTERP
virtual void load_earlyret_value(TosState state);
@@ -299,7 +303,11 @@ class InterpreterMacroAssembler: public MacroAssembler {
void record_klass_in_profile(Register receiver, Register scratch, bool is_virtual_call);
void record_klass_in_profile_helper(Register receiver, Register scratch,
- int start_row, Label& done, bool is_virtual_call);
+ Label& done, bool is_virtual_call);
+ void record_item_in_profile_helper(Register item,
+ Register scratch, int start_row, Label& done, int total_rows,
+ OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
+ int non_profiled_offset);
void update_mdp_by_offset(int offset_of_disp, Register scratch);
void update_mdp_by_offset(Register reg, int offset_of_disp,
@@ -312,6 +320,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
void profile_call(Register scratch);
void profile_final_call(Register scratch);
void profile_virtual_call(Register receiver, Register scratch, bool receiver_can_be_null = false);
+ void profile_called_method(Register method, Register scratch) NOT_JVMCI_RETURN;
void profile_ret(TosState state, Register return_bci, Register scratch);
void profile_null_seen(Register scratch);
void profile_typecheck(Register klass, Register scratch);
diff --git a/hotspot/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp b/hotspot/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp
index de4997bce7a..287e9f2971a 100644
--- a/hotspot/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp
@@ -34,11 +34,9 @@
address generate_abstract_entry(void);
// there are no math intrinsics on sparc
address generate_math_entry(AbstractInterpreter::MethodKind kind) { return NULL; }
- address generate_jump_to_normal_entry(void);
- address generate_accessor_entry(void) { return generate_jump_to_normal_entry(); }
- address generate_empty_entry(void) { return generate_jump_to_normal_entry(); }
+ address generate_accessor_entry(void) { return NULL; }
+ address generate_empty_entry(void) { return NULL; }
address generate_Reference_get_entry(void);
- void lock_method(void);
void save_native_result(void);
void restore_native_result(void);
@@ -48,4 +46,5 @@
// Not supported
address generate_CRC32_update_entry() { return NULL; }
address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return NULL; }
+ address generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return NULL; }
#endif // CPU_SPARC_VM_INTERPRETERGENERATOR_SPARC_HPP
diff --git a/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp
index f8d8f590c99..c5fc75d049f 100644
--- a/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/interpreter_sparc.cpp
@@ -241,15 +241,6 @@ void InterpreterGenerator::generate_counter_overflow(Label& Lcontinue) {
// Various method entries
-address InterpreterGenerator::generate_jump_to_normal_entry(void) {
- address entry = __ pc();
- assert(Interpreter::entry_for_kind(Interpreter::zerolocals) != NULL, "should already be generated");
- AddressLiteral al(Interpreter::entry_for_kind(Interpreter::zerolocals));
- __ jump_to(al, G3_scratch);
- __ delayed()->nop();
- return entry;
-}
-
// Abstract method entry
// Attempt to execute abstract method. Throw exception
//
diff --git a/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp b/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp
new file mode 100644
index 00000000000..10da55791d3
--- /dev/null
+++ b/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "vmreg_sparc.inline.hpp"
+
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+ if (inst->is_call() || inst->is_jump()) {
+ return pc_offset + NativeCall::instruction_size;
+ } else if (inst->is_call_reg()) {
+ return pc_offset + NativeCallReg::instruction_size;
+ } else if (inst->is_sethi()) {
+ return pc_offset + NativeFarCall::instruction_size;
+ } else {
+ fatal("unsupported type of instruction for call site");
+ return 0;
+ }
+}
+
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) {
+ address pc = _instructions->start() + pc_offset;
+ Handle obj = HotSpotObjectConstantImpl::object(constant);
+ jobject value = JNIHandles::make_local(obj());
+ if (HotSpotObjectConstantImpl::compressed(constant)) {
+#ifdef _LP64
+ int oop_index = _oop_recorder->find_index(value);
+ RelocationHolder rspec = oop_Relocation::spec(oop_index);
+ _instructions->relocate(pc, rspec, 1);
+#else
+ fatal("compressed oop on 32bit");
+#endif
+ } else {
+ NativeMovConstReg* move = nativeMovConstReg_at(pc);
+ move->set_data((intptr_t) value);
+
+ // We need two relocations: one on the sethi and one on the add.
+ int oop_index = _oop_recorder->find_index(value);
+ RelocationHolder rspec = oop_Relocation::spec(oop_index);
+ _instructions->relocate(pc + NativeMovConstReg::sethi_offset, rspec);
+ _instructions->relocate(pc + NativeMovConstReg::add_offset, rspec);
+ }
+}
+
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
+ address pc = _instructions->start() + pc_offset;
+ NativeInstruction* inst = nativeInstruction_at(pc);
+ NativeInstruction* inst1 = nativeInstruction_at(pc + 4);
+ if(inst->is_sethi() && inst1->is_nop()) {
+ address const_start = _constants->start();
+ address dest = _constants->start() + data_offset;
+ if(_constants_size > 0) {
+ _instructions->relocate(pc + NativeMovConstReg::sethi_offset, internal_word_Relocation::spec((address) dest));
+ _instructions->relocate(pc + NativeMovConstReg::add_offset, internal_word_Relocation::spec((address) dest));
+ }
+ TRACE_jvmci_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset);
+ }else {
+ int const_size = align_size_up(_constants->end()-_constants->start(), CodeEntryAlignment);
+ NativeMovRegMem* load = nativeMovRegMem_at(pc);
+ // This offset must match with SPARCLoadConstantTableBaseOp.emitCode
+ load->set_offset(- (const_size - data_offset + Assembler::min_simm13()));
+ TRACE_jvmci_3("relocating ld at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset);
+ }
+}
+
+void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+ fatal("CodeInstaller::pd_relocate_CodeBlob - sparc unimp");
+}
+
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+ address pc = (address) inst;
+ if (inst->is_call()) {
+ NativeCall* call = nativeCall_at(pc);
+ call->set_destination((address) foreign_call_destination);
+ _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec());
+ } else if (inst->is_sethi()) {
+ NativeJump* jump = nativeJump_at(pc);
+ jump->set_jump_destination((address) foreign_call_destination);
+ _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec());
+ } else {
+ fatal(err_msg("unknown call or jump instruction at " PTR_FORMAT, p2i(pc)));
+ }
+ TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst));
+}
+
+void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+#ifdef ASSERT
+ Method* method = NULL;
+ // we need to check, this might also be an unresolved method
+ if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
+ method = getMethodFromHotSpotMethod(hotspot_method);
+ }
+#endif
+ switch (_next_call_type) {
+ case INLINE_INVOKE:
+ break;
+ case INVOKEVIRTUAL:
+ case INVOKEINTERFACE: {
+ assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
+ _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc));
+ break;
+ }
+ case INVOKESTATIC: {
+ assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_static_call_stub());
+ _instructions->relocate(call->instruction_address(), relocInfo::static_call_type);
+ break;
+ }
+ case INVOKESPECIAL: {
+ assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
+ _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type);
+ break;
+ }
+ default:
+ fatal("invalid _next_call_type value");
+ break;
+ }
+}
+
+void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
+ switch (mark) {
+ case POLL_NEAR:
+ fatal("unimplemented");
+ break;
+ case POLL_FAR:
+ _instructions->relocate(pc, relocInfo::poll_type);
+ break;
+ case POLL_RETURN_NEAR:
+ fatal("unimplemented");
+ break;
+ case POLL_RETURN_FAR:
+ _instructions->relocate(pc, relocInfo::poll_return_type);
+ break;
+ default:
+ fatal("invalid mark value");
+ break;
+ }
+}
+
+// convert JVMCI register indices (as used in oop maps) to HotSpot registers
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg) {
+ if (jvmci_reg < RegisterImpl::number_of_registers) {
+ return as_Register(jvmci_reg)->as_VMReg();
+ } else {
+ jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_registers;
+ floatRegisterNumber += MAX2(0, floatRegisterNumber-32); // Beginning with f32, only every second register is going to be addressed
+ if (floatRegisterNumber < FloatRegisterImpl::number_of_registers) {
+ return as_FloatRegister(floatRegisterNumber)->as_VMReg();
+ }
+ ShouldNotReachHere();
+ return NULL;
+ }
+}
+
+bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) {
+ return !hotspotRegister->is_FloatRegister();
+}
diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp
index 84fa71cb119..2647d327bd5 100644
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp
@@ -1596,7 +1596,7 @@ void MacroAssembler::debug(char* msg, RegistersForDebugging* regs) {
else {
::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", msg);
}
- assert(false, err_msg("DEBUG MESSAGE: %s", msg));
+ assert(false, "DEBUG MESSAGE: %s", msg);
}
diff --git a/hotspot/src/cpu/sparc/vm/memset_with_concurrent_readers_sparc.cpp b/hotspot/src/cpu/sparc/vm/memset_with_concurrent_readers_sparc.cpp
index eabafbebc3b..aa4e4c16bb7 100644
--- a/hotspot/src/cpu/sparc/vm/memset_with_concurrent_readers_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/memset_with_concurrent_readers_sparc.cpp
@@ -61,8 +61,8 @@ inline void fill_subword(void* start, void* end, int value) {
" sub %[offset], %[end], %[offset]\n\t" // offset := start - end
" sllx %[offset], 2, %[offset]\n\t" // scale offset for instruction size of 4
" add %[offset], 40, %[offset]\n\t" // offset += 10 * instruction size
- " rd %pc, %[pc]\n\t" // dispatch on scaled offset
- " jmpl %[pc]+%[offset], %g0\n\t"
+ " rd %%pc, %[pc]\n\t" // dispatch on scaled offset
+ " jmpl %[pc]+%[offset], %%g0\n\t"
" nop\n\t"
// DISPATCH: no direct reference, but without it the store block may be elided.
"1:\n\t"
@@ -108,7 +108,7 @@ void memset_with_concurrent_readers(void* to, int value, size_t size) {
// Unroll loop x8.
" sub %[aend], %[ato], %[temp]\n\t"
" cmp %[temp], 56\n\t" // cc := (aligned_end - aligned_to) > 7 words
- " ba %xcc, 2f\n\t" // goto TEST always
+ " ba %%xcc, 2f\n\t" // goto TEST always
" sub %[aend], 56, %[temp]\n\t" // limit := aligned_end - 7 words
// LOOP:
"1:\n\t" // unrolled x8 store loop top
@@ -123,7 +123,7 @@ void memset_with_concurrent_readers(void* to, int value, size_t size) {
" stx %[xvalue], [%[ato]-8]\n\t"
// TEST:
"2:\n\t"
- " bgu,a %xcc, 1b\n\t" // goto LOOP if more than 7 words remaining
+ " bgu,a %%xcc, 1b\n\t" // goto LOOP if more than 7 words remaining
" add %[ato], 64, %[ato]\n\t" // aligned_to += 8, for next iteration
// Fill remaining < 8 full words.
// Dispatch on (aligned_end - aligned_to).
@@ -132,8 +132,8 @@ void memset_with_concurrent_readers(void* to, int value, size_t size) {
" sub %[ato], %[aend], %[ato]\n\t" // offset := aligned_to - aligned_end
" srax %[ato], 1, %[ato]\n\t" // scale offset for instruction size of 4
" add %[ato], 40, %[ato]\n\t" // offset += 10 * instruction size
- " rd %pc, %[temp]\n\t" // dispatch on scaled offset
- " jmpl %[temp]+%[ato], %g0\n\t"
+ " rd %%pc, %[temp]\n\t" // dispatch on scaled offset
+ " jmpl %[temp]+%[ato], %%g0\n\t"
" nop\n\t"
// DISPATCH: no direct reference, but without it the store block may be elided.
"3:\n\t"
diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp
index ba1f5c90753..5246059b470 100644
--- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp
@@ -56,7 +56,7 @@ void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_
#ifdef ASSERT
static int check_nonzero(const char* xname, int x) {
- assert(x != 0, err_msg("%s should be nonzero", xname));
+ assert(x != 0, "%s should be nonzero", xname);
return x;
}
#define NONZERO(x) check_nonzero(#x, x)
@@ -453,7 +453,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
}
default:
- fatal(err_msg_res("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid)));
+ fatal("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid));
break;
}
diff --git a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp
index eaf543e128b..44e0470133e 100644
--- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp
@@ -53,6 +53,7 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC {
bool is_nop() { return long_at(0) == nop_instruction(); }
bool is_call() { return is_op(long_at(0), Assembler::call_op); }
+ bool is_call_reg() { return is_op(long_at(0), Assembler::arith_op); }
bool is_sethi() { return (is_op2(long_at(0), Assembler::sethi_op2)
&& inv_rd(long_at(0)) != G0); }
@@ -415,6 +416,19 @@ inline NativeCall* nativeCall_at(address instr) {
return call;
}
+class NativeCallReg: public NativeInstruction {
+ public:
+ enum Sparc_specific_constants {
+ instruction_size = 8,
+ return_address_offset = 8,
+ instruction_offset = 0
+ };
+
+ address next_instruction_address() const {
+ return addr_at(instruction_size);
+ }
+};
+
// The NativeFarCall is an abstraction for accessing/manipulating native call-anywhere
// instructions in the sparcv9 vm. Used to call native methods which may be loaded
// anywhere in the address space, possibly out of reach of a call instruction.
diff --git a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp
index 28d7f917562..a9f2421c0fb 100644
--- a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp
@@ -197,8 +197,5 @@ address Relocation::pd_get_address_from_code() {
void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
}
-void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
-}
-
void metadata_Relocation::pd_fix_value(address x) {
}
diff --git a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp
index 2c4e892f467..449488b94c9 100644
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp
@@ -43,6 +43,9 @@
#include "compiler/compileBroker.hpp"
#include "shark/sharkCompiler.hpp"
#endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciJavaClasses.hpp"
+#endif
#define __ masm->
@@ -316,7 +319,7 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm) {
// 8 bytes FP registers are saved by default on SPARC.
bool SharedRuntime::is_wide_vector(int size) {
// Note, MaxVectorSize == 8 on SPARC.
- assert(size <= 8, err_msg_res("%d bytes vectors are not supported", size));
+ assert(size <= 8, "%d bytes vectors are not supported", size);
return size > 8;
}
@@ -464,7 +467,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
break;
default:
- fatal(err_msg_res("unknown basic type %d", sig_bt[i]));
+ fatal("unknown basic type %d", sig_bt[i]);
break;
}
}
@@ -513,10 +516,10 @@ class AdapterGenerator {
const VMRegPair *regs,
Label& skip_fixup);
void gen_i2c_adapter(int total_args_passed,
- // VMReg max_arg,
- int comp_args_on_stack, // VMRegStackSlots
- const BasicType *sig_bt,
- const VMRegPair *regs);
+ // VMReg max_arg,
+ int comp_args_on_stack, // VMRegStackSlots
+ const BasicType *sig_bt,
+ const VMRegPair *regs);
AdapterGenerator(MacroAssembler *_masm) : masm(_masm) {}
};
@@ -760,13 +763,11 @@ static void range_check(MacroAssembler* masm, Register pc_reg, Register temp_reg
__ bind(L_fail);
}
-void AdapterGenerator::gen_i2c_adapter(
- int total_args_passed,
- // VMReg max_arg,
- int comp_args_on_stack, // VMRegStackSlots
- const BasicType *sig_bt,
- const VMRegPair *regs) {
-
+void AdapterGenerator::gen_i2c_adapter(int total_args_passed,
+ // VMReg max_arg,
+ int comp_args_on_stack, // VMRegStackSlots
+ const BasicType *sig_bt,
+ const VMRegPair *regs) {
// Generate an I2C adapter: adjust the I-frame to make space for the C-frame
// layout. Lesp was saved by the calling I-frame and will be restored on
// return. Meanwhile, outgoing arg space is all owned by the callee
@@ -990,6 +991,21 @@ void AdapterGenerator::gen_i2c_adapter(
// Jump to the compiled code just as if compiled code was doing it.
__ ld_ptr(G5_method, in_bytes(Method::from_compiled_offset()), G3);
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ // check if this call should be routed towards a specific entry point
+ __ ld(Address(G2_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())), G1);
+ __ cmp(G0, G1);
+ Label no_alternative_target;
+ __ br(Assembler::equal, false, Assembler::pn, no_alternative_target);
+ __ delayed()->nop();
+
+ __ ld_ptr(G2_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset()), G3);
+ __ st_ptr(G0, Address(G2_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())));
+
+ __ bind(no_alternative_target);
+ }
+#endif // INCLUDE_JVMCI
// 6243940 We might end up in handle_wrong_method if
// the callee is deoptimized as we race thru here. If that
@@ -1006,6 +1022,15 @@ void AdapterGenerator::gen_i2c_adapter(
__ delayed()->nop();
}
+void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
+ int total_args_passed,
+ int comp_args_on_stack,
+ const BasicType *sig_bt,
+ const VMRegPair *regs) {
+ AdapterGenerator agen(masm);
+ agen.gen_i2c_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs);
+}
+
// ---------------------------------------------------------------
AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
int total_args_passed,
@@ -1016,9 +1041,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
AdapterFingerPrint* fingerprint) {
address i2c_entry = __ pc();
- AdapterGenerator agen(masm);
-
- agen.gen_i2c_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs);
+ gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
// -------------------------------------------------------------------------
@@ -1063,7 +1086,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
}
address c2i_entry = __ pc();
-
+ AdapterGenerator agen(masm);
agen.gen_c2i_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs, L_skip_fixup);
__ flush();
@@ -1859,7 +1882,7 @@ static void gen_special_dispatch(MacroAssembler* masm,
} else if (iid == vmIntrinsics::_invokeBasic) {
has_receiver = true;
} else {
- fatal(err_msg_res("unexpected intrinsic id %d", iid));
+ fatal("unexpected intrinsic id %d", iid);
}
if (member_reg != noreg) {
@@ -2916,6 +2939,11 @@ void SharedRuntime::generate_deopt_blob() {
pad += StackShadowPages*16 + 32;
}
#endif
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ pad += 1000; // Increase the buffer size when compiling for JVMCI
+ }
+#endif
#ifdef _LP64
CodeBuffer buffer("deopt_blob", 2100+pad, 512);
#else
@@ -2982,6 +3010,45 @@ void SharedRuntime::generate_deopt_blob() {
__ ba(cont);
__ delayed()->mov(Deoptimization::Unpack_deopt, L0deopt_mode);
+
+#if INCLUDE_JVMCI
+ Label after_fetch_unroll_info_call;
+ int implicit_exception_uncommon_trap_offset = 0;
+ int uncommon_trap_offset = 0;
+
+ if (EnableJVMCI) {
+ masm->block_comment("BEGIN implicit_exception_uncommon_trap");
+ implicit_exception_uncommon_trap_offset = __ offset() - start;
+
+ __ ld_ptr(G2_thread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset()), O7);
+ __ st_ptr(G0, Address(G2_thread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())));
+ __ add(O7, -8, O7);
+
+ uncommon_trap_offset = __ offset() - start;
+
+ // Save everything in sight.
+ (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
+ __ set_last_Java_frame(SP, NULL);
+
+ __ ld(G2_thread, in_bytes(JavaThread::pending_deoptimization_offset()), O1);
+ __ sub(G0, 1, L1);
+ __ st(L1, G2_thread, in_bytes(JavaThread::pending_deoptimization_offset()));
+
+ __ mov((int32_t)Deoptimization::Unpack_reexecute, L0deopt_mode);
+ __ mov(G2_thread, O0);
+ __ call(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap));
+ __ delayed()->nop();
+ oop_maps->add_gc_map( __ offset()-start, map->deep_copy());
+ __ get_thread();
+ __ add(O7, 8, O7);
+ __ reset_last_Java_frame();
+
+ __ ba(after_fetch_unroll_info_call);
+ __ delayed()->nop(); // Delay slot
+ masm->block_comment("END implicit_exception_uncommon_trap");
+ } // EnableJVMCI
+#endif // INCLUDE_JVMCI
+
int exception_offset = __ offset() - start;
// restore G2, the trampoline destroyed it
@@ -3004,6 +3071,7 @@ void SharedRuntime::generate_deopt_blob() {
int exception_in_tls_offset = __ offset() - start;
// No need to update oop_map as each call to save_live_registers will produce identical oopmap
+ // Opens a new stack frame
(void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
// Restore G2_thread
@@ -3035,7 +3103,12 @@ void SharedRuntime::generate_deopt_blob() {
// Reexecute entry, similar to c2 uncommon trap
//
int reexecute_offset = __ offset() - start;
-
+#if INCLUDE_JVMCI && !defined(COMPILER1)
+ if (EnableJVMCI && UseJVMCICompiler) {
+ // JVMCI does not use this kind of deoptimization
+ __ should_not_reach_here();
+ }
+#endif
// No need to update oop_map as each call to save_live_registers will produce identical oopmap
(void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words);
@@ -3059,6 +3132,11 @@ void SharedRuntime::generate_deopt_blob() {
__ reset_last_Java_frame();
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ __ bind(after_fetch_unroll_info_call);
+ }
+#endif
// NOTE: we know that only O0/O1 will be reloaded by restore_result_registers
// so this move will survive
@@ -3124,6 +3202,12 @@ void SharedRuntime::generate_deopt_blob() {
masm->flush();
_deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_words);
_deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ _deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset);
+ _deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
+ }
+#endif
}
#ifdef COMPILER2
diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad
index 04491901ddb..886a9c30d02 100644
--- a/hotspot/src/cpu/sparc/vm/sparc.ad
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad
@@ -1098,7 +1098,7 @@ void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
Register r = as_Register(ra_->get_encode(this));
CodeSection* consts_section = __ code()->consts();
int consts_size = consts_section->align_at_start(consts_section->size());
- assert(constant_table.size() == consts_size, err_msg("must be: %d == %d", constant_table.size(), consts_size));
+ assert(constant_table.size() == consts_size, "must be: %d == %d", constant_table.size(), consts_size);
if (UseRDPCForConstantTableBase) {
// For the following RDPC logic to work correctly the consts
@@ -1860,6 +1860,10 @@ const bool Matcher::match_rule_supported(int opcode) {
return true; // Per default match rules are supported.
}
+const int Matcher::float_pressure(int default_pressure_threshold) {
+ return default_pressure_threshold;
+}
+
int Matcher::regnum_to_fpu_offset(int regnum) {
return regnum - 32; // The FP registers are in the second chunk
}
diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
index e9ffb17136e..703a1b0f30c 100644
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
@@ -204,6 +204,20 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
address entry = __ pc();
__ get_constant_pool_cache(LcpoolCache); // load LcpoolCache
+#if INCLUDE_JVMCI
+ // Check if we need to take lock at entry of synchronized method.
+ if (UseJVMCICompiler) {
+ Label L;
+ Address pending_monitor_enter_addr(G2_thread, JavaThread::pending_monitorenter_offset());
+ __ ldbool(pending_monitor_enter_addr, Gtemp); // Load if pending monitor enter
+ __ cmp_and_br_short(Gtemp, G0, Assembler::equal, Assembler::pn, L);
+ // Clear flag.
+ __ stbool(G0, pending_monitor_enter_addr);
+ // Take lock.
+ lock_method();
+ __ bind(L);
+ }
+#endif
{ Label L;
Address exception_addr(G2_thread, Thread::pending_exception_offset());
__ ld_ptr(exception_addr, Gtemp); // Load pending exception.
@@ -349,7 +363,7 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
// Allocate monitor and lock method (asm interpreter)
// ebx - Method*
//
-void InterpreterGenerator::lock_method(void) {
+void TemplateInterpreterGenerator::lock_method() {
__ ld(Lmethod, in_bytes(Method::access_flags_offset()), O0); // Load access flags.
#ifdef ASSERT
@@ -779,14 +793,14 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// Generate regular method entry
__ bind(slow_path);
- (void) generate_normal_entry(false);
+ __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals));
return entry;
}
#endif // INCLUDE_ALL_GCS
// If G1 is not enabled then attempt to go through the accessor entry point
// Reference.get is an accessor
- return generate_jump_to_normal_entry();
+ return NULL;
}
//
diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.hpp b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.hpp
index 9b6cd216fbb..43d7cef64f4 100644
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.hpp
@@ -37,9 +37,9 @@
#ifdef _LP64
// The sethi() instruction generates lots more instructions when shell
// stack limit is unlimited, so that's why this is much bigger.
- const static int InterpreterCodeSize = 210 * K;
+ const static int InterpreterCodeSize = 260 * K;
#else
- const static int InterpreterCodeSize = 180 * K;
+ const static int InterpreterCodeSize = 230 * K;
#endif
#endif // CPU_SPARC_VM_TEMPLATEINTERPRETER_SPARC_HPP
diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp
index 8909c404003..48da68c0cba 100644
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp
@@ -2949,12 +2949,14 @@ void TemplateTable::prepare_invoke(int byte_no,
void TemplateTable::generate_vtable_call(Register Rrecv, Register Rindex, Register Rret) {
+ Register Rtemp = G4_scratch;
Register Rcall = Rindex;
assert_different_registers(Rcall, G5_method, Gargs, Rret);
// get target Method* & entry point
__ lookup_virtual_method(Rrecv, Rindex, G5_method);
__ profile_arguments_type(G5_method, Rcall, Gargs, true);
+ __ profile_called_method(G5_method, Rtemp);
__ call_from_interpreter(Rcall, Gargs, Rret);
}
@@ -3211,6 +3213,7 @@ void TemplateTable::invokeinterface(int byte_no) {
assert_different_registers(Rcall, G5_method, Gargs, Rret);
__ profile_arguments_type(G5_method, Rcall, Gargs, true);
+ __ profile_called_method(G5_method, Rscratch);
__ call_from_interpreter(Rcall, Gargs, Rret);
}
@@ -3486,7 +3489,8 @@ void TemplateTable::checkcast() {
Register RspecifiedKlass = O4;
// Check for casting a NULL
- __ br_null_short(Otos_i, Assembler::pn, is_null);
+ __ br_null(Otos_i, false, Assembler::pn, is_null);
+ __ delayed()->nop();
// Get value klass in RobjKlass
__ load_klass(Otos_i, RobjKlass); // get value klass
@@ -3542,7 +3546,8 @@ void TemplateTable::instanceof() {
Register RspecifiedKlass = O4;
// Check for casting a NULL
- __ br_null_short(Otos_i, Assembler::pt, is_null);
+ __ br_null(Otos_i, false, Assembler::pt, is_null);
+ __ delayed()->nop();
// Get value klass in RobjKlass
__ load_klass(Otos_i, RobjKlass); // get value klass
diff --git a/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp b/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp
index 56805aed838..e0be8b60ff9 100644
--- a/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp
@@ -37,10 +37,11 @@
/******************************/ \
/* JavaFrameAnchor */ \
/******************************/ \
- volatile_nonstatic_field(JavaFrameAnchor, _flags, int)
-
-#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
+ volatile_nonstatic_field(JavaFrameAnchor, _flags, int) \
+ static_field(VM_Version, _features, int)
+#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
+ declare_toplevel_type(VM_Version)
#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \
/******************************/ \
@@ -78,7 +79,11 @@
declare_c2_constant(R_G4_num) \
declare_c2_constant(R_G5_num) \
declare_c2_constant(R_G6_num) \
- declare_c2_constant(R_G7_num)
+ declare_c2_constant(R_G7_num) \
+ declare_constant(VM_Version::vis1_instructions_m) \
+ declare_constant(VM_Version::vis2_instructions_m) \
+ declare_constant(VM_Version::vis3_instructions_m) \
+ declare_constant(VM_Version::cbcond_instructions_m)
#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp
index c9b0690c648..0438025fed3 100644
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp
@@ -40,10 +40,6 @@ void VM_Version::initialize() {
PrefetchScanIntervalInBytes = prefetch_scan_interval_in_bytes();
PrefetchFieldsAhead = prefetch_fields_ahead();
- assert(0 <= AllocatePrefetchInstr && AllocatePrefetchInstr <= 1, "invalid value");
- if( AllocatePrefetchInstr < 0 ) AllocatePrefetchInstr = 0;
- if( AllocatePrefetchInstr > 1 ) AllocatePrefetchInstr = 0;
-
// Allocation prefetch settings
intx cache_line_size = prefetch_data_size();
if( cache_line_size > AllocatePrefetchStepSize )
@@ -59,13 +55,6 @@ void VM_Version::initialize() {
AllocatePrefetchDistance = allocate_prefetch_distance();
AllocatePrefetchStyle = allocate_prefetch_style();
- assert((AllocatePrefetchDistance % AllocatePrefetchStepSize) == 0 &&
- (AllocatePrefetchDistance > 0), "invalid value");
- if ((AllocatePrefetchDistance % AllocatePrefetchStepSize) != 0 ||
- (AllocatePrefetchDistance <= 0)) {
- AllocatePrefetchDistance = AllocatePrefetchStepSize;
- }
-
if (AllocatePrefetchStyle == 3 && !has_blk_init()) {
warning("BIS instructions are not available on this CPU");
FLAG_SET_DEFAULT(AllocatePrefetchStyle, 1);
@@ -73,13 +62,6 @@ void VM_Version::initialize() {
guarantee(VM_Version::has_v9(), "only SPARC v9 is supported");
- assert(ArraycopySrcPrefetchDistance < 4096, "invalid value");
- if (ArraycopySrcPrefetchDistance >= 4096)
- ArraycopySrcPrefetchDistance = 4064;
- assert(ArraycopyDstPrefetchDistance < 4096, "invalid value");
- if (ArraycopyDstPrefetchDistance >= 4096)
- ArraycopyDstPrefetchDistance = 4064;
-
UseSSE = 0; // Only on x86 and x64
_supports_cx8 = has_v9();
diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp
index d1c40e6488e..c21a6ee13d5 100644
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp
@@ -29,6 +29,7 @@
#include "runtime/vm_version.hpp"
class VM_Version: public Abstract_VM_Version {
+ friend class VMStructs;
protected:
enum Feature_Flag {
v8_instructions = 0,
diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp
index c7d743c9324..c66c6022bd1 100644
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp
@@ -733,11 +733,11 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
// these asserts are somewhat nonsensical
#ifndef _LP64
assert(which == imm_operand || which == disp32_operand,
- err_msg("which %d is_64_bit %d ip " INTPTR_FORMAT, which, is_64bit, p2i(ip)));
+ "which %d is_64_bit %d ip " INTPTR_FORMAT, which, is_64bit, p2i(ip));
#else
assert((which == call32_operand || which == imm_operand) && is_64bit ||
which == narrow_oop_operand && !is_64bit,
- err_msg("which %d is_64_bit %d ip " INTPTR_FORMAT, which, is_64bit, p2i(ip)));
+ "which %d is_64_bit %d ip " INTPTR_FORMAT, which, is_64bit, p2i(ip));
#endif // _LP64
return ip;
@@ -770,6 +770,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0x55: // andnps
case 0x56: // orps
case 0x57: // xorps
+ case 0x59: //mulpd
case 0x6E: // movd
case 0x7E: // movd
case 0xAE: // ldmxcsr, stmxcsr, fxrstor, fxsave, clflush
@@ -877,21 +878,35 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
// Check second byte
NOT_LP64(assert((0xC0 & *ip) == 0xC0, "shouldn't have LDS and LES instructions"));
+ int vex_opcode;
// First byte
if ((0xFF & *inst) == VEX_3bytes) {
+ vex_opcode = VEX_OPCODE_MASK & *ip;
ip++; // third byte
is_64bit = ((VEX_W & *ip) == VEX_W);
+ } else {
+ vex_opcode = VEX_OPCODE_0F;
}
ip++; // opcode
// To find the end of instruction (which == end_pc_operand).
- switch (0xFF & *ip) {
- case 0x61: // pcmpestri r, r/a, #8
- case 0x70: // pshufd r, r/a, #8
- case 0x73: // psrldq r, #8
- tail_size = 1; // the imm8
- break;
- default:
- break;
+ switch (vex_opcode) {
+ case VEX_OPCODE_0F:
+ switch (0xFF & *ip) {
+ case 0x70: // pshufd r, r/a, #8
+ case 0x71: // ps[rl|ra|ll]w r, #8
+ case 0x72: // ps[rl|ra|ll]d r, #8
+ case 0x73: // ps[rl|ra|ll]q r, #8
+ case 0xC2: // cmp[ps|pd|ss|sd] r, r, r/a, #8
+ case 0xC4: // pinsrw r, r, r/a, #8
+ case 0xC5: // pextrw r/a, r, #8
+ case 0xC6: // shufp[s|d] r, r, r/a, #8
+ tail_size = 1; // the imm8
+ break;
+ }
+ break;
+ case VEX_OPCODE_0F_3A:
+ tail_size = 1;
+ break;
}
ip++; // skip opcode
debug_only(has_disp32 = true); // has both kinds of operands!
@@ -1604,6 +1619,85 @@ void Assembler::cpuid() {
emit_int8((unsigned char)0xA2);
}
+// Opcode / Instruction Op / En 64 - Bit Mode Compat / Leg Mode Description Implemented
+// F2 0F 38 F0 / r CRC32 r32, r / m8 RM Valid Valid Accumulate CRC32 on r / m8. v
+// F2 REX 0F 38 F0 / r CRC32 r32, r / m8* RM Valid N.E. Accumulate CRC32 on r / m8. -
+// F2 REX.W 0F 38 F0 / r CRC32 r64, r / m8 RM Valid N.E. Accumulate CRC32 on r / m8. -
+//
+// F2 0F 38 F1 / r CRC32 r32, r / m16 RM Valid Valid Accumulate CRC32 on r / m16. v
+//
+// F2 0F 38 F1 / r CRC32 r32, r / m32 RM Valid Valid Accumulate CRC32 on r / m32. v
+//
+// F2 REX.W 0F 38 F1 / r CRC32 r64, r / m64 RM Valid N.E. Accumulate CRC32 on r / m64. v
+void Assembler::crc32(Register crc, Register v, int8_t sizeInBytes) {
+ assert(VM_Version::supports_sse4_2(), "");
+ int8_t w = 0x01;
+ Prefix p = Prefix_EMPTY;
+
+ emit_int8((int8_t)0xF2);
+ switch (sizeInBytes) {
+ case 1:
+ w = 0;
+ break;
+ case 2:
+ case 4:
+ break;
+ LP64_ONLY(case 8:)
+ // This instruction is not valid in 32 bits
+ // Note:
+ // http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
+ //
+ // Page B - 72 Vol. 2C says
+ // qwreg2 to qwreg 1111 0010 : 0100 1R0B : 0000 1111 : 0011 1000 : 1111 0000 : 11 qwreg1 qwreg2
+ // mem64 to qwreg 1111 0010 : 0100 1R0B : 0000 1111 : 0011 1000 : 1111 0000 : mod qwreg r / m
+ // F0!!!
+ // while 3 - 208 Vol. 2A
+ // F2 REX.W 0F 38 F1 / r CRC32 r64, r / m64 RM Valid N.E.Accumulate CRC32 on r / m64.
+ //
+ // the 0 on a last bit is reserved for a different flavor of this instruction :
+ // F2 REX.W 0F 38 F0 / r CRC32 r64, r / m8 RM Valid N.E.Accumulate CRC32 on r / m8.
+ p = REX_W;
+ break;
+ default:
+ assert(0, "Unsupported value for a sizeInBytes argument");
+ break;
+ }
+ LP64_ONLY(prefix(crc, v, p);)
+ emit_int8((int8_t)0x0F);
+ emit_int8(0x38);
+ emit_int8((int8_t)(0xF0 | w));
+ emit_int8(0xC0 | ((crc->encoding() & 0x7) << 3) | (v->encoding() & 7));
+}
+
+void Assembler::crc32(Register crc, Address adr, int8_t sizeInBytes) {
+ assert(VM_Version::supports_sse4_2(), "");
+ InstructionMark im(this);
+ int8_t w = 0x01;
+ Prefix p = Prefix_EMPTY;
+
+ emit_int8((int8_t)0xF2);
+ switch (sizeInBytes) {
+ case 1:
+ w = 0;
+ break;
+ case 2:
+ case 4:
+ break;
+ LP64_ONLY(case 8:)
+ // This instruction is not valid in 32 bits
+ p = REX_W;
+ break;
+ default:
+ assert(0, "Unsupported value for a sizeInBytes argument");
+ break;
+ }
+ LP64_ONLY(prefix(crc, adr, p);)
+ emit_int8((int8_t)0x0F);
+ emit_int8(0x38);
+ emit_int8((int8_t)(0xF0 | w));
+ emit_operand(crc, adr);
+}
+
void Assembler::cvtdq2pd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith_nonds(0xE6, dst, src, VEX_SIMD_F3, /* no_mask_reg */ false, /* legacy_mode */ true);
@@ -2399,7 +2493,7 @@ void Assembler::movsbl(Register dst, Address src) { // movsxb
void Assembler::movsbl(Register dst, Register src) { // movsxb
NOT_LP64(assert(src->has_byte_register(), "must have byte register"));
- int encode = prefix_and_encode(dst->encoding(), src->encoding(), true);
+ int encode = prefix_and_encode(dst->encoding(), false, src->encoding(), true);
emit_int8(0x0F);
emit_int8((unsigned char)0xBE);
emit_int8((unsigned char)(0xC0 | encode));
@@ -2516,7 +2610,7 @@ void Assembler::movzbl(Register dst, Address src) { // movzxb
void Assembler::movzbl(Register dst, Register src) { // movzxb
NOT_LP64(assert(src->has_byte_register(), "must have byte register"));
- int encode = prefix_and_encode(dst->encoding(), src->encoding(), true);
+ int encode = prefix_and_encode(dst->encoding(), false, src->encoding(), true);
emit_int8(0x0F);
emit_int8((unsigned char)0xB6);
emit_int8(0xC0 | encode);
@@ -2951,6 +3045,15 @@ void Assembler::pextrq(Register dst, XMMRegister src, int imm8) {
emit_int8(imm8);
}
+void Assembler::pextrw(Register dst, XMMRegister src, int imm8) {
+ assert(VM_Version::supports_sse2(), "");
+ int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
+ emit_int8((unsigned char)0xC5);
+ emit_int8((unsigned char)(0xC0 | encode));
+ emit_int8(imm8);
+}
+
void Assembler::pinsrd(XMMRegister dst, Register src, int imm8) {
assert(VM_Version::supports_sse4_1(), "");
int encode = simd_prefix_and_encode(dst, dst, as_XMMRegister(src->encoding()), VEX_SIMD_66, /* no_mask_reg */ true,
@@ -2969,6 +3072,15 @@ void Assembler::pinsrq(XMMRegister dst, Register src, int imm8) {
emit_int8(imm8);
}
+void Assembler::pinsrw(XMMRegister dst, Register src, int imm8) {
+ assert(VM_Version::supports_sse2(), "");
+ int encode = simd_prefix_and_encode(dst, dst, as_XMMRegister(src->encoding()), VEX_SIMD_66, /* no_mask_reg */ true,
+ VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ _legacy_mode_bw);
+ emit_int8((unsigned char)0xC4);
+ emit_int8((unsigned char)(0xC0 | encode));
+ emit_int8(imm8);
+}
+
void Assembler::pmovzxbw(XMMRegister dst, Address src) {
assert(VM_Version::supports_sse4_1(), "");
if (VM_Version::supports_evex()) {
@@ -3984,6 +4096,16 @@ void Assembler::mulpd(XMMRegister dst, XMMRegister src) {
}
}
+void Assembler::mulpd(XMMRegister dst, Address src) {
+ _instruction_uses_vl = true;
+ NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+ if (VM_Version::supports_evex()) {
+ emit_simd_arith_q(0x59, dst, src, VEX_SIMD_66);
+ } else {
+ emit_simd_arith(0x59, dst, src, VEX_SIMD_66);
+ }
+}
+
void Assembler::mulps(XMMRegister dst, XMMRegister src) {
_instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
@@ -4172,6 +4294,26 @@ void Assembler::vandps(XMMRegister dst, XMMRegister nds, Address src, int vector
emit_vex_arith(0x54, dst, nds, src, VEX_SIMD_NONE, vector_len, /* no_mask_reg */ false, /* legacy_mode */ _legacy_mode_dq);
}
+void Assembler::unpckhpd(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
+ NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+ if (VM_Version::supports_evex()) {
+ emit_simd_arith_q(0x15, dst, src, VEX_SIMD_66);
+ } else {
+ emit_simd_arith(0x15, dst, src, VEX_SIMD_66);
+ }
+}
+
+void Assembler::unpcklpd(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
+ NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+ if (VM_Version::supports_evex()) {
+ emit_simd_arith_q(0x14, dst, src, VEX_SIMD_66);
+ } else {
+ emit_simd_arith(0x14, dst, src, VEX_SIMD_66);
+ }
+}
+
void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
if (VM_Version::supports_avx512dq()) {
@@ -4792,8 +4934,9 @@ void Assembler::vpsrad(XMMRegister dst, XMMRegister src, XMMRegister shift, int
}
-// AND packed integers
+// logical operations packed integers
void Assembler::pand(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
emit_simd_arith(0xDB, dst, src, VEX_SIMD_66);
}
@@ -4814,6 +4957,17 @@ void Assembler::vpand(XMMRegister dst, XMMRegister nds, Address src, int vector_
emit_vex_arith(0xDB, dst, nds, src, VEX_SIMD_66, vector_len);
}
+void Assembler::pandn(XMMRegister dst, XMMRegister src) {
+ _instruction_uses_vl = true;
+ NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+ if (VM_Version::supports_evex()) {
+ emit_simd_arith_q(0xDF, dst, src, VEX_SIMD_66);
+ }
+ else {
+ emit_simd_arith(0xDF, dst, src, VEX_SIMD_66);
+ }
+}
+
void Assembler::por(XMMRegister dst, XMMRegister src) {
_instruction_uses_vl = true;
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
@@ -6223,6 +6377,14 @@ void Assembler::shldl(Register dst, Register src) {
emit_int8((unsigned char)(0xC0 | src->encoding() << 3 | dst->encoding()));
}
+// 0F A4 / r ib
+void Assembler::shldl(Register dst, Register src, int8_t imm8) {
+ emit_int8(0x0F);
+ emit_int8((unsigned char)0xA4);
+ emit_int8((unsigned char)(0xC0 | src->encoding() << 3 | dst->encoding()));
+ emit_int8(imm8);
+}
+
void Assembler::shrdl(Register dst, Register src) {
emit_int8(0x0F);
emit_int8((unsigned char)0xAD);
@@ -6362,12 +6524,12 @@ int Assembler::prefixq_and_encode(int reg_enc) {
return reg_enc;
}
-int Assembler::prefix_and_encode(int dst_enc, int src_enc, bool byteinst) {
+int Assembler::prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte) {
if (dst_enc < 8) {
if (src_enc >= 8) {
prefix(REX_B);
src_enc -= 8;
- } else if (byteinst && src_enc >= 4) {
+ } else if ((src_is_byte && src_enc >= 4) || (dst_is_byte && dst_enc >= 4)) {
prefix(REX);
}
} else {
@@ -6408,6 +6570,40 @@ void Assembler::prefix(Register reg) {
}
}
+void Assembler::prefix(Register dst, Register src, Prefix p) {
+ if (src->encoding() >= 8) {
+ p = (Prefix)(p | REX_B);
+ }
+ if (dst->encoding() >= 8) {
+ p = (Prefix)( p | REX_R);
+ }
+ if (p != Prefix_EMPTY) {
+ // do not generate an empty prefix
+ prefix(p);
+ }
+}
+
+void Assembler::prefix(Register dst, Address adr, Prefix p) {
+ if (adr.base_needs_rex()) {
+ if (adr.index_needs_rex()) {
+ assert(false, "prefix(Register dst, Address adr, Prefix p) does not support handling of an X");
+ } else {
+ prefix(REX_B);
+ }
+ } else {
+ if (adr.index_needs_rex()) {
+ assert(false, "prefix(Register dst, Address adr, Prefix p) does not support handling of an X");
+ }
+ }
+ if (dst->encoding() >= 8) {
+ p = (Prefix)(p | REX_R);
+ }
+ if (p != Prefix_EMPTY) {
+ // do not generate an empty prefix
+ prefix(p);
+ }
+}
+
void Assembler::prefix(Address adr) {
if (adr.base_needs_rex()) {
if (adr.index_needs_rex()) {
diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp
index 3b3781c58f5..ed039c552d1 100644
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp
@@ -506,7 +506,8 @@ class Assembler : public AbstractAssembler {
VEX_3bytes = 0xC4,
VEX_2bytes = 0xC5,
- EVEX_4bytes = 0x62
+ EVEX_4bytes = 0x62,
+ Prefix_EMPTY = 0x0
};
enum VexPrefix {
@@ -535,7 +536,8 @@ class Assembler : public AbstractAssembler {
VEX_OPCODE_NONE = 0x0,
VEX_OPCODE_0F = 0x1,
VEX_OPCODE_0F_38 = 0x2,
- VEX_OPCODE_0F_3A = 0x3
+ VEX_OPCODE_0F_3A = 0x3,
+ VEX_OPCODE_MASK = 0x1F
};
enum AvxVectorLen {
@@ -611,10 +613,15 @@ private:
int prefix_and_encode(int reg_enc, bool byteinst = false);
int prefixq_and_encode(int reg_enc);
- int prefix_and_encode(int dst_enc, int src_enc, bool byteinst = false);
+ int prefix_and_encode(int dst_enc, int src_enc) {
+ return prefix_and_encode(dst_enc, false, src_enc, false);
+ }
+ int prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte);
int prefixq_and_encode(int dst_enc, int src_enc);
void prefix(Register reg);
+ void prefix(Register dst, Register src, Prefix p);
+ void prefix(Register dst, Address adr, Prefix p);
void prefix(Address adr);
void prefixq(Address adr);
@@ -1177,6 +1184,10 @@ private:
// Identify processor type and features
void cpuid();
+ // CRC32C
+ void crc32(Register crc, Register v, int8_t sizeInBytes);
+ void crc32(Register crc, Address adr, int8_t sizeInBytes);
+
// Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value
void cvtsd2ss(XMMRegister dst, XMMRegister src);
void cvtsd2ss(XMMRegister dst, Address src);
@@ -1672,10 +1683,14 @@ private:
// SSE 4.1 extract
void pextrd(Register dst, XMMRegister src, int imm8);
void pextrq(Register dst, XMMRegister src, int imm8);
+ // SSE 2 extract
+ void pextrw(Register dst, XMMRegister src, int imm8);
// SSE 4.1 insert
void pinsrd(XMMRegister dst, Register src, int imm8);
void pinsrq(XMMRegister dst, Register src, int imm8);
+ // SSE 2 insert
+ void pinsrw(XMMRegister dst, Register src, int imm8);
// SSE4.1 packed move
void pmovzxbw(XMMRegister dst, XMMRegister src);
@@ -1783,6 +1798,7 @@ private:
void setb(Condition cc, Register dst);
void shldl(Register dst, Register src);
+ void shldl(Register dst, Register src, int8_t imm8);
void shll(Register dst, int imm8);
void shll(Register dst);
@@ -1925,6 +1941,7 @@ private:
// Multiply Packed Floating-Point Values
void mulpd(XMMRegister dst, XMMRegister src);
+ void mulpd(XMMRegister dst, Address src);
void mulps(XMMRegister dst, XMMRegister src);
void vmulpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vmulps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
@@ -1951,6 +1968,9 @@ private:
void vandpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vandps(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
+ void unpckhpd(XMMRegister dst, XMMRegister src);
+ void unpcklpd(XMMRegister dst, XMMRegister src);
+
// Bitwise Logical XOR of Packed Floating-Point Values
void xorpd(XMMRegister dst, XMMRegister src);
void xorps(XMMRegister dst, XMMRegister src);
@@ -2046,6 +2066,9 @@ private:
void vpand(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpand(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
+ // Andn packed integers
+ void pandn(XMMRegister dst, XMMRegister src);
+
// Or packed integers
void por(XMMRegister dst, XMMRegister src);
void vpor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.inline.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.inline.hpp
index 7dbb0950712..7219943a969 100644
--- a/hotspot/src/cpu/x86/vm/assembler_x86.inline.hpp
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.inline.hpp
@@ -33,10 +33,12 @@
inline int Assembler::prefix_and_encode(int reg_enc, bool byteinst) { return reg_enc; }
inline int Assembler::prefixq_and_encode(int reg_enc) { return reg_enc; }
-inline int Assembler::prefix_and_encode(int dst_enc, int src_enc, bool byteinst) { return dst_enc << 3 | src_enc; }
+inline int Assembler::prefix_and_encode(int dst_enc, bool dst_is_byte, int src_enc, bool src_is_byte) { return dst_enc << 3 | src_enc; }
inline int Assembler::prefixq_and_encode(int dst_enc, int src_enc) { return dst_enc << 3 | src_enc; }
inline void Assembler::prefix(Register reg) {}
+inline void Assembler::prefix(Register dst, Register src, Prefix p) {}
+inline void Assembler::prefix(Register dst, Address adr, Prefix p) {}
inline void Assembler::prefix(Address adr) {}
inline void Assembler::prefixq(Address adr) {}
diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
index ff07711acc0..9870ac1c802 100644
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
@@ -2457,9 +2457,6 @@ void LIR_Assembler::intrinsic_op(LIR_Code code, LIR_Opr value, LIR_Opr unused, L
// Should consider not saving rbx, if not necessary
__ trigfunc('t', op->as_Op2()->fpu_stack_size());
break;
- case lir_exp :
- __ exp_with_fallback(op->as_Op2()->fpu_stack_size());
- break;
case lir_pow :
__ pow_with_fallback(op->as_Op2()->fpu_stack_size());
break;
@@ -2684,7 +2681,7 @@ void LIR_Assembler::comp_op(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2,
#endif // _LP64
}
} else {
- fatal(err_msg("unexpected type: %s", basictype_to_str(c->type())));
+ fatal("unexpected type: %s", basictype_to_str(c->type()));
}
// cpu register - address
} else if (opr2->is_address()) {
diff --git a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
index 1ee690ea442..f51fa24b07d 100644
--- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
@@ -808,6 +808,12 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
assert(x->number_of_arguments() == 1 || (x->number_of_arguments() == 2 && x->id() == vmIntrinsics::_dpow), "wrong type");
+
+ if (x->id() == vmIntrinsics::_dexp) {
+ do_ExpIntrinsic(x);
+ return;
+ }
+
LIRItem value(x->argument_at(0), this);
bool use_fpu = false;
@@ -818,7 +824,6 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
case vmIntrinsics::_dtan:
case vmIntrinsics::_dlog:
case vmIntrinsics::_dlog10:
- case vmIntrinsics::_dexp:
case vmIntrinsics::_dpow:
use_fpu = true;
}
@@ -870,7 +875,6 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
case vmIntrinsics::_dtan: __ tan (calc_input, calc_result, tmp1, tmp2); break;
case vmIntrinsics::_dlog: __ log (calc_input, calc_result, tmp1); break;
case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, tmp1); break;
- case vmIntrinsics::_dexp: __ exp (calc_input, calc_result, tmp1, tmp2, FrameMap::rax_opr, FrameMap::rcx_opr, FrameMap::rdx_opr); break;
case vmIntrinsics::_dpow: __ pow (calc_input, calc_input2, calc_result, tmp1, tmp2, FrameMap::rax_opr, FrameMap::rcx_opr, FrameMap::rdx_opr); break;
default: ShouldNotReachHere();
}
@@ -880,6 +884,32 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
}
}
+void LIRGenerator::do_ExpIntrinsic(Intrinsic* x) {
+ LIRItem value(x->argument_at(0), this);
+ value.set_destroys_register();
+
+ LIR_Opr calc_result = rlock_result(x);
+ LIR_Opr result_reg = result_register_for(x->type());
+
+ BasicTypeList signature(1);
+ signature.append(T_DOUBLE);
+ CallingConvention* cc = frame_map()->c_calling_convention(&signature);
+
+ value.load_item_force(cc->at(0));
+
+#ifndef _LP64
+ LIR_Opr tmp = FrameMap::fpu0_double_opr;
+ result_reg = tmp;
+ if (VM_Version::supports_sse2()) {
+ __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
+ } else {
+ __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dexp), getThreadTemp(), result_reg, cc->args());
+ }
+#else
+ __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
+#endif
+ __ move(result_reg, calc_result);
+}
void LIRGenerator::do_ArrayCopy(Intrinsic* x) {
assert(x->number_of_arguments() == 5, "wrong type");
diff --git a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp
index ba5dc48623d..4f79619d564 100644
--- a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp
@@ -814,8 +814,7 @@ void FpuStackAllocator::handle_op2(LIR_Op2* op2) {
case lir_tan:
case lir_sin:
- case lir_cos:
- case lir_exp: {
+ case lir_cos: {
// sin, cos and exp need two temporary fpu stack slots, so there are two temporary
// registers (stored in right and temp of the operation).
// the stack allocator must guarantee that the stack slots are really free,
diff --git a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp
index a32e0a0bae6..db3692f8ccc 100644
--- a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp
@@ -48,11 +48,11 @@ define_pd_global(intx, CompileThreshold, 10000);
define_pd_global(intx, OnStackReplacePercentage, 140);
define_pd_global(intx, ConditionalMoveLimit, 3);
-define_pd_global(intx, FLOATPRESSURE, 6);
define_pd_global(intx, FreqInlineSize, 325);
define_pd_global(intx, MinJumpTableSize, 10);
#ifdef AMD64
define_pd_global(intx, INTPRESSURE, 13);
+define_pd_global(intx, FLOATPRESSURE, 14);
define_pd_global(intx, InteriorEntryAlignment, 16);
define_pd_global(size_t, NewSizeThreadIncrease, ScaleForWordSize(4*K));
define_pd_global(intx, LoopUnrollLimit, 60);
@@ -64,6 +64,7 @@ define_pd_global(intx, CodeCacheExpansionSize, 64*K);
define_pd_global(uint64_t, MaxRAM, 128ULL*G);
#else
define_pd_global(intx, INTPRESSURE, 6);
+define_pd_global(intx, FLOATPRESSURE, 6);
define_pd_global(intx, InteriorEntryAlignment, 4);
define_pd_global(size_t, NewSizeThreadIncrease, 4*K);
define_pd_global(intx, LoopUnrollLimit, 50); // Design center runs on 1.3.1
@@ -82,6 +83,7 @@ define_pd_global(bool, OptoPeephole, true);
define_pd_global(bool, UseCISCSpill, true);
define_pd_global(bool, OptoScheduling, false);
define_pd_global(bool, OptoBundling, false);
+define_pd_global(bool, OptoRegScheduling, true);
define_pd_global(intx, ReservedCodeCacheSize, 48*M);
define_pd_global(intx, NonProfiledCodeHeapSize, 21*M);
diff --git a/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp b/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp
index 29eba2fb99d..865e149331c 100644
--- a/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp
@@ -50,13 +50,15 @@ bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) {
// ----------------------------------------------------------------------------
#define __ _masm.
-address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
// Stub is fixed up when the corresponding call is converted from
// calling compiled code to calling interpreted code.
// movq rbx, 0
// jmp -5 # to self
- address mark = cbuf.insts_mark(); // Get mark within main instrs section.
+ if (mark == NULL) {
+ mark = cbuf.insts_mark(); // Get mark within main instrs section.
+ }
// Note that the code buffer's insts_mark is always relative to insts.
// That's why we must use the macroassembler to generate a stub.
@@ -73,6 +75,8 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
// This is recognized as unresolved by relocs/nativeinst/ic code.
__ jump(RuntimeAddress(__ pc()));
+ assert(__ pc() - base <= to_interp_stub_size(), "wrong stub size");
+
// Update current stubs pointer and restore insts_end.
__ end_a_stub();
return base;
@@ -104,10 +108,15 @@ void CompiledStaticCall::set_to_interpreted(methodHandle callee, address entry)
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
- assert(method_holder->data() == 0 || method_holder->data() == (intptr_t)callee(),
+#ifdef ASSERT
+ // read the value once
+ intptr_t data = method_holder->data();
+ address destination = jump->jump_destination();
+ assert(data == 0 || data == (intptr_t)callee(),
"a) MT-unsafe modification of inline cache");
- assert(jump->jump_destination() == (address)-1 || jump->jump_destination() == entry,
+ assert(destination == (address)-1 || destination == entry,
"b) MT-unsafe modification of inline cache");
+#endif
// Update stub.
method_holder->set_data((intptr_t)callee());
@@ -124,11 +133,12 @@ void CompiledStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub)
assert(stub != NULL, "stub not found");
// Creation also verifies the object.
NativeMovConstReg* method_holder = nativeMovConstReg_at(stub);
- NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
method_holder->set_data(0);
+ NativeJump* jump = nativeJump_at(method_holder->next_instruction_address());
jump->set_jump_destination((address)-1);
}
+
//-----------------------------------------------------------------------------
// Non-product mode code
#ifndef PRODUCT
@@ -150,5 +160,4 @@ void CompiledStaticCall::verify() {
// Verify state.
assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check");
}
-
#endif // !PRODUCT
diff --git a/hotspot/src/cpu/x86/vm/cppInterpreterGenerator_x86.hpp b/hotspot/src/cpu/x86/vm/cppInterpreterGenerator_x86.hpp
index 9f81215b396..bf47c3430ef 100644
--- a/hotspot/src/cpu/x86/vm/cppInterpreterGenerator_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/cppInterpreterGenerator_x86.hpp
@@ -29,6 +29,7 @@
void generate_more_monitors();
void generate_deopt_handling();
+ void lock_method(void);
address generate_interpreter_frame_manager(bool synchronized); // C++ interpreter only
void generate_compute_interpreter_state(const Register state,
const Register prev_state,
diff --git a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp
index 27f1b309727..b3ed77e68c6 100644
--- a/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/cppInterpreter_x86.cpp
@@ -741,7 +741,7 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
// Find preallocated monitor and lock method (C++ interpreter)
// rbx - Method*
//
-void InterpreterGenerator::lock_method(void) {
+void CppInterpreterGenerator::lock_method() {
// assumes state == rsi/r13 == pointer to current interpreterState
// minimally destroys rax, rdx|c_rarg1, rdi
//
@@ -807,7 +807,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// If G1 is not enabled then attempt to go through the accessor entry point
// Reference.get is an accessor
- return generate_jump_to_normal_entry();
+ return NULL;
}
//
diff --git a/hotspot/src/cpu/x86/vm/crc32c.h b/hotspot/src/cpu/x86/vm/crc32c.h
new file mode 100644
index 00000000000..83746b42947
--- /dev/null
+++ b/hotspot/src/cpu/x86/vm/crc32c.h
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*
+*/
+
+enum {
+ // S. Gueron / Information Processing Letters 112 (2012) 184
+ // shows than anything above 6K and below 32K is a good choice
+ // 32K does not deliver any further performance gains
+ // 6K=8*256 (*3 as we compute 3 blocks together)
+ //
+ // Thus selecting the smallest value so it could apply to the largest number
+ // of buffer sizes.
+ CRC32C_HIGH = 8 * 256,
+
+ // empirical
+ // based on ubench study using methodology described in
+ // V. Gopal et al. / Fast CRC Computation for iSCSI Polynomial Using CRC32 Instruction April 2011 8
+ //
+ // arbitrary value between 27 and 256
+ CRC32C_MIDDLE = 8 * 86,
+
+ // V. Gopal et al. / Fast CRC Computation for iSCSI Polynomial Using CRC32 Instruction April 2011 9
+ // shows that 240 and 1024 are equally good choices as the 216==8*27
+ //
+ // Selecting the smallest value which resulted in a significant performance improvement over
+ // sequential version
+ CRC32C_LOW = 8 * 27,
+
+ CRC32C_NUM_ChunkSizeInBytes = 3,
+
+ // We need to compute powers of 64N and 128N for each "chunk" size
+ CRC32C_NUM_PRECOMPUTED_CONSTANTS = ( 2 * CRC32C_NUM_ChunkSizeInBytes )
+};
+// Notes:
+// 1. Why we need to choose a "chunk" approach?
+// Overhead of computing a powers and powers of for an arbitrary buffer of size N is significant
+// (implementation approaches a library perf.)
+// 2. Why only 3 "chunks"?
+// Performance experiments results showed that a HIGH+LOW was not delivering a stable speedup
+// curve.
+//
+// Disclaimer:
+// If you ever decide to increase/decrease number of "chunks" be sure to modify
+// a) constants table generation (hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp)
+// b) constant fetch from that table (macroAssembler_x86.cpp)
+// c) unrolled for loop (macroAssembler_x86.cpp)
diff --git a/hotspot/src/cpu/x86/vm/frame_x86.cpp b/hotspot/src/cpu/x86/vm/frame_x86.cpp
index f831342b9d7..695902087f4 100644
--- a/hotspot/src/cpu/x86/vm/frame_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp
@@ -48,8 +48,6 @@ void RegisterMap::check_location_valid() {
}
#endif
-PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-
// Profiling/safepoint support
bool frame::safe_for_sender(JavaThread *thread) {
@@ -280,7 +278,7 @@ void frame::patch_pc(Thread* thread, address pc) {
address* pc_addr = &(((address*) sp())[-1]);
if (TracePcPatching) {
tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]",
- pc_addr, *pc_addr, pc);
+ p2i(pc_addr), p2i(*pc_addr), p2i(pc));
}
// Either the return address is the original one or we are going to
// patch in the same address that's already there.
@@ -458,11 +456,11 @@ frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
// This is the sp before any possible extension (adapter/locals).
intptr_t* unextended_sp = interpreter_frame_sender_sp();
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
if (map->update_map()) {
update_map_with_saved_link(map, (intptr_t**) addr_at(link_offset));
}
-#endif // COMPILER2
+#endif // COMPILER2 || INCLUDE_JVMCI
return frame(sender_sp, unextended_sp, link(), sender_pc());
}
@@ -683,10 +681,19 @@ void frame::describe_pd(FrameValues& values, int frame_no) {
DESCRIBE_FP_OFFSET(interpreter_frame_locals);
DESCRIBE_FP_OFFSET(interpreter_frame_bcp);
DESCRIBE_FP_OFFSET(interpreter_frame_initial_sp);
-#endif
+#ifdef AMD64
+ } else if (is_entry_frame()) {
+ // This could be more descriptive if we use the enum in
+ // stubGenerator to map to real names but it's most important to
+ // claim these frame slots so the error checking works.
+ for (int i = 0; i < entry_frame_after_call_words; i++) {
+ values.describe(frame_no, fp() - i, err_msg("call_stub word fp - %d", i));
+ }
+#endif // AMD64
}
-}
#endif
+}
+#endif // !PRODUCT
intptr_t *frame::initial_deoptimization_info() {
// used to reset the saved FP
diff --git a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp
index 7f6a99ad2d6..3b5cd411ea3 100644
--- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp
+++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp
@@ -78,7 +78,11 @@ inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address
assert(((nmethod*)_cb)->insts_contains(_pc), "original PC must be in nmethod");
_deopt_state = is_deoptimized;
} else {
- _deopt_state = not_deoptimized;
+ if (_cb->is_deoptimization_stub()) {
+ _deopt_state = is_deoptimized;
+ } else {
+ _deopt_state = not_deoptimized;
+ }
}
}
diff --git a/hotspot/src/cpu/x86/vm/globals_x86.hpp b/hotspot/src/cpu/x86/vm/globals_x86.hpp
index 1777d54af7e..fe81aac91f4 100644
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp
@@ -46,7 +46,7 @@ define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs
// the the vep is aligned at CodeEntryAlignment whereas c2 only aligns
// the uep and the vep doesn't get real alignment but just slops on by
// only assured that the entry instruction meets the 5 byte size requirement.
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
define_pd_global(intx, CodeEntryAlignment, 32);
#else
define_pd_global(intx, CodeEntryAlignment, 16);
@@ -55,16 +55,28 @@ define_pd_global(intx, OptoLoopAlignment, 16);
define_pd_global(intx, InlineFrequencyCount, 100);
define_pd_global(intx, InlineSmallCode, 1000);
-define_pd_global(intx, StackYellowPages, NOT_WINDOWS(2) WINDOWS_ONLY(3));
-define_pd_global(intx, StackRedPages, 1);
+#define DEFAULT_STACK_YELLOW_PAGES (NOT_WINDOWS(2) WINDOWS_ONLY(3))
+#define DEFAULT_STACK_RED_PAGES (1)
+
+#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
+#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
+
#ifdef AMD64
// Very large C++ stack frames using solaris-amd64 optimized builds
// due to lack of optimization caused by C++ compiler bugs
-define_pd_global(intx, StackShadowPages, NOT_WIN64(20) WIN64_ONLY(6) DEBUG_ONLY(+2));
+#define DEFAULT_STACK_SHADOW_PAGES (NOT_WIN64(20) WIN64_ONLY(6) DEBUG_ONLY(+2))
+// For those clients that do not use write socket, we allow
+// the min range value to be below that of the default
+#define MIN_STACK_SHADOW_PAGES (NOT_WIN64(10) WIN64_ONLY(6) DEBUG_ONLY(+2))
#else
-define_pd_global(intx, StackShadowPages, 4 DEBUG_ONLY(+5));
+#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
+#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
#endif // AMD64
+define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
+define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
+define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
+
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
@@ -91,6 +103,7 @@ define_pd_global(bool, PreserveFramePointer, false);
\
product(intx, UseAVX, 99, \
"Highest supported AVX instructions set on x86/x64") \
+ range(0, 99) \
\
product(bool, UseCLMUL, false, \
"Control whether CLMUL instructions can be used on x86/x64") \
@@ -134,6 +147,7 @@ define_pd_global(bool, PreserveFramePointer, false);
\
product(uintx, RTMRetryCount, 5, \
"Number of RTM retries on lock abort or busy") \
+ range(0, max_uintx) \
\
experimental(intx, RTMSpinLoopCount, 100, \
"Spin count for lock to become free before RTM retry") \
diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp
index 5501b91530c..ea4c18d11c6 100644
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp
@@ -40,6 +40,11 @@
// Implementation of InterpreterMacroAssembler
+void InterpreterMacroAssembler::jump_to_entry(address entry) {
+ assert(entry, "Entry must have been generated by now");
+ jump(RuntimeAddress(entry));
+}
+
#ifndef CC_INTERP
void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) {
Label update, next, none;
@@ -1497,13 +1502,39 @@ void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
bind(skip_receiver_profile);
// The method data pointer needs to be updated to reflect the new target.
+#if INCLUDE_JVMCI
+ if (MethodProfileWidth == 0) {
+ update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size()));
+ }
+#else // INCLUDE_JVMCI
update_mdp_by_constant(mdp,
in_bytes(VirtualCallData::
virtual_call_data_size()));
+#endif // INCLUDE_JVMCI
bind(profile_continue);
}
}
+#if INCLUDE_JVMCI
+void InterpreterMacroAssembler::profile_called_method(Register method, Register mdp, Register reg2) {
+ assert_different_registers(method, mdp, reg2);
+ if (ProfileInterpreter && MethodProfileWidth > 0) {
+ Label profile_continue;
+
+ // If no method data exists, go to profile_continue.
+ test_method_data_pointer(mdp, profile_continue);
+
+ Label done;
+ record_item_in_profile_helper(method, mdp, reg2, 0, done, MethodProfileWidth,
+ &VirtualCallData::method_offset, &VirtualCallData::method_count_offset, in_bytes(VirtualCallData::nonprofiled_receiver_count_offset()));
+ bind(done);
+
+ update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size()));
+ bind(profile_continue);
+ }
+}
+#endif // INCLUDE_JVMCI
+
// This routine creates a state machine for updating the multi-row
// type profile at a virtual call site (or other type-sensitive bytecode).
// The machine visits each row (of receiver/count) until the receiver type
@@ -1523,14 +1554,36 @@ void InterpreterMacroAssembler::record_klass_in_profile_helper(
if (is_virtual_call) {
increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
}
- return;
- }
+#if INCLUDE_JVMCI
+ else if (EnableJVMCI) {
+ increment_mdp_data_at(mdp, in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset()));
+ }
+#endif // INCLUDE_JVMCI
+ } else {
+ int non_profiled_offset = -1;
+ if (is_virtual_call) {
+ non_profiled_offset = in_bytes(CounterData::count_offset());
+ }
+#if INCLUDE_JVMCI
+ else if (EnableJVMCI) {
+ non_profiled_offset = in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset());
+ }
+#endif // INCLUDE_JVMCI
- int last_row = VirtualCallData::row_limit() - 1;
+ record_item_in_profile_helper(receiver, mdp, reg2, 0, done, TypeProfileWidth,
+ &VirtualCallData::receiver_offset, &VirtualCallData::receiver_count_offset, non_profiled_offset);
+ }
+}
+
+void InterpreterMacroAssembler::record_item_in_profile_helper(Register item, Register mdp,
+ Register reg2, int start_row, Label& done, int total_rows,
+ OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
+ int non_profiled_offset) {
+ int last_row = total_rows - 1;
assert(start_row <= last_row, "must be work left to do");
- // Test this row for both the receiver and for null.
+ // Test this row for both the item and for null.
// Take any of three different outcomes:
- // 1. found receiver => increment count and goto done
+ // 1. found item => increment count and goto done
// 2. found null => keep looking for case 1, maybe allocate this cell
// 3. found something else => keep looking for cases 1 and 2
// Case 3 is handled by a recursive call.
@@ -1538,30 +1591,30 @@ void InterpreterMacroAssembler::record_klass_in_profile_helper(
Label next_test;
bool test_for_null_also = (row == start_row);
- // See if the receiver is receiver[n].
- int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row));
- test_mdp_data_at(mdp, recvr_offset, receiver,
+ // See if the item is item[n].
+ int item_offset = in_bytes(item_offset_fn(row));
+ test_mdp_data_at(mdp, item_offset, item,
(test_for_null_also ? reg2 : noreg),
next_test);
- // (Reg2 now contains the receiver from the CallData.)
+ // (Reg2 now contains the item from the CallData.)
- // The receiver is receiver[n]. Increment count[n].
- int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row));
+ // The item is item[n]. Increment count[n].
+ int count_offset = in_bytes(item_count_offset_fn(row));
increment_mdp_data_at(mdp, count_offset);
jmp(done);
bind(next_test);
if (test_for_null_also) {
Label found_null;
- // Failed the equality check on receiver[n]... Test for null.
+ // Failed the equality check on item[n]... Test for null.
testptr(reg2, reg2);
if (start_row == last_row) {
// The only thing left to do is handle the null case.
- if (is_virtual_call) {
+ if (non_profiled_offset >= 0) {
jccb(Assembler::zero, found_null);
- // Receiver did not match any saved receiver and there is no empty row for it.
+ // Item did not match any saved item and there is no empty row for it.
// Increment total counter to indicate polymorphic case.
- increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
+ increment_mdp_data_at(mdp, non_profiled_offset);
jmp(done);
bind(found_null);
} else {
@@ -1573,21 +1626,22 @@ void InterpreterMacroAssembler::record_klass_in_profile_helper(
jcc(Assembler::zero, found_null);
// Put all the "Case 3" tests here.
- record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call);
+ record_item_in_profile_helper(item, mdp, reg2, start_row + 1, done, total_rows,
+ item_offset_fn, item_count_offset_fn, non_profiled_offset);
- // Found a null. Keep searching for a matching receiver,
+ // Found a null. Keep searching for a matching item,
// but remember that this is an empty (unused) slot.
bind(found_null);
}
}
- // In the fall-through case, we found no matching receiver, but we
- // observed the receiver[start_row] is NULL.
+ // In the fall-through case, we found no matching item, but we
+ // observed the item[start_row] is NULL.
- // Fill in the receiver field and increment the count.
- int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row));
- set_mdp_data_at(mdp, recvr_offset, receiver);
- int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row));
+ // Fill in the item field and increment the count.
+ int item_offset = in_bytes(item_offset_fn(start_row));
+ set_mdp_data_at(mdp, item_offset, item);
+ int count_offset = in_bytes(item_count_offset_fn(start_row));
movl(reg2, DataLayout::counter_increment);
set_mdp_data_at(mdp, count_offset, reg2);
if (start_row > 0) {
diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp
index 35d1ad35686..08a293f99a2 100644
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp
@@ -32,6 +32,7 @@
// This file specializes the assember with interpreter-specific macros
+typedef ByteSize (*OffsetFunction)(uint);
class InterpreterMacroAssembler: public MacroAssembler {
@@ -60,6 +61,8 @@ class InterpreterMacroAssembler: public MacroAssembler {
_locals_register(LP64_ONLY(r14) NOT_LP64(rdi)),
_bcp_register(LP64_ONLY(r13) NOT_LP64(rsi)) {}
+ void jump_to_entry(address entry);
+
void load_earlyret_value(TosState state);
#ifdef CC_INTERP
@@ -249,6 +252,10 @@ class InterpreterMacroAssembler: public MacroAssembler {
void record_klass_in_profile_helper(Register receiver, Register mdp,
Register reg2, int start_row,
Label& done, bool is_virtual_call);
+ void record_item_in_profile_helper(Register item, Register mdp,
+ Register reg2, int start_row, Label& done, int total_rows,
+ OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn,
+ int non_profiled_offset);
void update_mdp_by_offset(Register mdp_in, int offset_of_offset);
void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp);
@@ -262,6 +269,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
void profile_virtual_call(Register receiver, Register mdp,
Register scratch2,
bool receiver_can_be_null = false);
+ void profile_called_method(Register method, Register mdp, Register reg2) NOT_JVMCI_RETURN;
void profile_ret(Register return_bci, Register mdp);
void profile_null_seen(Register mdp);
void profile_typecheck(Register mdp, Register klass, Register scratch);
diff --git a/hotspot/src/cpu/x86/vm/interpreterGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/interpreterGenerator_x86.cpp
index 229803a80ff..e22e3d366a0 100644
--- a/hotspot/src/cpu/x86/vm/interpreterGenerator_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/interpreterGenerator_x86.cpp
@@ -31,17 +31,6 @@
#define __ _masm->
-// Jump into normal path for accessor and empty entry to jump to normal entry
-// The "fast" optimization don't update compilation count therefore can disable inlining
-// for these functions that should be inlined.
-address InterpreterGenerator::generate_jump_to_normal_entry(void) {
- address entry_point = __ pc();
-
- assert(Interpreter::entry_for_kind(Interpreter::zerolocals) != NULL, "should already be generated");
- __ jump(RuntimeAddress(Interpreter::entry_for_kind(Interpreter::zerolocals)));
- return entry_point;
-}
-
// Abstract method entry
// Attempt to execute abstract method. Throw exception
address InterpreterGenerator::generate_abstract_entry(void) {
diff --git a/hotspot/src/cpu/x86/vm/interpreterGenerator_x86.hpp b/hotspot/src/cpu/x86/vm/interpreterGenerator_x86.hpp
index 70e38d9a245..ad9ca0fba3d 100644
--- a/hotspot/src/cpu/x86/vm/interpreterGenerator_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/interpreterGenerator_x86.hpp
@@ -36,19 +36,18 @@
address generate_native_entry(bool synchronized);
address generate_abstract_entry(void);
address generate_math_entry(AbstractInterpreter::MethodKind kind);
- address generate_jump_to_normal_entry(void);
- address generate_accessor_entry(void) { return generate_jump_to_normal_entry(); }
- address generate_empty_entry(void) { return generate_jump_to_normal_entry(); }
+ address generate_accessor_entry(void) { return NULL; }
+ address generate_empty_entry(void) { return NULL; }
address generate_Reference_get_entry();
address generate_CRC32_update_entry();
address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind);
+ address generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind);
#ifndef _LP64
address generate_Float_intBitsToFloat_entry();
address generate_Float_floatToRawIntBits_entry();
address generate_Double_longBitsToDouble_entry();
address generate_Double_doubleToRawLongBits_entry();
#endif
- void lock_method(void);
void generate_stack_overflow_check(void);
void generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue);
diff --git a/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp
index 4a2903b3736..2e641aa2522 100644
--- a/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp
+++ b/hotspot/src/cpu/x86/vm/interpreter_x86_32.cpp
@@ -151,11 +151,15 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin
__ pop_fTOS();
break;
case Interpreter::java_lang_math_exp:
- __ exp_with_fallback(0);
- // Store to stack to convert 80bit precision back to 64bits
- __ push_fTOS();
- __ pop_fTOS();
- break;
+ __ subptr(rsp, 2*wordSize);
+ __ fstp_d(Address(rsp, 0));
+ if (VM_Version::supports_sse2()) {
+ __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dexp())));
+ } else {
+ __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dexp)));
+ }
+ __ addptr(rsp, 2*wordSize);
+ break;
default :
ShouldNotReachHere();
}
diff --git a/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp
index af4f7fac388..682addd3c77 100644
--- a/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp
@@ -52,8 +52,6 @@
#define __ _masm->
-PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-
#ifdef _WIN64
address AbstractInterpreterGenerator::generate_slow_signature_handler() {
address entry = __ pc();
@@ -252,6 +250,9 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin
if (kind == Interpreter::java_lang_math_sqrt) {
__ sqrtsd(xmm0, Address(rsp, wordSize));
+ } else if (kind == Interpreter::java_lang_math_exp) {
+ __ movdbl(xmm0, Address(rsp, wordSize));
+ __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dexp())));
} else {
__ fld_d(Address(rsp, wordSize));
switch (kind) {
@@ -278,9 +279,6 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin
// empty stack slot)
__ pow_with_fallback(0);
break;
- case Interpreter::java_lang_math_exp:
- __ exp_with_fallback(0);
- break;
default :
ShouldNotReachHere();
}
diff --git a/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp b/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp
new file mode 100644
index 00000000000..6b467b1110b
--- /dev/null
+++ b/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "compiler/disassembler.hpp"
+#include "oops/oop.inline.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/sharedRuntime.hpp"
+#include "jvmci/jvmciEnv.hpp"
+#include "jvmci/jvmciCodeInstaller.hpp"
+#include "jvmci/jvmciJavaClasses.hpp"
+#include "jvmci/jvmciCompilerToVM.hpp"
+#include "jvmci/jvmciRuntime.hpp"
+#include "asm/register.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "code/vmreg.hpp"
+#include "vmreg_x86.inline.hpp"
+
+jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, oop method) {
+ if (inst->is_call() || inst->is_jump()) {
+ assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size");
+ return (pc_offset + NativeCall::instruction_size);
+ } else if (inst->is_mov_literal64()) {
+ // mov+call instruction pair
+ jint offset = pc_offset + NativeMovConstReg::instruction_size;
+ u_char* call = (u_char*) (_instructions->start() + offset);
+ if (call[0] == Assembler::REX_B) {
+ offset += 1; /* prefix byte for extended register R8-R15 */
+ call++;
+ }
+ assert(call[0] == 0xFF, "expected call");
+ offset += 2; /* opcode byte + modrm byte */
+ return (offset);
+ } else if (inst->is_call_reg()) {
+ // the inlined vtable stub contains a "call register" instruction
+ assert(method != NULL, "only valid for virtual calls");
+ return (pc_offset + ((NativeCallReg *) inst)->next_instruction_offset());
+ } else if (inst->is_cond_jump()) {
+ address pc = (address) (inst);
+ return pc_offset + (jint) (Assembler::locate_next_instruction(pc) - pc);
+ } else {
+ fatal("unsupported type of instruction for call site");
+ return 0;
+ }
+}
+
+void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) {
+ address pc = _instructions->start() + pc_offset;
+ Handle obj = HotSpotObjectConstantImpl::object(constant);
+ jobject value = JNIHandles::make_local(obj());
+ if (HotSpotObjectConstantImpl::compressed(constant)) {
+#ifdef _LP64
+ address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
+ int oop_index = _oop_recorder->find_index(value);
+ _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand);
+ TRACE_jvmci_3("relocating (narrow oop constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
+#else
+ fatal("compressed oop on 32bit");
+#endif
+ } else {
+ address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
+ *((jobject*) operand) = value;
+ _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand);
+ TRACE_jvmci_3("relocating (oop constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
+ }
+}
+
+void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
+ address pc = _instructions->start() + pc_offset;
+
+ address operand = Assembler::locate_operand(pc, Assembler::disp32_operand);
+ address next_instruction = Assembler::locate_next_instruction(pc);
+ address dest = _constants->start() + data_offset;
+
+ long disp = dest - next_instruction;
+ assert(disp == (jint) disp, "disp doesn't fit in 32 bits");
+ *((jint*) operand) = (jint) disp;
+
+ _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand);
+ TRACE_jvmci_3("relocating at " PTR_FORMAT "/" PTR_FORMAT " with destination at " PTR_FORMAT " (%d)", p2i(pc), p2i(operand), p2i(dest), data_offset);
+}
+
+void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
+ if (cb->is_nmethod()) {
+ nmethod* nm = (nmethod*) cb;
+ nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point());
+ } else {
+ nativeJump_at((address)inst)->set_jump_destination(cb->code_begin());
+ }
+ _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
+}
+
+void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
+ address pc = (address) inst;
+ if (inst->is_call()) {
+ // NOTE: for call without a mov, the offset must fit a 32-bit immediate
+ // see also CompilerToVM.getMaxCallTargetOffset()
+ NativeCall* call = nativeCall_at(pc);
+ call->set_destination((address) foreign_call_destination);
+ _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+ } else if (inst->is_mov_literal64()) {
+ NativeMovConstReg* mov = nativeMovConstReg_at(pc);
+ mov->set_data((intptr_t) foreign_call_destination);
+ _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand);
+ } else if (inst->is_jump()) {
+ NativeJump* jump = nativeJump_at(pc);
+ jump->set_jump_destination((address) foreign_call_destination);
+ _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand);
+ } else if (inst->is_cond_jump()) {
+ address old_dest = nativeGeneralJump_at(pc)->jump_destination();
+ address disp = Assembler::locate_operand(pc, Assembler::call32_operand);
+ *(jint*) disp += ((address) foreign_call_destination) - old_dest;
+ _instructions->relocate(pc, runtime_call_Relocation::spec(), Assembler::call32_operand);
+ } else {
+ fatal("unsupported relocation for foreign call");
+ }
+
+ TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst));
+}
+
+void CodeInstaller::pd_relocate_JavaMethod(oop hotspot_method, jint pc_offset) {
+#ifdef ASSERT
+ Method* method = NULL;
+ // we need to check, this might also be an unresolved method
+ if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) {
+ method = getMethodFromHotSpotMethod(hotspot_method);
+ }
+#endif
+ switch (_next_call_type) {
+ case INLINE_INVOKE:
+ break;
+ case INVOKEVIRTUAL:
+ case INVOKEINTERFACE: {
+ assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface");
+
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_virtual_call_stub());
+ _instructions->relocate(call->instruction_address(),
+ virtual_call_Relocation::spec(_invoke_mark_pc),
+ Assembler::call32_operand);
+ break;
+ }
+ case INVOKESTATIC: {
+ assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic");
+
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_static_call_stub());
+ _instructions->relocate(call->instruction_address(),
+ relocInfo::static_call_type, Assembler::call32_operand);
+ break;
+ }
+ case INVOKESPECIAL: {
+ assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial");
+ NativeCall* call = nativeCall_at(_instructions->start() + pc_offset);
+ call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub());
+ _instructions->relocate(call->instruction_address(),
+ relocInfo::opt_virtual_call_type, Assembler::call32_operand);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static void relocate_poll_near(address pc) {
+ NativeInstruction* ni = nativeInstruction_at(pc);
+ int32_t* disp = (int32_t*) Assembler::locate_operand(pc, Assembler::disp32_operand);
+ int32_t offset = *disp; // The Java code installed the polling page offset into the disp32 operand
+ intptr_t new_disp = (intptr_t) (os::get_polling_page() + offset) - (intptr_t) ni;
+ *disp = (int32_t)new_disp;
+}
+
+
+void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
+ switch (mark) {
+ case POLL_NEAR: {
+ relocate_poll_near(pc);
+ _instructions->relocate(pc, relocInfo::poll_type, Assembler::disp32_operand);
+ break;
+ }
+ case POLL_FAR:
+ // This is a load from a register so there is no relocatable operand.
+ // We just have to ensure that the format is not disp32_operand
+ // so that poll_Relocation::fix_relocation_after_move does the right
+ // thing (i.e. ignores this relocation record)
+ _instructions->relocate(pc, relocInfo::poll_type, Assembler::imm_operand);
+ break;
+ case POLL_RETURN_NEAR: {
+ relocate_poll_near(pc);
+ _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::disp32_operand);
+ break;
+ }
+ case POLL_RETURN_FAR:
+ // see comment above for POLL_FAR
+ _instructions->relocate(pc, relocInfo::poll_return_type, Assembler::imm_operand);
+ break;
+ default:
+ fatal("invalid mark value");
+ break;
+ }
+}
+
+// convert JVMCI register indices (as used in oop maps) to HotSpot registers
+VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg) {
+ if (jvmci_reg < RegisterImpl::number_of_registers) {
+ return as_Register(jvmci_reg)->as_VMReg();
+ } else {
+ jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_registers;
+ if (floatRegisterNumber < XMMRegisterImpl::number_of_registers) {
+ return as_XMMRegister(floatRegisterNumber)->as_VMReg();
+ }
+ ShouldNotReachHere();
+ return NULL;
+ }
+}
+
+bool CodeInstaller::is_general_purpose_reg(VMReg hotspotRegister) {
+ return !(hotspotRegister->is_FloatRegister() || hotspotRegister->is_XMMRegister());
+}
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
index eb6e422a854..eef3cd90afe 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
@@ -45,6 +45,7 @@
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
#include "gc/g1/heapRegion.hpp"
#endif // INCLUDE_ALL_GCS
+#include "crc32c.h"
#ifdef PRODUCT
#define BLOCK_COMMENT(str) /* nothing */
@@ -56,8 +57,6 @@
#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
-PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-
#ifdef ASSERT
bool AbstractAssembler::pd_check_instruction_mark() { return true; }
#endif
@@ -417,7 +416,7 @@ void MacroAssembler::debug32(int rdi, int rsi, int rbp, int rsp, int rbx, int rd
::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", msg);
}
// Don't assert holding the ttyLock
- assert(false, err_msg("DEBUG MESSAGE: %s", msg));
+ assert(false, "DEBUG MESSAGE: %s", msg);
ThreadStateTransition::transition(thread, _thread_in_vm, saved_state);
}
@@ -883,7 +882,7 @@ void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[]) {
ttyLocker ttyl;
::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n",
msg);
- assert(false, err_msg("DEBUG MESSAGE: %s", msg));
+ assert(false, "DEBUG MESSAGE: %s", msg);
}
}
@@ -2888,7 +2887,7 @@ void MacroAssembler::divss(XMMRegister dst, AddressLiteral src) {
}
// !defined(COMPILER2) is because of stupid core builds
-#if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2)
+#if !defined(_LP64) || defined(COMPILER1) || !defined(COMPILER2) || INCLUDE_JVMCI
void MacroAssembler::empty_FPU_stack() {
if (VM_Version::supports_mmx()) {
emms();
@@ -2896,7 +2895,7 @@ void MacroAssembler::empty_FPU_stack() {
for (int i = 8; i-- > 0; ) ffree(i);
}
}
-#endif // !LP64 || C1 || !C2
+#endif // !LP64 || C1 || !C2 || INCLUDE_JVMCI
// Defines obj, preserves var_size_in_bytes
@@ -3032,6 +3031,15 @@ void MacroAssembler::fldcw(AddressLiteral src) {
Assembler::fldcw(as_Address(src));
}
+void MacroAssembler::mulpd(XMMRegister dst, AddressLiteral src) {
+ if (reachable(src)) {
+ Assembler::mulpd(dst, as_Address(src));
+ } else {
+ lea(rscratch1, src);
+ Assembler::mulpd(dst, Address(rscratch1, 0));
+ }
+}
+
void MacroAssembler::pow_exp_core_encoding() {
// kills rax, rcx, rdx
subptr(rsp,sizeof(jdouble));
@@ -3104,19 +3112,7 @@ void MacroAssembler::fast_pow() {
BLOCK_COMMENT("} fast_pow");
}
-void MacroAssembler::fast_exp() {
- // computes exp(X) = 2^(X * log2(e))
- // if fast computation is not possible, result is NaN. Requires
- // fallback from user of this macro.
- // increase precision for intermediate steps of the computation
- increase_precision();
- fldl2e(); // Stack: log2(e) X ...
- fmulp(1); // Stack: (X*log2(e)) ...
- pow_exp_core_encoding(); // Stack: exp(X) ...
- restore_precision();
-}
-
-void MacroAssembler::pow_or_exp(bool is_exp, int num_fpu_regs_in_use) {
+void MacroAssembler::pow_or_exp(int num_fpu_regs_in_use) {
// kills rax, rcx, rdx
// pow and exp needs 2 extra registers on the fpu stack.
Label slow_case, done;
@@ -3128,182 +3124,164 @@ void MacroAssembler::pow_or_exp(bool is_exp, int num_fpu_regs_in_use) {
Register tmp2 = rax;
Register tmp3 = rcx;
- if (is_exp) {
- // Stack: X
- fld_s(0); // duplicate argument for runtime call. Stack: X X
- fast_exp(); // Stack: exp(X) X
- fcmp(tmp, 0, false, false); // Stack: exp(X) X
- // exp(X) not equal to itself: exp(X) is NaN go to slow case.
- jcc(Assembler::parity, slow_case);
- // get rid of duplicate argument. Stack: exp(X)
- if (num_fpu_regs_in_use > 0) {
- fxch();
- fpop();
- } else {
- ffree(1);
- }
- jmp(done);
+ // Stack: X Y
+ Label x_negative, y_not_2;
+
+ static double two = 2.0;
+ ExternalAddress two_addr((address)&two);
+
+ // constant maybe too far on 64 bit
+ lea(tmp2, two_addr);
+ fld_d(Address(tmp2, 0)); // Stack: 2 X Y
+ fcmp(tmp, 2, true, false); // Stack: X Y
+ jcc(Assembler::parity, y_not_2);
+ jcc(Assembler::notEqual, y_not_2);
+
+ fxch(); fpop(); // Stack: X
+ fmul(0); // Stack: X*X
+
+ jmp(done);
+
+ bind(y_not_2);
+
+ fldz(); // Stack: 0 X Y
+ fcmp(tmp, 1, true, false); // Stack: X Y
+ jcc(Assembler::above, x_negative);
+
+ // X >= 0
+
+ fld_s(1); // duplicate arguments for runtime call. Stack: Y X Y
+ fld_s(1); // Stack: X Y X Y
+ fast_pow(); // Stack: X^Y X Y
+ fcmp(tmp, 0, false, false); // Stack: X^Y X Y
+ // X^Y not equal to itself: X^Y is NaN go to slow case.
+ jcc(Assembler::parity, slow_case);
+ // get rid of duplicate arguments. Stack: X^Y
+ if (num_fpu_regs_in_use > 0) {
+ fxch(); fpop();
+ fxch(); fpop();
} else {
- // Stack: X Y
- Label x_negative, y_not_2;
+ ffree(2);
+ ffree(1);
+ }
+ jmp(done);
- static double two = 2.0;
- ExternalAddress two_addr((address)&two);
+ // X <= 0
+ bind(x_negative);
- // constant maybe too far on 64 bit
- lea(tmp2, two_addr);
- fld_d(Address(tmp2, 0)); // Stack: 2 X Y
- fcmp(tmp, 2, true, false); // Stack: X Y
- jcc(Assembler::parity, y_not_2);
- jcc(Assembler::notEqual, y_not_2);
+ fld_s(1); // Stack: Y X Y
+ frndint(); // Stack: int(Y) X Y
+ fcmp(tmp, 2, false, false); // Stack: int(Y) X Y
+ jcc(Assembler::notEqual, slow_case);
- fxch(); fpop(); // Stack: X
- fmul(0); // Stack: X*X
+ subptr(rsp, 8);
- jmp(done);
-
- bind(y_not_2);
-
- fldz(); // Stack: 0 X Y
- fcmp(tmp, 1, true, false); // Stack: X Y
- jcc(Assembler::above, x_negative);
-
- // X >= 0
-
- fld_s(1); // duplicate arguments for runtime call. Stack: Y X Y
- fld_s(1); // Stack: X Y X Y
- fast_pow(); // Stack: X^Y X Y
- fcmp(tmp, 0, false, false); // Stack: X^Y X Y
- // X^Y not equal to itself: X^Y is NaN go to slow case.
- jcc(Assembler::parity, slow_case);
- // get rid of duplicate arguments. Stack: X^Y
- if (num_fpu_regs_in_use > 0) {
- fxch(); fpop();
- fxch(); fpop();
- } else {
- ffree(2);
- ffree(1);
- }
- jmp(done);
-
- // X <= 0
- bind(x_negative);
-
- fld_s(1); // Stack: Y X Y
- frndint(); // Stack: int(Y) X Y
- fcmp(tmp, 2, false, false); // Stack: int(Y) X Y
- jcc(Assembler::notEqual, slow_case);
-
- subptr(rsp, 8);
-
- // For X^Y, when X < 0, Y has to be an integer and the final
- // result depends on whether it's odd or even. We just checked
- // that int(Y) == Y. We move int(Y) to gp registers as a 64 bit
- // integer to test its parity. If int(Y) is huge and doesn't fit
- // in the 64 bit integer range, the integer indefinite value will
- // end up in the gp registers. Huge numbers are all even, the
- // integer indefinite number is even so it's fine.
+ // For X^Y, when X < 0, Y has to be an integer and the final
+ // result depends on whether it's odd or even. We just checked
+ // that int(Y) == Y. We move int(Y) to gp registers as a 64 bit
+ // integer to test its parity. If int(Y) is huge and doesn't fit
+ // in the 64 bit integer range, the integer indefinite value will
+ // end up in the gp registers. Huge numbers are all even, the
+ // integer indefinite number is even so it's fine.
#ifdef ASSERT
- // Let's check we don't end up with an integer indefinite number
- // when not expected. First test for huge numbers: check whether
- // int(Y)+1 == int(Y) which is true for very large numbers and
- // those are all even. A 64 bit integer is guaranteed to not
- // overflow for numbers where y+1 != y (when precision is set to
- // double precision).
- Label y_not_huge;
+ // Let's check we don't end up with an integer indefinite number
+ // when not expected. First test for huge numbers: check whether
+ // int(Y)+1 == int(Y) which is true for very large numbers and
+ // those are all even. A 64 bit integer is guaranteed to not
+ // overflow for numbers where y+1 != y (when precision is set to
+ // double precision).
+ Label y_not_huge;
- fld1(); // Stack: 1 int(Y) X Y
- fadd(1); // Stack: 1+int(Y) int(Y) X Y
+ fld1(); // Stack: 1 int(Y) X Y
+ fadd(1); // Stack: 1+int(Y) int(Y) X Y
#ifdef _LP64
- // trip to memory to force the precision down from double extended
- // precision
- fstp_d(Address(rsp, 0));
- fld_d(Address(rsp, 0));
+ // trip to memory to force the precision down from double extended
+ // precision
+ fstp_d(Address(rsp, 0));
+ fld_d(Address(rsp, 0));
#endif
- fcmp(tmp, 1, true, false); // Stack: int(Y) X Y
+ fcmp(tmp, 1, true, false); // Stack: int(Y) X Y
#endif
- // move int(Y) as 64 bit integer to thread's stack
- fistp_d(Address(rsp,0)); // Stack: X Y
+ // move int(Y) as 64 bit integer to thread's stack
+ fistp_d(Address(rsp,0)); // Stack: X Y
#ifdef ASSERT
- jcc(Assembler::notEqual, y_not_huge);
+ jcc(Assembler::notEqual, y_not_huge);
- // Y is huge so we know it's even. It may not fit in a 64 bit
- // integer and we don't want the debug code below to see the
- // integer indefinite value so overwrite int(Y) on the thread's
- // stack with 0.
- movl(Address(rsp, 0), 0);
- movl(Address(rsp, 4), 0);
+ // Y is huge so we know it's even. It may not fit in a 64 bit
+ // integer and we don't want the debug code below to see the
+ // integer indefinite value so overwrite int(Y) on the thread's
+ // stack with 0.
+ movl(Address(rsp, 0), 0);
+ movl(Address(rsp, 4), 0);
- bind(y_not_huge);
+ bind(y_not_huge);
#endif
- fld_s(1); // duplicate arguments for runtime call. Stack: Y X Y
- fld_s(1); // Stack: X Y X Y
- fabs(); // Stack: abs(X) Y X Y
- fast_pow(); // Stack: abs(X)^Y X Y
- fcmp(tmp, 0, false, false); // Stack: abs(X)^Y X Y
- // abs(X)^Y not equal to itself: abs(X)^Y is NaN go to slow case.
+ fld_s(1); // duplicate arguments for runtime call. Stack: Y X Y
+ fld_s(1); // Stack: X Y X Y
+ fabs(); // Stack: abs(X) Y X Y
+ fast_pow(); // Stack: abs(X)^Y X Y
+ fcmp(tmp, 0, false, false); // Stack: abs(X)^Y X Y
+ // abs(X)^Y not equal to itself: abs(X)^Y is NaN go to slow case.
- pop(tmp2);
- NOT_LP64(pop(tmp3));
- jcc(Assembler::parity, slow_case);
+ pop(tmp2);
+ NOT_LP64(pop(tmp3));
+ jcc(Assembler::parity, slow_case);
#ifdef ASSERT
- // Check that int(Y) is not integer indefinite value (int
- // overflow). Shouldn't happen because for values that would
- // overflow, 1+int(Y)==Y which was tested earlier.
+ // Check that int(Y) is not integer indefinite value (int
+ // overflow). Shouldn't happen because for values that would
+ // overflow, 1+int(Y)==Y which was tested earlier.
#ifndef _LP64
- {
- Label integer;
- testl(tmp2, tmp2);
- jcc(Assembler::notZero, integer);
- cmpl(tmp3, 0x80000000);
- jcc(Assembler::notZero, integer);
- STOP("integer indefinite value shouldn't be seen here");
- bind(integer);
- }
-#else
- {
- Label integer;
- mov(tmp3, tmp2); // preserve tmp2 for parity check below
- shlq(tmp3, 1);
- jcc(Assembler::carryClear, integer);
- jcc(Assembler::notZero, integer);
- STOP("integer indefinite value shouldn't be seen here");
- bind(integer);
- }
-#endif
-#endif
-
- // get rid of duplicate arguments. Stack: X^Y
- if (num_fpu_regs_in_use > 0) {
- fxch(); fpop();
- fxch(); fpop();
- } else {
- ffree(2);
- ffree(1);
- }
-
- testl(tmp2, 1);
- jcc(Assembler::zero, done); // X <= 0, Y even: X^Y = abs(X)^Y
- // X <= 0, Y even: X^Y = -abs(X)^Y
-
- fchs(); // Stack: -abs(X)^Y Y
- jmp(done);
+ {
+ Label integer;
+ testl(tmp2, tmp2);
+ jcc(Assembler::notZero, integer);
+ cmpl(tmp3, 0x80000000);
+ jcc(Assembler::notZero, integer);
+ STOP("integer indefinite value shouldn't be seen here");
+ bind(integer);
}
+#else
+ {
+ Label integer;
+ mov(tmp3, tmp2); // preserve tmp2 for parity check below
+ shlq(tmp3, 1);
+ jcc(Assembler::carryClear, integer);
+ jcc(Assembler::notZero, integer);
+ STOP("integer indefinite value shouldn't be seen here");
+ bind(integer);
+ }
+#endif
+#endif
+
+ // get rid of duplicate arguments. Stack: X^Y
+ if (num_fpu_regs_in_use > 0) {
+ fxch(); fpop();
+ fxch(); fpop();
+ } else {
+ ffree(2);
+ ffree(1);
+ }
+
+ testl(tmp2, 1);
+ jcc(Assembler::zero, done); // X <= 0, Y even: X^Y = abs(X)^Y
+ // X <= 0, Y even: X^Y = -abs(X)^Y
+
+ fchs(); // Stack: -abs(X)^Y Y
+ jmp(done);
// slow case: runtime call
bind(slow_case);
fpop(); // pop incorrect result or int(Y)
- fp_runtime_fallback(is_exp ? CAST_FROM_FN_PTR(address, SharedRuntime::dexp) : CAST_FROM_FN_PTR(address, SharedRuntime::dpow),
- is_exp ? 1 : 2, num_fpu_regs_in_use);
+ fp_runtime_fallback(CAST_FROM_FN_PTR(address, SharedRuntime::dpow), 2, num_fpu_regs_in_use);
// Come here with result in F-TOS
bind(done);
@@ -6267,7 +6245,9 @@ void MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool fp_
// Save caller's stack pointer into RBP if the frame pointer is preserved.
if (PreserveFramePointer) {
movptr(rbp, rsp);
- addptr(rbp, framesize + wordSize);
+ if (framesize > 0) {
+ addptr(rbp, framesize);
+ }
}
}
@@ -8636,6 +8616,471 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len, Regi
notl(crc); // ~c
}
+#ifdef _LP64
+// S. Gueron / Information Processing Letters 112 (2012) 184
+// Algorithm 4: Computing carry-less multiplication using a precomputed lookup table.
+// Input: A 32 bit value B = [byte3, byte2, byte1, byte0].
+// Output: the 64-bit carry-less product of B * CONST
+void MacroAssembler::crc32c_ipl_alg4(Register in, uint32_t n,
+ Register tmp1, Register tmp2, Register tmp3) {
+ lea(tmp3, ExternalAddress(StubRoutines::crc32c_table_addr()));
+ if (n > 0) {
+ addq(tmp3, n * 256 * 8);
+ }
+ // Q1 = TABLEExt[n][B & 0xFF];
+ movl(tmp1, in);
+ andl(tmp1, 0x000000FF);
+ shll(tmp1, 3);
+ addq(tmp1, tmp3);
+ movq(tmp1, Address(tmp1, 0));
+
+ // Q2 = TABLEExt[n][B >> 8 & 0xFF];
+ movl(tmp2, in);
+ shrl(tmp2, 8);
+ andl(tmp2, 0x000000FF);
+ shll(tmp2, 3);
+ addq(tmp2, tmp3);
+ movq(tmp2, Address(tmp2, 0));
+
+ shlq(tmp2, 8);
+ xorq(tmp1, tmp2);
+
+ // Q3 = TABLEExt[n][B >> 16 & 0xFF];
+ movl(tmp2, in);
+ shrl(tmp2, 16);
+ andl(tmp2, 0x000000FF);
+ shll(tmp2, 3);
+ addq(tmp2, tmp3);
+ movq(tmp2, Address(tmp2, 0));
+
+ shlq(tmp2, 16);
+ xorq(tmp1, tmp2);
+
+ // Q4 = TABLEExt[n][B >> 24 & 0xFF];
+ shrl(in, 24);
+ andl(in, 0x000000FF);
+ shll(in, 3);
+ addq(in, tmp3);
+ movq(in, Address(in, 0));
+
+ shlq(in, 24);
+ xorq(in, tmp1);
+ // return Q1 ^ Q2 << 8 ^ Q3 << 16 ^ Q4 << 24;
+}
+
+void MacroAssembler::crc32c_pclmulqdq(XMMRegister w_xtmp1,
+ Register in_out,
+ uint32_t const_or_pre_comp_const_index, bool is_pclmulqdq_supported,
+ XMMRegister w_xtmp2,
+ Register tmp1,
+ Register n_tmp2, Register n_tmp3) {
+ if (is_pclmulqdq_supported) {
+ movdl(w_xtmp1, in_out); // modified blindly
+
+ movl(tmp1, const_or_pre_comp_const_index);
+ movdl(w_xtmp2, tmp1);
+ pclmulqdq(w_xtmp1, w_xtmp2, 0);
+
+ movdq(in_out, w_xtmp1);
+ } else {
+ crc32c_ipl_alg4(in_out, const_or_pre_comp_const_index, tmp1, n_tmp2, n_tmp3);
+ }
+}
+
+// Recombination Alternative 2: No bit-reflections
+// T1 = (CRC_A * U1) << 1
+// T2 = (CRC_B * U2) << 1
+// C1 = T1 >> 32
+// C2 = T2 >> 32
+// T1 = T1 & 0xFFFFFFFF
+// T2 = T2 & 0xFFFFFFFF
+// T1 = CRC32(0, T1)
+// T2 = CRC32(0, T2)
+// C1 = C1 ^ T1
+// C2 = C2 ^ T2
+// CRC = C1 ^ C2 ^ CRC_C
+void MacroAssembler::crc32c_rec_alt2(uint32_t const_or_pre_comp_const_index_u1, uint32_t const_or_pre_comp_const_index_u2, bool is_pclmulqdq_supported, Register in_out, Register in1, Register in2,
+ XMMRegister w_xtmp1, XMMRegister w_xtmp2, XMMRegister w_xtmp3,
+ Register tmp1, Register tmp2,
+ Register n_tmp3) {
+ crc32c_pclmulqdq(w_xtmp1, in_out, const_or_pre_comp_const_index_u1, is_pclmulqdq_supported, w_xtmp3, tmp1, tmp2, n_tmp3);
+ crc32c_pclmulqdq(w_xtmp2, in1, const_or_pre_comp_const_index_u2, is_pclmulqdq_supported, w_xtmp3, tmp1, tmp2, n_tmp3);
+ shlq(in_out, 1);
+ movl(tmp1, in_out);
+ shrq(in_out, 32);
+ xorl(tmp2, tmp2);
+ crc32(tmp2, tmp1, 4);
+ xorl(in_out, tmp2); // we don't care about upper 32 bit contents here
+ shlq(in1, 1);
+ movl(tmp1, in1);
+ shrq(in1, 32);
+ xorl(tmp2, tmp2);
+ crc32(tmp2, tmp1, 4);
+ xorl(in1, tmp2);
+ xorl(in_out, in1);
+ xorl(in_out, in2);
+}
+
+// Set N to predefined value
+// Subtract from a lenght of a buffer
+// execute in a loop:
+// CRC_A = 0xFFFFFFFF, CRC_B = 0, CRC_C = 0
+// for i = 1 to N do
+// CRC_A = CRC32(CRC_A, A[i])
+// CRC_B = CRC32(CRC_B, B[i])
+// CRC_C = CRC32(CRC_C, C[i])
+// end for
+// Recombine
+void MacroAssembler::crc32c_proc_chunk(uint32_t size, uint32_t const_or_pre_comp_const_index_u1, uint32_t const_or_pre_comp_const_index_u2, bool is_pclmulqdq_supported,
+ Register in_out1, Register in_out2, Register in_out3,
+ Register tmp1, Register tmp2, Register tmp3,
+ XMMRegister w_xtmp1, XMMRegister w_xtmp2, XMMRegister w_xtmp3,
+ Register tmp4, Register tmp5,
+ Register n_tmp6) {
+ Label L_processPartitions;
+ Label L_processPartition;
+ Label L_exit;
+
+ bind(L_processPartitions);
+ cmpl(in_out1, 3 * size);
+ jcc(Assembler::less, L_exit);
+ xorl(tmp1, tmp1);
+ xorl(tmp2, tmp2);
+ movq(tmp3, in_out2);
+ addq(tmp3, size);
+
+ bind(L_processPartition);
+ crc32(in_out3, Address(in_out2, 0), 8);
+ crc32(tmp1, Address(in_out2, size), 8);
+ crc32(tmp2, Address(in_out2, size * 2), 8);
+ addq(in_out2, 8);
+ cmpq(in_out2, tmp3);
+ jcc(Assembler::less, L_processPartition);
+ crc32c_rec_alt2(const_or_pre_comp_const_index_u1, const_or_pre_comp_const_index_u2, is_pclmulqdq_supported, in_out3, tmp1, tmp2,
+ w_xtmp1, w_xtmp2, w_xtmp3,
+ tmp4, tmp5,
+ n_tmp6);
+ addq(in_out2, 2 * size);
+ subl(in_out1, 3 * size);
+ jmp(L_processPartitions);
+
+ bind(L_exit);
+}
+#else
+void MacroAssembler::crc32c_ipl_alg4(Register in_out, uint32_t n,
+ Register tmp1, Register tmp2, Register tmp3,
+ XMMRegister xtmp1, XMMRegister xtmp2) {
+ lea(tmp3, ExternalAddress(StubRoutines::crc32c_table_addr()));
+ if (n > 0) {
+ addl(tmp3, n * 256 * 8);
+ }
+ // Q1 = TABLEExt[n][B & 0xFF];
+ movl(tmp1, in_out);
+ andl(tmp1, 0x000000FF);
+ shll(tmp1, 3);
+ addl(tmp1, tmp3);
+ movq(xtmp1, Address(tmp1, 0));
+
+ // Q2 = TABLEExt[n][B >> 8 & 0xFF];
+ movl(tmp2, in_out);
+ shrl(tmp2, 8);
+ andl(tmp2, 0x000000FF);
+ shll(tmp2, 3);
+ addl(tmp2, tmp3);
+ movq(xtmp2, Address(tmp2, 0));
+
+ psllq(xtmp2, 8);
+ pxor(xtmp1, xtmp2);
+
+ // Q3 = TABLEExt[n][B >> 16 & 0xFF];
+ movl(tmp2, in_out);
+ shrl(tmp2, 16);
+ andl(tmp2, 0x000000FF);
+ shll(tmp2, 3);
+ addl(tmp2, tmp3);
+ movq(xtmp2, Address(tmp2, 0));
+
+ psllq(xtmp2, 16);
+ pxor(xtmp1, xtmp2);
+
+ // Q4 = TABLEExt[n][B >> 24 & 0xFF];
+ shrl(in_out, 24);
+ andl(in_out, 0x000000FF);
+ shll(in_out, 3);
+ addl(in_out, tmp3);
+ movq(xtmp2, Address(in_out, 0));
+
+ psllq(xtmp2, 24);
+ pxor(xtmp1, xtmp2); // Result in CXMM
+ // return Q1 ^ Q2 << 8 ^ Q3 << 16 ^ Q4 << 24;
+}
+
+void MacroAssembler::crc32c_pclmulqdq(XMMRegister w_xtmp1,
+ Register in_out,
+ uint32_t const_or_pre_comp_const_index, bool is_pclmulqdq_supported,
+ XMMRegister w_xtmp2,
+ Register tmp1,
+ Register n_tmp2, Register n_tmp3) {
+ if (is_pclmulqdq_supported) {
+ movdl(w_xtmp1, in_out);
+
+ movl(tmp1, const_or_pre_comp_const_index);
+ movdl(w_xtmp2, tmp1);
+ pclmulqdq(w_xtmp1, w_xtmp2, 0);
+ // Keep result in XMM since GPR is 32 bit in length
+ } else {
+ crc32c_ipl_alg4(in_out, const_or_pre_comp_const_index, tmp1, n_tmp2, n_tmp3, w_xtmp1, w_xtmp2);
+ }
+}
+
+void MacroAssembler::crc32c_rec_alt2(uint32_t const_or_pre_comp_const_index_u1, uint32_t const_or_pre_comp_const_index_u2, bool is_pclmulqdq_supported, Register in_out, Register in1, Register in2,
+ XMMRegister w_xtmp1, XMMRegister w_xtmp2, XMMRegister w_xtmp3,
+ Register tmp1, Register tmp2,
+ Register n_tmp3) {
+ crc32c_pclmulqdq(w_xtmp1, in_out, const_or_pre_comp_const_index_u1, is_pclmulqdq_supported, w_xtmp3, tmp1, tmp2, n_tmp3);
+ crc32c_pclmulqdq(w_xtmp2, in1, const_or_pre_comp_const_index_u2, is_pclmulqdq_supported, w_xtmp3, tmp1, tmp2, n_tmp3);
+
+ psllq(w_xtmp1, 1);
+ movdl(tmp1, w_xtmp1);
+ psrlq(w_xtmp1, 32);
+ movdl(in_out, w_xtmp1);
+
+ xorl(tmp2, tmp2);
+ crc32(tmp2, tmp1, 4);
+ xorl(in_out, tmp2);
+
+ psllq(w_xtmp2, 1);
+ movdl(tmp1, w_xtmp2);
+ psrlq(w_xtmp2, 32);
+ movdl(in1, w_xtmp2);
+
+ xorl(tmp2, tmp2);
+ crc32(tmp2, tmp1, 4);
+ xorl(in1, tmp2);
+ xorl(in_out, in1);
+ xorl(in_out, in2);
+}
+
+void MacroAssembler::crc32c_proc_chunk(uint32_t size, uint32_t const_or_pre_comp_const_index_u1, uint32_t const_or_pre_comp_const_index_u2, bool is_pclmulqdq_supported,
+ Register in_out1, Register in_out2, Register in_out3,
+ Register tmp1, Register tmp2, Register tmp3,
+ XMMRegister w_xtmp1, XMMRegister w_xtmp2, XMMRegister w_xtmp3,
+ Register tmp4, Register tmp5,
+ Register n_tmp6) {
+ Label L_processPartitions;
+ Label L_processPartition;
+ Label L_exit;
+
+ bind(L_processPartitions);
+ cmpl(in_out1, 3 * size);
+ jcc(Assembler::less, L_exit);
+ xorl(tmp1, tmp1);
+ xorl(tmp2, tmp2);
+ movl(tmp3, in_out2);
+ addl(tmp3, size);
+
+ bind(L_processPartition);
+ crc32(in_out3, Address(in_out2, 0), 4);
+ crc32(tmp1, Address(in_out2, size), 4);
+ crc32(tmp2, Address(in_out2, size*2), 4);
+ crc32(in_out3, Address(in_out2, 0+4), 4);
+ crc32(tmp1, Address(in_out2, size+4), 4);
+ crc32(tmp2, Address(in_out2, size*2+4), 4);
+ addl(in_out2, 8);
+ cmpl(in_out2, tmp3);
+ jcc(Assembler::less, L_processPartition);
+
+ push(tmp3);
+ push(in_out1);
+ push(in_out2);
+ tmp4 = tmp3;
+ tmp5 = in_out1;
+ n_tmp6 = in_out2;
+
+ crc32c_rec_alt2(const_or_pre_comp_const_index_u1, const_or_pre_comp_const_index_u2, is_pclmulqdq_supported, in_out3, tmp1, tmp2,
+ w_xtmp1, w_xtmp2, w_xtmp3,
+ tmp4, tmp5,
+ n_tmp6);
+
+ pop(in_out2);
+ pop(in_out1);
+ pop(tmp3);
+
+ addl(in_out2, 2 * size);
+ subl(in_out1, 3 * size);
+ jmp(L_processPartitions);
+
+ bind(L_exit);
+}
+#endif //LP64
+
+#ifdef _LP64
+// Algorithm 2: Pipelined usage of the CRC32 instruction.
+// Input: A buffer I of L bytes.
+// Output: the CRC32C value of the buffer.
+// Notations:
+// Write L = 24N + r, with N = floor (L/24).
+// r = L mod 24 (0 <= r < 24).
+// Consider I as the concatenation of A|B|C|R, where A, B, C, each,
+// N quadwords, and R consists of r bytes.
+// A[j] = I [8j+7:8j], j= 0, 1, ..., N-1
+// B[j] = I [N + 8j+7:N + 8j], j= 0, 1, ..., N-1
+// C[j] = I [2N + 8j+7:2N + 8j], j= 0, 1, ..., N-1
+// if r > 0 R[j] = I [3N +j], j= 0, 1, ...,r-1
+void MacroAssembler::crc32c_ipl_alg2_alt2(Register in_out, Register in1, Register in2,
+ Register tmp1, Register tmp2, Register tmp3,
+ Register tmp4, Register tmp5, Register tmp6,
+ XMMRegister w_xtmp1, XMMRegister w_xtmp2, XMMRegister w_xtmp3,
+ bool is_pclmulqdq_supported) {
+ uint32_t const_or_pre_comp_const_index[CRC32C_NUM_PRECOMPUTED_CONSTANTS];
+ Label L_wordByWord;
+ Label L_byteByByteProlog;
+ Label L_byteByByte;
+ Label L_exit;
+
+ if (is_pclmulqdq_supported ) {
+ const_or_pre_comp_const_index[1] = *(uint32_t *)StubRoutines::_crc32c_table_addr;
+ const_or_pre_comp_const_index[0] = *((uint32_t *)StubRoutines::_crc32c_table_addr+1);
+
+ const_or_pre_comp_const_index[3] = *((uint32_t *)StubRoutines::_crc32c_table_addr + 2);
+ const_or_pre_comp_const_index[2] = *((uint32_t *)StubRoutines::_crc32c_table_addr + 3);
+
+ const_or_pre_comp_const_index[5] = *((uint32_t *)StubRoutines::_crc32c_table_addr + 4);
+ const_or_pre_comp_const_index[4] = *((uint32_t *)StubRoutines::_crc32c_table_addr + 5);
+ assert((CRC32C_NUM_PRECOMPUTED_CONSTANTS - 1 ) == 5, "Checking whether you declared all of the constants based on the number of \"chunks\"");
+ } else {
+ const_or_pre_comp_const_index[0] = 1;
+ const_or_pre_comp_const_index[1] = 0;
+
+ const_or_pre_comp_const_index[2] = 3;
+ const_or_pre_comp_const_index[3] = 2;
+
+ const_or_pre_comp_const_index[4] = 5;
+ const_or_pre_comp_const_index[5] = 4;
+ }
+ crc32c_proc_chunk(CRC32C_HIGH, const_or_pre_comp_const_index[0], const_or_pre_comp_const_index[1], is_pclmulqdq_supported,
+ in2, in1, in_out,
+ tmp1, tmp2, tmp3,
+ w_xtmp1, w_xtmp2, w_xtmp3,
+ tmp4, tmp5,
+ tmp6);
+ crc32c_proc_chunk(CRC32C_MIDDLE, const_or_pre_comp_const_index[2], const_or_pre_comp_const_index[3], is_pclmulqdq_supported,
+ in2, in1, in_out,
+ tmp1, tmp2, tmp3,
+ w_xtmp1, w_xtmp2, w_xtmp3,
+ tmp4, tmp5,
+ tmp6);
+ crc32c_proc_chunk(CRC32C_LOW, const_or_pre_comp_const_index[4], const_or_pre_comp_const_index[5], is_pclmulqdq_supported,
+ in2, in1, in_out,
+ tmp1, tmp2, tmp3,
+ w_xtmp1, w_xtmp2, w_xtmp3,
+ tmp4, tmp5,
+ tmp6);
+ movl(tmp1, in2);
+ andl(tmp1, 0x00000007);
+ negl(tmp1);
+ addl(tmp1, in2);
+ addq(tmp1, in1);
+
+ BIND(L_wordByWord);
+ cmpq(in1, tmp1);
+ jcc(Assembler::greaterEqual, L_byteByByteProlog);
+ crc32(in_out, Address(in1, 0), 4);
+ addq(in1, 4);
+ jmp(L_wordByWord);
+
+ BIND(L_byteByByteProlog);
+ andl(in2, 0x00000007);
+ movl(tmp2, 1);
+
+ BIND(L_byteByByte);
+ cmpl(tmp2, in2);
+ jccb(Assembler::greater, L_exit);
+ crc32(in_out, Address(in1, 0), 1);
+ incq(in1);
+ incl(tmp2);
+ jmp(L_byteByByte);
+
+ BIND(L_exit);
+}
+#else
+void MacroAssembler::crc32c_ipl_alg2_alt2(Register in_out, Register in1, Register in2,
+ Register tmp1, Register tmp2, Register tmp3,
+ Register tmp4, Register tmp5, Register tmp6,
+ XMMRegister w_xtmp1, XMMRegister w_xtmp2, XMMRegister w_xtmp3,
+ bool is_pclmulqdq_supported) {
+ uint32_t const_or_pre_comp_const_index[CRC32C_NUM_PRECOMPUTED_CONSTANTS];
+ Label L_wordByWord;
+ Label L_byteByByteProlog;
+ Label L_byteByByte;
+ Label L_exit;
+
+ if (is_pclmulqdq_supported) {
+ const_or_pre_comp_const_index[1] = *(uint32_t *)StubRoutines::_crc32c_table_addr;
+ const_or_pre_comp_const_index[0] = *((uint32_t *)StubRoutines::_crc32c_table_addr + 1);
+
+ const_or_pre_comp_const_index[3] = *((uint32_t *)StubRoutines::_crc32c_table_addr + 2);
+ const_or_pre_comp_const_index[2] = *((uint32_t *)StubRoutines::_crc32c_table_addr + 3);
+
+ const_or_pre_comp_const_index[5] = *((uint32_t *)StubRoutines::_crc32c_table_addr + 4);
+ const_or_pre_comp_const_index[4] = *((uint32_t *)StubRoutines::_crc32c_table_addr + 5);
+ } else {
+ const_or_pre_comp_const_index[0] = 1;
+ const_or_pre_comp_const_index[1] = 0;
+
+ const_or_pre_comp_const_index[2] = 3;
+ const_or_pre_comp_const_index[3] = 2;
+
+ const_or_pre_comp_const_index[4] = 5;
+ const_or_pre_comp_const_index[5] = 4;
+ }
+ crc32c_proc_chunk(CRC32C_HIGH, const_or_pre_comp_const_index[0], const_or_pre_comp_const_index[1], is_pclmulqdq_supported,
+ in2, in1, in_out,
+ tmp1, tmp2, tmp3,
+ w_xtmp1, w_xtmp2, w_xtmp3,
+ tmp4, tmp5,
+ tmp6);
+ crc32c_proc_chunk(CRC32C_MIDDLE, const_or_pre_comp_const_index[2], const_or_pre_comp_const_index[3], is_pclmulqdq_supported,
+ in2, in1, in_out,
+ tmp1, tmp2, tmp3,
+ w_xtmp1, w_xtmp2, w_xtmp3,
+ tmp4, tmp5,
+ tmp6);
+ crc32c_proc_chunk(CRC32C_LOW, const_or_pre_comp_const_index[4], const_or_pre_comp_const_index[5], is_pclmulqdq_supported,
+ in2, in1, in_out,
+ tmp1, tmp2, tmp3,
+ w_xtmp1, w_xtmp2, w_xtmp3,
+ tmp4, tmp5,
+ tmp6);
+ movl(tmp1, in2);
+ andl(tmp1, 0x00000007);
+ negl(tmp1);
+ addl(tmp1, in2);
+ addl(tmp1, in1);
+
+ BIND(L_wordByWord);
+ cmpl(in1, tmp1);
+ jcc(Assembler::greaterEqual, L_byteByByteProlog);
+ crc32(in_out, Address(in1,0), 4);
+ addl(in1, 4);
+ jmp(L_wordByWord);
+
+ BIND(L_byteByByteProlog);
+ andl(in2, 0x00000007);
+ movl(tmp2, 1);
+
+ BIND(L_byteByByte);
+ cmpl(tmp2, in2);
+ jccb(Assembler::greater, L_exit);
+ movb(tmp1, Address(in1, 0));
+ crc32(in_out, tmp1, 1);
+ incl(in1);
+ incl(tmp2);
+ jmp(L_byteByByte);
+
+ BIND(L_exit);
+}
+#endif // LP64
#undef BIND
#undef BLOCK_COMMENT
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
index 1a2fa3c163a..0b178ed8eeb 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
@@ -907,14 +907,14 @@ class MacroAssembler: public Assembler {
// all corner cases and may result in NaN and require fallback to a
// runtime call.
void fast_pow();
- void fast_exp();
+ void fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
+ XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
+ Register rax, Register rcx, Register rdx, Register tmp);
void increase_precision();
void restore_precision();
- // computes exp(x). Fallback to runtime call included.
- void exp_with_fallback(int num_fpu_regs_in_use) { pow_or_exp(true, num_fpu_regs_in_use); }
// computes pow(x,y). Fallback to runtime call included.
- void pow_with_fallback(int num_fpu_regs_in_use) { pow_or_exp(false, num_fpu_regs_in_use); }
+ void pow_with_fallback(int num_fpu_regs_in_use) { pow_or_exp(num_fpu_regs_in_use); }
private:
@@ -925,7 +925,7 @@ private:
void pow_exp_core_encoding();
// computes pow(x,y) or exp(x). Fallback to runtime call included.
- void pow_or_exp(bool is_exp, int num_fpu_regs_in_use);
+ void pow_or_exp(int num_fpu_regs_in_use);
// these are private because users should be doing movflt/movdbl
@@ -971,6 +971,10 @@ public:
void movsd(XMMRegister dst, Address src) { Assembler::movsd(dst, src); }
void movsd(XMMRegister dst, AddressLiteral src);
+ void mulpd(XMMRegister dst, XMMRegister src) { Assembler::mulpd(dst, src); }
+ void mulpd(XMMRegister dst, Address src) { Assembler::mulpd(dst, src); }
+ void mulpd(XMMRegister dst, AddressLiteral src);
+
void mulsd(XMMRegister dst, XMMRegister src) { Assembler::mulsd(dst, src); }
void mulsd(XMMRegister dst, Address src) { Assembler::mulsd(dst, src); }
void mulsd(XMMRegister dst, AddressLiteral src);
@@ -1278,9 +1282,42 @@ public:
Register raxReg);
#endif
- // CRC32 code for java.util.zip.CRC32::updateBytes() instrinsic.
+ // CRC32 code for java.util.zip.CRC32::updateBytes() intrinsic.
void update_byte_crc32(Register crc, Register val, Register table);
void kernel_crc32(Register crc, Register buf, Register len, Register table, Register tmp);
+ // CRC32C code for java.util.zip.CRC32C::updateBytes() intrinsic
+ // Note on a naming convention:
+ // Prefix w = register only used on a Westmere+ architecture
+ // Prefix n = register only used on a Nehalem architecture
+#ifdef _LP64
+ void crc32c_ipl_alg4(Register in_out, uint32_t n,
+ Register tmp1, Register tmp2, Register tmp3);
+#else
+ void crc32c_ipl_alg4(Register in_out, uint32_t n,
+ Register tmp1, Register tmp2, Register tmp3,
+ XMMRegister xtmp1, XMMRegister xtmp2);
+#endif
+ void crc32c_pclmulqdq(XMMRegister w_xtmp1,
+ Register in_out,
+ uint32_t const_or_pre_comp_const_index, bool is_pclmulqdq_supported,
+ XMMRegister w_xtmp2,
+ Register tmp1,
+ Register n_tmp2, Register n_tmp3);
+ void crc32c_rec_alt2(uint32_t const_or_pre_comp_const_index_u1, uint32_t const_or_pre_comp_const_index_u2, bool is_pclmulqdq_supported, Register in_out, Register in1, Register in2,
+ XMMRegister w_xtmp1, XMMRegister w_xtmp2, XMMRegister w_xtmp3,
+ Register tmp1, Register tmp2,
+ Register n_tmp3);
+ void crc32c_proc_chunk(uint32_t size, uint32_t const_or_pre_comp_const_index_u1, uint32_t const_or_pre_comp_const_index_u2, bool is_pclmulqdq_supported,
+ Register in_out1, Register in_out2, Register in_out3,
+ Register tmp1, Register tmp2, Register tmp3,
+ XMMRegister w_xtmp1, XMMRegister w_xtmp2, XMMRegister w_xtmp3,
+ Register tmp4, Register tmp5,
+ Register n_tmp6);
+ void crc32c_ipl_alg2_alt2(Register in_out, Register in1, Register in2,
+ Register tmp1, Register tmp2, Register tmp3,
+ Register tmp4, Register tmp5, Register tmp6,
+ XMMRegister w_xtmp1, XMMRegister w_xtmp2, XMMRegister w_xtmp3,
+ bool is_pclmulqdq_supported);
// Fold 128-bit data chunk
void fold_128bit_crc32(XMMRegister xcrc, XMMRegister xK, XMMRegister xtmp, Register buf, int offset);
void fold_128bit_crc32(XMMRegister xcrc, XMMRegister xK, XMMRegister xtmp, XMMRegister xbuf);
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86_libm.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86_libm.cpp
new file mode 100644
index 00000000000..b5b66b7f10a
--- /dev/null
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86_libm.cpp
@@ -0,0 +1,677 @@
+/*
+ * Copyright (c) 2015, Intel Corporation.
+ * Intel Math Library (LIBM) Source Code
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/******************************************************************************/
+// ALGORITHM DESCRIPTION
+// ---------------------
+//
+// Description:
+// Let K = 64 (table size).
+// x x/log(2) n
+// e = 2 = 2 * T[j] * (1 + P(y))
+// where
+// x = m*log(2)/K + y, y in [-log(2)/K..log(2)/K]
+// m = n*K + j, m,n,j - signed integer, j in [-K/2..K/2]
+// j/K
+// values of 2 are tabulated as T[j] = T_hi[j] ( 1 + T_lo[j]).
+//
+// P(y) is a minimax polynomial approximation of exp(x)-1
+// on small interval [-log(2)/K..log(2)/K] (were calculated by Maple V).
+//
+// To avoid problems with arithmetic overflow and underflow,
+// n n1 n2
+// value of 2 is safely computed as 2 * 2 where n1 in [-BIAS/2..BIAS/2]
+// where BIAS is a value of exponent bias.
+//
+// Special cases:
+// exp(NaN) = NaN
+// exp(+INF) = +INF
+// exp(-INF) = 0
+// exp(x) = 1 for subnormals
+// for finite argument, only exp(0)=1 is exact
+// For IEEE double
+// if x > 709.782712893383973096 then exp(x) overflow
+// if x < -745.133219101941108420 then exp(x) underflow
+//
+/******************************************************************************/
+
+
+#include "precompiled.hpp"
+#include "asm/assembler.hpp"
+#include "asm/assembler.inline.hpp"
+#include "macroAssembler_x86.hpp"
+
+#ifdef _MSC_VER
+#define ALIGNED_(x) __declspec(align(x))
+#else
+#define ALIGNED_(x) __attribute__ ((aligned(x)))
+#endif
+
+#ifdef _LP64
+
+ALIGNED_(16) juint _cv[] =
+{
+ 0x652b82feUL, 0x40571547UL, 0x652b82feUL, 0x40571547UL, 0xfefa0000UL,
+ 0x3f862e42UL, 0xfefa0000UL, 0x3f862e42UL, 0xbc9e3b3aUL, 0x3d1cf79aUL,
+ 0xbc9e3b3aUL, 0x3d1cf79aUL, 0xfffffffeUL, 0x3fdfffffUL, 0xfffffffeUL,
+ 0x3fdfffffUL, 0xe3289860UL, 0x3f56c15cUL, 0x555b9e25UL, 0x3fa55555UL,
+ 0xc090cf0fUL, 0x3f811115UL, 0x55548ba1UL, 0x3fc55555UL
+};
+
+ALIGNED_(16) juint _shifter[] =
+{
+ 0x00000000UL, 0x43380000UL, 0x00000000UL, 0x43380000UL
+};
+
+ALIGNED_(16) juint _mmask[] =
+{
+ 0xffffffc0UL, 0x00000000UL, 0xffffffc0UL, 0x00000000UL
+};
+
+ALIGNED_(16) juint _bias[] =
+{
+ 0x0000ffc0UL, 0x00000000UL, 0x0000ffc0UL, 0x00000000UL
+};
+
+ALIGNED_(16) juint _Tbl_addr[] =
+{
+ 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x0e03754dUL,
+ 0x3cad7bbfUL, 0x3e778060UL, 0x00002c9aUL, 0x3567f613UL, 0x3c8cd252UL,
+ 0xd3158574UL, 0x000059b0UL, 0x61e6c861UL, 0x3c60f74eUL, 0x18759bc8UL,
+ 0x00008745UL, 0x5d837b6cUL, 0x3c979aa6UL, 0x6cf9890fUL, 0x0000b558UL,
+ 0x702f9cd1UL, 0x3c3ebe3dUL, 0x32d3d1a2UL, 0x0000e3ecUL, 0x1e63bcd8UL,
+ 0x3ca3516eUL, 0xd0125b50UL, 0x00011301UL, 0x26f0387bUL, 0x3ca4c554UL,
+ 0xaea92ddfUL, 0x0001429aUL, 0x62523fb6UL, 0x3ca95153UL, 0x3c7d517aUL,
+ 0x000172b8UL, 0x3f1353bfUL, 0x3c8b898cUL, 0xeb6fcb75UL, 0x0001a35bUL,
+ 0x3e3a2f5fUL, 0x3c9aecf7UL, 0x3168b9aaUL, 0x0001d487UL, 0x44a6c38dUL,
+ 0x3c8a6f41UL, 0x88628cd6UL, 0x0002063bUL, 0xe3a8a894UL, 0x3c968efdUL,
+ 0x6e756238UL, 0x0002387aUL, 0x981fe7f2UL, 0x3c80472bUL, 0x65e27cddUL,
+ 0x00026b45UL, 0x6d09ab31UL, 0x3c82f7e1UL, 0xf51fdee1UL, 0x00029e9dUL,
+ 0x720c0ab3UL, 0x3c8b3782UL, 0xa6e4030bUL, 0x0002d285UL, 0x4db0abb6UL,
+ 0x3c834d75UL, 0x0a31b715UL, 0x000306feUL, 0x5dd3f84aUL, 0x3c8fdd39UL,
+ 0xb26416ffUL, 0x00033c08UL, 0xcc187d29UL, 0x3ca12f8cUL, 0x373aa9caUL,
+ 0x000371a7UL, 0x738b5e8bUL, 0x3ca7d229UL, 0x34e59ff6UL, 0x0003a7dbUL,
+ 0xa72a4c6dUL, 0x3c859f48UL, 0x4c123422UL, 0x0003dea6UL, 0x259d9205UL,
+ 0x3ca8b846UL, 0x21f72e29UL, 0x0004160aUL, 0x60c2ac12UL, 0x3c4363edUL,
+ 0x6061892dUL, 0x00044e08UL, 0xdaa10379UL, 0x3c6ecce1UL, 0xb5c13cd0UL,
+ 0x000486a2UL, 0xbb7aafb0UL, 0x3c7690ceUL, 0xd5362a27UL, 0x0004bfdaUL,
+ 0x9b282a09UL, 0x3ca083ccUL, 0x769d2ca6UL, 0x0004f9b2UL, 0xc1aae707UL,
+ 0x3ca509b0UL, 0x569d4f81UL, 0x0005342bUL, 0x18fdd78eUL, 0x3c933505UL,
+ 0x36b527daUL, 0x00056f47UL, 0xe21c5409UL, 0x3c9063e1UL, 0xdd485429UL,
+ 0x0005ab07UL, 0x2b64c035UL, 0x3c9432e6UL, 0x15ad2148UL, 0x0005e76fUL,
+ 0x99f08c0aUL, 0x3ca01284UL, 0xb03a5584UL, 0x0006247eUL, 0x0073dc06UL,
+ 0x3c99f087UL, 0x82552224UL, 0x00066238UL, 0x0da05571UL, 0x3c998d4dUL,
+ 0x667f3bccUL, 0x0006a09eUL, 0x86ce4786UL, 0x3ca52bb9UL, 0x3c651a2eUL,
+ 0x0006dfb2UL, 0x206f0dabUL, 0x3ca32092UL, 0xe8ec5f73UL, 0x00071f75UL,
+ 0x8e17a7a6UL, 0x3ca06122UL, 0x564267c8UL, 0x00075febUL, 0x461e9f86UL,
+ 0x3ca244acUL, 0x73eb0186UL, 0x0007a114UL, 0xabd66c55UL, 0x3c65ebe1UL,
+ 0x36cf4e62UL, 0x0007e2f3UL, 0xbbff67d0UL, 0x3c96fe9fUL, 0x994cce12UL,
+ 0x00082589UL, 0x14c801dfUL, 0x3c951f14UL, 0x9b4492ecUL, 0x000868d9UL,
+ 0xc1f0eab4UL, 0x3c8db72fUL, 0x422aa0dbUL, 0x0008ace5UL, 0x59f35f44UL,
+ 0x3c7bf683UL, 0x99157736UL, 0x0008f1aeUL, 0x9c06283cUL, 0x3ca360baUL,
+ 0xb0cdc5e4UL, 0x00093737UL, 0x20f962aaUL, 0x3c95e8d1UL, 0x9fde4e4fUL,
+ 0x00097d82UL, 0x2b91ce27UL, 0x3c71affcUL, 0x82a3f090UL, 0x0009c491UL,
+ 0x589a2ebdUL, 0x3c9b6d34UL, 0x7b5de564UL, 0x000a0c66UL, 0x9ab89880UL,
+ 0x3c95277cUL, 0xb23e255cUL, 0x000a5503UL, 0x6e735ab3UL, 0x3c846984UL,
+ 0x5579fdbfUL, 0x000a9e6bUL, 0x92cb3387UL, 0x3c8c1a77UL, 0x995ad3adUL,
+ 0x000ae89fUL, 0xdc2d1d96UL, 0x3ca22466UL, 0xb84f15faUL, 0x000b33a2UL,
+ 0xb19505aeUL, 0x3ca1112eUL, 0xf2fb5e46UL, 0x000b7f76UL, 0x0a5fddcdUL,
+ 0x3c74ffd7UL, 0x904bc1d2UL, 0x000bcc1eUL, 0x30af0cb3UL, 0x3c736eaeUL,
+ 0xdd85529cUL, 0x000c199bUL, 0xd10959acUL, 0x3c84e08fUL, 0x2e57d14bUL,
+ 0x000c67f1UL, 0x6c921968UL, 0x3c676b2cUL, 0xdcef9069UL, 0x000cb720UL,
+ 0x36df99b3UL, 0x3c937009UL, 0x4a07897bUL, 0x000d072dUL, 0xa63d07a7UL,
+ 0x3c74a385UL, 0xdcfba487UL, 0x000d5818UL, 0xd5c192acUL, 0x3c8e5a50UL,
+ 0x03db3285UL, 0x000da9e6UL, 0x1c4a9792UL, 0x3c98bb73UL, 0x337b9b5eUL,
+ 0x000dfc97UL, 0x603a88d3UL, 0x3c74b604UL, 0xe78b3ff6UL, 0x000e502eUL,
+ 0x92094926UL, 0x3c916f27UL, 0xa2a490d9UL, 0x000ea4afUL, 0x41aa2008UL,
+ 0x3c8ec3bcUL, 0xee615a27UL, 0x000efa1bUL, 0x31d185eeUL, 0x3c8a64a9UL,
+ 0x5b6e4540UL, 0x000f5076UL, 0x4d91cd9dUL, 0x3c77893bUL, 0x819e90d8UL,
+ 0x000fa7c1UL
+};
+
+ALIGNED_(16) juint _ALLONES[] =
+{
+ 0xffffffffUL, 0xffffffffUL, 0xffffffffUL, 0xffffffffUL
+};
+
+ALIGNED_(16) juint _ebias[] =
+{
+ 0x00000000UL, 0x3ff00000UL, 0x00000000UL, 0x3ff00000UL
+};
+
+ALIGNED_(4) juint _XMAX[] =
+{
+ 0xffffffffUL, 0x7fefffffUL
+};
+
+ALIGNED_(4) juint _XMIN[] =
+{
+ 0x00000000UL, 0x00100000UL
+};
+
+ALIGNED_(4) juint _INF[] =
+{
+ 0x00000000UL, 0x7ff00000UL
+};
+
+ALIGNED_(4) juint _ZERO[] =
+{
+ 0x00000000UL, 0x00000000UL
+};
+
+ALIGNED_(4) juint _ONE_val[] =
+{
+ 0x00000000UL, 0x3ff00000UL
+};
+
+
+// Registers:
+// input: xmm0
+// scratch: xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
+// rax, rdx, rcx, tmp - r11
+
+// Code generated by Intel C compiler for LIBM library
+
+void MacroAssembler::fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register eax, Register ecx, Register edx, Register tmp) {
+ Label L_2TAG_PACKET_0_0_2, L_2TAG_PACKET_1_0_2, L_2TAG_PACKET_2_0_2, L_2TAG_PACKET_3_0_2;
+ Label L_2TAG_PACKET_4_0_2, L_2TAG_PACKET_5_0_2, L_2TAG_PACKET_6_0_2, L_2TAG_PACKET_7_0_2;
+ Label L_2TAG_PACKET_8_0_2, L_2TAG_PACKET_9_0_2, L_2TAG_PACKET_10_0_2, L_2TAG_PACKET_11_0_2;
+ Label L_2TAG_PACKET_12_0_2, B1_3, B1_5, start;
+
+ assert_different_registers(tmp, eax, ecx, edx);
+ jmp(start);
+ address cv = (address)_cv;
+ address Shifter = (address)_shifter;
+ address mmask = (address)_mmask;
+ address bias = (address)_bias;
+ address Tbl_addr = (address)_Tbl_addr;
+ address ALLONES = (address)_ALLONES;
+ address ebias = (address)_ebias;
+ address XMAX = (address)_XMAX;
+ address XMIN = (address)_XMIN;
+ address INF = (address)_INF;
+ address ZERO = (address)_ZERO;
+ address ONE_val = (address)_ONE_val;
+
+ bind(start);
+ subq(rsp, 24);
+ movsd(Address(rsp, 8), xmm0);
+ unpcklpd(xmm0, xmm0);
+ movdqu(xmm1, ExternalAddress(cv)); // 0x652b82feUL, 0x40571547UL, 0x652b82feUL, 0x40571547UL
+ movdqu(xmm6, ExternalAddress(Shifter)); // 0x00000000UL, 0x43380000UL, 0x00000000UL, 0x43380000UL
+ movdqu(xmm2, ExternalAddress(16+cv)); // 0xfefa0000UL, 0x3f862e42UL, 0xfefa0000UL, 0x3f862e42UL
+ movdqu(xmm3, ExternalAddress(32+cv)); // 0xbc9e3b3aUL, 0x3d1cf79aUL, 0xbc9e3b3aUL, 0x3d1cf79aUL
+ pextrw(eax, xmm0, 3);
+ andl(eax, 32767);
+ movl(edx, 16527);
+ subl(edx, eax);
+ subl(eax, 15504);
+ orl(edx, eax);
+ cmpl(edx, INT_MIN);
+ jcc(Assembler::aboveEqual, L_2TAG_PACKET_0_0_2);
+ mulpd(xmm1, xmm0);
+ addpd(xmm1, xmm6);
+ movapd(xmm7, xmm1);
+ subpd(xmm1, xmm6);
+ mulpd(xmm2, xmm1);
+ movdqu(xmm4, ExternalAddress(64+cv)); // 0xe3289860UL, 0x3f56c15cUL, 0x555b9e25UL, 0x3fa55555UL
+ mulpd(xmm3, xmm1);
+ movdqu(xmm5, ExternalAddress(80+cv)); // 0xc090cf0fUL, 0x3f811115UL, 0x55548ba1UL, 0x3fc55555UL
+ subpd(xmm0, xmm2);
+ movdl(eax, xmm7);
+ movl(ecx, eax);
+ andl(ecx, 63);
+ shll(ecx, 4);
+ sarl(eax, 6);
+ movl(edx, eax);
+ movdqu(xmm6, ExternalAddress(mmask)); // 0xffffffc0UL, 0x00000000UL, 0xffffffc0UL, 0x00000000UL
+ pand(xmm7, xmm6);
+ movdqu(xmm6, ExternalAddress(bias)); // 0x0000ffc0UL, 0x00000000UL, 0x0000ffc0UL, 0x00000000UL
+ paddq(xmm7, xmm6);
+ psllq(xmm7, 46);
+ subpd(xmm0, xmm3);
+ lea(tmp, ExternalAddress(Tbl_addr));
+ movdqu(xmm2, Address(ecx,tmp));
+ mulpd(xmm4, xmm0);
+ movapd(xmm6, xmm0);
+ movapd(xmm1, xmm0);
+ mulpd(xmm6, xmm6);
+ mulpd(xmm0, xmm6);
+ addpd(xmm5, xmm4);
+ mulsd(xmm0, xmm6);
+ mulpd(xmm6, ExternalAddress(48+cv)); // 0xfffffffeUL, 0x3fdfffffUL, 0xfffffffeUL, 0x3fdfffffUL
+ addsd(xmm1, xmm2);
+ unpckhpd(xmm2, xmm2);
+ mulpd(xmm0, xmm5);
+ addsd(xmm1, xmm0);
+ por(xmm2, xmm7);
+ unpckhpd(xmm0, xmm0);
+ addsd(xmm0, xmm1);
+ addsd(xmm0, xmm6);
+ addl(edx, 894);
+ cmpl(edx, 1916);
+ jcc (Assembler::above, L_2TAG_PACKET_1_0_2);
+ mulsd(xmm0, xmm2);
+ addsd(xmm0, xmm2);
+ jmp (B1_5);
+
+ bind(L_2TAG_PACKET_1_0_2);
+ xorpd(xmm3, xmm3);
+ movdqu(xmm4, ExternalAddress(ALLONES)); // 0xffffffffUL, 0xffffffffUL, 0xffffffffUL, 0xffffffffUL
+ movl(edx, -1022);
+ subl(edx, eax);
+ movdl(xmm5, edx);
+ psllq(xmm4, xmm5);
+ movl(ecx, eax);
+ sarl(eax, 1);
+ pinsrw(xmm3, eax, 3);
+ movdqu(xmm6, ExternalAddress(ebias)); // 0x00000000UL, 0x3ff00000UL, 0x00000000UL, 0x3ff00000UL
+ psllq(xmm3, 4);
+ psubd(xmm2, xmm3);
+ mulsd(xmm0, xmm2);
+ cmpl(edx, 52);
+ jcc(Assembler::greater, L_2TAG_PACKET_2_0_2);
+ pand(xmm4, xmm2);
+ paddd(xmm3, xmm6);
+ subsd(xmm2, xmm4);
+ addsd(xmm0, xmm2);
+ cmpl(ecx, 1023);
+ jcc(Assembler::greaterEqual, L_2TAG_PACKET_3_0_2);
+ pextrw(ecx, xmm0, 3);
+ andl(ecx, 32768);
+ orl(edx, ecx);
+ cmpl(edx, 0);
+ jcc(Assembler::equal, L_2TAG_PACKET_4_0_2);
+ movapd(xmm6, xmm0);
+ addsd(xmm0, xmm4);
+ mulsd(xmm0, xmm3);
+ pextrw(ecx, xmm0, 3);
+ andl(ecx, 32752);
+ cmpl(ecx, 0);
+ jcc(Assembler::equal, L_2TAG_PACKET_5_0_2);
+ jmp(B1_5);
+
+ bind(L_2TAG_PACKET_5_0_2);
+ mulsd(xmm6, xmm3);
+ mulsd(xmm4, xmm3);
+ movdqu(xmm0, xmm6);
+ pxor(xmm6, xmm4);
+ psrad(xmm6, 31);
+ pshufd(xmm6, xmm6, 85);
+ psllq(xmm0, 1);
+ psrlq(xmm0, 1);
+ pxor(xmm0, xmm6);
+ psrlq(xmm6, 63);
+ paddq(xmm0, xmm6);
+ paddq(xmm0, xmm4);
+ movl(Address(rsp,0), 15);
+ jmp(L_2TAG_PACKET_6_0_2);
+
+ bind(L_2TAG_PACKET_4_0_2);
+ addsd(xmm0, xmm4);
+ mulsd(xmm0, xmm3);
+ jmp(B1_5);
+
+ bind(L_2TAG_PACKET_3_0_2);
+ addsd(xmm0, xmm4);
+ mulsd(xmm0, xmm3);
+ pextrw(ecx, xmm0, 3);
+ andl(ecx, 32752);
+ cmpl(ecx, 32752);
+ jcc(Assembler::aboveEqual, L_2TAG_PACKET_7_0_2);
+ jmp(B1_5);
+
+ bind(L_2TAG_PACKET_2_0_2);
+ paddd(xmm3, xmm6);
+ addpd(xmm0, xmm2);
+ mulsd(xmm0, xmm3);
+ movl(Address(rsp,0), 15);
+ jmp(L_2TAG_PACKET_6_0_2);
+
+ bind(L_2TAG_PACKET_8_0_2);
+ cmpl(eax, 2146435072);
+ jcc(Assembler::aboveEqual, L_2TAG_PACKET_9_0_2);
+ movl(eax, Address(rsp,12));
+ cmpl(eax, INT_MIN);
+ jcc(Assembler::aboveEqual, L_2TAG_PACKET_10_0_2);
+ movsd(xmm0, ExternalAddress(XMAX)); // 0xffffffffUL, 0x7fefffffUL
+ mulsd(xmm0, xmm0);
+
+ bind(L_2TAG_PACKET_7_0_2);
+ movl(Address(rsp,0), 14);
+ jmp(L_2TAG_PACKET_6_0_2);
+
+ bind(L_2TAG_PACKET_10_0_2);
+ movsd(xmm0, ExternalAddress(XMIN)); // 0x00000000UL, 0x00100000UL
+ mulsd(xmm0, xmm0);
+ movl(Address(rsp,0), 15);
+ jmp(L_2TAG_PACKET_6_0_2);
+
+ bind(L_2TAG_PACKET_9_0_2);
+ movl(edx, Address(rsp,8));
+ cmpl(eax, 2146435072);
+ jcc(Assembler::above, L_2TAG_PACKET_11_0_2);
+ cmpl(edx, 0);
+ jcc(Assembler::notEqual, L_2TAG_PACKET_11_0_2);
+ movl(eax, Address(rsp,12));
+ cmpl(eax, 2146435072);
+ jcc(Assembler::notEqual, L_2TAG_PACKET_12_0_2);
+ movsd(xmm0, ExternalAddress(INF)); // 0x00000000UL, 0x7ff00000UL
+ jmp(B1_5);
+
+ bind(L_2TAG_PACKET_12_0_2);
+ movsd(xmm0, ExternalAddress(ZERO)); // 0x00000000UL, 0x00000000UL
+ jmp(B1_5);
+
+ bind(L_2TAG_PACKET_11_0_2);
+ movsd(xmm0, Address(rsp, 8));
+ addsd(xmm0, xmm0);
+ jmp(B1_5);
+
+ bind(L_2TAG_PACKET_0_0_2);
+ movl(eax, Address(rsp, 12));
+ andl(eax, 2147483647);
+ cmpl(eax, 1083179008);
+ jcc(Assembler::aboveEqual, L_2TAG_PACKET_8_0_2);
+ movsd(Address(rsp, 8), xmm0);
+ addsd(xmm0, ExternalAddress(ONE_val)); // 0x00000000UL, 0x3ff00000UL
+ jmp(B1_5);
+
+ bind(L_2TAG_PACKET_6_0_2);
+ movq(Address(rsp, 16), xmm0);
+
+ bind(B1_3);
+ movq(xmm0, Address(rsp, 16));
+
+ bind(B1_5);
+ addq(rsp, 24);
+}
+#endif
+
+#ifndef _LP64
+
+ALIGNED_(16) juint _static_const_table[] =
+{
+ 0x00000000UL, 0xfff00000UL, 0x00000000UL, 0xfff00000UL, 0xffffffc0UL,
+ 0x00000000UL, 0xffffffc0UL, 0x00000000UL, 0x0000ffc0UL, 0x00000000UL,
+ 0x0000ffc0UL, 0x00000000UL, 0x00000000UL, 0x43380000UL, 0x00000000UL,
+ 0x43380000UL, 0x652b82feUL, 0x40571547UL, 0x652b82feUL, 0x40571547UL,
+ 0xfefa0000UL, 0x3f862e42UL, 0xfefa0000UL, 0x3f862e42UL, 0xbc9e3b3aUL,
+ 0x3d1cf79aUL, 0xbc9e3b3aUL, 0x3d1cf79aUL, 0xfffffffeUL, 0x3fdfffffUL,
+ 0xfffffffeUL, 0x3fdfffffUL, 0xe3289860UL, 0x3f56c15cUL, 0x555b9e25UL,
+ 0x3fa55555UL, 0xc090cf0fUL, 0x3f811115UL, 0x55548ba1UL, 0x3fc55555UL,
+ 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x00000000UL, 0x0e03754dUL,
+ 0x3cad7bbfUL, 0x3e778060UL, 0x00002c9aUL, 0x3567f613UL, 0x3c8cd252UL,
+ 0xd3158574UL, 0x000059b0UL, 0x61e6c861UL, 0x3c60f74eUL, 0x18759bc8UL,
+ 0x00008745UL, 0x5d837b6cUL, 0x3c979aa6UL, 0x6cf9890fUL, 0x0000b558UL,
+ 0x702f9cd1UL, 0x3c3ebe3dUL, 0x32d3d1a2UL, 0x0000e3ecUL, 0x1e63bcd8UL,
+ 0x3ca3516eUL, 0xd0125b50UL, 0x00011301UL, 0x26f0387bUL, 0x3ca4c554UL,
+ 0xaea92ddfUL, 0x0001429aUL, 0x62523fb6UL, 0x3ca95153UL, 0x3c7d517aUL,
+ 0x000172b8UL, 0x3f1353bfUL, 0x3c8b898cUL, 0xeb6fcb75UL, 0x0001a35bUL,
+ 0x3e3a2f5fUL, 0x3c9aecf7UL, 0x3168b9aaUL, 0x0001d487UL, 0x44a6c38dUL,
+ 0x3c8a6f41UL, 0x88628cd6UL, 0x0002063bUL, 0xe3a8a894UL, 0x3c968efdUL,
+ 0x6e756238UL, 0x0002387aUL, 0x981fe7f2UL, 0x3c80472bUL, 0x65e27cddUL,
+ 0x00026b45UL, 0x6d09ab31UL, 0x3c82f7e1UL, 0xf51fdee1UL, 0x00029e9dUL,
+ 0x720c0ab3UL, 0x3c8b3782UL, 0xa6e4030bUL, 0x0002d285UL, 0x4db0abb6UL,
+ 0x3c834d75UL, 0x0a31b715UL, 0x000306feUL, 0x5dd3f84aUL, 0x3c8fdd39UL,
+ 0xb26416ffUL, 0x00033c08UL, 0xcc187d29UL, 0x3ca12f8cUL, 0x373aa9caUL,
+ 0x000371a7UL, 0x738b5e8bUL, 0x3ca7d229UL, 0x34e59ff6UL, 0x0003a7dbUL,
+ 0xa72a4c6dUL, 0x3c859f48UL, 0x4c123422UL, 0x0003dea6UL, 0x259d9205UL,
+ 0x3ca8b846UL, 0x21f72e29UL, 0x0004160aUL, 0x60c2ac12UL, 0x3c4363edUL,
+ 0x6061892dUL, 0x00044e08UL, 0xdaa10379UL, 0x3c6ecce1UL, 0xb5c13cd0UL,
+ 0x000486a2UL, 0xbb7aafb0UL, 0x3c7690ceUL, 0xd5362a27UL, 0x0004bfdaUL,
+ 0x9b282a09UL, 0x3ca083ccUL, 0x769d2ca6UL, 0x0004f9b2UL, 0xc1aae707UL,
+ 0x3ca509b0UL, 0x569d4f81UL, 0x0005342bUL, 0x18fdd78eUL, 0x3c933505UL,
+ 0x36b527daUL, 0x00056f47UL, 0xe21c5409UL, 0x3c9063e1UL, 0xdd485429UL,
+ 0x0005ab07UL, 0x2b64c035UL, 0x3c9432e6UL, 0x15ad2148UL, 0x0005e76fUL,
+ 0x99f08c0aUL, 0x3ca01284UL, 0xb03a5584UL, 0x0006247eUL, 0x0073dc06UL,
+ 0x3c99f087UL, 0x82552224UL, 0x00066238UL, 0x0da05571UL, 0x3c998d4dUL,
+ 0x667f3bccUL, 0x0006a09eUL, 0x86ce4786UL, 0x3ca52bb9UL, 0x3c651a2eUL,
+ 0x0006dfb2UL, 0x206f0dabUL, 0x3ca32092UL, 0xe8ec5f73UL, 0x00071f75UL,
+ 0x8e17a7a6UL, 0x3ca06122UL, 0x564267c8UL, 0x00075febUL, 0x461e9f86UL,
+ 0x3ca244acUL, 0x73eb0186UL, 0x0007a114UL, 0xabd66c55UL, 0x3c65ebe1UL,
+ 0x36cf4e62UL, 0x0007e2f3UL, 0xbbff67d0UL, 0x3c96fe9fUL, 0x994cce12UL,
+ 0x00082589UL, 0x14c801dfUL, 0x3c951f14UL, 0x9b4492ecUL, 0x000868d9UL,
+ 0xc1f0eab4UL, 0x3c8db72fUL, 0x422aa0dbUL, 0x0008ace5UL, 0x59f35f44UL,
+ 0x3c7bf683UL, 0x99157736UL, 0x0008f1aeUL, 0x9c06283cUL, 0x3ca360baUL,
+ 0xb0cdc5e4UL, 0x00093737UL, 0x20f962aaUL, 0x3c95e8d1UL, 0x9fde4e4fUL,
+ 0x00097d82UL, 0x2b91ce27UL, 0x3c71affcUL, 0x82a3f090UL, 0x0009c491UL,
+ 0x589a2ebdUL, 0x3c9b6d34UL, 0x7b5de564UL, 0x000a0c66UL, 0x9ab89880UL,
+ 0x3c95277cUL, 0xb23e255cUL, 0x000a5503UL, 0x6e735ab3UL, 0x3c846984UL,
+ 0x5579fdbfUL, 0x000a9e6bUL, 0x92cb3387UL, 0x3c8c1a77UL, 0x995ad3adUL,
+ 0x000ae89fUL, 0xdc2d1d96UL, 0x3ca22466UL, 0xb84f15faUL, 0x000b33a2UL,
+ 0xb19505aeUL, 0x3ca1112eUL, 0xf2fb5e46UL, 0x000b7f76UL, 0x0a5fddcdUL,
+ 0x3c74ffd7UL, 0x904bc1d2UL, 0x000bcc1eUL, 0x30af0cb3UL, 0x3c736eaeUL,
+ 0xdd85529cUL, 0x000c199bUL, 0xd10959acUL, 0x3c84e08fUL, 0x2e57d14bUL,
+ 0x000c67f1UL, 0x6c921968UL, 0x3c676b2cUL, 0xdcef9069UL, 0x000cb720UL,
+ 0x36df99b3UL, 0x3c937009UL, 0x4a07897bUL, 0x000d072dUL, 0xa63d07a7UL,
+ 0x3c74a385UL, 0xdcfba487UL, 0x000d5818UL, 0xd5c192acUL, 0x3c8e5a50UL,
+ 0x03db3285UL, 0x000da9e6UL, 0x1c4a9792UL, 0x3c98bb73UL, 0x337b9b5eUL,
+ 0x000dfc97UL, 0x603a88d3UL, 0x3c74b604UL, 0xe78b3ff6UL, 0x000e502eUL,
+ 0x92094926UL, 0x3c916f27UL, 0xa2a490d9UL, 0x000ea4afUL, 0x41aa2008UL,
+ 0x3c8ec3bcUL, 0xee615a27UL, 0x000efa1bUL, 0x31d185eeUL, 0x3c8a64a9UL,
+ 0x5b6e4540UL, 0x000f5076UL, 0x4d91cd9dUL, 0x3c77893bUL, 0x819e90d8UL,
+ 0x000fa7c1UL, 0x00000000UL, 0x3ff00000UL, 0x00000000UL, 0x7ff00000UL,
+ 0x00000000UL, 0x00000000UL, 0xffffffffUL, 0x7fefffffUL, 0x00000000UL,
+ 0x00100000UL
+};
+
+//registers,
+// input: (rbp + 8)
+// scratch: xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
+// rax, rdx, rcx, rbx (tmp)
+
+// Code generated by Intel C compiler for LIBM library
+
+void MacroAssembler::fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register eax, Register ecx, Register edx, Register tmp) {
+ Label L_2TAG_PACKET_0_0_2, L_2TAG_PACKET_1_0_2, L_2TAG_PACKET_2_0_2, L_2TAG_PACKET_3_0_2;
+ Label L_2TAG_PACKET_4_0_2, L_2TAG_PACKET_5_0_2, L_2TAG_PACKET_6_0_2, L_2TAG_PACKET_7_0_2;
+ Label L_2TAG_PACKET_8_0_2, L_2TAG_PACKET_9_0_2, L_2TAG_PACKET_10_0_2, L_2TAG_PACKET_11_0_2;
+ Label L_2TAG_PACKET_12_0_2, L_2TAG_PACKET_13_0_2, B1_3, B1_5, start;
+
+ assert_different_registers(tmp, eax, ecx, edx);
+ jmp(start);
+ address static_const_table = (address)_static_const_table;
+
+ bind(start);
+ subl(rsp, 120);
+ movl(Address(rsp, 64), tmp);
+ lea(tmp, ExternalAddress(static_const_table));
+ movdqu(xmm0, Address(rsp, 128));
+ unpcklpd(xmm0, xmm0);
+ movdqu(xmm1, Address(tmp, 64)); // 0x652b82feUL, 0x40571547UL, 0x652b82feUL, 0x40571547UL
+ movdqu(xmm6, Address(tmp, 48)); // 0x00000000UL, 0x43380000UL, 0x00000000UL, 0x43380000UL
+ movdqu(xmm2, Address(tmp, 80)); // 0xfefa0000UL, 0x3f862e42UL, 0xfefa0000UL, 0x3f862e42UL
+ movdqu(xmm3, Address(tmp, 96)); // 0xbc9e3b3aUL, 0x3d1cf79aUL, 0xbc9e3b3aUL, 0x3d1cf79aUL
+ pextrw(eax, xmm0, 3);
+ andl(eax, 32767);
+ movl(edx, 16527);
+ subl(edx, eax);
+ subl(eax, 15504);
+ orl(edx, eax);
+ cmpl(edx, INT_MIN);
+ jcc(Assembler::aboveEqual, L_2TAG_PACKET_0_0_2);
+ mulpd(xmm1, xmm0);
+ addpd(xmm1, xmm6);
+ movapd(xmm7, xmm1);
+ subpd(xmm1, xmm6);
+ mulpd(xmm2, xmm1);
+ movdqu(xmm4, Address(tmp, 128)); // 0xe3289860UL, 0x3f56c15cUL, 0x555b9e25UL, 0x3fa55555UL
+ mulpd(xmm3, xmm1);
+ movdqu(xmm5, Address(tmp, 144)); // 0xc090cf0fUL, 0x3f811115UL, 0x55548ba1UL, 0x3fc55555UL
+ subpd(xmm0, xmm2);
+ movdl(eax, xmm7);
+ movl(ecx, eax);
+ andl(ecx, 63);
+ shll(ecx, 4);
+ sarl(eax, 6);
+ movl(edx, eax);
+ movdqu(xmm6, Address(tmp, 16)); // 0xffffffc0UL, 0x00000000UL, 0xffffffc0UL, 0x00000000UL
+ pand(xmm7, xmm6);
+ movdqu(xmm6, Address(tmp, 32)); // 0x0000ffc0UL, 0x00000000UL, 0x0000ffc0UL, 0x00000000UL
+ paddq(xmm7, xmm6);
+ psllq(xmm7, 46);
+ subpd(xmm0, xmm3);
+ movdqu(xmm2, Address(tmp, ecx, Address::times_1, 160));
+ mulpd(xmm4, xmm0);
+ movapd(xmm6, xmm0);
+ movapd(xmm1, xmm0);
+ mulpd(xmm6, xmm6);
+ mulpd(xmm0, xmm6);
+ addpd(xmm5, xmm4);
+ mulsd(xmm0, xmm6);
+ mulpd(xmm6, Address(tmp, 112)); // 0xfffffffeUL, 0x3fdfffffUL, 0xfffffffeUL, 0x3fdfffffUL
+ addsd(xmm1, xmm2);
+ unpckhpd(xmm2, xmm2);
+ mulpd(xmm0, xmm5);
+ addsd(xmm1, xmm0);
+ por(xmm2, xmm7);
+ unpckhpd(xmm0, xmm0);
+ addsd(xmm0, xmm1);
+ addsd(xmm0, xmm6);
+ addl(edx, 894);
+ cmpl(edx, 1916);
+ jcc (Assembler::above, L_2TAG_PACKET_1_0_2);
+ mulsd(xmm0, xmm2);
+ addsd(xmm0, xmm2);
+ jmp(L_2TAG_PACKET_2_0_2);
+
+ bind(L_2TAG_PACKET_1_0_2);
+ fnstcw(Address(rsp, 24));
+ movzwl(edx, Address(rsp, 24));
+ orl(edx, 768);
+ movw(Address(rsp, 28), edx);
+ fldcw(Address(rsp, 28));
+ movl(edx, eax);
+ sarl(eax, 1);
+ subl(edx, eax);
+ movdqu(xmm6, Address(tmp, 0)); // 0x00000000UL, 0xfff00000UL, 0x00000000UL, 0xfff00000UL
+ pandn(xmm6, xmm2);
+ addl(eax, 1023);
+ movdl(xmm3, eax);
+ psllq(xmm3, 52);
+ por(xmm6, xmm3);
+ addl(edx, 1023);
+ movdl(xmm4, edx);
+ psllq(xmm4, 52);
+ movsd(Address(rsp, 8), xmm0);
+ fld_d(Address(rsp, 8));
+ movsd(Address(rsp, 16), xmm6);
+ fld_d(Address(rsp, 16));
+ fmula(1);
+ faddp(1);
+ movsd(Address(rsp, 8), xmm4);
+ fld_d(Address(rsp, 8));
+ fmulp(1);
+ fstp_d(Address(rsp, 8));
+ movsd(xmm0,Address(rsp, 8));
+ fldcw(Address(rsp, 24));
+ pextrw(ecx, xmm0, 3);
+ andl(ecx, 32752);
+ cmpl(ecx, 32752);
+ jcc(Assembler::greaterEqual, L_2TAG_PACKET_3_0_2);
+ cmpl(ecx, 0);
+ jcc(Assembler::equal, L_2TAG_PACKET_4_0_2);
+ jmp(L_2TAG_PACKET_2_0_2);
+ cmpl(ecx, INT_MIN);
+ jcc(Assembler::less, L_2TAG_PACKET_3_0_2);
+ cmpl(ecx, -1064950997);
+ jcc(Assembler::less, L_2TAG_PACKET_2_0_2);
+ jcc(Assembler::greater, L_2TAG_PACKET_4_0_2);
+ movl(edx, Address(rsp, 128));
+ cmpl(edx ,-17155601);
+ jcc(Assembler::less, L_2TAG_PACKET_2_0_2);
+ jmp(L_2TAG_PACKET_4_0_2);
+
+ bind(L_2TAG_PACKET_3_0_2);
+ movl(edx, 14);
+ jmp(L_2TAG_PACKET_5_0_2);
+
+ bind(L_2TAG_PACKET_4_0_2);
+ movl(edx, 15);
+
+ bind(L_2TAG_PACKET_5_0_2);
+ movsd(Address(rsp, 0), xmm0);
+ movsd(xmm0, Address(rsp, 128));
+ fld_d(Address(rsp, 0));
+ jmp(L_2TAG_PACKET_6_0_2);
+
+ bind(L_2TAG_PACKET_7_0_2);
+ cmpl(eax, 2146435072);
+ jcc(Assembler::greaterEqual, L_2TAG_PACKET_8_0_2);
+ movl(eax, Address(rsp, 132));
+ cmpl(eax, INT_MIN);
+ jcc(Assembler::greaterEqual, L_2TAG_PACKET_9_0_2);
+ movsd(xmm0, Address(tmp, 1208)); // 0xffffffffUL, 0x7fefffffUL
+ mulsd(xmm0, xmm0);
+ movl(edx, 14);
+ jmp(L_2TAG_PACKET_5_0_2);
+
+ bind(L_2TAG_PACKET_9_0_2);
+ movsd(xmm0, Address(tmp, 1216));
+ mulsd(xmm0, xmm0);
+ movl(edx, 15);
+ jmp(L_2TAG_PACKET_5_0_2);
+
+ bind(L_2TAG_PACKET_8_0_2);
+ movl(edx, Address(rsp, 128));
+ cmpl(eax, 2146435072);
+ jcc(Assembler::above, L_2TAG_PACKET_10_0_2);
+ cmpl(edx, 0);
+ jcc(Assembler::notEqual, L_2TAG_PACKET_10_0_2);
+ movl(eax, Address(rsp, 132));
+ cmpl(eax, 2146435072);
+ jcc(Assembler::notEqual, L_2TAG_PACKET_11_0_2);
+ movsd(xmm0, Address(tmp, 1192)); // 0x00000000UL, 0x7ff00000UL
+ jmp(L_2TAG_PACKET_2_0_2);
+
+ bind(L_2TAG_PACKET_11_0_2);
+ movsd(xmm0, Address(tmp, 1200)); // 0x00000000UL, 0x00000000UL
+ jmp(L_2TAG_PACKET_2_0_2);
+
+ bind(L_2TAG_PACKET_10_0_2);
+ movsd(xmm0, Address(rsp, 128));
+ addsd(xmm0, xmm0);
+ jmp(L_2TAG_PACKET_2_0_2);
+
+ bind(L_2TAG_PACKET_0_0_2);
+ movl(eax, Address(rsp, 132));
+ andl(eax, 2147483647);
+ cmpl(eax, 1083179008);
+ jcc(Assembler::aboveEqual, L_2TAG_PACKET_7_0_2);
+ movsd(xmm0, Address(rsp, 128));
+ addsd(xmm0, Address(tmp, 1184)); // 0x00000000UL, 0x3ff00000UL
+ jmp(L_2TAG_PACKET_2_0_2);
+
+ bind(L_2TAG_PACKET_2_0_2);
+ movsd(Address(rsp, 48), xmm0);
+ fld_d(Address(rsp, 48));
+
+ bind(L_2TAG_PACKET_6_0_2);
+ movl(tmp, Address(rsp, 64));
+}
+
+#endif
diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp
index 1a476e80c75..be97c30acf1 100644
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp
@@ -30,8 +30,6 @@
#include "memory/allocation.inline.hpp"
#include "prims/methodHandles.hpp"
-PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-
#define __ _masm->
#ifdef PRODUCT
@@ -53,7 +51,7 @@ void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_
#ifdef ASSERT
static int check_nonzero(const char* xname, int x) {
- assert(x != 0, err_msg("%s should be nonzero", xname));
+ assert(x != 0, "%s should be nonzero", xname);
return x;
}
#define NONZERO(x) check_nonzero(#x, x)
@@ -456,7 +454,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
}
default:
- fatal(err_msg_res("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid)));
+ fatal("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid));
break;
}
@@ -488,7 +486,7 @@ void trace_method_handle_stub(const char* adaptername,
const char* mh_reg_name = has_mh ? "rcx_mh" : "rcx";
tty->print_cr("MH %s %s=" PTR_FORMAT " sp=" PTR_FORMAT,
adaptername, mh_reg_name,
- (void *)mh, entry_sp);
+ p2i(mh), p2i(entry_sp));
if (Verbose) {
tty->print_cr("Registers:");
diff --git a/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp b/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp
index c38455f1fca..26c6f3392ad 100644
--- a/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp
@@ -35,18 +35,15 @@
#include "c1/c1_Runtime1.hpp"
#endif
-PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-
void NativeInstruction::wrote(int offset) {
ICache::invalidate_word(addr_at(offset));
}
-
void NativeCall::verify() {
// Make sure code pattern is actually a call imm32 instruction.
int inst = ubyte_at(0);
if (inst != instruction_code) {
- tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", instruction_address(),
+ tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", p2i(instruction_address()),
inst);
fatal("not a call disp32");
}
@@ -63,7 +60,7 @@ address NativeCall::destination() const {
void NativeCall::print() {
tty->print_cr(PTR_FORMAT ": call " PTR_FORMAT,
- instruction_address(), destination());
+ p2i(instruction_address()), p2i(destination()));
}
// Inserts a native call instruction at a given pc
@@ -230,7 +227,7 @@ void NativeMovConstReg::verify() {
void NativeMovConstReg::print() {
tty->print_cr(PTR_FORMAT ": mov reg, " INTPTR_FORMAT,
- instruction_address(), data());
+ p2i(instruction_address()), data());
}
//-------------------------------------------------------------------
@@ -396,7 +393,7 @@ void NativeMovRegMem::verify() {
void NativeMovRegMem::print() {
- tty->print_cr("0x%x: mov reg, [reg + %x]", instruction_address(), offset());
+ tty->print_cr(PTR_FORMAT ": mov reg, [reg + %x]", p2i(instruction_address()), offset());
}
//-------------------------------------------------------------------
@@ -418,7 +415,7 @@ void NativeLoadAddress::verify() {
void NativeLoadAddress::print() {
- tty->print_cr("0x%x: lea [reg + %x], reg", instruction_address(), offset());
+ tty->print_cr(PTR_FORMAT ": lea [reg + %x], reg", p2i(instruction_address()), offset());
}
//--------------------------------------------------------------------------------
@@ -474,6 +471,7 @@ void NativeJump::check_verified_entry_alignment(address entry, address verified_
//
// In C2 the 5+ byte sized instruction is enforced by code in MachPrologNode::emit.
// In C1 the restriction is enforced by CodeEmitter::method_entry
+// In JVMCI, the restriction is enforced by HotSpotFrameContext.enter(...)
//
void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
// complete jump instruction (to be inserted) is in code_buffer;
diff --git a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp
index 529512731cf..6c527d49991 100644
--- a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp
@@ -60,6 +60,7 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC {
bool is_nop() { return ubyte_at(0) == nop_instruction_code; }
inline bool is_call();
+ inline bool is_call_reg();
inline bool is_illegal();
inline bool is_return();
inline bool is_jump();
@@ -180,6 +181,24 @@ inline NativeCall* nativeCall_before(address return_address) {
return call;
}
+class NativeCallReg: public NativeInstruction {
+ public:
+ enum Intel_specific_constants {
+ instruction_code = 0xFF,
+ instruction_offset = 0,
+ return_address_offset_norex = 2,
+ return_address_offset_rex = 3
+ };
+
+ int next_instruction_offset() const {
+ if (ubyte_at(0) == NativeCallReg::instruction_code) {
+ return return_address_offset_norex;
+ } else {
+ return return_address_offset_rex;
+ }
+ }
+};
+
// An interface for accessing/manipulating native mov reg, imm32 instructions.
// (used to manipulate inlined 32bit data dll calls, etc.)
class NativeMovConstReg: public NativeInstruction {
@@ -519,6 +538,9 @@ class NativeTstRegMem: public NativeInstruction {
inline bool NativeInstruction::is_illegal() { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; }
inline bool NativeInstruction::is_call() { return ubyte_at(0) == NativeCall::instruction_code; }
+inline bool NativeInstruction::is_call_reg() { return ubyte_at(0) == NativeCallReg::instruction_code ||
+ (ubyte_at(1) == NativeCallReg::instruction_code &&
+ (ubyte_at(0) == Assembler::REX || ubyte_at(0) == Assembler::REX_B)); }
inline bool NativeInstruction::is_return() { return ubyte_at(0) == NativeReturn::instruction_code ||
ubyte_at(0) == NativeReturnX::instruction_code; }
inline bool NativeInstruction::is_jump() { return ubyte_at(0) == NativeJump::instruction_code ||
@@ -527,26 +549,24 @@ inline bool NativeInstruction::is_cond_jump() { return (int_at(0) & 0xF0FF) =
(ubyte_at(0) & 0xF0) == 0x70; /* short jump */ }
inline bool NativeInstruction::is_safepoint_poll() {
#ifdef AMD64
- if (Assembler::is_polling_page_far()) {
- // two cases, depending on the choice of the base register in the address.
- if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
- ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl &&
- (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) ||
- ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
- (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) {
- return true;
- } else {
- return false;
- }
- } else {
- if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
- ubyte_at(1) == 0x05) { // 00 rax 101
- address fault = addr_at(6) + int_at(2);
- return os::is_poll_address(fault);
- } else {
- return false;
- }
+ // Try decoding a near safepoint first:
+ if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
+ ubyte_at(1) == 0x05) { // 00 rax 101
+ address fault = addr_at(6) + int_at(2);
+ NOT_JVMCI(assert(!Assembler::is_polling_page_far(), "unexpected poll encoding");)
+ return os::is_poll_address(fault);
}
+ // Now try decoding a far safepoint:
+ // two cases, depending on the choice of the base register in the address.
+ if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix &&
+ ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl &&
+ (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) ||
+ ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
+ (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) {
+ NOT_JVMCI(assert(Assembler::is_polling_page_far(), "unexpected poll encoding");)
+ return true;
+ }
+ return false;
#else
return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl ) &&
diff --git a/hotspot/src/cpu/x86/vm/registerMap_x86.cpp b/hotspot/src/cpu/x86/vm/registerMap_x86.cpp
new file mode 100644
index 00000000000..32e71c7e263
--- /dev/null
+++ b/hotspot/src/cpu/x86/vm/registerMap_x86.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/registerMap.hpp"
+#include "vmreg_x86.inline.hpp"
+
+address RegisterMap::pd_location(VMReg reg) const {
+ if (reg->is_XMMRegister()) {
+ int regBase = reg->value() - ConcreteRegisterImpl::max_fpr;
+ if (regBase % 4 == 0) {
+ // Reads of the low and high 16 byte parts should be handled by location itself
+ // because they have separate callee saved entries.
+ // See RegisterSaver::save_live_registers().
+ return NULL;
+ }
+ VMReg baseReg = as_XMMRegister(regBase / XMMRegisterImpl::max_slots_per_register)->as_VMReg();
+ intptr_t offset = (reg->value() - baseReg->value()) * VMRegImpl::stack_slot_size; // offset in bytes
+ if (offset >= 16) {
+ // The high part of YMM registers are saved in a their own area in the frame
+ baseReg = baseReg->next()->next()->next()->next();
+ offset -= 16;
+ }
+ address baseLocation = location(baseReg);
+ if (baseLocation != NULL) {
+ return baseLocation + offset;
+ }
+ }
+ return NULL;
+}
diff --git a/hotspot/src/cpu/x86/vm/registerMap_x86.hpp b/hotspot/src/cpu/x86/vm/registerMap_x86.hpp
index 5d91b1ba755..0cbf0646831 100644
--- a/hotspot/src/cpu/x86/vm/registerMap_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/registerMap_x86.hpp
@@ -31,11 +31,7 @@
private:
// This is the hook for finding a register in an "well-known" location,
// such as a register block of a predetermined format.
- // Since there is none, we just return NULL.
- // See registerMap_sparc.hpp for an example of grabbing registers
- // from register save areas of a standard layout.
- address pd_location(VMReg reg) const {return NULL;}
-
+ address pd_location(VMReg reg) const;
// no PD state to clear or copy:
void pd_clear() {}
void pd_initialize() {}
diff --git a/hotspot/src/cpu/x86/vm/register_x86.cpp b/hotspot/src/cpu/x86/vm/register_x86.cpp
index 00cba4c9461..2a07a9eb19c 100644
--- a/hotspot/src/cpu/x86/vm/register_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/register_x86.cpp
@@ -69,6 +69,31 @@ const char* XMMRegisterImpl::name() const {
return is_valid() ? names[encoding()] : "xnoreg";
}
+const char* XMMRegisterImpl::sub_word_name(int i) const {
+ const char* names[number_of_registers * 8] = {
+ "xmm0:0", "xmm0:1", "xmm0:2", "xmm0:3", "xmm0:4", "xmm0:5", "xmm0:6", "xmm0:7",
+ "xmm1:0", "xmm1:1", "xmm1:2", "xmm1:3", "xmm1:4", "xmm1:5", "xmm1:6", "xmm1:7",
+ "xmm2:0", "xmm2:1", "xmm2:2", "xmm2:3", "xmm2:4", "xmm2:5", "xmm2:6", "xmm2:7",
+ "xmm3:0", "xmm3:1", "xmm3:2", "xmm3:3", "xmm3:4", "xmm3:5", "xmm3:6", "xmm3:7",
+ "xmm4:0", "xmm4:1", "xmm4:2", "xmm4:3", "xmm4:4", "xmm4:5", "xmm4:6", "xmm4:7",
+ "xmm5:0", "xmm5:1", "xmm5:2", "xmm5:3", "xmm5:4", "xmm5:5", "xmm5:6", "xmm5:7",
+ "xmm6:0", "xmm6:1", "xmm6:2", "xmm6:3", "xmm6:4", "xmm6:5", "xmm6:6", "xmm6:7",
+ "xmm7:0", "xmm7:1", "xmm7:2", "xmm7:3", "xmm7:4", "xmm7:5", "xmm7:6", "xmm7:7",
+#ifdef AMD64
+ "xmm8:0", "xmm8:1", "xmm8:2", "xmm8:3", "xmm8:4", "xmm8:5", "xmm8:6", "xmm8:7",
+ "xmm9:0", "xmm9:1", "xmm9:2", "xmm9:3", "xmm9:4", "xmm9:5", "xmm9:6", "xmm9:7",
+ "xmm10:0", "xmm10:1", "xmm10:2", "xmm10:3", "xmm10:4", "xmm10:5", "xmm10:6", "xmm10:7",
+ "xmm11:0", "xmm11:1", "xmm11:2", "xmm11:3", "xmm11:4", "xmm11:5", "xmm11:6", "xmm11:7",
+ "xmm12:0", "xmm12:1", "xmm12:2", "xmm12:3", "xmm12:4", "xmm12:5", "xmm12:6", "xmm12:7",
+ "xmm13:0", "xmm13:1", "xmm13:2", "xmm13:3", "xmm13:4", "xmm13:5", "xmm13:6", "xmm13:7",
+ "xmm14:0", "xmm14:1", "xmm14:2", "xmm14:3", "xmm14:4", "xmm14:5", "xmm14:6", "xmm14:7",
+ "xmm15:0", "xmm15:1", "xmm15:2", "xmm15:3", "xmm15:4", "xmm15:5", "xmm15:6", "xmm15:7",
+#endif // AMD64
+ };
+ assert(i >= 0 && i < 8, "offset too large");
+ return is_valid() ? names[encoding() * 8 + i] : "xnoreg";
+}
+
const char* KRegisterImpl::name() const {
const char* names[number_of_registers] = {
"k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"
diff --git a/hotspot/src/cpu/x86/vm/register_x86.hpp b/hotspot/src/cpu/x86/vm/register_x86.hpp
index ccce3850261..1d1c6eef627 100644
--- a/hotspot/src/cpu/x86/vm/register_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/register_x86.hpp
@@ -162,9 +162,10 @@ class XMMRegisterImpl: public AbstractRegisterImpl {
XMMRegister successor() const { return as_XMMRegister(encoding() + 1); }
// accessors
- int encoding() const { assert(is_valid(), err_msg("invalid register (%d)", (int)(intptr_t)this )); return (intptr_t)this; }
+ int encoding() const { assert(is_valid(), "invalid register (%d)", (int)(intptr_t)this ); return (intptr_t)this; }
bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; }
const char* name() const;
+ const char* sub_word_name(int offset) const;
};
@@ -245,7 +246,7 @@ public:
KRegister successor() const { return as_KRegister(encoding() + 1); }
// accessors
- int encoding() const { assert(is_valid(), err_msg("invalid register (%d)", (int)(intptr_t)this)); return (intptr_t)this; }
+ int encoding() const { assert(is_valid(), "invalid register (%d)", (int)(intptr_t)this); return (intptr_t)this; }
bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; }
const char* name() const;
};
diff --git a/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp b/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp
index 32b2d073cce..4c558b7c3cd 100644
--- a/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/relocInfo_x86.cpp
@@ -180,39 +180,17 @@ address Relocation::pd_get_address_from_code() {
void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
#ifdef _LP64
- if (!Assembler::is_polling_page_far()) {
- typedef Assembler::WhichOperand WhichOperand;
- WhichOperand which = (WhichOperand) format();
- // This format is imm but it is really disp32
- which = Assembler::disp32_operand;
+ typedef Assembler::WhichOperand WhichOperand;
+ WhichOperand which = (WhichOperand) format();
+#if !INCLUDE_JVMCI
+ assert((which == Assembler::disp32_operand) == !Assembler::is_polling_page_far(), "format not set correctly");
+#endif
+ if (which == Assembler::disp32_operand) {
address orig_addr = old_addr_for(addr(), src, dest);
NativeInstruction* oni = nativeInstruction_at(orig_addr);
int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
// This poll_addr is incorrect by the size of the instruction it is irrelevant
intptr_t poll_addr = (intptr_t)oni + *orig_disp;
-
- NativeInstruction* ni = nativeInstruction_at(addr());
- intptr_t new_disp = poll_addr - (intptr_t) ni;
-
- int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which);
- * disp = (int32_t)new_disp;
- }
-#endif // _LP64
-}
-
-void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) {
-#ifdef _LP64
- if (!Assembler::is_polling_page_far()) {
- typedef Assembler::WhichOperand WhichOperand;
- WhichOperand which = (WhichOperand) format();
- // This format is imm but it is really disp32
- which = Assembler::disp32_operand;
- address orig_addr = old_addr_for(addr(), src, dest);
- NativeInstruction* oni = nativeInstruction_at(orig_addr);
- int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which);
- // This poll_addr is incorrect by the size of the instruction it is irrelevant
- intptr_t poll_addr = (intptr_t)oni + *orig_disp;
-
NativeInstruction* ni = nativeInstruction_at(addr());
intptr_t new_disp = poll_addr - (intptr_t) ni;
diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp
index 80f2873c04f..e2047549877 100644
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp
@@ -699,12 +699,11 @@ static void range_check(MacroAssembler* masm, Register pc_reg, Register temp_reg
__ bind(L_fail);
}
-static void gen_i2c_adapter(MacroAssembler *masm,
- int total_args_passed,
- int comp_args_on_stack,
- const BasicType *sig_bt,
- const VMRegPair *regs) {
-
+void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
+ int total_args_passed,
+ int comp_args_on_stack,
+ const BasicType *sig_bt,
+ const VMRegPair *regs) {
// Note: rsi contains the senderSP on entry. We must preserve it since
// we may do a i2c -> c2i transition if we lose a race where compiled
// code goes non-entrant while we get args ready.
@@ -1434,7 +1433,7 @@ static void gen_special_dispatch(MacroAssembler* masm,
} else if (iid == vmIntrinsics::_invokeBasic) {
has_receiver = true;
} else {
- fatal(err_msg_res("unexpected intrinsic id %d", iid));
+ fatal("unexpected intrinsic id %d", iid);
}
if (member_reg != noreg) {
diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
index 46874844473..0b17c56095c 100644
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
@@ -43,6 +43,9 @@
#ifdef COMPILER2
#include "opto/runtime.hpp"
#endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciJavaClasses.hpp"
+#endif
#define __ masm->
@@ -158,23 +161,25 @@ class RegisterSaver {
OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) {
int vect_words = 0;
+ int ymmhi_offset = -1;
int off = 0;
int num_xmm_regs = XMMRegisterImpl::number_of_registers;
if (UseAVX < 3) {
num_xmm_regs = num_xmm_regs/2;
}
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
if (save_vectors) {
assert(UseAVX > 0, "512bit vectors are supported only with EVEX");
assert(MaxVectorSize == 64, "only 512bit vectors are supported now");
// Save upper half of YMM registers
vect_words = 16 * num_xmm_regs / wordSize;
if (UseAVX < 3) {
+ ymmhi_offset = additional_frame_words;
additional_frame_words += vect_words;
}
}
#else
- assert(!save_vectors, "vectors are generated only by C2");
+ assert(!save_vectors, "vectors are generated only by C2 and JVMCI");
#endif
// Always make the frame size 16-byte aligned
@@ -220,6 +225,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
OopMap* map = new OopMap(frame_size_in_slots, 0);
#define STACK_OFFSET(x) VMRegImpl::stack2reg((x) + additional_frame_slots)
+#define YMMHI_STACK_OFFSET(x) VMRegImpl::stack2reg((x / VMRegImpl::stack_slot_size) + ymmhi_offset)
map->set_callee_saved(STACK_OFFSET( rax_off ), rax->as_VMReg());
map->set_callee_saved(STACK_OFFSET( rcx_off ), rcx->as_VMReg());
@@ -257,6 +263,28 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
}
}
+#if defined(COMPILER2) || INCLUDE_JVMCI
+ if (save_vectors) {
+ assert(ymmhi_offset != -1, "save area must exist");
+ map->set_callee_saved(YMMHI_STACK_OFFSET( 0), xmm0->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET( 16), xmm1->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET( 32), xmm2->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET( 48), xmm3->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET( 64), xmm4->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET( 80), xmm5->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET( 96), xmm6->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(112), xmm7->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(128), xmm8->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(144), xmm9->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(160), xmm10->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(176), xmm11->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(192), xmm12->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(208), xmm13->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(224), xmm14->as_VMReg()->next(4));
+ map->set_callee_saved(YMMHI_STACK_OFFSET(240), xmm15->as_VMReg()->next(4));
+ }
+#endif // COMPILER2 || INCLUDE_JVMCI
+
// %%% These should all be a waste but we'll keep things as they were for now
if (true) {
map->set_callee_saved(STACK_OFFSET( raxH_off ), rax->as_VMReg()->next());
@@ -307,7 +335,7 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve
// Pop arg register save area
__ addptr(rsp, frame::arg_reg_save_area_bytes);
}
-#ifdef COMPILER2
+#if defined(COMPILER2) || INCLUDE_JVMCI
// On EVEX enabled targets everything is handled in pop fpu state
if ((restore_vectors) && (UseAVX < 3)) {
assert(UseAVX > 0, "256/512-bit vectors are supported only with AVX");
@@ -320,7 +348,7 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve
__ addptr(rsp, num_xmm_regs*16);
}
#else
- assert(!restore_vectors, "vectors are generated only by C2");
+ assert(!restore_vectors, "vectors are generated only by C2 and JVMCI");
#endif
// Recover CPU state
__ pop_CPU_state();
@@ -655,11 +683,11 @@ static void range_check(MacroAssembler* masm, Register pc_reg, Register temp_reg
__ bind(L_fail);
}
-static void gen_i2c_adapter(MacroAssembler *masm,
- int total_args_passed,
- int comp_args_on_stack,
- const BasicType *sig_bt,
- const VMRegPair *regs) {
+void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm,
+ int total_args_passed,
+ int comp_args_on_stack,
+ const BasicType *sig_bt,
+ const VMRegPair *regs) {
// Note: r13 contains the senderSP on entry. We must preserve it since
// we may do a i2c -> c2i transition if we lose a race where compiled
@@ -752,6 +780,18 @@ static void gen_i2c_adapter(MacroAssembler *masm,
// Pre-load the register-jump target early, to schedule it better.
__ movptr(r11, Address(rbx, in_bytes(Method::from_compiled_offset())));
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ // check if this call should be routed towards a specific entry point
+ __ cmpptr(Address(r15_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())), 0);
+ Label no_alternative_target;
+ __ jcc(Assembler::equal, no_alternative_target);
+ __ movptr(r11, Address(r15_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())));
+ __ movptr(Address(r15_thread, in_bytes(JavaThread::jvmci_alternate_call_target_offset())), 0);
+ __ bind(no_alternative_target);
+ }
+#endif // INCLUDE_JVMCI
+
// Now generate the shuffle code. Pick up all register args and move the
// rest through the floating point stack top.
for (int i = 0; i < total_args_passed; i++) {
@@ -1695,7 +1735,7 @@ static void gen_special_dispatch(MacroAssembler* masm,
} else if (iid == vmIntrinsics::_invokeBasic) {
has_receiver = true;
} else {
- fatal(err_msg_res("unexpected intrinsic id %d", iid));
+ fatal("unexpected intrinsic id %d", iid);
}
if (member_reg != noreg) {
@@ -2685,7 +2725,13 @@ void SharedRuntime::generate_deopt_blob() {
// Allocate space for the code
ResourceMark rm;
// Setup code generation tools
- CodeBuffer buffer("deopt_blob", 2048, 1024);
+ int pad = 0;
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ pad += 512; // Increase the buffer size when compiling for JVMCI
+ }
+#endif
+ CodeBuffer buffer("deopt_blob", 2048+pad, 1024);
MacroAssembler* masm = new MacroAssembler(&buffer);
int frame_size_in_words;
OopMap* map = NULL;
@@ -2734,6 +2780,12 @@ void SharedRuntime::generate_deopt_blob() {
__ jmp(cont);
int reexecute_offset = __ pc() - start;
+#if INCLUDE_JVMCI && !defined(COMPILER1)
+ if (EnableJVMCI && UseJVMCICompiler) {
+ // JVMCI does not use this kind of deoptimization
+ __ should_not_reach_here();
+ }
+#endif
// Reexecute case
// return address is the pc describes what bci to do re-execute at
@@ -2744,6 +2796,38 @@ void SharedRuntime::generate_deopt_blob() {
__ movl(r14, Deoptimization::Unpack_reexecute); // callee-saved
__ jmp(cont);
+#if INCLUDE_JVMCI
+ Label after_fetch_unroll_info_call;
+ int implicit_exception_uncommon_trap_offset = 0;
+ int uncommon_trap_offset = 0;
+
+ if (EnableJVMCI) {
+ implicit_exception_uncommon_trap_offset = __ pc() - start;
+
+ __ pushptr(Address(r15_thread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())));
+ __ movptr(Address(r15_thread, in_bytes(JavaThread::jvmci_implicit_exception_pc_offset())), (int32_t)NULL_WORD);
+
+ uncommon_trap_offset = __ pc() - start;
+
+ // Save everything in sight.
+ RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words);
+ // fetch_unroll_info needs to call last_java_frame()
+ __ set_last_Java_frame(noreg, noreg, NULL);
+
+ __ movl(c_rarg1, Address(r15_thread, in_bytes(JavaThread::pending_deoptimization_offset())));
+ __ movl(Address(r15_thread, in_bytes(JavaThread::pending_deoptimization_offset())), -1);
+
+ __ movl(r14, (int32_t)Deoptimization::Unpack_reexecute);
+ __ mov(c_rarg0, r15_thread);
+ __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
+ oop_maps->add_gc_map( __ pc()-start, map->deep_copy());
+
+ __ reset_last_Java_frame(false, false);
+
+ __ jmp(after_fetch_unroll_info_call);
+ } // EnableJVMCI
+#endif // INCLUDE_JVMCI
+
int exception_offset = __ pc() - start;
// Prolog for exception case
@@ -2829,6 +2913,12 @@ void SharedRuntime::generate_deopt_blob() {
__ reset_last_Java_frame(false, false);
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ __ bind(after_fetch_unroll_info_call);
+ }
+#endif
+
// Load UnrollBlock* into rdi
__ mov(rdi, rax);
@@ -3003,6 +3093,12 @@ void SharedRuntime::generate_deopt_blob() {
_deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_in_words);
_deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset);
+#if INCLUDE_JVMCI
+ if (EnableJVMCI) {
+ _deopt_blob->set_uncommon_trap_offset(uncommon_trap_offset);
+ _deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
+ }
+#endif
}
#ifdef COMPILER2
diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp
index 35c8d0940b6..ba7cb9950bf 100644
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp
@@ -2134,14 +2134,6 @@ class StubGenerator: public StubCodeGenerator {
__ trigfunc('t');
__ ret(0);
}
- {
- StubCodeMark mark(this, "StubRoutines", "exp");
- StubRoutines::_intrinsic_exp = (double (*)(double)) __ pc();
-
- __ fld_d(Address(rsp, 4));
- __ exp_with_fallback(0);
- __ ret(0);
- }
{
StubCodeMark mark(this, "StubRoutines", "pow");
StubRoutines::_intrinsic_pow = (double (*)(double,double)) __ pc();
@@ -2991,6 +2983,89 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
+ /**
+ * Arguments:
+ *
+ * Inputs:
+ * rsp(4) - int crc
+ * rsp(8) - byte* buf
+ * rsp(12) - int length
+ * rsp(16) - table_start - optional (present only when doing a library_calll,
+ * not used by x86 algorithm)
+ *
+ * Ouput:
+ * rax - int crc result
+ */
+ address generate_updateBytesCRC32C(bool is_pclmulqdq_supported) {
+ assert(UseCRC32CIntrinsics, "need SSE4_2");
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "updateBytesCRC32C");
+ address start = __ pc();
+ const Register crc = rax; // crc
+ const Register buf = rcx; // source java byte array address
+ const Register len = rdx; // length
+ const Register d = rbx;
+ const Register g = rsi;
+ const Register h = rdi;
+ const Register empty = 0; // will never be used, in order not
+ // to change a signature for crc32c_IPL_Alg2_Alt2
+ // between 64/32 I'm just keeping it here
+ assert_different_registers(crc, buf, len, d, g, h);
+
+ BLOCK_COMMENT("Entry:");
+ __ enter(); // required for proper stackwalking of RuntimeStub frame
+ Address crc_arg(rsp, 4 + 4 + 0); // ESP+4 +
+ // we need to add additional 4 because __ enter
+ // have just pushed ebp on a stack
+ Address buf_arg(rsp, 4 + 4 + 4);
+ Address len_arg(rsp, 4 + 4 + 8);
+ // Load up:
+ __ movl(crc, crc_arg);
+ __ movl(buf, buf_arg);
+ __ movl(len, len_arg);
+ __ push(d);
+ __ push(g);
+ __ push(h);
+ __ crc32c_ipl_alg2_alt2(crc, buf, len,
+ d, g, h,
+ empty, empty, empty,
+ xmm0, xmm1, xmm2,
+ is_pclmulqdq_supported);
+ __ pop(h);
+ __ pop(g);
+ __ pop(d);
+ __ leave(); // required for proper stackwalking of RuntimeStub frame
+ __ ret(0);
+
+ return start;
+ }
+
+ address generate_libmExp() {
+ address start = __ pc();
+
+ const XMMRegister x0 = xmm0;
+ const XMMRegister x1 = xmm1;
+ const XMMRegister x2 = xmm2;
+ const XMMRegister x3 = xmm3;
+
+ const XMMRegister x4 = xmm4;
+ const XMMRegister x5 = xmm5;
+ const XMMRegister x6 = xmm6;
+ const XMMRegister x7 = xmm7;
+
+ const Register tmp = rbx;
+
+ BLOCK_COMMENT("Entry:");
+ __ enter(); // required for proper stackwalking of RuntimeStub frame
+ __ fast_exp(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp);
+ __ leave(); // required for proper stackwalking of RuntimeStub frame
+ __ ret(0);
+
+ return start;
+
+ }
+
+
// Safefetch stubs.
void generate_safefetch(const char* name, int size, address* entry,
address* fault_pc, address* continuation_pc) {
@@ -3204,6 +3279,16 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_crc_table_adr = (address)StubRoutines::x86::_crc_table;
StubRoutines::_updateBytesCRC32 = generate_updateBytesCRC32();
}
+
+ if (UseCRC32CIntrinsics) {
+ bool supports_clmul = VM_Version::supports_clmul();
+ StubRoutines::x86::generate_CRC32C_table(supports_clmul);
+ StubRoutines::_crc32c_table_addr = (address)StubRoutines::x86::_crc32c_table;
+ StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C(supports_clmul);
+ }
+ if (VM_Version::supports_sse2()) {
+ StubRoutines::_dexp = generate_libmExp();
+ }
}
diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
index 36049bae44b..c37e02ecd39 100644
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
@@ -3038,19 +3038,6 @@ class StubGenerator: public StubCodeGenerator {
__ addq(rsp, 8);
__ ret(0);
}
- {
- StubCodeMark mark(this, "StubRoutines", "exp");
- StubRoutines::_intrinsic_exp = (double (*)(double)) __ pc();
-
- __ subq(rsp, 8);
- __ movdbl(Address(rsp, 0), xmm0);
- __ fld_d(Address(rsp, 0));
- __ exp_with_fallback(0);
- __ fstp_d(Address(rsp, 0));
- __ movdbl(xmm0, Address(rsp, 0));
- __ addq(rsp, 8);
- __ ret(0);
- }
{
StubCodeMark mark(this, "StubRoutines", "pow");
StubRoutines::_intrinsic_pow = (double (*)(double,double)) __ pc();
@@ -3958,6 +3945,64 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
+ /**
+ * Arguments:
+ *
+ * Inputs:
+ * c_rarg0 - int crc
+ * c_rarg1 - byte* buf
+ * c_rarg2 - long length
+ * c_rarg3 - table_start - optional (present only when doing a library_calll,
+ * not used by x86 algorithm)
+ *
+ * Ouput:
+ * rax - int crc result
+ */
+ address generate_updateBytesCRC32C(bool is_pclmulqdq_supported) {
+ assert(UseCRC32CIntrinsics, "need SSE4_2");
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "updateBytesCRC32C");
+ address start = __ pc();
+ //reg.arg int#0 int#1 int#2 int#3 int#4 int#5 float regs
+ //Windows RCX RDX R8 R9 none none XMM0..XMM3
+ //Lin / Sol RDI RSI RDX RCX R8 R9 XMM0..XMM7
+ const Register crc = c_rarg0; // crc
+ const Register buf = c_rarg1; // source java byte array address
+ const Register len = c_rarg2; // length
+ const Register a = rax;
+ const Register j = r9;
+ const Register k = r10;
+ const Register l = r11;
+#ifdef _WIN64
+ const Register y = rdi;
+ const Register z = rsi;
+#else
+ const Register y = rcx;
+ const Register z = r8;
+#endif
+ assert_different_registers(crc, buf, len, a, j, k, l, y, z);
+
+ BLOCK_COMMENT("Entry:");
+ __ enter(); // required for proper stackwalking of RuntimeStub frame
+#ifdef _WIN64
+ __ push(y);
+ __ push(z);
+#endif
+ __ crc32c_ipl_alg2_alt2(crc, buf, len,
+ a, j, k,
+ l, y, z,
+ c_farg0, c_farg1, c_farg2,
+ is_pclmulqdq_supported);
+ __ movl(rax, crc);
+#ifdef _WIN64
+ __ pop(z);
+ __ pop(y);
+#endif
+ __ leave(); // required for proper stackwalking of RuntimeStub frame
+ __ ret(0);
+
+ return start;
+ }
/**
* Arguments:
@@ -4122,6 +4167,44 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
+ address generate_libmExp() {
+ address start = __ pc();
+
+ const XMMRegister x0 = xmm0;
+ const XMMRegister x1 = xmm1;
+ const XMMRegister x2 = xmm2;
+ const XMMRegister x3 = xmm3;
+
+ const XMMRegister x4 = xmm4;
+ const XMMRegister x5 = xmm5;
+ const XMMRegister x6 = xmm6;
+ const XMMRegister x7 = xmm7;
+
+ const Register tmp = r11;
+
+ BLOCK_COMMENT("Entry:");
+ __ enter(); // required for proper stackwalking of RuntimeStub frame
+
+#ifdef _WIN64
+ // save the xmm registers which must be preserved 6-7
+ __ movdqu(xmm_save(6), as_XMMRegister(6));
+ __ movdqu(xmm_save(7), as_XMMRegister(7));
+#endif
+ __ fast_exp(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp);
+
+#ifdef _WIN64
+ // restore xmm regs belonging to calling function
+ __ movdqu(as_XMMRegister(6), xmm_save(6));
+ __ movdqu(as_XMMRegister(7), xmm_save(7));
+#endif
+
+ __ leave(); // required for proper stackwalking of RuntimeStub frame
+ __ ret(0);
+
+ return start;
+
+ }
+
#undef __
#define __ masm->
@@ -4302,6 +4385,14 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_crc_table_adr = (address)StubRoutines::x86::_crc_table;
StubRoutines::_updateBytesCRC32 = generate_updateBytesCRC32();
}
+
+ if (UseCRC32CIntrinsics) {
+ bool supports_clmul = VM_Version::supports_clmul();
+ StubRoutines::x86::generate_CRC32C_table(supports_clmul);
+ StubRoutines::_crc32c_table_addr = (address)StubRoutines::x86::_crc32c_table;
+ StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C(supports_clmul);
+ }
+ StubRoutines::_dexp = generate_libmExp();
}
void generate_all() {
diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp
index 9b0d8fc756f..cd5681a44d6 100644
--- a/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp
@@ -27,6 +27,7 @@
#include "runtime/frame.inline.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp"
+#include "crc32c.h"
// Implementation of the platform-specific part of StubRoutines - for
// a description of how to extend it, see the stubRoutines.hpp file.
@@ -130,3 +131,107 @@ juint StubRoutines::x86::_crc_table[] =
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
0x2d02ef8dUL
};
+
+#define D 32
+#define P 0x82F63B78 // Reflection of Castagnoli (0x11EDC6F41)
+
+#define TILL_CYCLE 31
+uint32_t _crc32c_pow_2k_table[TILL_CYCLE]; // because _crc32c_pow_2k_table[TILL_CYCLE == 31] == _crc32c_pow_2k_table[0]
+
+// A. Kadatch and B. Jenkins / Everything we know about CRC but afraid to forget September 3, 2010 8
+// Listing 1: Multiplication of normalized polynomials
+// "a" and "b" occupy D least significant bits.
+uint32_t crc32c_multiply(uint32_t a, uint32_t b) {
+ uint32_t product = 0;
+ uint32_t b_pow_x_table[D + 1]; // b_pow_x_table[k] = (b * x**k) mod P
+ b_pow_x_table[0] = b;
+ for (int k = 0; k < D; ++k) {
+ // If "a" has non-zero coefficient at x**k,/ add ((b * x**k) mod P) to the result.
+ if ((a & (uint64_t)(1 << (D - 1 - k))) != 0) product ^= b_pow_x_table[k];
+
+ // Compute b_pow_x_table[k+1] = (b ** x**(k+1)) mod P.
+ if (b_pow_x_table[k] & 1) {
+ // If degree of (b_pow_x_table[k] * x) is D, then
+ // degree of (b_pow_x_table[k] * x - P) is less than D.
+ b_pow_x_table[k + 1] = (b_pow_x_table[k] >> 1) ^ P;
+ }
+ else {
+ b_pow_x_table[k + 1] = b_pow_x_table[k] >> 1;
+ }
+ }
+ return product;
+}
+#undef D
+#undef P
+
+// A. Kadatch and B. Jenkins / Everything we know about CRC but afraid to forget September 3, 2010 9
+void crc32c_init_pow_2k(void) {
+ // _crc32c_pow_2k_table(0) =
+ // x^(2^k) mod P(x) = x mod P(x) = x
+ // Since we are operating on a reflected values
+ // x = 10b, reflect(x) = 0x40000000
+ _crc32c_pow_2k_table[0] = 0x40000000;
+
+ for (int k = 1; k < TILL_CYCLE; k++) {
+ // _crc32c_pow_2k_table(k+1) = _crc32c_pow_2k_table(k-1)^2 mod P(x)
+ uint32_t tmp = _crc32c_pow_2k_table[k - 1];
+ _crc32c_pow_2k_table[k] = crc32c_multiply(tmp, tmp);
+ }
+}
+
+// x^N mod P(x)
+uint32_t crc32c_f_pow_n(uint32_t n) {
+ // result = 1 (polynomial)
+ uint32_t one, result = 0x80000000, i = 0;
+
+ while (one = (n & 1), (n == 1 || n - one > 0)) {
+ if (one) {
+ result = crc32c_multiply(result, _crc32c_pow_2k_table[i]);
+ }
+ n >>= 1;
+ i++;
+ }
+
+ return result;
+}
+
+juint *StubRoutines::x86::_crc32c_table;
+
+void StubRoutines::x86::generate_CRC32C_table(bool is_pclmulqdq_table_supported) {
+
+ static juint pow_n[CRC32C_NUM_PRECOMPUTED_CONSTANTS];
+
+ crc32c_init_pow_2k();
+
+ pow_n[0] = crc32c_f_pow_n(CRC32C_HIGH * 8); // 8N * 8 = 64N
+ pow_n[1] = crc32c_f_pow_n(CRC32C_HIGH * 8 * 2); // 128N
+
+ pow_n[2] = crc32c_f_pow_n(CRC32C_MIDDLE * 8);
+ pow_n[3] = crc32c_f_pow_n(CRC32C_MIDDLE * 8 * 2);
+
+ pow_n[4] = crc32c_f_pow_n(CRC32C_LOW * 8);
+ pow_n[CRC32C_NUM_PRECOMPUTED_CONSTANTS - 1] =
+ crc32c_f_pow_n(CRC32C_LOW * 8 * 2);
+
+ if (is_pclmulqdq_table_supported) {
+ _crc32c_table = pow_n;
+ } else {
+ static julong pclmulqdq_table[CRC32C_NUM_PRECOMPUTED_CONSTANTS * 256];
+
+ for (int j = 0; j < CRC32C_NUM_PRECOMPUTED_CONSTANTS; j++) {
+ static juint X_CONST = pow_n[j];
+ for (int64_t i = 0; i < 256; i++) { // to force 64 bit wide computations
+ // S. Gueron / Information Processing Letters 112 (2012) 184
+ // Algorithm 3: Generating a carry-less multiplication lookup table.
+ // Input: A 32-bit constant, X_CONST.
+ // Output: A table of 256 entries, each one is a 64-bit quadword,
+ // that can be used for computing "byte" * X_CONST, for a given byte.
+ pclmulqdq_table[j * 256 + i] =
+ ((i & 1) * X_CONST) ^ ((i & 2) * X_CONST) ^ ((i & 4) * X_CONST) ^
+ ((i & 8) * X_CONST) ^ ((i & 16) * X_CONST) ^ ((i & 32) * X_CONST) ^
+ ((i & 64) * X_CONST) ^ ((i & 128) * X_CONST);
+ }
+ }
+ _crc32c_table = (juint*)pclmulqdq_table;
+ }
+}
diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp
index bb160486cd1..7e236967fb8 100644
--- a/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp
@@ -36,6 +36,8 @@
// masks and table for CRC32
static uint64_t _crc_by128_masks[];
static juint _crc_table[];
+ // table for CRC32C
+ static juint* _crc32c_table;
// swap mask for ghash
static address _ghash_long_swap_mask_addr;
static address _ghash_byte_swap_mask_addr;
@@ -46,5 +48,6 @@
static address crc_by128_masks_addr() { return (address)_crc_by128_masks; }
static address ghash_long_swap_mask_addr() { return _ghash_long_swap_mask_addr; }
static address ghash_byte_swap_mask_addr() { return _ghash_byte_swap_mask_addr; }
+ static void generate_CRC32C_table(bool is_pclmulqdq_supported);
#endif // CPU_X86_VM_STUBROUTINES_X86_32_HPP
diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
index eab2e64a618..6e27d776142 100644
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
@@ -538,7 +538,7 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
// Allocate monitor and lock method (asm interpreter)
// rbx, - Method*
//
-void InterpreterGenerator::lock_method(void) {
+void TemplateInterpreterGenerator::lock_method() {
// synchronize method
const Address access_flags (rbx, Method::access_flags_offset());
const Address monitor_block_top (rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize);
@@ -697,15 +697,14 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
__ jmp(rdi);
__ bind(slow_path);
- (void) generate_normal_entry(false);
-
+ __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals));
return entry;
}
#endif // INCLUDE_ALL_GCS
// If G1 is not enabled then attempt to go through the accessor entry point
// Reference.get is an accessor
- return generate_jump_to_normal_entry();
+ return NULL;
}
/**
@@ -753,12 +752,10 @@ address InterpreterGenerator::generate_CRC32_update_entry() {
// generate a vanilla native entry as the slow path
__ bind(slow_path);
-
- (void) generate_native_entry(false);
-
+ __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native));
return entry;
}
- return generate_native_entry(false);
+ return NULL;
}
/**
@@ -790,18 +787,25 @@ address InterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpret
const Register buf = rdx; // source java byte array address
const Register len = rdi; // length
+ // value x86_32
+ // interp. arg ptr ESP + 4
+ // int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int len)
+ // 3 2 1 0
+ // int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len)
+ // 4 2,3 1 0
+
// Arguments are reversed on java expression stack
- __ movl(len, Address(rsp, wordSize)); // Length
+ __ movl(len, Address(rsp, 4 + 0)); // Length
// Calculate address of start element
if (kind == Interpreter::java_util_zip_CRC32_updateByteBuffer) {
- __ movptr(buf, Address(rsp, 3*wordSize)); // long buf
- __ addptr(buf, Address(rsp, 2*wordSize)); // + offset
- __ movl(crc, Address(rsp, 5*wordSize)); // Initial CRC
+ __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // long buf
+ __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
+ __ movl(crc, Address(rsp, 4 + 4 * wordSize)); // Initial CRC
} else {
- __ movptr(buf, Address(rsp, 3*wordSize)); // byte[] array
+ __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // byte[] array
__ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size
- __ addptr(buf, Address(rsp, 2*wordSize)); // + offset
- __ movl(crc, Address(rsp, 4*wordSize)); // Initial CRC
+ __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
+ __ movl(crc, Address(rsp, 4 + 3 * wordSize)); // Initial CRC
}
__ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32()), crc, buf, len);
@@ -814,12 +818,57 @@ address InterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpret
// generate a vanilla native entry as the slow path
__ bind(slow_path);
+ __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native));
+ return entry;
+ }
+ return NULL;
+}
- (void) generate_native_entry(false);
+/**
+* Method entry for static native methods:
+* int java.util.zip.CRC32C.updateBytes(int crc, byte[] b, int off, int end)
+* int java.util.zip.CRC32C.updateByteBuffer(int crc, long address, int off, int end)
+*/
+address InterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) {
+ if (UseCRC32CIntrinsics) {
+ address entry = __ pc();
+ // Load parameters
+ const Register crc = rax; // crc
+ const Register buf = rcx; // source java byte array address
+ const Register len = rdx; // length
+ const Register end = len;
+
+ // value x86_32
+ // interp. arg ptr ESP + 4
+ // int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int end)
+ // 3 2 1 0
+ // int java.util.zip.CRC32.updateByteBuffer(int crc, long address, int off, int end)
+ // 4 2,3 1 0
+
+ // Arguments are reversed on java expression stack
+ __ movl(end, Address(rsp, 4 + 0)); // end
+ __ subl(len, Address(rsp, 4 + 1 * wordSize)); // end - offset == length
+ // Calculate address of start element
+ if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) {
+ __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // long address
+ __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
+ __ movl(crc, Address(rsp, 4 + 4 * wordSize)); // Initial CRC
+ } else {
+ __ movptr(buf, Address(rsp, 4 + 2 * wordSize)); // byte[] array
+ __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size
+ __ addptr(buf, Address(rsp, 4 + 1 * wordSize)); // + offset
+ __ movl(crc, Address(rsp, 4 + 3 * wordSize)); // Initial CRC
+ }
+ __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32C()), crc, buf, len);
+ // result in rax
+ // _areturn
+ __ pop(rdi); // get return address
+ __ mov(rsp, rsi); // set sp to sender sp
+ __ jmp(rdi);
return entry;
}
- return generate_native_entry(false);
+ return NULL;
}
/**
@@ -827,10 +876,8 @@ address InterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpret
* java.lang.Float.intBitsToFloat(int bits)
*/
address InterpreterGenerator::generate_Float_intBitsToFloat_entry() {
- address entry;
-
if (UseSSE >= 1) {
- entry = __ pc();
+ address entry = __ pc();
// rsi: the sender's SP
@@ -844,11 +891,10 @@ address InterpreterGenerator::generate_Float_intBitsToFloat_entry() {
__ pop(rdi); // get return address
__ mov(rsp, rsi); // set rsp to the sender's SP
__ jmp(rdi);
- } else {
- entry = generate_native_entry(false);
+ return entry;
}
- return entry;
+ return NULL;
}
/**
@@ -856,10 +902,8 @@ address InterpreterGenerator::generate_Float_intBitsToFloat_entry() {
* java.lang.Float.floatToRawIntBits(float value)
*/
address InterpreterGenerator::generate_Float_floatToRawIntBits_entry() {
- address entry;
-
if (UseSSE >= 1) {
- entry = __ pc();
+ address entry = __ pc();
// rsi: the sender's SP
@@ -873,11 +917,10 @@ address InterpreterGenerator::generate_Float_floatToRawIntBits_entry() {
__ pop(rdi); // get return address
__ mov(rsp, rsi); // set rsp to the sender's SP
__ jmp(rdi);
- } else {
- entry = generate_native_entry(false);
+ return entry;
}
- return entry;
+ return NULL;
}
@@ -886,10 +929,8 @@ address InterpreterGenerator::generate_Float_floatToRawIntBits_entry() {
* java.lang.Double.longBitsToDouble(long bits)
*/
address InterpreterGenerator::generate_Double_longBitsToDouble_entry() {
- address entry;
-
if (UseSSE >= 2) {
- entry = __ pc();
+ address entry = __ pc();
// rsi: the sender's SP
@@ -903,11 +944,10 @@ address InterpreterGenerator::generate_Double_longBitsToDouble_entry() {
__ pop(rdi); // get return address
__ mov(rsp, rsi); // set rsp to the sender's SP
__ jmp(rdi);
- } else {
- entry = generate_native_entry(false);
+ return entry;
}
- return entry;
+ return NULL;
}
/**
@@ -915,10 +955,8 @@ address InterpreterGenerator::generate_Double_longBitsToDouble_entry() {
* java.lang.Double.doubleToRawLongBits(double value)
*/
address InterpreterGenerator::generate_Double_doubleToRawLongBits_entry() {
- address entry;
-
if (UseSSE >= 2) {
- entry = __ pc();
+ address entry = __ pc();
// rsi: the sender's SP
@@ -933,11 +971,10 @@ address InterpreterGenerator::generate_Double_doubleToRawLongBits_entry() {
__ pop(rdi); // get return address
__ mov(rsp, rsi); // set rsp to the sender's SP
__ jmp(rdi);
- } else {
- entry = generate_native_entry(false);
+ return entry;
}
- return entry;
+ return NULL;
}
//
diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
index 5a8466f60e8..cea18ba83a7 100644
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
@@ -198,13 +198,27 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
}
-address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state,
- int step) {
+address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, int step) {
address entry = __ pc();
// NULL last_sp until next java call
__ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD);
__ restore_bcp();
__ restore_locals();
+#if INCLUDE_JVMCI
+ // Check if we need to take lock at entry of synchronized method.
+ if (UseJVMCICompiler) {
+ Label L;
+ __ cmpb(Address(r15_thread, JavaThread::pending_monitorenter_offset()), 0);
+ __ jcc(Assembler::zero, L);
+ // Clear flag.
+ __ movb(Address(r15_thread, JavaThread::pending_monitorenter_offset()), 0);
+ // Satisfy calling convention for lock_method().
+ __ get_method(rbx);
+ // Take lock.
+ lock_method();
+ __ bind(L);
+ }
+#endif
// handle exceptions
{
Label L;
@@ -500,7 +514,7 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
// rax
// c_rarg0, c_rarg1, c_rarg2, c_rarg3, ...(param regs)
// rscratch1, rscratch2 (scratch regs)
-void InterpreterGenerator::lock_method(void) {
+void TemplateInterpreterGenerator::lock_method() {
// synchronize method
const Address access_flags(rbx, Method::access_flags_offset());
const Address monitor_block_top(
@@ -677,15 +691,14 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// generate a vanilla interpreter entry as the slow path
__ bind(slow_path);
- (void) generate_normal_entry(false);
-
+ __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals));
return entry;
}
#endif // INCLUDE_ALL_GCS
// If G1 is not enabled then attempt to go through the accessor entry point
// Reference.get is an accessor
- return generate_jump_to_normal_entry();
+ return NULL;
}
/**
@@ -733,12 +746,10 @@ address InterpreterGenerator::generate_CRC32_update_entry() {
// generate a vanilla native entry as the slow path
__ bind(slow_path);
-
- (void) generate_native_entry(false);
-
+ __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native));
return entry;
}
- return generate_native_entry(false);
+ return NULL;
}
/**
@@ -796,12 +807,61 @@ address InterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpret
// generate a vanilla native entry as the slow path
__ bind(slow_path);
+ __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::native));
+ return entry;
+ }
+ return NULL;
+}
- (void) generate_native_entry(false);
+/**
+* Method entry for static native methods:
+* int java.util.zip.CRC32C.updateBytes(int crc, byte[] b, int off, int end)
+* int java.util.zip.CRC32C.updateByteBuffer(int crc, long address, int off, int end)
+*/
+address InterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) {
+ if (UseCRC32CIntrinsics) {
+ address entry = __ pc();
+ // Load parameters
+ const Register crc = c_rarg0; // crc
+ const Register buf = c_rarg1; // source java byte array address
+ const Register len = c_rarg2;
+ const Register off = c_rarg3; // offset
+ const Register end = len;
+
+ // Arguments are reversed on java expression stack
+ // Calculate address of start element
+ if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) {
+ __ movptr(buf, Address(rsp, 3 * wordSize)); // long buf
+ __ movl2ptr(off, Address(rsp, 2 * wordSize)); // offset
+ __ addq(buf, off); // + offset
+ __ movl(crc, Address(rsp, 5 * wordSize)); // Initial CRC
+ // Note on 5 * wordSize vs. 4 * wordSize:
+ // * int java.util.zip.CRC32C.updateByteBuffer(int crc, long address, int off, int end)
+ // 4 2,3 1 0
+ // end starts at SP + 8
+ // The Java(R) Virtual Machine Specification Java SE 7 Edition
+ // 4.10.2.3. Values of Types long and double
+ // "When calculating operand stack length, values of type long and double have length two."
+ } else {
+ __ movptr(buf, Address(rsp, 3 * wordSize)); // byte[] array
+ __ addptr(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // + header size
+ __ movl2ptr(off, Address(rsp, 2 * wordSize)); // offset
+ __ addq(buf, off); // + offset
+ __ movl(crc, Address(rsp, 4 * wordSize)); // Initial CRC
+ }
+ __ movl(end, Address(rsp, wordSize)); // end
+ __ subl(end, off); // end - off
+ __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, StubRoutines::updateBytesCRC32C()), crc, buf, len);
+ // result in rax
+ // _areturn
+ __ pop(rdi); // get return address
+ __ mov(rsp, r13); // set sp to sender sp
+ __ jmp(rdi);
return entry;
}
- return generate_native_entry(false);
+
+ return NULL;
}
// Interpreter stub for calling a native method. (asm interpreter)
diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp
index 2a992389170..82e355f797e 100644
--- a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp
@@ -3595,6 +3595,8 @@ void TemplateTable::invokevirtual_helper(Register index,
__ profile_virtual_call(rax, rlocals, rdx);
// get target Method* & entry point
__ lookup_virtual_method(rax, index, method);
+ __ profile_called_method(method, rdx, rbcp);
+
__ profile_arguments_type(rdx, method, rbcp, true);
__ jump_from_interpreted(method, rdx);
}
@@ -3694,6 +3696,7 @@ void TemplateTable::invokeinterface(int byte_no) {
__ testptr(rbx, rbx);
__ jcc(Assembler::zero, no_such_method);
+ __ profile_called_method(rbx, rbcp, rdx);
__ profile_arguments_type(rdx, rbx, rbcp, true);
// do the call
diff --git a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp
index 89cbc3b15a5..121ec0a02ac 100644
--- a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp
@@ -37,13 +37,50 @@
/******************************/ \
/* JavaFrameAnchor */ \
/******************************/ \
- volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*)
+ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \
+ static_field(VM_Version, _cpuFeatures, uint64_t)
-#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
+#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
+ declare_toplevel_type(VM_Version)
-#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
+#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \
+ LP64_ONLY(declare_constant(frame::arg_reg_save_area_bytes)) \
+ declare_constant(frame::interpreter_frame_sender_sp_offset) \
+ declare_constant(frame::interpreter_frame_last_sp_offset) \
+ declare_constant(VM_Version::CPU_CX8) \
+ declare_constant(VM_Version::CPU_CMOV) \
+ declare_constant(VM_Version::CPU_FXSR) \
+ declare_constant(VM_Version::CPU_HT) \
+ declare_constant(VM_Version::CPU_MMX) \
+ declare_constant(VM_Version::CPU_3DNOW_PREFETCH) \
+ declare_constant(VM_Version::CPU_SSE) \
+ declare_constant(VM_Version::CPU_SSE2) \
+ declare_constant(VM_Version::CPU_SSE3) \
+ declare_constant(VM_Version::CPU_SSSE3) \
+ declare_constant(VM_Version::CPU_SSE4A) \
+ declare_constant(VM_Version::CPU_SSE4_1) \
+ declare_constant(VM_Version::CPU_SSE4_2) \
+ declare_constant(VM_Version::CPU_POPCNT) \
+ declare_constant(VM_Version::CPU_LZCNT) \
+ declare_constant(VM_Version::CPU_TSC) \
+ declare_constant(VM_Version::CPU_TSCINV) \
+ declare_constant(VM_Version::CPU_AVX) \
+ declare_constant(VM_Version::CPU_AVX2) \
+ declare_constant(VM_Version::CPU_AES) \
+ declare_constant(VM_Version::CPU_ERMS) \
+ declare_constant(VM_Version::CPU_CLMUL) \
+ declare_constant(VM_Version::CPU_BMI1) \
+ declare_constant(VM_Version::CPU_BMI2) \
+ declare_constant(VM_Version::CPU_RTM) \
+ declare_constant(VM_Version::CPU_ADX) \
+ declare_constant(VM_Version::CPU_AVX512F) \
+ declare_constant(VM_Version::CPU_AVX512DQ) \
+ declare_constant(VM_Version::CPU_AVX512PF) \
+ declare_constant(VM_Version::CPU_AVX512ER) \
+ declare_constant(VM_Version::CPU_AVX512CD) \
+ declare_constant(VM_Version::CPU_AVX512BW)
#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
index f29b51469ff..4e2e1942cef 100644
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
@@ -661,6 +661,18 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
}
+ if (supports_sse4_2()) {
+ if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) {
+ UseCRC32CIntrinsics = true;
+ }
+ }
+ else if (UseCRC32CIntrinsics) {
+ if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) {
+ warning("CRC32C intrinsics are not available on this CPU");
+ }
+ FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
+ }
+
// The AES intrinsic stubs require AES instruction support (of course)
// but also require sse3 mode for instructions it use.
if (UseAES && (UseSSE > 2)) {
@@ -704,12 +716,6 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
}
- if (UseCRC32CIntrinsics) {
- if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics))
- warning("CRC32C intrinsics are not available on this CPU");
- FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
- }
-
if (UseAdler32Intrinsics) {
warning("Adler32Intrinsics not available on this CPU.");
FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
@@ -781,6 +787,8 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseFPUForSpilling, false);
}
}
+#endif
+#if defined(COMPILER2) || INCLUDE_JVMCI
if (MaxVectorSize > 0) {
if (!is_power_of_2(MaxVectorSize)) {
warning("MaxVectorSize must be a power of 2");
@@ -797,7 +805,7 @@ void VM_Version::get_processor_features() {
// Vectors (in XMM) are only supported with SSE2+
FLAG_SET_DEFAULT(MaxVectorSize, 0);
}
-#ifdef ASSERT
+#if defined(COMPILER2) && defined(ASSERT)
if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) {
tty->print_cr("State of YMM registers after signal handle:");
int nreg = 2 LP64_ONLY(+2);
@@ -810,9 +818,11 @@ void VM_Version::get_processor_features() {
tty->cr();
}
}
-#endif
+#endif // COMPILER2 && ASSERT
}
+#endif // COMPILER2 || INCLUDE_JVMCI
+#ifdef COMPILER2
#ifdef _LP64
if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
UseMultiplyToLenIntrinsic = true;
@@ -1082,11 +1092,6 @@ void VM_Version::get_processor_features() {
}
#endif // COMPILER2
- assert(0 <= AllocatePrefetchInstr && AllocatePrefetchInstr <= 3, "invalid value");
-
- // set valid Prefetch instruction
- if( AllocatePrefetchInstr < 0 ) AllocatePrefetchInstr = 0;
- if( AllocatePrefetchInstr > 3 ) AllocatePrefetchInstr = 3;
if( AllocatePrefetchInstr == 3 && !supports_3dnow_prefetch() ) AllocatePrefetchInstr=0;
if( !supports_sse() && supports_3dnow_prefetch() ) AllocatePrefetchInstr = 3;
@@ -1125,7 +1130,6 @@ void VM_Version::get_processor_features() {
}
#endif
}
- assert(AllocatePrefetchDistance % AllocatePrefetchStepSize == 0, "invalid value");
#ifdef _LP64
// Prefetch settings
diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp
index 45abb210ffe..d97c681cfc0 100644
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp
@@ -29,6 +29,7 @@
#include "runtime/vm_version.hpp"
class VM_Version : public Abstract_VM_Version {
+ friend class VMStructs;
public:
// cpuid result register layouts. These are all unions of a uint32_t
// (in case anyone wants access to the register as a whole) and a bitfield.
diff --git a/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp b/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp
index 2487fc87455..13f595884eb 100644
--- a/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp
@@ -35,8 +35,6 @@
#include "opto/runtime.hpp"
#endif
-PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-
// machine-dependent part of VtableStubs: create VtableStub of correct size and
// initialize its code
@@ -113,7 +111,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
if (PrintMiscellaneous && (WizardMode || Verbose)) {
tty->print_cr("vtable #%d at " PTR_FORMAT "[%d] left over: %d",
- vtable_index, s->entry_point(),
+ vtable_index, p2i(s->entry_point()),
(int)(s->code_end() - s->entry_point()),
(int)(s->code_end() - __ pc()));
}
@@ -206,7 +204,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
if (PrintMiscellaneous && (WizardMode || Verbose)) {
tty->print_cr("itable #%d at " PTR_FORMAT "[%d] left over: %d",
- itable_index, s->entry_point(),
+ itable_index, p2i(s->entry_point()),
(int)(s->code_end() - s->entry_point()),
(int)(s->code_end() - __ pc()));
}
diff --git a/hotspot/src/cpu/x86/vm/x86.ad b/hotspot/src/cpu/x86/vm/x86.ad
index 120be4f0bd1..00a017bfc8f 100644
--- a/hotspot/src/cpu/x86/vm/x86.ad
+++ b/hotspot/src/cpu/x86/vm/x86.ad
@@ -1712,6 +1712,18 @@ const bool Matcher::match_rule_supported(int opcode) {
return ret_value; // Per default match rules are supported.
}
+const int Matcher::float_pressure(int default_pressure_threshold) {
+ int float_pressure_threshold = default_pressure_threshold;
+#ifdef _LP64
+ if (UseAVX > 2) {
+ // Increase pressure threshold on machines with AVX3 which have
+ // 2x more XMM registers.
+ float_pressure_threshold = default_pressure_threshold * 2;
+ }
+#endif
+ return float_pressure_threshold;
+}
+
// Max vector size in bytes. 0 if not supported.
const int Matcher::vector_width_in_bytes(BasicType bt) {
assert(is_java_primitive(bt), "only primitive type vectors");
diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad
index 79b55056cba..009a3acacb0 100644
--- a/hotspot/src/cpu/x86/vm/x86_32.ad
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad
@@ -580,7 +580,11 @@ void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
st->print("MOV [ESP + #%d], EBP\t# Save EBP",framesize);
if (PreserveFramePointer) {
st->print("\n\t");
- st->print("MOV EBP, [ESP + #%d]\t# Save the caller's SP into EBP", (framesize + wordSize));
+ st->print("MOV EBP, ESP\t# Save the caller's SP into EBP");
+ if (framesize > 0) {
+ st->print("\n\t");
+ st->print("ADD EBP, #%d", framesize);
+ }
}
}
@@ -9911,35 +9915,6 @@ instruct powD_reg(regD dst, regD src0, regD src1, eAXRegI rax, eDXRegI rdx, eCXR
ins_pipe( pipe_slow );
%}
-
-instruct expDPR_reg(regDPR1 dpr1, eAXRegI rax, eDXRegI rdx, eCXRegI rcx, eFlagsReg cr) %{
- predicate (UseSSE<=1);
- match(Set dpr1 (ExpD dpr1));
- effect(KILL rax, KILL rcx, KILL rdx, KILL cr);
- format %{ "fast_exp $dpr1 -> $dpr1 // KILL $rax, $rcx, $rdx" %}
- ins_encode %{
- __ fast_exp();
- %}
- ins_pipe( pipe_slow );
-%}
-
-instruct expD_reg(regD dst, regD src, eAXRegI rax, eDXRegI rdx, eCXRegI rcx, eFlagsReg cr) %{
- predicate (UseSSE>=2);
- match(Set dst (ExpD src));
- effect(KILL rax, KILL rcx, KILL rdx, KILL cr);
- format %{ "fast_exp $dst -> $src // KILL $rax, $rcx, $rdx" %}
- ins_encode %{
- __ subptr(rsp, 8);
- __ movdbl(Address(rsp, 0), $src$$XMMRegister);
- __ fld_d(Address(rsp, 0));
- __ fast_exp();
- __ fstp_d(Address(rsp, 0));
- __ movdbl($dst$$XMMRegister, Address(rsp, 0));
- __ addptr(rsp, 8);
- %}
- ins_pipe( pipe_slow );
-%}
-
instruct log10DPR_reg(regDPR1 dst, regDPR1 src) %{
predicate (UseSSE<=1);
// The source Double operand on FPU stack
diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad
index 9fcc7033c8a..b49f60592a7 100644
--- a/hotspot/src/cpu/x86/vm/x86_64.ad
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad
@@ -867,7 +867,11 @@ void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
st->print("movq [rsp + #%d], rbp\t# Save rbp",framesize);
if (PreserveFramePointer) {
st->print("\n\t");
- st->print("movq rbp, [rsp + #%d]\t# Save the caller's SP into rbp", (framesize + wordSize));
+ st->print("movq rbp, rsp\t# Save the caller's SP into rbp");
+ if (framesize > 0) {
+ st->print("\n\t");
+ st->print("addq rbp, #%d", framesize);
+ }
}
}
@@ -2136,12 +2140,13 @@ encode %{
RELOC_DISP32);
}
if (_method) {
- // Emit stub for static call.
- address stub = CompiledStaticCall::emit_to_interp_stub(cbuf);
+ // Emit stubs for static call.
+ address mark = cbuf.insts_mark();
+ address stub = CompiledStaticCall::emit_to_interp_stub(cbuf, mark);
if (stub == NULL) {
ciEnv::current()->record_failure("CodeCache is full");
return;
- }
+ }
}
%}
@@ -3767,6 +3772,22 @@ operand indIndexScale(any_RegP reg, rRegL lreg, immI2 scale)
%}
%}
+operand indPosIndexScale(any_RegP reg, rRegI idx, immI2 scale)
+%{
+ constraint(ALLOC_IN_RC(ptr_reg));
+ predicate(n->in(3)->in(1)->as_Type()->type()->is_long()->_lo >= 0);
+ match(AddP reg (LShiftL (ConvI2L idx) scale));
+
+ op_cost(10);
+ format %{"[$reg + pos $idx << $scale]" %}
+ interface(MEMORY_INTER) %{
+ base($reg);
+ index($idx);
+ scale($scale);
+ disp(0x0);
+ %}
+%}
+
// Indirect Memory Times Scale Plus Index Register Plus Offset Operand
operand indIndexScaleOffset(any_RegP reg, immL32 off, rRegL lreg, immI2 scale)
%{
@@ -4159,7 +4180,7 @@ operand cmpOpUCF2() %{
// case of this is memory operands.
opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex,
- indIndexScale, indIndexScaleOffset, indPosIndexOffset, indPosIndexScaleOffset,
+ indIndexScale, indPosIndexScale, indIndexScaleOffset, indPosIndexOffset, indPosIndexScaleOffset,
indCompressedOopOffset,
indirectNarrow, indOffset8Narrow, indOffset32Narrow,
indIndexOffsetNarrow, indIndexNarrow, indIndexScaleNarrow,
@@ -5186,6 +5207,17 @@ instruct leaPIdxScale(rRegP dst, indIndexScale mem)
ins_pipe(ialu_reg_reg_fat);
%}
+instruct leaPPosIdxScale(rRegP dst, indPosIndexScale mem)
+%{
+ match(Set dst mem);
+
+ ins_cost(110);
+ format %{ "leaq $dst, $mem\t# ptr idxscale" %}
+ opcode(0x8D);
+ ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem));
+ ins_pipe(ialu_reg_reg_fat);
+%}
+
instruct leaPIdxScaleOff(rRegP dst, indIndexScaleOffset mem)
%{
match(Set dst mem);
@@ -9871,22 +9903,6 @@ instruct powD_reg(regD dst, regD src0, regD src1, rax_RegI rax, rdx_RegI rdx, rc
ins_pipe( pipe_slow );
%}
-instruct expD_reg(regD dst, regD src, rax_RegI rax, rdx_RegI rdx, rcx_RegI rcx, rFlagsReg cr) %{
- match(Set dst (ExpD src));
- effect(KILL rax, KILL rcx, KILL rdx, KILL cr);
- format %{ "fast_exp $dst -> $src // KILL $rax, $rcx, $rdx" %}
- ins_encode %{
- __ subptr(rsp, 8);
- __ movdbl(Address(rsp, 0), $src$$XMMRegister);
- __ fld_d(Address(rsp, 0));
- __ fast_exp();
- __ fstp_d(Address(rsp, 0));
- __ movdbl($dst$$XMMRegister, Address(rsp, 0));
- __ addptr(rsp, 8);
- %}
- ins_pipe( pipe_slow );
-%}
-
//----------Arithmetic Conversion Instructions---------------------------------
instruct roundFloat_nop(regF dst)
diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
index 4875e109538..78dad699f97 100644
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
@@ -816,7 +816,7 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
// If G1 is not enabled then attempt to go through the normal entry point
// Reference.get could be instrumented by jvmti
- return generate_normal_entry(false);
+ return NULL;
}
address InterpreterGenerator::generate_native_entry(bool synchronized) {
diff --git a/hotspot/src/cpu/zero/vm/globals_zero.hpp b/hotspot/src/cpu/zero/vm/globals_zero.hpp
index 511554d1cf3..cc46781cd0a 100644
--- a/hotspot/src/cpu/zero/vm/globals_zero.hpp
+++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp
@@ -45,9 +45,17 @@ define_pd_global(intx, OptoLoopAlignment, 16);
define_pd_global(intx, InlineFrequencyCount, 100);
define_pd_global(intx, InlineSmallCode, 1000 );
-define_pd_global(intx, StackYellowPages, 2);
-define_pd_global(intx, StackRedPages, 1);
-define_pd_global(intx, StackShadowPages, 5 LP64_ONLY(+1) DEBUG_ONLY(+3));
+#define DEFAULT_STACK_YELLOW_PAGES (2)
+#define DEFAULT_STACK_RED_PAGES (1)
+#define DEFAULT_STACK_SHADOW_PAGES (5 LP64_ONLY(+1) DEBUG_ONLY(+3))
+
+#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
+#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
+#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
+
+define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
+define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
+define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
diff --git a/hotspot/src/cpu/zero/vm/interpreterGenerator_zero.hpp b/hotspot/src/cpu/zero/vm/interpreterGenerator_zero.hpp
index 68516b4daf9..8f54ae265a9 100644
--- a/hotspot/src/cpu/zero/vm/interpreterGenerator_zero.hpp
+++ b/hotspot/src/cpu/zero/vm/interpreterGenerator_zero.hpp
@@ -42,4 +42,5 @@
// Not supported
address generate_CRC32_update_entry() { return NULL; }
address generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return NULL; }
+ address generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { return NULL; }
#endif // CPU_ZERO_VM_INTERPRETERGENERATOR_ZERO_HPP
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java
new file mode 100644
index 00000000000..591b3c0eee6
--- /dev/null
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.amd64;
+
+import static jdk.vm.ci.code.MemoryBarriers.*;
+import static jdk.vm.ci.code.Register.*;
+
+import java.nio.*;
+import java.util.*;
+
+import jdk.vm.ci.code.*;
+import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents the AMD64 architecture.
+ */
+public class AMD64 extends Architecture {
+
+ public static final RegisterCategory CPU = new RegisterCategory("CPU");
+
+ // @formatter:off
+
+ // General purpose CPU registers
+ public static final Register rax = new Register(0, 0, "rax", CPU);
+ public static final Register rcx = new Register(1, 1, "rcx", CPU);
+ public static final Register rdx = new Register(2, 2, "rdx", CPU);
+ public static final Register rbx = new Register(3, 3, "rbx", CPU);
+ public static final Register rsp = new Register(4, 4, "rsp", CPU);
+ public static final Register rbp = new Register(5, 5, "rbp", CPU);
+ public static final Register rsi = new Register(6, 6, "rsi", CPU);
+ public static final Register rdi = new Register(7, 7, "rdi", CPU);
+
+ public static final Register r8 = new Register(8, 8, "r8", CPU);
+ public static final Register r9 = new Register(9, 9, "r9", CPU);
+ public static final Register r10 = new Register(10, 10, "r10", CPU);
+ public static final Register r11 = new Register(11, 11, "r11", CPU);
+ public static final Register r12 = new Register(12, 12, "r12", CPU);
+ public static final Register r13 = new Register(13, 13, "r13", CPU);
+ public static final Register r14 = new Register(14, 14, "r14", CPU);
+ public static final Register r15 = new Register(15, 15, "r15", CPU);
+
+ public static final Register[] cpuRegisters = {
+ rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
+ r8, r9, r10, r11, r12, r13, r14, r15
+ };
+
+ private static final int XMM_REFERENCE_MAP_SHIFT = 2;
+
+ public static final RegisterCategory XMM = new RegisterCategory("XMM", cpuRegisters.length, XMM_REFERENCE_MAP_SHIFT);
+
+ // XMM registers
+ public static final Register xmm0 = new Register(16, 0, "xmm0", XMM);
+ public static final Register xmm1 = new Register(17, 1, "xmm1", XMM);
+ public static final Register xmm2 = new Register(18, 2, "xmm2", XMM);
+ public static final Register xmm3 = new Register(19, 3, "xmm3", XMM);
+ public static final Register xmm4 = new Register(20, 4, "xmm4", XMM);
+ public static final Register xmm5 = new Register(21, 5, "xmm5", XMM);
+ public static final Register xmm6 = new Register(22, 6, "xmm6", XMM);
+ public static final Register xmm7 = new Register(23, 7, "xmm7", XMM);
+
+ public static final Register xmm8 = new Register(24, 8, "xmm8", XMM);
+ public static final Register xmm9 = new Register(25, 9, "xmm9", XMM);
+ public static final Register xmm10 = new Register(26, 10, "xmm10", XMM);
+ public static final Register xmm11 = new Register(27, 11, "xmm11", XMM);
+ public static final Register xmm12 = new Register(28, 12, "xmm12", XMM);
+ public static final Register xmm13 = new Register(29, 13, "xmm13", XMM);
+ public static final Register xmm14 = new Register(30, 14, "xmm14", XMM);
+ public static final Register xmm15 = new Register(31, 15, "xmm15", XMM);
+
+ public static final Register[] xmmRegisters = {
+ xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
+ xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+ };
+
+ public static final Register[] cpuxmmRegisters = {
+ rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
+ r8, r9, r10, r11, r12, r13, r14, r15,
+ xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
+ xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
+ };
+
+ /**
+ * Register used to construct an instruction-relative address.
+ */
+ public static final Register rip = new Register(32, -1, "rip", SPECIAL);
+
+ public static final Register[] allRegisters = {
+ rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
+ r8, r9, r10, r11, r12, r13, r14, r15,
+ xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
+ xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
+ rip
+ };
+
+ // @formatter:on
+
+ /**
+ * Basic set of CPU features mirroring what is returned from the cpuid instruction. See:
+ * {@code VM_Version::cpuFeatureFlags}.
+ */
+ public static enum CPUFeature {
+ CX8,
+ CMOV,
+ FXSR,
+ HT,
+ MMX,
+ AMD_3DNOW_PREFETCH,
+ SSE,
+ SSE2,
+ SSE3,
+ SSSE3,
+ SSE4A,
+ SSE4_1,
+ SSE4_2,
+ POPCNT,
+ LZCNT,
+ TSC,
+ TSCINV,
+ AVX,
+ AVX2,
+ AES,
+ ERMS,
+ CLMUL,
+ BMI1,
+ BMI2,
+ RTM,
+ ADX,
+ AVX512F,
+ AVX512DQ,
+ AVX512PF,
+ AVX512ER,
+ AVX512CD,
+ AVX512BW
+ }
+
+ private final EnumSet features;
+
+ /**
+ * Set of flags to control code emission.
+ */
+ public static enum Flag {
+ UseCountLeadingZerosInstruction,
+ UseCountTrailingZerosInstruction
+ }
+
+ private final EnumSet flags;
+
+ public AMD64(EnumSet features, EnumSet flags) {
+ super("AMD64", JavaKind.Long, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, cpuRegisters.length + (xmmRegisters.length << XMM_REFERENCE_MAP_SHIFT), 8);
+ this.features = features;
+ this.flags = flags;
+ assert features.contains(CPUFeature.SSE2) : "minimum config for x64";
+ }
+
+ public EnumSet getFeatures() {
+ return features;
+ }
+
+ public EnumSet getFlags() {
+ return flags;
+ }
+
+ @Override
+ public PlatformKind getPlatformKind(JavaKind javaKind) {
+ if (javaKind.isObject()) {
+ return getWordKind();
+ } else {
+ return javaKind;
+ }
+ }
+
+ @Override
+ public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
+ if (!(platformKind instanceof JavaKind)) {
+ return false;
+ }
+
+ JavaKind kind = (JavaKind) platformKind;
+ if (category.equals(CPU)) {
+ switch (kind) {
+ case Boolean:
+ case Byte:
+ case Char:
+ case Short:
+ case Int:
+ case Long:
+ return true;
+ }
+ } else if (category.equals(XMM)) {
+ switch (kind) {
+ case Float:
+ case Double:
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public PlatformKind getLargestStorableKind(RegisterCategory category) {
+ if (category.equals(CPU)) {
+ return JavaKind.Long;
+ } else if (category.equals(XMM)) {
+ return JavaKind.Double;
+ } else {
+ return JavaKind.Illegal;
+ }
+ }
+}
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/overview.html b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/overview.html
new file mode 100644
index 00000000000..6f12f4bc25a
--- /dev/null
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/overview.html
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+The jdk.vm.ci.code project provides an API to the runtime's native code cache.
+It allows installation and execution of native code.
+
+
+
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/AbstractAddress.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/AbstractAddress.java
new file mode 100644
index 00000000000..5b14cfc8c52
--- /dev/null
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/AbstractAddress.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * Abstract base class that represents a platform specific address.
+ */
+public abstract class AbstractAddress {
+}
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java
new file mode 100644
index 00000000000..148d2ac5ec6
--- /dev/null
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import java.nio.*;
+import java.util.*;
+
+import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents a CPU architecture, including information such as its endianness, CPU registers, word
+ * width, etc.
+ */
+public abstract class Architecture {
+
+ /**
+ * The number of entries required in a {@link ReferenceMap} covering all the registers that may
+ * store references. The index of a register in the reference map is given by
+ * {@link Register#getReferenceMapIndex()}.
+ */
+ private final int registerReferenceMapSize;
+
+ /**
+ * The architecture specific type of a native word.
+ */
+ private final PlatformKind wordKind;
+
+ /**
+ * The name of this architecture (e.g. "AMD64", "SPARCv9").
+ */
+ private final String name;
+
+ /**
+ * Array of all available registers on this architecture. The index of each register in this
+ * array is equal to its {@linkplain Register#number number}.
+ */
+ private final Register[] registers;
+
+ /**
+ * The byte ordering can be either little or big endian.
+ */
+ private final ByteOrder byteOrder;
+
+ /**
+ * Whether the architecture supports unaligned memory accesses.
+ */
+ private final boolean unalignedMemoryAccess;
+
+ /**
+ * Mask of the barrier constants denoting the barriers that are not required to be explicitly
+ * inserted under this architecture.
+ */
+ private final int implicitMemoryBarriers;
+
+ /**
+ * Offset in bytes from the beginning of a call instruction to the displacement.
+ */
+ private final int machineCodeCallDisplacementOffset;
+
+ /**
+ * The size of the return address pushed to the stack by a call instruction. A value of 0
+ * denotes that call linkage uses registers instead (e.g. SPARC).
+ */
+ private final int returnAddressSize;
+
+ protected Architecture(String name, PlatformKind wordKind, ByteOrder byteOrder, boolean unalignedMemoryAccess, Register[] registers, int implicitMemoryBarriers, int nativeCallDisplacementOffset,
+ int registerReferenceMapSize, int returnAddressSize) {
+ this.name = name;
+ this.registers = registers;
+ this.wordKind = wordKind;
+ this.byteOrder = byteOrder;
+ this.unalignedMemoryAccess = unalignedMemoryAccess;
+ this.implicitMemoryBarriers = implicitMemoryBarriers;
+ this.machineCodeCallDisplacementOffset = nativeCallDisplacementOffset;
+ this.registerReferenceMapSize = registerReferenceMapSize;
+ this.returnAddressSize = returnAddressSize;
+ }
+
+ /**
+ * Converts this architecture to a string.
+ *
+ * @return the string representation of this architecture
+ */
+ @Override
+ public final String toString() {
+ return getName().toLowerCase();
+ }
+
+ public int getRegisterReferenceMapSize() {
+ return registerReferenceMapSize;
+ }
+
+ /**
+ * Gets the natural size of words (typically registers and pointers) of this architecture, in
+ * bytes.
+ */
+ public int getWordSize() {
+ return wordKind.getSizeInBytes();
+ }
+
+ public PlatformKind getWordKind() {
+ return wordKind;
+ }
+
+ /**
+ * Gets the name of this architecture.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Gets an array of all available registers on this architecture. The index of each register in
+ * this array is equal to its {@linkplain Register#number number}.
+ */
+ public Register[] getRegisters() {
+ return registers.clone();
+ }
+
+ public ByteOrder getByteOrder() {
+ return byteOrder;
+ }
+
+ /**
+ * @return true if the architecture supports unaligned memory accesses.
+ */
+ public boolean supportsUnalignedMemoryAccess() {
+ return unalignedMemoryAccess;
+ }
+
+ /**
+ * Gets the size of the return address pushed to the stack by a call instruction. A value of 0
+ * denotes that call linkage uses registers instead.
+ */
+ public int getReturnAddressSize() {
+ return returnAddressSize;
+ }
+
+ /**
+ * Gets the offset in bytes from the beginning of a call instruction to the displacement.
+ */
+ public int getMachineCodeCallDisplacementOffset() {
+ return machineCodeCallDisplacementOffset;
+ }
+
+ /**
+ * Determines the barriers in a given barrier mask that are explicitly required on this
+ * architecture.
+ *
+ * @param barriers a mask of the barrier constants
+ * @return the value of {@code barriers} minus the barriers unnecessary on this architecture
+ */
+ public final int requiredBarriers(int barriers) {
+ return barriers & ~implicitMemoryBarriers;
+ }
+
+ /**
+ * Determine whether a kind can be stored in a register of a given category.
+ *
+ * @param category the category of the register
+ * @param kind the kind that should be stored in the register
+ */
+ public abstract boolean canStoreValue(RegisterCategory category, PlatformKind kind);
+
+ /**
+ * Return the largest kind that can be stored in a register of a given category.
+ *
+ * @param category the category of the register
+ * @return the largest kind that can be stored in a register {@code category}
+ */
+ public abstract PlatformKind getLargestStorableKind(RegisterCategory category);
+
+ /**
+ * Return the {@link PlatformKind} that is used to store values of a given {@link JavaKind}.
+ */
+ public abstract PlatformKind getPlatformKind(JavaKind javaKind);
+
+ @Override
+ public final boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof Architecture) {
+ Architecture that = (Architecture) obj;
+ if (this.name.equals(that.name)) {
+ assert this.byteOrder.equals(that.byteOrder);
+ assert this.implicitMemoryBarriers == that.implicitMemoryBarriers;
+ assert this.machineCodeCallDisplacementOffset == that.machineCodeCallDisplacementOffset;
+ assert this.registerReferenceMapSize == that.registerReferenceMapSize;
+ assert Arrays.equals(this.registers, that.registers);
+ assert this.returnAddressSize == that.returnAddressSize;
+ assert this.unalignedMemoryAccess == that.unalignedMemoryAccess;
+ assert this.wordKind == that.wordKind;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public final int hashCode() {
+ return name.hashCode();
+ }
+}
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BailoutException.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BailoutException.java
new file mode 100644
index 00000000000..ad26925cc35
--- /dev/null
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BailoutException.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import java.util.*;
+
+/**
+ * Exception thrown when the compiler refuses to compile a method because of problems with the
+ * method. e.g. bytecode wouldn't verify, too big, JSR/ret too complicated, etc. This exception is
+ * not meant to indicate problems with the compiler itself.
+ */
+public class BailoutException extends RuntimeException {
+
+ public static final long serialVersionUID = 8974598793458772L;
+ private final boolean permanent;
+
+ /**
+ * Creates a new {@link BailoutException}.
+ *
+ *
+ * @param args parameters to the formatter
+ */
+ public BailoutException(String format, Object... args) {
+ super(String.format(Locale.ENGLISH, format, args));
+ this.permanent = true;
+ }
+
+ /**
+ * Creates a new {@link BailoutException}.
+ *
+ *
+ * @param args parameters to the formatter
+ */
+ public BailoutException(Throwable cause, String format, Object... args) {
+ super(String.format(Locale.ENGLISH, format, args), cause);
+ this.permanent = true;
+ }
+
+ /**
+ * Creates a new {@link BailoutException}.
+ *
+ * @param permanent specifies whether this exception will occur again if compilation is retried
+ * @param args parameters to the formatter
+ */
+ public BailoutException(boolean permanent, String format, Object... args) {
+ super(String.format(Locale.ENGLISH, format, args));
+ this.permanent = permanent;
+ }
+
+ /**
+ * @return whether this exception will occur again if compilation is retried
+ */
+ public boolean isPermanent() {
+ return permanent;
+ }
+}
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java
new file mode 100644
index 00000000000..e51f83ee18c
--- /dev/null
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents the Java bytecode frame state(s) at a given position including {@link Value locations}
+ * where to find the local variables, operand stack values and locked objects of the bytecode
+ * frame(s).
+ */
+public class BytecodeFrame extends BytecodePosition {
+
+ /**
+ * An array of values representing how to reconstruct the state of the Java frame. This is array
+ * is partitioned as follows:
+ *
+ *
+ *
+ *
Start index (inclusive)
+ *
End index (exclusive)
+ *
Description
+ *
+ *
+ *
0
+ *
numLocals
+ *
Local variables
+ *
+ *
+ *
numLocals
+ *
numLocals + numStack
+ *
Operand stack
+ *
+ *
+ *
numLocals + numStack
+ *
values.length
+ *
Locked objects
+ *
+ *
+ *
+ * Note that the number of locals and the number of stack slots may be smaller than the maximum
+ * number of locals and stack slots as specified in the compiled method.
+ */
+ public final JavaValue[] values;
+
+ /**
+ * An array describing the Java kind of the {@link #values}. It records a kind for the locals
+ * and the operand stack.
+ */
+ public final JavaKind[] slotKinds;
+
+ /**
+ * The number of locals in the values array.
+ */
+ public final int numLocals;
+
+ /**
+ * The number of stack slots in the values array.
+ */
+ public final int numStack;
+
+ /**
+ * The number of locks in the values array.
+ */
+ public final int numLocks;
+
+ /**
+ * True if this is a position inside an exception handler before the exception object has been
+ * consumed. In this case, {@link #numStack} {@code == 1} and {@link #getStackValue(int)
+ * getStackValue(0)} is the location of the exception object. If deoptimization happens at this
+ * position, the interpreter will rethrow the exception instead of executing the bytecode
+ * instruction at this position.
+ */
+ public final boolean rethrowException;
+
+ public final boolean duringCall;
+
+ /**
+ * This BCI should be used for frame states that are built for code with no meaningful BCI.
+ */
+ public static final int UNKNOWN_BCI = -5;
+
+ /**
+ * The BCI for exception unwind. This is synthetic code and has no representation in bytecode.
+ * In contrast with {@link #AFTER_EXCEPTION_BCI}, at this point, if the method is synchronized,
+ * the monitor is still held.
+ */
+ public static final int UNWIND_BCI = -1;
+
+ /**
+ * The BCI for the state before starting to execute a method. Note that if the method is
+ * synchronized, the monitor is not yet held.
+ */
+ public static final int BEFORE_BCI = -2;
+
+ /**
+ * The BCI for the state after finishing the execution of a method and returning normally. Note
+ * that if the method was synchronized the monitor is already released.
+ */
+ public static final int AFTER_BCI = -3;
+
+ /**
+ * The BCI for exception unwind. This is synthetic code and has no representation in bytecode.
+ * In contrast with {@link #UNWIND_BCI}, at this point, if the method is synchronized, the
+ * monitor is already released.
+ */
+ public static final int AFTER_EXCEPTION_BCI = -4;
+
+ /**
+ * This BCI should be used for states that cannot be the target of a deoptimization, like
+ * snippet frame states.
+ */
+ public static final int INVALID_FRAMESTATE_BCI = -6;
+
+ /**
+ * Determines if a given BCI matches one of the placeholder BCI constants defined in this class.
+ */
+ public static boolean isPlaceholderBci(int bci) {
+ return bci < 0;
+ }
+
+ /**
+ * Gets the name of a given placeholder BCI.
+ */
+ public static String getPlaceholderBciName(int bci) {
+ assert isPlaceholderBci(bci);
+ if (bci == BytecodeFrame.AFTER_BCI) {
+ return "AFTER_BCI";
+ } else if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI) {
+ return "AFTER_EXCEPTION_BCI";
+ } else if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
+ return "INVALID_FRAMESTATE_BCI";
+ } else if (bci == BytecodeFrame.BEFORE_BCI) {
+ return "BEFORE_BCI";
+ } else if (bci == BytecodeFrame.UNKNOWN_BCI) {
+ return "UNKNOWN_BCI";
+ } else {
+ assert bci == BytecodeFrame.UNWIND_BCI;
+ return "UNWIND_BCI";
+ }
+ }
+
+ /**
+ * Creates a new frame object.
+ *
+ * @param caller the caller frame (which may be {@code null})
+ * @param method the method
+ * @param bci a BCI within the method
+ * @param rethrowException specifies if the VM should re-throw the pending exception when
+ * deopt'ing using this frame
+ * @param values the frame state {@link #values}
+ * @param numLocals the number of local variables
+ * @param numStack the depth of the stack
+ * @param numLocks the number of locked objects
+ */
+ public BytecodeFrame(BytecodeFrame caller, ResolvedJavaMethod method, int bci, boolean rethrowException, boolean duringCall, JavaValue[] values, JavaKind[] slotKinds, int numLocals, int numStack,
+ int numLocks) {
+ super(caller, method, bci);
+ assert values != null;
+ this.rethrowException = rethrowException;
+ this.duringCall = duringCall;
+ this.values = values;
+ this.slotKinds = slotKinds;
+ this.numLocals = numLocals;
+ this.numStack = numStack;
+ this.numLocks = numLocks;
+ assert !rethrowException || numStack == 1 : "must have exception on top of the stack";
+ }
+
+ /**
+ * Ensure that the frame state is formatted as expected by the JVM, with null or Illegal in the
+ * slot following a double word item. This should really be checked in FrameState itself but
+ * because of Word type rewriting and alternative backends that can't be done.
+ */
+ public boolean validateFormat() {
+ if (caller() != null) {
+ caller().validateFormat();
+ }
+ for (int i = 0; i < numLocals + numStack; i++) {
+ if (values[i] != null) {
+ JavaKind kind = slotKinds[i];
+ if (kind.needsTwoSlots()) {
+ assert slotKinds.length > i + 1 : String.format("missing second word %s", this);
+ assert slotKinds[i + 1] == JavaKind.Illegal : this;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Gets the value representing the specified local variable.
+ *
+ * @param i the local variable index
+ * @return the value that can be used to reconstruct the local's current value
+ */
+ public JavaValue getLocalValue(int i) {
+ return values[i];
+ }
+
+ /**
+ * Gets the value representing the specified stack slot.
+ *
+ * @param i the stack index
+ * @return the value that can be used to reconstruct the stack slot's current value
+ */
+ public JavaValue getStackValue(int i) {
+ return values[i + numLocals];
+ }
+
+ /**
+ * Gets the value representing the specified lock.
+ *
+ * @param i the lock index
+ * @return the value that can be used to reconstruct the lock's current value
+ */
+ public JavaValue getLockValue(int i) {
+ return values[i + numLocals + numStack];
+ }
+
+ /**
+ * Gets the caller of this frame.
+ *
+ * @return {@code null} if this frame has no caller
+ */
+ public BytecodeFrame caller() {
+ return (BytecodeFrame) getCaller();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof BytecodeFrame && super.equals(obj)) {
+ BytecodeFrame that = (BytecodeFrame) obj;
+ // @formatter:off
+ if (this.duringCall == that.duringCall &&
+ this.rethrowException == that.rethrowException &&
+ this.numLocals == that.numLocals &&
+ this.numLocks == that.numLocks &&
+ this.numStack == that.numStack &&
+ Arrays.equals(this.values, that.values)) {
+ return true;
+ }
+ // @formatter:off
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return CodeUtil.append(new StringBuilder(100), this).toString();
+ }
+}
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java
new file mode 100644
index 00000000000..a17b427c5bb
--- /dev/null
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodePosition.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Represents a code position, that is, a chain of inlined methods with bytecode locations, that is
+ * communicated from the compiler to the runtime system. A code position can be used by the runtime
+ * system to reconstruct a source-level stack trace for exceptions and to create
+ * {@linkplain BytecodeFrame frames} for deoptimization.
+ */
+public class BytecodePosition {
+
+ private final BytecodePosition caller;
+ private final ResolvedJavaMethod method;
+ private final int bci;
+
+ /**
+ * Constructs a new object representing a given parent/caller, a given method, and a given BCI.
+ *
+ * @param caller the parent position
+ * @param method the method
+ * @param bci a BCI within the method
+ */
+ public BytecodePosition(BytecodePosition caller, ResolvedJavaMethod method, int bci) {
+ assert method != null;
+ this.caller = caller;
+ this.method = method;
+ this.bci = bci;
+ }
+
+ /**
+ * Converts this code position to a string representation.
+ *
+ * @return a string representation of this code position
+ */
+ @Override
+ public String toString() {
+ return CodeUtil.append(new StringBuilder(100), this).toString();
+ }
+
+ /**
+ * Deep equality test.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj != null && getClass() == obj.getClass()) {
+ BytecodePosition that = (BytecodePosition) obj;
+ if (this.bci == that.bci && Objects.equals(this.getMethod(), that.getMethod()) && Objects.equals(this.caller, that.caller)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return getBCI();
+ }
+
+ /**
+ * @return The location within the method, as a bytecode index. The constant {@code -1} may be
+ * used to indicate the location is unknown, for example within code synthesized by the
+ * compiler.
+ */
+ public int getBCI() {
+ return bci;
+ }
+
+ /**
+ * @return The runtime interface method for this position.
+ */
+ public ResolvedJavaMethod getMethod() {
+ return method;
+ }
+
+ /**
+ * The position where this position has been called, {@code null} if none.
+ */
+ public BytecodePosition getCaller() {
+ return caller;
+ }
+
+ /**
+ * Adds a caller to the current position returning the new position.
+ */
+ public BytecodePosition addCaller(BytecodePosition link) {
+ if (getCaller() == null) {
+ return new BytecodePosition(link, getMethod(), getBCI());
+ } else {
+ return new BytecodePosition(getCaller().addCaller(link), getMethod(), getBCI());
+ }
+ }
+}
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java
new file mode 100644
index 00000000000..c299c8400de
--- /dev/null
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import static jdk.vm.ci.code.ValueUtil.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * A calling convention describes the locations in which the arguments for a call are placed and the
+ * location in which the return value is placed if the call is not void.
+ */
+public class CallingConvention {
+
+ /**
+ * Constants denoting the type of a call for which a calling convention is requested.
+ */
+ public enum Type {
+ /**
+ * A request for the outgoing argument locations at a call site to Java code.
+ */
+ JavaCall(true),
+
+ /**
+ * A request for the incoming argument locations.
+ */
+ JavaCallee(false),
+
+ /**
+ * A request for the outgoing argument locations at a call site to external native code that
+ * complies with the platform ABI.
+ */
+ NativeCall(true);
+
+ /**
+ * Determines if this is a request for the outgoing argument locations at a call site.
+ */
+ public final boolean out;
+
+ public static final Type[] VALUES = values();
+
+ private Type(boolean out) {
+ this.out = out;
+ }
+ }
+
+ /**
+ * The amount of stack space (in bytes) required for the stack-based arguments of the call.
+ */
+ private final int stackSize;
+
+ private final AllocatableValue returnLocation;
+
+ /**
+ * The ordered locations in which the arguments are placed.
+ */
+ private final AllocatableValue[] argumentLocations;
+
+ /**
+ * Creates a description of the registers and stack locations used by a call.
+ *
+ * @param stackSize amount of stack space (in bytes) required for the stack-based arguments of
+ * the call
+ * @param returnLocation the location for the return value or {@link Value#ILLEGAL} if a void
+ * call
+ * @param argumentLocations the ordered locations in which the arguments are placed
+ */
+ public CallingConvention(int stackSize, AllocatableValue returnLocation, AllocatableValue... argumentLocations) {
+ assert argumentLocations != null;
+ assert returnLocation != null;
+ this.argumentLocations = argumentLocations;
+ this.stackSize = stackSize;
+ this.returnLocation = returnLocation;
+ assert verify();
+ }
+
+ /**
+ * Gets the location for the return value or {@link Value#ILLEGAL} if a void call.
+ */
+ public AllocatableValue getReturn() {
+ return returnLocation;
+ }
+
+ /**
+ * Gets the location for the {@code index}'th argument.
+ */
+ public AllocatableValue getArgument(int index) {
+ return argumentLocations[index];
+ }
+
+ /**
+ * Gets the amount of stack space (in bytes) required for the stack-based arguments of the call.
+ */
+ public int getStackSize() {
+ return stackSize;
+ }
+
+ /**
+ * Gets the number of locations required for the arguments.
+ */
+ public int getArgumentCount() {
+ return argumentLocations.length;
+ }
+
+ /**
+ * Gets the locations required for the arguments.
+ */
+ public AllocatableValue[] getArguments() {
+ if (argumentLocations.length == 0) {
+ return argumentLocations;
+ }
+ return argumentLocations.clone();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("CallingConvention[");
+ String sep = "";
+ for (Value op : argumentLocations) {
+ sb.append(sep).append(op);
+ sep = ", ";
+ }
+ if (!returnLocation.equals(Value.ILLEGAL)) {
+ sb.append(" -> ").append(returnLocation);
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+
+ private boolean verify() {
+ for (int i = 0; i < argumentLocations.length; i++) {
+ Value location = argumentLocations[i];
+ assert isStackSlot(location) || isAllocatableValue(location);
+ }
+ return true;
+ }
+}
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java
new file mode 100644
index 00000000000..d0007ac08b4
--- /dev/null
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeCacheProvider.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import jdk.vm.ci.code.CompilationResult.*;
+import jdk.vm.ci.code.DataSection.*;
+import jdk.vm.ci.meta.*;
+
+/**
+ * Access to code cache related details and requirements.
+ */
+public interface CodeCacheProvider {
+
+ /**
+ * Adds the given compilation result as an implementation of the given method without making it
+ * the default implementation.
+ *
+ * @param method a method to which the executable code is begin added
+ * @param compResult the compilation result to be added
+ * @param speculationLog the speculation log to be used
+ * @return a reference to the compiled and ready-to-run code or throws a
+ * {@link BailoutException} if the code installation failed
+ */
+ InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode);
+
+ /**
+ * Sets the given compilation result as the default implementation of the given method.
+ *
+ * @param method a method to which the executable code is begin added
+ * @param compResult the compilation result to be added
+ * @return a reference to the compiled and ready-to-run code or null if the code installation
+ * failed
+ */
+ InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult);
+
+ /**
+ * Gets a name for a {@link Mark} mark.
+ */
+ default String getMarkName(Mark mark) {
+ return String.valueOf(mark.id);
+ }
+
+ /**
+ * Gets a name for the {@linkplain Call#target target} of a {@link Call}.
+ */
+ default String getTargetName(Call call) {
+ return String.valueOf(call.target);
+ }
+
+ /**
+ * Gets the register configuration to use when compiling a given method.
+ */
+ RegisterConfig getRegisterConfig();
+
+ /**
+ * Minimum size of the stack area reserved for outgoing parameters. This area is reserved in all
+ * cases, even when the compiled method has no regular call instructions.
+ *
+ * @return the minimum size of the outgoing parameter area in bytes
+ */
+ int getMinimumOutgoingSize();
+
+ /**
+ * Determines if a {@link DataPatch} should be created for a given primitive constant that is
+ * part of a {@link CompilationResult}. A data patch is always created for an object constant.
+ */
+ boolean needsDataPatch(JavaConstant constant);
+
+ /**
+ * Create a {@link Data} item for one or more {@link Constant Constants}, that can be used in a
+ * {@link DataPatch}. If more than one {@link Constant} is given, then they are tightly packed
+ * into a single {@link Data} item.
+ */
+ Data createDataItem(Constant... constants);
+
+ /**
+ * Gets a description of the target architecture.
+ */
+ TargetDescription getTarget();
+
+ /**
+ * Create a new speculation log for the target runtime.
+ */
+ SpeculationLog createSpeculationLog();
+}
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeUtil.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeUtil.java
new file mode 100644
index 00000000000..bae5a53b8e7
--- /dev/null
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CodeUtil.java
@@ -0,0 +1,471 @@
+/*
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.vm.ci.code;
+
+import java.util.*;
+
+import jdk.vm.ci.meta.*;
+
+/**
+ * Miscellaneous collection of utility methods used by {@code jdk.vm.ci.code} and its clients.
+ */
+public class CodeUtil {
+
+ public static final String NEW_LINE = String.format("%n");
+
+ public static final int K = 1024;
+ public static final int M = 1024 * 1024;
+
+ public static boolean isOdd(int n) {
+ return (n & 1) == 1;
+ }
+
+ public static boolean isEven(int n) {
+ return (n & 1) == 0;
+ }
+
+ /**
+ * Checks whether the specified integer is a power of two.
+ *
+ * @param val the value to check
+ * @return {@code true} if the value is a power of two; {@code false} otherwise
+ */
+ public static boolean isPowerOf2(int val) {
+ return val > 0 && (val & val - 1) == 0;
+ }
+
+ /**
+ * Checks whether the specified long is a power of two.
+ *
+ * @param val the value to check
+ * @return {@code true} if the value is a power of two; {@code false} otherwise
+ */
+ public static boolean isPowerOf2(long val) {
+ return val > 0 && (val & val - 1) == 0;
+ }
+
+ /**
+ * Computes the log (base 2) of the specified integer, rounding down. (E.g {@code log2(8) = 3},
+ * {@code log2(21) = 4} )
+ *
+ * @param val the value
+ * @return the log base 2 of the value
+ */
+ public static int log2(int val) {
+ assert val > 0;
+ return (Integer.SIZE - 1) - Integer.numberOfLeadingZeros(val);
+ }
+
+ /**
+ * Computes the log (base 2) of the specified long, rounding down. (E.g {@code log2(8) = 3},
+ * {@code log2(21) = 4})
+ *
+ * @param val the value
+ * @return the log base 2 of the value
+ */
+ public static int log2(long val) {
+ assert val > 0;
+ return (Long.SIZE - 1) - Long.numberOfLeadingZeros(val);
+ }
+
+ /**
+ * Narrow an integer value to a given bit width, and return the result as a signed long.
+ *
+ * @param value the value
+ * @param resultBits the result bit width
+ * @return {@code value} interpreted as {@code resultBits} bit number, encoded as signed long
+ */
+ public static long narrow(long value, int resultBits) {
+ long ret = value & mask(resultBits);
+ return signExtend(ret, resultBits);
+ }
+
+ /**
+ * Sign extend an integer.
+ *
+ * @param value the input value
+ * @param inputBits the bit width of the input value
+ * @return a signed long with the same value as the signed {@code inputBits}-bit number
+ * {@code value}
+ */
+ public static long signExtend(long value, int inputBits) {
+ if (inputBits < 64) {
+ if ((value >>> (inputBits - 1) & 1) == 1) {
+ return value | (-1L << inputBits);
+ } else {
+ return value & ~(-1L << inputBits);
+ }
+ } else {
+ return value;
+ }
+ }
+
+ /**
+ * Zero extend an integer.
+ *
+ * @param value the input value
+ * @param inputBits the bit width of the input value
+ * @return an unsigned long with the same value as the unsigned {@code inputBits}-bit number
+ * {@code value}
+ */
+ public static long zeroExtend(long value, int inputBits) {
+ if (inputBits < 64) {
+ return value & ~(-1L << inputBits);
+ } else {
+ return value;
+ }
+ }
+
+ /**
+ * Convert an integer to long.
+ *
+ * @param value the input value
+ * @param inputBits the bit width of the input value
+ * @param unsigned whether the values should be interpreted as signed or unsigned
+ * @return a long with the same value as the {@code inputBits}-bit number {@code value}
+ */
+ public static long convert(long value, int inputBits, boolean unsigned) {
+ if (unsigned) {
+ return zeroExtend(value, inputBits);
+ } else {
+ return signExtend(value, inputBits);
+ }
+ }
+
+ /**
+ * Get a bitmask with the low {@code bits} bit set and the high {@code 64 - bits} bit clear.
+ */
+ public static long mask(int bits) {
+ assert 0 <= bits && bits <= 64;
+ if (bits == 64) {
+ return 0xffffffffffffffffL;
+ } else {
+ return (1L << bits) - 1;
+ }
+ }
+
+ /**
+ * Get the minimum value representable in a {@code bits} bit signed integer.
+ */
+ public static long minValue(int bits) {
+ assert 0 < bits && bits <= 64;
+ return -1L << (bits - 1);
+ }
+
+ /**
+ * Get the maximum value representable in a {@code bits} bit signed integer.
+ */
+ public static long maxValue(int bits) {
+ assert 0 < bits && bits <= 64;
+ return mask(bits - 1);
+ }
+
+ /**
+ * Formats the values in a frame as a tabulated string.
+ *
+ * @param frame
+ * @return the values in {@code frame} as a tabulated string
+ */
+ public static String tabulateValues(BytecodeFrame frame) {
+ int cols = Math.max(frame.numLocals, Math.max(frame.numStack, frame.numLocks));
+ assert cols > 0;
+ ArrayList