diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 10146e2ba8a..6ed900e384c 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -1,2 +1,3 @@ cfeea66a3fa8ca3686a7cfa2d0ce8ab0169f168d jdk7-b24 cbc8ad9dd0e085a607427ea35411990982f19a36 jdk7-b25 +9410f77cc30c604d1caf7c9fe3a57fa19e1acbe8 jdk7-b26 diff --git a/README-builds.html b/README-builds.html index 096d192e2b9..a2cf768e122 100644 --- a/README-builds.html +++ b/README-builds.html @@ -1,1447 +1,1587 @@ - -OpenJDK Build README - - -
- -
-

OpenJDK Build README

-
- - -
- -

Introduction

- -
-

- This README file contains build instructions for the - OpenJDK. - Building the source code for the - OpenJDK - requires - a certain degree of technical expertise. -

- - -
- -

Contents

- -
- -
- - -
- -

Minimum Build Environments

- -
-

- This file often describes specific requirements for what we call the - "minimum build environments" (MBE) for the JDK. - Building with the MBE will generate the most compatible - bits that install on, and run correctly on, the most variations - of the same base OS and hardware architecture. - These usually represent what is often called the - least common denominator platforms. - It is understood that most developers will NOT be using these - specific platforms, and in fact creating these specific platforms - may be difficult due to the age of some of this software. -

- -

- The minimum OS and C/C++ compiler versions needed for building the - OpenJDK: -

-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + OpenJDK Build README + + + +
Base OS and ArchitectureOSCompiler
Linux X86 (32bit)Red Hat Enterprise Linux 4 gcc 4
Linux X64 (64bit)Red Hat Enterprise Linux 4 gcc 4
Solaris SPARC (32bit)Solaris 10 + patches -
- See SunSolve for patch downloads. -
Sun Studio 11
Solaris SPARCV9 (64bit)Solaris 10 + patches -
- See SunSolve for patch downloads. -
Sun Studio 11
Solaris X86 (32bit)Solaris 10 + patches -
- See SunSolve for patch downloads. -
Sun Studio 11
Solaris X64 (64bit)Solaris 10 + patches -
- See SunSolve for patch downloads. -
Sun Studio 11
Windows X86 (32bit)Windows XPMicrosoft Visual Studio .NET 2003 Professional
Windows X64 (64bit)Windows Server 2003 - Enterprise x64 EditionMicrosoft Platform SDK - April 2005
+ + + + + +
+ + OpenJDK + +
+

OpenJDK Build README

+
-
-
- - -
- -

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

- -

Fedora

- -
- TBD -
- -

Debian

- -
- TBD -
- -

Ubuntu

- -
-

- In addition to needing the Bootstrap JDK and the Binary Plugs, - when building on Ubuntu you will need to - make sure certain packages are installed. - In particular, certain X11 packages, make, m4, gawk, gcc 4, - binutils, cups, freetype - and alsa. - -

Ubuntu 6.06

- -

- The following list of packages for Ubuntu 6.06 is a working set that - does appear to work. - -

- Note that it's quite possible that some of these - packages are not required, so anyone discovering that some of the - packages listed below are NOT required, - please let the - OpenJDK - team know. -

- All the packages below can be installed with the - Synaptic Package manager provided with the base Ubuntu 6.06 release. - -

- -
- -

Ubuntu 7.04

- -

- Using the Synaptic Package Manager, download the following - packages (double indented packages are automatically aquired - due to package dependencies): - -

- -
-
- - -
- -

Source Directory Structure

- -
-

- The source code for the OpenJDK is delivered in a set of - directories: - hotspot, - langtools, - corba, - jaxws, - jaxp, - and - jdk. - The hotspot directory contains the source code and make - files for building the OpenJDK Hotspot Virtual Machine. - The langtools directory contains the source code and make - files for building the OpenJDK javac and language tools. - The corba directory contains the source code and make - files for building the OpenJDK Corba files. - The jaxws directory contains the source code and make - files for building the OpenJDK JAXWS files. - The jaxp directory contains the source code and make - files for building the OpenJDK JAXP files. - The jdk directory contains the source code and make files for - building the OpenJDK runtime libraries and misc files. - The top level Makefile - is used to build the entire OpenJDK. -

- - -
- -

Build Information

- -
-

- Building the - OpenJDK - is done with a gmake - command line and various - environment or make variable settings that direct the make rules - to where various components have been installed. - Where possible the makefiles will attempt to located the various - components in the default locations or any component specific - variable settings. - When the normal defaults fail or components cannot be found, - the various - ALT_* variables (alternates) - can be used to help the makefiles locate components. -

- Refer to the bash/sh/ksh setup file - jdk/make/jdk_generic_profile.sh - if you need help in setting up your environment variables. - A build could be as simple as: -

-

+        
+ +
+

Minimum Build Environments

+
+ This file often describes specific requirements for what we call the + "minimum build environments" (MBE) for the JDK. + Building with the MBE will generate the most compatible + bits that install on, and run correctly on, the most variations + of the same base OS and hardware architecture. + These usually represent what is often called the + least common denominator platforms. + It is understood that most developers will NOT be using these + specific platforms, and in fact creating these specific platforms + may be difficult due to the age of some of this software. +

+ The minimum OS and C/C++ compiler versions needed for building the + OpenJDK: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Base OS and ArchitectureOSCompiler
Linux X86 (32bit)Red Hat Enterprise Linux 4 gcc 4
Linux X64 (64bit)Red Hat Enterprise Linux 4 gcc 4
Solaris SPARC (32bit)Solaris 10 + patches +
+ See + SunSolve for patch downloads. +
Sun Studio 11
Solaris SPARCV9 (64bit)Solaris 10 + patches +
+ See + SunSolve for patch downloads. +
Sun Studio 11
Solaris X86 (32bit)Solaris 10 + patches +
+ See + SunSolve for patch downloads. +
Sun Studio 11
Solaris X64 (64bit)Solaris 10 + patches +
+ See + SunSolve for patch downloads. +
Sun Studio 11
Windows X86 (32bit)Windows XPMicrosoft Visual Studio .NET 2003 Professional
Windows X64 (64bit)Windows Server 2003 - Enterprise x64 EditionMicrosoft Platform SDK - April 2005
+

+ +
+

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

Fedora

+
+ TBD +
+ +

Debian

+
+ TBD +
+ +

Ubuntu

+
+ In addition to needing the Bootstrap JDK and the Binary Plugs, + when building on Ubuntu you will need to + make sure certain packages are installed. + In particular, certain X11 packages, make, m4, gawk, gcc 4, + binutils, cups, freetype + and alsa. + +

Ubuntu 6.06

+

+ The following list of packages for Ubuntu 6.06 is a working set that + does appear to work. +

+ Note that it's quite possible that some of these + packages are not required, so anyone discovering that some of the + packages listed below are NOT required, + please let the + OpenJDK + team know. +

+ All the packages below can be installed with the + Synaptic Package manager provided with the base Ubuntu 6.06 release. +

+
    +
  • binutils (2.16.1cvs20060117-1ubuntu2.1)
  • +
  • cpp (4:4.0.3-1)
  • +
  • cpp-4.0 (4.0.3-1ubuntu5)
  • +
  • libfreetype6-dev
  • +
  • g++ (4:4.0.3-1)
  • +
  • g++-4.0 (4.0.3-1ubuntu5)
  • +
  • gawk (1:3.1.5-2build1)
  • +
  • gcc (4:4.0.3-1)
  • +
  • gcc-4.0 (4.0.3-1ubuntu5)
  • +
  • libasound2-dev (1.0.10-2ubuntu4)
  • +
  • libc6 (2.3.6-0ubuntu20) to 2.3.6-0ubuntu20.4
  • +
  • libc6-dev (2.3.6-0ubuntu20.4)
  • +
  • libc6-i686 (2.3.6-0ubuntu20) to 2.3.6-0ubuntu20.4
  • +
  • libcupsys2-dev (1.2.2-0ubuntu0.6.06)
  • +
  • libgcrypt11-dev (1.2.2-1)
  • +
  • libgnutls-dev (1.2.9-2ubuntu1.1)
  • +
  • libgnutls12 (1.2.9-2ubuntu1) to 1.2.9-2ubuntu1.1
  • +
  • libgpg-error-dev (1.1-4)
  • +
  • libice-dev (2:1.0.0-0ubuntu2)
  • +
  • liblockfile1 (1.06.1)
  • +
  • libopencdk8-dev (0.5.7-2)
  • +
  • libpopt-dev (1.7-5)
  • +
  • libsm-dev (2:1.0.0-0ubuntu2)
  • +
  • libstdc++6-4.0-dev (4.0.3-1ubuntu5)
  • +
  • libtasn1-2-dev (0.2.17-1ubuntu1)
  • +
  • libx11-dev (2:1.0.0-0ubuntu9)
  • +
  • libxau-dev (1:1.0.0-0ubuntu4)
  • +
  • libxaw-headers (2:1.0.1-0ubuntu3)
  • +
  • libxaw7-dev (2:1.0.1-0ubuntu3)
  • +
  • libxdmcp-dev (1:1.0.0-0ubuntu2)
  • +
  • libxext-dev (2:1.0.0-0ubuntu4)
  • +
  • libxi-dev (2:1.0.0-0ubuntu3)
  • +
  • libxmu-dev (2:1.0.0-0ubuntu3)
  • +
  • libxmu-headers (2:1.0.0-0ubuntu3)
  • +
  • libxmuu-dev (2:1.0.0-0ubuntu3)
  • +
  • libxp-dev (6.8.2-11ubuntu2)
  • +
  • libxpm-dev (1:3.5.4.2-0ubuntu3)
  • +
  • libxrandr-dev (1:1.1.0.2-0ubuntu4)
  • +
  • libxt-dev (1:1.0.0-0ubuntu3)
  • +
  • libxtrap-dev (2:1.0.0-0ubuntu2)
  • +
  • libxtst-dev (2:1.0.1-0ubuntu2)
  • +
  • libxv-dev (2:1.0.1-0ubuntu3)
  • +
  • linux-kernel-headers (2.6.11.2-0ubuntu18)
  • +
  • m4 (1.4.4-1)
  • +
  • make (3.80+3.81.b4-1)
  • +
  • ssl-cert (1.0.13)
  • +
  • x-dev (7.0.4-0ubuntu2)
  • +
  • x11proto-core-dev (7.0.4-0ubuntu2)
  • +
  • x11proto-input-dev (1.3.2-0ubuntu2)
  • +
  • x11proto-kb-dev (1.0.2-0ubuntu2)
  • +
  • x11proto-randr-dev (1.1.2-0ubuntu2)
  • +
  • x11proto-record-dev (1.13.2-0ubuntu2)
  • +
  • x11proto-trap-dev (3.4.3-0ubuntu2)
  • +
  • x11proto-video-dev (2.2.2-0ubuntu2)
  • +
  • x11proto-xext-dev (7.0.2-0ubuntu2)
  • +
  • xlibs-dev (7.0.0-0ubuntu45)
  • +
  • zlib1g-dev (1:1.2.3-6ubuntu4)
  • +
+
+ +

Ubuntu 7.04

+

+ Using the Synaptic Package Manager, download the following + packages (double indented packages are automatically aquired + due to package dependencies): +

+
    +
  • build-essential
  • +
      +
    • dpkg-dev
    • +
    • g++
    • +
    • g++-4.1
    • +
    • libc6-dev
    • +
    • libstdc++6.4.1-dev
    • +
    • linux-libc-dev
    • +
    +
  • gawk
  • +
  • m4
  • +
  • libasound2-dev
  • +
  • libcupsys2-dev
  • +
      +
    • libgcrypt11-dev
    • +
    • lgnutls-dev
    • +
    • libgpg-error-dev
    • +
    • liblzo-dev
    • +
    • libopencdk8-dev
    • +
    • libpopt-dev
    • +
    • libtasn1-3-dev
    • +
    • zlib1g-dev
    • +
    +
  • sun-java6-jdk
  • +
      +
    • java-common
    • +
    • libltdl3
    • +
    • odbcinst1debian1
    • +
    • sun-java6-bin
    • +
    • sun-java6-jre
    • +
    • unixodbc
    • +
    +
  • xlibs-dev
  • +
      +
    • (many)
    • +
    +
  • x11proto-print-dev
  • +
  • libxaw7-dev
  • +
      +
    • libxaw-headers
    • +
    +
  • libxp-dev
  • +
  • libfreetype6-dev
  • +
+
+
+ +
+

Source Directory Structure

+
+

+ The source code for the OpenJDK is delivered in a set of + directories: + hotspot, + langtools, + corba, + jaxws, + jaxp, + and + jdk. + The hotspot directory contains the source code and make + files for building the OpenJDK Hotspot Virtual Machine. + The langtools directory contains the source code and make + files for building the OpenJDK javac and language tools. + The corba directory contains the source code and make + files for building the OpenJDK Corba files. + The jaxws directory contains the source code and make + files for building the OpenJDK JAXWS files. + The jaxp directory contains the source code and make + files for building the OpenJDK JAXP files. + The jdk directory contains the source code and make files for + building the OpenJDK runtime libraries and misc files. + The top level Makefile + is used to build the entire OpenJDK. +

+ +
+

Build Information

+
+ Building the OpenJDK + is done with a gmake + command line and various + environment or make variable settings that direct the make rules + to where various components have been installed. + Where possible the makefiles will attempt to located the various + components in the default locations or any component specific + variable settings. + When the normal defaults fail or components cannot be found, + the various + ALT_* variables (alternates) + can be used to help the makefiles locate components. +

+ Refer to the bash/sh/ksh setup file + jdk/make/jdk_generic_profile.sh + if you need help in setting up your environment variables. + A build could be as simple as: +

+

                 bash
                 . jdk/make/jdk_generic_profile.sh
                 gmake sanity && gmake
-        
-
-

- Of course ksh or sh would work too. - But some customization will probably be necessary. - The sanity rule will make some basic checks on build - dependencies and generate appropriate warning messages - regarding missing, out of date, or newer than expected components - found on your system. -

- - -
- -

GNU make (gmake)

- -
-

- The Makefiles in the - OpenJDK - are only valid when used with the - GNU version of the utility command make - (gmake). - A few notes about using GNU make: -

    -
  • - In general, you need GNU make version 3.78.1 or newer. -
  • -
  • - Place the location of the GNU make binary in the PATH. -
  • -
  • - Linux: - The /usr/bin/make command should work fine for you. -
  • -
  • - Solaris: - Do NOT use /usr/bin/make on Solaris. - If your Solaris system has the software - from the Solaris Companion CD installed, - you should use gmake - which will be located in either the /opt/sfw/bin or - /usr/sfw/bin directory. -
  • -
  • - Windows: - Make sure you start your build inside a bash/sh/ksh shell. -
    - WARNING: Watch out for make version 3.81, it may - not work due to a lack of support for drive letter paths - like C:/. Use a 3.80 version, or find a newer - version that has this problem fixed. -
  • -
-

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

- - -
- -

Basic Linux System Setup

- -
-

- i586 only: - The minimum recommended hardware for building the Linux version - is a Pentium class processor or better, at least 256 MB of RAM, and - approximately 1.5 GB of free disk space. -

- X64 only: - The minimum recommended hardware for building the Linux - version is an AMD Opteron class processor, at least 512 MB of RAM, and - approximately 4 GB of free disk space. -

- The build will use the tools contained in - /bin and - /usr/bin - of a standard installation of the Linux operating environment. - You should ensure that these directories are in your - PATH. -

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

- - - -

Basic Linux Check List

- -
-
    -
  1. - Install the - Bootstrap JDK, set - ALT_BOOTDIR. -
  2. -
  3. - Install the - Binary Plugs, set - ALT_BINARY_PLUGS_PATH. -
  4. -
  5. - Install or upgrade the FreeType development - package. -
  6. -
-
- - -
- -

Basic Solaris System Setup

- -
-

- The minimum recommended hardware for building the - Solaris SPARC version is an UltraSPARC with 512 MB of RAM. - For building - the Solaris x86 version, a Pentium class processor or better and at - least 128 MB of RAM are recommended. - Approximately 1.4 GB of free disk - space is needed for a 32-bit build. -

- If you are building the 64bit version, you should - run the command "isainfo -v" to verify that you have a - 64-bit installation. - An additional 7 GB of free disk space is needed - for a 64-bit build. -

- The build uses the tools contained in /usr/ccs/bin - and /usr/bin of a standard developer or full installation of - the Solaris operating environment. -

- - - -

Basic Solaris Check List

- -
-
    -
  1. - Install the - Bootstrap JDK, set - ALT_BOOTDIR. -
  2. -
  3. - Install the - Binary Plugs, set - ALT_BINARY_PLUGS_PATH. -
  4. -
  5. - Install the - Sun Studio Compilers, set - ALT_COMPILER_PATH. -
  6. -
  7. - Install the - CUPS Include files, set - ALT_CUPS_HEADERS_PATH. -
  8. -
-
- - -
- -

Basic Windows System Setup

- -
-

- i586 only: - The minimum recommended hardware for building the 32bit or X86 - Windows version is an Pentium class processor or better, at least - 512 MB of RAM, and approximately 600 MB of free disk space. - - NOTE: The Windows 2000 build machines need to use the - file system NTFS. - Build machines formatted to FAT32 will not work - because FAT32 doesn't support case-sensitivity in file names. - -

- X64 only: - The minimum recommended hardware for building - the Windows X64 version is an AMD Opteron class processor, at least 1 - GB of RAM, and approximately 10 GB of free disk space. -

- - - -

Windows Paths

- -
-

- Windows: - Note that GNU make is a historic utility and is based very - heavily on shell scripting, so it does not tolerate the Windows habit - of having spaces in pathnames or the use of the \characters in pathnames. - Luckily on most Windows systems, you can use /instead of \, and - there is always a 'short' pathname without spaces for any path that - contains spaces. - Unfortunately, this short pathname can be somewhat dynamic and the - formula is difficult to explain. - You can use cygpath utility to map pathnames with spaces - or the \character into the C:/ style of pathname - (called 'mixed'), e.g. - cygpath -s -m "path". -

- The makefiles will try to translate any pathnames supplied - to it into the C:/ style automatically. -

- Note that 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 uses ":"). - 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. - So be careful with paths on Windows. -

- - - -

Basic Windows Check List

- -
-
    -
  1. - Install the - CYGWIN product. -
  2. -
  3. - Install the - Bootstrap JDK, set - ALT_BOOTDIR. -
  4. -
  5. - Install the - Binary Plugs, set - ALT_BINARY_PLUGS_PATH.. -
  6. -
  7. - Install the - Microsoft Visual Studio .NET 2003 Professional or the - Microsoft Platform SDK. -
  8. -
  9. - Setup all environment variables for compilers - (see compilers). -
  10. -
  11. - Install - Microsoft DirectX SDK. -
  12. -
-
- - -
- -

Build Dependencies

- -
-

- Depending on the platform, the - OpenJDK - build process has some basic - dependencies on components not part of the - OpenJDK - sources. - Some of these are specific to a platform, some even specific to - an architecture. - Each dependency will have a set of ALT variables that can be set - to tell the makefiles where to locate the component. - In most cases setting these ALT variables may not be necessary - and the makefiles will find defaults on the system in standard - install locations or through component specific variables. - -

Bootstrap JDK

- -
-

- All - OpenJDK - builds require access to the previously released - JDK 6, this is often called a bootstrap JDK. - The JDK 6 binaries can be downloaded from Sun's - JDK 6 download site. - For build performance reasons - is very important that this bootstrap JDK be made available on the - local disk of the machine doing the build. - You should always set - ALT_BOOTDIR - to point to the location of - the bootstrap JDK installation, this is the directory pathname - that contains a bin, lib, and include - It's also a good idea to also place its bin directory - in the PATH environment variable, although it's - not required. -

- Solaris: - Some pre-installed JDK images may be available to you in the - directory /usr/jdk/instances. - If you don't set - ALT_BOOTDIR - the makefiles will look in that location for a JDK it can use. -

- -

Binary Plugs

- -
-

- Not all of the source code that makes up the JDK is available - under an open-source license. - In order to build an OpenJDK binary from source code, - you must first download and install the appropriate - binary plug bundles from the OpenJDK, go to the - OpenJDK site and select - the "Bundles(7)" link. - During the OpenJDK build process these "binary plugs" - for the encumbered components will be copied into your - resulting OpenJDK binary build image. - These binary plug files are only for the purpose of - building an OpenJDK binary. - Make sure you set - ALT_BINARY_PLUGS_PATH - to the root of this installation. -

- -

Certificate Authority File (cacert)

- -
-

- See - www.wikipedia.org/wiki/CAcert - 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. - The variable - ALT_CACERTS_FILE - can be used to override the default location of the - cacerts file that will get placed in your build. - By default an empty cacerts file is provided and that should be - fine for most JDK developers. -

- -

Compilers

- -
- - - Linux gcc/binutils - - -
-

- The GNU gcc compiler version should be 3.2.2 or newer. - The binutils package should be 2.11.93.0.2-11 or newer. - The compiler used should be the default compiler installed - in /usr/bin. -

- - Solaris: Sun Studio - -
-

- At a minimum, the - - Sun Studio 11 Compilers - (containing version 5.8 of the C and C++ compilers) is required, - with patches from the - - SunSolve web site. -

- Set - ALT_COMPILER_PATH - to point to the location of - the compiler binaries, and place this location in the PATH. -

- The Sun Studio Express compilers at: - - Sun Studio Express Download site - are also an option, although these compilers have not - been extensively used yet. -

- - - Windows i586: Microsoft Visual Studio .NET 2003 Professional - - -
-

- The 32-bit - OpenJDK - Windows build - requires Microsoft Visual Studio .NET 2003 (VS2003) Professional - Edition compiler. - The compiler and other tools are expected to reside - in the location defined by the variable VS71COMNTOOLS which - is set by the Microsoft Visual Studio .NET installer. -

- Once the compiler is installed, - it is recommended that you run VCVARS32.BAT - to set the compiler environment variables - MSVCDIR, - INCLUDE, - LIB, and - PATH - prior to building the - OpenJDK. - The above environment variables MUST be set. -

- The Microsoft Visual Studio .NET 2005 (VS2005) compiler - will not work at this time due to the new runtime dll - and the manifest requirements. -

- - - Windows X64: Microsoft Platform SDK April 2005 - - -
-

- On X64, - the Microsoft Platform Software - Development Kit (SDK), April 2005 Edition compiler, is required for - building the - OpenJDK - because it contains the C/C++ compiler. - You will need to minimally install the Core SDK and - the MDAC SDK features of this compiler. -

- Once the Platform SDK is installed, - it is recommended that you run SetEnv.Cmd /X64 - to set the compiler environment variables - MSSDK, - MSTOOLS, - INCLUDE, - LIB, and - PATH - prior to building the - OpenJDK. - The above environment variables MUST be set. -

- Note that this compiler may say it's version is a - Microsoft Visual Studio .NET 2005 (VS2005), but be careful, - it will not match the official VS2005 product. - This Platform SDK compiler is only used on X64 builds. -

- -
- -

Common UNIX Printing System (CUPS) Headers (Solaris & Linux)

- -
-

- Solaris: - CUPS header files are required for building the - OpenJDK on Solaris. - 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 - /opt/sfw/cups. -

- Linux: - CUPS header files are required for building the - OpenJDK on Linux. - The Linux header files are usually available from a "cups" - development package, it's recommended that you try and use - the package provided by the particular version of Linux that - you are using. -

- The CUPS header files can always be downloaded from - www.cups.org. - The variable - ALT_CUPS_HEADERS_PATH - can be used to override the default location of the - CUPS Header files. -

- -

FreeType 2

- -
-

- Version 2.3 or newer of FreeType is required for building the OpenJDK. - 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 FreeType library and header files. -

-

- You can always download latest FreeType version from the - FreeType website. -

-

- Makefiles will try to pick FreeType from /usr/lib and /usr/include. - In case it is installed elsewhere you will need to set environment - variables - ALT_FREETYPE_LIB_PATH - and - ALT_FREETYPE_HEADERS_PATH - to refer to place where library and header files are installed. -

-
- -

Advanced Linux Sound Architecture (ALSA) (Linux only)

- -
-

- Linux only: - 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, it's recommended that you try and use - the package provided by the particular version of Linux that - you are using. - The makefiles will check this emit a sanity error if it is - missing or the wrong version. - As a last resort you can go to the - - Advanced Linux Sound Architecture Site. -

- -

Windows Specific Dependencies

- -
- - Unix Command Tools (CYGWIN) - -
-

- The - OpenJDK - requires access to a set of unix command tools - on Windows which can be supplied by - CYGWIN. -

- The - OpenJDK - build - requires CYGWIN version 1.5.12 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 NamePackageDescription
ar.exeDevelbinutils: The GNU assembler, linker and binary - utilities
make.exeDevelmake: The GNU version of the 'make' utility
m4.exeInterpretersm4: GNU implementation of the traditional Unix macro - processor
cpio.exeUtilscpio: A program to manage archives of files
file.exeUtilsfile: Determines file type using 'magic' numbers
+
+

+ Of course ksh or sh would work too. + But some customization will probably be necessary. + The sanity rule will make some basic checks on build + dependencies and generate appropriate warning messages + regarding missing, out of date, or newer than expected components + found on your system.

- - - Microsoft DirectX 9.0 SDK header files and libraries - - + +
+

GNU make (gmake)

+ The Makefiles in the OpenJDK are only valid when used with the + GNU version of the utility command make + (gmake). + A few notes about using GNU make: +
    +
  • + In general, you need GNU make version 3.78.1 or newer. +
  • +
  • + Place the location of the GNU make binary in the PATH. +
  • +
  • + Linux: + The /usr/bin/make command should work fine for you. +
  • +
  • + Solaris: + Do NOT use /usr/bin/make on Solaris. + If your Solaris system has the software + from the Solaris Companion CD installed, + you should use gmake + which will be located in either the /opt/sfw/bin or + /usr/sfw/bin directory. +
  • +
  • + Windows: + Make sure you start your build inside a bash/sh/ksh shell. +
    + WARNING: Watch out for make version 3.81, it may + not work due to a lack of support for drive letter paths + like C:/. See + section on gmake. + Use a 3.80 version, or find a newer + version that has this problem fixed. + The older 3.80 version of make.exe can be downloaded with this + + link. + Also see the + + mozilla developer center + on this topic. +
  • +

- Microsoft DirectX 9.0 SDK (Summer 2004) - headers are required for building - OpenJDK. - This SDK can be downloaded from - - Microsoft DirectX 9.0 SDK (Summer 2004). - If the link above becomes obsolete, the SDK can be found from - the Microsoft Download Site - (search with "DirectX 9.0 SDK Update Summer 2004"). - The location of this SDK can be set with - ALT_DXSDK_PATH - but it's normally found via the DirectX environment variable - DXSDK_DIR. + 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/.

- - - MSVCRT.DLL - - -
-

+ +


+

Basic Linux System Setup

+
i586 only: - The - OpenJDK - 32bit build requires - access to MSVCRT.DLL - version 6.00.8337.0 or newer. - If the MSVCRT.DLL is not installed in - the system32 directory set the - ALT_MSVCRT_DLL_PATH - variable to the location. + The minimum recommended hardware for building the Linux version + is a Pentium class processor or better, at least 256 MB of RAM, and + approximately 1.5 GB of free disk space.

X64 only: - The OpenJDK 64bit build requires access to - MSVCRT.DLL version 7.0.3790.0 or newer, which is - usually supplied by the - Platform SDK. - If it is not available from the Platform SDK, - set the - ALT_MSVCRT_DLL_PATH - variable to the location. -

- - - MSVCR71.DLL - - -
+ The minimum recommended hardware for building the Linux + version is an AMD Opteron class processor, at least 512 MB of RAM, and + approximately 4 GB of free disk space. +

+ The build will use the tools contained in + /bin and + /usr/bin + of a standard installation of the Linux operating environment. + You should ensure that these directories are in your + PATH.

- i586 only: - The - OpenJDK - build requires access to - MSVCR71.DLL version 7.10.3052.4 or newer which should be - supplied by the - Visual Studio product - If the MSVCR71.DLL is not available from the - Visual Studio product - set the - ALT_MSVCR71_DLL_PATH - variable to the location. + 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.

- -
- - -
- - -
- -

Creating the Build

- -
-

- Once a machine is setup to build the - OpenJDK, - the steps to create the - build are fairly simple. - The various ALT settings can either be made into variables - or can be supplied on the - gmake - command. -

-

    -
  1. Use the sanity rule to double check all the ALT settings: -
    - - gmake - sanity - [ARCH_DATA_MODEL=32 or 64] - [other "ALT_" overrides] - -
    -
  2. -
  3. Start the build with the command: -
    - - gmake - [ARCH_DATA_MODEL=32 or 64] - [ALT_OUTPUTDIR=output_directory] - [other "ALT_" overrides] - -
    -
  4. -
-

- Solaris: - Note that ARCH_DATA_MODEL is really only needed on Solaris to - indicate you want to built the 64-bit version. - And before the Solaris 64-bit binaries can be used, they - must be merged with the binaries from a separate 32-bit build. - The merged binaries may then be used in either 32-bit or 64-bit mode, with - the selection occurring at runtime - with the -d32 or -d64 options. -

- - -
- -

Testing the Build

- -
-

- When the build is completed, you should see the generated - binaries and associated files in the j2sdk-image - directory in the output directory. - The default output directory is - build/platform, - where platform is one of -

    -
  • solaris-sparc
  • -
  • solaris-sparcv9
  • -
  • solaris-i586
  • -
  • solaris-amd64
  • -
  • linux-i586
  • -
  • linux-amd64
  • -
  • windows-i586
  • -
  • windows-amd64
  • -
- In particular, the - build/platform/j2sdk-image/bin - directory should contain executables for the - OpenJDK - tools and utilities. -

- You can test that the build completed properly by using the build - to run the various demos that you will find in the - build/platform/j2sdk-image/demo - directory. -

- The provided regression tests can be run with the jtreg - utility from - the jtreg site. -

- - -
- -

Environment/Make Variables

- -

-Some of the -environment or make variables (just called variables in this -document) that can impact the build are: - -

- -
- -
PATH
-
Typically you want to set the PATH to include: -
    -
  • The location of the GNU make binary
  • -
  • The location of the JDK 6 java - (see Bootstrap JDK)
  • -
  • The location of the C/C++ compilers - (see compilers)
  • -
  • The location or locations for the Unix command utilities - (e.g. /usr/bin)
  • -
-
- -
ARCH_DATA_MODEL
-
The ARCH_DATA_MODEL variable - is used to specify whether the build is to generate 32-bit or 64-bit - binaries. - The Solaris build supports either 32-bit or 64-bit builds, but - Windows and Linux will support only one, depending on the specific - OS being used. - Normally, setting this variable is only necessary on Solaris. - Set ARCH_DATA_MODEL to 32 for generating 32-bit binaries, - or to 64 for generating 64-bit binaries. -
- -
ALT_BOOTDIR
-
- The location of the bootstrap JDK installation. - See Bootstrap JDK for more information. - You should always install your own local Bootstrap JDK and - always set ALT_BOOTDIR explicitly. -
- -
ALT_OUTPUTDIR
-
- An override for specifying the (absolute) path of where the - build output is to go. - The default output directory will be build/platform. -
- -
ALT_COMPILER_PATH
-
- The location of the C/C++ compiler. - The default varies depending on the platform. -
- -
ALT_CACERTS_FILE
-
- The location of the cacerts file. - The default will refer to - jdk/src/share/lib/security/cacerts. -
- -
ALT_BINARY_PLUGS_PATH
-
- The location of the binary plugs installation. - See Binary Plugs for more information. - You should always have a local copy of a - recent Binary Plugs install image - and set this variable to that location. -
- -
ALT_CUPS_HEADERS_PATH
-
- The location of the CUPS header files. - See CUPS information for more information. - If this path does not exist the fallback path is - /usr/include. -
- - -
ALT_FREETYPE_LIB_PATH
-
- The location of the FreeType shared library. - See FreeType information for details. -
- -
ALT_FREETYPE_HEADERS_PATH
-
- The location of the FreeType header files. - See FreeType information for details. -
- -
Windows specific:
-
-
-
ALT_MSDEVTOOLS_PATH
-
- The location of the Microsoft Visual Studio .NET 2003 - tools 'bin' directory. - The default is usually derived from + +

Basic Linux Check List

+
+
    +
  1. + Install the + Bootstrap JDK, set + ALT_BOOTDIR. +
  2. +
  3. + Install the + Binary Plugs, set + ALT_BINARY_PLUGS_PATH. +
  4. +
  5. + Optional Import JDK, set + ALT_JDK_IMPORT_PATH. +
  6. +
  7. + Install or upgrade the FreeType development + package. +
  8. +
+
+ +
+

Basic Solaris System Setup

+
+ The minimum recommended hardware for building the + Solaris SPARC version is an UltraSPARC with 512 MB of RAM. + For building + the Solaris x86 version, a Pentium class processor or better and at + least 512 MB of RAM are recommended. + Approximately 1.4 GB of free disk + space is needed for a 32-bit build. +

+ If you are building the 64bit version, you should + run the command "isainfo -v" to verify that you have a + 64-bit installation, it should say sparcv9 or + amd64. + An additional 7 GB of free disk space is needed + for a 64-bit build. +

+ The build uses the tools contained in /usr/ccs/bin + and /usr/bin of a standard developer or full installation of + the Solaris operating environment. +

+ Solaris patches specific to the JDK can be downloaded from the + + SunSolve JDK Solaris patches download page. + You should ensure that the latest patch cluster for + your version of the Solaris operating environment has also + been installed. +

+ +

Basic Solaris Check List

+
+
    +
  1. + Install the + Bootstrap JDK, set + ALT_BOOTDIR. +
  2. +
  3. + Install the + Binary Plugs, set + ALT_BINARY_PLUGS_PATH. +
  4. +
  5. + Optional Import JDK, set + ALT_JDK_IMPORT_PATH. +
  6. +
  7. + Install the + Sun Studio Compilers, set ALT_COMPILER_PATH. -
- -
ALT_DXSDK_PATH
-
- The location of the - Microsoft DirectX 9 SDK. - The default will be to try and use the DirectX environment - variable DXSDK_DIR, - failing that, look in C:/DXSDK. -
- -
ALT_MSVCRT_DLL_PATH
-
- The location of the - MSVCRT.DLL. -
- -
ALT_MSVCR71_DLL_PATH
-
- i586 only: - The location of the - MSVCR71.DLL. -
-
-
- -
-
- - -
- -

Troubleshooting

- -
-

- 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. - Look for the check list of the platform you are building on in the - Table of Contents. - -

- You can validate your build environment by using the sanity - target. - Any errors listed - will stop the build from starting, and any warnings may result in - a flawed product build. - We strongly encourage you to evaluate every - sanity check warning and fix it if required, before you proceed - further with your build. - -

- Some of the more common problems with builds are briefly described - below, with suggestions for remedies. - -

+ +
+

Basic Windows System Setup

+
+ i586 only: + The minimum recommended hardware for building the 32bit or X86 + Windows version is an Pentium class processor or better, at least + 512 MB of RAM, and approximately 600 MB of free disk space. + + NOTE: The Windows 2000 build machines need to use the + file system NTFS. + Build machines formatted to FAT32 will not work + because FAT32 doesn't support case-sensitivity in file names. + +

+ X64 only: + The minimum recommended hardware for building + the Windows X64 version is an AMD Opteron class processor, at least 1 + GB of RAM, and approximately 10 GB of free disk space. +

+ +

Windows Paths

+
+ Windows: + Note that GNU make is a historic utility and is based very + heavily on shell scripting, so it does not tolerate the Windows habit + of having spaces in pathnames or the use of the \characters in pathnames. + Luckily on most Windows systems, you can use /instead of \, and + there is always a 'short' pathname without spaces for any path that + contains spaces. + Unfortunately, this short pathname can be somewhat dynamic and the + formula is difficult to explain. + You can use cygpath utility to map pathnames with spaces + or the \character into the C:/ style of pathname + (called 'mixed'), e.g. + cygpath -s -m "path". +

+ The makefiles will try to translate any pathnames supplied + to it into the C:/ style automatically. +

+ Note that 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 uses ":"). + 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. + So be careful with paths on Windows. +

+ +

Basic Windows Check List

+
+
    +
  1. + Install the + CYGWIN product. +
  2. +
  3. + Install the + Bootstrap JDK, set + ALT_BOOTDIR. +
  4. +
  5. + Install the + Binary Plugs, set + ALT_BINARY_PLUGS_PATH.. +
  6. +
  7. + Optional Import JDK, set + ALT_JDK_IMPORT_PATH. +
  8. +
  9. + Install the + Microsoft Visual Studio .NET 2003 Professional or the + Microsoft Platform SDK. +
  10. +
  11. + Setup all environment variables for compilers + (see compilers). +
  12. +
  13. + Install + Microsoft DirectX SDK. +
  14. +
+
+ +
+

Build Dependencies

+
+ Depending on the platform, the OpenJDK build process has some basic + dependencies on components not part of the OpenJDK sources. + Some of these are specific to a platform, some even specific to + an architecture. + Each dependency will have a set of ALT variables that can be set + to tell the makefiles where to locate the component. + In most cases setting these ALT variables may not be necessary + and the makefiles will find defaults on the system in standard + install locations or through component specific variables. + +

Bootstrap JDK

+ All OpenJDK builds require access to the previously released + JDK 6, this is often called a bootstrap JDK. + The JDK 6 binaries can be downloaded from Sun's + JDK 6 download site. + For build performance reasons + is very important that this bootstrap JDK be made available on the + local disk of the machine doing the build. + You should always set + ALT_BOOTDIR + to point to the location of + the bootstrap JDK installation, this is the directory pathname + that contains a bin, lib, and include + It's also a good idea to also place its bin directory + in the PATH environment variable, although it's + not required.

- If your build machine seems to be overloaded from too many - simultaneous C++ compiles, try setting the HOTSPOT_BUILD_JOBS - variable to 1 (if you're using a multiple CPU - machine, setting it to more than the the number of CPUs is probably - not a good idea). -

- Creating the javadocs can be very slow, if you are running - javadoc, consider skipping that step. -

- Faster hardware and more RAM always helps too. - 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. + Solaris: + Some pre-installed JDK images may be available to you in the + directory /usr/jdk/instances. + If you don't set + ALT_BOOTDIR + the makefiles will look in that location for a JDK it can use.

- -
  • - File time issues: + +

    Binary Plugs

    -

    - If you see warnings that refer to file time stamps, e.g. + Not all of the source code that makes up the JDK is available + under an open-source license. + This is a temporary situation and these binary plugs will be + replaced with fully open source replacements as soon as possible. + So currently, in order to build a complete OpenJDK image, + you must first download and install the appropriate + binary plug bundles for the OpenJDK, go to the + OpenJDK site and select + the "Bundles(7)" link and download the binaryplugs for + your particular platform. + The file downloaded is a jar file that must be extracted by running + the jar file with:

    - Warning message: File `xxx' has modification time in - the future. -
    - Warning message: Clock skew detected. Your build may - be incomplete. +
    +            java -jar jdk-7-ea-plug-bnn-os-arch-dd_month_year.jar
    +                    
    +
    + A prompt will be issued for acceptance of these binary plug files. + During the OpenJDK build process these "binary plugs" + for the encumbered components will be copied into your + resulting OpenJDK binary build image. + These binary plug files are only for the purpose of + building an OpenJDK binary. + Make sure you set + ALT_BINARY_PLUGS_PATH + to the root of this installation. +
    + +

    Optional Import JDK

    +
    + The ALT_JDK_IMPORT_PATH + setting is only needed if you are not building the entire + JDK. For example, if you have built the entire JDK once, and + wanted to avoid repeatedly building the Hotspot VM, you could + set this to the location of the previous JDK install image + and the build will copy the needed files from this import area. +
    + +

    Certificate Authority File (cacert)

    +
    + 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. + The variable + ALT_CACERTS_FILE + can be used to override the default location of the + cacerts file that will get placed in your build. + By default an empty cacerts file is provided and that should be + fine for most JDK developers. +
    + +

    Compilers

    +
    + Linux gcc/binutils +
    + The GNU gcc compiler version should be 3.2.2 or newer. + The binutils package should be 2.11.93.0.2-11 or newer. + The compiler used should be the default compiler installed + in /usr/bin. +

    + Older Linux systems may require a gcc and bunutils update. + The Redhat Enterprise Advanced Server 2.1 update 2 system + is one of these systems. + RedHat Linux users can obtain this binutils package from + Redhat web site. + You will need to remove the default compiler and binutils + packages and install the required packages + into the default location on the system. + However if you have a new video card driver, like + Geforce 4 it is best to use + the same compiler as the kernel was built with to + build the new video card driver module. + So you should build the modules before making this change. +

    + Solaris: Sun Studio +
    + At a minimum, the + + Sun Studio 11 Compilers + (containing version 5.8 of the C and C++ compilers) is required, + with patches from the + + SunSolve web site. +

    + Set + ALT_COMPILER_PATH + to point to the location of + the compiler binaries, and place this location in the PATH. +

    + The Sun Studio Express compilers at: + + Sun Studio Express Download site + are also an option, although these compilers have not + been extensively used yet. +

    + Windows i586: Microsoft Visual Studio .NET 2003 Professional +
    + The 32-bit OpenJDK Windows build + requires Microsoft Visual Studio .NET 2003 (VS2003) Professional + Edition compiler. + The compiler and other tools are expected to reside + in the location defined by the variable VS71COMNTOOLS which + is set by the Microsoft Visual Studio .NET installer. +

    + Once the compiler is installed, + it is recommended that you run VCVARS32.BAT + to set the compiler environment variables + MSVCDIR, + INCLUDE, + LIB, and + PATH + prior to building the + OpenJDK. + The above environment variables MUST be set. +

    + The Microsoft Visual Studio .NET 2005 (VS2005) compiler + will not work at this time due to the new runtime dll + and the manifest requirements. +

    + Windows X64: Microsoft Platform SDK April 2005 +
    + On X64, the Microsoft Platform Software + Development Kit (SDK), April 2005 Edition compiler, + is required for building the OpenJDK + because it contains the C/C++ compiler. + You will need to minimally install the Core SDK and + the MDAC SDK features of this compiler. +

    + Once the Platform SDK is installed, + it is recommended that you run SetEnv.Cmd /X64 + to set the compiler environment variables + MSSDK, + MSTOOLS, + INCLUDE, + LIB, and + PATH + prior to building the + OpenJDK. + The above environment variables MUST be set. +

    + Note that this compiler may say it's version is a + Microsoft Visual Studio .NET 2005 (VS2005), but be careful, + it will not match the official VS2005 product. + This Platform SDK compiler is only used on X64 builds. +

    +
    + +

    Zip and Unzip

    +
    + Version 2.2 (November 3rd 1997) or newer of the zip utility + and version 5.12 or newer of the unzip utility is needed + to build the JDK. + With Solaris, Linux, and Windows CYGWIN, the zip and unzip + utilities installed on the system should be fine. + Information and the source code for + ZIP.EXE and UNZIP.EXE is available on the + info-zip web site. +
    + +

    Common UNIX Printing System (CUPS) Headers (Solaris & Linux)

    +
    + Solaris: + CUPS header files are required for building the + OpenJDK on Solaris. + 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 + /opt/sfw/cups. +

    + Linux: + CUPS header files are required for building the + OpenJDK on Linux. + The Linux header files are usually available from a "cups" + development package, it's recommended that you try and use + the package provided by the particular version of Linux that + you are using. +

    + The CUPS header files can always be downloaded from + www.cups.org. + The variable + ALT_CUPS_HEADERS_PATH + can be used to override the default location of the + CUPS Header files. +

    + +

    FreeType 2

    +
    + Version 2.3 or newer of FreeType is required for building the OpenJDK. + 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 FreeType library and header files. +

    + You can always download latest FreeType version from the + FreeType website. +

    + Makefiles will try to pick FreeType from /usr/lib and /usr/include. + In case it is installed elsewhere you will need to set environment + variables + ALT_FREETYPE_LIB_PATH + and + ALT_FREETYPE_HEADERS_PATH + to refer to place where library and header files are installed. +

    + +

    Advanced Linux Sound Architecture (ALSA) (Linux only)

    +
    + Linux only: + 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, it's highly recommended that you try and use + the package provided by the particular version of Linux that + you are using. + The makefiles will check this emit a sanity error if it is + missing or the wrong version. +

    + In particular, older Linux systems will likely not have the + right version of ALSA installed, for example + Redhat AS 2.1 U2 and SuSE 8.1 do not include a sufficiently + recent ALSA distribution. + On rpm-based systems, you can see if ALSA is installed by + running this command: +

    +                    rpm -qa | grep alsa
    +                
    + Both alsa and alsa-devel packages are needed. +

    + If your distribution does not come with ALSA, and you can't + find ALSA packages built for your particular system, + you can try to install the pre-built ALSA rpm packages from + + www.freshrpms.net. + Note that installing a newer ALSA could + break sound output if an older version of ALSA was previously + installed on the system, but it will enable JDK compilation. +

    + Installation: execute as root
    + [i586]: rpm -Uv --force alsa-lib-devel-0.9.1-rh61.i386.rpm
    + [x64]: rpm -Uv --force alsa-lib-devel-0.9.8-amd64.x86_64.rpm
    + Uninstallation:
    + [i586]: rpm -ev alsa-lib-devel-0.9.1-rh61
    + [x64]:rpm -ev alsa-lib-devel-0.9.8-amd64
    + Make sure that you do not link to the static library + (libasound.a), + by verifying that the dynamic library (libasound.so) is + correctly installed in /usr/lib. +
    + As a last resort you can go to the + + Advanced Linux Sound Architecture Site and build it from + source. +
    + Download driver and library + source tarballs from + ALSA's homepage. + As root, execute the following + commands (you may need to adapt the version number): +
    +                        
    +                            $ tar xjf alsa-driver-0.9.1.tar.bz2
    +                            $ cd alsa-driver-0.9.1
    +                            $ ./configure
    +                            $ make install
    +                            $ cd ..
    +                            $ tar xjf alsa-lib-0.9.1.tar.bz2
    +                            $ cd alsa-lib-0.9.1
    +                            $ ./configure
    +                            $ make install
    +                        
    +                    
    + Should one of the above steps fail, refer to the documentation on + ALSA's home page. +
    + Note that this is a minimum install that enables + building the JDK platform. To actually use ALSA sound drivers, more + steps are necessary as outlined in the documentation on ALSA's homepage. +

    + ALSA can be uninstalled by executing make uninstall first in + the alsa-lib-0.9.1 directory and then in + alsa-driver-0.9.1. +

    + There are no ALT* variables to change the assumed locations of ALSA, + the makefiles will expect to find the ALSA include files and library at: + /usr/include/alsa and /usr/lib/libasound.so. +
  • + +

    Windows Specific Dependencies

    +
    + Unix Command Tools (CYGWIN) +
    + The OpenJDK requires access to a set of unix command tools + on Windows which can be supplied by + CYGWIN. +

    + The OpenJDK build requires CYGWIN version 1.5.12 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 NamePackageDescription
    ar.exeDevelbinutils: The GNU assembler, linker and binary + utilities
    make.exeDevelmake: The GNU version of the 'make' utility
    m4.exeInterpretersm4: GNU implementation of the traditional Unix macro + processor
    cpio.exeUtilscpio: A program to manage archives of files
    awk.exeUtilsawk: Pattern-directed scanning and processing language
    file.exeUtilsfile: Determines file type using 'magic' numbers
    zip.exeUtilszip: Package and compress (archive) files
    unzip.exeUtilsunzip: Extract compressed files in a ZIP archive
    free.exeUtilsfree: Display amount of free and used memory in the system

    - 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. - For example, an out-of-sync clock has been known to cause an old - version of javac to be used to compile some files, resulting in errors - when the pre-1.4 compiler ran across the new assert keyword - in the 1.4 source code. -

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

    - -
  • - Error message: Trouble writing out table to disk + Microsoft DirectX 9.0 SDK header files and libraries
    -

    - Increase the amount of swap space on your build machine. + Microsoft DirectX 9.0 SDK (Summer 2004) + headers are required for building + OpenJDK. + This SDK can be downloaded from + + Microsoft DirectX 9.0 SDK (Summer 2004). + If the link above becomes obsolete, the SDK can be found from + the Microsoft Download Site + (search with "DirectX 9.0 SDK Update Summer 2004"). + The location of this SDK can be set with + ALT_DXSDK_PATH + but it's normally found via the DirectX environment variable + DXSDK_DIR.

    -
  • -
  • - Error Message: libstdc++ not found: + MSVCRT.DLL +
    + i586 only: + The OpenJDK 32bit build requires access to + MSVCRT.DLL version 6.00.8337.0 or newer. + If the MSVCRT.DLL is not installed in + the system32 directory set the + ALT_MSVCRT_DLL_PATH + variable to the location. +

    + X64 only: + The OpenJDK 64bit build requires access to + MSVCRT.DLL version 7.0.3790.0 or newer, which is + usually supplied by the + Platform SDK. + If it is not available from the Platform SDK, + set the + ALT_MSVCRT_DLL_PATH + variable to the location. +

    + MSVCR71.DLL
    - 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 64bit Linux versions (e.g. Fedora) - only install the 64bit 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. + i586 only: + The + OpenJDK + build requires access to + MSVCR71.DLL version 7.10.3052.4 or newer which should be + supplied by the + Visual Studio product + If the MSVCR71.DLL is not available from the + Visual Studio product + set the + ALT_MSVCR71_DLL_PATH + variable to the location.
    -
  • -
  • - 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: -

      - -
    1. $ su root
    2. -
    3. # system-config-securitylevel
    4. -
    5. In the window that appears, select the SELinux tab
    6. -
    7. Disable SELinux
    8. -
    -

    - Alternatively, instead of completely disabling it you could - disable just this one check. -

      -
    1. Select System->Administration->SELinux Management
    2. -
    3. In the SELinux Management Tool which appears, - select "Boolean" from the menu on the left
    4. -
    5. Expand the "Memory Protection" group
    6. -
    7. Check the first item, labeled - "Allow all unconfined executables to use libraries requiring text relocation ..."
    8. -
    -
    -
  • - -
    - -
    +
    + +
    +

    Creating the Build

    +
    + Once a machine is setup to build the OpenJDK, + the steps to create the build are fairly simple. + The various ALT settings can either be made into variables + or can be supplied on the + gmake + command. +
      +
    1. Use the sanity rule to double check all the ALT settings: +
      + + gmake + sanity + [ARCH_DATA_MODEL=32 or 64] + [other "ALT_" overrides] + +
      +
    2. +
    3. Start the build with the command: +
      + + gmake + [ARCH_DATA_MODEL=32 or 64] + [ALT_OUTPUTDIR=output_directory] + [other "ALT_" overrides] + +
      +
    4. +
    +

    + Solaris: + Note that ARCH_DATA_MODEL is really only needed on Solaris to + indicate you want to built the 64-bit version. + And before the Solaris 64-bit binaries can be used, they + must be merged with the binaries from a separate 32-bit build. + The merged binaries may then be used in either 32-bit or 64-bit mode, with + the selection occurring at runtime + with the -d32 or -d64 options. +

    + +
    +

    Testing the Build

    +
    + When the build is completed, you should see the generated + binaries and associated files in the j2sdk-image + directory in the output directory. + The default output directory is + build/platform, + where platform is one of +
      +
    • solaris-sparc
    • +
    • solaris-sparcv9
    • +
    • solaris-i586
    • +
    • solaris-amd64
    • +
    • linux-i586
    • +
    • linux-amd64
    • +
    • windows-i586
    • +
    • windows-amd64
    • +
    + In particular, the + build/platform/j2sdk-image/bin + directory should contain executables for the + OpenJDK tools and utilities. +

    + You can test that the build completed properly by using the build + to run the various demos that you will find in the + build/platform/j2sdk-image/demo + directory. +

    + The provided regression tests can be run with the jtreg + utility from + the jtreg site. +

    + +
    +

    Environment/Make Variables

    +

    + Some of the + environment or make variables (just called variables in this + document) that can impact the build are: +

    +
    +
    PATH
    +
    Typically you want to set the PATH to include: +
      +
    • The location of the GNU make binary
    • +
    • The location of the Bootstrap JDK java + (see Bootstrap JDK)
    • +
    • The location of the C/C++ compilers + (see compilers)
    • +
    • The location or locations for the Unix command utilities + (e.g. /usr/bin)
    • +
    +
    +
    MILESTONE
    +
    + The milestone name for the build (e.g."beta"). + The default value is "internal". +
    +
    BUILD_NUMBER
    +
    + The build number for the build (e.g. "b27"). + The default value is "b00". +
    +
    ARCH_DATA_MODEL
    +
    The ARCH_DATA_MODEL variable + is used to specify whether the build is to generate 32-bit or 64-bit + binaries. + The Solaris build supports either 32-bit or 64-bit builds, but + Windows and Linux will support only one, depending on the specific + OS being used. + Normally, setting this variable is only necessary on Solaris. + Set ARCH_DATA_MODEL to 32 for generating 32-bit binaries, + or to 64 for generating 64-bit binaries. +
    +
    ALT_BOOTDIR
    +
    + The location of the bootstrap JDK installation. + See Bootstrap JDK for more information. + You should always install your own local Bootstrap JDK and + always set ALT_BOOTDIR explicitly. +
    +
    ALT_BINARY_PLUGS_PATH
    +
    + The location of the binary plugs installation. + See Binary Plugs for more information. + You should always have a local copy of a + recent Binary Plugs install image + and set this variable to that location. +
    +
    ALT_JDK_IMPORT_PATH
    +
    + The location of a previously built JDK installation. + See Optional Import JDK for more information. +
    +
    ALT_OUTPUTDIR
    +
    + An override for specifying the (absolute) path of where the + build output is to go. + The default output directory will be build/platform. +
    +
    ALT_COMPILER_PATH
    +
    + The location of the C/C++ compiler. + The default varies depending on the platform. +
    +
    ALT_CACERTS_FILE
    +
    + The location of the cacerts file. + The default will refer to + jdk/src/share/lib/security/cacerts. +
    +
    ALT_CUPS_HEADERS_PATH
    +
    + The location of the CUPS header files. + See CUPS information for more information. + If this path does not exist the fallback path is + /usr/include. +
    +
    ALT_FREETYPE_LIB_PATH
    +
    + The location of the FreeType shared library. + See FreeType information for details. +
    +
    ALT_FREETYPE_HEADERS_PATH
    +
    + The location of the FreeType header files. + See FreeType information for details. +
    +
    ALT_JDK_DEVTOOLS_PATH
    +
    + The default root location of the devtools. + The default value is + $(ALT_SLASH_JAVA)/devtools. +
    +
    ALT_DEVTOOLS_PATH
    +
    + The location of tools like the + zip and unzip + binaries, but might also contain the GNU make utility + (gmake). + So this area is a bit of a grab bag, especially on Windows. + The default value depends on the platform and + Unix Commands being used. + On Linux the default will be + $(ALT_JDK_DEVTOOLS_PATH)/linux/bin, + on Solaris + $(ALT_JDK_DEVTOOLS_PATH)/{sparc,i386}/bin, + on Windows with MKS + %SYSTEMDRIVE%/UTILS, + and on Windows with CYGWIN + /usr/bin. +
    +
    ALT_UNIXCOMMAND_PATH
    +
    + An override for specifying where the + Unix command set are located. + The default location varies depending on the platform, + "%SYSTEMDRIVE%/MKSNT" or + $(ROOTDIR) on Windows with MKS, otherwise it's + "/bin" or /usr/bin. +
    +
    ALT_UNIXCCS_PATH
    +
    + Solaris only: + An override for specifying where the Unix CCS + command set are located. + The default location is /usr/ccs/bin +
    +
    ALT_USRBIN_PATH
    +
    + An override for specifying where the + Unix /usr/bin commands are located. You usually do not need + to set this variable: the default location is /usr/bin) +
    +
    ALT_SLASHJAVA
    +
    + The default root location for many of the ALT path locations + of the following ALT variables. + The default value is + "/java" on Solaris and Linux, + "J:" on Windows. +
    +
    ALT_BUILD_JDK_IMPORT_PATH
    +
    + These are useful in managing builds on multiple platforms. + The default network location for all of the import JDK images + for all platforms. + If ALT_JDK_IMPORT_PATH + is not set, this directory will be used and should contain + the following directories: + solaris-sparc, + solaris-i586, + solaris-sparcv9, + solaris-amd64, + linux-i586, + linux-amd64, + windows-i586, + and + windows-amd64. + Where each of these directories contain the import JDK image + for that platform. +
    +
    ALT_BUILD_BINARY_PLUGS_PATH
    +
    + These are useful in managing builds on multiple platforms. + The default network location for all of the binary plug images + for all platforms. + If ALT_BINARY_PLUGS_PATH + is not set, this directory will be used and should contain + the following directories: + solaris-sparc, + solaris-i586, + solaris-sparcv9, + solaris-amd64, + linux-i586, + linux-amd64, + windows-i586, + and + windows-amd64. + Where each of these directories contain the binary plugs image + for that platform. +
    +
    Windows specific:
    +
    +
    +
    ALT_MSDEVTOOLS_PATH
    +
    + The location of the Microsoft Visual Studio .NET 2003 + tools 'bin' directory. + The default is usually derived from + ALT_COMPILER_PATH. +
    +
    ALT_DXSDK_PATH
    +
    + The location of the + Microsoft DirectX 9 SDK. + The default will be to try and use the DirectX environment + variable DXSDK_DIR, + failing that, look in C:/DXSDK. +
    +
    ALT_MSVCRT_DLL_PATH
    +
    + The location of the + MSVCRT.DLL. +
    +
    ALT_MSVCR71_DLL_PATH
    +
    + i586 only: + The location of the + MSVCR71.DLL. +
    +
    +
    +
    +
    + +
    +

    Troubleshooting

    +
    + 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. + Look for the check list of the platform you are building on in the + Table of Contents. +

    + You can validate your build environment by using the sanity + target. + Any errors listed + will stop the build from starting, and any warnings may result in + a flawed product build. + We strongly encourage you to evaluate every + sanity check warning and fix it if required, before you proceed + further with your build. +

    + Some of the more common problems with builds are briefly described + below, with suggestions for remedies. +

    +
    +
    + + diff --git a/corba/.hgtags b/corba/.hgtags index 751872e11c7..3832215a78c 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -1,2 +1,3 @@ 55540e827aef970ecc010b7e06b912d991c8e3ce jdk7-b24 5e61d5df62586474414d1058e9186441aa908f51 jdk7-b25 +0043eb3d4e628f049ff80a8c223b5657136085e7 jdk7-b26 diff --git a/hotspot/.hgignore b/hotspot/.hgignore index 8c4cff4cd1f..24a19191195 100644 --- a/hotspot/.hgignore +++ b/hotspot/.hgignore @@ -1,170 +1,4 @@ -^build/solaris/solaris_sparc_compiler1/ -^build/solaris/solaris_sparc_compiler2/ -^build/solaris/solaris_sparc_core/ -^build/solaris/solaris_sparc_kernel/ -^build/solaris/solaris_sparc_docs/ -^build/solaris/jdk-solaris-sparc/ -^build/solaris/export-solaris-sparc/ -^build/solaris/solaris_sparcv9_compiler1/ -^build/solaris/solaris_sparcv9_compiler2/ -^build/solaris/solaris_sparcv9_core/ -^build/solaris/solaris_sparcv9_kernel/ -^build/solaris/solaris_sparcv9_docs/ -^build/solaris/jdk-solaris-sparcv9/ -^build/solaris/export-solaris-sparcv9/ -^build/solaris/solaris_sparc32_compiler1/ -^build/solaris/solaris_sparc32_compiler2/ -^build/solaris/solaris_sparc32_core/ -^build/solaris/solaris_sparc32_kernel/ -^build/solaris/solaris_sparc32_docs/ -^build/solaris/jdk-solaris-sparc32/ -^build/solaris/export-solaris-sparc32/ -^build/solaris/solaris_sparc64_compiler1/ -^build/solaris/solaris_sparc64_compiler2/ -^build/solaris/solaris_sparc64_core/ -^build/solaris/solaris_sparc64_kernel/ -^build/solaris/solaris_sparc64_docs/ -^build/solaris/jdk-solaris-sparc64/ -^build/solaris/export-solaris-sparc64/ -^build/solaris/solaris_i486_compiler1/ -^build/solaris/solaris_i486_compiler2/ -^build/solaris/solaris_i486_core/ -^build/solaris/solaris_i486_kernel/ -^build/solaris/solaris_i486_docs/ -^build/solaris/jdk-solaris-i486/ -^build/solaris/export-solaris-i486/ -^build/solaris/solaris_i386_compiler1/ -^build/solaris/solaris_i386_compiler2/ -^build/solaris/solaris_i386_core/ -^build/solaris/solaris_i386_kernel/ -^build/solaris/solaris_i386_docs/ -^build/solaris/jdk-solaris-i386/ -^build/solaris/export-solaris-i386/ -^build/solaris/solaris_amd64_compiler1/ -^build/solaris/solaris_amd64_compiler2/ -^build/solaris/solaris_amd64_core/ -^build/solaris/solaris_amd64_kernel/ -^build/solaris/solaris_amd64_docs/ -^build/solaris/jdk-solaris-amd64/ -^build/solaris/export-solaris-amd64/ -^build/solaris/solaris_x64_compiler1/ -^build/solaris/solaris_x64_compiler2/ -^build/solaris/solaris_x64_core/ -^build/solaris/solaris_x64_kernel/ -^build/solaris/solaris_x64_docs/ -^build/solaris/jdk-solaris-x64/ -^build/solaris/export-solaris-x64/ -^build/windows/windows_sparc_compiler1/ -^build/windows/windows_sparc_compiler2/ -^build/windows/windows_sparc_core/ -^build/windows/windows_sparc_kernel/ -^build/windows/windows_sparc_docs/ -^build/windows/jdk-windows-sparc/ -^build/windows/export-windows-sparc/ -^build/windows/windows_sparcv9_compiler1/ -^build/windows/windows_sparcv9_compiler2/ -^build/windows/windows_sparcv9_core/ -^build/windows/windows_sparcv9_kernel/ -^build/windows/windows_sparcv9_docs/ -^build/windows/jdk-windows-sparcv9/ -^build/windows/export-windows-sparcv9/ -^build/windows/windows_sparc32_compiler1/ -^build/windows/windows_sparc32_compiler2/ -^build/windows/windows_sparc32_core/ -^build/windows/windows_sparc32_kernel/ -^build/windows/windows_sparc32_docs/ -^build/windows/jdk-windows-sparc32/ -^build/windows/export-windows-sparc32/ -^build/windows/windows_sparc64_compiler1/ -^build/windows/windows_sparc64_compiler2/ -^build/windows/windows_sparc64_core/ -^build/windows/windows_sparc64_kernel/ -^build/windows/windows_sparc64_docs/ -^build/windows/jdk-windows-sparc64/ -^build/windows/export-windows-sparc64/ -^build/windows/windows_i486_compiler1/ -^build/windows/windows_i486_compiler2/ -^build/windows/windows_i486_core/ -^build/windows/windows_i486_kernel/ -^build/windows/windows_i486_docs/ -^build/windows/jdk-windows-i486/ -^build/windows/export-windows-i486/ -^build/windows/windows_i386_compiler1/ -^build/windows/windows_i386_compiler2/ -^build/windows/windows_i386_core/ -^build/windows/windows_i386_kernel/ -^build/windows/windows_i386_docs/ -^build/windows/jdk-windows-i386/ -^build/windows/export-windows-i386/ -^build/windows/windows_amd64_compiler1/ -^build/windows/windows_amd64_compiler2/ -^build/windows/windows_amd64_core/ -^build/windows/windows_amd64_kernel/ -^build/windows/windows_amd64_docs/ -^build/windows/jdk-windows-amd64/ -^build/windows/export-windows-amd64/ -^build/windows/windows_x64_compiler1/ -^build/windows/windows_x64_compiler2/ -^build/windows/windows_x64_core/ -^build/windows/windows_x64_kernel/ -^build/windows/windows_x64_docs/ -^build/windows/jdk-windows-x64/ -^build/windows/export-windows-x64/ -^build/linux/linux_sparc_compiler1/ -^build/linux/linux_sparc_compiler2/ -^build/linux/linux_sparc_core/ -^build/linux/linux_sparc_kernel/ -^build/linux/linux_sparc_docs/ -^build/linux/jdk-linux-sparc/ -^build/linux/export-linux-sparc/ -^build/linux/linux_sparcv9_compiler1/ -^build/linux/linux_sparcv9_compiler2/ -^build/linux/linux_sparcv9_core/ -^build/linux/linux_sparcv9_kernel/ -^build/linux/linux_sparcv9_docs/ -^build/linux/jdk-linux-sparcv9/ -^build/linux/export-linux-sparcv9/ -^build/linux/linux_sparc32_compiler1/ -^build/linux/linux_sparc32_compiler2/ -^build/linux/linux_sparc32_core/ -^build/linux/linux_sparc32_kernel/ -^build/linux/linux_sparc32_docs/ -^build/linux/jdk-linux-sparc32/ -^build/linux/export-linux-sparc32/ -^build/linux/linux_sparc64_compiler1/ -^build/linux/linux_sparc64_compiler2/ -^build/linux/linux_sparc64_core/ -^build/linux/linux_sparc64_kernel/ -^build/linux/linux_sparc64_docs/ -^build/linux/jdk-linux-sparc64/ -^build/linux/export-linux-sparc64/ -^build/linux/linux_i486_compiler1/ -^build/linux/linux_i486_compiler2/ -^build/linux/linux_i486_core/ -^build/linux/linux_i486_kernel/ -^build/linux/linux_i486_docs/ -^build/linux/jdk-linux-i486/ -^build/linux/export-linux-i486/ -^build/linux/linux_i386_compiler1/ -^build/linux/linux_i386_compiler2/ -^build/linux/linux_i386_core/ -^build/linux/linux_i386_kernel/ -^build/linux/linux_i386_docs/ -^build/linux/jdk-linux-i386/ -^build/linux/export-linux-i386/ -^build/linux/linux_amd64_compiler1/ -^build/linux/linux_amd64_compiler2/ -^build/linux/linux_amd64_core/ -^build/linux/linux_amd64_kernel/ -^build/linux/linux_amd64_docs/ -^build/linux/jdk-linux-amd64/ -^build/linux/export-linux-amd64/ -^build/linux/linux_x64_compiler1/ -^build/linux/linux_x64_compiler2/ -^build/linux/linux_x64_core/ -^build/linux/linux_x64_kernel/ -^build/linux/linux_x64_docs/ -^build/linux/jdk-linux-x64/ -^build/linux/export-linux-x64/ +^build/ ^dist/ ^nbproject/private/ +^src/share/tools/hsdis/bin/ diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 8eaaa375622..f3431f3fa42 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -1,2 +1,3 @@ a61af66fc99eb5ec9d50c05b0c599757b1289ceb jdk7-b24 7836be3e92d0a4f9ee7566f602c91f5609534e66 jdk7-b25 +ad0b851458ff9d1d490ed2d79bb84f75a9fdb753 jdk7-b26 diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java index 458e97195db..50e81f34789 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java @@ -885,7 +885,12 @@ public class CommandProcessor { out.println("found at " + addr); } } - + public void visitCompOopAddress(Address addr) { + Address val = addr.getCompOopAddressAt(0); + if (AddressOps.equal(val, value)) { + out.println("found at " + addr); + } + } public void epilogue() { } }; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java index 45c4866fc46..fb583936574 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HSDB.java @@ -1011,8 +1011,21 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener { Assert.that(addr.andWithMask(VM.getVM().getAddressSize() - 1) == null, "Address " + addr + "should have been aligned"); } - // Check contents OopHandle handle = addr.getOopHandleAt(0); + addAnnotation(addr, handle); + } + + public void visitCompOopAddress(Address addr) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(addr.andWithMask(VM.getVM().getAddressSize() - 1) == null, + "Address " + addr + "should have been aligned"); + } + OopHandle handle = addr.getCompOopHandleAt(0); + addAnnotation(addr, handle); + } + + public void addAnnotation(Address addr, OopHandle handle) { + // Check contents String anno = "null oop"; if (handle != null) { // Find location diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java index b8f263db638..21bc43d77bf 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java @@ -306,6 +306,8 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase { entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride); } while (nameAddr != null); + String symbol = "heapOopSize"; // global int constant and value is initialized at runtime. + addIntConstant(symbol, (int)lookupInProcess(symbol).getCIntegerAt(0, 4, false)); } private void readVMLongConstants() { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java index cbf86acdc7c..3d9c6bbe5d8 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/compiler/OopMapSet.java @@ -68,7 +68,8 @@ public class OopMapSet extends VMObject { public void visitValueLocation(Address valueAddr) { } - public void visitDeadLocation(Address deadAddr) { + public void visitNarrowOopLocation(Address narrowOopAddr) { + addressVisitor.visitCompOopAddress(narrowOopAddr); } } @@ -197,9 +198,9 @@ public class OopMapSet extends VMObject { } } - // We want dead, value and oop oop_types + // 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.DEAD_VALUE + OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE }; { @@ -214,8 +215,8 @@ public class OopMapSet extends VMObject { visitor.visitOopLocation(loc); } else if (omv.getType() == OopMapValue.OopTypes.VALUE_VALUE) { visitor.visitValueLocation(loc); - } else if (omv.getType() == OopMapValue.OopTypes.DEAD_VALUE) { - visitor.visitDeadLocation(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 b8edcc1fb08..3b7e66b1777 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 @@ -50,7 +50,7 @@ public class OopMapValue { static int UNUSED_VALUE; static int OOP_VALUE; static int VALUE_VALUE; - static int DEAD_VALUE; + static int NARROWOOP_VALUE; static int CALLEE_SAVED_VALUE; static int DERIVED_OOP_VALUE; @@ -74,7 +74,7 @@ public class OopMapValue { UNUSED_VALUE = db.lookupIntConstant("OopMapValue::unused_value").intValue(); OOP_VALUE = db.lookupIntConstant("OopMapValue::oop_value").intValue(); VALUE_VALUE = db.lookupIntConstant("OopMapValue::value_value").intValue(); - DEAD_VALUE = db.lookupIntConstant("OopMapValue::dead_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(); } @@ -83,7 +83,7 @@ public class OopMapValue { 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 DEAD_VALUE = new OopTypes() { int getValue() { return OopMapValue.DEAD_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; }}; @@ -106,7 +106,7 @@ 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 isDead() { return (getValue() & TYPE_MASK_IN_PLACE) == DEAD_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; } @@ -118,7 +118,7 @@ public class OopMapValue { 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 == DEAD_VALUE) return OopTypes.DEAD_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; else throw new InternalError("unknown which " + which + " (TYPE_MASK_IN_PLACE = " + TYPE_MASK_IN_PLACE + ")"); 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 379927dda74..612223667e4 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 @@ -32,5 +32,5 @@ public interface OopMapVisitor { public void visitOopLocation(Address oopAddr); public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr); public void visitValueLocation(Address valueAddr); - public void visitDeadLocation(Address deadAddr); + public void visitNarrowOopLocation(Address narrowOopAddr); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/Address.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/Address.java index dd02c304b3f..66996c4f9a7 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/Address.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/Address.java @@ -87,6 +87,8 @@ public interface Address { throws UnmappedAddressException, UnalignedAddressException; /** This returns null if the address at the given offset is NULL. */ public Address getAddressAt (long offset) throws UnmappedAddressException, UnalignedAddressException; + /** Returns the decoded address at the given offset */ + public Address getCompOopAddressAt (long offset) throws UnmappedAddressException, UnalignedAddressException; // // Java-related routines @@ -103,6 +105,8 @@ public interface Address { /** This returns null if the address at the given offset is NULL. */ public OopHandle getOopHandleAt (long offset) throws UnmappedAddressException, UnalignedAddressException, NotInHeapException; + public OopHandle getCompOopHandleAt (long offset) + throws UnmappedAddressException, UnalignedAddressException, NotInHeapException; // // C/C++-related mutators. These throw UnmappedAddressException if diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/Debugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/Debugger.java index d1575e8f75d..3e85bb7635d 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/Debugger.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/Debugger.java @@ -118,6 +118,9 @@ public interface Debugger extends SymbolLookup, ThreadAccess { public long getJIntSize(); public long getJLongSize(); public long getJShortSize(); + public long getHeapBase(); + public long getHeapOopSize(); + public long getLogMinObjAlignmentInBytes(); public ReadResult readBytesFromProcess(long address, long numBytes) throws DebuggerException; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/DebuggerBase.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/DebuggerBase.java index 75d10ca2275..4bef7b0daae 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/DebuggerBase.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/DebuggerBase.java @@ -37,6 +37,7 @@ package sun.jvm.hotspot.debugger; DbxDebugger interfaces.

    */ public abstract class DebuggerBase implements Debugger { + // May be set lazily, but must be set before calling any of the read // routines below protected MachineDescription machDesc; @@ -52,6 +53,11 @@ public abstract class DebuggerBase implements Debugger { protected long jlongSize; protected long jshortSize; protected boolean javaPrimitiveTypesConfigured; + // heap data. + protected long oopSize; + protected long heapOopSize; + protected long heapBase; // heap base for compressed oops. + protected long logMinObjAlignmentInBytes; // Used to decode compressed oops. // Should be initialized if desired by calling initCache() private PageCache cache; @@ -153,6 +159,12 @@ public abstract class DebuggerBase implements Debugger { javaPrimitiveTypesConfigured = true; } + public void putHeapConst(long heapBase, long heapOopSize, long logMinObjAlignmentInBytes) { + this.heapBase = heapBase; + this.heapOopSize = heapOopSize; + this.logMinObjAlignmentInBytes = logMinObjAlignmentInBytes; + } + /** May be called by subclasses if desired to initialize the page cache but may not be overridden */ protected final void initCache(long pageSize, long maxNumPages) { @@ -442,6 +454,16 @@ public abstract class DebuggerBase implements Debugger { return readCInteger(address, machDesc.getAddressSize(), true); } + protected long readCompOopAddressValue(long address) + throws UnmappedAddressException, UnalignedAddressException { + long value = readCInteger(address, getHeapOopSize(), true); + if (value != 0) { + // See oop.inline.hpp decode_heap_oop + value = (long)(heapBase + (long)(value << logMinObjAlignmentInBytes)); + } + return value; + } + protected void writeAddressValue(long address, long value) throws UnmappedAddressException, UnalignedAddressException { writeCInteger(address, machDesc.getAddressSize(), value); @@ -518,4 +540,15 @@ public abstract class DebuggerBase implements Debugger { public long getJShortSize() { return jshortSize; } + + public long getHeapOopSize() { + return heapOopSize; + } + + public long getHeapBase() { + return heapBase; + } + public long getLogMinObjAlignmentInBytes() { + return logMinObjAlignmentInBytes; + } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/JVMDebugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/JVMDebugger.java index 6308f7dd8ef..c478d33d088 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/JVMDebugger.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/JVMDebugger.java @@ -42,4 +42,5 @@ public interface JVMDebugger extends Debugger { long jintSize, long jlongSize, long jshortSize); + public void putHeapConst(long heapBase, long heapOopSize, long logMinObjAlignment); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescription.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescription.java index bbe2f69f883..9498c2e25fb 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescription.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescription.java @@ -35,13 +35,6 @@ public interface MachineDescription extends Serializable { able to traverse arrays of pointers or oops. */ public long getAddressSize(); - /** Returns the size of an address in bytes. Currently needed to be - able to traverse arrays of pointers or oops. (FIXME: since we're - already reading the Java primitive types' sizes from the remote - VM, it would be nice to remove this routine, using a similar - mechanism to how the TypeDataBase deals with primitive types.) */ - public long getOopSize(); - /** Returns the maximum value of the C integer type with the given size in bytes and signedness. Throws IllegalArgumentException if the size in bytes is not legal for a C type (or can not be diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionAMD64.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionAMD64.java index 5e5d34217ef..3dd6e513ead 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionAMD64.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionAMD64.java @@ -29,10 +29,6 @@ public class MachineDescriptionAMD64 extends MachineDescriptionTwosComplement im return 8; } - public long getOopSize() { - return 8; - } - public boolean isLP64() { return true; } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionIA64.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionIA64.java index 6cc6accd531..4099844799b 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionIA64.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionIA64.java @@ -29,10 +29,6 @@ public class MachineDescriptionIA64 extends MachineDescriptionTwosComplement imp return 8; } - public long getOopSize() { - return 8; - } - public boolean isLP64() { return true; } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionIntelX86.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionIntelX86.java index fe486a6cf3e..e333b139fcd 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionIntelX86.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionIntelX86.java @@ -29,10 +29,6 @@ public class MachineDescriptionIntelX86 extends MachineDescriptionTwosComplement return 4; } - public long getOopSize() { - return 4; - } - public boolean isBigEndian() { return false; } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionSPARC32Bit.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionSPARC32Bit.java index 7c33d40e0ee..5e70d16d975 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionSPARC32Bit.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionSPARC32Bit.java @@ -29,10 +29,6 @@ public class MachineDescriptionSPARC32Bit extends MachineDescriptionTwosCompleme return 4; } - public long getOopSize() { - return 4; - } - public boolean isBigEndian() { return true; } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionSPARC64Bit.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionSPARC64Bit.java index 22a88d87599..289f9ca8f2b 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionSPARC64Bit.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionSPARC64Bit.java @@ -29,9 +29,6 @@ public class MachineDescriptionSPARC64Bit extends MachineDescriptionTwosCompleme return 8; } - public long getOopSize() { - return 8; - } public boolean isBigEndian() { return true; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxAddress.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxAddress.java index 374dabf5794..d0c039e41ba 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxAddress.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxAddress.java @@ -71,6 +71,9 @@ class DbxAddress implements Address { public Address getAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException { return debugger.readAddress(addr + offset); } + public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException { + return debugger.readCompOopAddress(addr + offset); + } // // Java-related routines @@ -113,6 +116,11 @@ class DbxAddress implements Address { return debugger.readOopHandle(addr + offset); } + public OopHandle getCompOopHandleAt(long offset) + throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { + return debugger.readCompOopHandle(addr + offset); + } + // Mutators -- not implemented for now (FIXME) public void setCIntegerAt(long offset, long numBytes, long value) { throw new DebuggerException("Unimplemented"); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebugger.java index 5e5c341c7a2..f73700c8e16 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebugger.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebugger.java @@ -43,7 +43,9 @@ public interface DbxDebugger extends JVMDebugger { public long readCInteger(long address, long numBytes, boolean isUnsigned) throws DebuggerException; public DbxAddress readAddress(long address) throws DebuggerException; + public DbxAddress readCompOopAddress(long address) throws DebuggerException; public DbxOopHandle readOopHandle(long address) throws DebuggerException; + public DbxOopHandle readCompOopHandle(long address) throws DebuggerException; public long[] getThreadIntegerRegisterSet(int tid) throws DebuggerException; public Address newAddress(long value) throws DebuggerException; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebuggerLocal.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebuggerLocal.java index ef99707d567..1501f2b07c5 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebuggerLocal.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dbx/DbxDebuggerLocal.java @@ -460,12 +460,23 @@ public class DbxDebuggerLocal extends DebuggerBase implements DbxDebugger { return (value == 0 ? null : new DbxAddress(this, value)); } + public DbxAddress readCompOopAddress(long address) + throws UnmappedAddressException, UnalignedAddressException { + long value = readCompOopAddressValue(address); + return (value == 0 ? null : new DbxAddress(this, value)); + } + /** From the DbxDebugger interface */ public DbxOopHandle readOopHandle(long address) throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { long value = readAddressValue(address); return (value == 0 ? null : new DbxOopHandle(this, value)); } + public DbxOopHandle readCompOopHandle(long address) + throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { + long value = readCompOopAddressValue(address); + return (value == 0 ? null : new DbxOopHandle(this, value)); + } //-------------------------------------------------------------------------------- // Thread context access. Can not be package private, but should diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dummy/DummyAddress.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dummy/DummyAddress.java index 2c9bc12ff58..5a3b4170859 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dummy/DummyAddress.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/dummy/DummyAddress.java @@ -76,6 +76,10 @@ class DummyAddress implements Address { return new DummyAddress(debugger, badLong); } + public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException { + return new DummyAddress(debugger, badLong); + } + // // Java-related routines // @@ -116,6 +120,10 @@ class DummyAddress implements Address { throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { return new DummyOopHandle(debugger, badLong); } + public OopHandle getCompOopHandleAt(long offset) + throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { + return new DummyOopHandle(debugger, badLong); + } // Mutators -- not implemented public void setCIntegerAt(long offset, long numBytes, long value) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxAddress.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxAddress.java index 1112a7847b9..64577da7acd 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxAddress.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxAddress.java @@ -74,6 +74,11 @@ class LinuxAddress implements Address { return debugger.readAddress(addr + offset); } + public Address getCompOopAddressAt(long offset) + throws UnalignedAddressException, UnmappedAddressException { + return debugger.readCompOopAddress(addr + offset); + } + // // Java-related routines // @@ -115,6 +120,11 @@ class LinuxAddress implements Address { return debugger.readOopHandle(addr + offset); } + public OopHandle getCompOopHandleAt(long offset) + throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { + return debugger.readCompOopHandle(addr + offset); + } + // Mutators -- not implemented for now (FIXME) public void setCIntegerAt(long offset, long numBytes, long value) { throw new DebuggerException("Unimplemented"); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebugger.java index b6ae0f45262..b3a062e82a8 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebugger.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebugger.java @@ -45,7 +45,9 @@ public interface LinuxDebugger extends JVMDebugger { public long readCInteger(long address, long numBytes, boolean isUnsigned) throws DebuggerException; public LinuxAddress readAddress(long address) throws DebuggerException; + public LinuxAddress readCompOopAddress(long address) throws DebuggerException; public LinuxOopHandle readOopHandle(long address) throws DebuggerException; + public LinuxOopHandle readCompOopHandle(long address) throws DebuggerException; public long[] getThreadIntegerRegisterSet(int lwp_id) throws DebuggerException; public long getAddressValue(Address addr) throws DebuggerException; public Address newAddress(long value) throws DebuggerException; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java index e92602efd52..7f4159f4a47 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java @@ -423,6 +423,11 @@ public class LinuxDebuggerLocal extends DebuggerBase implements LinuxDebugger { long value = readAddressValue(address); return (value == 0 ? null : new LinuxAddress(this, value)); } + public LinuxAddress readCompOopAddress(long address) + throws UnmappedAddressException, UnalignedAddressException { + long value = readCompOopAddressValue(address); + return (value == 0 ? null : new LinuxAddress(this, value)); + } /** From the LinuxDebugger interface */ public LinuxOopHandle readOopHandle(long address) @@ -431,6 +436,12 @@ public class LinuxDebuggerLocal extends DebuggerBase implements LinuxDebugger { long value = readAddressValue(address); return (value == 0 ? null : new LinuxOopHandle(this, value)); } + public LinuxOopHandle readCompOopHandle(long address) + throws UnmappedAddressException, UnalignedAddressException, + NotInHeapException { + long value = readCompOopAddressValue(address); + return (value == 0 ? null : new LinuxOopHandle(this, value)); + } //---------------------------------------------------------------------- // Thread context access diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcAddress.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcAddress.java index 9bde3f272ae..17c75774dfe 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcAddress.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcAddress.java @@ -72,6 +72,10 @@ class ProcAddress implements Address { return debugger.readAddress(addr + offset); } + public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException { + return debugger.readCompOopAddress(addr + offset); + } + // // Java-related routines // @@ -112,6 +116,10 @@ class ProcAddress implements Address { throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { return debugger.readOopHandle(addr + offset); } + public OopHandle getCompOopHandleAt(long offset) + throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { + return debugger.readCompOopHandle(addr + offset); + } // Mutators -- not implemented for now (FIXME) public void setCIntegerAt(long offset, long numBytes, long value) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebugger.java index d175f1580b8..e17d2b422be 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebugger.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebugger.java @@ -46,7 +46,9 @@ public interface ProcDebugger extends JVMDebugger { public long readCInteger(long address, long numBytes, boolean isUnsigned) throws DebuggerException; public ProcAddress readAddress(long address) throws DebuggerException; + public ProcAddress readCompOopAddress(long address) throws DebuggerException; public ProcOopHandle readOopHandle(long address) throws DebuggerException; + public ProcOopHandle readCompOopHandle(long address) throws DebuggerException; public long[] getThreadIntegerRegisterSet(int tid) throws DebuggerException; public long getAddressValue(Address addr) throws DebuggerException; public Address newAddress(long value) throws DebuggerException; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java index 49edcae486a..5b89e610595 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/proc/ProcDebuggerLocal.java @@ -53,8 +53,6 @@ import sun.jvm.hotspot.utilities.*; */ public class ProcDebuggerLocal extends DebuggerBase implements ProcDebugger { - - protected static final int cacheSize = 16 * 1024 * 1024; // 16 MB //------------------------------------------------------------------------ @@ -337,10 +335,21 @@ public class ProcDebuggerLocal extends DebuggerBase implements ProcDebugger { return (value == 0 ? null : new ProcAddress(this, value)); } + public ProcAddress readCompOopAddress(long address) + throws UnmappedAddressException, UnalignedAddressException { + long value = readCompOopAddressValue(address); + return (value == 0 ? null : new ProcAddress(this, value)); + } + /** From the ProcDebugger interface */ public ProcOopHandle readOopHandle(long address) throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { - long value = readAddressValue(address); + long value = readAddressValue(address); + return (value == 0 ? null : new ProcOopHandle(this, value)); + } + + public ProcOopHandle readCompOopHandle(long address) { + long value = readCompOopAddressValue(address); return (value == 0 ? null : new ProcOopHandle(this, value)); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteAddress.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteAddress.java index 8bd981c649c..287f7cbbc2a 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteAddress.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteAddress.java @@ -71,6 +71,9 @@ class RemoteAddress implements Address { public Address getAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException { return debugger.readAddress(addr + offset); } + public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException { + return debugger.readCompOopAddress(addr + offset); + } // // Java-related routines @@ -112,6 +115,10 @@ class RemoteAddress implements Address { throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { return debugger.readOopHandle(addr + offset); } + public OopHandle getCompOopHandleAt(long offset) + throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { + return debugger.readCompOopHandle(addr + offset); + } // Mutators -- not implemented for now (FIXME) public void setCIntegerAt(long offset, long numBytes, long value) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebugger.java index 2b776a064eb..6850195d4eb 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebugger.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebugger.java @@ -65,6 +65,9 @@ public interface RemoteDebugger extends Remote { public long getJIntSize() throws RemoteException; public long getJLongSize() throws RemoteException; public long getJShortSize() throws RemoteException; + public long getHeapBase() throws RemoteException; + public long getHeapOopSize() throws RemoteException; + public long getLogMinObjAlignmentInBytes() throws RemoteException; public boolean areThreadsEqual(long addrOrId1, boolean isAddress1, long addrOrId2, boolean isAddress2) throws RemoteException; public int getThreadHashCode(long addrOrId, boolean isAddress) throws RemoteException; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java index bcf5e512bda..4be718ef6e2 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerClient.java @@ -85,6 +85,9 @@ public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger { jlongSize = remoteDebugger.getJLongSize(); jshortSize = remoteDebugger.getJShortSize(); javaPrimitiveTypesConfigured = true; + heapBase = remoteDebugger.getHeapBase(); + heapOopSize = remoteDebugger.getHeapOopSize(); + logMinObjAlignmentInBytes = remoteDebugger.getLogMinObjAlignmentInBytes(); } catch (RemoteException e) { throw new DebuggerException(e); @@ -298,12 +301,24 @@ public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger { return (value == 0 ? null : new RemoteAddress(this, value)); } + RemoteAddress readCompOopAddress(long address) + throws UnmappedAddressException, UnalignedAddressException { + long value = readCompOopAddressValue(address); + return (value == 0 ? null : new RemoteAddress(this, value)); + } + RemoteOopHandle readOopHandle(long address) throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { long value = readAddressValue(address); return (value == 0 ? null : new RemoteOopHandle(this, value)); } + RemoteOopHandle readCompOopHandle(long address) + throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { + long value = readCompOopAddressValue(address); + return (value == 0 ? null : new RemoteOopHandle(this, value)); + } + boolean areThreadsEqual(Address addr1, Address addr2) { try { return remoteDebugger.areThreadsEqual(getAddressValue(addr1), true, diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerServer.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerServer.java index 42056f45463..922890fb9ea 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerServer.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/remote/RemoteDebuggerServer.java @@ -114,6 +114,17 @@ public class RemoteDebuggerServer extends UnicastRemoteObject return debugger.getJShortSize(); } + public long getHeapBase() throws RemoteException { + return debugger.getHeapBase(); + } + + public long getHeapOopSize() throws RemoteException { + return debugger.getHeapOopSize(); + } + + public long getLogMinObjAlignmentInBytes() throws RemoteException { + return debugger.getLogMinObjAlignmentInBytes(); + } public boolean areThreadsEqual(long addrOrId1, boolean isAddress1, long addrOrId2, boolean isAddress2) throws RemoteException { ThreadProxy t1 = getThreadProxy(addrOrId1, isAddress1); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Address.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Address.java index 26524d25531..0afbcacfd63 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Address.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Address.java @@ -72,6 +72,10 @@ class Win32Address implements Address { return debugger.readAddress(addr + offset); } + public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException { + return debugger.readCompOopAddress(addr + offset); + } + // // Java-related routines // @@ -112,6 +116,10 @@ class Win32Address implements Address { throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { return debugger.readOopHandle(addr + offset); } + public OopHandle getCompOopHandleAt(long offset) + throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { + return debugger.readCompOopHandle(addr + offset); + } // // C/C++-related mutators diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Debugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Debugger.java index 283c0ae2e0d..3c2558200bc 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Debugger.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32Debugger.java @@ -45,7 +45,9 @@ public interface Win32Debugger extends JVMDebugger { public long readCInteger(long address, long numBytes, boolean isUnsigned) throws DebuggerException; public Win32Address readAddress(long address) throws DebuggerException; + public Win32Address readCompOopAddress(long address) throws DebuggerException; public Win32OopHandle readOopHandle(long address) throws DebuggerException; + public Win32OopHandle readCompOopHandle(long address) throws DebuggerException; public void writeJBoolean(long address, boolean value) throws DebuggerException; public void writeJByte(long address, byte value) throws DebuggerException; public void writeJChar(long address, char value) throws DebuggerException; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32DebuggerLocal.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32DebuggerLocal.java index 0f4b11695aa..0380eb3b529 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32DebuggerLocal.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/win32/Win32DebuggerLocal.java @@ -306,12 +306,22 @@ public class Win32DebuggerLocal extends DebuggerBase implements Win32Debugger { return (Win32Address) newAddress(readAddressValue(address)); } + public Win32Address readCompOopAddress(long address) + throws UnmappedAddressException, UnalignedAddressException { + return (Win32Address) newAddress(readCompOopAddressValue(address)); + } + /** From the Win32Debugger interface */ public Win32OopHandle readOopHandle(long address) throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { long value = readAddressValue(address); return (value == 0 ? null : new Win32OopHandle(this, value)); } + public Win32OopHandle readCompOopHandle(long address) + throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { + long value = readCompOopAddressValue(address); + return (value == 0 ? null : new Win32OopHandle(this, value)); + } /** From the Win32Debugger interface */ public void writeAddress(long address, Win32Address value) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgAddress.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgAddress.java index 6033ee1b192..4a0d7f21cdb 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgAddress.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgAddress.java @@ -72,6 +72,10 @@ class WindbgAddress implements Address { return debugger.readAddress(addr + offset); } + public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException { + return debugger.readCompOopAddress(addr + offset); + } + // // Java-related routines // @@ -113,6 +117,10 @@ class WindbgAddress implements Address { return debugger.readOopHandle(addr + offset); } + public OopHandle getCompOopHandleAt(long offset) + throws UnalignedAddressException, UnmappedAddressException, NotInHeapException { + return debugger.readCompOopHandle(addr + offset); + } // // C/C++-related mutators // diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebugger.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebugger.java index b368058fe13..03654377c6a 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebugger.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebugger.java @@ -45,7 +45,9 @@ public interface WindbgDebugger extends JVMDebugger { public long readCInteger(long address, long numBytes, boolean isUnsigned) throws DebuggerException; public WindbgAddress readAddress(long address) throws DebuggerException; + public WindbgAddress readCompOopAddress(long address) throws DebuggerException; public WindbgOopHandle readOopHandle(long address) throws DebuggerException; + public WindbgOopHandle readCompOopHandle(long address) throws DebuggerException; // The returned array of register contents is guaranteed to be in // the same order as in the DbxDebugger for Solaris/x86 or amd64; that is, diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java index 09a5464169b..687f45a4ebd 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/WindbgDebuggerLocal.java @@ -39,6 +39,7 @@ import sun.jvm.hotspot.debugger.cdbg.*; import sun.jvm.hotspot.debugger.cdbg.basic.BasicDebugEvent; import sun.jvm.hotspot.utilities.*; import sun.jvm.hotspot.utilities.memo.*; +import sun.jvm.hotspot.runtime.*; /**

    An implementation of the JVMDebugger interface which talks to windbg and symbol table management is done in Java.

    @@ -315,12 +316,22 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger return (WindbgAddress) newAddress(readAddressValue(address)); } + public WindbgAddress readCompOopAddress(long address) + throws UnmappedAddressException, UnalignedAddressException { + return (WindbgAddress) newAddress(readCompOopAddressValue(address)); + } + /** From the WindbgDebugger interface */ public WindbgOopHandle readOopHandle(long address) throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { long value = readAddressValue(address); return (value == 0 ? null : new WindbgOopHandle(this, value)); } + public WindbgOopHandle readCompOopHandle(long address) + throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { + long value = readCompOopAddressValue(address); + return (value == 0 ? null : new WindbgOopHandle(this, value)); + } /** From the WindbgDebugger interface */ public int getAddressSize() { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java index ed173c6a2bd..ce9aa9226fe 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java @@ -63,12 +63,22 @@ public class SystemDictionary { javaSystemLoaderField = type.getOopField("_java_system_loader"); nofBuckets = db.lookupIntConstant("SystemDictionary::_nof_buckets").intValue(); - objectKlassField = type.getOopField("_object_klass"); - classLoaderKlassField = type.getOopField("_classloader_klass"); - stringKlassField = type.getOopField("_string_klass"); - systemKlassField = type.getOopField("_system_klass"); - threadKlassField = type.getOopField("_thread_klass"); - threadGroupKlassField = type.getOopField("_threadGroup_klass"); + objectKlassField = type.getOopField(WK_KLASS("object_klass")); + classLoaderKlassField = type.getOopField(WK_KLASS("classloader_klass")); + stringKlassField = type.getOopField(WK_KLASS("string_klass")); + systemKlassField = type.getOopField(WK_KLASS("system_klass")); + threadKlassField = type.getOopField(WK_KLASS("thread_klass")); + threadGroupKlassField = type.getOopField(WK_KLASS("threadGroup_klass")); + } + + // This WK functions must follow the definitions in systemDictionary.hpp: + private static String WK_KLASS(String name) { + //#define WK_KLASS(name) _well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)] + return ("_well_known_klasses[SystemDictionary::"+WK_KLASS_ENUM_NAME(name)+"]"); + } + private static String WK_KLASS_ENUM_NAME(String kname) { + //#define WK_KLASS_ENUM_NAME(kname) kname##_knum + return (kname+"_knum"); } public Dictionary dictionary() { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java index 67fdf0c4915..3b35ea6dbd0 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/Universe.java @@ -53,6 +53,8 @@ public class Universe { // system obj array klass object private static sun.jvm.hotspot.types.OopField systemObjArrayKlassObjField; + private static AddressField heapBaseField; + static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -83,6 +85,8 @@ public class Universe { doubleArrayKlassObjField = type.getOopField("_doubleArrayKlassObj"); systemObjArrayKlassObjField = type.getOopField("_systemObjArrayKlassObj"); + + heapBaseField = type.getAddressField("_heap_base"); } public Universe() { @@ -96,6 +100,14 @@ public class Universe { } } + public static long getHeapBase() { + if (heapBaseField.getValue() == null) { + return 0; + } else { + return heapBaseField.getValue().minus(null); + } + } + /** Returns "TRUE" iff "p" points into the allocated area of the heap. */ public boolean isIn(Address p) { return heap().isIn(p); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Array.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Array.java index 1f78aece062..b04782d8eed 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Array.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Array.java @@ -47,18 +47,52 @@ public class Array extends Oop { private static void initialize(TypeDataBase db) throws WrongTypeException { Type type = db.lookupType("arrayOopDesc"); - length = new CIntField(type.getCIntegerField("_length"), 0); - headerSize = type.getSize(); + typeSize = (int)type.getSize(); } // Size of the arrayOopDesc - private static long headerSize; + private static long headerSize=0; + private static long lengthOffsetInBytes=0; + private static long typeSize; - // Fields - private static CIntField length; + private static long headerSizeInBytes() { + if (headerSize != 0) { + return headerSize; + } + if (VM.getVM().isCompressedOopsEnabled()) { + headerSize = typeSize; + } else { + headerSize = VM.getVM().alignUp(typeSize + VM.getVM().getIntSize(), + VM.getVM().getHeapWordSize()); + } + return headerSize; + } + + private static long headerSize(BasicType type) { + if (Universe.elementTypeShouldBeAligned(type)) { + return alignObjectSize(headerSizeInBytes())/VM.getVM().getHeapWordSize(); + } else { + return headerSizeInBytes()/VM.getVM().getHeapWordSize(); + } + } + + private long lengthOffsetInBytes() { + if (lengthOffsetInBytes != 0) { + return lengthOffsetInBytes; + } + if (VM.getVM().isCompressedOopsEnabled()) { + lengthOffsetInBytes = typeSize - VM.getVM().getIntSize(); + } else { + lengthOffsetInBytes = typeSize; + } + return lengthOffsetInBytes; + } // Accessors for declared fields - public long getLength() { return length.getValue(this); } + public long getLength() { + boolean isUnsigned = true; + return this.getHandle().getCIntegerAt(lengthOffsetInBytes(), VM.getVM().getIntSize(), isUnsigned); + } public long getObjectSize() { ArrayKlass klass = (ArrayKlass) getKlass(); @@ -72,20 +106,12 @@ public class Array extends Oop { } public static long baseOffsetInBytes(BasicType type) { - if (Universe.elementTypeShouldBeAligned(type)) { - return (VM.getVM().isLP64()) ? alignObjectSize(headerSize) - : VM.getVM().alignUp(headerSize, 8); - } else { - return headerSize; - } + return headerSize(type) * VM.getVM().getHeapWordSize(); } public boolean isArray() { return true; } public void iterateFields(OopVisitor visitor, boolean doVMFields) { super.iterateFields(visitor, doVMFields); - if (doVMFields) { - visitor.doCInt(length, true); - } } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java index ccd6f3e33a6..7d06c5cddde 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java @@ -31,10 +31,10 @@ import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.*; -// A ConstantPool is an array containing class constants +// A ConstantPool is an oop containing class constants // as described in the class file -public class ConstantPool extends Array implements ClassConstants { +public class ConstantPool extends Oop implements ClassConstants { // Used for debugging this code private static final boolean DEBUG = false; @@ -55,8 +55,9 @@ public class ConstantPool extends Array implements ClassConstants { tags = new OopField(type.getOopField("_tags"), 0); cache = new OopField(type.getOopField("_cache"), 0); poolHolder = new OopField(type.getOopField("_pool_holder"), 0); + length = new CIntField(type.getCIntegerField("_length"), 0); headerSize = type.getSize(); - elementSize = db.getOopSize(); + elementSize = 0; } ConstantPool(OopHandle handle, ObjectHeap heap) { @@ -68,7 +69,7 @@ public class ConstantPool extends Array implements ClassConstants { private static OopField tags; private static OopField cache; private static OopField poolHolder; - + private static CIntField length; // number of elements in oop private static long headerSize; private static long elementSize; @@ -76,12 +77,22 @@ public class ConstantPool extends Array implements ClassConstants { public TypeArray getTags() { return (TypeArray) tags.getValue(this); } public ConstantPoolCache getCache() { return (ConstantPoolCache) cache.getValue(this); } public Klass getPoolHolder() { return (Klass) poolHolder.getValue(this); } + public int getLength() { return (int)length.getValue(this); } + + private long getElementSize() { + if (elementSize !=0 ) { + return elementSize; + } else { + elementSize = VM.getVM().getOopSize(); + } + return elementSize; + } private long indexOffset(long index) { if (Assert.ASSERTS_ENABLED) { - Assert.that(index > 0 && index < getLength(), "invalid cp index"); + Assert.that(index > 0 && index < getLength(), "invalid cp index " + index + " " + getLength()); } - return (index * elementSize) + headerSize; + return (index * getElementSize()) + headerSize; } public ConstantTag getTagAt(long index) { @@ -464,7 +475,7 @@ public class ConstantPool extends Array implements ClassConstants { } public long getObjectSize() { - return alignObjectSize(headerSize + (getLength() * elementSize)); + return alignObjectSize(headerSize + (getLength() * getElementSize())); } //---------------------------------------------------------------------- diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java index 9285f8e7898..a7930e6466a 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java @@ -31,10 +31,10 @@ import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.*; -// A ConstantPool is an array containing class constants -// as described in the class file - -public class ConstantPoolCache extends Array { +// ConstantPoolCache : A constant pool cache (constantPoolCacheOopDesc). +// See cpCacheOop.hpp for details about this class. +// +public class ConstantPoolCache extends Oop { static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -47,9 +47,9 @@ public class ConstantPoolCache extends Array { Type type = db.lookupType("constantPoolCacheOopDesc"); constants = new OopField(type.getOopField("_constant_pool"), 0); baseOffset = type.getSize(); - Type elType = db.lookupType("ConstantPoolCacheEntry"); elementSize = elType.getSize(); + length = new CIntField(type.getCIntegerField("_length"), 0); } ConstantPoolCache(OopHandle handle, ObjectHeap heap) { @@ -62,6 +62,8 @@ public class ConstantPoolCache extends Array { private static long baseOffset; private static long elementSize; + private static CIntField length; + public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); } @@ -87,6 +89,10 @@ public class ConstantPoolCache extends Array { tty.print("ConstantPoolCache for " + getConstants().getPoolHolder().getName().asString()); } + public int getLength() { + return (int) length.getValue(this); + } + public void iterateFields(OopVisitor visitor, boolean doVMFields) { super.iterateFields(visitor, doVMFields); if (doVMFields) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCacheKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCacheKlass.java index 7d87e984128..ce5d2bf4035 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCacheKlass.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCacheKlass.java @@ -32,7 +32,7 @@ import sun.jvm.hotspot.types.*; // A ConstantPoolCacheKlass is the klass of a ConstantPoolCache -public class ConstantPoolCacheKlass extends ArrayKlass { +public class ConstantPoolCacheKlass extends Klass { static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -43,13 +43,20 @@ public class ConstantPoolCacheKlass extends ArrayKlass { private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { Type type = db.lookupType("constantPoolCacheKlass"); + headerSize = type.getSize() + Oop.getHeaderSize(); } ConstantPoolCacheKlass(OopHandle handle, ObjectHeap heap) { super(handle, heap); } + public long getObjectSize() { return alignObjectSize(headerSize); } + public void printValueOn(PrintStream tty) { tty.print("ConstantPoolCacheKlass"); } + + private static long headerSize; } + + diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolKlass.java index c40a87dab18..a29285aa00f 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolKlass.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolKlass.java @@ -32,7 +32,7 @@ import sun.jvm.hotspot.types.*; // A ConstantPoolKlass is the klass of a ConstantPool -public class ConstantPoolKlass extends ArrayKlass { +public class ConstantPoolKlass extends Klass { static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -43,13 +43,19 @@ public class ConstantPoolKlass extends ArrayKlass { private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { Type type = db.lookupType("constantPoolKlass"); + headerSize = type.getSize() + Oop.getHeaderSize(); } ConstantPoolKlass(OopHandle handle, ObjectHeap heap) { super(handle, heap); } + public long getObjectSize() { return alignObjectSize(headerSize); } + public void printValueOn(PrintStream tty) { tty.print("ConstantPoolKlass"); } -}; + + private static long headerSize; +} + diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/DefaultOopVisitor.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/DefaultOopVisitor.java index 6340ec35f40..0c5b933db9e 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/DefaultOopVisitor.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/DefaultOopVisitor.java @@ -46,6 +46,7 @@ public class DefaultOopVisitor implements OopVisitor { // Callback methods for each field type in an object public void doOop(OopField field, boolean isVMField) {} + public void doOop(NarrowOopField field, boolean isVMField) {} public void doByte(ByteField field, boolean isVMField) {} public void doChar(CharField field, boolean isVMField) {} public void doBoolean(BooleanField field, boolean isVMField) {} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Instance.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Instance.java index f707915ba71..4d8bfbfc045 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Instance.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Instance.java @@ -40,15 +40,26 @@ public class Instance extends Oop { } }); } + private static long typeSize; private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { Type type = db.lookupType("instanceOopDesc"); + typeSize = type.getSize(); } Instance(OopHandle handle, ObjectHeap heap) { super(handle, heap); } + // Returns header size in bytes. + public static long getHeaderSize() { + if (VM.getVM().isCompressedOopsEnabled()) { + return typeSize - VM.getVM().getIntSize(); + } else { + return typeSize; + } + } + public boolean isInstance() { return true; } public void iterateFields(OopVisitor visitor, boolean doVMFields) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index c98a35f3d64..ca95b6c56ed 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -467,7 +467,6 @@ public class InstanceKlass extends Klass { for (int index = 0; index < length; index += NEXT_OFFSET) { short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET); short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); - FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex)); AccessFlags access = new AccessFlags(accessFlags); if (access.isStatic()) { @@ -790,7 +789,11 @@ public class InstanceKlass extends Klass { short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET); FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex)); if (type.isOop()) { - return new OopField(this, index); + if (VM.getVM().isCompressedOopsEnabled()) { + return new NarrowOopField(this, index); + } else { + return new OopField(this, index); + } } if (type.isByte()) { return new ByteField(this, index); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java index 256a6bd4ef1..ec1313187ef 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java @@ -171,8 +171,7 @@ public class Klass extends Oop implements ClassConstants { } public long getObjectSize() { - System.out.println("should not reach here"); - return 0; + throw new RuntimeException("should not reach here"); } /** Array class with specific rank */ diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/NarrowOopField.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/NarrowOopField.java new file mode 100644 index 00000000000..778979eb59c --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/NarrowOopField.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.oops; + +import sun.jvm.hotspot.debugger.*; + +// The class for an oop field simply provides access to the value. +public class NarrowOopField extends OopField { + public NarrowOopField(FieldIdentifier id, long offset, boolean isVMField) { + super(id, offset, isVMField); + } + + public NarrowOopField(sun.jvm.hotspot.types.OopField vmField, long startOffset) { + super(new NamedFieldIdentifier(vmField.getName()), vmField.getOffset() + startOffset, true); + } + + public NarrowOopField(InstanceKlass holder, int fieldArrayIndex) { + super(holder, fieldArrayIndex); + } + + public Oop getValue(Oop obj) { + return obj.getHeap().newOop(getValueAsOopHandle(obj)); + } + + /** Debugging support */ + public OopHandle getValueAsOopHandle(Oop obj) { + return obj.getHandle().getCompOopHandleAt(getOffset()); + } + + public void setValue(Oop obj) throws MutationException { + // Fix this: setOopAt is missing in Address + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjArray.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjArray.java index ff558489f14..7ef6d8d820c 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjArray.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjArray.java @@ -43,7 +43,7 @@ public class ObjArray extends Array { private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { Type type = db.lookupType("objArrayOopDesc"); - elementSize = db.getOopSize(); + elementSize = VM.getVM().getHeapOopSize(); } ObjArray(OopHandle handle, ObjectHeap heap) { @@ -54,9 +54,17 @@ public class ObjArray extends Array { private static long elementSize; - public Oop getObjAt(long index) { + public OopHandle getOopHandleAt(long index) { long offset = baseOffsetInBytes(BasicType.T_OBJECT) + (index * elementSize); - return getHeap().newOop(getHandle().getOopHandleAt(offset)); + if (VM.getVM().isCompressedOopsEnabled()) { + return getHandle().getCompOopHandleAt(offset); + } else { + return getHandle().getOopHandleAt(offset); + } + } + + public Oop getObjAt(long index) { + return getHeap().newOop(getOopHandleAt(index)); } public void printValueOn(PrintStream tty) { @@ -69,7 +77,13 @@ public class ObjArray extends Array { long baseOffset = baseOffsetInBytes(BasicType.T_OBJECT); for (int index = 0; index < length; index++) { long offset = baseOffset + (index * elementSize); - visitor.doOop(new OopField(new IndexableFieldIdentifier(index), offset, false), false); + OopField field; + if (VM.getVM().isCompressedOopsEnabled()) { + field = new NarrowOopField(new IndexableFieldIdentifier(index), offset, false); + } else { + field = new OopField(new IndexableFieldIdentifier(index), offset, false); + } + visitor.doOop(field, false); } } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java index fe849e527d8..0aae96fcf42 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java @@ -41,6 +41,12 @@ import sun.jvm.hotspot.utilities.*; public class ObjectHeap { + private static final boolean DEBUG; + + static { + DEBUG = System.getProperty("sun.jvm.hotspot.oops.ObjectHeap.DEBUG") != null; + } + private OopHandle symbolKlassHandle; private OopHandle methodKlassHandle; private OopHandle constMethodKlassHandle; @@ -152,7 +158,7 @@ public class ObjectHeap { public ObjectHeap(TypeDataBase db) throws WrongTypeException { // Get commonly used sizes of basic types - oopSize = db.getOopSize(); + oopSize = VM.getVM().getOopSize(); byteSize = db.getJByteType().getSize(); charSize = db.getJCharType().getSize(); booleanSize = db.getJBooleanType().getSize(); @@ -440,12 +446,16 @@ public class ObjectHeap { try { // Traverses the space from bottom to top OopHandle handle = bottom.addOffsetToAsOopHandle(0); + while (handle.lessThan(top)) { Oop obj = null; try { obj = newOop(handle); } catch (UnknownOopException exp) { + if (DEBUG) { + throw new RuntimeException(" UnknownOopException " + exp); + } } if (obj == null) { //Find the object size using Printezis bits and skip over diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHistogram.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHistogram.java index 7e30ccf20b5..f263d49ffc3 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHistogram.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHistogram.java @@ -64,8 +64,17 @@ public class ObjectHistogram implements HeapVisitor { List list = getElements(); ObjectHistogramElement.titleOn(tty); Iterator iterator = list.listIterator(); + int num=0; + int totalCount=0; + int totalSize=0; while (iterator.hasNext()) { - ((ObjectHistogramElement) iterator.next()).printOn(tty); + ObjectHistogramElement el = (ObjectHistogramElement) iterator.next(); + num++; + totalCount+=el.getCount(); + totalSize+=el.getSize(); + tty.print(num + ":" + "\t\t"); + el.printOn(tty); } + tty.println("Total : " + "\t" + totalCount + "\t" + totalSize); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHistogramElement.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHistogramElement.java index 9b3df5310d7..65117314f7e 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHistogramElement.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHistogramElement.java @@ -110,12 +110,12 @@ public class ObjectHistogramElement { public static void titleOn(PrintStream tty) { tty.println("Object Histogram:"); tty.println(); - tty.println("Size" + "\t" + "Count" + "\t" + "Class description"); - tty.println("-------------------------------------------------------"); + tty.println("num " + "\t" + " #instances" + "\t" + "#bytes" + "\t" + "Class description"); + tty.println("--------------------------------------------------------------------------"); } public void printOn(PrintStream tty) { - tty.print(size + "\t" + count + "\t"); + tty.print(count + "\t" + size + "\t"); tty.print(getDescription()); tty.println(); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Oop.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Oop.java index 0ace3595754..2bdf7eab706 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Oop.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Oop.java @@ -47,7 +47,8 @@ public class Oop { private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { Type type = db.lookupType("oopDesc"); mark = new CIntField(type.getCIntegerField("_mark"), 0); - klass = new OopField(type.getOopField("_klass"), 0); + klass = new OopField(type.getOopField("_metadata._klass"), 0); + compressedKlass = new NarrowOopField(type.getOopField("_metadata._compressed_klass"), 0); headerSize = type.getSize(); } @@ -67,10 +68,11 @@ public class Oop { public OopHandle getHandle() { return handle; } private static long headerSize; - public static long getHeaderSize() { return headerSize; } + public static long getHeaderSize() { return headerSize; } // Header size in bytes. private static CIntField mark; private static OopField klass; + private static NarrowOopField compressedKlass; public boolean isShared() { return CompactingPermGenGen.isShared(handle); @@ -86,7 +88,13 @@ public class Oop { // Accessors for declared fields public Mark getMark() { return new Mark(getHandle()); } - public Klass getKlass() { return (Klass) klass.getValue(this); } + public Klass getKlass() { + if (VM.getVM().isCompressedOopsEnabled()) { + return (Klass) compressedKlass.getValue(this); + } else { + return (Klass) klass.getValue(this); + } + } public boolean isA(Klass k) { return getKlass().isSubtypeOf(k); @@ -120,7 +128,7 @@ public class Oop { // Align the object size. public static long alignObjectSize(long size) { - return VM.getVM().alignUp(size, VM.getVM().getMinObjAlignmentInBytes()); + return VM.getVM().alignUp(size, VM.getVM().getMinObjAlignment()); } // All vm's align longs, so pad out certain offsets. @@ -163,7 +171,11 @@ public class Oop { void iterateFields(OopVisitor visitor, boolean doVMFields) { if (doVMFields) { visitor.doCInt(mark, true); - visitor.doOop(klass, true); + if (VM.getVM().isCompressedOopsEnabled()) { + visitor.doOop(compressedKlass, true); + } else { + visitor.doOop(klass, true); + } } } @@ -219,6 +231,10 @@ public class Oop { if (handle == null) { return null; } - return handle.getOopHandleAt(klass.getOffset()); + if (VM.getVM().isCompressedOopsEnabled()) { + return handle.getCompOopHandleAt(compressedKlass.getOffset()); + } else { + return handle.getOopHandleAt(klass.getOffset()); + } } }; diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopPrinter.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopPrinter.java index ee6ffa7cc40..0574343d207 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopPrinter.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopPrinter.java @@ -57,6 +57,13 @@ public class OopPrinter implements OopVisitor { Oop.printOopValueOn(field.getValue(getObj()), tty); tty.println(); } + + public void doOop(NarrowOopField field, boolean isVMField) { + printField(field); + Oop.printOopValueOn(field.getValue(getObj()), tty); + tty.println(); + } + public void doChar(CharField field, boolean isVMField) { printField(field); char c = field.getValue(getObj()); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java index d3b7c8b6f91..1613da85bb8 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java @@ -281,8 +281,11 @@ public class OopUtilities implements /* imports */ JVMTIThreadState { } catch (RuntimeException re) { // ignore, currently java_lang_Class::hc_klass_offset is zero } - - hcKlassField = new OopField(new NamedFieldIdentifier("hc_klass"), hcKlassOffset, true); + if (VM.getVM().isCompressedOopsEnabled()) { + hcKlassField = new NarrowOopField(new NamedFieldIdentifier("hc_klass"), hcKlassOffset, true); + } else { + hcKlassField = new OopField(new NamedFieldIdentifier("hc_klass"), hcKlassOffset, true); + } } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopVisitor.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopVisitor.java index 35a671d0a0f..9bb12a45701 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopVisitor.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/OopVisitor.java @@ -41,6 +41,7 @@ public interface OopVisitor { // Callback methods for each field type in an object public void doOop(OopField field, boolean isVMField); + public void doOop(NarrowOopField field, boolean isVMField); public void doByte(ByteField field, boolean isVMField); public void doChar(CharField field, boolean isVMField); public void doBoolean(BooleanField field, boolean isVMField); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/AddressVisitor.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/AddressVisitor.java index a2949af8357..f9c55318fb9 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/AddressVisitor.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/AddressVisitor.java @@ -31,4 +31,5 @@ import sun.jvm.hotspot.debugger.*; public interface AddressVisitor { public void visitAddress(Address addr); + public void visitCompOopAddress(Address addr); } 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 63e6ee2c6bb..ad07426313b 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 @@ -534,7 +534,8 @@ public abstract class Frame implements Cloneable { public void visitValueLocation(Address valueAddr) { } - public void visitDeadLocation(Address deadAddr) { + public void visitNarrowOopLocation(Address compOopAddr) { + addressVisitor.visitCompOopAddress(compOopAddr); } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java index 9ce98f2de9c..c6ab99073e7 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -36,6 +36,7 @@ import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.utilities.*; +import sun.jvm.hotspot.runtime.*; /**

    This class encapsulates the global state of the VM; the universe, object heap, interpreter, etc. It is a Singleton and @@ -93,6 +94,10 @@ public class VM { private boolean isLP64; private int bytesPerLong; private int minObjAlignmentInBytes; + private int logMinObjAlignmentInBytes; + private int heapWordSize; + private int heapOopSize; + private int oopSize; /** This is only present in a non-core build */ private CodeCache codeCache; /** This is only present in a C1 build */ @@ -117,6 +122,7 @@ public class VM { private static Type uintxType; private static CIntegerType boolType; private Boolean sharingEnabled; + private Boolean compressedOopsEnabled; // command line flags supplied to VM - see struct Flag in globals.hpp public static final class Flag { @@ -308,6 +314,11 @@ public class VM { } bytesPerLong = db.lookupIntConstant("BytesPerLong").intValue(); minObjAlignmentInBytes = db.lookupIntConstant("MinObjAlignmentInBytes").intValue(); + // minObjAlignment = db.lookupIntConstant("MinObjAlignment").intValue(); + logMinObjAlignmentInBytes = db.lookupIntConstant("LogMinObjAlignmentInBytes").intValue(); + heapWordSize = db.lookupIntConstant("HeapWordSize").intValue(); + oopSize = db.lookupIntConstant("oopSize").intValue(); + heapOopSize = db.lookupIntConstant("heapOopSize").intValue(); intxType = db.lookupType("intx"); uintxType = db.lookupType("uintx"); @@ -331,6 +342,8 @@ public class VM { throw new RuntimeException("Attempt to initialize VM twice"); } soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian()); + debugger.putHeapConst(Universe.getHeapBase(), soleInstance.getHeapOopSize(), + soleInstance.logMinObjAlignmentInBytes); for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) { ((Observer) iter.next()).update(null, null); } @@ -440,13 +453,17 @@ public class VM { } public long getOopSize() { - return db.getOopSize(); + return oopSize; } public long getLogAddressSize() { return logAddressSize; } + public long getIntSize() { + return db.getJIntType().getSize(); + } + /** NOTE: this offset is in BYTES in this system! */ public long getStackBias() { return stackBias; @@ -467,10 +484,24 @@ public class VM { } /** Get minimum object alignment in bytes. */ - public int getMinObjAlignmentInBytes() { + public int getMinObjAlignment() { return minObjAlignmentInBytes; } + public int getMinObjAlignmentInBytes() { + return minObjAlignmentInBytes; + } + public int getLogMinObjAlignmentInBytes() { + return logMinObjAlignmentInBytes; + } + + public int getHeapWordSize() { + return heapWordSize; + } + + public int getHeapOopSize() { + return heapOopSize; + } /** Utility routine for getting data structure alignment correct */ public long alignUp(long size, long alignment) { return (size + alignment - 1) & ~(alignment - 1); @@ -701,6 +732,14 @@ public class VM { return sharingEnabled.booleanValue(); } + public boolean isCompressedOopsEnabled() { + if (compressedOopsEnabled == null) { + Flag flag = getCommandLineFlag("UseCompressedOops"); + compressedOopsEnabled = (flag == null) ? Boolean.FALSE: + (flag.getBool()? Boolean.TRUE: Boolean.FALSE); + } + return compressedOopsEnabled.booleanValue(); + } // returns null, if not available. public Flag[] getCommandLineFlags() { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/Field.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/Field.java index 4afe853848b..bfda1f18640 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/Field.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/Field.java @@ -109,6 +109,8 @@ public interface Field { public Address getAddress (Address addr) throws UnmappedAddressException, UnalignedAddressException, WrongTypeException; public OopHandle getOopHandle(Address addr) throws UnmappedAddressException, UnalignedAddressException, WrongTypeException, NotInHeapException; + public OopHandle getNarrowOopHandle(Address addr) + throws UnmappedAddressException, UnalignedAddressException, WrongTypeException, NotInHeapException; /**

    These accessors require that the field be static; otherwise, a WrongTypeException will be thrown. Note that type checking is @@ -138,4 +140,6 @@ public interface Field { public Address getAddress () throws UnmappedAddressException, UnalignedAddressException; public OopHandle getOopHandle() throws UnmappedAddressException, UnalignedAddressException, NotInHeapException; + public OopHandle getNarrowOopHandle() + throws UnmappedAddressException, UnalignedAddressException, NotInHeapException; } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/NarrowOopField.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/NarrowOopField.java new file mode 100644 index 00000000000..945d68c4133 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/NarrowOopField.java @@ -0,0 +1,41 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.types; + +import sun.jvm.hotspot.debugger.*; + +/** A specialization of Field which represents a field containing an + narrow oop value and which adds typechecked getValue() routines returning + OopHandles. */ + +public interface NarrowOopField extends OopField { + /** The field must be nonstatic and the type of the field must be an + oop type, or a WrongTypeException will be thrown. */ + public OopHandle getValue(Address addr) throws UnmappedAddressException, UnalignedAddressException, WrongTypeException; + + /** The field must be static and the type of the field must be an + oop type, or a WrongTypeException will be thrown. */ + public OopHandle getValue() throws UnmappedAddressException, UnalignedAddressException, WrongTypeException; +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/Type.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/Type.java index 08fb47f2e9d..b565d326d94 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/Type.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/Type.java @@ -122,5 +122,6 @@ public interface Type { public JShortField getJShortField (String fieldName) throws WrongTypeException; public CIntegerField getCIntegerField (String fieldName) throws WrongTypeException; public OopField getOopField (String fieldName) throws WrongTypeException; + public NarrowOopField getNarrowOopField (String fieldName) throws WrongTypeException; public AddressField getAddressField (String fieldName); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicField.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicField.java index a2f1f540b35..10e2b7aa0aa 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicField.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicField.java @@ -43,6 +43,19 @@ public class BasicField implements Field { /** Used for static fields only */ private Address staticFieldAddress; + // Copy constructor to create NarrowOopField from OopField. + public BasicField(Field fld) { + BasicField field = (BasicField)fld; + + this.db = field.db; + this.containingType = field.containingType; + this.name = field.name; + this.type = field.type; + this.size = field.size; + this.isStatic = field.isStatic; + this.offset = field.offset; + this.staticFieldAddress = field.staticFieldAddress; + } /** offsetInBytes is ignored if the field is static; staticFieldAddress is used only if the field is static. */ public BasicField(BasicTypeDataBase db, Type containingType, String name, Type type, @@ -161,6 +174,13 @@ public class BasicField implements Field { } return addr.getOopHandleAt(offset); } + public OopHandle getNarrowOopHandle(Address addr) + throws UnmappedAddressException, UnalignedAddressException, WrongTypeException, NotInHeapException { + if (isStatic) { + throw new WrongTypeException(); + } + return addr.getCompOopHandleAt(offset); + } //-------------------------------------------------------------------------------- // Dereferencing operations for static fields @@ -234,4 +254,11 @@ public class BasicField implements Field { } return staticFieldAddress.getOopHandleAt(0); } + public OopHandle getNarrowOopHandle() + throws UnmappedAddressException, UnalignedAddressException, WrongTypeException, NotInHeapException { + if (!isStatic) { + throw new WrongTypeException(); + } + return staticFieldAddress.getCompOopHandleAt(0); + } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicFieldWrapper.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicFieldWrapper.java index 0692efd7a15..77717bedcda 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicFieldWrapper.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicFieldWrapper.java @@ -95,6 +95,10 @@ public class BasicFieldWrapper implements Field { throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { return field.getOopHandle(addr); } + public OopHandle getNarrowOopHandle(Address addr) + throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { + return field.getNarrowOopHandle(addr); + } public boolean getJBoolean () throws UnmappedAddressException, UnalignedAddressException, WrongTypeException { return field.getJBoolean(); @@ -130,4 +134,8 @@ public class BasicFieldWrapper implements Field { throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { return field.getOopHandle(); } + public OopHandle getNarrowOopHandle() + throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { + return field.getNarrowOopHandle(); + } } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicNarrowOopField.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicNarrowOopField.java new file mode 100644 index 00000000000..8180d4a3209 --- /dev/null +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicNarrowOopField.java @@ -0,0 +1,65 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.types.basic; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.types.*; + +/** A specialization of BasicField which represents a field containing + an oop value and which adds typechecked getValue() routines + returning OopHandles. */ + +public class BasicNarrowOopField extends BasicOopField implements NarrowOopField { + + private static final boolean DEBUG = false; + + public BasicNarrowOopField (OopField oopf) { + super(oopf); + } + + public BasicNarrowOopField(BasicTypeDataBase db, Type containingType, String name, Type type, + boolean isStatic, long offset, Address staticFieldAddress) { + super(db, containingType, name, type, isStatic, offset, staticFieldAddress); + + if (DEBUG) { + System.out.println(" name " + name + " type " + type + " isStatic " + isStatic + " offset " + offset + " static addr " + staticFieldAddress); + } + if (!type.isOopType()) { + throw new WrongTypeException("Type of a BasicOopField must be an oop type"); + } + } + + /** The field must be nonstatic and the type of the field must be a + Java oop, or a WrongTypeException will be thrown. */ + public OopHandle getValue(Address addr) throws UnmappedAddressException, UnalignedAddressException, WrongTypeException { + return getNarrowOopHandle(addr); + } + + /** The field must be static and the type of the field must be a + Java oop, or a WrongTypeException will be thrown. */ + public OopHandle getValue() throws UnmappedAddressException, UnalignedAddressException, WrongTypeException { + return getNarrowOopHandle(); + } +} diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicOopField.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicOopField.java index fe493802292..1886a4c5324 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicOopField.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicOopField.java @@ -32,6 +32,12 @@ import sun.jvm.hotspot.types.*; returning OopHandles. */ public class BasicOopField extends BasicField implements OopField { + + + public BasicOopField(OopField oopf) { + super(oopf); + } + public BasicOopField(BasicTypeDataBase db, Type containingType, String name, Type type, boolean isStatic, long offset, Address staticFieldAddress) { super(db, containingType, name, type, isStatic, offset, staticFieldAddress); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicType.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicType.java index ef1939a9028..112ff722cb2 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicType.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicType.java @@ -273,6 +273,10 @@ public class BasicType implements Type { return (OopField) field; } + public NarrowOopField getNarrowOopField(String fieldName) throws WrongTypeException { + return (NarrowOopField) new BasicNarrowOopField(getOopField(fieldName)); + } + public AddressField getAddressField(String fieldName) { // This type can not be inferred (for now), so provide a wrapper Field field = getField(fieldName); @@ -287,7 +291,7 @@ public class BasicType implements Type { name was already present in this class. */ public void addField(Field field) { if (nameToFieldMap.get(field.getName()) != null) { - throw new RuntimeException("field of name \"" + field.getName() + "\" already present"); + throw new RuntimeException("field of name \"" + field.getName() + "\" already present in type " + this); } nameToFieldMap.put(field.getName(), field); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java index 80671cada43..5db97d60177 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java @@ -27,6 +27,7 @@ package sun.jvm.hotspot.types.basic; import java.util.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.runtime.VM; /**

    This is a basic implementation of the TypeDataBase interface. It allows an external type database builder to add types to be @@ -146,7 +147,7 @@ public class BasicTypeDataBase implements TypeDataBase { } public long getOopSize() { - return machDesc.getOopSize(); + return VM.getVM().getOopSize(); } public boolean addressTypeIsEqualToType(Address addr, Type type) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/FindInHeapPanel.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/FindInHeapPanel.java index 38f57682a2d..a3eae3bca8d 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/FindInHeapPanel.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/FindInHeapPanel.java @@ -92,7 +92,17 @@ public class FindInHeapPanel extends JPanel { iterated += addressSize; updateProgressBar(); } + public void visitCompOopAddress(Address addr) { + if (error) return; + Address val = addr.getCompOopAddressAt(0); + if (AddressOps.equal(val, value)) { + error = reportResult(addr); + } + iterated += addressSize; + updateProgressBar(); + + } public void epilogue() { iterated = 0; updateProgressBar(); 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 9c5c35dffd6..6d66bb77d84 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 @@ -1077,8 +1077,8 @@ public class HTMLGenerator implements /* imports */ ClassConstants { oms = new OopMapStream(map, OopMapValue.OopTypes.VALUE_VALUE); buf.append(omvIterator.iterate(oms, "Value:", false)); - oms = new OopMapStream(map, OopMapValue.OopTypes.DEAD_VALUE); - buf.append(omvIterator.iterate(oms, "Dead:", false)); + oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE); + buf.append(omvIterator.iterate(oms, "Oop:", false)); oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); buf.append(omvIterator.iterate(oms, "Callee saved:", true)); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/AbstractHeapGraphWriter.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/AbstractHeapGraphWriter.java index 28c9f5e7b16..0da5005f604 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/AbstractHeapGraphWriter.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/AbstractHeapGraphWriter.java @@ -155,6 +155,9 @@ public abstract class AbstractHeapGraphWriter implements HeapGraphWriter { } catch (IOException exp) { throw new RuntimeException(exp); } + } + public void visitCompOopAddress(Address handleAddr) { + throw new RuntimeException("Should not reach here. JNIHandles are not compressed"); } }); } catch (RuntimeException re) { diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java index c1eb5aa467a..16226721865 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java @@ -574,6 +574,10 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter { throw new RuntimeException(exp); } } + public void visitCompOopAddress(Address handleAddr) { + throw new RuntimeException( + " Should not reach here. JNIHandles are not compressed \n"); + } }); } catch (RuntimeException re) { handleRuntimeException(re); @@ -601,8 +605,7 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter { writeObjectID(array.getKlass().getJavaMirror()); final int length = (int) array.getLength(); for (int index = 0; index < length; index++) { - long offset = OBJECT_BASE_OFFSET + index * OBJ_ID_SIZE; - OopHandle handle = array.getHandle().getOopHandleAt(offset); + OopHandle handle = array.getOopHandleAt(index); writeObjectID(getAddressValue(handle)); } } @@ -803,8 +806,13 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter { break; case JVM_SIGNATURE_CLASS: case JVM_SIGNATURE_ARRAY: { - OopHandle handle = ((OopField)field).getValueAsOopHandle(oop); - writeObjectID(getAddressValue(handle)); + if (VM.getVM().isCompressedOopsEnabled()) { + OopHandle handle = ((NarrowOopField)field).getValueAsOopHandle(oop); + writeObjectID(getAddressValue(handle)); + } else { + OopHandle handle = ((OopField)field).getValueAsOopHandle(oop); + writeObjectID(getAddressValue(handle)); + } break; } default: diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java index f3e219c2430..f5ca60a8e5c 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java @@ -282,6 +282,15 @@ public class ReversePtrsAnalysis { markAndTraverse(next); } + public void visitCompOopAddress(Address addr) { + Oop next = heap.newOop(addr.getCompOopHandleAt(0)); + LivenessPathElement lp = new LivenessPathElement(null, + new NamedFieldIdentifier(baseRootDescription + + " @ " + addr)); + rp.put(lp, next); + markAndTraverse(next); + } + private String baseRootDescription; } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/RobustOopDeterminator.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/RobustOopDeterminator.java index 405609f25df..2d6957f5812 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/RobustOopDeterminator.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/RobustOopDeterminator.java @@ -51,7 +51,11 @@ public class RobustOopDeterminator { private static void initialize(TypeDataBase db) { Type type = db.lookupType("oopDesc"); - klassField = type.getOopField("_klass"); + if (VM.getVM().isCompressedOopsEnabled()) { + klassField = type.getNarrowOopField("_metadata._compressed_klass"); + } else { + klassField = type.getOopField("_metadata._klass"); + } } public static boolean oopLooksValid(OopHandle oop) { diff --git a/hotspot/build/windows/projectfiles/tiered/vm.def b/hotspot/build/windows/projectfiles/tiered/vm.def deleted file mode 100644 index 4475c606215..00000000000 --- a/hotspot/build/windows/projectfiles/tiered/vm.def +++ /dev/null @@ -1,7 +0,0 @@ -; -; This .DEF file is a placeholder for one which is automatically -; generated during the build process. See -; build\windows\build_vm_def.sh and -; build\windows\makefiles\makedeps.make (esp. the "-prelink" -; options). -; diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index b6924757324..2fc73534b4e 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -85,6 +85,9 @@ C1_VM_TARGETS=product1 fastdebug1 optimized1 jvmg1 C2_VM_TARGETS=product fastdebug optimized jvmg KERNEL_VM_TARGETS=productkernel fastdebugkernel optimizedkernel jvmgkernel +# JDK directory list +JDK_DIRS=bin include jre lib demo + all: all_product all_fastdebug all_product: product product1 productkernel docs export_product all_fastdebug: fastdebug fastdebug1 fastdebugkernel docs export_fastdebug @@ -341,7 +344,7 @@ copy_product_jdk: $(RM) -r $(JDK_IMAGE_DIR) $(MKDIR) -p $(JDK_IMAGE_DIR) ($(CD) $(JDK_IMPORT_PATH) && \ - $(TAR) -cf - bin include jre lib) | \ + $(TAR) -cf - $(JDK_DIRS)) | \ ($(CD) $(JDK_IMAGE_DIR) && $(TAR) -xf -) copy_fastdebug_jdk: @@ -349,11 +352,11 @@ copy_fastdebug_jdk: $(MKDIR) -p $(JDK_IMAGE_DIR)/fastdebug if [ -d $(JDK_IMPORT_PATH)/fastdebug ] ; then \ ($(CD) $(JDK_IMPORT_PATH)/fastdebug && \ - $(TAR) -cf - bin include jre lib) | \ + $(TAR) -cf - $(JDK_DIRS)) | \ ($(CD) $(JDK_IMAGE_DIR)/fastdebug && $(TAR) -xf -) ; \ else \ ($(CD) $(JDK_IMPORT_PATH) && \ - $(TAR) -cf - bin include jre lib) | \ + $(TAR) -cf - $(JDK_DIRS)) | \ ($(CD) $(JDK_IMAGE_DIR)/fastdebug && $(TAR) -xf -) ; \ fi @@ -362,15 +365,15 @@ copy_debug_jdk: $(MKDIR) -p $(JDK_IMAGE_DIR)/debug if [ -d $(JDK_IMPORT_PATH)/debug ] ; then \ ($(CD) $(JDK_IMPORT_PATH)/debug && \ - $(TAR) -cf - bin include jre lib) | \ + $(TAR) -cf - $(JDK_DIRS)) | \ ($(CD) $(JDK_IMAGE_DIR)/debug && $(TAR) -xf -) ; \ elif [ -d $(JDK_IMPORT_PATH)/fastdebug ] ; then \ ($(CD) $(JDK_IMPORT_PATH)/fastdebug && \ - $(TAR) -cf - bin include jre lib) | \ + $(TAR) -cf - $(JDK_DIRS)) | \ ($(CD) $(JDK_IMAGE_DIR)/debug && $(TAR) -xf -) ; \ else \ ($(CD) $(JDK_IMPORT_PATH) && \ - $(TAR) -cf - bin include jre lib) | \ + $(TAR) -cf - $(JDK_DIRS)) | \ ($(CD) $(JDK_IMAGE_DIR)/debug && $(TAR) -xf -) ; \ fi diff --git a/hotspot/make/defs.make b/hotspot/make/defs.make index f3e686ae54e..056d90c4846 100644 --- a/hotspot/make/defs.make +++ b/hotspot/make/defs.make @@ -57,6 +57,7 @@ endef # When the tree of subdirs is built, this setting is stored in each flags.make. GAMMADIR := $(shell until ([ -d dev ]&&echo $${GAMMADIR:-/GAMMADIR/}) || ([ -d src/share/vm ]&&pwd); do cd ..; done) HS_SRC_DIR=$(GAMMADIR)/src +HS_MAKE_DIR=$(GAMMADIR)/make HS_BUILD_DIR=$(GAMMADIR)/build ifeq ($(USER),) @@ -170,17 +171,17 @@ endif # The platform dependent defs.make defines platform specific variable such # as ARCH, EXPORT_LIST etc. We must place the include here after BOOTDIR is defined. -include $(GAMMADIR)/build/$(OSNAME)/makefiles/defs.make +include $(GAMMADIR)/make/$(OSNAME)/makefiles/defs.make # We are trying to put platform specific defintions -# files to build/$(OSNAME)/makefiles dictory. However +# files to make/$(OSNAME)/makefiles dictory. However # some definitions are common for both linux and solaris, # so we put them here. ifneq ($(OSNAME),windows) - ABS_OUTPUTDIR := $(shell $(CD) $(OUTPUTDIR); $(PWD)) + ABS_OUTPUTDIR := $(shell mkdir -p $(OUTPUTDIR); $(CD) $(OUTPUTDIR); $(PWD)) ABS_BOOTDIR := $(shell $(CD) $(BOOTDIR); $(PWD)) ABS_GAMMADIR := $(shell $(CD) $(GAMMADIR); $(PWD)) - ABS_OS_MAKEFILE := $(shell $(CD) $(HS_BUILD_DIR)/$(OSNAME); $(PWD))/Makefile + ABS_OS_MAKEFILE := $(shell $(CD) $(HS_MAKE_DIR)/$(OSNAME); $(PWD))/Makefile # uname, HotSpot source directory, build directory and JDK use different names # for CPU architectures. diff --git a/hotspot/make/hotspot_distro b/hotspot/make/hotspot_distro new file mode 100644 index 00000000000..9b111a2b3ec --- /dev/null +++ b/hotspot/make/hotspot_distro @@ -0,0 +1,14 @@ +# +# Copyright 2006-2007 Sun Microsystems, Inc. All rights reserved. +# SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. +# + +# +# This file format must remain compatible with both +# GNU Makefile and Microsoft nmake formats. +# + +# Don't put quotes (fail windows build). +HOTSPOT_VM_DISTRO=Java HotSpot(TM) +COMPANY_NAME=Sun Microsystems, Inc. +PRODUCT_NAME=Java(TM) Platform SE diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 573a5ad3258..c4478727175 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -31,11 +31,11 @@ # # Don't put quotes (fail windows build). -HOTSPOT_VM_COPYRIGHT=Copyright 2007 +HOTSPOT_VM_COPYRIGHT=Copyright 2008 -HS_MAJOR_VER=12 +HS_MAJOR_VER=13 HS_MINOR_VER=0 -HS_BUILD_NUMBER=03 +HS_BUILD_NUMBER=01 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 diff --git a/hotspot/make/jprt.properties b/hotspot/make/jprt.properties index 1e9f5fb6413..fd5a75de042 100644 --- a/hotspot/make/jprt.properties +++ b/hotspot/make/jprt.properties @@ -29,6 +29,11 @@ JPRT.tools.default.release=jdk1.7.0 # Build result bundles are not partial builds| but include everything JPRT.need.sibling.build=false +# Directories needed to build +JPRT.bundle.src.dirs=make src agent +JPRT.bundle.exclude.src.dirs=build + + # Standard list of JPRT build targets for this workspace JPRT.build.targets= \ solaris_sparc_5.10-{product|fastdebug|debug}, \ diff --git a/hotspot/build/linux/Makefile b/hotspot/make/linux/Makefile similarity index 94% rename from hotspot/build/linux/Makefile rename to hotspot/make/linux/Makefile index 106344f0dbe..0e1ee65277a 100644 --- a/hotspot/build/linux/Makefile +++ b/hotspot/make/linux/Makefile @@ -59,7 +59,7 @@ include ../../make/defs.make else include $(GAMMADIR)/make/defs.make endif -include $(GAMMADIR)/build/$(OSNAME)/makefiles/rules.make +include $(GAMMADIR)/make/$(OSNAME)/makefiles/rules.make ifndef LP64 ifndef CC_INTERP @@ -182,7 +182,7 @@ TARGETS_C1 = $(addsuffix 1,$(TARGETS)) TARGETS_TIERED = $(addsuffix tiered,$(TARGETS)) TARGETS_CORE = $(addsuffix core,$(TARGETS)) -BUILDTREE_MAKE = $(GAMMADIR)/build/$(OSNAME)/makefiles/buildtree.make +BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) ARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) @@ -225,24 +225,24 @@ check_j2se_version: fi $(SUBDIRS_TIERED): $(BUILDTREE_MAKE) - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/build/$(OSNAME)/Makefile checks + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=tiered $(SUBDIRS_C2): $(BUILDTREE_MAKE) ifdef FORCE_TIERED - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/build/$(OSNAME)/Makefile checks + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=tiered FORCE_TIERED=1 else - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/build/$(OSNAME)/Makefile checks + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=compiler2 endif $(SUBDIRS_C1): $(BUILDTREE_MAKE) - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/build/$(OSNAME)/Makefile checks + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=compiler1 $(SUBDIRS_CORE): $(BUILDTREE_MAKE) - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/build/$(OSNAME)/Makefile checks + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=core # Define INSTALL=y at command line to automatically copy JVM into JAVA_HOME @@ -284,7 +284,7 @@ treecore: $(SUBDIRS_CORE) # Hence create a docs directory beside ...$(ARCH)_[...] docs: checks $(QUIETLY) mkdir -p $(SUBDIR_DOCS) - $(MAKE) -f $(GAMMADIR)/build/$(OSNAME)/makefiles/jvmti.make $(MFLAGS) $(BUILDTREE_VARS) JvmtiOutDir=$(SUBDIR_DOCS) jvmtidocs + $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/makefiles/jvmti.make $(MFLAGS) $(BUILDTREE_VARS) JvmtiOutDir=$(SUBDIR_DOCS) jvmtidocs # Synonyms for win32-like targets. compiler2: jvmg product @@ -301,7 +301,7 @@ clean_compiler1 clean_compiler2 clean_core: clean: clean_compiler2 clean_compiler1 clean_core clean_docs -include $(GAMMADIR)/build/$(OSNAME)/makefiles/cscope.make +include $(GAMMADIR)/make/$(OSNAME)/makefiles/cscope.make #------------------------------------------------------------------------------- diff --git a/hotspot/build/linux/Queens.class b/hotspot/make/linux/Queens.class similarity index 100% rename from hotspot/build/linux/Queens.class rename to hotspot/make/linux/Queens.class diff --git a/hotspot/build/linux/README b/hotspot/make/linux/README similarity index 100% rename from hotspot/build/linux/README rename to hotspot/make/linux/README diff --git a/hotspot/build/linux/adlc_updater b/hotspot/make/linux/adlc_updater similarity index 100% rename from hotspot/build/linux/adlc_updater rename to hotspot/make/linux/adlc_updater diff --git a/hotspot/build/linux/build.sh b/hotspot/make/linux/build.sh similarity index 94% rename from hotspot/build/linux/build.sh rename to hotspot/make/linux/build.sh index a8b2630e3cf..4239c6dcbe9 100644 --- a/hotspot/build/linux/build.sh +++ b/hotspot/make/linux/build.sh @@ -91,5 +91,5 @@ case ${Location} in esac echo \ -${GNUMAKE} -f ${Location}/build/linux/Makefile $Build_Options GAMMADIR=${Location} -${GNUMAKE} -f ${Location}/build/linux/Makefile $Build_Options GAMMADIR=${Location} +${GNUMAKE} -f ${Location}/make/linux/Makefile $Build_Options GAMMADIR=${Location} +${GNUMAKE} -f ${Location}/make/linux/Makefile $Build_Options GAMMADIR=${Location} diff --git a/hotspot/build/linux/makefiles/adjust-mflags.sh b/hotspot/make/linux/makefiles/adjust-mflags.sh similarity index 100% rename from hotspot/build/linux/makefiles/adjust-mflags.sh rename to hotspot/make/linux/makefiles/adjust-mflags.sh diff --git a/hotspot/build/linux/makefiles/adlc.make b/hotspot/make/linux/makefiles/adlc.make similarity index 98% rename from hotspot/build/linux/makefiles/adlc.make rename to hotspot/make/linux/makefiles/adlc.make index 9ed67794f07..16e48c84ed5 100644 --- a/hotspot/build/linux/makefiles/adlc.make +++ b/hotspot/make/linux/makefiles/adlc.make @@ -26,7 +26,7 @@ # build directories. # It knows how to compile, link, and run the adlc. -include $(GAMMADIR)/build/$(Platform_os_family)/makefiles/rules.make +include $(GAMMADIR)/make/$(Platform_os_family)/makefiles/rules.make # ######################################################################### @@ -138,7 +138,7 @@ endif # used to selectively update generated adlc files. This should # provide a nice compilation speed improvement. # -ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/build/$(OS) +ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/make/$(OS) ADLC_UPDATER = adlc_updater # This action refreshes all generated adlc files simultaneously. diff --git a/hotspot/build/linux/makefiles/amd64.make b/hotspot/make/linux/makefiles/amd64.make similarity index 100% rename from hotspot/build/linux/makefiles/amd64.make rename to hotspot/make/linux/makefiles/amd64.make diff --git a/hotspot/build/linux/makefiles/buildtree.make b/hotspot/make/linux/makefiles/buildtree.make similarity index 89% rename from hotspot/build/linux/makefiles/buildtree.make rename to hotspot/make/linux/makefiles/buildtree.make index a71aa64f12e..54a30d2ad0a 100644 --- a/hotspot/build/linux/makefiles/buildtree.make +++ b/hotspot/make/linux/makefiles/buildtree.make @@ -64,9 +64,9 @@ QUIETLY$(MAKE_VERBOSE) = @ TESTFLAGS = -Xbatch -showversion ifdef USE_SUNCC -PLATFORM_FILE = $(GAMMADIR)/build/$(OS_FAMILY)/platform_$(BUILDARCH).suncc +PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH).suncc else -PLATFORM_FILE = $(GAMMADIR)/build/$(OS_FAMILY)/platform_$(BUILDARCH) +PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH) endif ifdef FORCE_TIERED @@ -111,7 +111,7 @@ TARGETS = debug fastdebug jvmg optimized product profiled SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) # For dependencies and recursive makes. -BUILDTREE_MAKE = $(GAMMADIR)/build/$(OS_FAMILY)/makefiles/buildtree.make +BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make \ env.sh env.csh .dbxrc test_gamma @@ -133,19 +133,19 @@ endif ifndef HOTSPOT_BUILD_USER HOTSPOT_BUILD_USER := $(shell whoami) endif -# Define HOTSPOT_VM_DISTRO based on settings in build/hotspot_distro -# or build/closed/hotspot_distro. +# Define HOTSPOT_VM_DISTRO based on settings in make/openjdk_distro +# or make/hotspot_distro. ifndef HOTSPOT_VM_DISTRO CLOSED_DIR_EXISTS := $(shell \ - if [ -d $(GAMMADIR)/build/closed ] ; then \ + if [ -d $(GAMMADIR)/src/closed ] ; then \ echo true; \ else \ echo false; \ fi) ifeq ($(CLOSED_DIR_EXISTS), true) - include $(GAMMADIR)/build/closed/hotspot_distro + include $(GAMMADIR)/make/hotspot_distro else - include $(GAMMADIR)/build/hotspot_distro + include $(GAMMADIR)/make/openjdk_distro endif endif @@ -199,8 +199,8 @@ flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \ echo "SYSDEFS += \$$(HOTSPOT_EXTRA_SYSDEFS)"; \ echo; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \ ) > $@ flags_vm.make: $(BUILDTREE_MAKE) ../shared_dirs.lst @@ -209,8 +209,8 @@ flags_vm.make: $(BUILDTREE_MAKE) ../shared_dirs.lst $(BUILDTREE_COMMENT); \ echo; \ [ "$(TARGET)" = profiled ] && \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/optimized.make"; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/$(TARGET).make"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/optimized.make"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(TARGET).make"; \ ) > $@ ../shared_dirs.lst: $(BUILDTREE_MAKE) $(GAMMADIR)/src/share/vm @@ -226,7 +226,7 @@ Makefile: $(BUILDTREE_MAKE) echo; \ echo include flags.make; \ echo; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/top.make"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/top.make"; \ ) > $@ vm.make: $(BUILDTREE_MAKE) @@ -237,7 +237,7 @@ vm.make: $(BUILDTREE_MAKE) echo include flags.make; \ echo include flags_vm.make; \ echo; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/$(@F)"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ adlc.make: $(BUILDTREE_MAKE) @@ -247,7 +247,7 @@ adlc.make: $(BUILDTREE_MAKE) echo; \ echo include flags.make; \ echo; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/$(@F)"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ jvmti.make: $(BUILDTREE_MAKE) @@ -257,7 +257,7 @@ jvmti.make: $(BUILDTREE_MAKE) echo; \ echo include flags.make; \ echo; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/$(@F)"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ sa.make: $(BUILDTREE_MAKE) @@ -267,7 +267,7 @@ sa.make: $(BUILDTREE_MAKE) echo; \ echo include flags.make; \ echo; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/$(@F)"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ env.sh: $(BUILDTREE_MAKE) @@ -339,7 +339,7 @@ test_gamma: $(BUILDTREE_MAKE) echo "then"; \ echo " $(WRONG_DATA_MODE_MSG); exit 0;"; \ echo "fi"; \ - echo 'CLASSPATH="$(GAMMADIR)/build/$(OS_FAMILY):$$CLASSPATH"'; \ + echo 'CLASSPATH="$(GAMMADIR)/make/$(OS_FAMILY):$$CLASSPATH"'; \ echo '[ -f gamma_g ] && { gamma=gamma_g; }'; \ echo './$${gamma:-gamma} $(TESTFLAGS) Queens < /dev/null'; \ ) > $@ diff --git a/hotspot/build/linux/makefiles/compiler1.make b/hotspot/make/linux/makefiles/compiler1.make similarity index 100% rename from hotspot/build/linux/makefiles/compiler1.make rename to hotspot/make/linux/makefiles/compiler1.make diff --git a/hotspot/build/linux/makefiles/compiler2.make b/hotspot/make/linux/makefiles/compiler2.make similarity index 100% rename from hotspot/build/linux/makefiles/compiler2.make rename to hotspot/make/linux/makefiles/compiler2.make diff --git a/hotspot/build/linux/makefiles/core.make b/hotspot/make/linux/makefiles/core.make similarity index 100% rename from hotspot/build/linux/makefiles/core.make rename to hotspot/make/linux/makefiles/core.make diff --git a/hotspot/build/linux/makefiles/cscope.make b/hotspot/make/linux/makefiles/cscope.make similarity index 91% rename from hotspot/build/linux/makefiles/cscope.make rename to hotspot/make/linux/makefiles/cscope.make index 149da265870..13ee5b65d0e 100644 --- a/hotspot/build/linux/makefiles/cscope.make +++ b/hotspot/make/linux/makefiles/cscope.make @@ -38,6 +38,7 @@ include $(GAMMADIR)/make/scm.make NAWK = awk RM = rm -f +HG = hg CS_TOP = ../.. CSDIRS = $(CS_TOP)/src $(CS_TOP)/build @@ -121,9 +122,9 @@ cscope cscope.out: cscope.files FORCE # relevant files first. cscope.files: .cscope.files.raw echo "$(CSINCS)" > $@ - -egrep -v "\.java|\/build\/" $< >> $@ + -egrep -v "\.java|\/make\/" $< >> $@ -fgrep ".java" $< >> $@ - -fgrep "/build/" $< >> $@ + -fgrep "/make/" $< >> $@ .cscope.files.raw: .nametable.files -find $(CSDIRS) -type d \( $(CS_PRUNE) \) -prune -o \ @@ -140,14 +141,17 @@ TAGS.clean: nametable.clean # .nametable.files and .nametable.files.tmp are used to determine if any files # were added to/deleted from/renamed in the workspace. If not, then there's -# normally no need to run find. To force a 'find': gmake nametable.clean. +# normally no need to rebuild the cscope database. To force a rebuild of +# the cscope database: gmake nametable.clean. .nametable.files: .nametable.files.tmp - cmp -s $@ $< || cp $< $@ - -.nametable.files.tmp: $(CS_TOP)/Codemgr_wsdata/nametable - $(NAWK) \ - '{ if (sub("( [a-z0-9]{2,8}){4}$$", "")) print $$0; }' $< > $@ + ( cmp -s $@ $< ) || ( cp $< $@ ) + -$(RM) $< +# `hg status' is slightly faster than `hg fstatus'. Both are +# quite a bit slower on an NFS mounted file system, so this is +# really geared towards repos on local file systems. +.nametable.files.tmp: + -$(HG) fstatus -acmn > $@ nametable.clean: -$(RM) .nametable.files .nametable.files.tmp diff --git a/hotspot/build/linux/makefiles/debug.make b/hotspot/make/linux/makefiles/debug.make similarity index 96% rename from hotspot/build/linux/makefiles/debug.make rename to hotspot/make/linux/makefiles/debug.make index 0ef44d6200a..75bb950891d 100644 --- a/hotspot/build/linux/makefiles/debug.make +++ b/hotspot/make/linux/makefiles/debug.make @@ -30,7 +30,7 @@ DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@) CFLAGS += $(DEBUG_CFLAGS/BYFILE) # Linker mapfile -MAPFILE = $(GAMMADIR)/build/linux/makefiles/mapfile-vers-debug +MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-debug _JUNK_ := $(shell echo -e >&2 ""\ "----------------------------------------------------------------------\n" \ diff --git a/hotspot/build/linux/makefiles/defs.make b/hotspot/make/linux/makefiles/defs.make similarity index 100% rename from hotspot/build/linux/makefiles/defs.make rename to hotspot/make/linux/makefiles/defs.make diff --git a/hotspot/build/linux/makefiles/dtrace.make b/hotspot/make/linux/makefiles/dtrace.make similarity index 100% rename from hotspot/build/linux/makefiles/dtrace.make rename to hotspot/make/linux/makefiles/dtrace.make diff --git a/hotspot/build/linux/makefiles/fastdebug.make b/hotspot/make/linux/makefiles/fastdebug.make similarity index 97% rename from hotspot/build/linux/makefiles/fastdebug.make rename to hotspot/make/linux/makefiles/fastdebug.make index 628f8bb99ba..c7ae47ac966 100644 --- a/hotspot/build/linux/makefiles/fastdebug.make +++ b/hotspot/make/linux/makefiles/fastdebug.make @@ -56,7 +56,7 @@ CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE) # to inhibit the effect of the previous line on CFLAGS. # Linker mapfile -MAPFILE = $(GAMMADIR)/build/linux/makefiles/mapfile-vers-debug +MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-debug G_SUFFIX = VERSION = optimized diff --git a/hotspot/build/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make similarity index 100% rename from hotspot/build/linux/makefiles/gcc.make rename to hotspot/make/linux/makefiles/gcc.make diff --git a/hotspot/build/linux/makefiles/hp.make b/hotspot/make/linux/makefiles/hp.make similarity index 100% rename from hotspot/build/linux/makefiles/hp.make rename to hotspot/make/linux/makefiles/hp.make diff --git a/hotspot/build/linux/makefiles/hp1.make b/hotspot/make/linux/makefiles/hp1.make similarity index 100% rename from hotspot/build/linux/makefiles/hp1.make rename to hotspot/make/linux/makefiles/hp1.make diff --git a/hotspot/build/linux/makefiles/i486.make b/hotspot/make/linux/makefiles/i486.make similarity index 100% rename from hotspot/build/linux/makefiles/i486.make rename to hotspot/make/linux/makefiles/i486.make diff --git a/hotspot/make/linux/makefiles/ia64.make b/hotspot/make/linux/makefiles/ia64.make new file mode 100644 index 00000000000..b7c3aa27777 --- /dev/null +++ b/hotspot/make/linux/makefiles/ia64.make @@ -0,0 +1,43 @@ +# +# Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# +# + +# +# IA64 only uses c++ based interpreter +CFLAGS += -DCC_INTERP -D_LP64=1 -DVM_LITTLE_ENDIAN +# Hotspot uses very unstrict aliasing turn this optimization off +OPT_CFLAGS += -fno-strict-aliasing +ifeq ($(VERSION),debug) +ASM_FLAGS= -DDEBUG +else +ASM_FLAGS= +endif +# workaround gcc bug in compiling varargs +OPT_CFLAGS/jni.o = -O0 + +# gcc/ia64 has a bug that internal gcc functions linked with libjvm.so +# are made public. Hiding those symbols will cause undefined symbol error +# when VM is dropped into older JDK. We probably will need an IA64 +# mapfile to include those symbols as a workaround. Disable linker mapfile +# for now. +LDNOMAP=true diff --git a/hotspot/build/linux/makefiles/jsig.make b/hotspot/make/linux/makefiles/jsig.make similarity index 100% rename from hotspot/build/linux/makefiles/jsig.make rename to hotspot/make/linux/makefiles/jsig.make diff --git a/hotspot/build/linux/makefiles/jvmg.make b/hotspot/make/linux/makefiles/jvmg.make similarity index 96% rename from hotspot/build/linux/makefiles/jvmg.make rename to hotspot/make/linux/makefiles/jvmg.make index dcdb2e82bb5..9bf70b45e1b 100644 --- a/hotspot/build/linux/makefiles/jvmg.make +++ b/hotspot/make/linux/makefiles/jvmg.make @@ -33,7 +33,7 @@ CFLAGS += $(DEBUG_CFLAGS/BYFILE) # to inhibit the effect of the previous line on CFLAGS. # Linker mapfile -MAPFILE = $(GAMMADIR)/build/linux/makefiles/mapfile-vers-debug +MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-debug G_SUFFIX = VERSION = debug diff --git a/hotspot/build/linux/makefiles/jvmti.make b/hotspot/make/linux/makefiles/jvmti.make similarity index 98% rename from hotspot/build/linux/makefiles/jvmti.make rename to hotspot/make/linux/makefiles/jvmti.make index d00e773aea1..a73624857f8 100644 --- a/hotspot/build/linux/makefiles/jvmti.make +++ b/hotspot/make/linux/makefiles/jvmti.make @@ -27,7 +27,7 @@ # # It knows how to build and run the tools to generate jvmti. -include $(GAMMADIR)/build/linux/makefiles/rules.make +include $(GAMMADIR)/make/linux/makefiles/rules.make # ######################################################################### diff --git a/hotspot/build/linux/makefiles/launcher.make b/hotspot/make/linux/makefiles/launcher.make similarity index 100% rename from hotspot/build/linux/makefiles/launcher.make rename to hotspot/make/linux/makefiles/launcher.make diff --git a/hotspot/build/linux/makefiles/makedeps.make b/hotspot/make/linux/makefiles/makedeps.make similarity index 97% rename from hotspot/build/linux/makefiles/makedeps.make rename to hotspot/make/linux/makefiles/makedeps.make index d503926456e..7bb452ace33 100644 --- a/hotspot/build/linux/makefiles/makedeps.make +++ b/hotspot/make/linux/makefiles/makedeps.make @@ -22,7 +22,7 @@ # # -include $(GAMMADIR)/build/linux/makefiles/rules.make +include $(GAMMADIR)/make/linux/makefiles/rules.make COMPILE.JAVAC.FLAGS += -d $(OUTDIR) diff --git a/hotspot/build/linux/makefiles/mapfile-vers-debug b/hotspot/make/linux/makefiles/mapfile-vers-debug similarity index 97% rename from hotspot/build/linux/makefiles/mapfile-vers-debug rename to hotspot/make/linux/makefiles/mapfile-vers-debug index 3f73de30725..da8e6798f28 100644 --- a/hotspot/build/linux/makefiles/mapfile-vers-debug +++ b/hotspot/make/linux/makefiles/mapfile-vers-debug @@ -1,4 +1,6 @@ # +# @(#)mapfile-vers-debug 1.18 07/10/25 16:47:35 +# # # Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -75,6 +77,11 @@ SUNWprivate_1.1 { JVM_DesiredAssertionStatus; JVM_DisableCompiler; JVM_DoPrivileged; + JVM_DTraceGetVersion; + JVM_DTraceActivate; + JVM_DTraceIsProbeEnabled; + JVM_DTraceIsSupported; + JVM_DTraceDispose; JVM_DumpAllStacks; JVM_DumpThreads; JVM_EnableCompiler; @@ -272,7 +279,9 @@ SUNWprivate_1.1 { jio_snprintf; jio_vfprintf; jio_vsnprintf; - fork1; + fork1; + numa_warn; + numa_error; # Needed because there is no JVM interface for this. sysThreadAvailableStackWithSlack; diff --git a/hotspot/build/linux/makefiles/mapfile-vers-jsig b/hotspot/make/linux/makefiles/mapfile-vers-jsig similarity index 100% rename from hotspot/build/linux/makefiles/mapfile-vers-jsig rename to hotspot/make/linux/makefiles/mapfile-vers-jsig diff --git a/hotspot/build/linux/makefiles/mapfile-vers-product b/hotspot/make/linux/makefiles/mapfile-vers-product similarity index 96% rename from hotspot/build/linux/makefiles/mapfile-vers-product rename to hotspot/make/linux/makefiles/mapfile-vers-product index df2994fcd49..7f5407c1309 100644 --- a/hotspot/build/linux/makefiles/mapfile-vers-product +++ b/hotspot/make/linux/makefiles/mapfile-vers-product @@ -1,4 +1,6 @@ # +# @(#)mapfile-vers-product 1.19 08/02/12 10:56:37 +# # # Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -75,6 +77,11 @@ SUNWprivate_1.1 { JVM_DesiredAssertionStatus; JVM_DisableCompiler; JVM_DoPrivileged; + JVM_DTraceGetVersion; + JVM_DTraceActivate; + JVM_DTraceIsProbeEnabled; + JVM_DTraceIsSupported; + JVM_DTraceDispose; JVM_DumpAllStacks; JVM_DumpThreads; JVM_EnableCompiler; @@ -267,7 +274,9 @@ SUNWprivate_1.1 { jio_snprintf; jio_vfprintf; jio_vsnprintf; - fork1; + fork1; + numa_warn; + numa_error; # Needed because there is no JVM interface for this. sysThreadAvailableStackWithSlack; diff --git a/hotspot/build/linux/makefiles/optimized.make b/hotspot/make/linux/makefiles/optimized.make similarity index 96% rename from hotspot/build/linux/makefiles/optimized.make rename to hotspot/make/linux/makefiles/optimized.make index d85775f6c6a..0d6aff8e91d 100644 --- a/hotspot/build/linux/makefiles/optimized.make +++ b/hotspot/make/linux/makefiles/optimized.make @@ -38,7 +38,7 @@ CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE) # to inhibit the effect of the previous line on CFLAGS. # Linker mapfile -MAPFILE = $(GAMMADIR)/build/linux/makefiles/mapfile-vers-debug +MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-debug G_SUFFIX = VERSION = optimized diff --git a/hotspot/build/linux/makefiles/product.make b/hotspot/make/linux/makefiles/product.make similarity index 96% rename from hotspot/build/linux/makefiles/product.make rename to hotspot/make/linux/makefiles/product.make index 6b6ccab740b..a128c1101fa 100644 --- a/hotspot/build/linux/makefiles/product.make +++ b/hotspot/make/linux/makefiles/product.make @@ -38,7 +38,7 @@ CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE) # to inhibit the effect of the previous line on CFLAGS. # Linker mapfile -MAPFILE = $(GAMMADIR)/build/linux/makefiles/mapfile-vers-product +MAPFILE = $(GAMMADIR)/make/linux/makefiles/mapfile-vers-product G_SUFFIX = SYSDEFS += -DPRODUCT diff --git a/hotspot/build/linux/makefiles/profiled.make b/hotspot/make/linux/makefiles/profiled.make similarity index 100% rename from hotspot/build/linux/makefiles/profiled.make rename to hotspot/make/linux/makefiles/profiled.make diff --git a/hotspot/build/linux/makefiles/rules.make b/hotspot/make/linux/makefiles/rules.make similarity index 100% rename from hotspot/build/linux/makefiles/rules.make rename to hotspot/make/linux/makefiles/rules.make diff --git a/hotspot/build/linux/makefiles/sa.make b/hotspot/make/linux/makefiles/sa.make similarity index 97% rename from hotspot/build/linux/makefiles/sa.make rename to hotspot/make/linux/makefiles/sa.make index 83551b87a4e..41843c5887d 100644 --- a/hotspot/build/linux/makefiles/sa.make +++ b/hotspot/make/linux/makefiles/sa.make @@ -28,11 +28,11 @@ # This makefile is used to build Serviceability Agent java code # and generate JNI header file for native methods. -include $(GAMMADIR)/build/linux/makefiles/rules.make +include $(GAMMADIR)/make/linux/makefiles/rules.make AGENT_DIR = $(GAMMADIR)/agent -include $(GAMMADIR)/build/sa.files +include $(GAMMADIR)/make/sa.files TOPDIR = $(shell echo `pwd`) GENERATED = $(TOPDIR)/../generated diff --git a/hotspot/build/linux/makefiles/saproc.make b/hotspot/make/linux/makefiles/saproc.make similarity index 100% rename from hotspot/build/linux/makefiles/saproc.make rename to hotspot/make/linux/makefiles/saproc.make diff --git a/hotspot/make/linux/makefiles/sparc.make b/hotspot/make/linux/makefiles/sparc.make new file mode 100644 index 00000000000..a86f9f7b6f5 --- /dev/null +++ b/hotspot/make/linux/makefiles/sparc.make @@ -0,0 +1,27 @@ +# +# Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# +# + +# Not included in includeDB because it has no dependencies +Obj_Files += linux_sparc.o + diff --git a/hotspot/build/linux/makefiles/sparcWorks.make b/hotspot/make/linux/makefiles/sparcWorks.make similarity index 100% rename from hotspot/build/linux/makefiles/sparcWorks.make rename to hotspot/make/linux/makefiles/sparcWorks.make diff --git a/hotspot/make/linux/makefiles/sparcv9.make b/hotspot/make/linux/makefiles/sparcv9.make new file mode 100644 index 00000000000..7aad864e51c --- /dev/null +++ b/hotspot/make/linux/makefiles/sparcv9.make @@ -0,0 +1,31 @@ +# +# Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# +# Not included in includeDB because it has no dependencies +Obj_Files += linux_sparc.o + +# gcc 4.0 miscompiles this code in -m64 +OPT_CFLAGS/macro.o = -O0 + +CFLAGS += -D_LP64=1 diff --git a/hotspot/build/linux/makefiles/tiered.make b/hotspot/make/linux/makefiles/tiered.make similarity index 100% rename from hotspot/build/linux/makefiles/tiered.make rename to hotspot/make/linux/makefiles/tiered.make diff --git a/hotspot/build/linux/makefiles/top.make b/hotspot/make/linux/makefiles/top.make similarity index 97% rename from hotspot/build/linux/makefiles/top.make rename to hotspot/make/linux/makefiles/top.make index 5da9a12d04f..f0aa13576d0 100644 --- a/hotspot/build/linux/makefiles/top.make +++ b/hotspot/make/linux/makefiles/top.make @@ -46,7 +46,7 @@ Plat_File = $(Platform_file) CDG = cd $(GENERATED); # Pick up MakeDeps' sources and definitions -include $(GAMMADIR)/build/$(Platform_os_family)/makefiles/makedeps.make +include $(GAMMADIR)/make/$(Platform_os_family)/makefiles/makedeps.make MakeDepsClass = MakeDeps.class ifdef USE_PRECOMPILED_HEADER @@ -153,7 +153,7 @@ sa_stuff: # resets -jN to -j1 for recursive runs. (How helpful.) # Note that the user must specify the desired parallelism level via a # command-line or environment variable name HOTSPOT_BUILD_JOBS. -$(adjust-mflags): $(GAMMADIR)/build/$(Platform_os_family)/makefiles/adjust-mflags.sh +$(adjust-mflags): $(GAMMADIR)/make/$(Platform_os_family)/makefiles/adjust-mflags.sh @+rm -f $@ $@+ @+cat $< > $@+ @+chmod +x $@+ diff --git a/hotspot/build/linux/makefiles/vm.make b/hotspot/make/linux/makefiles/vm.make similarity index 98% rename from hotspot/build/linux/makefiles/vm.make rename to hotspot/make/linux/makefiles/vm.make index 567e6779145..65b18ef9e87 100644 --- a/hotspot/build/linux/makefiles/vm.make +++ b/hotspot/make/linux/makefiles/vm.make @@ -26,7 +26,7 @@ # directory. # Common build rules. -MAKEFILES_DIR=$(GAMMADIR)/build/$(Platform_os_family)/makefiles +MAKEFILES_DIR=$(GAMMADIR)/make/$(Platform_os_family)/makefiles include $(MAKEFILES_DIR)/rules.make default: build @@ -71,6 +71,7 @@ endif # The following variables are defined in the generated flags.make file. BUILD_VERSION = -DHOTSPOT_RELEASE_VERSION="\"$(HS_BUILD_VER)\"" JRE_VERSION = -DJRE_RELEASE_VERSION="\"$(JRE_RELEASE_VER)\"" +HS_LIB_ARCH = -DHOTSPOT_LIB_ARCH=\"$(LIBARCH)\" BUILD_TARGET = -DHOTSPOT_BUILD_TARGET="\"$(TARGET)\"" BUILD_USER = -DHOTSPOT_BUILD_USER="\"$(HOTSPOT_BUILD_USER)\"" VM_DISTRO = -DHOTSPOT_VM_DISTRO="\"$(HOTSPOT_VM_DISTRO)\"" @@ -81,6 +82,7 @@ CPPFLAGS = \ ${BUILD_VERSION} \ ${BUILD_TARGET} \ ${BUILD_USER} \ + ${HS_LIB_ARCH} \ ${JRE_VERSION} \ ${VM_DISTRO} diff --git a/hotspot/build/linux/platform_amd64 b/hotspot/make/linux/platform_amd64 similarity index 88% rename from hotspot/build/linux/platform_amd64 rename to hotspot/make/linux/platform_amd64 index 2a76633d259..b612635958e 100644 --- a/hotspot/build/linux/platform_amd64 +++ b/hotspot/make/linux/platform_amd64 @@ -12,6 +12,4 @@ lib_arch = amd64 compiler = gcc -gnu_dis_arch = amd64 - sysdefs = -DLINUX -D_GNU_SOURCE -DAMD64 diff --git a/hotspot/build/linux/platform_amd64.suncc b/hotspot/make/linux/platform_amd64.suncc similarity index 100% rename from hotspot/build/linux/platform_amd64.suncc rename to hotspot/make/linux/platform_amd64.suncc diff --git a/hotspot/build/linux/platform_i486 b/hotspot/make/linux/platform_i486 similarity index 89% rename from hotspot/build/linux/platform_i486 rename to hotspot/make/linux/platform_i486 index 7f8b111675b..610ac91ce79 100644 --- a/hotspot/build/linux/platform_i486 +++ b/hotspot/make/linux/platform_i486 @@ -12,6 +12,4 @@ lib_arch = i386 compiler = gcc -gnu_dis_arch = i386 - sysdefs = -DLINUX -D_GNU_SOURCE -DIA32 diff --git a/hotspot/build/linux/platform_i486.suncc b/hotspot/make/linux/platform_i486.suncc similarity index 100% rename from hotspot/build/linux/platform_i486.suncc rename to hotspot/make/linux/platform_i486.suncc diff --git a/hotspot/make/linux/platform_ia64 b/hotspot/make/linux/platform_ia64 new file mode 100644 index 00000000000..7474e5bf923 --- /dev/null +++ b/hotspot/make/linux/platform_ia64 @@ -0,0 +1,15 @@ +os_family = linux + +arch = ia64 + +os_arch = linux_ia64 + +lib_arch = ia64 + +compiler = gcc + +gnu_dis_arch = ia64 + +sysdefs = -DLINUX -D_GNU_SOURCE -DIA64 -DCC_INTERP + +mark_style = alignment diff --git a/hotspot/build/linux/platform_sparc b/hotspot/make/linux/platform_sparc similarity index 89% rename from hotspot/build/linux/platform_sparc rename to hotspot/make/linux/platform_sparc index 2fda1971bd6..8d9e3ee7201 100644 --- a/hotspot/build/linux/platform_sparc +++ b/hotspot/make/linux/platform_sparc @@ -12,6 +12,4 @@ lib_arch = sparc compiler = gcc -gnu_dis_arch = sparc - sysdefs = -DLINUX -D_GNU_SOURCE -DSPARC diff --git a/hotspot/make/linux/platform_sparcv9 b/hotspot/make/linux/platform_sparcv9 new file mode 100644 index 00000000000..c9f8722c406 --- /dev/null +++ b/hotspot/make/linux/platform_sparcv9 @@ -0,0 +1,15 @@ +os_family = linux + +arch = sparc + +arch_model = sparc + +os_arch = linux_sparc + +os_arch_model = linux_sparc + +lib_arch = sparcv9 + +compiler = gcc + +sysdefs = -DLINUX -D_GNU_SOURCE -DSPARC diff --git a/hotspot/build/hotspot_distro b/hotspot/make/openjdk_distro similarity index 100% rename from hotspot/build/hotspot_distro rename to hotspot/make/openjdk_distro diff --git a/hotspot/build/sa.files b/hotspot/make/sa.files similarity index 100% rename from hotspot/build/sa.files rename to hotspot/make/sa.files diff --git a/hotspot/build/solaris/Makefile b/hotspot/make/solaris/Makefile similarity index 94% rename from hotspot/build/solaris/Makefile rename to hotspot/make/solaris/Makefile index 0a7615aa794..0751fe9eb53 100644 --- a/hotspot/build/solaris/Makefile +++ b/hotspot/make/solaris/Makefile @@ -50,7 +50,7 @@ include ../../make/defs.make else include $(GAMMADIR)/make/defs.make endif -include $(GAMMADIR)/build/$(OSNAME)/makefiles/rules.make +include $(GAMMADIR)/make/$(OSNAME)/makefiles/rules.make ifndef LP64 ifndef CC_INTERP @@ -165,7 +165,7 @@ TARGETS_TIERED = $(addsuffix tiered,$(TARGETS)) TARGETS_CORE = $(addsuffix core,$(TARGETS)) TARGETS_KERNEL = $(addsuffix kernel,$(TARGETS)) -BUILDTREE_MAKE = $(GAMMADIR)/build/$(OSNAME)/makefiles/buildtree.make +BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) ARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) BUILDTREE_VARS += HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION) @@ -208,28 +208,28 @@ check_j2se_version: fi $(SUBDIRS_TIERED): $(BUILDTREE_MAKE) - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/build/$(OSNAME)/Makefile checks + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=tiered $(SUBDIRS_C2): $(BUILDTREE_MAKE) ifdef FORCE_TIERED - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/build/$(OSNAME)/Makefile checks + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=tiered FORCE_TIERED=1 else - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/build/$(OSNAME)/Makefile checks + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=compiler2 endif $(SUBDIRS_C1): $(BUILDTREE_MAKE) - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/build/$(OSNAME)/Makefile checks + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=compiler1 $(SUBDIRS_CORE): $(BUILDTREE_MAKE) - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/build/$(OSNAME)/Makefile checks + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=core $(SUBDIRS_KERNEL): $(BUILDTREE_MAKE) - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/build/$(OSNAME)/Makefile checks + $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=kernel # Define INSTALL=y at command line to automatically copy JVM into JAVA_HOME @@ -279,7 +279,7 @@ treekernel: $(SUBDIRS_KERNEL) # Hence create a docs directory beside ...$(ARCH)_[...] docs: checks $(QUIETLY) mkdir -p $(SUBDIR_DOCS) - $(MAKE) -f $(GAMMADIR)/build/$(OSNAME)/makefiles/jvmti.make $(MFLAGS) $(BUILDTREE_VARS) JvmtiOutDir=$(SUBDIR_DOCS) jvmtidocs + $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/makefiles/jvmti.make $(MFLAGS) $(BUILDTREE_VARS) JvmtiOutDir=$(SUBDIR_DOCS) jvmtidocs # Synonyms for win32-like targets. compiler2: jvmg product @@ -296,7 +296,7 @@ clean_compiler1 clean_compiler2 clean_core clean_kernel: clean: clean_compiler2 clean_compiler1 clean_core clean_docs clean_kernel -include $(GAMMADIR)/build/$(OSNAME)/makefiles/cscope.make +include $(GAMMADIR)/make/$(OSNAME)/makefiles/cscope.make #------------------------------------------------------------------------------- diff --git a/hotspot/build/solaris/Queens.class b/hotspot/make/solaris/Queens.class similarity index 100% rename from hotspot/build/solaris/Queens.class rename to hotspot/make/solaris/Queens.class diff --git a/hotspot/build/solaris/adlc_updater b/hotspot/make/solaris/adlc_updater similarity index 100% rename from hotspot/build/solaris/adlc_updater rename to hotspot/make/solaris/adlc_updater diff --git a/hotspot/build/solaris/build.sh b/hotspot/make/solaris/build.sh similarity index 97% rename from hotspot/build/solaris/build.sh rename to hotspot/make/solaris/build.sh index 57920f388ba..bb8d175758c 100644 --- a/hotspot/build/solaris/build.sh +++ b/hotspot/make/solaris/build.sh @@ -121,7 +121,7 @@ case ${ws_path} in esac echo \ -${GNUMAKE} -f ${ws_path}/build/solaris/Makefile \ +${GNUMAKE} -f ${ws_path}/make/solaris/Makefile \ $config GAMMADIR=${ws_path} $options -${GNUMAKE} -f ${ws_path}/build/solaris/Makefile \ +${GNUMAKE} -f ${ws_path}/make/solaris/Makefile \ $config GAMMADIR=${ws_path} $options diff --git a/hotspot/build/solaris/makefiles/adjust-mflags.sh b/hotspot/make/solaris/makefiles/adjust-mflags.sh similarity index 100% rename from hotspot/build/solaris/makefiles/adjust-mflags.sh rename to hotspot/make/solaris/makefiles/adjust-mflags.sh diff --git a/hotspot/build/solaris/makefiles/adlc.make b/hotspot/make/solaris/makefiles/adlc.make similarity index 98% rename from hotspot/build/solaris/makefiles/adlc.make rename to hotspot/make/solaris/makefiles/adlc.make index 467c7d499ed..b67ae554da0 100644 --- a/hotspot/build/solaris/makefiles/adlc.make +++ b/hotspot/make/solaris/makefiles/adlc.make @@ -26,7 +26,7 @@ # build directories. # It knows how to compile, link, and run the adlc. -include $(GAMMADIR)/build/$(Platform_os_family)/makefiles/rules.make +include $(GAMMADIR)/make/$(Platform_os_family)/makefiles/rules.make # ######################################################################### @@ -154,7 +154,7 @@ endif # used to selectively update generated adlc files. This should # provide a nice compilation speed improvement. # -ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/build/$(OS) +ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/make/$(OS) ADLC_UPDATER = adlc_updater # This action refreshes all generated adlc files simultaneously. diff --git a/hotspot/build/solaris/makefiles/amd64.make b/hotspot/make/solaris/makefiles/amd64.make similarity index 100% rename from hotspot/build/solaris/makefiles/amd64.make rename to hotspot/make/solaris/makefiles/amd64.make diff --git a/hotspot/build/solaris/makefiles/buildtree.make b/hotspot/make/solaris/makefiles/buildtree.make similarity index 90% rename from hotspot/build/solaris/makefiles/buildtree.make rename to hotspot/make/solaris/makefiles/buildtree.make index 84d2beb9ed2..1fb22360dca 100644 --- a/hotspot/build/solaris/makefiles/buildtree.make +++ b/hotspot/make/solaris/makefiles/buildtree.make @@ -65,10 +65,10 @@ TESTFLAGS = -Xbatch -showversion ### maye ARCH_XXX instead? ifdef USE_GCC -PLATFORM_FILE = $(GAMMADIR)/build/$(OS_FAMILY)/platform_$(BUILDARCH).gcc +PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH).gcc GCC_LIB = /usr/local/lib else -PLATFORM_FILE = $(GAMMADIR)/build/$(OS_FAMILY)/platform_$(BUILDARCH) +PLATFORM_FILE = $(GAMMADIR)/make/$(OS_FAMILY)/platform_$(BUILDARCH) GCC_LIB = endif @@ -114,7 +114,7 @@ TARGETS = debug fastdebug jvmg optimized product profiled SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) # For dependencies and recursive makes. -BUILDTREE_MAKE = $(GAMMADIR)/build/$(OS_FAMILY)/makefiles/buildtree.make +BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make \ env.ksh env.csh .dbxrc test_gamma @@ -136,19 +136,19 @@ endif ifndef HOTSPOT_BUILD_USER HOTSPOT_BUILD_USER := $(shell whoami) endif -# Define HOTSPOT_VM_DISTRO based on settings in build/hotspot_distro -# or build/closed/hotspot_distro. +# Define HOTSPOT_VM_DISTRO based on settings in make/openjdk_distro +# or make/hotspot_distro. ifndef HOTSPOT_VM_DISTRO CLOSED_DIR_EXISTS := $(shell \ - if [ -d $(GAMMADIR)/build/closed ] ; then \ + if [ -d $(GAMMADIR)/src/closed ] ; then \ echo true; \ else \ echo false; \ fi) ifeq ($(CLOSED_DIR_EXISTS), true) - include $(GAMMADIR)/build/closed/hotspot_distro + include $(GAMMADIR)/make/hotspot_distro else - include $(GAMMADIR)/build/hotspot_distro + include $(GAMMADIR)/make/openjdk_distro endif endif @@ -203,8 +203,8 @@ flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \ echo "SYSDEFS += \$$(HOTSPOT_EXTRA_SYSDEFS)"; \ echo; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \ ) > $@ flags_vm.make: $(BUILDTREE_MAKE) ../shared_dirs.lst @@ -213,8 +213,8 @@ flags_vm.make: $(BUILDTREE_MAKE) ../shared_dirs.lst $(BUILDTREE_COMMENT); \ echo; \ [ "$(TARGET)" = profiled ] && \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/optimized.make"; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/$(TARGET).make"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/optimized.make"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(TARGET).make"; \ ) > $@ ../shared_dirs.lst: $(BUILDTREE_MAKE) $(GAMMADIR)/src/share/vm @@ -230,7 +230,7 @@ Makefile: $(BUILDTREE_MAKE) echo; \ echo include flags.make; \ echo; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/top.make"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/top.make"; \ ) > $@ vm.make: $(BUILDTREE_MAKE) @@ -241,7 +241,7 @@ vm.make: $(BUILDTREE_MAKE) echo include flags.make; \ echo include flags_vm.make; \ echo; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/$(@F)"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ adlc.make: $(BUILDTREE_MAKE) @@ -251,7 +251,7 @@ adlc.make: $(BUILDTREE_MAKE) echo; \ echo include flags.make; \ echo; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/$(@F)"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ jvmti.make: $(BUILDTREE_MAKE) @@ -261,7 +261,7 @@ jvmti.make: $(BUILDTREE_MAKE) echo; \ echo include flags.make; \ echo; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/$(@F)"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ sa.make: $(BUILDTREE_MAKE) @@ -271,7 +271,7 @@ sa.make: $(BUILDTREE_MAKE) echo; \ echo include flags.make; \ echo; \ - echo "include \$$(GAMMADIR)/build/$(OS_FAMILY)/makefiles/$(@F)"; \ + echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ ) > $@ env.ksh: $(BUILDTREE_MAKE) @@ -351,7 +351,7 @@ test_gamma: $(BUILDTREE_MAKE) echo "then"; \ echo " $(WRONG_DATA_MODE_MSG); exit 0;"; \ echo "fi"; \ - echo 'CLASSPATH="$(GAMMADIR)/build/$(OS_FAMILY):$$CLASSPATH"'; \ + echo 'CLASSPATH="$(GAMMADIR)/make/$(OS_FAMILY):$$CLASSPATH"'; \ echo '[ -f gamma_g ] && { gamma=gamma_g; }'; \ echo './$${gamma:-gamma} $(TESTFLAGS) Queens < /dev/null'; \ ) > $@ diff --git a/hotspot/build/solaris/makefiles/compiler1.make b/hotspot/make/solaris/makefiles/compiler1.make similarity index 100% rename from hotspot/build/solaris/makefiles/compiler1.make rename to hotspot/make/solaris/makefiles/compiler1.make diff --git a/hotspot/build/solaris/makefiles/compiler2.make b/hotspot/make/solaris/makefiles/compiler2.make similarity index 100% rename from hotspot/build/solaris/makefiles/compiler2.make rename to hotspot/make/solaris/makefiles/compiler2.make diff --git a/hotspot/build/solaris/makefiles/core.make b/hotspot/make/solaris/makefiles/core.make similarity index 100% rename from hotspot/build/solaris/makefiles/core.make rename to hotspot/make/solaris/makefiles/core.make diff --git a/hotspot/build/solaris/makefiles/cscope.make b/hotspot/make/solaris/makefiles/cscope.make similarity index 89% rename from hotspot/build/solaris/makefiles/cscope.make rename to hotspot/make/solaris/makefiles/cscope.make index 20644ec8151..6fa197a56af 100644 --- a/hotspot/build/solaris/makefiles/cscope.make +++ b/hotspot/make/solaris/makefiles/cscope.make @@ -38,9 +38,10 @@ include $(GAMMADIR)/make/scm.make NAWK = /usr/xpg4/bin/awk RM = rm -f +HG = hg CS_TOP = ../.. -CSDIRS = $(CS_TOP)/src $(CS_TOP)/build +CSDIRS = $(CS_TOP)/src $(CS_TOP)/make CSINCS = $(CSDIRS:%=-I%) CSCOPE = cscope @@ -60,7 +61,7 @@ ifndef CSHEADERS RMCCHEADERS= -o -name CClassHeaders endif -# Use CS_GENERATED=x to include auto-generated files in the build directories. +# Use CS_GENERATED=x to include auto-generated files in the make directories. ifdef CS_GENERATED CS_ADD_GENERATED = -o -name '*.incl' else @@ -122,9 +123,9 @@ cscope cscope.out: cscope.files FORCE # relevant files first. cscope.files: .cscope.files.raw echo "$(CSINCS)" > $@ - -egrep -v "\.java|\/build\/" $< >> $@ + -egrep -v "\.java|\/make\/" $< >> $@ -fgrep ".java" $< >> $@ - -fgrep "/build/" $< >> $@ + -fgrep "/make/" $< >> $@ .cscope.files.raw: .nametable.files -find $(CSDIRS) -type d \( $(CS_PRUNE) \) -prune -o \ @@ -141,13 +142,17 @@ TAGS.clean: nametable.clean # .nametable.files and .nametable.files.tmp are used to determine if any files # were added to/deleted from/renamed in the workspace. If not, then there's -# normally no need to run find. To force a 'find': gmake nametable.clean. +# normally no need to rebuild the cscope database. To force a rebuild of +# the cscope database: gmake nametable.clean. .nametable.files: .nametable.files.tmp - cmp -s $@ $< || cp $< $@ + ( cmp -s $@ $< ) || ( cp $< $@ ) + -$(RM) $< -.nametable.files.tmp: $(CS_TOP)/Codemgr_wsdata/nametable - $(NAWK) \ - '{ if (sub("( [a-z0-9]{2,8}){4}$$", "")) print $$0; }' $< > $@ +# `hg status' is slightly faster than `hg fstatus'. Both are +# quite a bit slower on an NFS mounted file system, so this is +# really geared towards repos on local file systems. +.nametable.files.tmp: + -$(HG) fstatus -acmn > $@ nametable.clean: -$(RM) .nametable.files .nametable.files.tmp diff --git a/hotspot/build/solaris/makefiles/debug.make b/hotspot/make/solaris/makefiles/debug.make similarity index 88% rename from hotspot/build/solaris/makefiles/debug.make rename to hotspot/make/solaris/makefiles/debug.make index f2a2786ecf6..d759910be9e 100644 --- a/hotspot/build/solaris/makefiles/debug.make +++ b/hotspot/make/solaris/makefiles/debug.make @@ -39,13 +39,13 @@ endif CFLAGS += $(DEBUG_CFLAGS/BYFILE) # Linker mapfiles -MAPFILE = $(GAMMADIR)/build/solaris/makefiles/mapfile-vers \ - $(GAMMADIR)/build/solaris/makefiles/mapfile-vers-debug \ - $(GAMMADIR)/build/solaris/makefiles/mapfile-vers-nonproduct +MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ + $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug \ + $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct # This mapfile is only needed when compiling with dtrace support, # and mustn't be otherwise. -MAPFILE_DTRACE = $(GAMMADIR)/build/solaris/makefiles/mapfile-vers-$(TYPE) +MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE) _JUNK_ := $(shell echo >&2 ""\ "-------------------------------------------------------------------------\n" \ diff --git a/hotspot/build/solaris/makefiles/defs.make b/hotspot/make/solaris/makefiles/defs.make similarity index 100% rename from hotspot/build/solaris/makefiles/defs.make rename to hotspot/make/solaris/makefiles/defs.make diff --git a/hotspot/build/solaris/makefiles/dtrace.make b/hotspot/make/solaris/makefiles/dtrace.make similarity index 98% rename from hotspot/build/solaris/makefiles/dtrace.make rename to hotspot/make/solaris/makefiles/dtrace.make index 4c974ede212..f4f7edf934d 100644 --- a/hotspot/build/solaris/makefiles/dtrace.make +++ b/hotspot/make/solaris/makefiles/dtrace.make @@ -193,10 +193,16 @@ $(DTRACE.o): $(DTRACE).d $(JVMOFFS).h $(JVMOFFS)Index.h $(DTraced_Files) .PHONY: dtraceCheck +SYSTEM_DTRACE_H = /usr/include/dtrace.h SYSTEM_DTRACE_PROG = /usr/sbin/dtrace PATCH_DTRACE_PROG = /opt/SUNWdtrd/sbin/dtrace systemDtraceFound := $(wildcard ${SYSTEM_DTRACE_PROG}) patchDtraceFound := $(wildcard ${PATCH_DTRACE_PROG}) +systemDtraceHdrFound := $(wildcard $(SYSTEM_DTRACE_H)) + +ifneq ("$(systemDtraceHdrFound)", "") +CFLAGS += -DHAVE_DTRACE_H +endif ifneq ("$(patchDtraceFound)", "") DTRACE_PROG=$(PATCH_DTRACE_PROG) diff --git a/hotspot/build/solaris/makefiles/fastdebug.make b/hotspot/make/solaris/makefiles/fastdebug.make similarity index 94% rename from hotspot/build/solaris/makefiles/fastdebug.make rename to hotspot/make/solaris/makefiles/fastdebug.make index 7f16a0e655b..0329b4c3678 100644 --- a/hotspot/build/solaris/makefiles/fastdebug.make +++ b/hotspot/make/solaris/makefiles/fastdebug.make @@ -100,13 +100,13 @@ DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@) CFLAGS += $(DEBUG_CFLAGS/BYFILE) # Linker mapfiles -MAPFILE = $(GAMMADIR)/build/solaris/makefiles/mapfile-vers \ - $(GAMMADIR)/build/solaris/makefiles/mapfile-vers-debug \ - $(GAMMADIR)/build/solaris/makefiles/mapfile-vers-nonproduct +MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ + $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug \ + $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct # This mapfile is only needed when compiling with dtrace support, # and mustn't be otherwise. -MAPFILE_DTRACE = $(GAMMADIR)/build/solaris/makefiles/mapfile-vers-$(TYPE) +MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE) G_SUFFIX = diff --git a/hotspot/build/solaris/makefiles/gcc.make b/hotspot/make/solaris/makefiles/gcc.make similarity index 100% rename from hotspot/build/solaris/makefiles/gcc.make rename to hotspot/make/solaris/makefiles/gcc.make diff --git a/hotspot/build/solaris/makefiles/hp.make b/hotspot/make/solaris/makefiles/hp.make similarity index 100% rename from hotspot/build/solaris/makefiles/hp.make rename to hotspot/make/solaris/makefiles/hp.make diff --git a/hotspot/build/solaris/makefiles/hp1.make b/hotspot/make/solaris/makefiles/hp1.make similarity index 100% rename from hotspot/build/solaris/makefiles/hp1.make rename to hotspot/make/solaris/makefiles/hp1.make diff --git a/hotspot/build/solaris/makefiles/i486.make b/hotspot/make/solaris/makefiles/i486.make similarity index 100% rename from hotspot/build/solaris/makefiles/i486.make rename to hotspot/make/solaris/makefiles/i486.make diff --git a/hotspot/build/solaris/makefiles/jsig.make b/hotspot/make/solaris/makefiles/jsig.make similarity index 100% rename from hotspot/build/solaris/makefiles/jsig.make rename to hotspot/make/solaris/makefiles/jsig.make diff --git a/hotspot/build/solaris/makefiles/jvmg.make b/hotspot/make/solaris/makefiles/jvmg.make similarity index 87% rename from hotspot/build/solaris/makefiles/jvmg.make rename to hotspot/make/solaris/makefiles/jvmg.make index ee0e4616a3c..24a3510d4a5 100644 --- a/hotspot/build/solaris/makefiles/jvmg.make +++ b/hotspot/make/solaris/makefiles/jvmg.make @@ -42,13 +42,13 @@ CFLAGS += $(DEBUG_CFLAGS/BYFILE) # to inhibit the effect of the previous line on CFLAGS. # Linker mapfiles -MAPFILE = $(GAMMADIR)/build/solaris/makefiles/mapfile-vers \ - $(GAMMADIR)/build/solaris/makefiles/mapfile-vers-debug \ - $(GAMMADIR)/build/solaris/makefiles/mapfile-vers-nonproduct +MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ + $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug \ + $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct # This mapfile is only needed when compiling with dtrace support, # and mustn't be otherwise. -MAPFILE_DTRACE = $(GAMMADIR)/build/solaris/makefiles/mapfile-vers-$(TYPE) +MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE) G_SUFFIX = VERSION = debug diff --git a/hotspot/build/solaris/makefiles/jvmti.make b/hotspot/make/solaris/makefiles/jvmti.make similarity index 98% rename from hotspot/build/solaris/makefiles/jvmti.make rename to hotspot/make/solaris/makefiles/jvmti.make index ba93d87975c..876714eb55d 100644 --- a/hotspot/build/solaris/makefiles/jvmti.make +++ b/hotspot/make/solaris/makefiles/jvmti.make @@ -27,7 +27,7 @@ # # It knows how to build and run the tools to generate jvmti. -include $(GAMMADIR)/build/solaris/makefiles/rules.make +include $(GAMMADIR)/make/solaris/makefiles/rules.make # ######################################################################### diff --git a/hotspot/build/solaris/makefiles/kernel.make b/hotspot/make/solaris/makefiles/kernel.make similarity index 100% rename from hotspot/build/solaris/makefiles/kernel.make rename to hotspot/make/solaris/makefiles/kernel.make diff --git a/hotspot/build/solaris/makefiles/launcher.make b/hotspot/make/solaris/makefiles/launcher.make similarity index 100% rename from hotspot/build/solaris/makefiles/launcher.make rename to hotspot/make/solaris/makefiles/launcher.make diff --git a/hotspot/build/solaris/makefiles/makedeps.make b/hotspot/make/solaris/makefiles/makedeps.make similarity index 97% rename from hotspot/build/solaris/makefiles/makedeps.make rename to hotspot/make/solaris/makefiles/makedeps.make index 71c8f455bcc..12b01a7da96 100644 --- a/hotspot/build/solaris/makefiles/makedeps.make +++ b/hotspot/make/solaris/makefiles/makedeps.make @@ -22,7 +22,7 @@ # # -include $(GAMMADIR)/build/solaris/makefiles/rules.make +include $(GAMMADIR)/make/solaris/makefiles/rules.make COMPILE.JAVAC.FLAGS += -d $(OUTDIR) diff --git a/hotspot/build/solaris/makefiles/mapfile-vers b/hotspot/make/solaris/makefiles/mapfile-vers similarity index 97% rename from hotspot/build/solaris/makefiles/mapfile-vers rename to hotspot/make/solaris/makefiles/mapfile-vers index 7b1a1743e79..f7ed56e5f10 100644 --- a/hotspot/build/solaris/makefiles/mapfile-vers +++ b/hotspot/make/solaris/makefiles/mapfile-vers @@ -1,4 +1,6 @@ # +# @(#)mapfile-vers 1.32 07/10/25 16:47:36 +# # # Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. @@ -75,6 +77,11 @@ SUNWprivate_1.1 { JVM_DesiredAssertionStatus; JVM_DisableCompiler; JVM_DoPrivileged; + JVM_DTraceGetVersion; + JVM_DTraceActivate; + JVM_DTraceIsProbeEnabled; + JVM_DTraceIsSupported; + JVM_DTraceDispose; JVM_DumpAllStacks; JVM_DumpThreads; JVM_EnableCompiler; diff --git a/hotspot/build/solaris/makefiles/mapfile-vers-COMPILER1 b/hotspot/make/solaris/makefiles/mapfile-vers-COMPILER1 similarity index 100% rename from hotspot/build/solaris/makefiles/mapfile-vers-COMPILER1 rename to hotspot/make/solaris/makefiles/mapfile-vers-COMPILER1 diff --git a/hotspot/build/solaris/makefiles/mapfile-vers-COMPILER2 b/hotspot/make/solaris/makefiles/mapfile-vers-COMPILER2 similarity index 100% rename from hotspot/build/solaris/makefiles/mapfile-vers-COMPILER2 rename to hotspot/make/solaris/makefiles/mapfile-vers-COMPILER2 diff --git a/hotspot/build/solaris/makefiles/mapfile-vers-CORE b/hotspot/make/solaris/makefiles/mapfile-vers-CORE similarity index 100% rename from hotspot/build/solaris/makefiles/mapfile-vers-CORE rename to hotspot/make/solaris/makefiles/mapfile-vers-CORE diff --git a/hotspot/build/solaris/makefiles/mapfile-vers-TIERED b/hotspot/make/solaris/makefiles/mapfile-vers-TIERED similarity index 100% rename from hotspot/build/solaris/makefiles/mapfile-vers-TIERED rename to hotspot/make/solaris/makefiles/mapfile-vers-TIERED diff --git a/hotspot/build/solaris/makefiles/mapfile-vers-debug b/hotspot/make/solaris/makefiles/mapfile-vers-debug similarity index 100% rename from hotspot/build/solaris/makefiles/mapfile-vers-debug rename to hotspot/make/solaris/makefiles/mapfile-vers-debug diff --git a/hotspot/build/solaris/makefiles/mapfile-vers-jsig b/hotspot/make/solaris/makefiles/mapfile-vers-jsig similarity index 100% rename from hotspot/build/solaris/makefiles/mapfile-vers-jsig rename to hotspot/make/solaris/makefiles/mapfile-vers-jsig diff --git a/hotspot/build/solaris/makefiles/mapfile-vers-jvm_db b/hotspot/make/solaris/makefiles/mapfile-vers-jvm_db similarity index 100% rename from hotspot/build/solaris/makefiles/mapfile-vers-jvm_db rename to hotspot/make/solaris/makefiles/mapfile-vers-jvm_db diff --git a/hotspot/build/solaris/makefiles/mapfile-vers-jvm_dtrace b/hotspot/make/solaris/makefiles/mapfile-vers-jvm_dtrace similarity index 100% rename from hotspot/build/solaris/makefiles/mapfile-vers-jvm_dtrace rename to hotspot/make/solaris/makefiles/mapfile-vers-jvm_dtrace diff --git a/hotspot/build/solaris/makefiles/mapfile-vers-nonproduct b/hotspot/make/solaris/makefiles/mapfile-vers-nonproduct similarity index 100% rename from hotspot/build/solaris/makefiles/mapfile-vers-nonproduct rename to hotspot/make/solaris/makefiles/mapfile-vers-nonproduct diff --git a/hotspot/build/solaris/makefiles/optimized.make b/hotspot/make/solaris/makefiles/optimized.make similarity index 91% rename from hotspot/build/solaris/makefiles/optimized.make rename to hotspot/make/solaris/makefiles/optimized.make index 31323ed12a6..4e8f6484790 100644 --- a/hotspot/build/solaris/makefiles/optimized.make +++ b/hotspot/make/solaris/makefiles/optimized.make @@ -43,12 +43,12 @@ CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE) # Linker mapfiles # NOTE: inclusion of nonproduct mapfile not necessary; read it for details -MAPFILE = $(GAMMADIR)/build/solaris/makefiles/mapfile-vers \ - $(GAMMADIR)/build/solaris/makefiles/mapfile-vers-nonproduct +MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ + $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct # This mapfile is only needed when compiling with dtrace support, # and mustn't be otherwise. -MAPFILE_DTRACE = $(GAMMADIR)/build/solaris/makefiles/mapfile-vers-$(TYPE) +MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE) # Set the environment variable HOTSPARC_GENERIC to "true" # to inhibit the effect of the previous line on CFLAGS. diff --git a/hotspot/build/solaris/makefiles/product.make b/hotspot/make/solaris/makefiles/product.make similarity index 88% rename from hotspot/build/solaris/makefiles/product.make rename to hotspot/make/solaris/makefiles/product.make index 2bc592702d2..d2e78c6646a 100644 --- a/hotspot/build/solaris/makefiles/product.make +++ b/hotspot/make/solaris/makefiles/product.make @@ -54,16 +54,16 @@ CFLAGS$(HOTSPARC_GENERIC) += $(OPT_CFLAGS/BYFILE) # Linker mapfiles # NOTE: inclusion of nonproduct mapfile not necessary; read it for details ifdef USE_GCC -MAPFILE = $(GAMMADIR)/build/solaris/makefiles/mapfile-vers +MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers else -MAPFILE = $(GAMMADIR)/build/solaris/makefiles/mapfile-vers \ - $(GAMMADIR)/build/solaris/makefiles/mapfile-vers-nonproduct +MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ + $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-nonproduct # This mapfile is only needed when compiling with dtrace support, # and mustn't be otherwise. -MAPFILE_DTRACE = $(GAMMADIR)/build/solaris/makefiles/mapfile-vers-$(TYPE) +MAPFILE_DTRACE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-$(TYPE) -REORDERFILE = $(GAMMADIR)/build/solaris/makefiles/reorder_$(TYPE)_$(BUILDARCH) +REORDERFILE = $(GAMMADIR)/make/solaris/makefiles/reorder_$(TYPE)_$(BUILDARCH) endif # Don't strip in VM build; JDK build will strip libraries later diff --git a/hotspot/build/solaris/makefiles/profiled.make b/hotspot/make/solaris/makefiles/profiled.make similarity index 100% rename from hotspot/build/solaris/makefiles/profiled.make rename to hotspot/make/solaris/makefiles/profiled.make diff --git a/hotspot/build/solaris/makefiles/reorder_COMPILER1_i486 b/hotspot/make/solaris/makefiles/reorder_COMPILER1_i486 similarity index 100% rename from hotspot/build/solaris/makefiles/reorder_COMPILER1_i486 rename to hotspot/make/solaris/makefiles/reorder_COMPILER1_i486 diff --git a/hotspot/build/solaris/makefiles/reorder_COMPILER1_sparc b/hotspot/make/solaris/makefiles/reorder_COMPILER1_sparc similarity index 100% rename from hotspot/build/solaris/makefiles/reorder_COMPILER1_sparc rename to hotspot/make/solaris/makefiles/reorder_COMPILER1_sparc diff --git a/hotspot/build/solaris/makefiles/reorder_COMPILER1_sparcv9 b/hotspot/make/solaris/makefiles/reorder_COMPILER1_sparcv9 similarity index 100% rename from hotspot/build/solaris/makefiles/reorder_COMPILER1_sparcv9 rename to hotspot/make/solaris/makefiles/reorder_COMPILER1_sparcv9 diff --git a/hotspot/build/solaris/makefiles/reorder_COMPILER2_amd64 b/hotspot/make/solaris/makefiles/reorder_COMPILER2_amd64 similarity index 100% rename from hotspot/build/solaris/makefiles/reorder_COMPILER2_amd64 rename to hotspot/make/solaris/makefiles/reorder_COMPILER2_amd64 diff --git a/hotspot/build/solaris/makefiles/reorder_COMPILER2_i486 b/hotspot/make/solaris/makefiles/reorder_COMPILER2_i486 similarity index 100% rename from hotspot/build/solaris/makefiles/reorder_COMPILER2_i486 rename to hotspot/make/solaris/makefiles/reorder_COMPILER2_i486 diff --git a/hotspot/build/solaris/makefiles/reorder_COMPILER2_sparc b/hotspot/make/solaris/makefiles/reorder_COMPILER2_sparc similarity index 100% rename from hotspot/build/solaris/makefiles/reorder_COMPILER2_sparc rename to hotspot/make/solaris/makefiles/reorder_COMPILER2_sparc diff --git a/hotspot/build/solaris/makefiles/reorder_COMPILER2_sparcv9 b/hotspot/make/solaris/makefiles/reorder_COMPILER2_sparcv9 similarity index 100% rename from hotspot/build/solaris/makefiles/reorder_COMPILER2_sparcv9 rename to hotspot/make/solaris/makefiles/reorder_COMPILER2_sparcv9 diff --git a/hotspot/build/solaris/makefiles/reorder_CORE_amd64 b/hotspot/make/solaris/makefiles/reorder_CORE_amd64 similarity index 100% rename from hotspot/build/solaris/makefiles/reorder_CORE_amd64 rename to hotspot/make/solaris/makefiles/reorder_CORE_amd64 diff --git a/hotspot/build/solaris/makefiles/reorder_CORE_i486 b/hotspot/make/solaris/makefiles/reorder_CORE_i486 similarity index 100% rename from hotspot/build/solaris/makefiles/reorder_CORE_i486 rename to hotspot/make/solaris/makefiles/reorder_CORE_i486 diff --git a/hotspot/build/solaris/makefiles/reorder_CORE_sparc b/hotspot/make/solaris/makefiles/reorder_CORE_sparc similarity index 100% rename from hotspot/build/solaris/makefiles/reorder_CORE_sparc rename to hotspot/make/solaris/makefiles/reorder_CORE_sparc diff --git a/hotspot/build/solaris/makefiles/reorder_CORE_sparcv9 b/hotspot/make/solaris/makefiles/reorder_CORE_sparcv9 similarity index 100% rename from hotspot/build/solaris/makefiles/reorder_CORE_sparcv9 rename to hotspot/make/solaris/makefiles/reorder_CORE_sparcv9 diff --git a/hotspot/build/solaris/makefiles/reorder_TIERED_amd64 b/hotspot/make/solaris/makefiles/reorder_TIERED_amd64 similarity index 100% rename from hotspot/build/solaris/makefiles/reorder_TIERED_amd64 rename to hotspot/make/solaris/makefiles/reorder_TIERED_amd64 diff --git a/hotspot/build/solaris/makefiles/reorder_TIERED_i486 b/hotspot/make/solaris/makefiles/reorder_TIERED_i486 similarity index 100% rename from hotspot/build/solaris/makefiles/reorder_TIERED_i486 rename to hotspot/make/solaris/makefiles/reorder_TIERED_i486 diff --git a/hotspot/build/solaris/makefiles/reorder_TIERED_sparc b/hotspot/make/solaris/makefiles/reorder_TIERED_sparc similarity index 100% rename from hotspot/build/solaris/makefiles/reorder_TIERED_sparc rename to hotspot/make/solaris/makefiles/reorder_TIERED_sparc diff --git a/hotspot/build/solaris/makefiles/rules.make b/hotspot/make/solaris/makefiles/rules.make similarity index 100% rename from hotspot/build/solaris/makefiles/rules.make rename to hotspot/make/solaris/makefiles/rules.make diff --git a/hotspot/build/solaris/makefiles/sa.make b/hotspot/make/solaris/makefiles/sa.make similarity index 97% rename from hotspot/build/solaris/makefiles/sa.make rename to hotspot/make/solaris/makefiles/sa.make index dc1f159a093..1143688394e 100644 --- a/hotspot/build/solaris/makefiles/sa.make +++ b/hotspot/make/solaris/makefiles/sa.make @@ -28,9 +28,9 @@ # This makefile is used to build Serviceability Agent java code # and generate JNI header file for native methods. -include $(GAMMADIR)/build/solaris/makefiles/rules.make +include $(GAMMADIR)/make/solaris/makefiles/rules.make AGENT_DIR = $(GAMMADIR)/agent -include $(GAMMADIR)/build/sa.files +include $(GAMMADIR)/make/sa.files GENERATED = ../generated # tools.jar is needed by the JDI - SA binding diff --git a/hotspot/build/solaris/makefiles/saproc.make b/hotspot/make/solaris/makefiles/saproc.make similarity index 100% rename from hotspot/build/solaris/makefiles/saproc.make rename to hotspot/make/solaris/makefiles/saproc.make diff --git a/hotspot/build/solaris/makefiles/sparc.make b/hotspot/make/solaris/makefiles/sparc.make similarity index 100% rename from hotspot/build/solaris/makefiles/sparc.make rename to hotspot/make/solaris/makefiles/sparc.make diff --git a/hotspot/build/solaris/makefiles/sparcWorks.make b/hotspot/make/solaris/makefiles/sparcWorks.make similarity index 98% rename from hotspot/build/solaris/makefiles/sparcWorks.make rename to hotspot/make/solaris/makefiles/sparcWorks.make index 50a8b2a6af5..a20546e6528 100644 --- a/hotspot/build/solaris/makefiles/sparcWorks.make +++ b/hotspot/make/solaris/makefiles/sparcWorks.make @@ -185,6 +185,12 @@ CFLAGS += $(GAMMADIR)/src/os_cpu/solaris_${Platform_arch}/vm/solaris_${Platform_ # no more exceptions CFLAGS/NOEX=-features=no%except + +# avoid compilation problems arising from fact that C++ compiler tries +# to search for external template definition by just compiling additional +# source files in th same context +CFLAGS += -template=no%extdef + # Reduce code bloat by reverting back to 5.0 behavior for static initializers CFLAGS += -features=no%split_init diff --git a/hotspot/build/solaris/makefiles/sparcv9.make b/hotspot/make/solaris/makefiles/sparcv9.make similarity index 100% rename from hotspot/build/solaris/makefiles/sparcv9.make rename to hotspot/make/solaris/makefiles/sparcv9.make diff --git a/hotspot/build/solaris/makefiles/tiered.make b/hotspot/make/solaris/makefiles/tiered.make similarity index 100% rename from hotspot/build/solaris/makefiles/tiered.make rename to hotspot/make/solaris/makefiles/tiered.make diff --git a/hotspot/build/solaris/makefiles/top.make b/hotspot/make/solaris/makefiles/top.make similarity index 97% rename from hotspot/build/solaris/makefiles/top.make rename to hotspot/make/solaris/makefiles/top.make index 14c9acd38ac..5a883565ada 100644 --- a/hotspot/build/solaris/makefiles/top.make +++ b/hotspot/make/solaris/makefiles/top.make @@ -45,7 +45,7 @@ Plat_File = $(Platform_file) CDG = cd $(GENERATED); # Pick up MakeDeps' sources and definitions -include $(GAMMADIR)/build/$(Platform_os_family)/makefiles/makedeps.make +include $(GAMMADIR)/make/$(Platform_os_family)/makefiles/makedeps.make MakeDepsClass = MakeDeps.class MakeDeps = $(RUN.JAVA) -classpath . MakeDeps @@ -150,7 +150,7 @@ sa_stuff: # resets -jN to -j1 for recursive runs. (How helpful.) # Note that the user must specify the desired parallelism level via a # command-line or environment variable name HOTSPOT_BUILD_JOBS. -$(adjust-mflags): $(GAMMADIR)/build/$(Platform_os_family)/makefiles/adjust-mflags.sh +$(adjust-mflags): $(GAMMADIR)/make/$(Platform_os_family)/makefiles/adjust-mflags.sh @+rm -f $@ $@+ @+cat $< > $@+ @+chmod +x $@+ diff --git a/hotspot/build/solaris/makefiles/vm.make b/hotspot/make/solaris/makefiles/vm.make similarity index 98% rename from hotspot/build/solaris/makefiles/vm.make rename to hotspot/make/solaris/makefiles/vm.make index c1fa4643129..43d31878e54 100644 --- a/hotspot/build/solaris/makefiles/vm.make +++ b/hotspot/make/solaris/makefiles/vm.make @@ -26,7 +26,7 @@ # directory. # Common build rules. -MAKEFILES_DIR=$(GAMMADIR)/build/$(Platform_os_family)/makefiles +MAKEFILES_DIR=$(GAMMADIR)/make/$(Platform_os_family)/makefiles include $(MAKEFILES_DIR)/rules.make default: build @@ -63,6 +63,7 @@ endif # The following variables are defined in the generated flags.make file. BUILD_VERSION = -DHOTSPOT_RELEASE_VERSION="\"$(HS_BUILD_VER)\"" JRE_VERSION = -DJRE_RELEASE_VERSION="\"$(JRE_RELEASE_VER)\"" +HS_LIB_ARCH = -DHOTSPOT_LIB_ARCH=\"$(LIBARCH)\" BUILD_TARGET = -DHOTSPOT_BUILD_TARGET="\"$(TARGET)\"" BUILD_USER = -DHOTSPOT_BUILD_USER="\"$(HOTSPOT_BUILD_USER)\"" VM_DISTRO = -DHOTSPOT_VM_DISTRO="\"$(HOTSPOT_VM_DISTRO)\"" @@ -73,6 +74,7 @@ CPPFLAGS = \ ${BUILD_VERSION} \ ${BUILD_TARGET} \ ${BUILD_USER} \ + ${HS_LIB_ARCH} \ ${JRE_VERSION} \ ${VM_DISTRO} diff --git a/hotspot/build/solaris/platform_amd64 b/hotspot/make/solaris/platform_amd64 similarity index 89% rename from hotspot/build/solaris/platform_amd64 rename to hotspot/make/solaris/platform_amd64 index 2cfe3d41681..f85242b1d30 100644 --- a/hotspot/build/solaris/platform_amd64 +++ b/hotspot/make/solaris/platform_amd64 @@ -12,6 +12,4 @@ lib_arch = amd64 compiler = sparcWorks -gnu_dis_arch = amd64 - sysdefs = -DSOLARIS -DSPARC_WORKS -DAMD64 diff --git a/hotspot/build/solaris/platform_amd64.gcc b/hotspot/make/solaris/platform_amd64.gcc similarity index 89% rename from hotspot/build/solaris/platform_amd64.gcc rename to hotspot/make/solaris/platform_amd64.gcc index 57d25fa6f44..ebd495bca40 100644 --- a/hotspot/build/solaris/platform_amd64.gcc +++ b/hotspot/make/solaris/platform_amd64.gcc @@ -12,6 +12,4 @@ lib_arch = amd64 compiler = gcc -gnu_dis_arch = amd64 - sysdefs = -DSOLARIS -D_GNU_SOURCE -DAMD64 diff --git a/hotspot/build/solaris/platform_i486 b/hotspot/make/solaris/platform_i486 similarity index 90% rename from hotspot/build/solaris/platform_i486 rename to hotspot/make/solaris/platform_i486 index c6902160b1f..91d4c5e7a64 100644 --- a/hotspot/build/solaris/platform_i486 +++ b/hotspot/make/solaris/platform_i486 @@ -12,6 +12,4 @@ lib_arch = i386 compiler = sparcWorks -gnu_dis_arch = i386 - sysdefs = -DSOLARIS -DSPARC_WORKS -DIA32 diff --git a/hotspot/build/solaris/platform_i486.gcc b/hotspot/make/solaris/platform_i486.gcc similarity index 89% rename from hotspot/build/solaris/platform_i486.gcc rename to hotspot/make/solaris/platform_i486.gcc index 8d1d57ff596..61d55e1b59e 100644 --- a/hotspot/build/solaris/platform_i486.gcc +++ b/hotspot/make/solaris/platform_i486.gcc @@ -12,6 +12,4 @@ lib_arch = i386 compiler = gcc -gnu_dis_arch = i386 - sysdefs = -DSOLARIS -D_GNU_SOURCE -DIA32 diff --git a/hotspot/build/solaris/platform_sparc b/hotspot/make/solaris/platform_sparc similarity index 89% rename from hotspot/build/solaris/platform_sparc rename to hotspot/make/solaris/platform_sparc index 4ff94c3ae68..424088ef53f 100644 --- a/hotspot/build/solaris/platform_sparc +++ b/hotspot/make/solaris/platform_sparc @@ -12,6 +12,4 @@ lib_arch = sparc compiler = sparcWorks -gnu_dis_arch = sparc - sysdefs = -DSOLARIS -DSPARC_WORKS -DSPARC diff --git a/hotspot/build/solaris/platform_sparc.gcc b/hotspot/make/solaris/platform_sparc.gcc similarity index 89% rename from hotspot/build/solaris/platform_sparc.gcc rename to hotspot/make/solaris/platform_sparc.gcc index 87d42becfa3..9a900f49384 100644 --- a/hotspot/build/solaris/platform_sparc.gcc +++ b/hotspot/make/solaris/platform_sparc.gcc @@ -12,6 +12,4 @@ lib_arch = sparc compiler = gcc -gnu_dis_arch = sparc - sysdefs = -DSOLARIS -D_GNU_SOURCE -DSPARC diff --git a/hotspot/build/solaris/platform_sparcv9 b/hotspot/make/solaris/platform_sparcv9 similarity index 81% rename from hotspot/build/solaris/platform_sparcv9 rename to hotspot/make/solaris/platform_sparcv9 index 4ff94c3ae68..a17dd08d29d 100644 --- a/hotspot/build/solaris/platform_sparcv9 +++ b/hotspot/make/solaris/platform_sparcv9 @@ -8,10 +8,8 @@ os_arch = solaris_sparc os_arch_model = solaris_sparc -lib_arch = sparc +lib_arch = sparcv9 compiler = sparcWorks -gnu_dis_arch = sparc - sysdefs = -DSOLARIS -DSPARC_WORKS -DSPARC diff --git a/hotspot/build/solaris/platform_sparcv9.gcc b/hotspot/make/solaris/platform_sparcv9.gcc similarity index 81% rename from hotspot/build/solaris/platform_sparcv9.gcc rename to hotspot/make/solaris/platform_sparcv9.gcc index 87d42becfa3..2824381774b 100644 --- a/hotspot/build/solaris/platform_sparcv9.gcc +++ b/hotspot/make/solaris/platform_sparcv9.gcc @@ -8,10 +8,8 @@ os_arch = solaris_sparc os_arch_model = solaris_sparc -lib_arch = sparc +lib_arch = sparcv9 compiler = gcc -gnu_dis_arch = sparc - sysdefs = -DSOLARIS -D_GNU_SOURCE -DSPARC diff --git a/hotspot/build/solaris/reorder.sh b/hotspot/make/solaris/reorder.sh similarity index 97% rename from hotspot/build/solaris/reorder.sh rename to hotspot/make/solaris/reorder.sh index 598f3ebbc38..925b0a2407c 100644 --- a/hotspot/build/solaris/reorder.sh +++ b/hotspot/make/solaris/reorder.sh @@ -55,8 +55,8 @@ test_setup() { echo "" echo "TEST_SETUP $1 $2" echo "" - libreldir=${ALT_OUTPUTDIR:-../../../build/solaris-$arch5}/reorder - libabsdir=${ALT_OUTPUTDIR:-$sdk_ws/build/solaris-$arch5}/reorder + libreldir=${ALT_OUTPUTDIR:-../../../make/solaris-$arch5}/reorder + libabsdir=${ALT_OUTPUTDIR:-$sdk_ws/make/solaris-$arch5}/reorder ( cd $sdk_ws/make/tools/reorder ; gnumake $libreldir/$arch5/libmcount.so ) if [ "${arch3}" = "i386" ] ; then # On Solaris/x86 we need to remove the symbol _mcount from the command @@ -271,11 +271,11 @@ jre=$sdk/jre arch3=`uname -p` # Arch name as used in Hotspot build: (eg. i486) -# /export/hotspot/build/solaris/solaris_${arch4}_compiler1 +# /export/hotspot/make/solaris/solaris_${arch4}_compiler1 arch4=$arch3 # Arch name as used in SDK build (eg. i586): -# /export/tiger/build/solaris-${arch3} +# /export/tiger/make/solaris-${arch3} arch5=$arch3 # Tweak for 64-bit sparc builds. At least they all agree. diff --git a/hotspot/build/test/Queens.java b/hotspot/make/test/Queens.java similarity index 100% rename from hotspot/build/test/Queens.java rename to hotspot/make/test/Queens.java diff --git a/hotspot/build/windows/README b/hotspot/make/windows/README similarity index 100% rename from hotspot/build/windows/README rename to hotspot/make/windows/README diff --git a/hotspot/build/windows/build.bat b/hotspot/make/windows/build.bat similarity index 91% rename from hotspot/build/windows/build.bat rename to hotspot/make/windows/build.bat index 7b7329b2098..36d4ec6b480 100644 --- a/hotspot/build/windows/build.bat +++ b/hotspot/make/windows/build.bat @@ -86,11 +86,11 @@ echo. goto usage :build -nmake -f %3/build/windows/build.make Variant=%2 WorkSpace=%3 BootStrapDir=%4 BuildUser="%USERNAME%" HOTSPOT_BUILD_VERSION="%5" %1 +nmake -f %3/make/windows/build.make Variant=%2 WorkSpace=%3 BootStrapDir=%4 BuildUser="%USERNAME%" HOTSPOT_BUILD_VERSION="%5" %1 goto end :build_adlc -nmake -f %3/build/windows/build.make Variant=compiler2 WorkSpace=%3 BootStrapDir=%4 BuildUser="%USERNAME%" HOTSPOT_BUILD_VERSION=%5 ADLC_ONLY=1 %1 +nmake -f %3/make/windows/build.make Variant=compiler2 WorkSpace=%3 BootStrapDir=%4 BuildUser="%USERNAME%" HOTSPOT_BUILD_VERSION=%5 ADLC_ONLY=1 %1 goto end :usage diff --git a/hotspot/build/windows/build.make b/hotspot/make/windows/build.make similarity index 92% rename from hotspot/build/windows/build.make rename to hotspot/make/windows/build.make index c5e48e1715d..a871a849eb1 100644 --- a/hotspot/build/windows/build.make +++ b/hotspot/make/windows/build.make @@ -118,13 +118,13 @@ VARIANT_TEXT=Kernel # !include "$(WorkSpace)/make/hotspot_version" -# Define HOTSPOT_VM_DISTRO based on settings in build/hotspot_distro -# or build/closed/hotspot_distro. +# Define HOTSPOT_VM_DISTRO based on settings in make/openjdk_distro +# or make/hotspot_distro. !ifndef HOTSPOT_VM_DISTRO -!if exists($(WorkSpace)\build\closed) -!include $(WorkSpace)\build\closed\hotspot_distro +!if exists($(WorkSpace)\src\closed) +!include $(WorkSpace)\make\hotspot_distro !else -!include $(WorkSpace)\build\hotspot_distro +!include $(WorkSpace)\make\openjdk_distro !endif !endif @@ -242,24 +242,24 @@ defaultTarget: product # product release optimized: checks $(variantDir) $(variantDir)\local.make sanity cd $(variantDir) - nmake -nologo -f $(WorkSpace)\build\windows\makefiles\top.make BUILD_FLAVOR=product ARCH=$(ARCH) + nmake -nologo -f $(WorkSpace)\make\windows\makefiles\top.make BUILD_FLAVOR=product ARCH=$(ARCH) # The debug or jvmg (all the same thing) is an optional build debug jvmg: checks $(variantDir) $(variantDir)\local.make sanity cd $(variantDir) - nmake -nologo -f $(WorkSpace)\build\windows\makefiles\top.make BUILD_FLAVOR=debug ARCH=$(ARCH) + nmake -nologo -f $(WorkSpace)\make\windows\makefiles\top.make BUILD_FLAVOR=debug ARCH=$(ARCH) fastdebug: checks $(variantDir) $(variantDir)\local.make sanity cd $(variantDir) - nmake -nologo -f $(WorkSpace)\build\windows\makefiles\top.make BUILD_FLAVOR=fastdebug ARCH=$(ARCH) + nmake -nologo -f $(WorkSpace)\make\windows\makefiles\top.make BUILD_FLAVOR=fastdebug ARCH=$(ARCH) develop: checks $(variantDir) $(variantDir)\local.make sanity cd $(variantDir) - nmake -nologo -f $(WorkSpace)\build\windows\makefiles\top.make BUILD_FLAVOR=product DEVELOP=1 ARCH=$(ARCH) + nmake -nologo -f $(WorkSpace)\make\windows\makefiles\top.make BUILD_FLAVOR=product DEVELOP=1 ARCH=$(ARCH) sanity: @ echo; @ cd $(variantDir) - @ nmake -nologo -f $(WorkSpace)\build\windows\makefiles\sanity.make + @ nmake -nologo -f $(WorkSpace)\make\windows\makefiles\sanity.make @ cd .. @ echo; @@ -293,7 +293,7 @@ $(variantDir)\local.make: checks @ echo BUILDARCH=$(BUILDARCH) >> $@ @ echo Platform_arch=$(Platform_arch) >> $@ @ echo Platform_arch_model=$(Platform_arch_model) >> $@ - @ sh $(WorkSpace)/build/windows/get_msc_ver.sh >> $@ + @ sh $(WorkSpace)/make/windows/get_msc_ver.sh >> $@ checks: checkVariant checkWorkSpace checkSA diff --git a/hotspot/build/windows/build_vm_def.sh b/hotspot/make/windows/build_vm_def.sh similarity index 96% rename from hotspot/build/windows/build_vm_def.sh rename to hotspot/make/windows/build_vm_def.sh index 4ccdb67d281..98e65150a65 100644 --- a/hotspot/build/windows/build_vm_def.sh +++ b/hotspot/make/windows/build_vm_def.sh @@ -24,7 +24,7 @@ # This shell script builds a vm.def file for the current VM variant. # The .def file exports vtbl symbols which allow the Serviceability -# Agent to run on Windows. See build/windows/projectfiles/*/vm.def +# Agent to run on Windows. See make/windows/projectfiles/*/vm.def # for more information. # # The script expects to be executed in the directory containing all of diff --git a/hotspot/build/windows/create.bat b/hotspot/make/windows/create.bat similarity index 97% rename from hotspot/build/windows/create.bat rename to hotspot/make/windows/create.bat index 71ad50d0bd6..a5a481ff7bd 100644 --- a/hotspot/build/windows/create.bat +++ b/hotspot/make/windows/create.bat @@ -69,7 +69,7 @@ set HotSpotBuildSpace=%2 set HotSpotJDKDist=%3 REM figure out MSC version -for /F %%i in ('sh %HotSpotWorkSpace%/build/windows/get_msc_ver.sh') do set %%i +for /F %%i in ('sh %HotSpotWorkSpace%/make/windows/get_msc_ver.sh') do set %%i echo ************************************************************** if "%MSC_VER%" == "1200" ( @@ -126,7 +126,7 @@ REM This is now safe to do. :copyfiles for /D %%i in (compiler1, compiler2, tiered, core, kernel) do ( if NOT EXIST %HotSpotBuildSpace%\%%i mkdir %HotSpotBuildSpace%\%%i -copy %HotSpotWorkSpace%\build\windows\projectfiles\%%i\* %HotSpotBuildSpace%\%%i\ > NUL +copy %HotSpotWorkSpace%\make\windows\projectfiles\%%i\* %HotSpotBuildSpace%\%%i\ > NUL ) REM force regneration of ProjectFile diff --git a/hotspot/build/windows/cross_build.bat b/hotspot/make/windows/cross_build.bat similarity index 95% rename from hotspot/build/windows/cross_build.bat rename to hotspot/make/windows/cross_build.bat index ef362caa07e..42e0fb147d7 100644 --- a/hotspot/build/windows/cross_build.bat +++ b/hotspot/make/windows/cross_build.bat @@ -40,7 +40,7 @@ SET OLDINCLUDE=%INCLUDE% SET OLDLIB=%LIB% SET OLDPATH=%PATH% call "%MSVCDir%\Bin\VCVARS32" -call %2\build\windows\build %1 adlc %2 %3 %4 +call %2\make\windows\build %1 adlc %2 %3 %4 SET INCLUDE=%OLDINCLUDE% SET LIB=%OLDLIB% SET PATH=%OLDPATH% @@ -52,7 +52,7 @@ SET MSSdk=C:\Program Files\Microsoft SDK :setenv2 call "%MSSdk%\SetEnv.bat" /XP64 SET ALT_ADLC_PATH=%CD%\windows_i486_compiler2\generated -call %2\build\windows\build %1 compiler2 %2 %3 %4 +call %2\make\windows\build %1 compiler2 %2 %3 %4 SET INCLUDE=%OLDINCLUDE% SET LIB=%OLDLIB% SET PATH=%OLDPATH% diff --git a/hotspot/build/windows/get_msc_ver.sh b/hotspot/make/windows/get_msc_ver.sh similarity index 100% rename from hotspot/build/windows/get_msc_ver.sh rename to hotspot/make/windows/get_msc_ver.sh diff --git a/hotspot/build/windows/jvmexp.lcf b/hotspot/make/windows/jvmexp.lcf similarity index 100% rename from hotspot/build/windows/jvmexp.lcf rename to hotspot/make/windows/jvmexp.lcf diff --git a/hotspot/build/windows/jvmexp_g.lcf b/hotspot/make/windows/jvmexp_g.lcf similarity index 100% rename from hotspot/build/windows/jvmexp_g.lcf rename to hotspot/make/windows/jvmexp_g.lcf diff --git a/hotspot/build/windows/makefiles/adlc.make b/hotspot/make/windows/makefiles/adlc.make similarity index 98% rename from hotspot/build/windows/makefiles/adlc.make rename to hotspot/make/windows/makefiles/adlc.make index 8dee8c3e6dd..f7665667fb1 100644 --- a/hotspot/build/windows/makefiles/adlc.make +++ b/hotspot/make/windows/makefiles/adlc.make @@ -22,7 +22,7 @@ # # -!include $(WorkSpace)/build/windows/makefiles/compile.make +!include $(WorkSpace)/make/windows/makefiles/compile.make # Rules for building adlc.exe diff --git a/hotspot/build/windows/makefiles/compile.make b/hotspot/make/windows/makefiles/compile.make similarity index 100% rename from hotspot/build/windows/makefiles/compile.make rename to hotspot/make/windows/makefiles/compile.make diff --git a/hotspot/build/windows/makefiles/debug.make b/hotspot/make/windows/makefiles/debug.make similarity index 88% rename from hotspot/build/windows/makefiles/debug.make rename to hotspot/make/windows/makefiles/debug.make index de7924173e5..7ea4aae9486 100644 --- a/hotspot/build/windows/makefiles/debug.make +++ b/hotspot/make/windows/makefiles/debug.make @@ -35,7 +35,7 @@ default:: _build_pch_file.obj $(AOUT) checkAndBuildSA CPP_FLAGS=$(CPP_FLAGS) $(DEBUG_OPT_OPTION) -!include $(WorkSpace)/build/windows/makefiles/vm.make +!include $(WorkSpace)/make/windows/makefiles/vm.make !include local.make !include $(GENERATED)/Dependencies @@ -46,10 +46,10 @@ HS_BUILD_ID=$(HS_BUILD_VER)-debug $(Res_Files): FORCE $(AOUT): $(Res_Files) $(Obj_Files) - sh $(WorkSpace)/build/windows/build_vm_def.sh + sh $(WorkSpace)/make/windows/build_vm_def.sh $(LINK) @<< $(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) << -!include $(WorkSpace)/build/windows/makefiles/shared.make -!include $(WorkSpace)/build/windows/makefiles/sa.make +!include $(WorkSpace)/make/windows/makefiles/shared.make +!include $(WorkSpace)/make/windows/makefiles/sa.make diff --git a/hotspot/build/windows/makefiles/defs.make b/hotspot/make/windows/makefiles/defs.make similarity index 97% rename from hotspot/build/windows/makefiles/defs.make rename to hotspot/make/windows/makefiles/defs.make index 1e1ab9fba47..19d49f17af6 100644 --- a/hotspot/build/windows/makefiles/defs.make +++ b/hotspot/make/windows/makefiles/defs.make @@ -26,7 +26,7 @@ # Include the top level defs.make under make directory instead of this one. # This file is included into make/defs.make. # On windows it is only used to construct parameters for -# build/windows/build.make when make/Makefile is used to build VM. +# make/windows/build.make when make/Makefile is used to build VM. SLASH_JAVA ?= J: PATH_SEP = ; @@ -112,7 +112,7 @@ else ABS_OUTPUTDIR := $(subst /,\\,$(shell $(CD) $(OUTPUTDIR);$(PWD))) ABS_BOOTDIR := $(subst /,\\,$(shell $(CD) $(BOOTDIR);$(PWD))) ABS_GAMMADIR := $(subst /,\\,$(shell $(CD) $(GAMMADIR);$(PWD))) - ABS_OS_MAKEFILE := $(subst /,\\,$(shell $(CD) $(HS_BUILD_DIR)/$(OSNAME);$(PWD))/build.make) + ABS_OS_MAKEFILE := $(subst /,\\,$(shell $(CD) $(HS_MAKE_DIR)/$(OSNAME);$(PWD))/build.make) endif # Disable building SA on windows until we are sure diff --git a/hotspot/build/windows/makefiles/fastdebug.make b/hotspot/make/windows/makefiles/fastdebug.make similarity index 88% rename from hotspot/build/windows/makefiles/fastdebug.make rename to hotspot/make/windows/makefiles/fastdebug.make index dcbacdc9449..cb6901bce2f 100644 --- a/hotspot/build/windows/makefiles/fastdebug.make +++ b/hotspot/make/windows/makefiles/fastdebug.make @@ -35,7 +35,7 @@ default:: _build_pch_file.obj $(AOUT) checkAndBuildSA CPP_FLAGS=$(CPP_FLAGS) $(FASTDEBUG_OPT_OPTION) -!include $(WorkSpace)/build/windows/makefiles/vm.make +!include $(WorkSpace)/make/windows/makefiles/vm.make !include local.make !include $(GENERATED)/Dependencies @@ -46,10 +46,10 @@ HS_BUILD_ID=$(HS_BUILD_VER)-fastdebug $(Res_Files): FORCE $(AOUT): $(Res_Files) $(Obj_Files) - sh $(WorkSpace)/build/windows/build_vm_def.sh + sh $(WorkSpace)/make/windows/build_vm_def.sh $(LINK) @<< $(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) << -!include $(WorkSpace)/build/windows/makefiles/shared.make -!include $(WorkSpace)/build/windows/makefiles/sa.make +!include $(WorkSpace)/make/windows/makefiles/shared.make +!include $(WorkSpace)/make/windows/makefiles/sa.make diff --git a/hotspot/build/windows/makefiles/generated.make b/hotspot/make/windows/makefiles/generated.make similarity index 90% rename from hotspot/build/windows/makefiles/generated.make rename to hotspot/make/windows/makefiles/generated.make index 8def591058d..7eff90d1681 100644 --- a/hotspot/build/windows/makefiles/generated.make +++ b/hotspot/make/windows/makefiles/generated.make @@ -23,15 +23,15 @@ # !include ../local.make -!include $(WorkSpace)/build/windows/makefiles/makedeps.make +!include $(WorkSpace)/make/windows/makefiles/makedeps.make !include local.make # Pick up rules for building JVMTI (JSR-163) JvmtiOutDir=jvmtifiles -!include $(WorkSpace)/build/windows/makefiles/jvmti.make +!include $(WorkSpace)/make/windows/makefiles/jvmti.make # Pick up rules for building SA -!include $(WorkSpace)/build/windows/makefiles/sa.make +!include $(WorkSpace)/make/windows/makefiles/sa.make !if ("$(Variant)" == "compiler2") || ("$(Variant)" == "tiered") default:: includeDB.current Dependencies incls/ad_$(Platform_arch_model).cpp incls/dfa_$(Platform_arch_model).cpp $(JvmtiGeneratedFiles) @@ -83,7 +83,7 @@ includeDB.current Dependencies: classes/MakeDeps.class $(IncludeDBs) cat $(IncludeDBs) > includeDB if exist incls rmdir /s /q incls mkdir incls - $(RUN_JAVA) -Djava.class.path=classes MakeDeps WinGammaPlatform$(VcVersion) $(WorkSpace)/build/windows/platform_$(BUILDARCH) includeDB $(MakeDepsOptions) + $(RUN_JAVA) -Djava.class.path=classes MakeDeps WinGammaPlatform$(VcVersion) $(WorkSpace)/make/windows/platform_$(BUILDARCH) includeDB $(MakeDepsOptions) rm -f includeDB.current cp includeDB includeDB.current @@ -94,8 +94,8 @@ classes/MakeDeps.class: $(MakeDepsSources) !if ("$(Variant)" == "compiler2") || ("$(Variant)" == "tiered") -!include $(WorkSpace)/build/windows/makefiles/adlc.make +!include $(WorkSpace)/make/windows/makefiles/adlc.make !endif -!include $(WorkSpace)/build/windows/makefiles/shared.make +!include $(WorkSpace)/make/windows/makefiles/shared.make diff --git a/hotspot/build/windows/makefiles/jvmti.make b/hotspot/make/windows/makefiles/jvmti.make similarity index 98% rename from hotspot/build/windows/makefiles/jvmti.make rename to hotspot/make/windows/makefiles/jvmti.make index 3bd5ce6e2f3..74600a11f77 100644 --- a/hotspot/build/windows/makefiles/jvmti.make +++ b/hotspot/make/windows/makefiles/jvmti.make @@ -27,7 +27,7 @@ # # It knows how to build and run the tools to generate jvmti. -!include $(WorkSpace)/build/windows/makefiles/rules.make +!include $(WorkSpace)/make/windows/makefiles/rules.make # ######################################################################### diff --git a/hotspot/build/windows/makefiles/makedeps.make b/hotspot/make/windows/makefiles/makedeps.make similarity index 97% rename from hotspot/build/windows/makefiles/makedeps.make rename to hotspot/make/windows/makefiles/makedeps.make index f82f4264858..e3164313d7e 100644 --- a/hotspot/build/windows/makefiles/makedeps.make +++ b/hotspot/make/windows/makefiles/makedeps.make @@ -22,7 +22,7 @@ # # -!include $(WorkSpace)/build/windows/makefiles/rules.make +!include $(WorkSpace)/make/windows/makefiles/rules.make # This is used externally by both batch and IDE builds, so can't # reference any of the HOTSPOTWORKSPACE, HOTSPOTBUILDSPACE, @@ -30,7 +30,7 @@ # # NOTE: unfortunately the MakeDepsSources list must be kept # synchronized between this and the Solaris version -# (build/solaris/makefiles/makedeps.make). +# (make/solaris/makefiles/makedeps.make). MakeDepsSources=\ $(WorkSpace)\src\share\tools\MakeDeps\Database.java \ @@ -119,7 +119,7 @@ MakeDepsIDEOptions=\ -additionalFile includeDB_gc_shared \ -additionalFile includeDB_gc_serial \ -additionalGeneratedFile $(HOTSPOTBUILDSPACE)\%f\%b vm.def \ - -prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\build\windows\build_vm_def.sh" \ + -prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh" \ $(MakeDepsIncludesPRIVATE) # Add in build-specific options diff --git a/hotspot/build/windows/makefiles/product.make b/hotspot/make/windows/makefiles/product.make similarity index 89% rename from hotspot/build/windows/makefiles/product.make rename to hotspot/make/windows/makefiles/product.make index d6fe73d125b..a2887cfcef3 100644 --- a/hotspot/build/windows/makefiles/product.make +++ b/hotspot/make/windows/makefiles/product.make @@ -38,7 +38,7 @@ RELEASE= RC_FLAGS=$(RC_FLAGS) /D "NDEBUG" -!include $(WorkSpace)/build/windows/makefiles/vm.make +!include $(WorkSpace)/make/windows/makefiles/vm.make !include local.make !include $(GENERATED)/Dependencies @@ -56,11 +56,11 @@ $(AOUT): $(Res_Files) $(Obj_Files) << !else $(AOUT): $(Res_Files) $(Obj_Files) - sh $(WorkSpace)/build/windows/build_vm_def.sh + sh $(WorkSpace)/make/windows/build_vm_def.sh $(LINK) @<< $(LINK_FLAGS) /out:$@ /implib:$*.lib /def:vm.def $(Obj_Files) $(Res_Files) << !endif -!include $(WorkSpace)/build/windows/makefiles/shared.make -!include $(WorkSpace)/build/windows/makefiles/sa.make +!include $(WorkSpace)/make/windows/makefiles/shared.make +!include $(WorkSpace)/make/windows/makefiles/sa.make diff --git a/hotspot/build/windows/makefiles/rules.make b/hotspot/make/windows/makefiles/rules.make similarity index 100% rename from hotspot/build/windows/makefiles/rules.make rename to hotspot/make/windows/makefiles/rules.make diff --git a/hotspot/build/windows/makefiles/sa.make b/hotspot/make/windows/makefiles/sa.make similarity index 97% rename from hotspot/build/windows/makefiles/sa.make rename to hotspot/make/windows/makefiles/sa.make index 0c649dcaf94..216c44fc870 100644 --- a/hotspot/build/windows/makefiles/sa.make +++ b/hotspot/make/windows/makefiles/sa.make @@ -33,8 +33,8 @@ checkAndBuildSA:: !else # This first part is used to build sa-jdi.jar -!include $(WorkSpace)/build/windows/makefiles/rules.make -!include $(WorkSpace)/build/sa.files +!include $(WorkSpace)/make/windows/makefiles/rules.make +!include $(WorkSpace)/make/sa.files GENERATED = ..\generated diff --git a/hotspot/build/windows/makefiles/sanity.make b/hotspot/make/windows/makefiles/sanity.make similarity index 100% rename from hotspot/build/windows/makefiles/sanity.make rename to hotspot/make/windows/makefiles/sanity.make diff --git a/hotspot/build/windows/makefiles/shared.make b/hotspot/make/windows/makefiles/shared.make similarity index 93% rename from hotspot/build/windows/makefiles/shared.make rename to hotspot/make/windows/makefiles/shared.make index 4e2b04d6f17..a5055045e82 100644 --- a/hotspot/build/windows/makefiles/shared.make +++ b/hotspot/make/windows/makefiles/shared.make @@ -40,7 +40,7 @@ $(SUBDIRS): FORCE @if not exist $@ mkdir $@ @if not exist $@\local.make echo # Empty > $@\local.make @echo nmake $(ACTION) in $(DIR)\$@ - cd $@ && $(MAKE) /NOLOGO /f $(WorkSpace)\build\windows\makefiles\$@.make $(ACTION) DIR=$(DIR)\$@ BUILD_FLAVOR=$(BUILD_FLAVOR) + cd $@ && $(MAKE) /NOLOGO /f $(WorkSpace)\make\windows\makefiles\$@.make $(ACTION) DIR=$(DIR)\$@ BUILD_FLAVOR=$(BUILD_FLAVOR) !endif # Creates the needed directory diff --git a/hotspot/build/windows/makefiles/top.make b/hotspot/make/windows/makefiles/top.make similarity index 95% rename from hotspot/build/windows/makefiles/top.make rename to hotspot/make/windows/makefiles/top.make index 1ff6e1f4eec..679e5692efc 100644 --- a/hotspot/build/windows/makefiles/top.make +++ b/hotspot/make/windows/makefiles/top.make @@ -30,5 +30,5 @@ SUBDIRS=generated SUBDIRS=generated $(BUILD_FLAVOR) !endif -!include $(WorkSpace)/build/windows/makefiles/shared.make +!include $(WorkSpace)/make/windows/makefiles/shared.make diff --git a/hotspot/build/windows/makefiles/vm.make b/hotspot/make/windows/makefiles/vm.make similarity index 99% rename from hotspot/build/windows/makefiles/vm.make rename to hotspot/make/windows/makefiles/vm.make index ddfc8729678..c911ab261f0 100644 --- a/hotspot/build/windows/makefiles/vm.make +++ b/hotspot/make/windows/makefiles/vm.make @@ -58,6 +58,7 @@ CPP_FLAGS=$(CPP_FLAGS) /D "COMPILER1" /D "COMPILER2" # The following variables are defined in the generated local.make file. CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_RELEASE_VERSION=\"$(HS_BUILD_VER)\"" CPP_FLAGS=$(CPP_FLAGS) /D "JRE_RELEASE_VERSION=\"$(JRE_RELEASE_VER)\"" +CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_LIB_ARCH=\"$(BUILDARCH)\"" CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_BUILD_TARGET=\"$(BUILD_FLAVOR)\"" CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_BUILD_USER=\"$(BuildUser)\"" CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_VM_DISTRO=\"$(HOTSPOT_VM_DISTRO)\"" diff --git a/hotspot/build/windows/platform_amd64 b/hotspot/make/windows/platform_amd64 similarity index 88% rename from hotspot/build/windows/platform_amd64 rename to hotspot/make/windows/platform_amd64 index e19b4878163..49a326e5690 100644 --- a/hotspot/build/windows/platform_amd64 +++ b/hotspot/make/windows/platform_amd64 @@ -10,6 +10,6 @@ os_arch = windows_x86 os_arch_model = windows_x86_64 -compiler = visCPP +lib_arch = amd64 -gnu_dis_arch = amd64 +compiler = visCPP diff --git a/hotspot/build/windows/platform_i486 b/hotspot/make/windows/platform_i486 similarity index 88% rename from hotspot/build/windows/platform_i486 rename to hotspot/make/windows/platform_i486 index a426305fb5d..bdb31681038 100644 --- a/hotspot/build/windows/platform_i486 +++ b/hotspot/make/windows/platform_i486 @@ -10,7 +10,6 @@ os_arch = windows_x86 os_arch_model = windows_x86_32 +lib_arch = i386 + compiler = visCPP - -gnu_dis_arch = i386 - diff --git a/hotspot/make/windows/platform_ia64 b/hotspot/make/windows/platform_ia64 new file mode 100644 index 00000000000..ca269b499fd --- /dev/null +++ b/hotspot/make/windows/platform_ia64 @@ -0,0 +1,12 @@ +// Platform file for Itanium Windows platform $Revision: 1.0 $ + +os_family = win32 + +arch = ia64 + +os_arch = win32_ia64 + +compiler = visCPP + +gnu_dis_arch = ia64 + diff --git a/hotspot/build/windows/projectfiles/common/Makefile b/hotspot/make/windows/projectfiles/common/Makefile similarity index 95% rename from hotspot/build/windows/projectfiles/common/Makefile rename to hotspot/make/windows/projectfiles/common/Makefile index b016cba8bf9..1b4a5bf7343 100644 --- a/hotspot/build/windows/projectfiles/common/Makefile +++ b/hotspot/make/windows/projectfiles/common/Makefile @@ -36,13 +36,13 @@ BootStrapDir=$(JAVA_HOME) !endif !endif -!include $(HOTSPOTWORKSPACE)/build/windows/makefiles/makedeps.make +!include $(HOTSPOTWORKSPACE)/make/windows/makefiles/makedeps.make # Pick up rules for building JVMTI (JSR-163) JvmtiOutDir=$(HOTSPOTBUILDSPACE)\jvmtifiles -!include $(HOTSPOTWORKSPACE)/build/windows/makefiles/jvmti.make +!include $(HOTSPOTWORKSPACE)/make/windows/makefiles/jvmti.make -Platform=$(HOTSPOTWORKSPACE)/build/windows/platform_$(BUILDARCH) +Platform=$(HOTSPOTWORKSPACE)/make/windows/platform_$(BUILDARCH) default:: $(AdditionalTargets) $(JvmtiGeneratedFiles) @@ -83,13 +83,13 @@ IncludeDBs = $(IncludeDBs_compiler1) !if "$(Variant)" == "compiler2" IncludeDBs = $(IncludeDBs_compiler2) # Pick up rules for building adlc -!include $(HOTSPOTWORKSPACE)/build/windows/makefiles/adlc.make +!include $(HOTSPOTWORKSPACE)/make/windows/makefiles/adlc.make !endif !if "$(Variant)" == "tiered" IncludeDBs = $(IncludeDBs_tiered) # Pick up rules for building adlc -!include $(HOTSPOTWORKSPACE)/build/windows/makefiles/adlc.make +!include $(HOTSPOTWORKSPACE)/make/windows/makefiles/adlc.make !endif !if "$(Variant)" == "core" diff --git a/hotspot/build/windows/projectfiles/compiler1/Makefile b/hotspot/make/windows/projectfiles/compiler1/Makefile similarity index 93% rename from hotspot/build/windows/projectfiles/compiler1/Makefile rename to hotspot/make/windows/projectfiles/compiler1/Makefile index 1cddb034fe2..e189845fd58 100644 --- a/hotspot/build/windows/projectfiles/compiler1/Makefile +++ b/hotspot/make/windows/projectfiles/compiler1/Makefile @@ -25,4 +25,4 @@ Variant=compiler1 !include local.make -!include $(HOTSPOTWORKSPACE)/build/windows/projectfiles/common/Makefile +!include $(HOTSPOTWORKSPACE)/make/windows/projectfiles/common/Makefile diff --git a/hotspot/build/windows/projectfiles/compiler1/vm.def b/hotspot/make/windows/projectfiles/compiler1/vm.def similarity index 54% rename from hotspot/build/windows/projectfiles/compiler1/vm.def rename to hotspot/make/windows/projectfiles/compiler1/vm.def index 4475c606215..7811a1fc9bb 100644 --- a/hotspot/build/windows/projectfiles/compiler1/vm.def +++ b/hotspot/make/windows/projectfiles/compiler1/vm.def @@ -1,7 +1,7 @@ ; ; This .DEF file is a placeholder for one which is automatically ; generated during the build process. See -; build\windows\build_vm_def.sh and -; build\windows\makefiles\makedeps.make (esp. the "-prelink" +; make\windows\build_vm_def.sh and +; make\windows\makefiles\makedeps.make (esp. the "-prelink" ; options). ; diff --git a/hotspot/build/windows/projectfiles/compiler1/vm.dsw b/hotspot/make/windows/projectfiles/compiler1/vm.dsw similarity index 100% rename from hotspot/build/windows/projectfiles/compiler1/vm.dsw rename to hotspot/make/windows/projectfiles/compiler1/vm.dsw diff --git a/hotspot/build/windows/projectfiles/compiler2/ADLCompiler.dsp b/hotspot/make/windows/projectfiles/compiler2/ADLCompiler.dsp similarity index 100% rename from hotspot/build/windows/projectfiles/compiler2/ADLCompiler.dsp rename to hotspot/make/windows/projectfiles/compiler2/ADLCompiler.dsp diff --git a/hotspot/build/windows/projectfiles/compiler2/ADLCompiler.dsw b/hotspot/make/windows/projectfiles/compiler2/ADLCompiler.dsw similarity index 100% rename from hotspot/build/windows/projectfiles/compiler2/ADLCompiler.dsw rename to hotspot/make/windows/projectfiles/compiler2/ADLCompiler.dsw diff --git a/hotspot/build/windows/projectfiles/compiler2/Makefile b/hotspot/make/windows/projectfiles/compiler2/Makefile similarity index 94% rename from hotspot/build/windows/projectfiles/compiler2/Makefile rename to hotspot/make/windows/projectfiles/compiler2/Makefile index eca41f04d5d..567f02030ee 100644 --- a/hotspot/build/windows/projectfiles/compiler2/Makefile +++ b/hotspot/make/windows/projectfiles/compiler2/Makefile @@ -26,4 +26,4 @@ Variant=compiler2 !include local.make AdditionalTargets=incls/ad_$(Platform_arch_model).cpp incls/dfa_$(Platform_arch_model).cpp -!include $(HOTSPOTWORKSPACE)/build/windows/projectfiles/common/Makefile +!include $(HOTSPOTWORKSPACE)/make/windows/projectfiles/common/Makefile diff --git a/hotspot/build/windows/projectfiles/compiler2/vm.def b/hotspot/make/windows/projectfiles/compiler2/vm.def similarity index 54% rename from hotspot/build/windows/projectfiles/compiler2/vm.def rename to hotspot/make/windows/projectfiles/compiler2/vm.def index 4475c606215..7811a1fc9bb 100644 --- a/hotspot/build/windows/projectfiles/compiler2/vm.def +++ b/hotspot/make/windows/projectfiles/compiler2/vm.def @@ -1,7 +1,7 @@ ; ; This .DEF file is a placeholder for one which is automatically ; generated during the build process. See -; build\windows\build_vm_def.sh and -; build\windows\makefiles\makedeps.make (esp. the "-prelink" +; make\windows\build_vm_def.sh and +; make\windows\makefiles\makedeps.make (esp. the "-prelink" ; options). ; diff --git a/hotspot/build/windows/projectfiles/compiler2/vm.dsw b/hotspot/make/windows/projectfiles/compiler2/vm.dsw similarity index 100% rename from hotspot/build/windows/projectfiles/compiler2/vm.dsw rename to hotspot/make/windows/projectfiles/compiler2/vm.dsw diff --git a/hotspot/build/windows/projectfiles/core/Makefile b/hotspot/make/windows/projectfiles/core/Makefile similarity index 93% rename from hotspot/build/windows/projectfiles/core/Makefile rename to hotspot/make/windows/projectfiles/core/Makefile index 243188b20ad..e42986de410 100644 --- a/hotspot/build/windows/projectfiles/core/Makefile +++ b/hotspot/make/windows/projectfiles/core/Makefile @@ -25,4 +25,4 @@ Variant=core !include local.make -!include $(HOTSPOTWORKSPACE)/build/windows/projectfiles/common/Makefile +!include $(HOTSPOTWORKSPACE)/make/windows/projectfiles/common/Makefile diff --git a/hotspot/build/windows/projectfiles/core/vm.def b/hotspot/make/windows/projectfiles/core/vm.def similarity index 54% rename from hotspot/build/windows/projectfiles/core/vm.def rename to hotspot/make/windows/projectfiles/core/vm.def index 4475c606215..7811a1fc9bb 100644 --- a/hotspot/build/windows/projectfiles/core/vm.def +++ b/hotspot/make/windows/projectfiles/core/vm.def @@ -1,7 +1,7 @@ ; ; This .DEF file is a placeholder for one which is automatically ; generated during the build process. See -; build\windows\build_vm_def.sh and -; build\windows\makefiles\makedeps.make (esp. the "-prelink" +; make\windows\build_vm_def.sh and +; make\windows\makefiles\makedeps.make (esp. the "-prelink" ; options). ; diff --git a/hotspot/build/windows/projectfiles/core/vm.dsw b/hotspot/make/windows/projectfiles/core/vm.dsw similarity index 100% rename from hotspot/build/windows/projectfiles/core/vm.dsw rename to hotspot/make/windows/projectfiles/core/vm.dsw diff --git a/hotspot/build/windows/projectfiles/kernel/Makefile b/hotspot/make/windows/projectfiles/kernel/Makefile similarity index 93% rename from hotspot/build/windows/projectfiles/kernel/Makefile rename to hotspot/make/windows/projectfiles/kernel/Makefile index 2ba53d245dd..0f8508e431e 100644 --- a/hotspot/build/windows/projectfiles/kernel/Makefile +++ b/hotspot/make/windows/projectfiles/kernel/Makefile @@ -25,4 +25,4 @@ Variant=compiler1 !include local.make -!include $(HOTSPOTWORKSPACE)/build/windows/projectfiles/common/Makefile +!include $(HOTSPOTWORKSPACE)/make/windows/projectfiles/common/Makefile diff --git a/hotspot/build/windows/projectfiles/kernel/vm.def b/hotspot/make/windows/projectfiles/kernel/vm.def similarity index 54% rename from hotspot/build/windows/projectfiles/kernel/vm.def rename to hotspot/make/windows/projectfiles/kernel/vm.def index 4475c606215..7811a1fc9bb 100644 --- a/hotspot/build/windows/projectfiles/kernel/vm.def +++ b/hotspot/make/windows/projectfiles/kernel/vm.def @@ -1,7 +1,7 @@ ; ; This .DEF file is a placeholder for one which is automatically ; generated during the build process. See -; build\windows\build_vm_def.sh and -; build\windows\makefiles\makedeps.make (esp. the "-prelink" +; make\windows\build_vm_def.sh and +; make\windows\makefiles\makedeps.make (esp. the "-prelink" ; options). ; diff --git a/hotspot/build/windows/projectfiles/kernel/vm.dsw b/hotspot/make/windows/projectfiles/kernel/vm.dsw similarity index 100% rename from hotspot/build/windows/projectfiles/kernel/vm.dsw rename to hotspot/make/windows/projectfiles/kernel/vm.dsw diff --git a/hotspot/build/windows/projectfiles/tiered/ADLCompiler.dsp b/hotspot/make/windows/projectfiles/tiered/ADLCompiler.dsp similarity index 100% rename from hotspot/build/windows/projectfiles/tiered/ADLCompiler.dsp rename to hotspot/make/windows/projectfiles/tiered/ADLCompiler.dsp diff --git a/hotspot/build/windows/projectfiles/tiered/ADLCompiler.dsw b/hotspot/make/windows/projectfiles/tiered/ADLCompiler.dsw similarity index 100% rename from hotspot/build/windows/projectfiles/tiered/ADLCompiler.dsw rename to hotspot/make/windows/projectfiles/tiered/ADLCompiler.dsw diff --git a/hotspot/build/windows/projectfiles/tiered/Makefile b/hotspot/make/windows/projectfiles/tiered/Makefile similarity index 94% rename from hotspot/build/windows/projectfiles/tiered/Makefile rename to hotspot/make/windows/projectfiles/tiered/Makefile index f92d249109b..1aaae59680d 100644 --- a/hotspot/build/windows/projectfiles/tiered/Makefile +++ b/hotspot/make/windows/projectfiles/tiered/Makefile @@ -26,4 +26,4 @@ Variant=tiered !include local.make AdditionalTargets=incls/ad_$(Platform_arch_model).cpp incls/dfa_$(Platform_arch_model).cpp -!include $(HOTSPOTWORKSPACE)/build/windows/projectfiles/common/Makefile +!include $(HOTSPOTWORKSPACE)/make/windows/projectfiles/common/Makefile diff --git a/hotspot/make/windows/projectfiles/tiered/vm.def b/hotspot/make/windows/projectfiles/tiered/vm.def new file mode 100644 index 00000000000..7811a1fc9bb --- /dev/null +++ b/hotspot/make/windows/projectfiles/tiered/vm.def @@ -0,0 +1,7 @@ +; +; This .DEF file is a placeholder for one which is automatically +; generated during the build process. See +; make\windows\build_vm_def.sh and +; make\windows\makefiles\makedeps.make (esp. the "-prelink" +; options). +; diff --git a/hotspot/build/windows/projectfiles/tiered/vm.dsw b/hotspot/make/windows/projectfiles/tiered/vm.dsw similarity index 100% rename from hotspot/build/windows/projectfiles/tiered/vm.dsw rename to hotspot/make/windows/projectfiles/tiered/vm.dsw diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index c6ea4fc0f80..a4963c65078 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -1779,7 +1779,7 @@ void MacroAssembler::verify_oop_subroutine() { // Check the klassOop of this object for being in the right area of memory. // Cannot do the load in the delay above slot in case O0 is null - ld_ptr(Address(O0_obj, 0, oopDesc::klass_offset_in_bytes()), O0_obj); + load_klass(O0_obj, O0_obj); // assert((klass & klass_mask) == klass_bits); if( Universe::verify_klass_mask() != Universe::verify_oop_mask() ) set(Universe::verify_klass_mask(), O2_mask); @@ -1788,8 +1788,9 @@ void MacroAssembler::verify_oop_subroutine() { and3(O0_obj, O2_mask, O4_temp); cmp(O4_temp, O3_bits); brx(notEqual, false, pn, fail); + delayed()->nop(); // Check the klass's klass - delayed()->ld_ptr(Address(O0_obj, 0, oopDesc::klass_offset_in_bytes()), O0_obj); + load_klass(O0_obj, O0_obj); and3(O0_obj, O2_mask, O4_temp); cmp(O4_temp, O3_bits); brx(notEqual, false, pn, fail); @@ -2588,8 +2589,9 @@ void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, R and3(mark_reg, markOopDesc::biased_lock_mask_in_place, temp_reg); cmp(temp_reg, markOopDesc::biased_lock_pattern); brx(Assembler::notEqual, false, Assembler::pn, cas_label); + delayed()->nop(); - delayed()->ld_ptr(Address(obj_reg, 0, oopDesc::klass_offset_in_bytes()), temp_reg); + load_klass(obj_reg, temp_reg); ld_ptr(Address(temp_reg, 0, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()), temp_reg); or3(G2_thread, temp_reg, temp_reg); xor3(mark_reg, temp_reg, temp_reg); @@ -2668,7 +2670,7 @@ void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, R // // FIXME: due to a lack of registers we currently blow away the age // bits in this situation. Should attempt to preserve them. - ld_ptr(Address(obj_reg, 0, oopDesc::klass_offset_in_bytes()), temp_reg); + load_klass(obj_reg, temp_reg); ld_ptr(Address(temp_reg, 0, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()), temp_reg); or3(G2_thread, temp_reg, temp_reg); casx_under_lock(mark_addr.base(), mark_reg, temp_reg, @@ -2700,7 +2702,7 @@ void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, R // // FIXME: due to a lack of registers we currently blow away the age // bits in this situation. Should attempt to preserve them. - ld_ptr(Address(obj_reg, 0, oopDesc::klass_offset_in_bytes()), temp_reg); + load_klass(obj_reg, temp_reg); ld_ptr(Address(temp_reg, 0, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()), temp_reg); casx_under_lock(mark_addr.base(), mark_reg, temp_reg, (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); @@ -3406,7 +3408,7 @@ void MacroAssembler::tlab_refill(Label& retry, Label& try_eden, Label& slow_case // set klass to intArrayKlass set((intptr_t)Universe::intArrayKlassObj_addr(), t2); ld_ptr(t2, 0, t2); - st_ptr(t2, top, oopDesc::klass_offset_in_bytes()); + store_klass(t2, top); sub(t1, typeArrayOopDesc::header_size(T_INT), t1); add(t1, ThreadLocalAllocBuffer::alignment_reserve(), t1); sll_ptr(t1, log2_intptr(HeapWordSize/sizeof(jint)), t1); @@ -3534,3 +3536,153 @@ void MacroAssembler::bang_stack_size(Register Rsize, Register Rtsp, st(G0, Rtsp, Rscratch); } } + +void MacroAssembler::load_klass(Register s, Register d) { + // The number of bytes in this code is used by + // MachCallDynamicJavaNode::ret_addr_offset() + // if this changes, change that. + if (UseCompressedOops) { + lduw(s, oopDesc::klass_offset_in_bytes(), d); + decode_heap_oop_not_null(d); + } else { + ld_ptr(s, oopDesc::klass_offset_in_bytes(), d); + } +} + +// ??? figure out src vs. dst! +void MacroAssembler::store_klass(Register d, Register s1) { + if (UseCompressedOops) { + assert(s1 != d, "not enough registers"); + encode_heap_oop_not_null(d); + // Zero out entire klass field first. + st_ptr(G0, s1, oopDesc::klass_offset_in_bytes()); + st(d, s1, oopDesc::klass_offset_in_bytes()); + } else { + st_ptr(d, s1, oopDesc::klass_offset_in_bytes()); + } +} + +void MacroAssembler::load_heap_oop(const Address& s, Register d, int offset) { + if (UseCompressedOops) { + lduw(s, d, offset); + decode_heap_oop(d); + } else { + ld_ptr(s, d, offset); + } +} + +void MacroAssembler::load_heap_oop(Register s1, Register s2, Register d) { + if (UseCompressedOops) { + lduw(s1, s2, d); + decode_heap_oop(d, d); + } else { + ld_ptr(s1, s2, d); + } +} + +void MacroAssembler::load_heap_oop(Register s1, int simm13a, Register d) { + if (UseCompressedOops) { + lduw(s1, simm13a, d); + decode_heap_oop(d, d); + } else { + ld_ptr(s1, simm13a, d); + } +} + +void MacroAssembler::store_heap_oop(Register d, Register s1, Register s2) { + if (UseCompressedOops) { + assert(s1 != d && s2 != d, "not enough registers"); + encode_heap_oop(d); + st(d, s1, s2); + } else { + st_ptr(d, s1, s2); + } +} + +void MacroAssembler::store_heap_oop(Register d, Register s1, int simm13a) { + if (UseCompressedOops) { + assert(s1 != d, "not enough registers"); + encode_heap_oop(d); + st(d, s1, simm13a); + } else { + st_ptr(d, s1, simm13a); + } +} + +void MacroAssembler::store_heap_oop(Register d, const Address& a, int offset) { + if (UseCompressedOops) { + assert(a.base() != d, "not enough registers"); + encode_heap_oop(d); + st(d, a, offset); + } else { + st_ptr(d, a, offset); + } +} + + +void MacroAssembler::encode_heap_oop(Register src, Register dst) { + assert (UseCompressedOops, "must be compressed"); + Label done; + if (src == dst) { + // optimize for frequent case src == dst + bpr(rc_nz, true, Assembler::pt, src, done); + delayed() -> sub(src, G6_heapbase, dst); // annuled if not taken + bind(done); + srlx(src, LogMinObjAlignmentInBytes, dst); + } else { + bpr(rc_z, false, Assembler::pn, src, done); + delayed() -> mov(G0, dst); + // could be moved before branch, and annulate delay, + // but may add some unneeded work decoding null + sub(src, G6_heapbase, dst); + srlx(dst, LogMinObjAlignmentInBytes, dst); + bind(done); + } +} + + +void MacroAssembler::encode_heap_oop_not_null(Register r) { + assert (UseCompressedOops, "must be compressed"); + sub(r, G6_heapbase, r); + srlx(r, LogMinObjAlignmentInBytes, r); +} + +void MacroAssembler::encode_heap_oop_not_null(Register src, Register dst) { + assert (UseCompressedOops, "must be compressed"); + sub(src, G6_heapbase, dst); + srlx(dst, LogMinObjAlignmentInBytes, dst); +} + +// Same algorithm as oops.inline.hpp decode_heap_oop. +void MacroAssembler::decode_heap_oop(Register src, Register dst) { + assert (UseCompressedOops, "must be compressed"); + Label done; + sllx(src, LogMinObjAlignmentInBytes, dst); + bpr(rc_nz, true, Assembler::pt, dst, done); + delayed() -> add(dst, G6_heapbase, dst); // annuled if not taken + bind(done); +} + +void MacroAssembler::decode_heap_oop_not_null(Register r) { + // Do not add assert code to this unless you change vtableStubs_sparc.cpp + // pd_code_size_limit. + assert (UseCompressedOops, "must be compressed"); + sllx(r, LogMinObjAlignmentInBytes, r); + add(r, G6_heapbase, r); +} + +void MacroAssembler::decode_heap_oop_not_null(Register src, Register dst) { + // Do not add assert code to this unless you change vtableStubs_sparc.cpp + // pd_code_size_limit. + assert (UseCompressedOops, "must be compressed"); + sllx(src, LogMinObjAlignmentInBytes, dst); + add(dst, G6_heapbase, dst); +} + +void MacroAssembler::reinit_heapbase() { + if (UseCompressedOops) { + // call indirectly to solve generation ordering problem + Address base(G6_heapbase, (address)Universe::heap_base_addr()); + load_ptr_contents(base, G6_heapbase); + } +} diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index 15ec5f5a199..c1aae2e6620 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -59,6 +59,7 @@ class BiasedLockingCounters; // This global always holds the current JavaThread pointer: REGISTER_DECLARATION(Register, G2_thread , G2); +REGISTER_DECLARATION(Register, G6_heapbase , G6); // The following globals are part of the Java calling convention: @@ -1975,6 +1976,31 @@ class MacroAssembler: public Assembler { inline void tstbool( Register s ) { tst(s); } inline void movbool( bool boolconst, Register d) { mov( (int) boolconst, d); } + // klass oop manipulations if compressed + void load_klass(Register src_oop, Register dst); + void store_klass(Register dst_oop, Register s1); + + // oop manipulations + void load_heap_oop(const Address& s, Register d, int offset = 0); + void load_heap_oop(Register s1, Register s2, Register d); + void load_heap_oop(Register s1, int simm13a, Register d); + void store_heap_oop(Register d, Register s1, Register s2); + void store_heap_oop(Register d, Register s1, int simm13a); + void store_heap_oop(Register d, const Address& a, int offset = 0); + + void encode_heap_oop(Register src, Register dst); + void encode_heap_oop(Register r) { + encode_heap_oop(r, r); + } + void decode_heap_oop(Register src, Register dst); + void decode_heap_oop(Register r) { + decode_heap_oop(r, r); + } + void encode_heap_oop_not_null(Register r); + void decode_heap_oop_not_null(Register r); + void encode_heap_oop_not_null(Register src, Register dst); + void decode_heap_oop_not_null(Register src, Register dst); + // Support for managing the JavaThread pointer (i.e.; the reference to // thread-local information). void get_thread(); // load G2_thread @@ -2050,6 +2076,9 @@ class MacroAssembler: public Assembler { void push_CPU_state(); void pop_CPU_state(); + // if heap base register is used - reinit it with the correct value + void reinit_heapbase(); + // Debugging void _verify_oop(Register reg, const char * msg, const char * file, int line); void _verify_oop_addr(Address addr, const char * msg, const char * file, int line); diff --git a/hotspot/src/cpu/sparc/vm/bytecodeInterpreter_sparc.hpp b/hotspot/src/cpu/sparc/vm/bytecodeInterpreter_sparc.hpp index 3cf99c6d4ec..dafab4bdcfd 100644 --- a/hotspot/src/cpu/sparc/vm/bytecodeInterpreter_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/bytecodeInterpreter_sparc.hpp @@ -78,7 +78,7 @@ public: #define LOCALS_SLOT(offset) ((intptr_t*)&locals[-(offset)]) #define LOCALS_ADDR(offset) ((address)locals[-(offset)]) -#define LOCALS_INT(offset) ((jint)(locals[-(offset)])) +#define LOCALS_INT(offset) (*((jint*)&locals[-(offset)])) #define LOCALS_FLOAT(offset) (*((jfloat*)&locals[-(offset)])) #define LOCALS_OBJECT(offset) ((oop)locals[-(offset)]) #define LOCALS_DOUBLE(offset) (((VMJavaVal64*)&locals[-((offset) + 1)])->d) diff --git a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp index 3e07437ce4f..523b0042a21 100644 --- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp @@ -236,7 +236,7 @@ void C1_MacroAssembler::initialize_object( Register t1, // temp register Register t2 // temp register ) { - const int hdr_size_in_bytes = oopDesc::header_size_in_bytes(); + const int hdr_size_in_bytes = instanceOopDesc::base_offset_in_bytes(); initialize_header(obj, klass, noreg, t1, t2); diff --git a/hotspot/src/cpu/sparc/vm/copy_sparc.hpp b/hotspot/src/cpu/sparc/vm/copy_sparc.hpp index 4b8d122a799..fc180cb43d3 100644 --- a/hotspot/src/cpu/sparc/vm/copy_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/copy_sparc.hpp @@ -137,24 +137,20 @@ static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) } static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) { -#if 0 - if (HeapWordsPerLong == 1 || - (HeapWordsPerLong == 2 && - mask_bits((uintptr_t)tohw, right_n_bits(LogBytesPerLong)) == 0 && - ((count & 1) ? false : count >>= 1))) { - julong* to = (julong*)tohw; - julong v = ((julong)value << 32) | value; - while (count-- > 0) { - *to++ = v; - } - } else { -#endif - juint* to = (juint*)tohw; - count *= HeapWordSize / BytesPerInt; - while (count-- > 0) { - *to++ = value; - } - // } +#ifdef _LP64 + guarantee(mask_bits((uintptr_t)tohw, right_n_bits(LogBytesPerLong)) == 0, + "unaligned fill words"); + julong* to = (julong*)tohw; + julong v = ((julong)value << 32) | value; + while (count-- > 0) { + *to++ = v; + } +#else // _LP64 + juint* to = (juint*)tohw; + while (count-- > 0) { + *to++ = value; + } +#endif // _LP64 } static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value) { diff --git a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp index b94b82f59a3..8bd53e47a51 100644 --- a/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/cppInterpreter_sparc.cpp @@ -159,7 +159,7 @@ address CppInterpreterGenerator::generate_tosca_to_stack_converter(BasicType typ break; case T_LONG : #ifndef _LP64 -#if !defined(_LP64) && defined(COMPILER2) +#if defined(COMPILER2) // All return values are where we want them, except for Longs. C2 returns // longs in G1 in the 32-bit build whereas the interpreter wants them in O0/O1. // Since the interpreter will return longs in G1 and O0/O1 in the 32bit @@ -173,10 +173,9 @@ address CppInterpreterGenerator::generate_tosca_to_stack_converter(BasicType typ // native result is in O0, O1 __ st(O1, L1_scratch, 0); // Low order __ st(O0, L1_scratch, -wordSize); // High order -#endif /* !_LP64 && COMPILER2 */ +#endif /* COMPILER2 */ #else - __ stx(O0, L1_scratch, 0); -__ breakpoint_trap(); + __ stx(O0, L1_scratch, -wordSize); #endif __ sub(L1_scratch, 2*wordSize, L1_scratch); break; @@ -237,7 +236,6 @@ address CppInterpreterGenerator::generate_stack_to_stack_converter(BasicType typ case T_VOID: break; break; case T_FLOAT : - __ breakpoint_trap(Assembler::zero); case T_BOOLEAN: case T_CHAR : case T_BYTE : @@ -255,11 +253,7 @@ address CppInterpreterGenerator::generate_stack_to_stack_converter(BasicType typ // except we allocated one extra word for this intepretState so we won't overwrite it // when we return a two word result. #ifdef _LP64 -__ breakpoint_trap(); - // Hmm now that longs are in one entry should "_ptr" really be "x"? __ ld_ptr(O0, 0, O2); - __ ld_ptr(O0, wordSize, O3); - __ st_ptr(O3, O1, 0); __ st_ptr(O2, O1, -wordSize); #else __ ld(O0, 0, O2); @@ -319,10 +313,7 @@ address CppInterpreterGenerator::generate_stack_to_native_abi_converter(BasicTyp // except we allocated one extra word for this intepretState so we won't overwrite it // when we return a two word result. #ifdef _LP64 -__ breakpoint_trap(); - // Hmm now that longs are in one entry should "_ptr" really be "x"? __ ld_ptr(O0, 0, O0->after_save()); - __ ld_ptr(O0, wordSize, O1->after_save()); #else __ ld(O0, wordSize, O1->after_save()); __ ld(O0, 0, O0->after_save()); @@ -1373,7 +1364,7 @@ void CppInterpreterGenerator::generate_more_monitors() { __ delayed()->ld_ptr(L1_scratch, entry_size, L3_scratch); // now zero the slot so we can find it. - __ st(G0, L4_scratch, BasicObjectLock::obj_offset_in_bytes()); + __ st_ptr(G0, L4_scratch, BasicObjectLock::obj_offset_in_bytes()); } @@ -1713,7 +1704,7 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { __ lduh(L4_scratch, in_bytes(methodOopDesc::size_of_parameters_offset()), L2_scratch); // get parameter size __ sll(L2_scratch, LogBytesPerWord, L2_scratch ); // parameter size in bytes __ add(L1_scratch, L2_scratch, L1_scratch); // stack destination for result - __ ld_ptr(L4_scratch, in_bytes(methodOopDesc::result_index_offset()), L3_scratch); // called method result type index + __ ld(L4_scratch, in_bytes(methodOopDesc::result_index_offset()), L3_scratch); // called method result type index // tosca is really just native abi __ set((intptr_t)CppInterpreter::_tosca_to_stack, L4_scratch); @@ -1757,7 +1748,7 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { __ ld_ptr(STATE(_prev_link), L1_scratch); __ ld_ptr(STATE(_method), L2_scratch); // get method just executed - __ ld_ptr(L2_scratch, in_bytes(methodOopDesc::result_index_offset()), L2_scratch); + __ ld(L2_scratch, in_bytes(methodOopDesc::result_index_offset()), L2_scratch); __ tst(L1_scratch); __ brx(Assembler::zero, false, Assembler::pt, return_to_initial_caller); __ delayed()->sll(L2_scratch, LogBytesPerWord, L2_scratch); @@ -1923,10 +1914,10 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { // compute the unused java stack size __ sub(Gargs, L1_scratch, L2_scratch); // compute unused space - // Round down the unused space to that stack is always aligned - // by making the unused space a multiple of the size of a long. + // Round down the unused space to that stack is always 16-byte aligned + // by making the unused space a multiple of the size of two longs. - __ and3(L2_scratch, -BytesPerLong, L2_scratch); + __ and3(L2_scratch, -2*BytesPerLong, L2_scratch); // Now trim the stack __ add(SP, L2_scratch, SP); @@ -2176,6 +2167,9 @@ int AbstractInterpreter::layout_activation(methodOop method, // MUCHO HACK intptr_t* frame_bottom = interpreter_frame->sp() - (full_frame_words - frame_words); + // 'interpreter_frame->sp()' is unbiased while 'frame_bottom' must be a biased value in 64bit mode. + assert(((intptr_t)frame_bottom & 0xf) == 0, "SP biased in layout_activation"); + frame_bottom = (intptr_t*)((intptr_t)frame_bottom - STACK_BIAS); /* Now fillin the interpreterState object */ diff --git a/hotspot/src/cpu/sparc/vm/disassembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/disassembler_sparc.cpp deleted file mode 100644 index fc7cc059798..00000000000 --- a/hotspot/src/cpu/sparc/vm/disassembler_sparc.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - */ - -# include "incls/_precompiled.incl" -# include "incls/_disassembler_sparc.cpp.incl" - -#ifndef PRODUCT - -#define SPARC_VERSION (VM_Version::v9_instructions_work()? \ - (VM_Version::v8_instructions_work()? "" : "9") : "8") - -// This routine is in the shared library: -typedef unsigned char* print_insn_sparc_t(unsigned char* start, DisassemblerEnv* env, - const char* sparc_version); - -void* Disassembler::_library = NULL; -dll_func Disassembler::_print_insn_sparc = NULL; - -bool Disassembler::load_library() { - if (_library == NULL) { - char buf[1024]; - char ebuf[1024]; - sprintf(buf, "disassembler%s", os::dll_file_extension()); - _library = hpi::dll_load(buf, ebuf, sizeof ebuf); - if (_library != NULL) { - tty->print_cr("Loaded disassembler"); - _print_insn_sparc = CAST_TO_FN_PTR(dll_func, hpi::dll_lookup(_library, "print_insn_sparc")); - } - } - return (_library != NULL) && (_print_insn_sparc != NULL); -} - - -class sparc_env : public DisassemblerEnv { - private: - nmethod* code; - outputStream* output; - const char* version; - - static void print_address(address value, outputStream* st); - - public: - sparc_env(nmethod* rcode, outputStream* routput) { - code = rcode; - output = routput; - version = SPARC_VERSION; - } - const char* sparc_version() { return version; } - void print_label(intptr_t value); - void print_raw(char* str) { output->print_raw(str); } - void print(char* format, ...); - char* string_for_offset(intptr_t value); - char* string_for_constant(unsigned char* pc, intptr_t value, int is_decimal); -}; - - -void sparc_env::print_address(address adr, outputStream* st) { - if (!Universe::is_fully_initialized()) { - st->print(INTPTR_FORMAT, (intptr_t)adr); - return; - } - if (StubRoutines::contains(adr)) { - StubCodeDesc *desc = StubCodeDesc::desc_for(adr); - if (desc == NULL) - desc = StubCodeDesc::desc_for(adr + frame::pc_return_offset); - if (desc == NULL) - st->print("Unknown stub at " INTPTR_FORMAT, adr); - else { - st->print("Stub::%s", desc->name()); - if (desc->begin() != adr) - st->print("%+d 0x%p",adr - desc->begin(), adr); - else if (WizardMode) st->print(" " INTPTR_FORMAT, adr); - } - } else { - BarrierSet* bs = Universe::heap()->barrier_set(); - if (bs->kind() == BarrierSet::CardTableModRef && - adr == (address)((CardTableModRefBS*)(bs))->byte_map_base) { - st->print("word_map_base"); - if (WizardMode) st->print(" " INTPTR_FORMAT, (intptr_t)adr); - } else { - st->print(INTPTR_FORMAT, (intptr_t)adr); - } - } -} - - -// called by the disassembler to print out jump addresses -void sparc_env::print_label(intptr_t value) { - print_address((address) value, output); -} - -void sparc_env::print(char* format, ...) { - va_list ap; - va_start(ap, format); - output->vprint(format, ap); - va_end(ap); -} - -char* sparc_env::string_for_offset(intptr_t value) { - stringStream st; - print_address((address) value, &st); - return st.as_string(); -} - -char* sparc_env::string_for_constant(unsigned char* pc, intptr_t value, int is_decimal) { - stringStream st; - oop obj; - if (code && (obj = code->embeddedOop_at(pc)) != NULL) { - obj->print_value_on(&st); - } else - { - print_address((address) value, &st); - } - return st.as_string(); -} - - -address Disassembler::decode_instruction(address start, DisassemblerEnv* env) { - const char* version = ((sparc_env*)env)->sparc_version(); - return ((print_insn_sparc_t*) _print_insn_sparc)(start, env, version); -} - - -const int show_bytes = false; // for disassembler debugging - - -void Disassembler::decode(CodeBlob* cb, outputStream* st) { - st = st ? st : tty; - st->print_cr("Decoding CodeBlob " INTPTR_FORMAT, cb); - decode(cb->instructions_begin(), cb->instructions_end(), st); -} - - -void Disassembler::decode(u_char* begin, u_char* end, outputStream* st) { - assert ((((intptr_t)begin | (intptr_t)end) % sizeof(int) == 0), "misaligned insn addr"); - st = st ? st : tty; - if (!load_library()) { - st->print_cr("Could not load disassembler"); - return; - } - sparc_env env(NULL, st); - unsigned char* p = (unsigned char*) begin; - CodeBlob* cb = CodeCache::find_blob_unsafe(begin); - while (p < (unsigned char*) end && p) { - if (cb != NULL) { - cb->print_block_comment(st, (intptr_t)(p - cb->instructions_begin())); - } - - unsigned char* p0 = p; - st->print(INTPTR_FORMAT ": ", p); - p = decode_instruction(p, &env); - if (show_bytes && p) { - st->print("\t\t\t"); - while (p0 < p) { st->print("%08lx ", *(int*)p0); p0 += sizeof(int); } - } - st->cr(); - } -} - - -void Disassembler::decode(nmethod* nm, outputStream* st) { - st = st ? st : tty; - - st->print_cr("Decoding compiled method " INTPTR_FORMAT ":", nm); - st->print("Code:"); - st->cr(); - - if (!load_library()) { - st->print_cr("Could not load disassembler"); - return; - } - sparc_env env(nm, st); - unsigned char* p = nm->instructions_begin(); - unsigned char* end = nm->instructions_end(); - assert ((((intptr_t)p | (intptr_t)end) % sizeof(int) == 0), "misaligned insn addr"); - - unsigned char *p1 = p; - int total_bucket_count = 0; - while (p1 < end && p1) { - unsigned char *p0 = p1; - ++p1; - address bucket_pc = FlatProfiler::bucket_start_for(p1); - if (bucket_pc != NULL && bucket_pc > p0 && bucket_pc <= p1) - total_bucket_count += FlatProfiler::bucket_count_for(p0); - } - - while (p < end && p) { - if (p == nm->entry_point()) st->print_cr("[Entry Point]"); - if (p == nm->verified_entry_point()) st->print_cr("[Verified Entry Point]"); - if (p == nm->exception_begin()) st->print_cr("[Exception Handler]"); - if (p == nm->stub_begin()) st->print_cr("[Stub Code]"); - if (p == nm->consts_begin()) st->print_cr("[Constants]"); - nm->print_block_comment(st, (intptr_t)(p - nm->instructions_begin())); - unsigned char* p0 = p; - st->print(" " INTPTR_FORMAT ": ", p); - p = decode_instruction(p, &env); - nm->print_code_comment_on(st, 40, p0, p); - st->cr(); - // Output pc bucket ticks if we have any - address bucket_pc = FlatProfiler::bucket_start_for(p); - if (bucket_pc != NULL && bucket_pc > p0 && bucket_pc <= p) { - int bucket_count = FlatProfiler::bucket_count_for(p0); - tty->print_cr("%3.1f%% [%d]", bucket_count*100.0/total_bucket_count, bucket_count); - tty->cr(); - } - } -} - -#endif // PRODUCT diff --git a/hotspot/src/cpu/sparc/vm/disassembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/disassembler_sparc.hpp index 827488b8e20..343f96d968d 100644 --- a/hotspot/src/cpu/sparc/vm/disassembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/disassembler_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-1999 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,30 +22,11 @@ * */ -// The disassembler prints out sparc code annotated -// with Java specific information. + static int pd_instruction_alignment() { + return sizeof(int); + } -class Disassembler { -#ifndef PRODUCT - private: - // points to the library. - static void* _library; - // points to the print_insn_sparc function. - static dll_func _print_insn_sparc; - // tries to load library and return whether it succedded. - static bool load_library(); - // decodes one instruction and return the start of the next instruction. - static address decode_instruction(address start, DisassemblerEnv* env); -#endif - public: - static void decode(CodeBlob *cb, outputStream* st = NULL) PRODUCT_RETURN; - static void decode(nmethod* nm, outputStream* st = NULL) PRODUCT_RETURN; - static void decode(u_char* begin, u_char* end, outputStream* st = NULL) PRODUCT_RETURN; -}; - -//Reconciliation History -// 1.9 98/04/29 10:45:51 disassembler_i486.hpp -// 1.10 98/05/11 16:47:20 disassembler_i486.hpp -// 1.12 99/06/22 16:37:37 disassembler_i486.hpp -// 1.13 99/08/06 10:09:04 disassembler_i486.hpp -//End + static const char* pd_cpu_opts() { + return (VM_Version::v9_instructions_work()? + (VM_Version::v8_instructions_work()? "" : "v9only") : "v8only"); + } diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp index e51cd9c70df..1e8077d55d9 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp @@ -157,22 +157,158 @@ void RegisterMap::shift_individual_registers() { check_location_valid(); } - bool frame::safe_for_sender(JavaThread *thread) { - address sp = (address)_sp; - if (sp != NULL && - (sp <= thread->stack_base() && sp >= thread->stack_base() - thread->stack_size())) { - // Unfortunately we can only check frame complete for runtime stubs and nmethod - // other generic buffer blobs are more problematic so we just assume they are - // ok. adapter blobs never have a frame complete and are never ok. - if (_cb != NULL && !_cb->is_frame_complete_at(_pc)) { - if (_cb->is_nmethod() || _cb->is_adapter_blob() || _cb->is_runtime_stub()) { - return false; - } - } - return true; + + address _SP = (address) sp(); + address _FP = (address) fp(); + address _UNEXTENDED_SP = (address) unextended_sp(); + // sp must be within the stack + bool sp_safe = (_SP <= thread->stack_base()) && + (_SP >= thread->stack_base() - thread->stack_size()); + + if (!sp_safe) { + return false; } - return false; + + // unextended sp must be within the stack and above or equal sp + bool unextended_sp_safe = (_UNEXTENDED_SP <= thread->stack_base()) && + (_UNEXTENDED_SP >= _SP); + + if (!unextended_sp_safe) return false; + + // an fp must be within the stack and above (but not equal) sp + bool fp_safe = (_FP <= thread->stack_base()) && + (_FP > _SP); + + // We know sp/unextended_sp are safe only fp is questionable here + + // If the current frame is known to the code cache then we can attempt to + // to construct the sender and do some validation of it. This goes a long way + // toward eliminating issues when we get in frame construction code + + if (_cb != NULL ) { + + // First check if frame is complete and tester is reliable + // Unfortunately we can only check frame complete for runtime stubs and nmethod + // other generic buffer blobs are more problematic so we just assume they are + // ok. adapter blobs never have a frame complete and are never ok. + + if (!_cb->is_frame_complete_at(_pc)) { + if (_cb->is_nmethod() || _cb->is_adapter_blob() || _cb->is_runtime_stub()) { + return false; + } + } + + // Entry frame checks + if (is_entry_frame()) { + // an entry frame must have a valid fp. + + if (!fp_safe) { + return false; + } + + // Validate the JavaCallWrapper an entry frame must have + + address jcw = (address)entry_frame_call_wrapper(); + + bool jcw_safe = (jcw <= thread->stack_base()) && ( jcw > _FP); + + return jcw_safe; + + } + + intptr_t* younger_sp = sp(); + intptr_t* _SENDER_SP = sender_sp(); // sender is actually just _FP + bool adjusted_stack = is_interpreted_frame(); + + address sender_pc = (address)younger_sp[I7->sp_offset_in_saved_window()] + pc_return_offset; + + + // We must always be able to find a recognizable pc + CodeBlob* sender_blob = CodeCache::find_blob_unsafe(sender_pc); + if (sender_pc == NULL || sender_blob == NULL) { + return false; + } + + // It should be safe to construct the sender though it might not be valid + + frame sender(_SENDER_SP, younger_sp, adjusted_stack); + + // Do we have a valid fp? + address sender_fp = (address) sender.fp(); + + // an fp must be within the stack and above (but not equal) current frame's _FP + + bool sender_fp_safe = (sender_fp <= thread->stack_base()) && + (sender_fp > _FP); + + if (!sender_fp_safe) { + return false; + } + + + // If the potential sender is the interpreter then we can do some more checking + if (Interpreter::contains(sender_pc)) { + return sender.is_interpreted_frame_valid(thread); + } + + // Could just be some random pointer within the codeBlob + if (!sender.cb()->instructions_contains(sender_pc)) return false; + + // We should never be able to see an adapter if the current frame is something from code cache + + if ( sender_blob->is_adapter_blob()) { + return false; + } + + if( sender.is_entry_frame()) { + // Validate the JavaCallWrapper an entry frame must have + + address jcw = (address)sender.entry_frame_call_wrapper(); + + bool jcw_safe = (jcw <= thread->stack_base()) && ( jcw > sender_fp); + + return jcw_safe; + } + + // If the frame size is 0 something is bad because every nmethod has a non-zero frame size + // because you must allocate window space + + if (sender_blob->frame_size() == 0) { + assert(!sender_blob->is_nmethod(), "should count return address at least"); + return false; + } + + // The sender should positively be an nmethod or call_stub. On sparc we might in fact see something else. + // The cause of this is because at a save instruction the O7 we get is a leftover from an earlier + // window use. So if a runtime stub creates two frames (common in fastdebug/jvmg) then we see the + // stale pc. So if the sender blob is not something we'd expect we have little choice but to declare + // the stack unwalkable. pd_get_top_frame_for_signal_handler tries to recover from this by unwinding + // that initial frame and retrying. + + if (!sender_blob->is_nmethod()) { + return false; + } + + // Could put some more validation for the potential non-interpreted sender + // frame we'd create by calling sender if I could think of any. Wait for next crash in forte... + + // One idea is seeing if the sender_pc we have is one that we'd expect to call to current cb + + // We've validated the potential sender that would be created + + return true; + + } + + // Must be native-compiled frame. Since sender will try and use fp to find + // linkages it must be safe + + if (!fp_safe) return false; + + // could try and do some more potential verification of native frame if we could think of some... + + return true; } // constructors @@ -450,7 +586,7 @@ void frame::pd_gc_epilog() { } -bool frame::is_interpreted_frame_valid() const { +bool frame::is_interpreted_frame_valid(JavaThread* thread) const { #ifdef CC_INTERP // Is there anything to do? #else @@ -462,6 +598,7 @@ bool frame::is_interpreted_frame_valid() const { if (sp() == 0 || (intptr_t(sp()) & (2*wordSize-1)) != 0) { return false; } + const intptr_t interpreter_frame_initial_sp_offset = interpreter_frame_vm_local_words; if (fp() + interpreter_frame_initial_sp_offset < sp()) { return false; @@ -471,9 +608,43 @@ bool frame::is_interpreted_frame_valid() const { if (fp() <= sp()) { // this attempts to deal with unsigned comparison above return false; } - if (fp() - sp() > 4096) { // stack frames shouldn't be large. + // do some validation of frame elements + + // first the method + + methodOop m = *interpreter_frame_method_addr(); + + // validate the method we'd find in this potential sender + if (!Universe::heap()->is_valid_method(m)) return false; + + // stack frames shouldn't be much larger than max_stack elements + + if (fp() - sp() > 1024 + m->max_stack()*Interpreter::stackElementSize()) { return false; } + + // validate bci/bcx + + intptr_t bcx = interpreter_frame_bcx(); + if (m->validate_bci_from_bcx(bcx) < 0) { + return false; + } + + // validate constantPoolCacheOop + + constantPoolCacheOop cp = *interpreter_frame_cache_addr(); + + if (cp == NULL || + !Space::is_aligned(cp) || + !Universe::heap()->is_permanent((void*)cp)) return false; + + // validate locals + + address locals = (address) *interpreter_frame_locals_addr(); + + if (locals > thread->stack_base() || locals < (address) fp()) return false; + + // We'd have to be pretty unlucky to be mislead at this point #endif /* CC_INTERP */ return true; } diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp index 5a868c82e03..aff31ce6c2f 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp @@ -859,7 +859,7 @@ void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, R // Generate a subtype check: branch to ok_is_subtype if sub_klass is -// a subtype of super_klass. Blows registers Rsub_klass, tmp1, tmp2. +// a subtype of super_klass. Blows registers Rsuper_klass, Rsub_klass, tmp1, tmp2. void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, Register Rsuper_klass, Register Rtmp1, @@ -891,6 +891,9 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, // Now do a linear scan of the secondary super-klass chain. delayed()->ld_ptr( Rsub_klass, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes(), Rtmp2 ); + // compress superclass + if (UseCompressedOops) encode_heap_oop(Rsuper_klass); + // Rtmp2 holds the objArrayOop of secondary supers. ld( Rtmp2, arrayOopDesc::length_offset_in_bytes(), Rtmp1 );// Load the array length // Check for empty secondary super list @@ -900,20 +903,28 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, bind( loop ); br( Assembler::equal, false, Assembler::pn, not_subtype ); delayed()->nop(); - // load next super to check - ld_ptr( Rtmp2, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rtmp3 ); - // Bump array pointer forward one oop - add( Rtmp2, wordSize, Rtmp2 ); + // load next super to check + if (UseCompressedOops) { + ld( Rtmp2, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rtmp3); + // Bump array pointer forward one oop + add( Rtmp2, 4, Rtmp2 ); + } else { + ld_ptr( Rtmp2, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rtmp3); + // Bump array pointer forward one oop + add( Rtmp2, wordSize, Rtmp2); + } // Look for Rsuper_klass on Rsub_klass's secondary super-class-overflow list cmp( Rtmp3, Rsuper_klass ); // A miss means we are NOT a subtype and need to keep looping brx( Assembler::notEqual, false, Assembler::pt, loop ); delayed()->deccc( Rtmp1 ); // dec trip counter in delay slot // Falling out the bottom means we found a hit; we ARE a subtype + if (UseCompressedOops) decode_heap_oop(Rsuper_klass); br( Assembler::always, false, Assembler::pt, ok_is_subtype ); // Update the cache - delayed()->st_ptr( Rsuper_klass, Rsub_klass, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() ); + delayed()->st_ptr( Rsuper_klass, Rsub_klass, + sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() ); bind(not_subtype); profile_typecheck_failed(Rtmp1); diff --git a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp index 331675102a8..3deee97da75 100644 --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp @@ -26,6 +26,10 @@ # include "incls/_nativeInst_sparc.cpp.incl" +bool NativeInstruction::is_dtrace_trap() { + return !is_nop(); +} + void NativeInstruction::set_data64_sethi(address instaddr, intptr_t x) { ResourceMark rm; CodeBuffer buf(instaddr, 10 * BytesPerInstWord ); diff --git a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp index ff0913515c7..1e7263b41ef 100644 --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp @@ -43,6 +43,7 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC { nop_instruction_size = 4 }; + bool is_dtrace_trap(); bool is_nop() { return long_at(0) == nop_instruction(); } bool is_call() { return is_op(long_at(0), Assembler::call_op); } bool is_sethi() { return (is_op2(long_at(0), Assembler::sethi_op2) diff --git a/hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp b/hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp index 0a8ab2e5cd8..4001805226b 100644 --- a/hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp @@ -131,6 +131,7 @@ REGISTER_DEFINITION(FloatRegister, Ftos_d2); REGISTER_DEFINITION(Register, G2_thread); +REGISTER_DEFINITION(Register, G6_heapbase); REGISTER_DEFINITION(Register, G5_method); REGISTER_DEFINITION(Register, G5_megamorphic_method); REGISTER_DEFINITION(Register, G5_inline_cache_reg); diff --git a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp index f58d87820e2..7f5c4f81407 100644 --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp @@ -160,18 +160,24 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ map->set_callee_saved(VMRegImpl::stack2reg((o5_offset + 4)>>2), O5->as_VMReg()); #endif /* _LP64 */ + +#ifdef _LP64 + int debug_offset = 0; +#else + int debug_offset = 4; +#endif // Save the G's __ stx(G1, SP, g1_offset+STACK_BIAS); - map->set_callee_saved(VMRegImpl::stack2reg((g1_offset + 4)>>2), G1->as_VMReg()); + map->set_callee_saved(VMRegImpl::stack2reg((g1_offset + debug_offset)>>2), G1->as_VMReg()); __ stx(G3, SP, g3_offset+STACK_BIAS); - map->set_callee_saved(VMRegImpl::stack2reg((g3_offset + 4)>>2), G3->as_VMReg()); + map->set_callee_saved(VMRegImpl::stack2reg((g3_offset + debug_offset)>>2), G3->as_VMReg()); __ stx(G4, SP, g4_offset+STACK_BIAS); - map->set_callee_saved(VMRegImpl::stack2reg((g4_offset + 4)>>2), G4->as_VMReg()); + map->set_callee_saved(VMRegImpl::stack2reg((g4_offset + debug_offset)>>2), G4->as_VMReg()); __ stx(G5, SP, g5_offset+STACK_BIAS); - map->set_callee_saved(VMRegImpl::stack2reg((g5_offset + 4)>>2), G5->as_VMReg()); + map->set_callee_saved(VMRegImpl::stack2reg((g5_offset + debug_offset)>>2), G5->as_VMReg()); // This is really a waste but we'll keep things as they were for now if (true) { @@ -182,11 +188,11 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ map->set_callee_saved(VMRegImpl::stack2reg((o3_offset)>>2), O3->as_VMReg()->next()); map->set_callee_saved(VMRegImpl::stack2reg((o4_offset)>>2), O4->as_VMReg()->next()); map->set_callee_saved(VMRegImpl::stack2reg((o5_offset)>>2), O5->as_VMReg()->next()); -#endif /* _LP64 */ map->set_callee_saved(VMRegImpl::stack2reg((g1_offset)>>2), G1->as_VMReg()->next()); map->set_callee_saved(VMRegImpl::stack2reg((g3_offset)>>2), G3->as_VMReg()->next()); map->set_callee_saved(VMRegImpl::stack2reg((g4_offset)>>2), G4->as_VMReg()->next()); map->set_callee_saved(VMRegImpl::stack2reg((g5_offset)>>2), G5->as_VMReg()->next()); +#endif /* _LP64 */ } @@ -1217,7 +1223,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm __ verify_oop(O0); __ verify_oop(G5_method); - __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_scratch); + __ load_klass(O0, G3_scratch); __ verify_oop(G3_scratch); #if !defined(_LP64) && defined(COMPILER2) @@ -1631,7 +1637,7 @@ static void long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { } } else if (dst.is_single_phys_reg()) { if (src.is_adjacent_aligned_on_stack(2)) { - __ ldd(FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_Register()); + __ ld_long(FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_Register()); } else { // dst is a single reg. // Remember lo is low address not msb for stack slots @@ -1820,7 +1826,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm, const Register temp_reg = G3_scratch; Address ic_miss(temp_reg, SharedRuntime::get_ic_miss_stub()); __ verify_oop(O0); - __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), temp_reg); + __ load_klass(O0, temp_reg); __ cmp(temp_reg, G5_inline_cache_reg); __ brx(Assembler::equal, true, Assembler::pt, L); __ delayed()->nop(); @@ -2495,6 +2501,551 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm, } +#ifdef HAVE_DTRACE_H +// --------------------------------------------------------------------------- +// Generate a dtrace nmethod for a given signature. The method takes arguments +// in the Java compiled code convention, marshals them to the native +// abi and then leaves nops at the position you would expect to call a native +// function. When the probe is enabled the nops are replaced with a trap +// instruction that dtrace inserts and the trace will cause a notification +// to dtrace. +// +// The probes are only able to take primitive types and java/lang/String as +// arguments. No other java types are allowed. Strings are converted to utf8 +// strings so that from dtrace point of view java strings are converted to C +// strings. There is an arbitrary fixed limit on the total space that a method +// can use for converting the strings. (256 chars per string in the signature). +// So any java string larger then this is truncated. + +static int fp_offset[ConcreteRegisterImpl::number_of_registers] = { 0 }; +static bool offsets_initialized = false; + +static VMRegPair reg64_to_VMRegPair(Register r) { + VMRegPair ret; + if (wordSize == 8) { + ret.set2(r->as_VMReg()); + } else { + ret.set_pair(r->successor()->as_VMReg(), r->as_VMReg()); + } + return ret; +} + + +nmethod *SharedRuntime::generate_dtrace_nmethod( + MacroAssembler *masm, methodHandle method) { + + + // generate_dtrace_nmethod is guarded by a mutex so we are sure to + // be single threaded in this method. + assert(AdapterHandlerLibrary_lock->owned_by_self(), "must be"); + + // Fill in the signature array, for the calling-convention call. + int total_args_passed = method->size_of_parameters(); + + BasicType* in_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed); + VMRegPair *in_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed); + + // The signature we are going to use for the trap that dtrace will see + // java/lang/String is converted. We drop "this" and any other object + // is converted to NULL. (A one-slot java/lang/Long object reference + // is converted to a two-slot long, which is why we double the allocation). + BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed * 2); + VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed * 2); + + int i=0; + int total_strings = 0; + int first_arg_to_pass = 0; + int total_c_args = 0; + int box_offset = java_lang_boxing_object::value_offset_in_bytes(); + + // Skip the receiver as dtrace doesn't want to see it + if( !method->is_static() ) { + in_sig_bt[i++] = T_OBJECT; + first_arg_to_pass = 1; + } + + SignatureStream ss(method->signature()); + for ( ; !ss.at_return_type(); ss.next()) { + BasicType bt = ss.type(); + in_sig_bt[i++] = bt; // Collect remaining bits of signature + out_sig_bt[total_c_args++] = bt; + if( bt == T_OBJECT) { + symbolOop s = ss.as_symbol_or_null(); + if (s == vmSymbols::java_lang_String()) { + total_strings++; + out_sig_bt[total_c_args-1] = T_ADDRESS; + } else if (s == vmSymbols::java_lang_Boolean() || + s == vmSymbols::java_lang_Byte()) { + out_sig_bt[total_c_args-1] = T_BYTE; + } else if (s == vmSymbols::java_lang_Character() || + s == vmSymbols::java_lang_Short()) { + out_sig_bt[total_c_args-1] = T_SHORT; + } else if (s == vmSymbols::java_lang_Integer() || + s == vmSymbols::java_lang_Float()) { + out_sig_bt[total_c_args-1] = T_INT; + } else if (s == vmSymbols::java_lang_Long() || + s == vmSymbols::java_lang_Double()) { + out_sig_bt[total_c_args-1] = T_LONG; + out_sig_bt[total_c_args++] = T_VOID; + } + } else if ( bt == T_LONG || bt == T_DOUBLE ) { + in_sig_bt[i++] = T_VOID; // Longs & doubles take 2 Java slots + // We convert double to long + out_sig_bt[total_c_args-1] = T_LONG; + out_sig_bt[total_c_args++] = T_VOID; + } else if ( bt == T_FLOAT) { + // We convert float to int + out_sig_bt[total_c_args-1] = T_INT; + } + } + + assert(i==total_args_passed, "validly parsed signature"); + + // Now get the compiled-Java layout as input arguments + int comp_args_on_stack; + comp_args_on_stack = SharedRuntime::java_calling_convention( + in_sig_bt, in_regs, total_args_passed, false); + + // We have received a description of where all the java arg are located + // on entry to the wrapper. We need to convert these args to where + // the a native (non-jni) function would expect them. To figure out + // where they go we convert the java signature to a C signature and remove + // T_VOID for any long/double we might have received. + + + // Now figure out where the args must be stored and how much stack space + // they require (neglecting out_preserve_stack_slots but space for storing + // the 1st six register arguments). It's weird see int_stk_helper. + // + int out_arg_slots; + out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); + + // Calculate the total number of stack slots we will need. + + // First count the abi requirement plus all of the outgoing args + int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots; + + // Plus a temp for possible converion of float/double/long register args + + int conversion_temp = stack_slots; + stack_slots += 2; + + + // Now space for the string(s) we must convert + + int string_locs = stack_slots; + stack_slots += total_strings * + (max_dtrace_string_size / VMRegImpl::stack_slot_size); + + // Ok The space we have allocated will look like: + // + // + // FP-> | | + // |---------------------| + // | string[n] | + // |---------------------| <- string_locs[n] + // | string[n-1] | + // |---------------------| <- string_locs[n-1] + // | ... | + // | ... | + // |---------------------| <- string_locs[1] + // | string[0] | + // |---------------------| <- string_locs[0] + // | temp | + // |---------------------| <- conversion_temp + // | outbound memory | + // | based arguments | + // | | + // |---------------------| + // | | + // SP-> | out_preserved_slots | + // + // + + // Now compute actual number of stack words we need rounding to make + // stack properly aligned. + stack_slots = round_to(stack_slots, 4 * VMRegImpl::slots_per_word); + + int stack_size = stack_slots * VMRegImpl::stack_slot_size; + + intptr_t start = (intptr_t)__ pc(); + + // First thing make an ic check to see if we should even be here + + { + Label L; + const Register temp_reg = G3_scratch; + Address ic_miss(temp_reg, SharedRuntime::get_ic_miss_stub()); + __ verify_oop(O0); + __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), temp_reg); + __ cmp(temp_reg, G5_inline_cache_reg); + __ brx(Assembler::equal, true, Assembler::pt, L); + __ delayed()->nop(); + + __ jump_to(ic_miss, 0); + __ delayed()->nop(); + __ align(CodeEntryAlignment); + __ bind(L); + } + + int vep_offset = ((intptr_t)__ pc()) - start; + + + // The instruction at the verified entry point must be 5 bytes or longer + // because it can be patched on the fly by make_non_entrant. The stack bang + // instruction fits that requirement. + + // Generate stack overflow check before creating frame + __ generate_stack_overflow_check(stack_size); + + assert(((intptr_t)__ pc() - start - vep_offset) >= 5, + "valid size for make_non_entrant"); + + // Generate a new frame for the wrapper. + __ save(SP, -stack_size, SP); + + // Frame is now completed as far a size and linkage. + + int frame_complete = ((intptr_t)__ pc()) - start; + +#ifdef ASSERT + bool reg_destroyed[RegisterImpl::number_of_registers]; + bool freg_destroyed[FloatRegisterImpl::number_of_registers]; + for ( int r = 0 ; r < RegisterImpl::number_of_registers ; r++ ) { + reg_destroyed[r] = false; + } + for ( int f = 0 ; f < FloatRegisterImpl::number_of_registers ; f++ ) { + freg_destroyed[f] = false; + } + +#endif /* ASSERT */ + + VMRegPair zero; + zero.set2(G0->as_VMReg()); + + int c_arg, j_arg; + + Register conversion_off = noreg; + + for (j_arg = first_arg_to_pass, c_arg = 0 ; + j_arg < total_args_passed ; j_arg++, c_arg++ ) { + + VMRegPair src = in_regs[j_arg]; + VMRegPair dst = out_regs[c_arg]; + +#ifdef ASSERT + if (src.first()->is_Register()) { + assert(!reg_destroyed[src.first()->as_Register()->encoding()], "ack!"); + } else if (src.first()->is_FloatRegister()) { + assert(!freg_destroyed[src.first()->as_FloatRegister()->encoding( + FloatRegisterImpl::S)], "ack!"); + } + if (dst.first()->is_Register()) { + reg_destroyed[dst.first()->as_Register()->encoding()] = true; + } else if (dst.first()->is_FloatRegister()) { + freg_destroyed[dst.first()->as_FloatRegister()->encoding( + FloatRegisterImpl::S)] = true; + } +#endif /* ASSERT */ + + switch (in_sig_bt[j_arg]) { + case T_ARRAY: + case T_OBJECT: + { + if (out_sig_bt[c_arg] == T_BYTE || out_sig_bt[c_arg] == T_SHORT || + out_sig_bt[c_arg] == T_INT || out_sig_bt[c_arg] == T_LONG) { + // need to unbox a one-slot value + Register in_reg = L0; + Register tmp = L2; + if ( src.first()->is_reg() ) { + in_reg = src.first()->as_Register(); + } else { + assert(Assembler::is_simm13(reg2offset(src.first()) + STACK_BIAS), + "must be"); + __ ld_ptr(FP, reg2offset(src.first()) + STACK_BIAS, in_reg); + } + // If the final destination is an acceptable register + if ( dst.first()->is_reg() ) { + if ( dst.is_single_phys_reg() || out_sig_bt[c_arg] != T_LONG ) { + tmp = dst.first()->as_Register(); + } + } + + Label skipUnbox; + if ( wordSize == 4 && out_sig_bt[c_arg] == T_LONG ) { + __ mov(G0, tmp->successor()); + } + __ br_null(in_reg, true, Assembler::pn, skipUnbox); + __ delayed()->mov(G0, tmp); + + switch (out_sig_bt[c_arg]) { + case T_BYTE: + __ ldub(in_reg, box_offset, tmp); break; + case T_SHORT: + __ lduh(in_reg, box_offset, tmp); break; + case T_INT: + __ ld(in_reg, box_offset, tmp); break; + case T_LONG: + __ ld_long(in_reg, box_offset, tmp); break; + default: ShouldNotReachHere(); + } + + __ bind(skipUnbox); + // If tmp wasn't final destination copy to final destination + if (tmp == L2) { + VMRegPair tmp_as_VM = reg64_to_VMRegPair(L2); + if (out_sig_bt[c_arg] == T_LONG) { + long_move(masm, tmp_as_VM, dst); + } else { + move32_64(masm, tmp_as_VM, out_regs[c_arg]); + } + } + if (out_sig_bt[c_arg] == T_LONG) { + assert(out_sig_bt[c_arg+1] == T_VOID, "must be"); + ++c_arg; // move over the T_VOID to keep the loop indices in sync + } + } else if (out_sig_bt[c_arg] == T_ADDRESS) { + Register s = + src.first()->is_reg() ? src.first()->as_Register() : L2; + Register d = + dst.first()->is_reg() ? dst.first()->as_Register() : L2; + + // We store the oop now so that the conversion pass can reach + // while in the inner frame. This will be the only store if + // the oop is NULL. + if (s != L2) { + // src is register + if (d != L2) { + // dst is register + __ mov(s, d); + } else { + assert(Assembler::is_simm13(reg2offset(dst.first()) + + STACK_BIAS), "must be"); + __ st_ptr(s, SP, reg2offset(dst.first()) + STACK_BIAS); + } + } else { + // src not a register + assert(Assembler::is_simm13(reg2offset(src.first()) + + STACK_BIAS), "must be"); + __ ld_ptr(FP, reg2offset(src.first()) + STACK_BIAS, d); + if (d == L2) { + assert(Assembler::is_simm13(reg2offset(dst.first()) + + STACK_BIAS), "must be"); + __ st_ptr(d, SP, reg2offset(dst.first()) + STACK_BIAS); + } + } + } else if (out_sig_bt[c_arg] != T_VOID) { + // Convert the arg to NULL + if (dst.first()->is_reg()) { + __ mov(G0, dst.first()->as_Register()); + } else { + assert(Assembler::is_simm13(reg2offset(dst.first()) + + STACK_BIAS), "must be"); + __ st_ptr(G0, SP, reg2offset(dst.first()) + STACK_BIAS); + } + } + } + break; + case T_VOID: + break; + + case T_FLOAT: + if (src.first()->is_stack()) { + // Stack to stack/reg is simple + move32_64(masm, src, dst); + } else { + if (dst.first()->is_reg()) { + // freg -> reg + int off = + STACK_BIAS + conversion_temp * VMRegImpl::stack_slot_size; + Register d = dst.first()->as_Register(); + if (Assembler::is_simm13(off)) { + __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(), + SP, off); + __ ld(SP, off, d); + } else { + if (conversion_off == noreg) { + __ set(off, L6); + conversion_off = L6; + } + __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(), + SP, conversion_off); + __ ld(SP, conversion_off , d); + } + } else { + // freg -> mem + int off = STACK_BIAS + reg2offset(dst.first()); + if (Assembler::is_simm13(off)) { + __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(), + SP, off); + } else { + if (conversion_off == noreg) { + __ set(off, L6); + conversion_off = L6; + } + __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(), + SP, conversion_off); + } + } + } + break; + + case T_DOUBLE: + assert( j_arg + 1 < total_args_passed && + in_sig_bt[j_arg + 1] == T_VOID && + out_sig_bt[c_arg+1] == T_VOID, "bad arg list"); + if (src.first()->is_stack()) { + // Stack to stack/reg is simple + long_move(masm, src, dst); + } else { + Register d = dst.first()->is_reg() ? dst.first()->as_Register() : L2; + + // Destination could be an odd reg on 32bit in which case + // we can't load direct to the destination. + + if (!d->is_even() && wordSize == 4) { + d = L2; + } + int off = STACK_BIAS + conversion_temp * VMRegImpl::stack_slot_size; + if (Assembler::is_simm13(off)) { + __ stf(FloatRegisterImpl::D, src.first()->as_FloatRegister(), + SP, off); + __ ld_long(SP, off, d); + } else { + if (conversion_off == noreg) { + __ set(off, L6); + conversion_off = L6; + } + __ stf(FloatRegisterImpl::D, src.first()->as_FloatRegister(), + SP, conversion_off); + __ ld_long(SP, conversion_off, d); + } + if (d == L2) { + long_move(masm, reg64_to_VMRegPair(L2), dst); + } + } + break; + + case T_LONG : + // 32bit can't do a split move of something like g1 -> O0, O1 + // so use a memory temp + if (src.is_single_phys_reg() && wordSize == 4) { + Register tmp = L2; + if (dst.first()->is_reg() && + (wordSize == 8 || dst.first()->as_Register()->is_even())) { + tmp = dst.first()->as_Register(); + } + + int off = STACK_BIAS + conversion_temp * VMRegImpl::stack_slot_size; + if (Assembler::is_simm13(off)) { + __ stx(src.first()->as_Register(), SP, off); + __ ld_long(SP, off, tmp); + } else { + if (conversion_off == noreg) { + __ set(off, L6); + conversion_off = L6; + } + __ stx(src.first()->as_Register(), SP, conversion_off); + __ ld_long(SP, conversion_off, tmp); + } + + if (tmp == L2) { + long_move(masm, reg64_to_VMRegPair(L2), dst); + } + } else { + long_move(masm, src, dst); + } + break; + + case T_ADDRESS: assert(false, "found T_ADDRESS in java args"); + + default: + move32_64(masm, src, dst); + } + } + + + // If we have any strings we must store any register based arg to the stack + // This includes any still live xmm registers too. + + if (total_strings > 0 ) { + + // protect all the arg registers + __ save_frame(0); + __ mov(G2_thread, L7_thread_cache); + const Register L2_string_off = L2; + + // Get first string offset + __ set(string_locs * VMRegImpl::stack_slot_size, L2_string_off); + + for (c_arg = 0 ; c_arg < total_c_args ; c_arg++ ) { + if (out_sig_bt[c_arg] == T_ADDRESS) { + + VMRegPair dst = out_regs[c_arg]; + const Register d = dst.first()->is_reg() ? + dst.first()->as_Register()->after_save() : noreg; + + // It's a string the oop and it was already copied to the out arg + // position + if (d != noreg) { + __ mov(d, O0); + } else { + assert(Assembler::is_simm13(reg2offset(dst.first()) + STACK_BIAS), + "must be"); + __ ld_ptr(FP, reg2offset(dst.first()) + STACK_BIAS, O0); + } + Label skip; + + __ br_null(O0, false, Assembler::pn, skip); + __ delayed()->add(FP, L2_string_off, O1); + + if (d != noreg) { + __ mov(O1, d); + } else { + assert(Assembler::is_simm13(reg2offset(dst.first()) + STACK_BIAS), + "must be"); + __ st_ptr(O1, FP, reg2offset(dst.first()) + STACK_BIAS); + } + + __ call(CAST_FROM_FN_PTR(address, SharedRuntime::get_utf), + relocInfo::runtime_call_type); + __ delayed()->add(L2_string_off, max_dtrace_string_size, L2_string_off); + + __ bind(skip); + + } + + } + __ mov(L7_thread_cache, G2_thread); + __ restore(); + + } + + + // Ok now we are done. Need to place the nop that dtrace wants in order to + // patch in the trap + + int patch_offset = ((intptr_t)__ pc()) - start; + + __ nop(); + + + // Return + + __ ret(); + __ delayed()->restore(); + + __ flush(); + + nmethod *nm = nmethod::new_dtrace_nmethod( + method, masm->code(), vep_offset, patch_offset, frame_complete, + stack_slots / VMRegImpl::slots_per_word); + return nm; + +} + +#endif // HAVE_DTRACE_H + // this function returns the adjust size (in number of words) to a c2i adapter // activation for use during deoptimization int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals) { diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 9360631b077..73458015efe 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -544,11 +544,19 @@ int MachCallDynamicJavaNode::ret_addr_offset() { assert(!UseInlineCaches, "expect vtable calls only if not using ICs"); int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes(); + int klass_load_size; + if (UseCompressedOops) { + klass_load_size = 3*BytesPerInstWord; // see MacroAssembler::load_klass() + } else { + klass_load_size = 1*BytesPerInstWord; + } if( Assembler::is_simm13(v_off) ) { - return (3*BytesPerInstWord + // ld_ptr, ld_ptr, ld_ptr + return klass_load_size + + (2*BytesPerInstWord + // ld_ptr, ld_ptr NativeCall::instruction_size); // call; delay slot } else { - return (5*BytesPerInstWord + // ld_ptr, set_hi, set, ld_ptr, ld_ptr + return klass_load_size + + (4*BytesPerInstWord + // set_hi, set, ld_ptr, ld_ptr NativeCall::instruction_size); // call; delay slot } } @@ -1591,7 +1599,13 @@ uint reloc_java_to_interp() { void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { st->print_cr("\nUEP:"); #ifdef _LP64 - st->print_cr("\tLDX [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check"); + if (UseCompressedOops) { + st->print_cr("\tLDUW [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check - compressed klass"); + st->print_cr("\tSLL R_G5,3,R_G5"); + st->print_cr("\tADD R_G5,R_G6_heap_base,R_G5"); + } else { + st->print_cr("\tLDX [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check"); + } st->print_cr("\tCMP R_G5,R_G3" ); st->print ("\tTne xcc,R_G0+ST_RESERVED_FOR_USER_0+2"); #else // _LP64 @@ -1610,7 +1624,7 @@ void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { assert( G5_ic_reg != temp_reg, "conflicting registers" ); // Load klass from reciever - __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), temp_reg); + __ load_klass(O0, temp_reg); // Compare against expected klass __ cmp(temp_reg, G5_ic_reg); // Branch to miss code, checks xcc or icc depending @@ -1811,6 +1825,11 @@ bool Matcher::can_be_java_arg( int reg ) { reg == R_I3H_num || reg == R_I4H_num || reg == R_I5H_num ) return true; + + if ((UseCompressedOops) && (reg == R_G6_num || reg == R_G6H_num)) { + return true; + } + #else // 32-bit builds with longs-in-one-entry pass longs in G1 & G4. // Longs cannot be passed in O regs, because O regs become I regs @@ -2474,7 +2493,13 @@ encode %{ // get receiver klass (receiver already checked for non-null) // If we end up going thru a c2i adapter interpreter expects method in G5 int off = __ offset(); - __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_scratch); + __ load_klass(O0, G3_scratch); + int klass_load_size; + if (UseCompressedOops) { + klass_load_size = 3*BytesPerInstWord; + } else { + klass_load_size = 1*BytesPerInstWord; + } int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes(); if( __ is_simm13(v_off) ) { @@ -2484,7 +2509,8 @@ encode %{ __ Assembler::sethi(v_off & ~0x3ff, G5_method); __ or3(G5_method, v_off & 0x3ff, G5_method); // ld_ptr, set_hi, set - assert(__ offset() - off == 3*BytesPerInstWord, "Unexpected instruction size(s)"); + assert(__ offset() - off == klass_load_size + 2*BytesPerInstWord, + "Unexpected instruction size(s)"); __ ld_ptr(G3, G5_method, G5_method); } // NOTE: for vtable dispatches, the vtable entry will never be null. @@ -2860,12 +2886,12 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{ int count_offset = java_lang_String:: count_offset_in_bytes(); // load str1 (jchar*) base address into tmp1_reg - __ ld_ptr(Address(str1_reg, 0, value_offset), tmp1_reg); + __ load_heap_oop(Address(str1_reg, 0, value_offset), tmp1_reg); __ ld(Address(str1_reg, 0, offset_offset), result_reg); __ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg); __ ld(Address(str1_reg, 0, count_offset), str1_reg); // hoisted __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); - __ ld_ptr(Address(str2_reg, 0, value_offset), tmp2_reg); // hoisted + __ load_heap_oop(Address(str2_reg, 0, value_offset), tmp2_reg); // hoisted __ add(result_reg, tmp1_reg, tmp1_reg); // load str2 (jchar*) base address into tmp2_reg @@ -3016,6 +3042,7 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{ MacroAssembler _masm(&cbuf); __ membar( Assembler::Membar_mask_bits(Assembler::StoreLoad) ); %} + enc_class enc_repl8b( iRegI src, iRegL dst ) %{ MacroAssembler _masm(&cbuf); Register src_reg = reg_to_register_object($src$$reg); @@ -3189,15 +3216,15 @@ frame %{ c_return_value %{ assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" ); #ifdef _LP64 - static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num }; - static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num}; - static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num }; - static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num}; + static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num }; + static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num}; + static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num }; + static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num}; #else // !_LP64 - static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num }; - static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num }; + static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num }; + static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num }; + static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num }; + static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num }; #endif return OptoRegPair( (is_outgoing?hi_out:hi_in)[ideal_reg], (is_outgoing?lo_out:lo_in)[ideal_reg] ); @@ -3207,15 +3234,15 @@ frame %{ return_value %{ assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" ); #ifdef _LP64 - static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num }; - static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num}; - static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num }; - static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num}; + static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num }; + static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num}; + static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num }; + static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num}; #else // !_LP64 - static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num}; - static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num}; + static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num }; + static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num}; + static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num }; + static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num}; #endif return OptoRegPair( (is_outgoing?hi_out:hi_in)[ideal_reg], (is_outgoing?lo_out:lo_in)[ideal_reg] ); @@ -3408,6 +3435,27 @@ operand immP_poll() %{ interface(CONST_INTER); %} +// Pointer Immediate +operand immN() +%{ + match(ConN); + + op_cost(10); + format %{ %} + interface(CONST_INTER); +%} + +// NULL Pointer Immediate +operand immN0() +%{ + predicate(n->get_narrowcon() == 0); + match(ConN); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + operand immL() %{ match(ConL); op_cost(40); @@ -3672,6 +3720,14 @@ operand o7RegI() %{ interface(REG_INTER); %} +operand iRegN() %{ + constraint(ALLOC_IN_RC(int_reg)); + match(RegN); + + format %{ %} + interface(REG_INTER); +%} + // Long Register operand iRegL() %{ constraint(ALLOC_IN_RC(long_reg)); @@ -5392,9 +5448,30 @@ instruct loadP(iRegP dst, memory mem) %{ ins_pipe(iload_mem); %} +// Load Compressed Pointer +instruct loadN(iRegN dst, memory mem) %{ + match(Set dst (LoadN mem)); + ins_cost(MEMORY_REF_COST); + size(4); + + format %{ "LDUW $mem,$dst\t! compressed ptr" %} + ins_encode %{ + Register base = as_Register($mem$$base); + Register index = as_Register($mem$$index); + Register dst = $dst$$Register; + if (index != G0) { + __ lduw(base, index, dst); + } else { + __ lduw(base, $mem$$disp, dst); + } + %} + ins_pipe(iload_mem); +%} + // Load Klass Pointer instruct loadKlass(iRegP dst, memory mem) %{ match(Set dst (LoadKlass mem)); + predicate(!n->in(MemNode::Address)->bottom_type()->is_narrow()); ins_cost(MEMORY_REF_COST); size(4); @@ -5409,6 +5486,30 @@ instruct loadKlass(iRegP dst, memory mem) %{ ins_pipe(iload_mem); %} +// Load Klass Pointer +instruct loadKlassComp(iRegP dst, memory mem) %{ + match(Set dst (LoadKlass mem)); + predicate(n->in(MemNode::Address)->bottom_type()->is_narrow()); + ins_cost(MEMORY_REF_COST); + + format %{ "LDUW $mem,$dst\t! compressed klass ptr" %} + + ins_encode %{ + Register base = as_Register($mem$$base); + Register index = as_Register($mem$$index); + Register dst = $dst$$Register; + if (index != G0) { + __ lduw(base, index, dst); + } else { + __ lduw(base, $mem$$disp, dst); + } + // klass oop never null but this is generated for nonheader klass loads + // too which can be null. + __ decode_heap_oop(dst); + %} + ins_pipe(iload_mem); +%} + // Load Short (16bit signed) instruct loadS(iRegI dst, memory mem) %{ match(Set dst (LoadS mem)); @@ -5508,6 +5609,24 @@ instruct loadConP_poll(iRegP dst, immP_poll src) %{ ins_pipe(loadConP_poll); %} +instruct loadConN(iRegN dst, immN src) %{ + match(Set dst src); + ins_cost(DEFAULT_COST * 2); + format %{ "SET $src,$dst\t!ptr" %} + ins_encode %{ + address con = (address)$src$$constant; + Register dst = $dst$$Register; + if (con == NULL) { + __ mov(G0, dst); + } else { + __ set_oop((jobject)$src$$constant, dst); + __ encode_heap_oop(dst); + } + %} + ins_pipe(loadConP); + +%} + instruct loadConL(iRegL dst, immL src, o7RegL tmp) %{ // %%% maybe this should work like loadConD match(Set dst src); @@ -5741,6 +5860,44 @@ instruct storeP0(memory dst, immP0 src) %{ ins_pipe(istore_mem_zero); %} +// Store Compressed Pointer +instruct storeN(memory dst, iRegN src) %{ + match(Set dst (StoreN dst src)); + ins_cost(MEMORY_REF_COST); + size(4); + + format %{ "STW $src,$dst\t! compressed ptr" %} + ins_encode %{ + Register base = as_Register($dst$$base); + Register index = as_Register($dst$$index); + Register src = $src$$Register; + if (index != G0) { + __ stw(src, base, index); + } else { + __ stw(src, base, $dst$$disp); + } + %} + ins_pipe(istore_mem_spORreg); +%} + +instruct storeN0(memory dst, immN0 src) %{ + match(Set dst (StoreN dst src)); + ins_cost(MEMORY_REF_COST); + size(4); + + format %{ "STW $src,$dst\t! compressed ptr" %} + ins_encode %{ + Register base = as_Register($dst$$base); + Register index = as_Register($dst$$index); + if (index != G0) { + __ stw(0, base, index); + } else { + __ stw(0, base, $dst$$disp); + } + %} + ins_pipe(istore_mem_zero); +%} + // Store Double instruct storeD( memory mem, regD src) %{ match(Set mem (StoreD mem src)); @@ -5798,6 +5955,48 @@ instruct storeA8B(memory mem, regD src) %{ ins_pipe(fstoreD_mem_reg); %} +// Convert oop pointer into compressed form +instruct encodeHeapOop(iRegN dst, iRegP src) %{ + predicate(n->bottom_type()->is_narrowoop()->make_oopptr()->ptr() != TypePtr::NotNull); + match(Set dst (EncodeP src)); + format %{ "encode_heap_oop $src, $dst" %} + ins_encode %{ + __ encode_heap_oop($src$$Register, $dst$$Register); + %} + ins_pipe(ialu_reg); +%} + +instruct encodeHeapOop_not_null(iRegN dst, iRegP src) %{ + predicate(n->bottom_type()->is_narrowoop()->make_oopptr()->ptr() == TypePtr::NotNull); + match(Set dst (EncodeP src)); + format %{ "encode_heap_oop_not_null $src, $dst" %} + ins_encode %{ + __ encode_heap_oop_not_null($src$$Register, $dst$$Register); + %} + ins_pipe(ialu_reg); +%} + +instruct decodeHeapOop(iRegP dst, iRegN src) %{ + predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull); + match(Set dst (DecodeN src)); + format %{ "decode_heap_oop $src, $dst" %} + ins_encode %{ + __ decode_heap_oop($src$$Register, $dst$$Register); + %} + ins_pipe(ialu_reg); +%} + +instruct decodeHeapOop_not_null(iRegP dst, iRegN src) %{ + predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull); + match(Set dst (DecodeN src)); + format %{ "decode_heap_oop_not_null $src, $dst" %} + ins_encode %{ + __ decode_heap_oop_not_null($src$$Register, $dst$$Register); + %} + ins_pipe(ialu_reg); +%} + + // Store Zero into Aligned Packed Bytes instruct storeA8B0(memory mem, immI0 zero) %{ match(Set mem (Store8B mem zero)); @@ -6434,17 +6633,27 @@ instruct compareAndSwapI_bool(iRegP mem_ptr, iRegI oldval, iRegI newval, iRegI r instruct compareAndSwapP_bool(iRegP mem_ptr, iRegP oldval, iRegP newval, iRegI res, o7RegI tmp1, flagsReg ccr ) %{ match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval))); effect( USE mem_ptr, KILL ccr, KILL tmp1); -#ifdef _LP64 format %{ "MOV $newval,O7\n\t" - "CASXA [$mem_ptr],$oldval,O7\t! If $oldval==[$mem_ptr] Then store O7 into [$mem_ptr], set O7=[$mem_ptr] in any case\n\t" + "CASA_PTR [$mem_ptr],$oldval,O7\t! If $oldval==[$mem_ptr] Then store O7 into [$mem_ptr], set O7=[$mem_ptr] in any case\n\t" "CMP $oldval,O7\t\t! See if we made progress\n\t" "MOV 1,$res\n\t" "MOVne xcc,R_G0,$res" %} +#ifdef _LP64 ins_encode( enc_casx(mem_ptr, oldval, newval), enc_lflags_ne_to_boolean(res) ); #else + ins_encode( enc_casi(mem_ptr, oldval, newval), + enc_iflags_ne_to_boolean(res) ); +#endif + ins_pipe( long_memory_op ); +%} + +instruct compareAndSwapN_bool_comp(iRegP mem_ptr, iRegN oldval, iRegN newval, iRegI res, o7RegI tmp, flagsReg ccr ) %{ + match(Set res (CompareAndSwapN mem_ptr (Binary oldval newval))); + effect( USE mem_ptr, KILL ccr, KILL tmp); + format %{ "MOV $newval,O7\n\t" "CASA [$mem_ptr],$oldval,O7\t! If $oldval==[$mem_ptr] Then store O7 into [$mem_ptr], set O7=[$mem_ptr] in any case\n\t" @@ -6452,9 +6661,18 @@ instruct compareAndSwapP_bool(iRegP mem_ptr, iRegP oldval, iRegP newval, iRegI r "MOV 1,$res\n\t" "MOVne icc,R_G0,$res" %} - ins_encode( enc_casi(mem_ptr, oldval, newval), - enc_iflags_ne_to_boolean(res) ); -#endif + ins_encode %{ + Register Rmem = reg_to_register_object($mem_ptr$$reg); + Register Rold = reg_to_register_object($oldval$$reg); + Register Rnew = reg_to_register_object($newval$$reg); + Register Rres = reg_to_register_object($res$$reg); + + __ cas(Rmem, Rold, Rnew); + __ cmp( Rold, Rnew ); + __ mov(1, Rres); + __ movcc( Assembler::notEqual, false, Assembler::icc, G0, Rres ); + %} + ins_pipe( long_memory_op ); %} @@ -8607,6 +8825,17 @@ instruct partialSubtypeCheck_vs_zero( flagsRegP pcc, o1RegP sub, o2RegP super, i ins_pipe(partial_subtype_check_pipe); %} + +instruct compP_iRegN_immN0(flagsRegP pcc, iRegN op1, immN0 op2 ) %{ + match(Set pcc (CmpN op1 op2)); + + size(4); + format %{ "CMP $op1,$op2\t! ptr" %} + opcode(Assembler::subcc_op3, Assembler::arith_op); + ins_encode( form3_rs1_simm13_rd( op1, op2, R_G0 ) ); + ins_pipe(ialu_cconly_reg_imm); +%} + // ============================================================================ // inlined locking and unlocking @@ -8648,9 +8877,10 @@ instruct clear_array(iRegX cnt, iRegP base, iRegX temp, Universe dummy, flagsReg ins_pipe(long_memory_op); %} -instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, flagsReg ccr) %{ +instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, + o7RegI tmp3, flagsReg ccr) %{ match(Set result (StrComp str1 str2)); - effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr); + effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3); ins_cost(300); format %{ "String Compare $str1,$str2 -> $result" %} ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, result) ); diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index 290cedb9bb0..73e092d620c 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -127,6 +127,7 @@ class StubGenerator: public StubCodeGenerator { // setup thread register __ ld_ptr(thread.as_address(), G2_thread); + __ reinit_heapbase(); #ifdef ASSERT // make sure we have no pending exceptions @@ -896,6 +897,7 @@ class StubGenerator: public StubCodeGenerator { // super: O2, argument, not changed // raddr: O7, blown by call address generate_partial_subtype_check() { + __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", "partial_subtype_check"); address start = __ pc(); Label loop, miss; @@ -914,7 +916,7 @@ class StubGenerator: public StubCodeGenerator { #if defined(COMPILER2) && !defined(_LP64) // Do not use a 'save' because it blows the 64-bit O registers. - __ add(SP,-4*wordSize,SP); // Make space for 4 temps + __ add(SP,-4*wordSize,SP); // Make space for 4 temps (stack must be 2 words aligned) __ st_ptr(L0,SP,(frame::register_save_words+0)*wordSize); __ st_ptr(L1,SP,(frame::register_save_words+1)*wordSize); __ st_ptr(L2,SP,(frame::register_save_words+2)*wordSize); @@ -934,6 +936,17 @@ class StubGenerator: public StubCodeGenerator { Register L2_super = L2; Register L3_index = L3; +#ifdef _LP64 + Register L4_ooptmp = L4; + + if (UseCompressedOops) { + // this must be under UseCompressedOops check, as we rely upon fact + // that L4 not clobbered in C2 on 32-bit platforms, where we do explicit save + // on stack, see several lines above + __ encode_heap_oop(Rsuper, L4_ooptmp); + } +#endif + inc_counter_np(SharedRuntime::_partial_subtype_ctr, L0, L1); __ ld_ptr( Rsub, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes(), L3 ); @@ -942,18 +955,33 @@ class StubGenerator: public StubCodeGenerator { __ clr(L3_index); // zero index // Load a little early; will load 1 off the end of the array. // Ok for now; revisit if we have other uses of this routine. - __ ld_ptr(L1_ary_ptr,0,L2_super);// Will load a little early - __ align(CodeEntryAlignment); + if (UseCompressedOops) { + __ ld(L1_ary_ptr,0,L2_super);// Will load a little early + } else { + __ ld_ptr(L1_ary_ptr,0,L2_super);// Will load a little early + } + assert(heapOopSize != 0, "heapOopSize should be initialized"); // The scan loop __ BIND(loop); - __ add(L1_ary_ptr,wordSize,L1_ary_ptr); // Bump by OOP size + __ add(L1_ary_ptr, heapOopSize, L1_ary_ptr); // Bump by OOP size __ cmp(L3_index,L0_ary_len); __ br(Assembler::equal,false,Assembler::pn,miss); __ delayed()->inc(L3_index); // Bump index - __ subcc(L2_super,Rsuper,Rret); // Check for match; zero in Rret for a hit - __ brx( Assembler::notEqual, false, Assembler::pt, loop ); - __ delayed()->ld_ptr(L1_ary_ptr,0,L2_super); // Will load a little early + + if (UseCompressedOops) { +#ifdef _LP64 + __ subcc(L2_super,L4_ooptmp,Rret); // Check for match; zero in Rret for a hit + __ br( Assembler::notEqual, false, Assembler::pt, loop ); + __ delayed()->ld(L1_ary_ptr,0,L2_super);// Will load a little early +#else + ShouldNotReachHere(); +#endif + } else { + __ subcc(L2_super,Rsuper,Rret); // Check for match; zero in Rret for a hit + __ brx( Assembler::notEqual, false, Assembler::pt, loop ); + __ delayed()->ld_ptr(L1_ary_ptr,0,L2_super);// Will load a little early + } // Got a hit; report success; set cache. Cache load doesn't // happen here; for speed it is directly emitted by the compiler. @@ -1107,7 +1135,6 @@ class StubGenerator: public StubCodeGenerator { } #endif // 0 } - // // Generate post-write barrier for array. // @@ -1148,8 +1175,8 @@ class StubGenerator: public StubCodeGenerator { Label L_loop; - __ sll_ptr(count, LogBytesPerOop, count); - __ sub(count, BytesPerOop, count); + __ sll_ptr(count, LogBytesPerHeapOop, count); + __ sub(count, BytesPerHeapOop, count); __ add(count, addr, count); // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.) __ srl_ptr(addr, CardTableModRefBS::card_shift, addr); @@ -1171,7 +1198,6 @@ class StubGenerator: public StubCodeGenerator { ShouldNotReachHere(); } - } @@ -2226,7 +2252,12 @@ class StubGenerator: public StubCodeGenerator { __ mov(count, G5); gen_write_ref_array_pre_barrier(G1, G5); #ifdef _LP64 - generate_disjoint_long_copy_core(aligned); + assert_clean_int(count, O3); // Make sure 'count' is clean int. + if (UseCompressedOops) { + generate_disjoint_int_copy_core(aligned); + } else { + generate_disjoint_long_copy_core(aligned); + } #else generate_disjoint_int_copy_core(aligned); #endif @@ -2274,10 +2305,14 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::arrayof_oop_disjoint_arraycopy() : disjoint_oop_copy_entry; - array_overlap_test(nooverlap_target, LogBytesPerWord); + array_overlap_test(nooverlap_target, LogBytesPerHeapOop); #ifdef _LP64 - generate_conjoint_long_copy_core(aligned); + if (UseCompressedOops) { + generate_conjoint_int_copy_core(aligned); + } else { + generate_conjoint_long_copy_core(aligned); + } #else generate_conjoint_int_copy_core(aligned); #endif @@ -2377,8 +2412,6 @@ class StubGenerator: public StubCodeGenerator { StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); - int klass_off = oopDesc::klass_offset_in_bytes(); - gen_write_ref_array_pre_barrier(G1, G5); @@ -2395,7 +2428,7 @@ class StubGenerator: public StubCodeGenerator { { Label L; __ mov(O3, G1); // spill: overlap test smashes O3 __ mov(O4, G4); // spill: overlap test smashes O4 - array_overlap_test(L, LogBytesPerWord); + array_overlap_test(L, LogBytesPerHeapOop); __ stop("checkcast_copy within a single array"); __ bind(L); __ mov(G1, O3); @@ -2429,18 +2462,18 @@ class StubGenerator: public StubCodeGenerator { __ bind(store_element); // deccc(G1_remain); // decrement the count (hoisted) - __ st_ptr(G3_oop, O1_to, O5_offset); // store the oop - __ inc(O5_offset, wordSize); // step to next offset + __ store_heap_oop(G3_oop, O1_to, O5_offset); // store the oop + __ inc(O5_offset, heapOopSize); // step to next offset __ brx(Assembler::zero, true, Assembler::pt, do_card_marks); __ delayed()->set(0, O0); // return -1 on success // ======== loop entry is here ======== __ bind(load_element); - __ ld_ptr(O0_from, O5_offset, G3_oop); // load the oop + __ load_heap_oop(O0_from, O5_offset, G3_oop); // load the oop __ br_null(G3_oop, true, Assembler::pt, store_element); __ delayed()->deccc(G1_remain); // decrement the count - __ ld_ptr(G3_oop, klass_off, G4_klass); // query the object klass + __ load_klass(G3_oop, G4_klass); // query the object klass generate_type_check(G4_klass, O3_ckoff, O4_ckval, G5_super, // branch to this on success: @@ -2642,17 +2675,23 @@ class StubGenerator: public StubCodeGenerator { BLOCK_COMMENT("arraycopy argument klass checks"); // get src->klass() - __ delayed()->ld_ptr(src, oopDesc::klass_offset_in_bytes(), G3_src_klass); + if (UseCompressedOops) { + __ delayed()->nop(); // ??? not good + __ load_klass(src, G3_src_klass); + } else { + __ delayed()->ld_ptr(src, oopDesc::klass_offset_in_bytes(), G3_src_klass); + } #ifdef ASSERT // assert(src->klass() != NULL); BLOCK_COMMENT("assert klasses not null"); { Label L_a, L_b; __ br_notnull(G3_src_klass, false, Assembler::pt, L_b); // it is broken if klass is NULL - __ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass); + __ delayed()->nop(); __ bind(L_a); __ stop("broken null klass"); __ bind(L_b); + __ load_klass(dst, G4_dst_klass); __ br_null(G4_dst_klass, false, Assembler::pn, L_a); // this would be broken also __ delayed()->mov(G0, G4_dst_klass); // scribble the temp BLOCK_COMMENT("assert done"); @@ -2673,12 +2712,19 @@ class StubGenerator: public StubCodeGenerator { // Load 32-bits signed value. Use br() instruction with it to check icc. __ lduw(G3_src_klass, lh_offset, G5_lh); + if (UseCompressedOops) { + __ load_klass(dst, G4_dst_klass); + } // Handle objArrays completely differently... juint objArray_lh = Klass::array_layout_helper(T_OBJECT); __ set(objArray_lh, O5_temp); __ cmp(G5_lh, O5_temp); __ br(Assembler::equal, false, Assembler::pt, L_objArray); - __ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass); + if (UseCompressedOops) { + __ delayed()->nop(); + } else { + __ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass); + } // if (src->klass() != dst->klass()) return -1; __ cmp(G3_src_klass, G4_dst_klass); @@ -2777,8 +2823,8 @@ class StubGenerator: public StubCodeGenerator { __ add(src, arrayOopDesc::base_offset_in_bytes(T_OBJECT), src); //src offset __ add(dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT), dst); //dst offset - __ sll_ptr(src_pos, LogBytesPerOop, src_pos); - __ sll_ptr(dst_pos, LogBytesPerOop, dst_pos); + __ sll_ptr(src_pos, LogBytesPerHeapOop, src_pos); + __ sll_ptr(dst_pos, LogBytesPerHeapOop, dst_pos); __ add(src, src_pos, from); // src_addr __ add(dst, dst_pos, to); // dst_addr __ BIND(L_plain_copy); @@ -2801,8 +2847,8 @@ class StubGenerator: public StubCodeGenerator { // Marshal the base address arguments now, freeing registers. __ add(src, arrayOopDesc::base_offset_in_bytes(T_OBJECT), src); //src offset __ add(dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT), dst); //dst offset - __ sll_ptr(src_pos, LogBytesPerOop, src_pos); - __ sll_ptr(dst_pos, LogBytesPerOop, dst_pos); + __ sll_ptr(src_pos, LogBytesPerHeapOop, src_pos); + __ sll_ptr(dst_pos, LogBytesPerHeapOop, dst_pos); __ add(src, src_pos, from); // src_addr __ add(dst, dst_pos, to); // dst_addr __ signx(length, count); // length (reloaded) diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp index a840f3e6807..63e2bdc3e59 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp @@ -591,7 +591,10 @@ address InterpreterGenerator::generate_accessor_entry(void) { address entry = __ pc(); Label slow_path; - if ( UseFastAccessorMethods) { + + // XXX: for compressed oops pointer loading and decoding doesn't fit in + // delay slot and damages G1 + if ( UseFastAccessorMethods && !UseCompressedOops ) { // Check if we need to reach a safepoint and generate full interpreter // frame if so. Address sync_state(G3_scratch, SafepointSynchronize::address_of_state()); @@ -953,6 +956,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { // Back from jni method Lmethod in this frame is DEAD, DEAD, DEAD __ restore_thread(L7_thread_cache); // restore G2_thread + __ reinit_heapbase(); // must we block? diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index 220b8813980..a9bc2b9eff3 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -462,8 +462,8 @@ void TemplateTable::aaload() { transition(itos, atos); // Otos_i: index // tos: array - __ index_check(O2, Otos_i, LogBytesPerWord, G3_scratch, O3); - __ ld_ptr(O3, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i); + __ index_check(O2, Otos_i, UseCompressedOops ? 2 : LogBytesPerWord, G3_scratch, O3); + __ load_heap_oop(O3, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i); __ verify_oop(Otos_i); } @@ -736,15 +736,16 @@ void TemplateTable::aastore() { // O2: index // O3: array __ verify_oop(Otos_i); - __ index_check_without_pop(O3, O2, LogBytesPerWord, G3_scratch, O1); + __ index_check_without_pop(O3, O2, UseCompressedOops ? 2 : LogBytesPerWord, G3_scratch, O1); // do array store check - check for NULL value first __ br_null( Otos_i, false, Assembler::pn, is_null ); - __ delayed()-> - ld_ptr(O3, oopDesc::klass_offset_in_bytes(), O4); // get array klass + __ delayed()->nop(); + + __ load_klass(O3, O4); // get array klass + __ load_klass(Otos_i, O5); // get value klass // do fast instanceof cache test - __ ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), O5); // get value klass __ ld_ptr(O4, sizeof(oopDesc) + objArrayKlass::element_klass_offset_in_bytes(), O4); @@ -766,7 +767,7 @@ void TemplateTable::aastore() { // Store is OK. __ bind(store_ok); - __ st_ptr(Otos_i, O1, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); + __ store_heap_oop(Otos_i, O1, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); // Quote from rememberedSet.hpp: For objArrays, the precise card // corresponding to the pointer store is dirtied so we don't need to // scavenge the entire array. @@ -777,7 +778,7 @@ void TemplateTable::aastore() { __ delayed()->inc(Lesp, 3* Interpreter::stackElementSize()); // adj sp (pops array, index and value) __ bind(is_null); - __ st_ptr(Otos_i, element); + __ store_heap_oop(Otos_i, element); __ profile_null_seen(G3_scratch); __ inc(Lesp, 3* Interpreter::stackElementSize()); // adj sp (pops array, index and value) __ bind(done); @@ -1833,7 +1834,7 @@ void TemplateTable::_return(TosState state) { assert(state == vtos, "only valid state"); __ mov(G0, G3_scratch); __ access_local_ptr(G3_scratch, Otos_i); - __ ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), O2); + __ load_klass(Otos_i, O2); __ set(JVM_ACC_HAS_FINALIZER, G3); __ ld(O2, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc), O2); __ andcc(G3, O2, G0); @@ -2078,7 +2079,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) { __ delayed() ->cmp(Rflags, itos); // atos - __ ld_ptr(Rclass, Roffset, Otos_i); + __ load_heap_oop(Rclass, Roffset, Otos_i); __ verify_oop(Otos_i); __ push(atos); if (!is_static) { @@ -2259,7 +2260,7 @@ void TemplateTable::fast_accessfield(TosState state) { __ ldf(FloatRegisterImpl::D, Otos_i, Roffset, Ftos_d); break; case Bytecodes::_fast_agetfield: - __ ld_ptr(Otos_i, Roffset, Otos_i); + __ load_heap_oop(Otos_i, Roffset, Otos_i); break; default: ShouldNotReachHere(); @@ -2448,7 +2449,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) { // atos __ pop_ptr(); __ verify_oop(Otos_i); - __ st_ptr(Otos_i, Rclass, Roffset); + __ store_heap_oop(Otos_i, Rclass, Roffset); __ store_check(G1_scratch, Rclass, Roffset); __ ba(false, checkVolatile); __ delayed()->tst(Lscratch); @@ -2490,7 +2491,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) { __ pop_ptr(); pop_and_check_object(Rclass); __ verify_oop(Otos_i); - __ st_ptr(Otos_i, Rclass, Roffset); + __ store_heap_oop(Otos_i, Rclass, Roffset); __ store_check(G1_scratch, Rclass, Roffset); patch_bytecode(Bytecodes::_fast_aputfield, G3_scratch, G4_scratch); __ ba(false, checkVolatile); @@ -2645,7 +2646,7 @@ void TemplateTable::fast_storefield(TosState state) { __ stf(FloatRegisterImpl::D, Ftos_d, Rclass, Roffset); break; case Bytecodes::_fast_aputfield: - __ st_ptr(Otos_i, Rclass, Roffset); + __ store_heap_oop(Otos_i, Rclass, Roffset); __ store_check(G1_scratch, Rclass, Roffset); break; default: @@ -2688,7 +2689,7 @@ void TemplateTable::fast_xaccess(TosState state) { __ verify_oop(Rreceiver); __ null_check(Rreceiver); if (state == atos) { - __ ld_ptr(Rreceiver, Roffset, Otos_i); + __ load_heap_oop(Rreceiver, Roffset, Otos_i); } else if (state == itos) { __ ld (Rreceiver, Roffset, Otos_i) ; } else if (state == ftos) { @@ -2790,7 +2791,7 @@ void TemplateTable::invokevirtual(int byte_no) { // get receiver klass __ null_check(O0, oopDesc::klass_offset_in_bytes()); - __ ld_ptr(Address(O0, 0, oopDesc::klass_offset_in_bytes()), Rrecv); + __ load_klass(O0, Rrecv); __ verify_oop(Rrecv); __ profile_virtual_call(Rrecv, O4); @@ -2958,7 +2959,7 @@ void TemplateTable::invokeinterface(int byte_no) { // get receiver klass __ null_check(O0, oopDesc::klass_offset_in_bytes()); - __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), RklassOop); + __ load_klass(O0, RklassOop); __ verify_oop(RklassOop); // Special case of invokeinterface called for virtual method of @@ -3221,7 +3222,7 @@ void TemplateTable::_new() { __ set((intptr_t)markOopDesc::prototype(), G4_scratch); } __ st_ptr(G4_scratch, RallocatedObject, oopDesc::mark_offset_in_bytes()); // mark - __ st_ptr(RinstanceKlass, RallocatedObject, oopDesc::klass_offset_in_bytes()); // klass + __ store_klass(RinstanceKlass, RallocatedObject); // klass { SkipIfEqual skip_if( @@ -3277,7 +3278,7 @@ void TemplateTable::checkcast() { __ delayed()->nop(); // Get value klass in RobjKlass - __ ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), RobjKlass); // get value klass + __ load_klass(Otos_i, RobjKlass); // get value klass // Get constant pool tag __ get_2_byte_integer_at_bcp(1, Lscratch, Roffset, InterpreterMacroAssembler::Unsigned); @@ -3295,13 +3296,14 @@ void TemplateTable::checkcast() { __ pop_ptr(Otos_i, G3_scratch); // restore receiver __ br(Assembler::always, false, Assembler::pt, resolved); - __ delayed()->ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), RobjKlass); // get value klass + __ delayed()->nop(); // Extract target class from constant pool __ bind(quicked); __ add(Roffset, sizeof(constantPoolOopDesc), Roffset); __ ld_ptr(Lscratch, Roffset, RspecifiedKlass); __ bind(resolved); + __ load_klass(Otos_i, RobjKlass); // get value klass // Generate a fast subtype check. Branch to cast_ok if no // failure. Throw exception if failure. @@ -3334,7 +3336,7 @@ void TemplateTable::instanceof() { __ delayed()->nop(); // Get value klass in RobjKlass - __ ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), RobjKlass); // get value klass + __ load_klass(Otos_i, RobjKlass); // get value klass // Get constant pool tag __ get_2_byte_integer_at_bcp(1, Lscratch, Roffset, InterpreterMacroAssembler::Unsigned); @@ -3352,7 +3354,7 @@ void TemplateTable::instanceof() { __ pop_ptr(Otos_i, G3_scratch); // restore receiver __ br(Assembler::always, false, Assembler::pt, resolved); - __ delayed()->ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), RobjKlass); // get value klass + __ delayed()->nop(); // Extract target class from constant pool @@ -3361,6 +3363,7 @@ void TemplateTable::instanceof() { __ get_constant_pool(Lscratch); __ ld_ptr(Lscratch, Roffset, RspecifiedKlass); __ bind(resolved); + __ load_klass(Otos_i, RobjKlass); // get value klass // Generate a fast subtype check. Branch to cast_ok if no // failure. Return 0 if failure. diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 755df962f5d..46b9e34e6a6 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -64,6 +64,15 @@ void VM_Version::initialize() { if (FLAG_IS_DEFAULT(UseInlineCaches)) { UseInlineCaches = false; } +#ifdef _LP64 + // Single issue niagara1 is slower for CompressedOops + // but niagaras after that it's fine. + if (!is_niagara1_plus()) { + if (FLAG_IS_DEFAULT(UseCompressedOops)) { + FLAG_SET_ERGO(bool, UseCompressedOops, false); + } + } +#endif // _LP64 #ifdef COMPILER2 // Indirect branch is the same cost as direct if (FLAG_IS_DEFAULT(UseJumpTables)) { diff --git a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp index c1ed4b351c5..299ce53e31e 100644 --- a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp @@ -60,7 +60,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { // get receiver klass address npe_addr = __ pc(); - __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_scratch); + __ load_klass(O0, G3_scratch); // set methodOop (in case of interpreted method), and destination address int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); @@ -131,7 +131,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { // get receiver klass (also an implicit null-check) address npe_addr = __ pc(); - __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_klassOop); + __ load_klass(O0, G3_klassOop); __ verify_oop(G3_klassOop); // Push a new window to get some temp registers. This chops the head of all @@ -237,11 +237,16 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) { else { const int slop = 2*BytesPerInstWord; // sethi;add (needed for long offsets) if (is_vtable_stub) { - const int basic = 5*BytesPerInstWord; // ld;ld;ld,jmp,nop + // ld;ld;ld,jmp,nop + const int basic = 5*BytesPerInstWord + + // shift;add for load_klass + (UseCompressedOops ? 2*BytesPerInstWord : 0); return basic + slop; } else { // save, ld, ld, sll, and, add, add, ld, cmp, br, add, ld, add, ld, ld, jmp, restore, sethi, jmpl, restore - const int basic = (20 LP64_ONLY(+ 6)) * BytesPerInstWord; + const int basic = (20 LP64_ONLY(+ 6)) * BytesPerInstWord + + // shift;add for load_klass + (UseCompressedOops ? 2*BytesPerInstWord : 0); return (basic + slop); } } diff --git a/hotspot/src/cpu/x86/vm/assembler_x86_32.cpp b/hotspot/src/cpu/x86/vm/assembler_x86_32.cpp index 533c4db8549..e68bf489309 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86_32.cpp @@ -3405,10 +3405,16 @@ void MacroAssembler::store_check_part_2(Register obj) { assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); CardTableModRefBS* ct = (CardTableModRefBS*)bs; assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); - ExternalAddress cardtable((address)ct->byte_map_base); - Address index(noreg, obj, Address::times_1); - movb(as_Address(ArrayAddress(cardtable, index)), 0); + // The calculation for byte_map_base is as follows: + // byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift); + // So this essentially converts an address to a displacement and + // it will never need to be relocated. On 64bit however the value may be too + // large for a 32bit displacement + + intptr_t disp = (intptr_t) ct->byte_map_base; + Address cardtable(noreg, obj, Address::times_1, disp); + movb(cardtable, 0); } diff --git a/hotspot/src/cpu/x86/vm/assembler_x86_64.cpp b/hotspot/src/cpu/x86/vm/assembler_x86_64.cpp index 23e39151b42..f700fd71b5e 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86_64.cpp @@ -127,6 +127,7 @@ int AbstractAssembler::code_fill_byte() { bool Assembler::reachable(AddressLiteral adr) { int64_t disp; + // None will force a 64bit literal to the code stream. Likely a placeholder // for something that will be patched later and we need to certain it will // always be reachable. @@ -636,7 +637,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) { case 0x8A: // movb r, a case 0x8B: // movl r, a case 0x8F: // popl a - debug_only(has_disp32 = true); + debug_only(has_disp32 = true;) break; case 0x68: // pushq #32 @@ -2891,7 +2892,7 @@ void Assembler::rep_set() { } // scans rcx double words (m64) at [rdi] for occurance of rax -void Assembler::repne_scan() { +void Assembler::repne_scanq() { // REPNE/REPNZ emit_byte(0xF2); // SCASQ @@ -2899,6 +2900,14 @@ void Assembler::repne_scan() { emit_byte(0xAF); } +void Assembler::repne_scanl() { + // REPNE/REPNZ + emit_byte(0xF2); + // SCASL + emit_byte(0xAF); +} + + void Assembler::setb(Condition cc, Register dst) { assert(0 <= cc && cc < 16, "illegal cc"); int encode = prefix_and_encode(dst->encoding(), true); @@ -4141,7 +4150,7 @@ void MacroAssembler::call_VM_base(Register oop_result, if (oop_result->is_valid()) { movq(oop_result, Address(r15_thread, JavaThread::vm_result_offset())); movptr(Address(r15_thread, JavaThread::vm_result_offset()), NULL_WORD); - verify_oop(oop_result); + verify_oop(oop_result, "broken oop in call_VM_base"); } } @@ -4427,9 +4436,32 @@ void MacroAssembler::store_check_part_2(Register obj) { assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); CardTableModRefBS* ct = (CardTableModRefBS*)bs; assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); - ExternalAddress cardtable((address)ct->byte_map_base); - Address index(noreg, obj, Address::times_1); - movb(as_Address(ArrayAddress(cardtable, index)), 0); + + // The calculation for byte_map_base is as follows: + // byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift); + // So this essentially converts an address to a displacement and + // it will never need to be relocated. On 64bit however the value may be too + // large for a 32bit displacement + + intptr_t disp = (intptr_t) ct->byte_map_base; + if (is_simm32(disp)) { + Address cardtable(noreg, obj, Address::times_1, disp); + movb(cardtable, 0); + } else { + // By doing it as an ExternalAddress disp could be converted to a rip-relative + // displacement and done in a single instruction given favorable mapping and + // a smarter version of as_Address. Worst case it is two instructions which + // is no worse off then loading disp into a register and doing as a simple + // Address() as above. + // We can't do as ExternalAddress as the only style since if disp == 0 we'll + // assert since NULL isn't acceptable in a reloci (see 6644928). In any case + // in some cases we'll get a single instruction version. + + ExternalAddress cardtable((address)disp); + Address index(noreg, obj, Address::times_1); + movb(as_Address(ArrayAddress(cardtable, index)), 0); + } + } void MacroAssembler::c2bool(Register x) { @@ -4597,7 +4629,6 @@ void MacroAssembler::verify_oop(Register reg, const char* s) { // pass args on stack, only touch rax pushq(reg); - // avoid using pushptr, as it modifies scratch registers // and our contract is not to modify anything ExternalAddress buffer((address)b); @@ -4658,15 +4689,19 @@ void MacroAssembler::warn(const char* msg) { popq(r12); } +#ifndef PRODUCT +extern "C" void findpc(intptr_t x); +#endif + void MacroAssembler::debug(char* msg, int64_t pc, int64_t regs[]) { // In order to get locks to work, we need to fake a in_VM state if (ShowMessageBoxOnError ) { JavaThread* thread = JavaThread::current(); JavaThreadState saved_state = thread->thread_state(); thread->set_thread_state(_thread_in_vm); - ttyLocker ttyl; #ifndef PRODUCT if (CountBytecodes || TraceBytecodes || StopInterpreterAt) { + ttyLocker ttyl; BytecodeCounter::print(); } #endif @@ -4674,7 +4709,13 @@ void MacroAssembler::debug(char* msg, int64_t pc, int64_t regs[]) { // XXX correct this offset for amd64 // This is the value of eip which points to where verify_oop will return. if (os::message_box(msg, "Execution stopped, print registers?")) { + ttyLocker ttyl; tty->print_cr("rip = 0x%016lx", pc); +#ifndef PRODUCT + tty->cr(); + findpc(pc); + tty->cr(); +#endif tty->print_cr("rax = 0x%016lx", regs[15]); tty->print_cr("rbx = 0x%016lx", regs[12]); tty->print_cr("rcx = 0x%016lx", regs[14]); @@ -4695,6 +4736,7 @@ void MacroAssembler::debug(char* msg, int64_t pc, int64_t regs[]) { } ThreadStateTransition::transition(thread, _thread_in_vm, saved_state); } else { + ttyLocker ttyl; ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", msg); } @@ -4891,7 +4933,7 @@ void MacroAssembler::tlab_refill(Label& retry, movq(Address(top, arrayOopDesc::length_offset_in_bytes()), t1); // set klass to intArrayKlass movptr(t1, ExternalAddress((address) Universe::intArrayKlassObj_addr())); - movq(Address(top, oopDesc::klass_offset_in_bytes()), t1); + store_klass(top, t1); // refill the tlab with an eden allocation bind(do_refill); @@ -4938,7 +4980,6 @@ int MacroAssembler::biased_locking_enter(Register lock_reg, Register obj_reg, Re assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg); assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); - Address klass_addr (obj_reg, oopDesc::klass_offset_in_bytes()); Address saved_mark_addr(lock_reg, 0); if (PrintBiasedLockingStatistics && counters == NULL) @@ -4962,7 +5003,7 @@ int MacroAssembler::biased_locking_enter(Register lock_reg, Register obj_reg, Re jcc(Assembler::notEqual, cas_label); // The bias pattern is present in the object's header. Need to check // whether the bias owner and the epoch are both still current. - movq(tmp_reg, klass_addr); + load_klass(tmp_reg, obj_reg); movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); orq(tmp_reg, r15_thread); xorq(tmp_reg, swap_reg); @@ -5037,7 +5078,7 @@ int MacroAssembler::biased_locking_enter(Register lock_reg, Register obj_reg, Re // // FIXME: due to a lack of registers we currently blow away the age // bits in this situation. Should attempt to preserve them. - movq(tmp_reg, klass_addr); + load_klass(tmp_reg, obj_reg); movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); orq(tmp_reg, r15_thread); if (os::is_MP()) { @@ -5068,7 +5109,7 @@ int MacroAssembler::biased_locking_enter(Register lock_reg, Register obj_reg, Re // // FIXME: due to a lack of registers we currently blow away the age // bits in this situation. Should attempt to preserve them. - movq(tmp_reg, klass_addr); + load_klass(tmp_reg, obj_reg); movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); if (os::is_MP()) { lock(); @@ -5104,6 +5145,138 @@ void MacroAssembler::biased_locking_exit(Register obj_reg, Register temp_reg, La } +void MacroAssembler::load_klass(Register dst, Register src) { + if (UseCompressedOops) { + movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); + decode_heap_oop_not_null(dst); + } else { + movq(dst, Address(src, oopDesc::klass_offset_in_bytes())); + } +} + +void MacroAssembler::store_klass(Register dst, Register src) { + if (UseCompressedOops) { + encode_heap_oop_not_null(src); + // zero the entire klass field first as the gap needs to be zeroed too. + movptr(Address(dst, oopDesc::klass_offset_in_bytes()), NULL_WORD); + movl(Address(dst, oopDesc::klass_offset_in_bytes()), src); + } else { + movq(Address(dst, oopDesc::klass_offset_in_bytes()), src); + } +} + +void MacroAssembler::load_heap_oop(Register dst, Address src) { + if (UseCompressedOops) { + movl(dst, src); + decode_heap_oop(dst); + } else { + movq(dst, src); + } +} + +void MacroAssembler::store_heap_oop(Address dst, Register src) { + if (UseCompressedOops) { + assert(!dst.uses(src), "not enough registers"); + encode_heap_oop(src); + movl(dst, src); + } else { + movq(dst, src); + } +} + +// Algorithm must match oop.inline.hpp encode_heap_oop. +void MacroAssembler::encode_heap_oop(Register r) { + assert (UseCompressedOops, "should be compressed"); +#ifdef ASSERT + Label ok; + pushq(rscratch1); // cmpptr trashes rscratch1 + cmpptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr())); + jcc(Assembler::equal, ok); + stop("MacroAssembler::encode_heap_oop: heap base corrupted?"); + bind(ok); + popq(rscratch1); +#endif + verify_oop(r, "broken oop in encode_heap_oop"); + testq(r, r); + cmovq(Assembler::equal, r, r12_heapbase); + subq(r, r12_heapbase); + shrq(r, LogMinObjAlignmentInBytes); +} + +void MacroAssembler::encode_heap_oop_not_null(Register r) { + assert (UseCompressedOops, "should be compressed"); +#ifdef ASSERT + Label ok; + testq(r, r); + jcc(Assembler::notEqual, ok); + stop("null oop passed to encode_heap_oop_not_null"); + bind(ok); +#endif + verify_oop(r, "broken oop in encode_heap_oop_not_null"); + subq(r, r12_heapbase); + shrq(r, LogMinObjAlignmentInBytes); +} + +void MacroAssembler::encode_heap_oop_not_null(Register dst, Register src) { + assert (UseCompressedOops, "should be compressed"); +#ifdef ASSERT + Label ok; + testq(src, src); + jcc(Assembler::notEqual, ok); + stop("null oop passed to encode_heap_oop_not_null2"); + bind(ok); +#endif + verify_oop(src, "broken oop in encode_heap_oop_not_null2"); + if (dst != src) { + movq(dst, src); + } + subq(dst, r12_heapbase); + shrq(dst, LogMinObjAlignmentInBytes); +} + +void MacroAssembler::decode_heap_oop(Register r) { + assert (UseCompressedOops, "should be compressed"); +#ifdef ASSERT + Label ok; + pushq(rscratch1); + cmpptr(r12_heapbase, + ExternalAddress((address)Universe::heap_base_addr())); + jcc(Assembler::equal, ok); + stop("MacroAssembler::decode_heap_oop: heap base corrupted?"); + bind(ok); + popq(rscratch1); +#endif + + Label done; + shlq(r, LogMinObjAlignmentInBytes); + jccb(Assembler::equal, done); + addq(r, r12_heapbase); +#if 0 + // alternate decoding probably a wash. + testq(r, r); + jccb(Assembler::equal, done); + leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); +#endif + bind(done); + verify_oop(r, "broken oop in decode_heap_oop"); +} + +void MacroAssembler::decode_heap_oop_not_null(Register r) { + assert (UseCompressedOops, "should only be used for compressed headers"); + // Cannot assert, unverified entry point counts instructions (see .ad file) + // vtableStubs also counts instructions in pd_code_size_limit. + assert(Address::times_8 == LogMinObjAlignmentInBytes, "decode alg wrong"); + leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); +} + +void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) { + assert (UseCompressedOops, "should only be used for compressed headers"); + // Cannot assert, unverified entry point counts instructions (see .ad file) + // vtableStubs also counts instructions in pd_code_size_limit. + assert(Address::times_8 == LogMinObjAlignmentInBytes, "decode alg wrong"); + leaq(dst, Address(r12_heapbase, src, Address::times_8, 0)); +} + Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { switch (cond) { // Note some conditions are synonyms for others @@ -5173,3 +5346,9 @@ void MacroAssembler::bang_stack_size(Register size, Register tmp) { movq(Address(tmp, (-i*os::vm_page_size())), size ); } } + +void MacroAssembler::reinit_heapbase() { + if (UseCompressedOops) { + movptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr())); + } +} diff --git a/hotspot/src/cpu/x86/vm/assembler_x86_64.hpp b/hotspot/src/cpu/x86/vm/assembler_x86_64.hpp index 30bca1e5612..9e1ccbfe59d 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86_64.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86_64.hpp @@ -37,7 +37,7 @@ class Argument VALUE_OBJ_CLASS_SPEC { #else n_int_register_parameters_c = 6, // rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...) n_float_register_parameters_c = 8, // xmm0 - xmm7 (c_farg0, c_farg1, ... ) -#endif +#endif // _WIN64 n_int_register_parameters_j = 6, // j_rarg0, j_rarg1, ... n_float_register_parameters_j = 8 // j_farg0, j_farg1, ... }; @@ -77,7 +77,7 @@ REGISTER_DECLARATION(XMMRegister, c_farg5, xmm5); REGISTER_DECLARATION(XMMRegister, c_farg6, xmm6); REGISTER_DECLARATION(XMMRegister, c_farg7, xmm7); -#endif +#endif // _WIN64 // Symbolically name the register arguments used by the Java calling convention. // We have control over the convention for java so we can do what we please. @@ -105,7 +105,7 @@ REGISTER_DECLARATION(Register, j_rarg4, rsi); #else REGISTER_DECLARATION(Register, j_rarg3, c_rarg4); REGISTER_DECLARATION(Register, j_rarg4, c_rarg5); -#endif /* _WIN64 */ +#endif // _WIN64 REGISTER_DECLARATION(Register, j_rarg5, c_rarg0); REGISTER_DECLARATION(XMMRegister, j_farg0, xmm0); @@ -120,7 +120,8 @@ REGISTER_DECLARATION(XMMRegister, j_farg7, xmm7); REGISTER_DECLARATION(Register, rscratch1, r10); // volatile REGISTER_DECLARATION(Register, rscratch2, r11); // volatile -REGISTER_DECLARATION(Register, r15_thread, r15); // callee-saved +REGISTER_DECLARATION(Register, r12_heapbase, r12); // callee-saved +REGISTER_DECLARATION(Register, r15_thread, r15); // callee-saved #endif // _LP64 @@ -785,7 +786,8 @@ class Assembler : public AbstractAssembler { void rep_movl(); void rep_movq(); void rep_set(); - void repne_scan(); + void repne_scanl(); + void repne_scanq(); void setb(Condition cc, Register dst); void clflush(Address adr); @@ -1099,6 +1101,19 @@ class MacroAssembler : public Assembler { void movbool(Address dst, Register src); void testbool(Register dst); + // oop manipulations + void load_klass(Register dst, Register src); + void store_klass(Register dst, Register src); + + void load_heap_oop(Register dst, Address src); + void store_heap_oop(Address dst, Register src); + void encode_heap_oop(Register r); + void decode_heap_oop(Register r); + void encode_heap_oop_not_null(Register r); + void decode_heap_oop_not_null(Register r); + void encode_heap_oop_not_null(Register dst, Register src); + void decode_heap_oop_not_null(Register dst, Register src); + // Stack frame creation/removal void enter(); void leave(); @@ -1250,6 +1265,9 @@ class MacroAssembler : public Assembler { void verify_oop(Register reg, const char* s = "broken oop"); void verify_oop_addr(Address addr, const char * s = "broken oop addr"); + // if heap base register is used - reinit it with the correct value + void reinit_heapbase(); + // only if +VerifyFPU void verify_FPU(int stack_depth, const char* s = "illegal FPU state") {} diff --git a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp index 39fc06190fc..b80a66ed87c 100644 --- a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp @@ -218,7 +218,7 @@ void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2, void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2) { assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, "con_size_in_bytes is not multiple of alignment"); - const int hdr_size_in_bytes = oopDesc::header_size_in_bytes(); + const int hdr_size_in_bytes = instanceOopDesc::base_offset_in_bytes(); initialize_header(obj, klass, noreg, t1, t2); diff --git a/hotspot/src/cpu/x86/vm/disassembler_x86.cpp b/hotspot/src/cpu/x86/vm/disassembler_x86.cpp deleted file mode 100644 index 9e75de3548a..00000000000 --- a/hotspot/src/cpu/x86/vm/disassembler_x86.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - * - */ - -# include "incls/_precompiled.incl" -# include "incls/_disassembler_x86.cpp.incl" - -#ifndef PRODUCT - -void* Disassembler::_library = NULL; -Disassembler::decode_func Disassembler::_decode_instruction = NULL; - -bool Disassembler::load_library() { - if (_library == NULL) { - char buf[1024]; - char ebuf[1024]; - sprintf(buf, "disassembler%s", os::dll_file_extension()); - _library = hpi::dll_load(buf, ebuf, sizeof ebuf); - if (_library != NULL) { - tty->print_cr("Loaded disassembler"); - _decode_instruction = CAST_TO_FN_PTR(Disassembler::decode_func, hpi::dll_lookup(_library, "decode_instruction")); - } - } - return (_library != NULL) && (_decode_instruction != NULL); -} - -class x86_env : public DisassemblerEnv { - private: - nmethod* code; - outputStream* output; - public: - x86_env(nmethod* rcode, outputStream* routput) { - code = rcode; - output = routput; - } - void print_label(intptr_t value); - void print_raw(char* str) { output->print_raw(str); } - void print(char* format, ...); - char* string_for_offset(intptr_t value); - char* string_for_constant(unsigned char* pc, intptr_t value, int is_decimal); -}; - - -void x86_env::print_label(intptr_t value) { - if (!Universe::is_fully_initialized()) { - output->print(INTPTR_FORMAT, value); - return; - } - address adr = (address) value; - if (StubRoutines::contains(adr)) { - StubCodeDesc* desc = StubCodeDesc::desc_for(adr); - const char * desc_name = "unknown stub"; - if (desc != NULL) { - desc_name = desc->name(); - } - output->print("Stub::%s", desc_name); - if (WizardMode) output->print(" " INTPTR_FORMAT, value); - } else { - output->print(INTPTR_FORMAT, value); - } -} - -void x86_env::print(char* format, ...) { - va_list ap; - va_start(ap, format); - output->vprint(format, ap); - va_end(ap); -} - -char* x86_env::string_for_offset(intptr_t value) { - stringStream st; - if (!Universe::is_fully_initialized()) { - st.print(INTX_FORMAT, value); - return st.as_string(); - } - BarrierSet* bs = Universe::heap()->barrier_set(); - BarrierSet::Name bsn = bs->kind(); - if (bs->kind() == BarrierSet::CardTableModRef && - (jbyte*) value == ((CardTableModRefBS*)(bs))->byte_map_base) { - st.print("word_map_base"); - } else { - st.print(INTX_FORMAT, value); - } - return st.as_string(); -} - -char* x86_env::string_for_constant(unsigned char* pc, intptr_t value, int is_decimal) { - stringStream st; - oop obj = NULL; - if (code && ((obj = code->embeddedOop_at(pc)) != NULL)) { - obj->print_value_on(&st); - } else { - if (is_decimal == 1) { - st.print(INTX_FORMAT, value); - } else { - st.print(INTPTR_FORMAT, value); - } - } - return st.as_string(); -} - - - -address Disassembler::decode_instruction(address start, DisassemblerEnv* env) { - return ((decode_func) _decode_instruction)(start, env); -} - - -void Disassembler::decode(CodeBlob* cb, outputStream* st) { - st = st ? st : tty; - st->print_cr("Decoding CodeBlob " INTPTR_FORMAT, cb); - decode(cb->instructions_begin(), cb->instructions_end(), st); -} - - -void Disassembler::decode(u_char* begin, u_char* end, outputStream* st) { - st = st ? st : tty; - - const int show_bytes = false; // for disassembler debugging - - if (!load_library()) { - st->print_cr("Could not load disassembler"); - return; - } - - x86_env env(NULL, st); - unsigned char* p = (unsigned char*) begin; - CodeBlob* cb = CodeCache::find_blob_unsafe(begin); - while (p < (unsigned char*) end) { - if (cb != NULL) { - cb->print_block_comment(st, (intptr_t)(p - cb->instructions_begin())); - } - - unsigned char* p0 = p; - st->print(" " INTPTR_FORMAT ": ", p); - p = decode_instruction(p, &env); - if (show_bytes) { - st->print("\t\t\t"); - while (p0 < p) st->print("%x ", *p0++); - } - st->cr(); - } -} - - -void Disassembler::decode(nmethod* nm, outputStream* st) { - st = st ? st : tty; - - st->print_cr("Decoding compiled method " INTPTR_FORMAT ":", nm); - st->print("Code:"); - st->cr(); - - if (!load_library()) { - st->print_cr("Could not load disassembler"); - return; - } - x86_env env(nm, st); - unsigned char* p = nm->instructions_begin(); - unsigned char* end = nm->instructions_end(); - while (p < end) { - if (p == nm->entry_point()) st->print_cr("[Entry Point]"); - if (p == nm->verified_entry_point()) st->print_cr("[Verified Entry Point]"); - if (p == nm->exception_begin()) st->print_cr("[Exception Handler]"); - if (p == nm->stub_begin()) st->print_cr("[Stub Code]"); - if (p == nm->consts_begin()) st->print_cr("[Constants]"); - nm->print_block_comment(st, (intptr_t)(p - nm->instructions_begin())); - unsigned char* p0 = p; - st->print(" " INTPTR_FORMAT ": ", p); - p = decode_instruction(p, &env); - nm->print_code_comment_on(st, 40, p0, p); - st->cr(); - // Output pc bucket ticks if we have any - address bucket_pc = FlatProfiler::bucket_start_for(p); - if (bucket_pc != NULL && bucket_pc > p0 && bucket_pc <= p) { - int bucket_count = FlatProfiler::bucket_count_for(bucket_pc); - tty->print_cr("[%d]", bucket_count); - } - } -} - -#endif // PRODUCT diff --git a/hotspot/src/cpu/x86/vm/disassembler_x86.hpp b/hotspot/src/cpu/x86/vm/disassembler_x86.hpp index 75da808aedb..bdf7d3500b0 100644 --- a/hotspot/src/cpu/x86/vm/disassembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/disassembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-1999 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,24 +22,10 @@ * */ -// The disassembler prints out intel 386 code annotated -// with Java specific information. + static int pd_instruction_alignment() { + return 1; + } -class Disassembler { -#ifndef PRODUCT - private: - typedef address (*decode_func)(address start, DisassemblerEnv* env); - // points the library. - static void* _library; - // points to the decode function. - static decode_func _decode_instruction; - // tries to load library and return whether it succedded. - static bool load_library(); - // decodes one instruction and return the start of the next instruction. - static address decode_instruction(address start, DisassemblerEnv* env); -#endif - public: - static void decode(CodeBlob *cb, outputStream* st = NULL) PRODUCT_RETURN; - static void decode(nmethod* nm, outputStream* st = NULL) PRODUCT_RETURN; - static void decode(u_char* begin, u_char* end, outputStream* st = NULL) PRODUCT_RETURN; -}; + static const char* pd_cpu_opts() { + return ""; + } diff --git a/hotspot/src/cpu/x86/vm/frame_x86.cpp b/hotspot/src/cpu/x86/vm/frame_x86.cpp index 5fa34595fc8..5019d16c367 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.cpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp @@ -37,39 +37,181 @@ bool frame::safe_for_sender(JavaThread *thread) { address sp = (address)_sp; address fp = (address)_fp; address unextended_sp = (address)_unextended_sp; - bool sp_safe = (sp != NULL && - (sp <= thread->stack_base()) && - (sp >= thread->stack_base() - thread->stack_size())); - bool unextended_sp_safe = (unextended_sp != NULL && - (unextended_sp <= thread->stack_base()) && - (unextended_sp >= thread->stack_base() - thread->stack_size())); - bool fp_safe = (fp != NULL && - (fp <= thread->stack_base()) && - (fp >= thread->stack_base() - thread->stack_size())); - if (sp_safe && unextended_sp_safe && fp_safe) { + // sp must be within the stack + bool sp_safe = (sp <= thread->stack_base()) && + (sp >= thread->stack_base() - thread->stack_size()); + + if (!sp_safe) { + return false; + } + + // unextended sp must be within the stack and above or equal sp + bool unextended_sp_safe = (unextended_sp <= thread->stack_base()) && + (unextended_sp >= sp); + + if (!unextended_sp_safe) { + return false; + } + + // an fp must be within the stack and above (but not equal) sp + bool fp_safe = (fp <= thread->stack_base()) && (fp > sp); + + // We know sp/unextended_sp are safe only fp is questionable here + + // If the current frame is known to the code cache then we can attempt to + // to construct the sender and do some validation of it. This goes a long way + // toward eliminating issues when we get in frame construction code + + if (_cb != NULL ) { + + // First check if frame is complete and tester is reliable // Unfortunately we can only check frame complete for runtime stubs and nmethod // other generic buffer blobs are more problematic so we just assume they are // ok. adapter blobs never have a frame complete and are never ok. - if (_cb != NULL && !_cb->is_frame_complete_at(_pc)) { + + if (!_cb->is_frame_complete_at(_pc)) { if (_cb->is_nmethod() || _cb->is_adapter_blob() || _cb->is_runtime_stub()) { return false; } } + // Entry frame checks + if (is_entry_frame()) { + // an entry frame must have a valid fp. + + if (!fp_safe) return false; + + // Validate the JavaCallWrapper an entry frame must have + + address jcw = (address)entry_frame_call_wrapper(); + + bool jcw_safe = (jcw <= thread->stack_base()) && ( jcw > fp); + + return jcw_safe; + + } + + intptr_t* sender_sp = NULL; + address sender_pc = NULL; + + if (is_interpreted_frame()) { + // fp must be safe + if (!fp_safe) { + return false; + } + + sender_pc = (address) this->fp()[return_addr_offset]; + sender_sp = (intptr_t*) addr_at(sender_sp_offset); + + } else { + // must be some sort of compiled/runtime frame + // fp does not have to be safe (although it could be check for c1?) + + sender_sp = _unextended_sp + _cb->frame_size(); + // On Intel the return_address is always the word on the stack + sender_pc = (address) *(sender_sp-1); + } + + // We must always be able to find a recognizable pc + CodeBlob* sender_blob = CodeCache::find_blob_unsafe(sender_pc); + if (sender_pc == NULL || sender_blob == NULL) { + return false; + } + + + // If the potential sender is the interpreter then we can do some more checking + if (Interpreter::contains(sender_pc)) { + + // ebp is always saved in a recognizable place in any code we generate. However + // only if the sender is interpreted/call_stub (c1 too?) are we certain that the saved ebp + // is really a frame pointer. + + intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset); + bool saved_fp_safe = ((address)saved_fp <= thread->stack_base()) && (saved_fp > sender_sp); + + if (!saved_fp_safe) { + return false; + } + + // construct the potential sender + + frame sender(sender_sp, saved_fp, sender_pc); + + return sender.is_interpreted_frame_valid(thread); + + } + + // Could just be some random pointer within the codeBlob + + if (!sender_blob->instructions_contains(sender_pc)) return false; + + // We should never be able to see an adapter if the current frame is something from code cache + + if ( sender_blob->is_adapter_blob()) { + return false; + } + + // Could be the call_stub + + if (StubRoutines::returns_to_call_stub(sender_pc)) { + intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset); + bool saved_fp_safe = ((address)saved_fp <= thread->stack_base()) && (saved_fp > sender_sp); + + if (!saved_fp_safe) { + return false; + } + + // construct the potential sender + + frame sender(sender_sp, saved_fp, sender_pc); + + // Validate the JavaCallWrapper an entry frame must have + address jcw = (address)sender.entry_frame_call_wrapper(); + + bool jcw_safe = (jcw <= thread->stack_base()) && ( jcw > (address)sender.fp()); + + return jcw_safe; + } + + // If the frame size is 0 something is bad because every nmethod has a non-zero frame size + // because the return address counts against the callee's frame. + + if (sender_blob->frame_size() == 0) { + assert(!sender_blob->is_nmethod(), "should count return address at least"); + return false; + } + + // We should never be able to see anything here except an nmethod. If something in the + // code cache (current frame) is called by an entity within the code cache that entity + // should not be anything but the call stub (already covered), the interpreter (already covered) + // or an nmethod. + + assert(sender_blob->is_nmethod(), "Impossible call chain"); + + // Could put some more validation for the potential non-interpreted sender + // frame we'd create by calling sender if I could think of any. Wait for next crash in forte... + + // One idea is seeing if the sender_pc we have is one that we'd expect to call to current cb + + // We've validated the potential sender that would be created return true; } - // Note: fp == NULL is not really a prerequisite for this to be safe to - // walk for c2. However we've modified the code such that if we get - // a failure with fp != NULL that we then try with FP == NULL. - // This is basically to mimic what a last_frame would look like if - // c2 had generated it. - if (sp_safe && unextended_sp_safe && fp == NULL) { - // frame must be complete if fp == NULL as fp == NULL is only sensible - // if we are looking at a nmethod and frame complete assures us of that. - if (_cb != NULL && _cb->is_frame_complete_at(_pc) && _cb->is_compiled_by_c2()) { - return true; - } + + // Must be native-compiled frame. Since sender will try and use fp to find + // linkages it must be safe + + if (!fp_safe) { + return false; } - return false; + + // Will the pc we fetch be non-zero (which we'll find at the oldest frame) + + if ( (address) this->fp()[return_addr_offset] == NULL) return false; + + + // could try and do some more potential verification of native frame if we could think of some... + + return true; + } @@ -292,7 +434,7 @@ void frame::pd_gc_epilog() { // nothing done here now } -bool frame::is_interpreted_frame_valid() const { +bool frame::is_interpreted_frame_valid(JavaThread* thread) const { // QQQ #ifdef CC_INTERP #else @@ -312,9 +454,45 @@ bool frame::is_interpreted_frame_valid() const { if (fp() <= sp()) { // this attempts to deal with unsigned comparison above return false; } - if (fp() - sp() > 4096) { // stack frames shouldn't be large. + + // do some validation of frame elements + + // first the method + + methodOop m = *interpreter_frame_method_addr(); + + // validate the method we'd find in this potential sender + if (!Universe::heap()->is_valid_method(m)) return false; + + // stack frames shouldn't be much larger than max_stack elements + + if (fp() - sp() > 1024 + m->max_stack()*Interpreter::stackElementSize()) { return false; } + + // validate bci/bcx + + intptr_t bcx = interpreter_frame_bcx(); + if (m->validate_bci_from_bcx(bcx) < 0) { + return false; + } + + // validate constantPoolCacheOop + + constantPoolCacheOop cp = *interpreter_frame_cache_addr(); + + if (cp == NULL || + !Space::is_aligned(cp) || + !Universe::heap()->is_permanent((void*)cp)) return false; + + // validate locals + + address locals = (address) *interpreter_frame_locals_addr(); + + if (locals > thread->stack_base() || locals < (address) fp()) return false; + + // We'd have to be pretty unlucky to be mislead at this point + #endif // CC_INTERP return true; } diff --git a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp index 095fa10163c..153b1002bff 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp @@ -72,15 +72,20 @@ inline frame::frame(intptr_t* sp, intptr_t* fp) { _unextended_sp = sp; _fp = fp; _pc = (address)(sp[-1]); - assert(_pc != NULL, "no pc?"); - _cb = CodeCache::find_blob(_pc); - // In case of native stubs, the pc retreived here might be - // wrong. (the _last_native_pc will have the right value) - // So do not put add any asserts on the _pc here. - // QQQ The above comment is wrong and has been wrong for years. This constructor - // should (and MUST) not be called in that situation. In the native situation - // the pc should be supplied to the constructor. + // Here's a sticky one. This constructor can be called via AsyncGetCallTrace + // when last_Java_sp is non-null but the pc fetched is junk. If we are truly + // unlucky the junk value could be to a zombied method and we'll die on the + // find_blob call. This is also why we can have no asserts on the validity + // of the pc we find here. AsyncGetCallTrace -> pd_get_top_frame_for_signal_handler + // -> pd_last_frame should use a specialized version of pd_last_frame which could + // call a specilaized frame constructor instead of this one. + // Then we could use the assert below. However this assert is of somewhat dubious + // value. + // assert(_pc != NULL, "no pc?"); + + _cb = CodeCache::find_blob(_pc); + _deopt_state = not_deoptimized; if (_cb != NULL && _cb->is_nmethod() && ((nmethod*)_cb)->is_deopt_pc(_pc)) { _pc = (((nmethod*)_cb)->get_original_pc(this)); diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp index 7ba7a83e156..25611881bbc 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp @@ -267,15 +267,29 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, addq(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); // Scan rcx words at [rdi] for occurance of rax // Set NZ/Z based on last compare - repne_scan(); - // Not equal? - jcc(Assembler::notEqual, not_subtype); + + // this part is kind tricky, as values in supers array could be 32 or 64 bit wide + // and we store values in objArrays always encoded, thus we need to encode value + // before repne + if (UseCompressedOops) { + encode_heap_oop(rax); + repne_scanl(); + // Not equal? + jcc(Assembler::notEqual, not_subtype); + // decode heap oop here for movq + decode_heap_oop(rax); + } else { + repne_scanq(); + jcc(Assembler::notEqual, not_subtype); + } // Must be equal but missed in cache. Update cache. movq(Address(Rsub_klass, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()), rax); jmp(ok_is_subtype); bind(not_subtype); + // decode heap oop here for miss + if (UseCompressedOops) decode_heap_oop(rax); profile_typecheck_failed(rcx); // blows rcx } diff --git a/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp index c9709ae854d..251c32065a0 100644 --- a/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/interpreter_x86_64.cpp @@ -375,7 +375,7 @@ address InterpreterGenerator::generate_accessor_entry(void) { __ cmpl(rdx, atos); __ jcc(Assembler::notEqual, notObj); // atos - __ movq(rax, field_address); + __ load_heap_oop(rax, field_address); __ jmp(xreturn_path); __ bind(notObj); diff --git a/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp b/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp index a501aef8fa2..9133af54123 100644 --- a/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp +++ b/hotspot/src/cpu/x86/vm/nativeInst_x86.cpp @@ -472,3 +472,7 @@ address NativeGeneralJump::jump_destination() const { else return addr_at(0) + length + sbyte_at(offset); } + +bool NativeInstruction::is_dtrace_trap() { + return (*(int32_t*)this & 0xff) == 0xcc; +} diff --git a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp index 12b7b0f5486..f4115bcf985 100644 --- a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp +++ b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp @@ -50,6 +50,7 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC { }; bool is_nop() { return ubyte_at(0) == nop_instruction_code; } + bool is_dtrace_trap(); inline bool is_call(); inline bool is_illegal(); inline bool is_return(); diff --git a/hotspot/src/cpu/x86/vm/register_definitions_x86.cpp b/hotspot/src/cpu/x86/vm/register_definitions_x86.cpp index 2379bfb58a7..c5fee6815da 100644 --- a/hotspot/src/cpu/x86/vm/register_definitions_x86.cpp +++ b/hotspot/src/cpu/x86/vm/register_definitions_x86.cpp @@ -106,6 +106,7 @@ REGISTER_DEFINITION(XMMRegister, j_farg7); REGISTER_DEFINITION(Register, rscratch1); REGISTER_DEFINITION(Register, rscratch2); +REGISTER_DEFINITION(Register, r12_heapbase); REGISTER_DEFINITION(Register, r15_thread); #endif // AMD64 diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index 3d30eb251ed..7dc635d0c34 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -1880,6 +1880,379 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, } +#ifdef HAVE_DTRACE_H +// --------------------------------------------------------------------------- +// Generate a dtrace nmethod for a given signature. The method takes arguments +// in the Java compiled code convention, marshals them to the native +// abi and then leaves nops at the position you would expect to call a native +// function. When the probe is enabled the nops are replaced with a trap +// instruction that dtrace inserts and the trace will cause a notification +// to dtrace. +// +// The probes are only able to take primitive types and java/lang/String as +// arguments. No other java types are allowed. Strings are converted to utf8 +// strings so that from dtrace point of view java strings are converted to C +// strings. There is an arbitrary fixed limit on the total space that a method +// can use for converting the strings. (256 chars per string in the signature). +// So any java string larger then this is truncated. + +nmethod *SharedRuntime::generate_dtrace_nmethod( + MacroAssembler *masm, methodHandle method) { + + // generate_dtrace_nmethod is guarded by a mutex so we are sure to + // be single threaded in this method. + assert(AdapterHandlerLibrary_lock->owned_by_self(), "must be"); + + // Fill in the signature array, for the calling-convention call. + int total_args_passed = method->size_of_parameters(); + + BasicType* in_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed); + VMRegPair *in_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed); + + // The signature we are going to use for the trap that dtrace will see + // java/lang/String is converted. We drop "this" and any other object + // is converted to NULL. (A one-slot java/lang/Long object reference + // is converted to a two-slot long, which is why we double the allocation). + BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed * 2); + VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed * 2); + + int i=0; + int total_strings = 0; + int first_arg_to_pass = 0; + int total_c_args = 0; + int box_offset = java_lang_boxing_object::value_offset_in_bytes(); + + if( !method->is_static() ) { // Pass in receiver first + in_sig_bt[i++] = T_OBJECT; + first_arg_to_pass = 1; + } + + // We need to convert the java args to where a native (non-jni) function + // would expect them. To figure out where they go we convert the java + // signature to a C signature. + + SignatureStream ss(method->signature()); + for ( ; !ss.at_return_type(); ss.next()) { + BasicType bt = ss.type(); + in_sig_bt[i++] = bt; // Collect remaining bits of signature + out_sig_bt[total_c_args++] = bt; + if( bt == T_OBJECT) { + symbolOop s = ss.as_symbol_or_null(); + if (s == vmSymbols::java_lang_String()) { + total_strings++; + out_sig_bt[total_c_args-1] = T_ADDRESS; + } else if (s == vmSymbols::java_lang_Boolean() || + s == vmSymbols::java_lang_Character() || + s == vmSymbols::java_lang_Byte() || + s == vmSymbols::java_lang_Short() || + s == vmSymbols::java_lang_Integer() || + s == vmSymbols::java_lang_Float()) { + out_sig_bt[total_c_args-1] = T_INT; + } else if (s == vmSymbols::java_lang_Long() || + s == vmSymbols::java_lang_Double()) { + out_sig_bt[total_c_args-1] = T_LONG; + out_sig_bt[total_c_args++] = T_VOID; + } + } else if ( bt == T_LONG || bt == T_DOUBLE ) { + in_sig_bt[i++] = T_VOID; // Longs & doubles take 2 Java slots + out_sig_bt[total_c_args++] = T_VOID; + } + } + + assert(i==total_args_passed, "validly parsed signature"); + + // Now get the compiled-Java layout as input arguments + int comp_args_on_stack; + comp_args_on_stack = SharedRuntime::java_calling_convention( + in_sig_bt, in_regs, total_args_passed, false); + + // Now figure out where the args must be stored and how much stack space + // they require (neglecting out_preserve_stack_slots). + + int out_arg_slots; + out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); + + // Calculate the total number of stack slots we will need. + + // First count the abi requirement plus all of the outgoing args + int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots; + + // Now space for the string(s) we must convert + + int* string_locs = NEW_RESOURCE_ARRAY(int, total_strings + 1); + for (i = 0; i < total_strings ; i++) { + string_locs[i] = stack_slots; + stack_slots += max_dtrace_string_size / VMRegImpl::stack_slot_size; + } + + // + 2 for return address (which we own) and saved rbp, + + stack_slots += 2; + + // Ok The space we have allocated will look like: + // + // + // FP-> | | + // |---------------------| + // | string[n] | + // |---------------------| <- string_locs[n] + // | string[n-1] | + // |---------------------| <- string_locs[n-1] + // | ... | + // | ... | + // |---------------------| <- string_locs[1] + // | string[0] | + // |---------------------| <- string_locs[0] + // | outbound memory | + // | based arguments | + // | | + // |---------------------| + // | | + // SP-> | out_preserved_slots | + // + // + + // Now compute actual number of stack words we need rounding to make + // stack properly aligned. + stack_slots = round_to(stack_slots, 2 * VMRegImpl::slots_per_word); + + int stack_size = stack_slots * VMRegImpl::stack_slot_size; + + intptr_t start = (intptr_t)__ pc(); + + // First thing make an ic check to see if we should even be here + + // We are free to use all registers as temps without saving them and + // restoring them except rbp. rbp, is the only callee save register + // as far as the interpreter and the compiler(s) are concerned. + + const Register ic_reg = rax; + const Register receiver = rcx; + Label hit; + Label exception_pending; + + + __ verify_oop(receiver); + __ cmpl(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes())); + __ jcc(Assembler::equal, hit); + + __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + + // verified entry must be aligned for code patching. + // and the first 5 bytes must be in the same cache line + // if we align at 8 then we will be sure 5 bytes are in the same line + __ align(8); + + __ bind(hit); + + int vep_offset = ((intptr_t)__ pc()) - start; + + + // The instruction at the verified entry point must be 5 bytes or longer + // because it can be patched on the fly by make_non_entrant. The stack bang + // instruction fits that requirement. + + // Generate stack overflow check + + + if (UseStackBanging) { + if (stack_size <= StackShadowPages*os::vm_page_size()) { + __ bang_stack_with_offset(StackShadowPages*os::vm_page_size()); + } else { + __ movl(rax, stack_size); + __ bang_stack_size(rax, rbx); + } + } else { + // need a 5 byte instruction to allow MT safe patching to non-entrant + __ fat_nop(); + } + + assert(((int)__ pc() - start - vep_offset) >= 5, + "valid size for make_non_entrant"); + + // Generate a new frame for the wrapper. + __ enter(); + + // -2 because return address is already present and so is saved rbp, + if (stack_size - 2*wordSize != 0) { + __ subl(rsp, stack_size - 2*wordSize); + } + + // Frame is now completed as far a size and linkage. + + int frame_complete = ((intptr_t)__ pc()) - start; + + // First thing we do store all the args as if we are doing the call. + // Since the C calling convention is stack based that ensures that + // all the Java register args are stored before we need to convert any + // string we might have. + + int sid = 0; + int c_arg, j_arg; + int string_reg = 0; + + for (j_arg = first_arg_to_pass, c_arg = 0 ; + j_arg < total_args_passed ; j_arg++, c_arg++ ) { + + VMRegPair src = in_regs[j_arg]; + VMRegPair dst = out_regs[c_arg]; + assert(dst.first()->is_stack() || in_sig_bt[j_arg] == T_VOID, + "stack based abi assumed"); + + switch (in_sig_bt[j_arg]) { + + case T_ARRAY: + case T_OBJECT: + if (out_sig_bt[c_arg] == T_ADDRESS) { + // Any register based arg for a java string after the first + // will be destroyed by the call to get_utf so we store + // the original value in the location the utf string address + // will eventually be stored. + if (src.first()->is_reg()) { + if (string_reg++ != 0) { + simple_move32(masm, src, dst); + } + } + } else if (out_sig_bt[c_arg] == T_INT || out_sig_bt[c_arg] == T_LONG) { + // need to unbox a one-word value + Register in_reg = rax; + if ( src.first()->is_reg() ) { + in_reg = src.first()->as_Register(); + } else { + simple_move32(masm, src, in_reg->as_VMReg()); + } + Label skipUnbox; + __ movl(Address(rsp, reg2offset_out(dst.first())), NULL_WORD); + if ( out_sig_bt[c_arg] == T_LONG ) { + __ movl(Address(rsp, reg2offset_out(dst.second())), NULL_WORD); + } + __ testl(in_reg, in_reg); + __ jcc(Assembler::zero, skipUnbox); + assert(dst.first()->is_stack() && + (!dst.second()->is_valid() || dst.second()->is_stack()), + "value(s) must go into stack slots"); + if ( out_sig_bt[c_arg] == T_LONG ) { + __ movl(rbx, Address(in_reg, + box_offset + VMRegImpl::stack_slot_size)); + __ movl(Address(rsp, reg2offset_out(dst.second())), rbx); + } + __ movl(in_reg, Address(in_reg, box_offset)); + __ movl(Address(rsp, reg2offset_out(dst.first())), in_reg); + __ bind(skipUnbox); + } else { + // Convert the arg to NULL + __ movl(Address(rsp, reg2offset_out(dst.first())), NULL_WORD); + } + if (out_sig_bt[c_arg] == T_LONG) { + assert(out_sig_bt[c_arg+1] == T_VOID, "must be"); + ++c_arg; // Move over the T_VOID To keep the loop indices in sync + } + break; + + case T_VOID: + break; + + case T_FLOAT: + float_move(masm, src, dst); + break; + + case T_DOUBLE: + assert( j_arg + 1 < total_args_passed && + in_sig_bt[j_arg + 1] == T_VOID, "bad arg list"); + double_move(masm, src, dst); + break; + + case T_LONG : + long_move(masm, src, dst); + break; + + case T_ADDRESS: assert(false, "found T_ADDRESS in java args"); + + default: + simple_move32(masm, src, dst); + } + } + + // Now we must convert any string we have to utf8 + // + + for (sid = 0, j_arg = first_arg_to_pass, c_arg = 0 ; + sid < total_strings ; j_arg++, c_arg++ ) { + + if (out_sig_bt[c_arg] == T_ADDRESS) { + + Address utf8_addr = Address( + rsp, string_locs[sid++] * VMRegImpl::stack_slot_size); + __ leal(rax, utf8_addr); + + // The first string we find might still be in the original java arg + // register + VMReg orig_loc = in_regs[j_arg].first(); + Register string_oop; + + // This is where the argument will eventually reside + Address dest = Address(rsp, reg2offset_out(out_regs[c_arg].first())); + + if (sid == 1 && orig_loc->is_reg()) { + string_oop = orig_loc->as_Register(); + assert(string_oop != rax, "smashed arg"); + } else { + + if (orig_loc->is_reg()) { + // Get the copy of the jls object + __ movl(rcx, dest); + } else { + // arg is still in the original location + __ movl(rcx, Address(rbp, reg2offset_in(orig_loc))); + } + string_oop = rcx; + + } + Label nullString; + __ movl(dest, NULL_WORD); + __ testl(string_oop, string_oop); + __ jcc(Assembler::zero, nullString); + + // Now we can store the address of the utf string as the argument + __ movl(dest, rax); + + // And do the conversion + __ call_VM_leaf(CAST_FROM_FN_PTR( + address, SharedRuntime::get_utf), string_oop, rax); + __ bind(nullString); + } + + if (in_sig_bt[j_arg] == T_OBJECT && out_sig_bt[c_arg] == T_LONG) { + assert(out_sig_bt[c_arg+1] == T_VOID, "must be"); + ++c_arg; // Move over the T_VOID To keep the loop indices in sync + } + } + + + // Ok now we are done. Need to place the nop that dtrace wants in order to + // patch in the trap + + int patch_offset = ((intptr_t)__ pc()) - start; + + __ nop(); + + + // Return + + __ leave(); + __ ret(0); + + __ flush(); + + nmethod *nm = nmethod::new_dtrace_nmethod( + method, masm->code(), vep_offset, patch_offset, frame_complete, + stack_slots / VMRegImpl::slots_per_word); + return nm; + +} + +#endif // HAVE_DTRACE_H + // this function returns the adjust size (in number of words) to a c2i adapter // activation for use during deoptimization int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals ) { diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index 7b0bf3e5458..8fa458680d3 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -789,7 +789,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm { __ verify_oop(holder); - __ movq(temp, Address(receiver, oopDesc::klass_offset_in_bytes())); + __ load_klass(temp, receiver); __ verify_oop(temp); __ cmpq(temp, Address(holder, compiledICHolderOopDesc::holder_klass_offset())); @@ -1297,21 +1297,26 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, const Register ic_reg = rax; const Register receiver = j_rarg0; + const Register tmp = rdx; Label ok; Label exception_pending; __ verify_oop(receiver); - __ cmpq(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes())); + __ pushq(tmp); // spill (any other registers free here???) + __ load_klass(tmp, receiver); + __ cmpq(ic_reg, tmp); __ jcc(Assembler::equal, ok); + __ popq(tmp); __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + __ bind(ok); + __ popq(tmp); + // Verified entry point must be aligned __ align(8); - __ bind(ok); - int vep_offset = ((intptr_t)__ pc()) - start; // The instruction at the verified entry point must be 5 bytes or longer @@ -1663,6 +1668,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, __ andq(rsp, -16); // align stack as required by ABI __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); __ movq(rsp, r12); // restore sp + __ reinit_heapbase(); // Restore any method result value restore_native_result(masm, ret_type, stack_slots); __ bind(Continue); @@ -1725,7 +1731,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, __ bind(done); } - { SkipIfEqual skip(masm, &DTraceMethodProbes, false); save_native_result(masm, ret_type, stack_slots); @@ -1829,6 +1834,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C))); __ movq(rsp, r12); // restore sp + __ reinit_heapbase(); #ifdef ASSERT { Label L; @@ -1859,6 +1865,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, __ andq(rsp, -16); // align stack as required by ABI __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages))); __ movq(rsp, r12); // restore sp + __ reinit_heapbase(); restore_native_result(masm, ret_type, stack_slots); // and continue __ jmp(reguard_done); @@ -1879,6 +1886,627 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, } +#ifdef HAVE_DTRACE_H +// --------------------------------------------------------------------------- +// Generate a dtrace nmethod for a given signature. The method takes arguments +// in the Java compiled code convention, marshals them to the native +// abi and then leaves nops at the position you would expect to call a native +// function. When the probe is enabled the nops are replaced with a trap +// instruction that dtrace inserts and the trace will cause a notification +// to dtrace. +// +// The probes are only able to take primitive types and java/lang/String as +// arguments. No other java types are allowed. Strings are converted to utf8 +// strings so that from dtrace point of view java strings are converted to C +// strings. There is an arbitrary fixed limit on the total space that a method +// can use for converting the strings. (256 chars per string in the signature). +// So any java string larger then this is truncated. + +static int fp_offset[ConcreteRegisterImpl::number_of_registers] = { 0 }; +static bool offsets_initialized = false; + + +nmethod *SharedRuntime::generate_dtrace_nmethod(MacroAssembler *masm, + methodHandle method) { + + + // generate_dtrace_nmethod is guarded by a mutex so we are sure to + // be single threaded in this method. + assert(AdapterHandlerLibrary_lock->owned_by_self(), "must be"); + + if (!offsets_initialized) { + fp_offset[c_rarg0->as_VMReg()->value()] = -1 * wordSize; + fp_offset[c_rarg1->as_VMReg()->value()] = -2 * wordSize; + fp_offset[c_rarg2->as_VMReg()->value()] = -3 * wordSize; + fp_offset[c_rarg3->as_VMReg()->value()] = -4 * wordSize; + fp_offset[c_rarg4->as_VMReg()->value()] = -5 * wordSize; + fp_offset[c_rarg5->as_VMReg()->value()] = -6 * wordSize; + + fp_offset[c_farg0->as_VMReg()->value()] = -7 * wordSize; + fp_offset[c_farg1->as_VMReg()->value()] = -8 * wordSize; + fp_offset[c_farg2->as_VMReg()->value()] = -9 * wordSize; + fp_offset[c_farg3->as_VMReg()->value()] = -10 * wordSize; + fp_offset[c_farg4->as_VMReg()->value()] = -11 * wordSize; + fp_offset[c_farg5->as_VMReg()->value()] = -12 * wordSize; + fp_offset[c_farg6->as_VMReg()->value()] = -13 * wordSize; + fp_offset[c_farg7->as_VMReg()->value()] = -14 * wordSize; + + offsets_initialized = true; + } + // Fill in the signature array, for the calling-convention call. + int total_args_passed = method->size_of_parameters(); + + BasicType* in_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed); + VMRegPair *in_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed); + + // The signature we are going to use for the trap that dtrace will see + // java/lang/String is converted. We drop "this" and any other object + // is converted to NULL. (A one-slot java/lang/Long object reference + // is converted to a two-slot long, which is why we double the allocation). + BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed * 2); + VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed * 2); + + int i=0; + int total_strings = 0; + int first_arg_to_pass = 0; + int total_c_args = 0; + int box_offset = java_lang_boxing_object::value_offset_in_bytes(); + + // Skip the receiver as dtrace doesn't want to see it + if( !method->is_static() ) { + in_sig_bt[i++] = T_OBJECT; + first_arg_to_pass = 1; + } + + // We need to convert the java args to where a native (non-jni) function + // would expect them. To figure out where they go we convert the java + // signature to a C signature. + + SignatureStream ss(method->signature()); + for ( ; !ss.at_return_type(); ss.next()) { + BasicType bt = ss.type(); + in_sig_bt[i++] = bt; // Collect remaining bits of signature + out_sig_bt[total_c_args++] = bt; + if( bt == T_OBJECT) { + symbolOop s = ss.as_symbol_or_null(); + if (s == vmSymbols::java_lang_String()) { + total_strings++; + out_sig_bt[total_c_args-1] = T_ADDRESS; + } else if (s == vmSymbols::java_lang_Boolean() || + s == vmSymbols::java_lang_Character() || + s == vmSymbols::java_lang_Byte() || + s == vmSymbols::java_lang_Short() || + s == vmSymbols::java_lang_Integer() || + s == vmSymbols::java_lang_Float()) { + out_sig_bt[total_c_args-1] = T_INT; + } else if (s == vmSymbols::java_lang_Long() || + s == vmSymbols::java_lang_Double()) { + out_sig_bt[total_c_args-1] = T_LONG; + out_sig_bt[total_c_args++] = T_VOID; + } + } else if ( bt == T_LONG || bt == T_DOUBLE ) { + in_sig_bt[i++] = T_VOID; // Longs & doubles take 2 Java slots + // We convert double to long + out_sig_bt[total_c_args-1] = T_LONG; + out_sig_bt[total_c_args++] = T_VOID; + } else if ( bt == T_FLOAT) { + // We convert float to int + out_sig_bt[total_c_args-1] = T_INT; + } + } + + assert(i==total_args_passed, "validly parsed signature"); + + // Now get the compiled-Java layout as input arguments + int comp_args_on_stack; + comp_args_on_stack = SharedRuntime::java_calling_convention( + in_sig_bt, in_regs, total_args_passed, false); + + // Now figure out where the args must be stored and how much stack space + // they require (neglecting out_preserve_stack_slots but space for storing + // the 1st six register arguments). It's weird see int_stk_helper. + + int out_arg_slots; + out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); + + // Calculate the total number of stack slots we will need. + + // First count the abi requirement plus all of the outgoing args + int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots; + + // Now space for the string(s) we must convert + int* string_locs = NEW_RESOURCE_ARRAY(int, total_strings + 1); + for (i = 0; i < total_strings ; i++) { + string_locs[i] = stack_slots; + stack_slots += max_dtrace_string_size / VMRegImpl::stack_slot_size; + } + + // Plus the temps we might need to juggle register args + // regs take two slots each + stack_slots += (Argument::n_int_register_parameters_c + + Argument::n_float_register_parameters_c) * 2; + + + // + 4 for return address (which we own) and saved rbp, + + stack_slots += 4; + + // Ok The space we have allocated will look like: + // + // + // FP-> | | + // |---------------------| + // | string[n] | + // |---------------------| <- string_locs[n] + // | string[n-1] | + // |---------------------| <- string_locs[n-1] + // | ... | + // | ... | + // |---------------------| <- string_locs[1] + // | string[0] | + // |---------------------| <- string_locs[0] + // | outbound memory | + // | based arguments | + // | | + // |---------------------| + // | | + // SP-> | out_preserved_slots | + // + // + + // Now compute actual number of stack words we need rounding to make + // stack properly aligned. + stack_slots = round_to(stack_slots, 4 * VMRegImpl::slots_per_word); + + int stack_size = stack_slots * VMRegImpl::stack_slot_size; + + intptr_t start = (intptr_t)__ pc(); + + // First thing make an ic check to see if we should even be here + + // We are free to use all registers as temps without saving them and + // restoring them except rbp. rbp, is the only callee save register + // as far as the interpreter and the compiler(s) are concerned. + + const Register ic_reg = rax; + const Register receiver = rcx; + Label hit; + Label exception_pending; + + + __ verify_oop(receiver); + __ cmpl(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes())); + __ jcc(Assembler::equal, hit); + + __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + + // verified entry must be aligned for code patching. + // and the first 5 bytes must be in the same cache line + // if we align at 8 then we will be sure 5 bytes are in the same line + __ align(8); + + __ bind(hit); + + int vep_offset = ((intptr_t)__ pc()) - start; + + + // The instruction at the verified entry point must be 5 bytes or longer + // because it can be patched on the fly by make_non_entrant. The stack bang + // instruction fits that requirement. + + // Generate stack overflow check + + if (UseStackBanging) { + if (stack_size <= StackShadowPages*os::vm_page_size()) { + __ bang_stack_with_offset(StackShadowPages*os::vm_page_size()); + } else { + __ movl(rax, stack_size); + __ bang_stack_size(rax, rbx); + } + } else { + // need a 5 byte instruction to allow MT safe patching to non-entrant + __ fat_nop(); + } + + assert(((uintptr_t)__ pc() - start - vep_offset) >= 5, + "valid size for make_non_entrant"); + + // Generate a new frame for the wrapper. + __ enter(); + + // -4 because return address is already present and so is saved rbp, + if (stack_size - 2*wordSize != 0) { + __ subq(rsp, stack_size - 2*wordSize); + } + + // Frame is now completed as far a size and linkage. + + int frame_complete = ((intptr_t)__ pc()) - start; + + int c_arg, j_arg; + + // State of input register args + + bool live[ConcreteRegisterImpl::number_of_registers]; + + live[j_rarg0->as_VMReg()->value()] = false; + live[j_rarg1->as_VMReg()->value()] = false; + live[j_rarg2->as_VMReg()->value()] = false; + live[j_rarg3->as_VMReg()->value()] = false; + live[j_rarg4->as_VMReg()->value()] = false; + live[j_rarg5->as_VMReg()->value()] = false; + + live[j_farg0->as_VMReg()->value()] = false; + live[j_farg1->as_VMReg()->value()] = false; + live[j_farg2->as_VMReg()->value()] = false; + live[j_farg3->as_VMReg()->value()] = false; + live[j_farg4->as_VMReg()->value()] = false; + live[j_farg5->as_VMReg()->value()] = false; + live[j_farg6->as_VMReg()->value()] = false; + live[j_farg7->as_VMReg()->value()] = false; + + + bool rax_is_zero = false; + + // All args (except strings) destined for the stack are moved first + for (j_arg = first_arg_to_pass, c_arg = 0 ; + j_arg < total_args_passed ; j_arg++, c_arg++ ) { + VMRegPair src = in_regs[j_arg]; + VMRegPair dst = out_regs[c_arg]; + + // Get the real reg value or a dummy (rsp) + + int src_reg = src.first()->is_reg() ? + src.first()->value() : + rsp->as_VMReg()->value(); + + bool useless = in_sig_bt[j_arg] == T_ARRAY || + (in_sig_bt[j_arg] == T_OBJECT && + out_sig_bt[c_arg] != T_INT && + out_sig_bt[c_arg] != T_ADDRESS && + out_sig_bt[c_arg] != T_LONG); + + live[src_reg] = !useless; + + if (dst.first()->is_stack()) { + + // Even though a string arg in a register is still live after this loop + // after the string conversion loop (next) it will be dead so we take + // advantage of that now for simpler code to manage live. + + live[src_reg] = false; + switch (in_sig_bt[j_arg]) { + + case T_ARRAY: + case T_OBJECT: + { + Address stack_dst(rsp, reg2offset_out(dst.first())); + + if (out_sig_bt[c_arg] == T_INT || out_sig_bt[c_arg] == T_LONG) { + // need to unbox a one-word value + Register in_reg = rax; + if ( src.first()->is_reg() ) { + in_reg = src.first()->as_Register(); + } else { + __ movq(rax, Address(rbp, reg2offset_in(src.first()))); + rax_is_zero = false; + } + Label skipUnbox; + __ movptr(Address(rsp, reg2offset_out(dst.first())), + (int32_t)NULL_WORD); + __ testq(in_reg, in_reg); + __ jcc(Assembler::zero, skipUnbox); + + Address src1(in_reg, box_offset); + if ( out_sig_bt[c_arg] == T_LONG ) { + __ movq(in_reg, src1); + __ movq(stack_dst, in_reg); + assert(out_sig_bt[c_arg+1] == T_VOID, "must be"); + ++c_arg; // skip over T_VOID to keep the loop indices in sync + } else { + __ movl(in_reg, src1); + __ movl(stack_dst, in_reg); + } + + __ bind(skipUnbox); + } else if (out_sig_bt[c_arg] != T_ADDRESS) { + // Convert the arg to NULL + if (!rax_is_zero) { + __ xorq(rax, rax); + rax_is_zero = true; + } + __ movq(stack_dst, rax); + } + } + break; + + case T_VOID: + break; + + case T_FLOAT: + // This does the right thing since we know it is destined for the + // stack + float_move(masm, src, dst); + break; + + case T_DOUBLE: + // This does the right thing since we know it is destined for the + // stack + double_move(masm, src, dst); + break; + + case T_LONG : + long_move(masm, src, dst); + break; + + case T_ADDRESS: assert(false, "found T_ADDRESS in java args"); + + default: + move32_64(masm, src, dst); + } + } + + } + + // If we have any strings we must store any register based arg to the stack + // This includes any still live xmm registers too. + + int sid = 0; + + if (total_strings > 0 ) { + for (j_arg = first_arg_to_pass, c_arg = 0 ; + j_arg < total_args_passed ; j_arg++, c_arg++ ) { + VMRegPair src = in_regs[j_arg]; + VMRegPair dst = out_regs[c_arg]; + + if (src.first()->is_reg()) { + Address src_tmp(rbp, fp_offset[src.first()->value()]); + + // string oops were left untouched by the previous loop even if the + // eventual (converted) arg is destined for the stack so park them + // away now (except for first) + + if (out_sig_bt[c_arg] == T_ADDRESS) { + Address utf8_addr = Address( + rsp, string_locs[sid++] * VMRegImpl::stack_slot_size); + if (sid != 1) { + // The first string arg won't be killed until after the utf8 + // conversion + __ movq(utf8_addr, src.first()->as_Register()); + } + } else if (dst.first()->is_reg()) { + if (in_sig_bt[j_arg] == T_FLOAT || in_sig_bt[j_arg] == T_DOUBLE) { + + // Convert the xmm register to an int and store it in the reserved + // location for the eventual c register arg + XMMRegister f = src.first()->as_XMMRegister(); + if (in_sig_bt[j_arg] == T_FLOAT) { + __ movflt(src_tmp, f); + } else { + __ movdbl(src_tmp, f); + } + } else { + // If the arg is an oop type we don't support don't bother to store + // it remember string was handled above. + bool useless = in_sig_bt[j_arg] == T_ARRAY || + (in_sig_bt[j_arg] == T_OBJECT && + out_sig_bt[c_arg] != T_INT && + out_sig_bt[c_arg] != T_LONG); + + if (!useless) { + __ movq(src_tmp, src.first()->as_Register()); + } + } + } + } + if (in_sig_bt[j_arg] == T_OBJECT && out_sig_bt[c_arg] == T_LONG) { + assert(out_sig_bt[c_arg+1] == T_VOID, "must be"); + ++c_arg; // skip over T_VOID to keep the loop indices in sync + } + } + + // Now that the volatile registers are safe, convert all the strings + sid = 0; + + for (j_arg = first_arg_to_pass, c_arg = 0 ; + j_arg < total_args_passed ; j_arg++, c_arg++ ) { + if (out_sig_bt[c_arg] == T_ADDRESS) { + // It's a string + Address utf8_addr = Address( + rsp, string_locs[sid++] * VMRegImpl::stack_slot_size); + // The first string we find might still be in the original java arg + // register + + VMReg src = in_regs[j_arg].first(); + + // We will need to eventually save the final argument to the trap + // in the von-volatile location dedicated to src. This is the offset + // from fp we will use. + int src_off = src->is_reg() ? + fp_offset[src->value()] : reg2offset_in(src); + + // This is where the argument will eventually reside + VMRegPair dst = out_regs[c_arg]; + + if (src->is_reg()) { + if (sid == 1) { + __ movq(c_rarg0, src->as_Register()); + } else { + __ movq(c_rarg0, utf8_addr); + } + } else { + // arg is still in the original location + __ movq(c_rarg0, Address(rbp, reg2offset_in(src))); + } + Label done, convert; + + // see if the oop is NULL + __ testq(c_rarg0, c_rarg0); + __ jcc(Assembler::notEqual, convert); + + if (dst.first()->is_reg()) { + // Save the ptr to utf string in the origina src loc or the tmp + // dedicated to it + __ movq(Address(rbp, src_off), c_rarg0); + } else { + __ movq(Address(rsp, reg2offset_out(dst.first())), c_rarg0); + } + __ jmp(done); + + __ bind(convert); + + __ lea(c_rarg1, utf8_addr); + if (dst.first()->is_reg()) { + __ movq(Address(rbp, src_off), c_rarg1); + } else { + __ movq(Address(rsp, reg2offset_out(dst.first())), c_rarg1); + } + // And do the conversion + __ call(RuntimeAddress( + CAST_FROM_FN_PTR(address, SharedRuntime::get_utf))); + + __ bind(done); + } + if (in_sig_bt[j_arg] == T_OBJECT && out_sig_bt[c_arg] == T_LONG) { + assert(out_sig_bt[c_arg+1] == T_VOID, "must be"); + ++c_arg; // skip over T_VOID to keep the loop indices in sync + } + } + // The get_utf call killed all the c_arg registers + live[c_rarg0->as_VMReg()->value()] = false; + live[c_rarg1->as_VMReg()->value()] = false; + live[c_rarg2->as_VMReg()->value()] = false; + live[c_rarg3->as_VMReg()->value()] = false; + live[c_rarg4->as_VMReg()->value()] = false; + live[c_rarg5->as_VMReg()->value()] = false; + + live[c_farg0->as_VMReg()->value()] = false; + live[c_farg1->as_VMReg()->value()] = false; + live[c_farg2->as_VMReg()->value()] = false; + live[c_farg3->as_VMReg()->value()] = false; + live[c_farg4->as_VMReg()->value()] = false; + live[c_farg5->as_VMReg()->value()] = false; + live[c_farg6->as_VMReg()->value()] = false; + live[c_farg7->as_VMReg()->value()] = false; + } + + // Now we can finally move the register args to their desired locations + + rax_is_zero = false; + + for (j_arg = first_arg_to_pass, c_arg = 0 ; + j_arg < total_args_passed ; j_arg++, c_arg++ ) { + + VMRegPair src = in_regs[j_arg]; + VMRegPair dst = out_regs[c_arg]; + + // Only need to look for args destined for the interger registers (since we + // convert float/double args to look like int/long outbound) + if (dst.first()->is_reg()) { + Register r = dst.first()->as_Register(); + + // Check if the java arg is unsupported and thereofre useless + bool useless = in_sig_bt[j_arg] == T_ARRAY || + (in_sig_bt[j_arg] == T_OBJECT && + out_sig_bt[c_arg] != T_INT && + out_sig_bt[c_arg] != T_ADDRESS && + out_sig_bt[c_arg] != T_LONG); + + + // If we're going to kill an existing arg save it first + if (live[dst.first()->value()]) { + // you can't kill yourself + if (src.first() != dst.first()) { + __ movq(Address(rbp, fp_offset[dst.first()->value()]), r); + } + } + if (src.first()->is_reg()) { + if (live[src.first()->value()] ) { + if (in_sig_bt[j_arg] == T_FLOAT) { + __ movdl(r, src.first()->as_XMMRegister()); + } else if (in_sig_bt[j_arg] == T_DOUBLE) { + __ movdq(r, src.first()->as_XMMRegister()); + } else if (r != src.first()->as_Register()) { + if (!useless) { + __ movq(r, src.first()->as_Register()); + } + } + } else { + // If the arg is an oop type we don't support don't bother to store + // it + if (!useless) { + if (in_sig_bt[j_arg] == T_DOUBLE || + in_sig_bt[j_arg] == T_LONG || + in_sig_bt[j_arg] == T_OBJECT ) { + __ movq(r, Address(rbp, fp_offset[src.first()->value()])); + } else { + __ movl(r, Address(rbp, fp_offset[src.first()->value()])); + } + } + } + live[src.first()->value()] = false; + } else if (!useless) { + // full sized move even for int should be ok + __ movq(r, Address(rbp, reg2offset_in(src.first()))); + } + + // At this point r has the original java arg in the final location + // (assuming it wasn't useless). If the java arg was an oop + // we have a bit more to do + + if (in_sig_bt[j_arg] == T_ARRAY || in_sig_bt[j_arg] == T_OBJECT ) { + if (out_sig_bt[c_arg] == T_INT || out_sig_bt[c_arg] == T_LONG) { + // need to unbox a one-word value + Label skip; + __ testq(r, r); + __ jcc(Assembler::equal, skip); + Address src1(r, box_offset); + if ( out_sig_bt[c_arg] == T_LONG ) { + __ movq(r, src1); + } else { + __ movl(r, src1); + } + __ bind(skip); + + } else if (out_sig_bt[c_arg] != T_ADDRESS) { + // Convert the arg to NULL + __ xorq(r, r); + } + } + + // dst can longer be holding an input value + live[dst.first()->value()] = false; + } + if (in_sig_bt[j_arg] == T_OBJECT && out_sig_bt[c_arg] == T_LONG) { + assert(out_sig_bt[c_arg+1] == T_VOID, "must be"); + ++c_arg; // skip over T_VOID to keep the loop indices in sync + } + } + + + // Ok now we are done. Need to place the nop that dtrace wants in order to + // patch in the trap + int patch_offset = ((intptr_t)__ pc()) - start; + + __ nop(); + + + // Return + + __ leave(); + __ ret(0); + + __ flush(); + + nmethod *nm = nmethod::new_dtrace_nmethod( + method, masm->code(), vep_offset, patch_offset, frame_complete, + stack_slots / VMRegImpl::slots_per_word); + return nm; + +} + +#endif // HAVE_DTRACE_H + // this function returns the adjust size (in number of words) to a c2i adapter // activation for use during deoptimization int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals ) { @@ -1941,9 +2569,8 @@ void SharedRuntime::generate_deopt_blob() { map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); // Normal deoptimization. Save exec mode for unpack_frames. - __ movl(r12, Deoptimization::Unpack_deopt); // callee-saved + __ movl(r14, Deoptimization::Unpack_deopt); // callee-saved __ jmp(cont); - int exception_offset = __ pc() - start; // Prolog for exception case @@ -1955,7 +2582,7 @@ void SharedRuntime::generate_deopt_blob() { map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); // Deopt during an exception. Save exec mode for unpack_frames. - __ movl(r12, Deoptimization::Unpack_exception); // callee-saved + __ movl(r14, Deoptimization::Unpack_exception); // callee-saved __ bind(cont); @@ -2088,7 +2715,7 @@ void SharedRuntime::generate_deopt_blob() { __ set_last_Java_frame(noreg, rbp, NULL); __ movq(c_rarg0, r15_thread); - __ movl(c_rarg1, r12); // second arg: exec_mode + __ movl(c_rarg1, r14); // second arg: exec_mode __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames))); // Set an oopmap for the call site diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 720222b31e9..5cfbc09fe74 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -30,6 +30,7 @@ // see the comment in stubRoutines.hpp #define __ _masm-> +#define TIMES_OOP (UseCompressedOops ? Address::times_4 : Address::times_8) #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ @@ -252,6 +253,7 @@ class StubGenerator: public StubCodeGenerator { // Load up thread register __ movq(r15_thread, thread); + __ reinit_heapbase(); #ifdef ASSERT // make sure we have no pending exceptions @@ -911,11 +913,12 @@ class StubGenerator: public StubCodeGenerator { // Stack after saving c_rarg3: // [tos + 0]: saved c_rarg3 // [tos + 1]: saved c_rarg2 - // [tos + 2]: saved flags - // [tos + 3]: return address - // * [tos + 4]: error message (char*) - // * [tos + 5]: object to verify (oop) - // * [tos + 6]: saved rax - saved by caller and bashed + // [tos + 2]: saved r12 (several TemplateTable methods use it) + // [tos + 3]: saved flags + // [tos + 4]: return address + // * [tos + 5]: error message (char*) + // * [tos + 6]: object to verify (oop) + // * [tos + 7]: saved rax - saved by caller and bashed // * = popped on exit address generate_verify_oop() { StubCodeMark mark(this, "StubRoutines", "verify_oop"); @@ -926,12 +929,24 @@ class StubGenerator: public StubCodeGenerator { __ pushfq(); __ incrementl(ExternalAddress((address) StubRoutines::verify_oop_count_addr())); + __ pushq(r12); + // save c_rarg2 and c_rarg3 __ pushq(c_rarg2); __ pushq(c_rarg3); + enum { + // After previous pushes. + oop_to_verify = 6 * wordSize, + saved_rax = 7 * wordSize, + + // Before the call to MacroAssembler::debug(), see below. + return_addr = 16 * wordSize, + error_msg = 17 * wordSize + }; + // get object - __ movq(rax, Address(rsp, 5 * wordSize)); + __ movq(rax, Address(rsp, oop_to_verify)); // make sure object is 'reasonable' __ testq(rax, rax); @@ -944,8 +959,11 @@ class StubGenerator: public StubCodeGenerator { __ cmpq(c_rarg2, c_rarg3); __ jcc(Assembler::notZero, error); + // set r12 to heapbase for load_klass() + __ reinit_heapbase(); + // make sure klass is 'reasonable' - __ movq(rax, Address(rax, oopDesc::klass_offset_in_bytes())); // get klass + __ load_klass(rax, rax); // get klass __ testq(rax, rax); __ jcc(Assembler::zero, error); // if klass is NULL it is broken // Check if the klass is in the right area of memory @@ -957,7 +975,7 @@ class StubGenerator: public StubCodeGenerator { __ jcc(Assembler::notZero, error); // make sure klass' klass is 'reasonable' - __ movq(rax, Address(rax, oopDesc::klass_offset_in_bytes())); + __ load_klass(rax, rax); __ testq(rax, rax); __ jcc(Assembler::zero, error); // if klass' klass is NULL it is broken // Check if the klass' klass is in the right area of memory @@ -969,39 +987,45 @@ class StubGenerator: public StubCodeGenerator { // return if everything seems ok __ bind(exit); - __ movq(rax, Address(rsp, 6 * wordSize)); // get saved rax back - __ popq(c_rarg3); // restore c_rarg3 - __ popq(c_rarg2); // restore c_rarg2 + __ movq(rax, Address(rsp, saved_rax)); // get saved rax back + __ popq(c_rarg3); // restore c_rarg3 + __ popq(c_rarg2); // restore c_rarg2 + __ popq(r12); // restore r12 __ popfq(); // restore flags __ ret(3 * wordSize); // pop caller saved stuff // handle errors __ bind(error); - __ movq(rax, Address(rsp, 6 * wordSize)); // get saved rax back - __ popq(c_rarg3); // get saved c_rarg3 back - __ popq(c_rarg2); // get saved c_rarg2 back + __ movq(rax, Address(rsp, saved_rax)); // get saved rax back + __ popq(c_rarg3); // get saved c_rarg3 back + __ popq(c_rarg2); // get saved c_rarg2 back + __ popq(r12); // get saved r12 back __ popfq(); // get saved flags off stack -- // will be ignored __ pushaq(); // push registers // (rip is already // already pushed) - // debug(char* msg, int64_t regs[]) + // debug(char* msg, int64_t pc, int64_t regs[]) // We've popped the registers we'd saved (c_rarg3, c_rarg2 and flags), and // pushed all the registers, so now the stack looks like: // [tos + 0] 16 saved registers // [tos + 16] return address - // [tos + 17] error message (char*) + // * [tos + 17] error message (char*) + // * [tos + 18] object to verify (oop) + // * [tos + 19] saved rax - saved by caller and bashed + // * = popped on exit - __ movq(c_rarg0, Address(rsp, 17 * wordSize)); // pass address of error message - __ movq(c_rarg1, rsp); // pass address of regs on stack + __ movq(c_rarg0, Address(rsp, error_msg)); // pass address of error message + __ movq(c_rarg1, Address(rsp, return_addr)); // pass return address + __ movq(c_rarg2, rsp); // pass address of regs on stack __ movq(r12, rsp); // remember rsp __ subq(rsp, frame::arg_reg_save_area_bytes);// windows __ andq(rsp, -16); // align stack as required by ABI BLOCK_COMMENT("call MacroAssembler::debug"); __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug))); __ movq(rsp, r12); // restore rsp - __ popaq(); // pop registers + __ popaq(); // pop registers (includes r12) __ ret(3 * wordSize); // pop caller saved stuff return start; @@ -1035,7 +1059,7 @@ class StubGenerator: public StubCodeGenerator { assert_different_registers(Rtmp, Rint); __ movslq(Rtmp, Rint); __ cmpq(Rtmp, Rint); - __ jccb(Assembler::equal, L); + __ jcc(Assembler::equal, L); __ stop("high 32-bits of int value are not 0"); __ bind(L); #endif @@ -1652,6 +1676,7 @@ class StubGenerator: public StubCodeGenerator { // Arguments: // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary // ignored + // is_oop - true => oop array, so generate store check code // name - stub name string // // Inputs: @@ -1665,9 +1690,9 @@ class StubGenerator: public StubCodeGenerator { // // Side Effects: // disjoint_int_copy_entry is set to the no-overlap entry point - // used by generate_conjoint_int_copy(). + // used by generate_conjoint_int_oop_copy(). // - address generate_disjoint_int_copy(bool aligned, const char *name) { + address generate_disjoint_int_oop_copy(bool aligned, bool is_oop, const char *name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -1680,19 +1705,30 @@ class StubGenerator: public StubCodeGenerator { const Register qword_count = count; const Register end_from = from; // source array end address const Register end_to = to; // destination array end address + const Register saved_to = r11; // saved destination array address // End pointers are inclusive, and if count is not zero they point // to the last unit copied: end_to[0] := end_from[0] __ enter(); // required for proper stackwalking of RuntimeStub frame assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. - disjoint_int_copy_entry = __ pc(); + (is_oop ? disjoint_oop_copy_entry : disjoint_int_copy_entry) = __ pc(); + + if (is_oop) { + // no registers are destroyed by this call + gen_write_ref_array_pre_barrier(/* dest */ c_rarg1, /* count */ c_rarg2); + } + BLOCK_COMMENT("Entry:"); // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) setup_arg_regs(); // from => rdi, to => rsi, count => rdx // r9 and r10 may be used to save non-volatile registers + if (is_oop) { + __ movq(saved_to, to); + } + // 'from', 'to' and 'count' are now valid __ movq(dword_count, count); __ shrq(count, 1); // count => qword_count @@ -1718,6 +1754,10 @@ class StubGenerator: public StubCodeGenerator { __ movl(Address(end_to, 8), rax); __ BIND(L_exit); + if (is_oop) { + __ leaq(end_to, Address(saved_to, dword_count, Address::times_4, -4)); + gen_write_ref_array_post_barrier(saved_to, end_to, rax); + } inc_counter_np(SharedRuntime::_jint_array_copy_ctr); restore_arg_regs(); __ xorq(rax, rax); // return 0 @@ -1734,6 +1774,7 @@ class StubGenerator: public StubCodeGenerator { // Arguments: // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary // ignored + // is_oop - true => oop array, so generate store check code // name - stub name string // // Inputs: @@ -1745,12 +1786,12 @@ class StubGenerator: public StubCodeGenerator { // the hardware handle it. The two dwords within qwords that span // cache line boundaries will still be loaded and stored atomicly. // - address generate_conjoint_int_copy(bool aligned, const char *name) { + address generate_conjoint_int_oop_copy(bool aligned, bool is_oop, const char *name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); - Label L_copy_32_bytes, L_copy_8_bytes, L_copy_2_bytes; + Label L_copy_32_bytes, L_copy_8_bytes, L_copy_2_bytes, L_exit; const Register from = rdi; // source array address const Register to = rsi; // destination array address const Register count = rdx; // elements count @@ -1760,14 +1801,21 @@ class StubGenerator: public StubCodeGenerator { __ enter(); // required for proper stackwalking of RuntimeStub frame assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. - int_copy_entry = __ pc(); + if (is_oop) { + // no registers are destroyed by this call + gen_write_ref_array_pre_barrier(/* dest */ c_rarg1, /* count */ c_rarg2); + } + + (is_oop ? oop_copy_entry : int_copy_entry) = __ pc(); BLOCK_COMMENT("Entry:"); // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) - array_overlap_test(disjoint_int_copy_entry, Address::times_4); + array_overlap_test(is_oop ? disjoint_oop_copy_entry : disjoint_int_copy_entry, + Address::times_4); setup_arg_regs(); // from => rdi, to => rsi, count => rdx // r9 and r10 may be used to save non-volatile registers + assert_clean_int(count, rax); // Make sure 'count' is clean int. // 'from', 'to' and 'count' are now valid __ movq(dword_count, count); __ shrq(count, 1); // count => qword_count @@ -1789,6 +1837,9 @@ class StubGenerator: public StubCodeGenerator { __ jcc(Assembler::notZero, L_copy_8_bytes); inc_counter_np(SharedRuntime::_jint_array_copy_ctr); + if (is_oop) { + __ jmp(L_exit); + } restore_arg_regs(); __ xorq(rax, rax); // return 0 __ leave(); // required for proper stackwalking of RuntimeStub frame @@ -1797,7 +1848,13 @@ class StubGenerator: public StubCodeGenerator { // Copy in 32-bytes chunks copy_32_bytes_backward(from, to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes); - inc_counter_np(SharedRuntime::_jint_array_copy_ctr); + inc_counter_np(SharedRuntime::_jint_array_copy_ctr); + __ bind(L_exit); + if (is_oop) { + Register end_to = rdx; + __ leaq(end_to, Address(to, dword_count, Address::times_4, -4)); + gen_write_ref_array_post_barrier(to, end_to, rax); + } restore_arg_regs(); __ xorq(rax, rax); // return 0 __ leave(); // required for proper stackwalking of RuntimeStub frame @@ -1817,7 +1874,7 @@ class StubGenerator: public StubCodeGenerator { // c_rarg1 - destination array address // c_rarg2 - element count, treated as ssize_t, can be zero // - // Side Effects: + // Side Effects: // disjoint_oop_copy_entry or disjoint_long_copy_entry is set to the // no-overlap entry point used by generate_conjoint_long_oop_copy(). // @@ -1857,7 +1914,7 @@ class StubGenerator: public StubCodeGenerator { // Copy from low to high addresses. Use 'to' as scratch. __ leaq(end_from, Address(from, qword_count, Address::times_8, -8)); - __ leaq(end_to, Address(to, qword_count, Address::times_8, -8)); + __ leaq(end_to, Address(to, qword_count, Address::times_8, -8)); __ negq(qword_count); __ jmp(L_copy_32_bytes); @@ -1923,11 +1980,14 @@ class StubGenerator: public StubCodeGenerator { address disjoint_copy_entry = NULL; if (is_oop) { + assert(!UseCompressedOops, "shouldn't be called for compressed oops"); disjoint_copy_entry = disjoint_oop_copy_entry; oop_copy_entry = __ pc(); + array_overlap_test(disjoint_oop_copy_entry, Address::times_8); } else { disjoint_copy_entry = disjoint_long_copy_entry; long_copy_entry = __ pc(); + array_overlap_test(disjoint_long_copy_entry, Address::times_8); } BLOCK_COMMENT("Entry:"); // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) @@ -1945,8 +2005,6 @@ class StubGenerator: public StubCodeGenerator { gen_write_ref_array_pre_barrier(to, saved_count); } - // Copy from high to low addresses. Use rcx as scratch. - __ jmp(L_copy_32_bytes); // Copy trailing qwords @@ -2038,7 +2096,14 @@ class StubGenerator: public StubCodeGenerator { // Scan rcx words at [rdi] for occurance of rax // Set NZ/Z based on last compare __ movq(rax, super_klass); - __ repne_scan(); + if (UseCompressedOops) { + // Compare against compressed form. Don't need to uncompress because + // looks like orig rax is restored in popq below. + __ encode_heap_oop(rax); + __ repne_scanl(); + } else { + __ repne_scanq(); + } // Unspill the temp. registers: __ popq(rdi); @@ -2115,7 +2180,7 @@ class StubGenerator: public StubCodeGenerator { // caller guarantees that the arrays really are different // otherwise, we would have to make conjoint checks { Label L; - array_overlap_test(L, Address::times_8); + array_overlap_test(L, TIMES_OOP); __ stop("checkcast_copy within a single array"); __ bind(L); } @@ -2160,12 +2225,11 @@ class StubGenerator: public StubCodeGenerator { #endif //ASSERT // Loop-invariant addresses. They are exclusive end pointers. - Address end_from_addr(from, length, Address::times_8, 0); - Address end_to_addr(to, length, Address::times_8, 0); + Address end_from_addr(from, length, TIMES_OOP, 0); + Address end_to_addr(to, length, TIMES_OOP, 0); // Loop-variant addresses. They assume post-incremented count < 0. - Address from_element_addr(end_from, count, Address::times_8, 0); - Address to_element_addr(end_to, count, Address::times_8, 0); - Address oop_klass_addr(rax_oop, oopDesc::klass_offset_in_bytes()); + Address from_element_addr(end_from, count, TIMES_OOP, 0); + Address to_element_addr(end_to, count, TIMES_OOP, 0); gen_write_ref_array_pre_barrier(to, count); @@ -2189,17 +2253,17 @@ class StubGenerator: public StubCodeGenerator { __ align(16); __ BIND(L_store_element); - __ movq(to_element_addr, rax_oop); // store the oop + __ store_heap_oop(to_element_addr, rax_oop); // store the oop __ incrementq(count); // increment the count toward zero __ jcc(Assembler::zero, L_do_card_marks); // ======== loop entry is here ======== __ BIND(L_load_element); - __ movq(rax_oop, from_element_addr); // load the oop + __ load_heap_oop(rax_oop, from_element_addr); // load the oop __ testq(rax_oop, rax_oop); __ jcc(Assembler::zero, L_store_element); - __ movq(r11_klass, oop_klass_addr); // query the object klass + __ load_klass(r11_klass, rax_oop);// query the object klass generate_type_check(r11_klass, ckoff, ckval, L_store_element); // ======== end loop ======== @@ -2425,15 +2489,14 @@ class StubGenerator: public StubCodeGenerator { // registers used as temp const Register r11_length = r11; // elements count to copy const Register r10_src_klass = r10; // array klass + const Register r9_dst_klass = r9; // dest array klass // if (length < 0) return -1; __ movl(r11_length, C_RARG4); // length (elements count, 32-bits value) __ testl(r11_length, r11_length); __ jccb(Assembler::negative, L_failed_0); - Address src_klass_addr(src, oopDesc::klass_offset_in_bytes()); - Address dst_klass_addr(dst, oopDesc::klass_offset_in_bytes()); - __ movq(r10_src_klass, src_klass_addr); + __ load_klass(r10_src_klass, src); #ifdef ASSERT // assert(src->klass() != NULL); BLOCK_COMMENT("assert klasses not null"); @@ -2443,7 +2506,8 @@ class StubGenerator: public StubCodeGenerator { __ bind(L1); __ stop("broken null klass"); __ bind(L2); - __ cmpq(dst_klass_addr, 0); + __ load_klass(r9_dst_klass, dst); + __ cmpq(r9_dst_klass, 0); __ jcc(Assembler::equal, L1); // this would be broken also BLOCK_COMMENT("assert done"); } @@ -2470,7 +2534,8 @@ class StubGenerator: public StubCodeGenerator { __ jcc(Assembler::equal, L_objArray); // if (src->klass() != dst->klass()) return -1; - __ cmpq(r10_src_klass, dst_klass_addr); + __ load_klass(r9_dst_klass, dst); + __ cmpq(r10_src_klass, r9_dst_klass); __ jcc(Assembler::notEqual, L_failed); // if (!src->is_Array()) return -1; @@ -2559,17 +2624,18 @@ class StubGenerator: public StubCodeGenerator { Label L_plain_copy, L_checkcast_copy; // test array classes for subtyping - __ cmpq(r10_src_klass, dst_klass_addr); // usual case is exact equality + __ load_klass(r9_dst_klass, dst); + __ cmpq(r10_src_klass, r9_dst_klass); // usual case is exact equality __ jcc(Assembler::notEqual, L_checkcast_copy); // Identically typed arrays can be copied without element-wise checks. arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length, r10, L_failed); - __ leaq(from, Address(src, src_pos, Address::times_8, + __ leaq(from, Address(src, src_pos, TIMES_OOP, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // src_addr - __ leaq(to, Address(dst, dst_pos, Address::times_8, - arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr + __ leaq(to, Address(dst, dst_pos, TIMES_OOP, + arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr __ movslq(count, r11_length); // length __ BIND(L_plain_copy); __ jump(RuntimeAddress(oop_copy_entry)); @@ -2579,7 +2645,7 @@ class StubGenerator: public StubCodeGenerator { { // assert(r11_length == C_RARG4); // will reload from here Register r11_dst_klass = r11; - __ movq(r11_dst_klass, dst_klass_addr); + __ load_klass(r11_dst_klass, dst); // Before looking at dst.length, make sure dst is also an objArray. __ cmpl(Address(r11_dst_klass, lh_offset), objArray_lh); @@ -2593,13 +2659,13 @@ class StubGenerator: public StubCodeGenerator { __ movl(r11_length, C_RARG4); // reload arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length, rax, L_failed); - __ movl(r11_dst_klass, dst_klass_addr); // reload + __ load_klass(r11_dst_klass, dst); // reload #endif // Marshal the base address arguments now, freeing registers. - __ leaq(from, Address(src, src_pos, Address::times_8, + __ leaq(from, Address(src, src_pos, TIMES_OOP, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); - __ leaq(to, Address(dst, dst_pos, Address::times_8, + __ leaq(to, Address(dst, dst_pos, TIMES_OOP, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); __ movl(count, C_RARG4); // length (reloaded) Register sco_temp = c_rarg3; // this register is free now @@ -2648,14 +2714,20 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, "jshort_disjoint_arraycopy"); StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, "jshort_arraycopy"); - StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(false, "jint_disjoint_arraycopy"); - StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(false, "jint_arraycopy"); + StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, false, "jint_disjoint_arraycopy"); + StubRoutines::_jint_arraycopy = generate_conjoint_int_oop_copy(false, false, "jint_arraycopy"); StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, false, "jlong_disjoint_arraycopy"); StubRoutines::_jlong_arraycopy = generate_conjoint_long_oop_copy(false, false, "jlong_arraycopy"); - StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, true, "oop_disjoint_arraycopy"); - StubRoutines::_oop_arraycopy = generate_conjoint_long_oop_copy(false, true, "oop_arraycopy"); + + if (UseCompressedOops) { + StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, true, "oop_disjoint_arraycopy"); + StubRoutines::_oop_arraycopy = generate_conjoint_int_oop_copy(false, true, "oop_arraycopy"); + } else { + StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, true, "oop_disjoint_arraycopy"); + StubRoutines::_oop_arraycopy = generate_conjoint_long_oop_copy(false, true, "oop_arraycopy"); + } StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy"); StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy"); diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp index 5750142530d..6134af3071a 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp @@ -664,7 +664,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { // work registers const Register method = rbx; - const Register t = r12; + const Register t = r11; // allocate space for parameters __ get_method(method); @@ -844,6 +844,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { __ andq(rsp, -16); // align stack as required by ABI __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); __ movq(rsp, r12); // restore sp + __ reinit_heapbase(); __ bind(Continue); } @@ -891,6 +892,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages))); __ movq(rsp, r12); // restore sp __ popaq(); // XXX only restore smashed registers + __ reinit_heapbase(); __ bind(no_reguard); } @@ -1360,6 +1362,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // rdx: return address/pc that threw exception __ restore_bcp(); // r13 points to call/send __ restore_locals(); + __ reinit_heapbase(); // restore r12 as heapbase. // Entry point for exceptions thrown within interpreter code Interpreter::_throw_exception_entry = __ pc(); // expression stack is undefined here @@ -1658,6 +1661,7 @@ void TemplateInterpreterGenerator::trace_bytecode(Template* t) { __ andq(rsp, -16); // align stack as required by ABI __ call(RuntimeAddress(Interpreter::trace_code(t->tos_in()))); __ movq(rsp, r12); // restore sp + __ reinit_heapbase(); } diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp index 53c908562f9..79bcd92f2e4 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp @@ -1632,7 +1632,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { // We need to prepare to execute the OSR method. First we must // migrate the locals and monitors off of the stack. - __ movl(rsi, rax); // save the nmethod + __ movl(rbx, rax); // save the nmethod const Register thread = rcx; __ get_thread(thread); @@ -1688,7 +1688,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { __ pushl(rdi); // and begin the OSR nmethod - __ jmp(Address(rsi, nmethod::osr_entry_point_offset())); + __ jmp(Address(rbx, nmethod::osr_entry_point_offset())); } } } diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp index 50db0e5853a..f84c8f8cc05 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp @@ -557,8 +557,8 @@ void TemplateTable::aaload() { // eax: index // rdx: array index_check(rdx, rax); // kills rbx - __ movq(rax, Address(rdx, rax, - Address::times_8, + __ load_heap_oop(rax, Address(rdx, rax, + UseCompressedOops ? Address::times_4 : Address::times_8, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); } @@ -870,15 +870,15 @@ void TemplateTable::aastore() { __ jcc(Assembler::zero, is_null); // Move subklass into rbx - __ movq(rbx, Address(rax, oopDesc::klass_offset_in_bytes())); + __ load_klass(rbx, rax); // Move superklass into rax - __ movq(rax, Address(rdx, oopDesc::klass_offset_in_bytes())); + __ load_klass(rax, rdx); __ movq(rax, Address(rax, sizeof(oopDesc) + objArrayKlass::element_klass_offset_in_bytes())); - // Compress array + index*8 + 12 into a single register. Frees rcx. + // Compress array + index*oopSize + 12 into a single register. Frees rcx. __ leaq(rdx, Address(rdx, rcx, - Address::times_8, + UseCompressedOops ? Address::times_4 : Address::times_8, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // Generate subtype check. Blows rcx, rdi @@ -892,17 +892,17 @@ void TemplateTable::aastore() { // Come here on success __ bind(ok_is_subtype); __ movq(rax, at_tos()); // Value - __ movq(Address(rdx, 0), rax); + __ store_heap_oop(Address(rdx, 0), rax); __ store_check(rdx); __ jmp(done); // Have a NULL in rax, rdx=array, ecx=index. Store NULL at ary[idx] __ bind(is_null); __ profile_null_seen(rbx); - __ movq(Address(rdx, rcx, - Address::times_8, - arrayOopDesc::base_offset_in_bytes(T_OBJECT)), - rax); + __ store_heap_oop(Address(rdx, rcx, + UseCompressedOops ? Address::times_4 : Address::times_8, + arrayOopDesc::base_offset_in_bytes(T_OBJECT)), + rax); // Pop stack arguments __ bind(done); @@ -1934,7 +1934,7 @@ void TemplateTable::_return(TosState state) { if (_desc->bytecode() == Bytecodes::_return_register_finalizer) { assert(state == vtos, "only valid state"); __ movq(c_rarg1, aaddress(0)); - __ movq(rdi, Address(c_rarg1, oopDesc::klass_offset_in_bytes())); + __ load_klass(rdi, c_rarg1); __ movl(rdi, Address(rdi, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc))); __ testl(rdi, JVM_ACC_HAS_FINALIZER); Label skip_register_finalizer; @@ -2184,7 +2184,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) { __ cmpl(flags, atos); __ jcc(Assembler::notEqual, notObj); // atos - __ movq(rax, field); + __ load_heap_oop(rax, field); __ push(atos); if (!is_static) { patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx); @@ -2394,7 +2394,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) { // atos __ pop(atos); if (!is_static) pop_and_check_object(obj); - __ movq(field, rax); + __ store_heap_oop(field, rax); __ store_check(obj, field); // Need to mark card if (!is_static) { patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx); @@ -2515,7 +2515,7 @@ void TemplateTable::jvmti_post_fast_field_mod() { const Address field(c_rarg3, 0); switch (bytecode()) { // load values into the jvalue object - case Bytecodes::_fast_aputfield: // fall through + case Bytecodes::_fast_aputfield: __ movq(field, rax); break; case Bytecodes::_fast_lputfield: __ movq(field, rax); break; case Bytecodes::_fast_iputfield: __ movl(field, rax); break; case Bytecodes::_fast_bputfield: __ movb(field, rax); break; @@ -2582,7 +2582,7 @@ void TemplateTable::fast_storefield(TosState state) { // access field switch (bytecode()) { case Bytecodes::_fast_aputfield: - __ movq(field, rax); + __ store_heap_oop(field, rax); __ store_check(rcx, field); break; case Bytecodes::_fast_lputfield: @@ -2631,8 +2631,8 @@ void TemplateTable::fast_accessfield(TosState state) { __ jcc(Assembler::zero, L1); // access constant pool cache entry __ get_cache_entry_pointer_at_bcp(c_rarg2, rcx, 1); - __ movq(r12, rax); // save object pointer before call_VM() clobbers it __ verify_oop(rax); + __ movq(r12, rax); // save object pointer before call_VM() clobbers it __ movq(c_rarg1, rax); // c_rarg1: object pointer copied above // c_rarg2: cache entry pointer @@ -2641,6 +2641,7 @@ void TemplateTable::fast_accessfield(TosState state) { InterpreterRuntime::post_field_access), c_rarg1, c_rarg2); __ movq(rax, r12); // restore object pointer + __ reinit_heapbase(); __ bind(L1); } @@ -2667,7 +2668,7 @@ void TemplateTable::fast_accessfield(TosState state) { // access field switch (bytecode()) { case Bytecodes::_fast_agetfield: - __ movq(rax, field); + __ load_heap_oop(rax, field); __ verify_oop(rax); break; case Bytecodes::_fast_lgetfield: @@ -2725,7 +2726,7 @@ void TemplateTable::fast_xaccess(TosState state) { __ movl(rax, Address(rax, rbx, Address::times_1)); break; case atos: - __ movq(rax, Address(rax, rbx, Address::times_1)); + __ load_heap_oop(rax, Address(rax, rbx, Address::times_1)); __ verify_oop(rax); break; case ftos: @@ -2787,7 +2788,8 @@ void TemplateTable::prepare_invoke(Register method, __ movl(recv, flags); __ andl(recv, 0xFF); if (TaggedStackInterpreter) __ shll(recv, 1); // index*2 - __ movq(recv, Address(rsp, recv, Address::times_8, -Interpreter::expr_offset_in_bytes(1))); + __ movq(recv, Address(rsp, recv, Address::times_8, + -Interpreter::expr_offset_in_bytes(1))); __ verify_oop(recv); } @@ -2854,7 +2856,7 @@ void TemplateTable::invokevirtual_helper(Register index, // get receiver klass __ null_check(recv, oopDesc::klass_offset_in_bytes()); - __ movq(rax, Address(recv, oopDesc::klass_offset_in_bytes())); + __ load_klass(rax, recv); __ verify_oop(rax); @@ -2866,8 +2868,8 @@ void TemplateTable::invokevirtual_helper(Register index, assert(vtableEntry::size() * wordSize == 8, "adjust the scaling in the code below"); __ movq(method, Address(rax, index, - Address::times_8, - base + vtableEntry::method_offset_in_bytes())); + Address::times_8, + base + vtableEntry::method_offset_in_bytes())); __ movq(rdx, Address(method, methodOopDesc::interpreter_entry_offset())); __ jump_from_interpreted(method, rdx); } @@ -2932,7 +2934,7 @@ void TemplateTable::invokeinterface(int byte_no) { // Get receiver klass into rdx - also a null check __ restore_locals(); // restore r14 - __ movq(rdx, Address(rcx, oopDesc::klass_offset_in_bytes())); + __ load_klass(rdx, rcx); __ verify_oop(rdx); // profile this call @@ -3161,7 +3163,7 @@ void TemplateTable::_new() { __ movptr(Address(rax, oopDesc::mark_offset_in_bytes()), (intptr_t) markOopDesc::prototype()); // header (address 0x1) } - __ movq(Address(rax, oopDesc::klass_offset_in_bytes()), rsi); // klass + __ store_klass(rax, rsi); // klass __ jmp(done); } @@ -3223,12 +3225,12 @@ void TemplateTable::checkcast() { typeArrayOopDesc::header_size(T_BYTE) * wordSize), JVM_CONSTANT_Class); __ jcc(Assembler::equal, quicked); - - __ movq(r12, rcx); // save rcx XXX __ push(atos); // save receiver for result, and for GC + __ movq(r12, rcx); // save rcx XXX call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - __ pop_ptr(rdx); // restore receiver __ movq(rcx, r12); // restore rcx XXX + __ reinit_heapbase(); + __ pop_ptr(rdx); // restore receiver __ jmpb(resolved); // Get superklass in rax and subklass in rbx @@ -3238,7 +3240,7 @@ void TemplateTable::checkcast() { Address::times_8, sizeof(constantPoolOopDesc))); __ bind(resolved); - __ movq(rbx, Address(rdx, oopDesc::klass_offset_in_bytes())); + __ load_klass(rbx, rdx); // Generate subtype check. Blows rcx, rdi. Object in rdx. // Superklass in rax. Subklass in rbx. @@ -3280,19 +3282,20 @@ void TemplateTable::instanceof() { JVM_CONSTANT_Class); __ jcc(Assembler::equal, quicked); - __ movq(r12, rcx); // save rcx __ push(atos); // save receiver for result, and for GC + __ movq(r12, rcx); // save rcx call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - __ pop_ptr(rdx); // restore receiver - __ movq(rdx, Address(rdx, oopDesc::klass_offset_in_bytes())); __ movq(rcx, r12); // restore rcx + __ reinit_heapbase(); + __ pop_ptr(rdx); // restore receiver + __ load_klass(rdx, rdx); __ jmpb(resolved); // Get superklass in rax and subklass in rdx __ bind(quicked); - __ movq(rdx, Address(rax, oopDesc::klass_offset_in_bytes())); + __ load_klass(rdx, rax); __ movq(rax, Address(rcx, rbx, - Address::times_8, sizeof(constantPoolOopDesc))); + Address::times_8, sizeof(constantPoolOopDesc))); __ bind(resolved); diff --git a/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp b/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp index c68f7f363e9..3a934d8d7f1 100644 --- a/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp @@ -56,7 +56,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { // get receiver klass address npe_addr = __ pc(); - __ movq(rax, Address(j_rarg0, oopDesc::klass_offset_in_bytes())); + __ load_klass(rax, j_rarg0); // compute entry offset (in words) int entry_offset = @@ -131,7 +131,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { // get receiver klass (also an implicit null-check) address npe_addr = __ pc(); - __ movq(rbx, Address(j_rarg0, oopDesc::klass_offset_in_bytes())); + __ load_klass(rbx, j_rarg0); // If we take a trap while this arg is on the stack we will not // be able to walk the stack properly. This is not an issue except @@ -181,7 +181,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { // Get methodOop and entrypoint for compiler // Get klass pointer again - __ movq(rax, Address(j_rarg0, oopDesc::klass_offset_in_bytes())); + __ load_klass(rax, j_rarg0); const Register method = rbx; __ movq(method, Address(rax, j_rarg1, Address::times_1, method_offset)); @@ -226,10 +226,12 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { int VtableStub::pd_code_size_limit(bool is_vtable_stub) { if (is_vtable_stub) { // Vtable stub size - return (DebugVtables ? 512 : 24) + (CountCompiledCalls ? 13 : 0); + return (DebugVtables ? 512 : 24) + (CountCompiledCalls ? 13 : 0) + + (UseCompressedOops ? 16 : 0); // 1 leaq can be 3 bytes + 1 long } else { // Itable stub size - return (DebugVtables ? 636 : 72) + (CountCompiledCalls ? 13 : 0); + return (DebugVtables ? 636 : 72) + (CountCompiledCalls ? 13 : 0) + + (UseCompressedOops ? 32 : 0); // 2 leaqs } } diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 5f54907359a..90607dc2508 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -4538,8 +4538,8 @@ frame %{ // Location of C & interpreter return values c_return_value %{ assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" ); - static int lo[Op_RegL+1] = { 0, 0, EAX_num, EAX_num, FPR1L_num, FPR1L_num, EAX_num }; - static int hi[Op_RegL+1] = { 0, 0, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, FPR1H_num, EDX_num }; + static int lo[Op_RegL+1] = { 0, 0, OptoReg::Bad, EAX_num, EAX_num, FPR1L_num, FPR1L_num, EAX_num }; + static int hi[Op_RegL+1] = { 0, 0, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, FPR1H_num, EDX_num }; // in SSE2+ mode we want to keep the FPU stack clean so pretend // that C functions return float and double results in XMM0. @@ -4554,8 +4554,8 @@ frame %{ // Location of return values return_value %{ assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" ); - static int lo[Op_RegL+1] = { 0, 0, EAX_num, EAX_num, FPR1L_num, FPR1L_num, EAX_num }; - static int hi[Op_RegL+1] = { 0, 0, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, FPR1H_num, EDX_num }; + static int lo[Op_RegL+1] = { 0, 0, OptoReg::Bad, EAX_num, EAX_num, FPR1L_num, FPR1L_num, EAX_num }; + static int hi[Op_RegL+1] = { 0, 0, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, FPR1H_num, EDX_num }; if( ideal_reg == Op_RegD && UseSSE>=2 ) return OptoRegPair(XMM0b_num,XMM0a_num); if( ideal_reg == Op_RegF && UseSSE>=1 ) diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 396f54f664e..2c79821c238 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -312,7 +312,6 @@ reg_class ptr_reg(RAX, RAX_H, R9, R9_H, R10, R10_H, R11, R11_H, - R12, R12_H, R13, R13_H, R14, R14_H); @@ -392,7 +391,6 @@ reg_class long_reg(RAX, RAX_H, R9, R9_H, R10, R10_H, R11, R11_H, - R12, R12_H, R13, R13_H, R14, R14_H); @@ -406,7 +404,6 @@ reg_class long_no_rax_rdx_reg(RBP, RBP_H, R9, R9_H, R10, R10_H, R11, R11_H, - R12, R12_H, R13, R13_H, R14, R14_H); @@ -421,7 +418,6 @@ reg_class long_no_rcx_reg(RBP, RBP_H, R9, R9_H, R10, R10_H, R11, R11_H, - R12, R12_H, R13, R13_H, R14, R14_H); @@ -436,7 +432,6 @@ reg_class long_no_rax_reg(RBP, RBP_H, R9, R9_H, R10, R10_H, R11, R11_H, - R12, R12_H, R13, R13_H, R14, R14_H); @@ -449,6 +444,9 @@ reg_class long_rcx_reg(RCX, RCX_H); // Singleton class for RDX long register reg_class long_rdx_reg(RDX, RDX_H); +// Singleton class for R12 long register +reg_class long_r12_reg(R12, R12_H); + // Class for all int registers (except RSP) reg_class int_reg(RAX, RDX, @@ -461,7 +459,6 @@ reg_class int_reg(RAX, R9, R10, R11, - R12, R13, R14); @@ -476,7 +473,6 @@ reg_class int_no_rcx_reg(RAX, R9, R10, R11, - R12, R13, R14); @@ -490,7 +486,6 @@ reg_class int_no_rax_rdx_reg(RBP, R9, R10, R11, - R12, R13, R14); @@ -1844,8 +1839,14 @@ uint reloc_java_to_interp() #ifndef PRODUCT void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const { - st->print_cr("cmpq rax, [j_rarg0 + oopDesc::klass_offset_in_bytes() #%d]\t" - "# Inline cache check", oopDesc::klass_offset_in_bytes()); + if (UseCompressedOops) { + st->print_cr("movl rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes() #%d]\t", oopDesc::klass_offset_in_bytes()); + st->print_cr("leaq rscratch1, [r12_heapbase, r, Address::times_8, 0]"); + st->print_cr("cmpq rax, rscratch1\t # Inline cache check"); + } else { + st->print_cr("cmpq rax, [j_rarg0 + oopDesc::klass_offset_in_bytes() #%d]\t" + "# Inline cache check", oopDesc::klass_offset_in_bytes()); + } st->print_cr("\tjne SharedRuntime::_ic_miss_stub"); st->print_cr("\tnop"); if (!OptoBreakpoint) { @@ -1860,7 +1861,12 @@ void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const #ifdef ASSERT uint code_size = cbuf.code_size(); #endif - masm.cmpq(rax, Address(j_rarg0, oopDesc::klass_offset_in_bytes())); + if (UseCompressedOops) { + masm.load_klass(rscratch1, j_rarg0); + masm.cmpq(rax, rscratch1); + } else { + masm.cmpq(rax, Address(j_rarg0, oopDesc::klass_offset_in_bytes())); + } masm.jump_cc(Assembler::notEqual, RuntimeAddress(SharedRuntime::get_ic_miss_stub())); @@ -1871,6 +1877,10 @@ void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const // Leave space for int3 nops_cnt += 1; } + if (UseCompressedOops) { + // ??? divisible by 4 is aligned? + nops_cnt += 1; + } masm.nop(nops_cnt); assert(cbuf.code_size() - code_size == size(ra_), @@ -1879,7 +1889,11 @@ void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const uint MachUEPNode::size(PhaseRegAlloc* ra_) const { - return OptoBreakpoint ? 11 : 12; + if (UseCompressedOops) { + return OptoBreakpoint ? 19 : 20; + } else { + return OptoBreakpoint ? 11 : 12; + } } @@ -2052,6 +2066,7 @@ bool Matcher::can_be_java_arg(int reg) reg == RCX_num || reg == RCX_H_num || reg == R8_num || reg == R8_H_num || reg == R9_num || reg == R9_H_num || + reg == R12_num || reg == R12_H_num || reg == XMM0_num || reg == XMM0_H_num || reg == XMM1_num || reg == XMM1_H_num || reg == XMM2_num || reg == XMM2_H_num || @@ -2087,6 +2102,17 @@ RegMask Matcher::modL_proj_mask() { return LONG_RDX_REG_mask; } +static Address build_address(int b, int i, int s, int d) { + Register index = as_Register(i); + Address::ScaleFactor scale = (Address::ScaleFactor)s; + if (index == rsp) { + index = noreg; + scale = Address::no_scale; + } + Address addr(as_Register(b), index, scale, d); + return addr; +} + %} //----------ENCODING BLOCK----------------------------------------------------- @@ -2545,7 +2571,7 @@ encode %{ Register Rrax = as_Register(RAX_enc); // super class Register Rrcx = as_Register(RCX_enc); // killed Register Rrsi = as_Register(RSI_enc); // sub class - Label hit, miss; + Label hit, miss, cmiss; MacroAssembler _masm(&cbuf); // Compare super with sub directly, since super is not in its own SSA. @@ -2562,12 +2588,27 @@ encode %{ Klass::secondary_supers_offset_in_bytes())); __ movl(Rrcx, Address(Rrdi, arrayOopDesc::length_offset_in_bytes())); __ addq(Rrdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); - __ repne_scan(); - __ jcc(Assembler::notEqual, miss); - __ movq(Address(Rrsi, - sizeof(oopDesc) + - Klass::secondary_super_cache_offset_in_bytes()), - Rrax); + if (UseCompressedOops) { + __ encode_heap_oop(Rrax); + __ repne_scanl(); + __ jcc(Assembler::notEqual, cmiss); + __ decode_heap_oop(Rrax); + __ movq(Address(Rrsi, + sizeof(oopDesc) + + Klass::secondary_super_cache_offset_in_bytes()), + Rrax); + __ jmp(hit); + __ bind(cmiss); + __ decode_heap_oop(Rrax); + __ jmp(miss); + } else { + __ repne_scanq(); + __ jcc(Assembler::notEqual, miss); + __ movq(Address(Rrsi, + sizeof(oopDesc) + + Klass::secondary_super_cache_offset_in_bytes()), + Rrax); + } __ bind(hit); if ($primary) { __ xorq(Rrdi, Rrdi); @@ -3693,10 +3734,10 @@ encode %{ int count_offset = java_lang_String::count_offset_in_bytes(); int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); - masm.movq(rax, Address(rsi, value_offset)); + masm.load_heap_oop(rax, Address(rsi, value_offset)); masm.movl(rcx, Address(rsi, offset_offset)); masm.leaq(rax, Address(rax, rcx, Address::times_2, base_offset)); - masm.movq(rbx, Address(rdi, value_offset)); + masm.load_heap_oop(rbx, Address(rdi, value_offset)); masm.movl(rcx, Address(rdi, offset_offset)); masm.leaq(rbx, Address(rbx, rcx, Address::times_2, base_offset)); @@ -4120,6 +4161,7 @@ encode %{ %} + //----------FRAME-------------------------------------------------------------- // Definition of frame structure and management information. // @@ -4255,6 +4297,7 @@ frame static const int lo[Op_RegL + 1] = { 0, 0, + RAX_num, // Op_RegN RAX_num, // Op_RegI RAX_num, // Op_RegP XMM0_num, // Op_RegF @@ -4264,13 +4307,14 @@ frame static const int hi[Op_RegL + 1] = { 0, 0, + OptoReg::Bad, // Op_RegN OptoReg::Bad, // Op_RegI RAX_H_num, // Op_RegP OptoReg::Bad, // Op_RegF XMM0_H_num, // Op_RegD RAX_H_num // Op_RegL }; - + assert(ARRAY_SIZE(hi) == _last_machine_leaf - 1, "missing type"); return OptoRegPair(hi[ideal_reg], lo[ideal_reg]); %} %} @@ -4417,9 +4461,25 @@ operand immP0() interface(CONST_INTER); %} -// Unsigned 31-bit Pointer Immediate -// Can be used in both 32-bit signed and 32-bit unsigned insns. -// Works for nulls and markOops; not for relocatable (oop) pointers. +// Pointer Immediate +operand immN() %{ + match(ConN); + + op_cost(10); + format %{ %} + interface(CONST_INTER); +%} + +// NULL Pointer Immediate +operand immN0() %{ + predicate(n->get_narrowcon() == 0); + match(ConN); + + op_cost(5); + format %{ %} + interface(CONST_INTER); +%} + operand immP31() %{ predicate(!n->as_Type()->type()->isa_oopptr() @@ -4431,6 +4491,7 @@ operand immP31() interface(CONST_INTER); %} + // Long Immediate operand immL() %{ @@ -4767,6 +4828,23 @@ operand rRegP() interface(REG_INTER); %} + +operand r12RegL() %{ + constraint(ALLOC_IN_RC(long_r12_reg)); + match(RegL); + + format %{ %} + interface(REG_INTER); +%} + +operand rRegN() %{ + constraint(ALLOC_IN_RC(int_reg)); + match(RegN); + + format %{ %} + interface(REG_INTER); +%} + // Question: Why is r15_RegP (the read-only TLS register) a match for rRegP? // Answer: Operand match rules govern the DFA as it processes instruction inputs. // It's fine for an instruction input which expects rRegP to match a r15_RegP. @@ -4822,6 +4900,18 @@ operand rax_RegP() interface(REG_INTER); %} +// Special Registers +// Return a compressed pointer value +operand rax_RegN() +%{ + constraint(ALLOC_IN_RC(int_rax_reg)); + match(RegN); + match(rRegN); + + format %{ %} + interface(REG_INTER); +%} + // Used in AtomicAdd operand rbx_RegP() %{ @@ -5112,6 +5202,21 @@ operand indIndexScaleOffset(any_RegP reg, immL32 off, rRegL lreg, immI2 scale) %} %} +// Indirect Memory Times Scale Plus Index Register Plus Offset Operand +operand indIndexScaleOffsetComp(rRegN src, immL32 off, r12RegL base) %{ + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP (DecodeN src base) off); + + op_cost(10); + format %{"[$base + $src << 3 + $off] (compressed)" %} + interface(MEMORY_INTER) %{ + base($base); + index($src); + scale(0x3); + disp($off); + %} +%} + // Indirect Memory Times Scale Plus Positive Index Register Plus Offset Operand operand indPosIndexScaleOffset(any_RegP reg, immL32 off, rRegI idx, immI2 scale) %{ @@ -5259,7 +5364,8 @@ operand cmpOpU() // case of this is memory operands. opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex, - indIndexScale, indIndexScaleOffset, indPosIndexScaleOffset); + indIndexScale, indIndexScaleOffset, indPosIndexScaleOffset, + indIndexScaleOffsetComp); //----------PIPELINE----------------------------------------------------------- // Rules which define the behavior of the target architectures pipeline. @@ -5937,10 +6043,28 @@ instruct loadP(rRegP dst, memory mem) ins_pipe(ialu_reg_mem); // XXX %} +// Load Compressed Pointer +instruct loadN(rRegN dst, memory mem, rFlagsReg cr) +%{ + match(Set dst (LoadN mem)); + effect(KILL cr); + + ins_cost(125); // XXX + format %{ "movl $dst, $mem\t# compressed ptr" %} + ins_encode %{ + Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); + Register dst = as_Register($dst$$reg); + __ movl(dst, addr); + %} + ins_pipe(ialu_reg_mem); // XXX +%} + + // Load Klass Pointer instruct loadKlass(rRegP dst, memory mem) %{ match(Set dst (LoadKlass mem)); + predicate(!n->in(MemNode::Address)->bottom_type()->is_narrow()); ins_cost(125); // XXX format %{ "movq $dst, $mem\t# class" %} @@ -5949,6 +6073,26 @@ instruct loadKlass(rRegP dst, memory mem) ins_pipe(ialu_reg_mem); // XXX %} +// Load Klass Pointer +instruct loadKlassComp(rRegP dst, memory mem) +%{ + match(Set dst (LoadKlass mem)); + predicate(n->in(MemNode::Address)->bottom_type()->is_narrow()); + + ins_cost(125); // XXX + format %{ "movl $dst, $mem\t# compressed class\n\t" + "decode_heap_oop $dst,$dst" %} + ins_encode %{ + Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); + Register dst = as_Register($dst$$reg); + __ movl(dst, addr); + // klass is never null in the header but this is generated for all + // klass loads not just the _klass field in the header. + __ decode_heap_oop(dst); + %} + ins_pipe(ialu_reg_mem); // XXX +%} + // Load Float instruct loadF(regF dst, memory mem) %{ @@ -6203,6 +6347,36 @@ instruct loadConF(regF dst, immF src) ins_pipe(pipe_slow); %} +instruct loadConN0(rRegN dst, immN0 src, rFlagsReg cr) %{ + match(Set dst src); + effect(KILL cr); + format %{ "xorq $dst, $src\t# compressed NULL ptr" %} + ins_encode %{ + Register dst = $dst$$Register; + __ xorq(dst, dst); + %} + ins_pipe(ialu_reg); +%} + +instruct loadConN(rRegN dst, immN src) %{ + match(Set dst src); + + ins_cost(125); + format %{ "movq $dst, $src\t# compressed ptr\n\t" + "encode_heap_oop_not_null $dst,$dst" %} + ins_encode %{ + address con = (address)$src$$constant; + Register dst = $dst$$Register; + if (con == NULL) { + ShouldNotReachHere(); + } else { + __ movoop(dst, (jobject)$src$$constant); + __ encode_heap_oop_not_null(dst); + } + %} + ins_pipe(ialu_reg_fat); // XXX +%} + instruct loadConF0(regF dst, immF0 src) %{ match(Set dst src); @@ -6458,6 +6632,22 @@ instruct storeImmP(memory mem, immP31 src) ins_pipe(ialu_mem_imm); %} +// Store Compressed Pointer +instruct storeN(memory mem, rRegN src, rFlagsReg cr) +%{ + match(Set mem (StoreN mem src)); + effect(KILL cr); + + ins_cost(125); // XXX + format %{ "movl $mem, $src\t# ptr" %} + ins_encode %{ + Address addr = build_address($mem$$base, $mem$$index, $mem$$scale, $mem$$disp); + Register src = as_Register($src$$reg); + __ movl(addr, src); + %} + ins_pipe(ialu_mem_reg); +%} + // Store Integer Immediate instruct storeImmI(memory mem, immI src) %{ @@ -6805,6 +6995,66 @@ instruct castP2X(rRegL dst, rRegP src) ins_pipe(ialu_reg_reg); // XXX %} + +// Convert oop pointer into compressed form +instruct encodeHeapOop(rRegN dst, rRegP src, rFlagsReg cr) %{ + predicate(n->bottom_type()->is_narrowoop()->make_oopptr()->ptr() != TypePtr::NotNull); + match(Set dst (EncodeP src)); + effect(KILL cr); + format %{ "encode_heap_oop $dst,$src" %} + ins_encode %{ + Register s = $src$$Register; + Register d = $dst$$Register; + if (s != d) { + __ movq(d, s); + } + __ encode_heap_oop(d); + %} + ins_pipe(ialu_reg_long); +%} + +instruct encodeHeapOop_not_null(rRegN dst, rRegP src, rFlagsReg cr) %{ + predicate(n->bottom_type()->is_narrowoop()->make_oopptr()->ptr() == TypePtr::NotNull); + match(Set dst (EncodeP src)); + effect(KILL cr); + format %{ "encode_heap_oop_not_null $dst,$src" %} + ins_encode %{ + Register s = $src$$Register; + Register d = $dst$$Register; + __ encode_heap_oop_not_null(d, s); + %} + ins_pipe(ialu_reg_long); +%} + +instruct decodeHeapOop(rRegP dst, rRegN src, rFlagsReg cr) %{ + predicate(n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull); + match(Set dst (DecodeN src)); + effect(KILL cr); + format %{ "decode_heap_oop $dst,$src" %} + ins_encode %{ + Register s = $src$$Register; + Register d = $dst$$Register; + if (s != d) { + __ movq(d, s); + } + __ decode_heap_oop(d); + %} + ins_pipe(ialu_reg_long); +%} + +instruct decodeHeapOop_not_null(rRegP dst, rRegN src) %{ + predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull); + match(Set dst (DecodeN src)); + format %{ "decode_heap_oop_not_null $dst,$src" %} + ins_encode %{ + Register s = $src$$Register; + Register d = $dst$$Register; + __ decode_heap_oop_not_null(d, s); + %} + ins_pipe(ialu_reg_long); +%} + + //----------Conditional Move--------------------------------------------------- // Jump // dummy instruction for generating temp registers @@ -7521,6 +7771,28 @@ instruct compareAndSwapI(rRegI res, %} +instruct compareAndSwapN(rRegI res, + memory mem_ptr, + rax_RegN oldval, rRegN newval, + rFlagsReg cr) %{ + match(Set res (CompareAndSwapN mem_ptr (Binary oldval newval))); + effect(KILL cr, KILL oldval); + + format %{ "cmpxchgl $mem_ptr,$newval\t# " + "If rax == $mem_ptr then store $newval into $mem_ptr\n\t" + "sete $res\n\t" + "movzbl $res, $res" %} + opcode(0x0F, 0xB1); + ins_encode(lock_prefix, + REX_reg_mem(newval, mem_ptr), + OpcP, OpcS, + reg_mem(newval, mem_ptr), + REX_breg(res), Opcode(0x0F), Opcode(0x94), reg(res), // sete + REX_reg_breg(res, res), // movzbl + Opcode(0xF), Opcode(0xB6), reg_reg(res, res)); + ins_pipe( pipe_cmpxchg ); +%} + //----------Subtraction Instructions------------------------------------------- // Integer Subtraction Instructions @@ -7803,6 +8075,18 @@ instruct mulL_mem_imm(rRegL dst, memory src, immL32 imm, rFlagsReg cr) ins_pipe(ialu_reg_mem_alu0); %} +instruct mulHiL_rReg(rdx_RegL dst, no_rax_RegL src, rax_RegL rax, rFlagsReg cr) +%{ + match(Set dst (MulHiL src rax)); + effect(USE_KILL rax, KILL cr); + + ins_cost(300); + format %{ "imulq RDX:RAX, RAX, $src\t# mulhi" %} + opcode(0xF7, 0x5); /* Opcode F7 /5 */ + ins_encode(REX_reg_wide(src), OpcP, reg_opc(src)); + ins_pipe(ialu_reg_reg_alu0); +%} + instruct divI_rReg(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div, rFlagsReg cr) %{ @@ -10771,6 +11055,14 @@ instruct testP_reg_mem(rFlagsReg cr, memory op, immP0 zero) ins_pipe(ialu_cr_reg_imm); %} +instruct testN_reg(rFlagsReg cr, rRegN src, immN0 zero) %{ + match(Set cr (CmpN src zero)); + + format %{ "testl $src, $src" %} + ins_encode %{ __ testl($src$$Register, $src$$Register); %} + ins_pipe(ialu_cr_reg_imm); +%} + // Yanked all unsigned pointer compare operations. // Pointer compares are done with CmpP which is already unsigned. @@ -11018,6 +11310,7 @@ instruct partialSubtypeCheck_vs_Zero(rFlagsReg cr, rdi_RegP result) %{ match(Set cr (CmpP (PartialSubtypeCheck sub super) zero)); + predicate(!UseCompressedOops); // decoding oop kills condition codes effect(KILL rcx, KILL result); ins_cost(1000); diff --git a/hotspot/src/share/vm/compiler/disassemblerEnv.hpp b/hotspot/src/os/linux/vm/dtraceJSDT_linux.cpp similarity index 68% rename from hotspot/src/share/vm/compiler/disassemblerEnv.hpp rename to hotspot/src/os/linux/vm/dtraceJSDT_linux.cpp index 69bb38f77c1..ea0eab9b975 100644 --- a/hotspot/src/share/vm/compiler/disassemblerEnv.hpp +++ b/hotspot/src/os/linux/vm/dtraceJSDT_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2002 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,14 +22,18 @@ * */ -// Call-back interface for external disassembler -class DisassemblerEnv { - public: - // printing - virtual void print_label(intptr_t value) = 0; - virtual void print_raw(char* str) = 0; - virtual void print(char* format, ...) = 0; - // helpers - virtual char* string_for_offset(intptr_t value) = 0; - virtual char* string_for_constant(unsigned char* pc, intptr_t value, int is_decimal) = 0; -}; +#include "incls/_precompiled.incl" +#include "incls/_dtraceJSDT_linux.cpp.incl" + +int DTraceJSDT::pd_activate( + void* baseAddress, jstring module, + jint providers_count, JVM_DTraceProvider* providers) { + return -1; +} + +void DTraceJSDT::pd_dispose(int handle) { +} + +jboolean DTraceJSDT::pd_is_supported() { + return false; +} diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 28289bce61c..d28700aab88 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2228,20 +2228,42 @@ bool os::commit_memory(char* addr, size_t size, size_t alignment_hint) { } void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } -void os::free_memory(char *addr, size_t bytes) { } + +void os::free_memory(char *addr, size_t bytes) { + uncommit_memory(addr, bytes); +} + void os::numa_make_global(char *addr, size_t bytes) { } -void os::numa_make_local(char *addr, size_t bytes) { } -bool os::numa_topology_changed() { return false; } -size_t os::numa_get_groups_num() { return 1; } -int os::numa_get_group_id() { return 0; } -size_t os::numa_get_leaf_groups(int *ids, size_t size) { - if (size > 0) { - ids[0] = 0; - return 1; + +void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { + Linux::numa_tonode_memory(addr, bytes, lgrp_hint); +} + +bool os::numa_topology_changed() { return false; } + +size_t os::numa_get_groups_num() { + int max_node = Linux::numa_max_node(); + return max_node > 0 ? max_node + 1 : 1; +} + +int os::numa_get_group_id() { + int cpu_id = Linux::sched_getcpu(); + if (cpu_id != -1) { + int lgrp_id = Linux::get_node_by_cpu(cpu_id); + if (lgrp_id != -1) { + return lgrp_id; + } } return 0; } +size_t os::numa_get_leaf_groups(int *ids, size_t size) { + for (size_t i = 0; i < size; i++) { + ids[i] = i; + } + return size; +} + bool os::get_page_info(char *start, page_info* info) { return false; } @@ -2250,6 +2272,74 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info return end; } +extern "C" void numa_warn(int number, char *where, ...) { } +extern "C" void numa_error(char *where) { } + +void os::Linux::libnuma_init() { + // sched_getcpu() should be in libc. + set_sched_getcpu(CAST_TO_FN_PTR(sched_getcpu_func_t, + dlsym(RTLD_DEFAULT, "sched_getcpu"))); + + if (sched_getcpu() != -1) { // Does it work? + void *handle = dlopen("libnuma.so", RTLD_LAZY); + if (handle != NULL) { + set_numa_node_to_cpus(CAST_TO_FN_PTR(numa_node_to_cpus_func_t, + dlsym(handle, "numa_node_to_cpus"))); + set_numa_max_node(CAST_TO_FN_PTR(numa_max_node_func_t, + dlsym(handle, "numa_max_node"))); + set_numa_available(CAST_TO_FN_PTR(numa_available_func_t, + dlsym(handle, "numa_available"))); + set_numa_tonode_memory(CAST_TO_FN_PTR(numa_tonode_memory_func_t, + dlsym(handle, "numa_tonode_memory"))); + if (numa_available() != -1) { + // Create a cpu -> node mapping + _cpu_to_node = new (ResourceObj::C_HEAP) GrowableArray(0, true); + rebuild_cpu_to_node_map(); + } + } + } +} + +// rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id. +// The table is later used in get_node_by_cpu(). +void os::Linux::rebuild_cpu_to_node_map() { + int cpu_num = os::active_processor_count(); + cpu_to_node()->clear(); + cpu_to_node()->at_grow(cpu_num - 1); + int node_num = numa_get_groups_num(); + int cpu_map_size = (cpu_num + BitsPerLong - 1) / BitsPerLong; + unsigned long *cpu_map = NEW_C_HEAP_ARRAY(unsigned long, cpu_map_size); + for (int i = 0; i < node_num; i++) { + if (numa_node_to_cpus(i, cpu_map, cpu_map_size * sizeof(unsigned long)) != -1) { + for (int j = 0; j < cpu_map_size; j++) { + if (cpu_map[j] != 0) { + for (int k = 0; k < BitsPerLong; k++) { + if (cpu_map[j] & (1UL << k)) { + cpu_to_node()->at_put(j * BitsPerLong + k, i); + } + } + } + } + } + } + FREE_C_HEAP_ARRAY(unsigned long, cpu_map); +} + +int os::Linux::get_node_by_cpu(int cpu_id) { + if (cpu_to_node() != NULL && cpu_id >= 0 && cpu_id < cpu_to_node()->length()) { + return cpu_to_node()->at(cpu_id); + } + return -1; +} + +GrowableArray* os::Linux::_cpu_to_node; +os::Linux::sched_getcpu_func_t os::Linux::_sched_getcpu; +os::Linux::numa_node_to_cpus_func_t os::Linux::_numa_node_to_cpus; +os::Linux::numa_max_node_func_t os::Linux::_numa_max_node; +os::Linux::numa_available_func_t os::Linux::_numa_available; +os::Linux::numa_tonode_memory_func_t os::Linux::_numa_tonode_memory; + + bool os::uncommit_memory(char* addr, size_t size) { return ::mmap(addr, size, PROT_READ|PROT_WRITE|PROT_EXEC, @@ -3552,6 +3642,10 @@ jint os::init_2(void) Linux::is_floating_stack() ? "floating stack" : "fixed stack"); } + if (UseNUMA) { + Linux::libnuma_init(); + } + if (MaxFDLimit) { // set the number of file descriptors to max. print out error // if getrlimit/setrlimit fails but continue regardless. diff --git a/hotspot/src/os/linux/vm/os_linux.hpp b/hotspot/src/os/linux/vm/os_linux.hpp index e3a204dc6cf..54fc117311f 100644 --- a/hotspot/src/os/linux/vm/os_linux.hpp +++ b/hotspot/src/os/linux/vm/os_linux.hpp @@ -59,6 +59,8 @@ class Linux { static bool _is_NPTL; static bool _supports_fast_thread_cpu_time; + static GrowableArray* _cpu_to_node; + protected: static julong _physical_memory; @@ -79,8 +81,9 @@ class Linux { static void set_is_LinuxThreads() { _is_NPTL = false; } static void set_is_floating_stack() { _is_floating_stack = true; } + static void rebuild_cpu_to_node_map(); + static GrowableArray* cpu_to_node() { return _cpu_to_node; } public: - static void init_thread_fpu_state(); static int get_fpu_control_word(); static void set_fpu_control_word(int fpu_control); @@ -143,6 +146,7 @@ class Linux { static bool is_floating_stack() { return _is_floating_stack; } static void libpthread_init(); + static void libnuma_init(); // Minimum stack size a thread can be created with (allowing // the VM to completely create the thread and enter user code) @@ -229,6 +233,38 @@ class Linux { #undef SR_SUSPENDED }; + +private: + typedef int (*sched_getcpu_func_t)(void); + typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen); + typedef int (*numa_max_node_func_t)(void); + typedef int (*numa_available_func_t)(void); + typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node); + + + static sched_getcpu_func_t _sched_getcpu; + static numa_node_to_cpus_func_t _numa_node_to_cpus; + static numa_max_node_func_t _numa_max_node; + static numa_available_func_t _numa_available; + static numa_tonode_memory_func_t _numa_tonode_memory; + + static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; } + static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; } + static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; } + static void set_numa_available(numa_available_func_t func) { _numa_available = func; } + static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; } + +public: + static int sched_getcpu() { return _sched_getcpu != NULL ? _sched_getcpu() : -1; } + static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) { + return _numa_node_to_cpus != NULL ? _numa_node_to_cpus(node, buffer, bufferlen) : -1; + } + static int numa_max_node() { return _numa_max_node != NULL ? _numa_max_node() : -1; } + static int numa_available() { return _numa_available != NULL ? _numa_available() : -1; } + static int numa_tonode_memory(void *start, size_t size, int node) { + return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1; + } + static int get_node_by_cpu(int cpu_id); }; diff --git a/hotspot/src/os/linux/vm/os_linux.inline.hpp b/hotspot/src/os/linux/vm/os_linux.inline.hpp index 55985cb3a34..399fa0c4474 100644 --- a/hotspot/src/os/linux/vm/os_linux.inline.hpp +++ b/hotspot/src/os/linux/vm/os_linux.inline.hpp @@ -120,3 +120,6 @@ inline int os::closedir(DIR *dirp) RESTARTABLE(_cmd, _result); \ return _result; \ } while(false) + +inline bool os::numa_has_static_binding() { return true; } +inline bool os::numa_has_group_homing() { return false; } diff --git a/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp b/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp index bceed658536..8e9be682488 100644 --- a/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp +++ b/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp @@ -196,7 +196,7 @@ int generateJvmOffsets(GEN_variant gen_variant) { printf("\n"); GEN_VALUE(OFFSET_HeapBlockHeader_used, offset_of(HeapBlock::Header, _used)); - GEN_OFFS(oopDesc, _klass); + GEN_OFFS(oopDesc, _metadata); printf("\n"); GEN_VALUE(AccessFlags_NATIVE, JVM_ACC_NATIVE); diff --git a/hotspot/src/os/solaris/dtrace/jhelper.d b/hotspot/src/os/solaris/dtrace/jhelper.d index ffbc7ad02ba..19b4c08c2d3 100644 --- a/hotspot/src/os/solaris/dtrace/jhelper.d +++ b/hotspot/src/os/solaris/dtrace/jhelper.d @@ -46,6 +46,7 @@ extern pointer __JvmOffsets; extern pointer __1cJCodeCacheF_heap_; extern pointer __1cIUniverseP_methodKlassObj_; extern pointer __1cIUniverseO_collectedHeap_; +extern pointer __1cIUniverseK_heap_base_; extern pointer __1cHnmethodG__vtbl_; extern pointer __1cKBufferBlobG__vtbl_; @@ -107,7 +108,7 @@ dtrace:helper:ustack: copyin_offset(OFFSET_constantPoolOopDesc_pool_holder); copyin_offset(OFFSET_HeapBlockHeader_used); - copyin_offset(OFFSET_oopDesc_klass); + copyin_offset(OFFSET_oopDesc_metadata); copyin_offset(OFFSET_symbolOopDesc_length); copyin_offset(OFFSET_symbolOopDesc_body); @@ -150,6 +151,7 @@ dtrace:helper:ustack: this->Universe_methodKlassOop = copyin_ptr(&``__1cIUniverseP_methodKlassObj_); this->CodeCache_heap_address = copyin_ptr(&``__1cJCodeCacheF_heap_); + this->Universe_heap_base = copyin_ptr(&``__1cIUniverseK_heap_base_); /* Reading volatile values */ this->CodeCache_low = copyin_ptr(this->CodeCache_heap_address + @@ -293,10 +295,27 @@ dtrace:helper:ustack: dtrace:helper:ustack: /!this->done && this->vtbl == this->BufferBlob_vtbl && +this->Universe_heap_base == NULL && this->methodOopPtr > this->heap_start && this->methodOopPtr < this->heap_end/ { MARK_LINE; - this->klass = copyin_ptr(this->methodOopPtr + OFFSET_oopDesc_klass); + this->klass = copyin_ptr(this->methodOopPtr + OFFSET_oopDesc_metadata); + this->methodOop = this->klass == this->Universe_methodKlassOop; + this->done = !this->methodOop; +} + +dtrace:helper:ustack: +/!this->done && this->vtbl == this->BufferBlob_vtbl && +this->Universe_heap_base != NULL && +this->methodOopPtr > this->heap_start && this->methodOopPtr < this->heap_end/ +{ + MARK_LINE; + /* + * Read compressed pointer and decode heap oop, same as oop.inline.hpp + */ + this->cklass = copyin_uint32(this->methodOopPtr + OFFSET_oopDesc_metadata); + this->klass = (uint64_t)((uintptr_t)this->Universe_heap_base + + ((uintptr_t)this->cklass << 3)); this->methodOop = this->klass == this->Universe_methodKlassOop; this->done = !this->methodOop; } diff --git a/hotspot/src/os/solaris/dtrace/libjvm_db.c b/hotspot/src/os/solaris/dtrace/libjvm_db.c index ac21ec23b19..5c133663d4b 100644 --- a/hotspot/src/os/solaris/dtrace/libjvm_db.c +++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c @@ -148,9 +148,11 @@ struct jvm_agent { uint64_t Universe_methodKlassObj_address; uint64_t CodeCache_heap_address; + uint64_t Universe_heap_base_address; /* Volatiles */ uint64_t Universe_methodKlassObj; + uint64_t Universe_heap_base; uint64_t CodeCache_low; uint64_t CodeCache_high; uint64_t CodeCache_segmap_low; @@ -166,7 +168,6 @@ struct jvm_agent { Frame_t curr_fr; }; - static int read_string(struct ps_prochandle *P, char *buf, /* caller's buffer */ @@ -185,6 +186,14 @@ read_string(struct ps_prochandle *P, return -1; } +static int read_compressed_pointer(jvm_agent_t* J, uint64_t base, uint32_t *ptr) { + int err = -1; + uint32_t ptr32; + err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t)); + *ptr = ptr32; + return err; +} + static int read_pointer(jvm_agent_t* J, uint64_t base, uint64_t* ptr) { int err = -1; uint32_t ptr32; @@ -270,6 +279,9 @@ static int parse_vmstructs(jvm_agent_t* J) { if (strcmp("_methodKlassObj", vmp->fieldName) == 0) { J->Universe_methodKlassObj_address = vmp->address; } + if (strcmp("_heap_base", vmp->fieldName) == 0) { + J->Universe_heap_base_address = vmp->address; + } } CHECK_FAIL(err); @@ -292,6 +304,8 @@ static int read_volatiles(jvm_agent_t* J) { err = read_pointer(J, J->Universe_methodKlassObj_address, &J->Universe_methodKlassObj); CHECK_FAIL(err); + err = read_pointer(J, J->Universe_heap_base_address, &J->Universe_heap_base); + CHECK_FAIL(err); err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low, &J->CodeCache_low); CHECK_FAIL(err); @@ -444,7 +458,17 @@ void Jagent_destroy(jvm_agent_t *J) { static int is_methodOop(jvm_agent_t* J, uint64_t methodOopPtr) { uint64_t klass; int err; - err = read_pointer(J, methodOopPtr + OFFSET_oopDesc_klass, &klass); + // If heap_base is nonnull, this was a compressed oop. + if (J->Universe_heap_base != NULL) { + uint32_t cklass; + err = read_compressed_pointer(J, methodOopPtr + OFFSET_oopDesc_metadata, + &cklass); + // decode heap oop, same as oop.inline.hpp + klass = (uint64_t)((uintptr_t)J->Universe_heap_base + + ((uintptr_t)cklass << 3)); + } else { + err = read_pointer(J, methodOopPtr + OFFSET_oopDesc_metadata, &klass); + } if (err != PS_OK) goto fail; return klass == J->Universe_methodKlassObj; diff --git a/hotspot/src/os/solaris/vm/dtraceJSDT_solaris.cpp b/hotspot/src/os/solaris/vm/dtraceJSDT_solaris.cpp new file mode 100644 index 00000000000..49f74216f16 --- /dev/null +++ b/hotspot/src/os/solaris/vm/dtraceJSDT_solaris.cpp @@ -0,0 +1,685 @@ +/* + * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#include "incls/_precompiled.incl" +#include "incls/_dtraceJSDT_solaris.cpp.incl" + +#ifdef HAVE_DTRACE_H + +#include +#include +#include +#include +#include + +static const char* devname = "/dev/dtrace/helper"; +static const char* olddevname = "/devices/pseudo/dtrace@0:helper"; + +static const char* string_sig = "uintptr_t"; +static const char* int_sig = "long"; +static const char* long_sig = "long long"; + +static void printDOFHelper(dof_helper_t* helper); + +static int dofhelper_open() { + int fd; + if ((fd = open64(devname, O_RDWR)) < 0) { + // Optimize next calls + devname = olddevname; + if ((fd = open64(devname, O_RDWR)) < 0) { + return -1; + } + } + return fd; +} + +static jint dof_register(jstring module, uint8_t* dof, void* modaddr) { + int probe; + dof_helper_t dh; + int fd; + + memset(&dh, 0, sizeof(dh)); + + char* module_name = java_lang_String::as_utf8_string( + JNIHandles::resolve_non_null(module)); + jio_snprintf(dh.dofhp_mod, sizeof(dh.dofhp_mod), "%s", module_name); + dh.dofhp_dof = (uint64_t)dof; + dh.dofhp_addr = (uint64_t)modaddr; + + fd = dofhelper_open(); + if (fd < 0) + return -1; + probe = ioctl(fd, DTRACEHIOC_ADDDOF, &dh); + close(fd); + if (PrintDTraceDOF) { + printDOFHelper(&dh); + tty->print_cr("DOF helper id = %d", probe); + } + return probe; +} + +int DTraceJSDT::pd_activate( + void* moduleBaseAddress, jstring module, + jint providers_count, JVM_DTraceProvider* providers) { + + // We need sections: + // (1) STRTAB + // ( + // (2) PROVIDER + // (3) PROBES + // (4) PROBOFFS + // (5) PROBARGS + // ) * Number of Providers + + // Type of sections we create + enum { + STRTAB = 0, + PROVIDERS = 1, + PROBES = 2, + PROBE_OFFSETS = 3, + ARG_OFFSETS = 4, + NUM_SECTIONS = 5 + }; + + static int alignment_for[NUM_SECTIONS] = { 1, 4, 8, 4, 1 }; + + ResourceMark rm; + + uint32_t num_sections = 1 + 4 * providers_count; + uint32_t offset = sizeof(dof_hdr_t) + (num_sections * sizeof(dof_sec_t)); + uint32_t* secoffs = NEW_RESOURCE_ARRAY(uint32_t, num_sections); + uint32_t* secsize = NEW_RESOURCE_ARRAY(uint32_t, num_sections); + + // Store offsets of all strings here in such order: + // zero-string (always 0) + // provider1-name + // probe1-function + // probe1-name + // arg-1 + // arg-2 + // ... + // probe2-function + // probe2-name + // arg-1 + // arg-2 + // provider2-name + // ... + + uint32_t strcount = 0; + // Count the number of strings we'll need + for(int prvc = 0; prvc < providers_count; ++prvc) { + JVM_DTraceProvider* provider = &providers[prvc]; + // Provider name + ++strcount; + for(int prbc = 0; prbc < provider->probe_count; ++prbc) { + JVM_DTraceProbe* p = &(provider->probes[prbc]); + symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); + // function + name + one per argument + strcount += 2 + ArgumentCount(sig).size(); + } + } + + // Create place for string offsets + uint32_t* stroffs = NEW_RESOURCE_ARRAY(uint32_t, strcount + 1); + uint32_t string_index = 0; + uint32_t curstr = 0; + + // First we need an empty string: "" + stroffs[curstr++] = string_index; + string_index += strlen("") + 1; + + for(int prvc = 0; prvc < providers_count; ++prvc) { + JVM_DTraceProvider* provider = &providers[prvc]; + char* provider_name = java_lang_String::as_utf8_string( + JNIHandles::resolve_non_null(provider->name)); + stroffs[curstr++] = string_index; + string_index += strlen(provider_name) + 1; + + // All probes + for(int prbc = 0; prbc < provider->probe_count; ++prbc) { + JVM_DTraceProbe* p = &(provider->probes[prbc]); + + char* function = java_lang_String::as_utf8_string( + JNIHandles::resolve_non_null(p->function)); + stroffs[curstr++] = string_index; + string_index += strlen(function) + 1; + + char* name = java_lang_String::as_utf8_string( + JNIHandles::resolve_non_null(p->name)); + stroffs[curstr++] = string_index; + string_index += strlen(name) + 1; + + symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); + SignatureStream ss(sig); + for ( ; !ss.at_return_type(); ss.next()) { + BasicType bt = ss.type(); + const char* t = NULL; + if (bt == T_OBJECT && + ss.as_symbol_or_null() == vmSymbols::java_lang_String()) { + t = string_sig; + } else if (bt == T_LONG) { + t = long_sig; + } else { + t = int_sig; + } + stroffs[curstr++] = string_index; + string_index += strlen(t) + 1; + } + } + } + secoffs[STRTAB] = offset; + secsize[STRTAB] = string_index; + offset += string_index; + + // Calculate the size of the rest + for(int prvc = 0; prvc < providers_count; ++prvc) { + JVM_DTraceProvider* provider = &providers[prvc]; + size_t provider_sec = PROVIDERS + prvc * 4; + size_t probe_sec = PROBES + prvc * 4; + size_t probeoffs_sec = PROBE_OFFSETS + prvc * 4; + size_t argoffs_sec = ARG_OFFSETS + prvc * 4; + + // Allocate space for the provider data struction + secoffs[provider_sec] = align_size_up(offset, alignment_for[PROVIDERS]); + secsize[provider_sec] = sizeof(dof_provider_t); + offset = secoffs[provider_sec] + secsize[provider_sec]; + + // Allocate space for all the probes + secoffs[probe_sec] = align_size_up(offset, alignment_for[PROBES]); + secsize[probe_sec] = sizeof(dof_probe_t) * provider->probe_count; + offset = secoffs[probe_sec] + secsize[probe_sec]; + + // Allocate space for the probe offsets + secoffs[probeoffs_sec] = align_size_up(offset, alignment_for[PROBE_OFFSETS]); + secsize[probeoffs_sec] = sizeof(uint32_t) * provider->probe_count; + offset = secoffs[probeoffs_sec] + secsize[probeoffs_sec]; + + // We need number of arguments argoffs + uint32_t argscount = 0; + for(int prbc = 0; prbc < provider->probe_count; ++prbc) { + JVM_DTraceProbe* p = &(provider->probes[prbc]); + symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); + argscount += ArgumentCount(sig).size(); + } + secoffs[argoffs_sec] = align_size_up(offset, alignment_for[ARG_OFFSETS]); + secsize[argoffs_sec] = sizeof(uint8_t) * argscount; + offset = secoffs[argoffs_sec] + secsize[argoffs_sec]; + } + + uint32_t size = offset; + + uint8_t* dof = NEW_RESOURCE_ARRAY(uint8_t, size); + if (!dof) { + return -1; + } + memset((void*)dof, 0, size); + + // Fill memory with proper values + dof_hdr_t* hdr = (dof_hdr_t*)dof; + hdr->dofh_ident[DOF_ID_MAG0] = DOF_MAG_MAG0; + hdr->dofh_ident[DOF_ID_MAG1] = DOF_MAG_MAG1; + hdr->dofh_ident[DOF_ID_MAG2] = DOF_MAG_MAG2; + hdr->dofh_ident[DOF_ID_MAG3] = DOF_MAG_MAG3; + hdr->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_NATIVE; // No variants + hdr->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE; // No variants + hdr->dofh_ident[DOF_ID_VERSION] = DOF_VERSION_1; // No variants + hdr->dofh_ident[DOF_ID_DIFVERS] = DIF_VERSION_2; // No variants + // all other fields of ident to zero + + hdr->dofh_flags = 0; + hdr->dofh_hdrsize = sizeof(dof_hdr_t); + hdr->dofh_secsize = sizeof(dof_sec_t); + hdr->dofh_secnum = num_sections; + hdr->dofh_secoff = sizeof(dof_hdr_t); + hdr->dofh_loadsz = size; + hdr->dofh_filesz = size; + + // First section: STRTAB + dof_sec_t* sec = (dof_sec_t*)(dof + sizeof(dof_hdr_t)); + sec->dofs_type = DOF_SECT_STRTAB; + sec->dofs_align = alignment_for[STRTAB]; + sec->dofs_flags = DOF_SECF_LOAD; + sec->dofs_entsize = 0; + sec->dofs_offset = secoffs[STRTAB]; + sec->dofs_size = secsize[STRTAB]; + // Make data for this section + char* str = (char*)(dof + sec->dofs_offset); + + *str = 0; str += 1; // "" + + // Run through all strings again + for(int prvc = 0; prvc < providers_count; ++prvc) { + JVM_DTraceProvider* provider = &providers[prvc]; + char* provider_name = java_lang_String::as_utf8_string( + JNIHandles::resolve_non_null(provider->name)); + strcpy(str, provider_name); + str += strlen(provider_name) + 1; + + // All probes + for(int prbc = 0; prbc < provider->probe_count; ++prbc) { + JVM_DTraceProbe* p = &(provider->probes[prbc]); + + char* function = java_lang_String::as_utf8_string( + JNIHandles::resolve_non_null(p->function)); + strcpy(str, function); + str += strlen(str) + 1; + + char* name = java_lang_String::as_utf8_string( + JNIHandles::resolve_non_null(p->name)); + strcpy(str, name); + str += strlen(name) + 1; + + symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); + SignatureStream ss(sig); + for ( ; !ss.at_return_type(); ss.next()) { + BasicType bt = ss.type(); + const char* t; + if (bt == T_OBJECT && + ss.as_symbol_or_null() == vmSymbols::java_lang_String()) { + t = string_sig; + } else if (bt == T_LONG) { + t = long_sig; + } else { + t = int_sig; + } + strcpy(str, t); + str += strlen(t) + 1; + } + } + } + + curstr = 1; + for(int prvc = 0; prvc < providers_count; ++prvc) { + JVM_DTraceProvider* provider = &providers[prvc]; + size_t provider_sec = PROVIDERS + prvc * 4; + size_t probe_sec = PROBES + prvc * 4; + size_t probeoffs_sec = PROBE_OFFSETS + prvc * 4; + size_t argoffs_sec = ARG_OFFSETS + prvc * 4; + + // PROVIDER /////////////////////////////////////////////////////////////// + // Section header + sec = (dof_sec_t*) + (dof + sizeof(dof_hdr_t) + sizeof(dof_sec_t) * provider_sec); + sec->dofs_type = DOF_SECT_PROVIDER; + sec->dofs_align = alignment_for[PROVIDERS]; + sec->dofs_flags = DOF_SECF_LOAD; + sec->dofs_entsize = 0; + sec->dofs_offset = secoffs[provider_sec]; + sec->dofs_size = secsize[provider_sec]; + // Make provider decriiption + dof_provider_t* prv = (dof_provider_t*)(dof + sec->dofs_offset); + prv->dofpv_strtab = STRTAB; + prv->dofpv_probes = probe_sec; + prv->dofpv_prargs = argoffs_sec; + prv->dofpv_proffs = probeoffs_sec; + prv->dofpv_name = stroffs[curstr++]; // Index in string table + prv->dofpv_provattr = DOF_ATTR( + provider->providerAttributes.nameStability, + provider->providerAttributes.dataStability, + provider->providerAttributes.dependencyClass); + prv->dofpv_modattr = DOF_ATTR( + provider->moduleAttributes.nameStability, + provider->moduleAttributes.dataStability, + provider->moduleAttributes.dependencyClass); + prv->dofpv_funcattr = DOF_ATTR( + provider->functionAttributes.nameStability, + provider->functionAttributes.dataStability, + provider->functionAttributes.dependencyClass); + prv->dofpv_nameattr = DOF_ATTR( + provider->nameAttributes.nameStability, + provider->nameAttributes.dataStability, + provider->nameAttributes.dependencyClass); + prv->dofpv_argsattr = DOF_ATTR( + provider->argsAttributes.nameStability, + provider->argsAttributes.dataStability, + provider->argsAttributes.dependencyClass); + + // PROBES ///////////////////////////////////////////////////////////////// + // Section header + sec = (dof_sec_t*) + (dof + sizeof(dof_hdr_t) + sizeof(dof_sec_t) * probe_sec); + sec->dofs_type = DOF_SECT_PROBES; + sec->dofs_align = alignment_for[PROBES]; + sec->dofs_flags = DOF_SECF_LOAD; + sec->dofs_entsize = sizeof(dof_probe_t); + sec->dofs_offset = secoffs[probe_sec]; + sec->dofs_size = secsize[probe_sec]; + // Make probes descriptions + uint32_t argsoffs = 0; + for(int prbc = 0; prbc < provider->probe_count; ++prbc) { + JVM_DTraceProbe* probe = &(provider->probes[prbc]); + methodOop m = JNIHandles::resolve_jmethod_id(probe->method); + int arg_count = ArgumentCount(m->signature()).size(); + assert(m->code() != NULL, "must have an nmethod"); + + dof_probe_t* prb = + (dof_probe_t*)(dof + sec->dofs_offset + prbc * sizeof(dof_probe_t)); + + prb->dofpr_addr = (uint64_t)m->code()->entry_point(); + prb->dofpr_func = stroffs[curstr++]; // Index in string table + prb->dofpr_name = stroffs[curstr++]; // Index in string table + prb->dofpr_nargv = stroffs[curstr ]; // Index in string table + // We spent siglen strings here + curstr += arg_count; + prb->dofpr_xargv = prb->dofpr_nargv; // Same bunch of strings + prb->dofpr_argidx = argsoffs; + prb->dofpr_offidx = prbc; + prb->dofpr_nargc = arg_count; + prb->dofpr_xargc = arg_count; + prb->dofpr_noffs = 1; // Number of offsets + // Next bunch of offsets + argsoffs += arg_count; + } + + // PROFFS ///////////////////////////////////////////////////////////////// + // Section header + sec = (dof_sec_t*) + (dof + sizeof(dof_hdr_t) + sizeof(dof_sec_t) * probeoffs_sec); + sec->dofs_type = DOF_SECT_PROFFS; + sec->dofs_align = alignment_for[PROBE_OFFSETS]; + sec->dofs_flags = DOF_SECF_LOAD; + sec->dofs_entsize = sizeof(uint32_t); + sec->dofs_offset = secoffs[probeoffs_sec]; + sec->dofs_size = secsize[probeoffs_sec]; + // Make offsets + for (int prbc = 0; prbc < provider->probe_count; ++prbc) { + uint32_t* pof = + (uint32_t*)(dof + sec->dofs_offset + sizeof(uint32_t) * prbc); + JVM_DTraceProbe* probe = &(provider->probes[prbc]); + methodOop m = JNIHandles::resolve_jmethod_id(probe->method); + *pof = m->code()->trap_offset(); + } + + // PRARGS ///////////////////////////////////////////////////////////////// + // Section header + sec = (dof_sec_t*) + (dof + sizeof(dof_hdr_t) + sizeof(dof_sec_t) * argoffs_sec); + sec->dofs_type = DOF_SECT_PRARGS; + sec->dofs_align = alignment_for[ARG_OFFSETS]; + sec->dofs_flags = DOF_SECF_LOAD; + sec->dofs_entsize = sizeof(uint8_t); + sec->dofs_offset = secoffs[argoffs_sec]; + sec->dofs_size = secsize[argoffs_sec]; + // Make arguments + uint8_t* par = (uint8_t*)(dof + sec->dofs_offset); + for (int prbc = 0; prbc < provider->probe_count; ++prbc) { + JVM_DTraceProbe* p = &(provider->probes[prbc]); + symbolOop sig = JNIHandles::resolve_jmethod_id(p->method)->signature(); + uint8_t count = (uint8_t)ArgumentCount(sig).size(); + for (uint8_t i = 0; i < count; ++i) { + *par++ = i; + } + } + } + + // Register module + return dof_register(module, dof, moduleBaseAddress); +} + + +void DTraceJSDT::pd_dispose(int handle) { + int fd; + if (handle == -1) { + return; + } + fd = dofhelper_open(); + if (fd < 0) + return; + ioctl(fd, DTRACEHIOC_REMOVE, handle); + close(fd); +} + +jboolean DTraceJSDT::pd_is_supported() { + int fd = dofhelper_open(); + if (fd < 0) { + return false; + } + close(fd); + return true; +} + +static const char* dofSecTypeFor(uint32_t type) { + switch (type) { + case 0: return "DOF_SECT_NONE"; + case 1: return "DOF_SECT_COMMENTS"; + case 2: return "DOF_SECT_SOURCE"; + case 3: return "DOF_SECT_ECBDESC"; + case 4: return "DOF_SECT_PROBEDESC"; + case 5: return "DOF_SECT_ACTDESC"; + case 6: return "DOF_SECT_DIFOHDR"; + case 7: return "DOF_SECT_DIF"; + case 8: return "DOF_SECT_STRTAB"; + case 9: return "DOF_SECT_VARTAB"; + case 10: return "DOF_SECT_RELTAB"; + case 11: return "DOF_SECT_TYPETAB"; + case 12: return "DOF_SECT_URELHDR"; + case 13: return "DOF_SECT_KRELHDR"; + case 14: return "DOF_SECT_OPTDESC"; + case 15: return "DOF_SECT_PROVIDER"; + case 16: return "DOF_SECT_PROBES"; + case 17: return "DOF_SECT_PRARGS"; + case 18: return "DOF_SECT_PROFFS"; + case 19: return "DOF_SECT_INTTAB"; + case 20: return "DOF_SECT_UTSNAME"; + case 21: return "DOF_SECT_XLTAB"; + case 22: return "DOF_SECT_XLMEMBERS"; + case 23: return "DOF_SECT_XLIMPORT"; + case 24: return "DOF_SECT_XLEXPORT"; + case 25: return "DOF_SECT_PREXPORT"; + case 26: return "DOF_SECT_PRENOFFS"; + default: return ""; + } +} + +static void printDOFStringTabSec(void* dof, dof_sec_t* sec) { + size_t tab = sec->dofs_offset; + size_t limit = sec->dofs_size; + tty->print_cr("// String Table:"); + for (size_t idx = 0; idx < limit; /*empty*/) { + char* str = ((char*)dof) + tab + idx; + tty->print_cr("// [0x%x + 0x%x] '%s'", tab, idx, str); + idx += strlen(str) + 1; + } +} + +static void printDOFProviderSec(void* dof, dof_sec_t* sec) { + dof_provider_t* prov = (dof_provider_t*)((char*)dof + sec->dofs_offset); + tty->print_cr("// dof_provider_t {"); + tty->print_cr("// dofpv_strtab = %d", prov->dofpv_strtab); + tty->print_cr("// dofpv_probes = %d", prov->dofpv_probes); + tty->print_cr("// dofpv_prargs = %d", prov->dofpv_prargs); + tty->print_cr("// dofpv_proffs = %d", prov->dofpv_proffs); + tty->print_cr("// dofpv_name = 0x%x", prov->dofpv_name); + tty->print_cr("// dofpv_provattr = 0x%08x", prov->dofpv_provattr); + tty->print_cr("// dofpv_modattr = 0x%08x", prov->dofpv_modattr); + tty->print_cr("// dofpv_funcattr = 0x%08x", prov->dofpv_funcattr); + tty->print_cr("// dofpv_nameattr = 0x%08x", prov->dofpv_nameattr); + tty->print_cr("// dofpv_argsattr = 0x%08x", prov->dofpv_argsattr); + tty->print_cr("// }"); +} + +static void printDOFProbesSec(void* dof, dof_sec_t* sec) { + size_t idx = sec->dofs_offset; + size_t limit = idx + sec->dofs_size; + for (size_t idx = sec->dofs_offset; idx < limit; idx += sec->dofs_entsize) { + dof_probe_t* prb = (dof_probe_t*)((char*)dof + idx); + tty->print_cr("// dof_probe_t {"); + tty->print_cr("// dofpr_addr = 0x%016llx", prb->dofpr_addr); + tty->print_cr("// dofpr_func = 0x%x", prb->dofpr_func); + tty->print_cr("// dofpr_name = 0x%x", prb->dofpr_name); + tty->print_cr("// dofpr_nargv = 0x%x", prb->dofpr_nargv); + tty->print_cr("// dofpr_xargv = 0x%x", prb->dofpr_xargv); + tty->print_cr("// dofpr_argidx = 0x%x", prb->dofpr_argidx); + tty->print_cr("// dofpr_offidx = 0x%x", prb->dofpr_offidx); + tty->print_cr("// dofpr_nargc = %d", prb->dofpr_nargc); + tty->print_cr("// dofpr_xargc = %d", prb->dofpr_xargc); + tty->print_cr("// dofpr_noffs = %d", prb->dofpr_noffs); + tty->print_cr("// }"); + } +} + +static void printDOFOffsetsSec(void* dof, dof_sec_t* sec) { + size_t tab = sec->dofs_offset; + size_t limit = sec->dofs_size; + tty->print_cr("// Offsets:"); + for (size_t idx = 0; idx < limit; idx += sec->dofs_entsize) { + uint32_t* off = (uint32_t*)((char*)dof + tab + idx); + tty->print_cr("// [0x%x + 0x%x]: %d", tab, idx, *off); + } +} + +static void printDOFArgsSec(void* dof, dof_sec_t* sec) { + size_t tab = sec->dofs_offset; + size_t limit = sec->dofs_size; + tty->print_cr("// Arguments:"); + for (size_t idx = 0; idx < limit; idx += sec->dofs_entsize) { + uint8_t* arg = (uint8_t*)((char*)dof + tab + idx); + tty->print_cr("// [0x%x + 0x%x]: %d", tab, idx, *arg); + } +} + +static void printDOFSection(void* dof, dof_sec_t* sec) { + tty->print_cr("// dof_sec_t {"); + tty->print_cr("// dofs_type = 0x%x /* %s */", + sec->dofs_type, dofSecTypeFor(sec->dofs_type)); + tty->print_cr("// dofs_align = %d", sec->dofs_align); + tty->print_cr("// dofs_flags = 0x%x", sec->dofs_flags); + tty->print_cr("// dofs_entsize = %d", sec->dofs_entsize); + tty->print_cr("// dofs_offset = 0x%llx", sec->dofs_offset); + tty->print_cr("// dofs_size = %lld", sec->dofs_size); + tty->print_cr("// }"); + switch (sec->dofs_type) { + case DOF_SECT_STRTAB: printDOFStringTabSec(dof, sec); break; + case DOF_SECT_PROVIDER: printDOFProviderSec(dof, sec); break; + case DOF_SECT_PROBES: printDOFProbesSec(dof, sec); break; + case DOF_SECT_PROFFS: printDOFOffsetsSec(dof, sec); break; + case DOF_SECT_PRARGS: printDOFArgsSec(dof, sec); break; + default: tty->print_cr("//

    "); + } +} + +static void printDOFHeader(dof_hdr_t* hdr) { + tty->print_cr("// dof_hdr_t {"); + tty->print_cr("// dofh_ident[DOF_ID_MAG0] = 0x%x", + hdr->dofh_ident[DOF_ID_MAG0]); + tty->print_cr("// dofh_ident[DOF_ID_MAG1] = 0x%x", + hdr->dofh_ident[DOF_ID_MAG1]); + tty->print_cr("// dofh_ident[DOF_ID_MAG2] = 0x%x", + hdr->dofh_ident[DOF_ID_MAG2]); + tty->print_cr("// dofh_ident[DOF_ID_MAG3] = 0x%x", + hdr->dofh_ident[DOF_ID_MAG3]); + tty->print_cr("// dofh_ident[DOF_ID_MODEL] = 0x%x", + hdr->dofh_ident[DOF_ID_MODEL]); + tty->print_cr("// dofh_ident[DOF_ID_ENCODING] = 0x%x", + hdr->dofh_ident[DOF_ID_ENCODING]); + tty->print_cr("// dofh_ident[DOF_ID_VERSION] = 0x%x", + hdr->dofh_ident[DOF_ID_VERSION]); + tty->print_cr("// dofh_ident[DOF_ID_DIFVERS] = 0x%x", + hdr->dofh_ident[DOF_ID_DIFVERS]); + tty->print_cr("// dofh_flags = 0x%x", hdr->dofh_flags); + tty->print_cr("// dofh_hdrsize = %d", hdr->dofh_hdrsize); + tty->print_cr("// dofh_secsize = %d", hdr->dofh_secsize); + tty->print_cr("// dofh_secnum = %d", hdr->dofh_secnum); + tty->print_cr("// dofh_secoff = %lld", hdr->dofh_secoff); + tty->print_cr("// dofh_loadsz = %lld", hdr->dofh_loadsz); + tty->print_cr("// dofh_filesz = %lld", hdr->dofh_filesz); + tty->print_cr("// }"); +} + +static void printDOF(void* dof) { + dof_hdr_t* hdr = (dof_hdr_t*)dof; + printDOFHeader(hdr); + for (int i = 0; i < hdr->dofh_secnum; ++i) { + dof_sec_t* sec = + (dof_sec_t*)((char*)dof + sizeof(dof_hdr_t) + i * sizeof(dof_sec_t)); + tty->print_cr("// [Section #%d]", i); + printDOFSection(dof, sec); + } +} + +/** + * This prints out hex data in a 'windbg' or 'xxd' form, where each line is: + * : 8 * + * example: + * 0000000: 7f44 4f46 0102 0102 0000 0000 0000 0000 .DOF............ + * 0000010: 0000 0000 0000 0040 0000 0020 0000 0005 .......@... .... + * 0000020: 0000 0000 0000 0040 0000 0000 0000 015d .......@.......] + * ... + */ +static void printDOFRawData(void* dof) { + size_t size = ((dof_hdr_t*)dof)->dofh_loadsz; + size_t limit = (size + 16) / 16 * 16; + for (size_t i = 0; i < limit; ++i) { + if (i % 16 == 0) { + tty->print("%07x:", i); + } + if (i % 2 == 0) { + tty->print(" "); + } + if (i < size) { + tty->print("%02x", ((unsigned char*)dof)[i]); + } else { + tty->print(" "); + } + if ((i + 1) % 16 == 0) { + tty->print(" "); + for (size_t j = 0; j < 16; ++j) { + size_t idx = i + j - 15; + char c = ((char*)dof)[idx]; + if (idx < size) { + tty->print("%c", c >= 32 && c <= 126 ? c : '.'); + } + } + tty->print_cr(""); + } + } + tty->print_cr(""); +} + +static void printDOFHelper(dof_helper_t* helper) { + tty->print_cr("// dof_helper_t {"); + tty->print_cr("// dofhp_mod = \"%s\"", helper->dofhp_mod); + tty->print_cr("// dofhp_addr = 0x%016llx", helper->dofhp_addr); + tty->print_cr("// dofhp_dof = 0x%016llx", helper->dofhp_dof); + printDOF((void*)helper->dofhp_dof); + tty->print_cr("// }"); + printDOFRawData((void*)helper->dofhp_dof); +} + +#else // ndef HAVE_DTRACE_H + +// Get here if we're not building on at least Solaris 10 +int DTraceJSDT::pd_activate( + void* baseAddress, jstring module, + jint provider_count, JVM_DTraceProvider* providers) { + return -1; +} + +void DTraceJSDT::pd_dispose(int handle) { +} + +jboolean DTraceJSDT::pd_is_supported() { + return false; +} +#endif diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 75ad158a9cd..ce6765e8d50 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -122,6 +122,13 @@ struct memcntl_mha { # define MADV_ACCESS_MANY 8 /* many processes to access heavily */ #endif +#ifndef LGRP_RSRC_CPU +# define LGRP_RSRC_CPU 0 /* CPU resources */ +#endif +#ifndef LGRP_RSRC_MEM +# define LGRP_RSRC_MEM 1 /* memory resources */ +#endif + // Some more macros from sys/mman.h that are not present in Solaris 8. #ifndef MAX_MEMINFO_CNT @@ -2602,7 +2609,7 @@ void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } // Tell the OS to make the range local to the first-touching LWP -void os::numa_make_local(char *addr, size_t bytes) { +void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { assert((intptr_t)addr % os::vm_page_size() == 0, "Address should be page-aligned."); if (madvise(addr, bytes, MADV_ACCESS_LWP) < 0) { debug_only(warning("MADV_ACCESS_LWP failed.")); @@ -2640,8 +2647,13 @@ size_t os::numa_get_leaf_groups(int *ids, size_t size) { return 1; } if (!r) { + // That's a leaf node. assert (bottom <= cur, "Sanity check"); - ids[bottom++] = ids[cur]; + // Check if the node has memory + if (Solaris::lgrp_resources(Solaris::lgrp_cookie(), ids[cur], + NULL, 0, LGRP_RSRC_MEM) > 0) { + ids[bottom++] = ids[cur]; + } } top += r; cur++; @@ -2664,11 +2676,20 @@ bool os::numa_topology_changed() { // Get the group id of the current LWP. int os::numa_get_group_id() { - int lgrp_id = os::Solaris::lgrp_home(P_LWPID, P_MYID); + int lgrp_id = Solaris::lgrp_home(P_LWPID, P_MYID); if (lgrp_id == -1) { return 0; } - return lgrp_id; + const int size = os::numa_get_groups_num(); + int *ids = (int*)alloca(size * sizeof(int)); + + // Get the ids of all lgroups with memory; r is the count. + int r = Solaris::lgrp_resources(Solaris::lgrp_cookie(), lgrp_id, + (Solaris::lgrp_id_t*)ids, size, LGRP_RSRC_MEM); + if (r <= 0) { + return 0; + } + return ids[os::random() % r]; } // Request information about the page. @@ -4353,6 +4374,7 @@ os::Solaris::lgrp_init_func_t os::Solaris::_lgrp_init; os::Solaris::lgrp_fini_func_t os::Solaris::_lgrp_fini; os::Solaris::lgrp_root_func_t os::Solaris::_lgrp_root; os::Solaris::lgrp_children_func_t os::Solaris::_lgrp_children; +os::Solaris::lgrp_resources_func_t os::Solaris::_lgrp_resources; os::Solaris::lgrp_nlgrps_func_t os::Solaris::_lgrp_nlgrps; os::Solaris::lgrp_cookie_stale_func_t os::Solaris::_lgrp_cookie_stale; os::Solaris::lgrp_cookie_t os::Solaris::_lgrp_cookie = 0; @@ -4391,61 +4413,52 @@ static address resolve_symbol(const char *name) { // threads. Calling thr_setprio is meaningless in this case. // bool isT2_libthread() { - int i, rslt; static prheader_t * lwpArray = NULL; static int lwpSize = 0; static int lwpFile = -1; lwpstatus_t * that; - int aslwpcount; char lwpName [128]; bool isT2 = false; #define ADR(x) ((uintptr_t)(x)) #define LWPINDEX(ary,ix) ((lwpstatus_t *)(((ary)->pr_entsize * (ix)) + (ADR((ary) + 1)))) - aslwpcount = 0; - lwpSize = 16*1024; - lwpArray = ( prheader_t *)NEW_C_HEAP_ARRAY (char, lwpSize); - lwpFile = open ("/proc/self/lstatus", O_RDONLY, 0); - if (lwpArray == NULL) { - if ( ThreadPriorityVerbose ) warning ("Couldn't allocate T2 Check array\n"); - return(isT2); - } + lwpFile = open("/proc/self/lstatus", O_RDONLY, 0); if (lwpFile < 0) { - if ( ThreadPriorityVerbose ) warning ("Couldn't open /proc/self/lstatus\n"); - return(isT2); + if (ThreadPriorityVerbose) warning ("Couldn't open /proc/self/lstatus\n"); + return false; } + lwpSize = 16*1024; for (;;) { lseek (lwpFile, 0, SEEK_SET); - rslt = read (lwpFile, lwpArray, lwpSize); - if ((lwpArray->pr_nent * lwpArray->pr_entsize) <= lwpSize) { + lwpArray = (prheader_t *)NEW_C_HEAP_ARRAY(char, lwpSize); + if (read(lwpFile, lwpArray, lwpSize) < 0) { + if (ThreadPriorityVerbose) warning("Error reading /proc/self/lstatus\n"); + break; + } + if ((lwpArray->pr_nent * lwpArray->pr_entsize) <= lwpSize) { + // We got a good snapshot - now iterate over the list. + int aslwpcount = 0; + for (int i = 0; i < lwpArray->pr_nent; i++ ) { + that = LWPINDEX(lwpArray,i); + if (that->pr_flags & PR_ASLWP) { + aslwpcount++; + } + } + if (aslwpcount == 0) isT2 = true; break; } - FREE_C_HEAP_ARRAY(char, lwpArray); lwpSize = lwpArray->pr_nent * lwpArray->pr_entsize; - lwpArray = ( prheader_t *)NEW_C_HEAP_ARRAY (char, lwpSize); - if (lwpArray == NULL) { - if ( ThreadPriorityVerbose ) warning ("Couldn't allocate T2 Check array\n"); - return(isT2); - } + FREE_C_HEAP_ARRAY(char, lwpArray); // retry. } - // We got a good snapshot - now iterate over the list. - for (i = 0; i < lwpArray->pr_nent; i++ ) { - that = LWPINDEX(lwpArray,i); - if (that->pr_flags & PR_ASLWP) { - aslwpcount++; - } - } - if ( aslwpcount == 0 ) isT2 = true; - FREE_C_HEAP_ARRAY(char, lwpArray); close (lwpFile); - if ( ThreadPriorityVerbose ) { - if ( isT2 ) tty->print_cr("We are running with a T2 libthread\n"); + if (ThreadPriorityVerbose) { + if (isT2) tty->print_cr("We are running with a T2 libthread\n"); else tty->print_cr("We are not running with a T2 libthread\n"); } - return (isT2); + return isT2; } @@ -4564,6 +4577,7 @@ void os::Solaris::liblgrp_init() { os::Solaris::set_lgrp_fini(CAST_TO_FN_PTR(lgrp_fini_func_t, dlsym(handle, "lgrp_fini"))); os::Solaris::set_lgrp_root(CAST_TO_FN_PTR(lgrp_root_func_t, dlsym(handle, "lgrp_root"))); os::Solaris::set_lgrp_children(CAST_TO_FN_PTR(lgrp_children_func_t, dlsym(handle, "lgrp_children"))); + os::Solaris::set_lgrp_resources(CAST_TO_FN_PTR(lgrp_resources_func_t, dlsym(handle, "lgrp_resources"))); os::Solaris::set_lgrp_nlgrps(CAST_TO_FN_PTR(lgrp_nlgrps_func_t, dlsym(handle, "lgrp_nlgrps"))); os::Solaris::set_lgrp_cookie_stale(CAST_TO_FN_PTR(lgrp_cookie_stale_func_t, dlsym(handle, "lgrp_cookie_stale"))); diff --git a/hotspot/src/os/solaris/vm/os_solaris.hpp b/hotspot/src/os/solaris/vm/os_solaris.hpp index b66bcb2bf6f..545802ae158 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.hpp @@ -66,6 +66,7 @@ class Solaris { typedef uintptr_t lgrp_cookie_t; typedef id_t lgrp_id_t; + typedef int lgrp_rsrc_t; typedef enum lgrp_view { LGRP_VIEW_CALLER, /* what's available to the caller */ LGRP_VIEW_OS /* what's available to operating system */ @@ -77,6 +78,9 @@ class Solaris { typedef lgrp_id_t (*lgrp_root_func_t)(lgrp_cookie_t cookie); typedef int (*lgrp_children_func_t)(lgrp_cookie_t cookie, lgrp_id_t parent, lgrp_id_t *lgrp_array, uint_t lgrp_array_size); + typedef int (*lgrp_resources_func_t)(lgrp_cookie_t cookie, lgrp_id_t lgrp, + lgrp_id_t *lgrp_array, uint_t lgrp_array_size, + lgrp_rsrc_t type); typedef int (*lgrp_nlgrps_func_t)(lgrp_cookie_t cookie); typedef int (*lgrp_cookie_stale_func_t)(lgrp_cookie_t cookie); typedef int (*meminfo_func_t)(const uint64_t inaddr[], int addr_count, @@ -88,6 +92,7 @@ class Solaris { static lgrp_fini_func_t _lgrp_fini; static lgrp_root_func_t _lgrp_root; static lgrp_children_func_t _lgrp_children; + static lgrp_resources_func_t _lgrp_resources; static lgrp_nlgrps_func_t _lgrp_nlgrps; static lgrp_cookie_stale_func_t _lgrp_cookie_stale; static lgrp_cookie_t _lgrp_cookie; @@ -109,7 +114,6 @@ class Solaris { static int (*get_libjsig_version)(); static void save_preinstalled_handler(int, struct sigaction&); static void check_signal_handler(int sig); - // For overridable signals static int _SIGinterrupt; // user-overridable INTERRUPT_SIGNAL static int _SIGasync; // user-overridable ASYNC_SIGNAL @@ -253,8 +257,9 @@ class Solaris { static void set_lgrp_init(lgrp_init_func_t func) { _lgrp_init = func; } static void set_lgrp_fini(lgrp_fini_func_t func) { _lgrp_fini = func; } static void set_lgrp_root(lgrp_root_func_t func) { _lgrp_root = func; } - static void set_lgrp_children(lgrp_children_func_t func) { _lgrp_children = func; } - static void set_lgrp_nlgrps(lgrp_nlgrps_func_t func) { _lgrp_nlgrps = func; } + static void set_lgrp_children(lgrp_children_func_t func) { _lgrp_children = func; } + static void set_lgrp_resources(lgrp_resources_func_t func) { _lgrp_resources = func; } + static void set_lgrp_nlgrps(lgrp_nlgrps_func_t func) { _lgrp_nlgrps = func; } static void set_lgrp_cookie_stale(lgrp_cookie_stale_func_t func) { _lgrp_cookie_stale = func; } static void set_lgrp_cookie(lgrp_cookie_t cookie) { _lgrp_cookie = cookie; } @@ -266,6 +271,12 @@ class Solaris { lgrp_id_t *lgrp_array, uint_t lgrp_array_size) { return _lgrp_children != NULL ? _lgrp_children(cookie, parent, lgrp_array, lgrp_array_size) : -1; } + static int lgrp_resources(lgrp_cookie_t cookie, lgrp_id_t lgrp, + lgrp_id_t *lgrp_array, uint_t lgrp_array_size, + lgrp_rsrc_t type) { + return _lgrp_resources != NULL ? _lgrp_resources(cookie, lgrp, lgrp_array, lgrp_array_size, type) : -1; + } + static int lgrp_nlgrps(lgrp_cookie_t cookie) { return _lgrp_nlgrps != NULL ? _lgrp_nlgrps(cookie) : -1; } static int lgrp_cookie_stale(lgrp_cookie_t cookie) { return _lgrp_cookie_stale != NULL ? _lgrp_cookie_stale(cookie) : -1; diff --git a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp index f75b50d15b2..3fe038dd6ce 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp +++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp @@ -204,3 +204,6 @@ do { \ RESTARTABLE(_cmd, _result); \ return _result; \ } while(false) + +inline bool os::numa_has_static_binding() { return false; } +inline bool os::numa_has_group_homing() { return true; } diff --git a/hotspot/src/os/windows/vm/dtraceJSDT_windows.cpp b/hotspot/src/os/windows/vm/dtraceJSDT_windows.cpp new file mode 100644 index 00000000000..8f8986a98a2 --- /dev/null +++ b/hotspot/src/os/windows/vm/dtraceJSDT_windows.cpp @@ -0,0 +1,39 @@ +/* + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#include "incls/_precompiled.incl" +#include "incls/_dtraceJSDT_windows.cpp.incl" + +int DTraceJSDT::pd_activate( + void* baseAddress, jstring module, + jint providers_count, JVM_DTraceProvider* providers) { + return -1; +} + +void DTraceJSDT::pd_dispose(int handle) { +} + +jboolean DTraceJSDT::pd_is_supported() { + return false; +} diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 8794b3f2d4d..a114b894690 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -2581,7 +2581,7 @@ bool os::unguard_memory(char* addr, size_t bytes) { void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } void os::free_memory(char *addr, size_t bytes) { } void os::numa_make_global(char *addr, size_t bytes) { } -void os::numa_make_local(char *addr, size_t bytes) { } +void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { } bool os::numa_topology_changed() { return false; } size_t os::numa_get_groups_num() { return 1; } int os::numa_get_group_id() { return 0; } @@ -3116,7 +3116,7 @@ jint os::init_2(void) { // as reserve size, since on a 64-bit platform we'll run into that more // often than running out of virtual memory space. We can use the // lower value of the two calculations as the os_thread_limit. - size_t max_address_space = ((size_t)1 << (BitsPerOop - 1)) - (200 * K * K); + size_t max_address_space = ((size_t)1 << (BitsPerWord - 1)) - (200 * K * K); win32::_os_thread_limit = (intx)(max_address_space / actual_reserve_size); // at exit methods are called in the reverse order of their registration. diff --git a/hotspot/src/os/windows/vm/os_windows.inline.hpp b/hotspot/src/os/windows/vm/os_windows.inline.hpp index 393a0181f38..26be952c03f 100644 --- a/hotspot/src/os/windows/vm/os_windows.inline.hpp +++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp @@ -69,3 +69,6 @@ inline void os::bang_stack_shadow_pages() { *((int *)(sp - (pages * vm_page_size()))) = 0; } } + +inline bool os::numa_has_static_binding() { return true; } +inline bool os::numa_has_group_homing() { return false; } diff --git a/hotspot/src/os_cpu/linux_sparc/vm/assembler_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/assembler_linux_sparc.cpp new file mode 100644 index 00000000000..7ffae8d17ea --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/assembler_linux_sparc.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#include "incls/_precompiled.incl" +#include "incls/_assembler_linux_sparc.cpp.incl" + +#include + +bool MacroAssembler::needs_explicit_null_check(intptr_t offset) { + // Since the linux kernel resides at the low end of + // user address space, no null pointer check is needed. + return offset < 0 || offset >= 0x100000; +} + +void MacroAssembler::read_ccr_trap(Register ccr_save) { + // No implementation + breakpoint_trap(); +} + +void MacroAssembler::write_ccr_trap(Register ccr_save, Register scratch1, Register scratch2) { + // No implementation + breakpoint_trap(); +} + +void MacroAssembler::flush_windows_trap() { trap(SP_TRAP_FWIN); } +void MacroAssembler::clean_windows_trap() { trap(SP_TRAP_CWIN); } + +// Use software breakpoint trap until we figure out how to do this on Linux +void MacroAssembler::get_psr_trap() { trap(SP_TRAP_SBPT); } +void MacroAssembler::set_psr_trap() { trap(SP_TRAP_SBPT); } diff --git a/hotspot/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp b/hotspot/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp new file mode 100644 index 00000000000..a932a1079bc --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp @@ -0,0 +1,206 @@ +/* + * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +// Implementation of class atomic + +inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; } +inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; } +inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; } +inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; } +inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; } +inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; } + +inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; } +inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; } +inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; } +inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; } +inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; } +inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; } + +inline void Atomic::inc (volatile jint* dest) { (void)add (1, dest); } +inline void Atomic::inc_ptr(volatile intptr_t* dest) { (void)add_ptr(1, dest); } +inline void Atomic::inc_ptr(volatile void* dest) { (void)add_ptr(1, dest); } + +inline void Atomic::dec (volatile jint* dest) { (void)add (-1, dest); } +inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); } +inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest); } + +inline jint Atomic::add (jint add_value, volatile jint* dest) { + intptr_t rv; + __asm__ volatile( + "1: \n\t" + " ld [%2], %%o2\n\t" + " add %1, %%o2, %%o3\n\t" + " cas [%2], %%o2, %%o3\n\t" + " cmp %%o2, %%o3\n\t" + " bne 1b\n\t" + " nop\n\t" + " add %1, %%o2, %0\n\t" + : "=r" (rv) + : "r" (add_value), "r" (dest) + : "memory", "o2", "o3"); + return rv; +} + +inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { + intptr_t rv; +#ifdef _LP64 + __asm__ volatile( + "1: \n\t" + " ldx [%2], %%o2\n\t" + " add %0, %%o2, %%o3\n\t" + " casx [%2], %%o2, %%o3\n\t" + " cmp %%o2, %%o3\n\t" + " bne %%xcc, 1b\n\t" + " nop\n\t" + " add %0, %%o2, %0\n\t" + : "=r" (rv) + : "r" (add_value), "r" (dest) + : "memory", "o2", "o3"); +#else + __asm__ volatile( + "1: \n\t" + " ld [%2], %%o2\n\t" + " add %1, %%o2, %%o3\n\t" + " cas [%2], %%o2, %%o3\n\t" + " cmp %%o2, %%o3\n\t" + " bne 1b\n\t" + " nop\n\t" + " add %1, %%o2, %0\n\t" + : "=r" (rv) + : "r" (add_value), "r" (dest) + : "memory", "o2", "o3"); +#endif // _LP64 + return rv; +} + +inline void* Atomic::add_ptr(intptr_t add_value, volatile void* dest) { + return (void*)add_ptr((intptr_t)add_value, (volatile intptr_t*)dest); +} + + +inline jint Atomic::xchg (jint exchange_value, volatile jint* dest) { + intptr_t rv = exchange_value; + __asm__ volatile( + " swap [%2],%1\n\t" + : "=r" (rv) + : "0" (exchange_value) /* we use same register as for return value */, "r" (dest) + : "memory"); + return rv; +} + +inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) { + intptr_t rv = exchange_value; +#ifdef _LP64 + __asm__ volatile( + "1:\n\t" + " mov %1, %%o3\n\t" + " ldx [%2], %%o2\n\t" + " casx [%2], %%o2, %%o3\n\t" + " cmp %%o2, %%o3\n\t" + " bne %%xcc, 1b\n\t" + " nop\n\t" + " mov %%o2, %0\n\t" + : "=r" (rv) + : "r" (exchange_value), "r" (dest) + : "memory", "o2", "o3"); +#else + __asm__ volatile( + "swap [%2],%1\n\t" + : "=r" (rv) + : "0" (exchange_value) /* we use same register as for return value */, "r" (dest) + : "memory"); +#endif // _LP64 + return rv; +} + +inline void* Atomic::xchg_ptr(void* exchange_value, volatile void* dest) { + return (void*)xchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest); +} + + +inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { + jint rv; + __asm__ volatile( + " cas [%2], %3, %0" + : "=r" (rv) + : "0" (exchange_value), "r" (dest), "r" (compare_value) + : "memory"); + return rv; +} + +inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { +#ifdef _LP64 + jlong rv; + __asm__ volatile( + " casx [%2], %3, %0" + : "=r" (rv) + : "0" (exchange_value), "r" (dest), "r" (compare_value) + : "memory"); + return rv; +#else + assert(VM_Version::v9_instructions_work(), "cas only supported on v9"); + volatile jlong_accessor evl, cvl, rv; + evl.long_value = exchange_value; + cvl.long_value = compare_value; + + __asm__ volatile( + " sllx %2, 32, %2\n\t" + " srl %3, 0, %3\n\t" + " or %2, %3, %2\n\t" + " sllx %5, 32, %5\n\t" + " srl %6, 0, %6\n\t" + " or %5, %6, %5\n\t" + " casx [%4], %5, %2\n\t" + " srl %2, 0, %1\n\t" + " srlx %2, 32, %0\n\t" + : "=r" (rv.words[0]), "=r" (rv.words[1]) + : "r" (evl.words[0]), "r" (evl.words[1]), "r" (dest), "r" (cvl.words[0]), "r" (cvl.words[1]) + : "memory"); + + return rv.long_value; +#endif +} + +inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value) { + intptr_t rv; +#ifdef _LP64 + __asm__ volatile( + " casx [%2], %3, %0" + : "=r" (rv) + : "0" (exchange_value), "r" (dest), "r" (compare_value) + : "memory"); +#else + __asm__ volatile( + " cas [%2], %3, %0" + : "=r" (rv) + : "0" (exchange_value), "r" (dest), "r" (compare_value) + : "memory"); +#endif // _LP64 + return rv; +} + +inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { + return (void*)cmpxchg_ptr((intptr_t)exchange_value, (volatile intptr_t*)dest, (intptr_t)compare_value); +} diff --git a/hotspot/src/os_cpu/linux_sparc/vm/globals_linux_sparc.hpp b/hotspot/src/os_cpu/linux_sparc/vm/globals_linux_sparc.hpp new file mode 100644 index 00000000000..4f2693db8ed --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/globals_linux_sparc.hpp @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +// +// Sets the default values for platform dependent flags used by the +// runtime system. (see globals.hpp) +// + +define_pd_global(uintx, JVMInvokeMethodSlack, 12288); +define_pd_global(intx, CompilerThreadStackSize, 0); + +// Only used on 64 bit Windows platforms +define_pd_global(bool, UseVectoredExceptions, false); diff --git a/hotspot/src/os_cpu/linux_sparc/vm/linux_sparc.ad b/hotspot/src/os_cpu/linux_sparc/vm/linux_sparc.ad new file mode 100644 index 00000000000..33288c5df2c --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/linux_sparc.ad @@ -0,0 +1,27 @@ +// +// Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +// CA 95054 USA or visit www.sun.com if you need additional information or +// have any questions. +// + +// +// + +// SPARC Linux Architecture Description File diff --git a/hotspot/src/os_cpu/linux_sparc/vm/linux_sparc.s b/hotspot/src/os_cpu/linux_sparc/vm/linux_sparc.s new file mode 100644 index 00000000000..dda3d05563e --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/linux_sparc.s @@ -0,0 +1,105 @@ +# +# Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + + # Prototype: int SafeFetch32 (int * adr, int ErrValue) + # The "ld" at Fetch32 is potentially faulting instruction. + # If the instruction traps the trap handler will arrange + # for control to resume at Fetch32Resume. + # By convention with the trap handler we ensure there is a non-CTI + # instruction in the trap shadow. + + + .globl SafeFetch32, Fetch32PFI, Fetch32Resume + .globl SafeFetchN + .align 32 + .type SafeFetch32,@function +SafeFetch32: + mov %o0, %g1 + mov %o1, %o0 +Fetch32PFI: + # <-- Potentially faulting instruction + ld [%g1], %o0 +Fetch32Resume: + nop + retl + nop + + .globl SafeFetchN, FetchNPFI, FetchNResume + .type SafeFetchN,@function + .align 32 +SafeFetchN: + mov %o0, %g1 + mov %o1, %o0 +FetchNPFI: + ldn [%g1], %o0 +FetchNResume: + nop + retl + nop + + # Possibilities: + # -- membar + # -- CAS (SP + BIAS, G0, G0) + # -- wr %g0, %asi + + .globl SpinPause + .type SpinPause,@function + .align 32 +SpinPause: + retl + mov %g0, %o0 + + .globl _Copy_conjoint_jlongs_atomic + .type _Copy_conjoint_jlongs_atomic,@function +_Copy_conjoint_jlongs_atomic: + cmp %o0, %o1 + bleu 4f + sll %o2, 3, %o4 + ba 2f + 1: + subcc %o4, 8, %o4 + std %o2, [%o1] + add %o0, 8, %o0 + add %o1, 8, %o1 + 2: + bge,a 1b + ldd [%o0], %o2 + ba 5f + nop + 3: + std %o2, [%o1+%o4] + 4: + subcc %o4, 8, %o4 + bge,a 3b + ldd [%o0+%o4], %o2 + 5: + retl + nop + + + .globl _flush_reg_windows + .align 32 + _flush_reg_windows: + ta 0x03 + retl + mov %fp, %o0 diff --git a/hotspot/src/os_cpu/linux_sparc/vm/orderAccess_linux_sparc.inline.hpp b/hotspot/src/os_cpu/linux_sparc/vm/orderAccess_linux_sparc.inline.hpp new file mode 100644 index 00000000000..9b39f98fb22 --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/orderAccess_linux_sparc.inline.hpp @@ -0,0 +1,102 @@ +/* + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +// Implementation of class OrderAccess. + +// Assume TSO. + +inline void OrderAccess::loadload() { acquire(); } +inline void OrderAccess::storestore() { release(); } +inline void OrderAccess::loadstore() { acquire(); } +inline void OrderAccess::storeload() { fence(); } + +inline void OrderAccess::acquire() { + __asm__ volatile ("nop" : : :); +} + +inline void OrderAccess::release() { + jint* dummy = (jint*)&dummy; + __asm__ volatile("stw %%g0, [%0]" : : "r" (dummy) : "memory"); +} + +inline void OrderAccess::fence() { + __asm__ volatile ("membar #StoreLoad" : : :); +} + +inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } +inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } +inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } +inline jlong OrderAccess::load_acquire(volatile jlong* p) { return *p; } +inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } +inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } +inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } +inline julong OrderAccess::load_acquire(volatile julong* p) { return *p; } +inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } +inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; } + +inline intptr_t OrderAccess::load_ptr_acquire(volatile intptr_t* p) { return *p; } +inline void* OrderAccess::load_ptr_acquire(volatile void* p) { return *(void* volatile *)p; } +inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return *(void* const volatile *)p; } + +inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } +inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } +inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } +inline void OrderAccess::release_store(volatile jlong* p, jlong v) { *p = v; } +inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } +inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } +inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } +inline void OrderAccess::release_store(volatile julong* p, julong v) { *p = v; } +inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } +inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; } + +inline void OrderAccess::release_store_ptr(volatile intptr_t* p, intptr_t v) { *p = v; } +inline void OrderAccess::release_store_ptr(volatile void* p, void* v) { *(void* volatile *)p = v; } + +inline void OrderAccess::store_fence(jbyte* p, jbyte v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jshort* p, jshort v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jint* p, jint v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jlong* p, jlong v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jubyte* p, jubyte v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jushort* p, jushort v) { *p = v; fence(); } +inline void OrderAccess::store_fence(juint* p, juint v) { *p = v; fence(); } +inline void OrderAccess::store_fence(julong* p, julong v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jfloat* p, jfloat v) { *p = v; fence(); } +inline void OrderAccess::store_fence(jdouble* p, jdouble v) { *p = v; fence(); } + +inline void OrderAccess::store_ptr_fence(intptr_t* p, intptr_t v) { *p = v; fence(); } +inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; fence(); } + +inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { *p = v; fence(); } +inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { *p = v; fence(); } +inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { *p = v; fence(); } +inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { *p = v; fence(); } +inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { *p = v; fence(); } +inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); } +inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { *p = v; fence(); } +inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { *p = v; fence(); } +inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } +inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); } + +inline void OrderAccess::release_store_ptr_fence(volatile intptr_t* p, intptr_t v) { *p = v; fence(); } +inline void OrderAccess::release_store_ptr_fence(volatile void* p, void* v) { *(void* volatile *)p = v; fence(); } diff --git a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp new file mode 100644 index 00000000000..cc209852554 --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp @@ -0,0 +1,648 @@ +/* + * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +// do not include precompiled header file + +#include "incls/_os_linux_sparc.cpp.incl" + +// Linux/Sparc has rather obscure naming of registers in sigcontext +// different between 32 and 64 bits +#ifdef _LP64 +#define SIG_PC(x) ((x)->sigc_regs.tpc) +#define SIG_NPC(x) ((x)->sigc_regs.tnpc) +#define SIG_REGS(x) ((x)->sigc_regs) +#else +#define SIG_PC(x) ((x)->si_regs.pc) +#define SIG_NPC(x) ((x)->si_regs.npc) +#define SIG_REGS(x) ((x)->si_regs) +#endif + +// those are to reference registers in sigcontext +enum { + CON_G0 = 0, + CON_G1, + CON_G2, + CON_G3, + CON_G4, + CON_G5, + CON_G6, + CON_G7, + CON_O0, + CON_O1, + CON_O2, + CON_O3, + CON_O4, + CON_O5, + CON_O6, + CON_O7, +}; + +static inline void set_cont_address(sigcontext* ctx, address addr) { + SIG_PC(ctx) = (intptr_t)addr; + SIG_NPC(ctx) = (intptr_t)(addr+4); +} + +// For Forte Analyzer AsyncGetCallTrace profiling support - thread is +// currently interrupted by SIGPROF. +// os::Solaris::fetch_frame_from_ucontext() tries to skip nested +// signal frames. Currently we don't do that on Linux, so it's the +// same as os::fetch_frame_from_context(). +ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread, + ucontext_t* uc, + intptr_t** ret_sp, + intptr_t** ret_fp) { + assert(thread != NULL, "just checking"); + assert(ret_sp != NULL, "just checking"); + assert(ret_fp != NULL, "just checking"); + + return os::fetch_frame_from_context(uc, ret_sp, ret_fp); +} + +ExtendedPC os::fetch_frame_from_context(void* ucVoid, + intptr_t** ret_sp, + intptr_t** ret_fp) { + ucontext_t* uc = (ucontext_t*) ucVoid; + ExtendedPC epc; + + if (uc != NULL) { + epc = ExtendedPC(os::Linux::ucontext_get_pc(uc)); + if (ret_sp) { + *ret_sp = os::Linux::ucontext_get_sp(uc); + } + if (ret_fp) { + *ret_fp = os::Linux::ucontext_get_fp(uc); + } + } else { + // construct empty ExtendedPC for return value checking + epc = ExtendedPC(NULL); + if (ret_sp) { + *ret_sp = (intptr_t*) NULL; + } + if (ret_fp) { + *ret_fp = (intptr_t*) NULL; + } + } + + return epc; +} + +frame os::fetch_frame_from_context(void* ucVoid) { + intptr_t* sp; + intptr_t* fp; + ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); + return frame(sp, fp, epc.pc()); +} + +frame os::get_sender_for_C_frame(frame* fr) { + return frame(fr->sender_sp(), fr->link(), fr->sender_pc()); +} + +frame os::current_frame() { + fprintf(stderr, "current_frame()"); + + intptr_t* sp = StubRoutines::Sparc::flush_callers_register_windows_func()(); + frame myframe(sp, frame::unpatchable, + CAST_FROM_FN_PTR(address, os::current_frame)); + if (os::is_first_C_frame(&myframe)) { + // stack is not walkable + return frame(NULL, frame::unpatchable, NULL); + } else { + return os::get_sender_for_C_frame(&myframe); + } +} + +address os::current_stack_pointer() { + register void *sp __asm__ ("sp"); + return (address)sp; +} + +static void current_stack_region(address* bottom, size_t* size) { + if (os::Linux::is_initial_thread()) { + // initial thread needs special handling because pthread_getattr_np() + // may return bogus value. + *bottom = os::Linux::initial_thread_stack_bottom(); + *size = os::Linux::initial_thread_stack_size(); + } else { + pthread_attr_t attr; + + int rslt = pthread_getattr_np(pthread_self(), &attr); + + // JVM needs to know exact stack location, abort if it fails + if (rslt != 0) { + if (rslt == ENOMEM) { + vm_exit_out_of_memory(0, "pthread_getattr_np"); + } else { + fatal1("pthread_getattr_np failed with errno = %d", rslt); + } + } + + if (pthread_attr_getstack(&attr, (void**)bottom, size) != 0) { + fatal("Can not locate current stack attributes!"); + } + + pthread_attr_destroy(&attr); + } + assert(os::current_stack_pointer() >= *bottom && + os::current_stack_pointer() < *bottom + *size, "just checking"); +} + +address os::current_stack_base() { + address bottom; + size_t size; + current_stack_region(&bottom, &size); + return bottom + size; +} + +size_t os::current_stack_size() { + // stack size includes normal stack and HotSpot guard pages + address bottom; + size_t size; + current_stack_region(&bottom, &size); + return size; +} + +char* os::non_memory_address_word() { + // Must never look like an address returned by reserve_memory, + // even in its subfields (as defined by the CPU immediate fields, + // if the CPU splits constants across multiple instructions). + // On SPARC, 0 != %hi(any real address), because there is no + // allocation in the first 1Kb of the virtual address space. + return (char*) 0; +} + +void os::initialize_thread() {} + +void os::print_context(outputStream *st, void *context) { + if (context == NULL) return; + + ucontext_t* uc = (ucontext_t*)context; + sigcontext* sc = (sigcontext*)context; + st->print_cr("Registers:"); + + st->print_cr(" O0=" INTPTR_FORMAT " O1=" INTPTR_FORMAT + " O2=" INTPTR_FORMAT " O3=" INTPTR_FORMAT, + SIG_REGS(sc).u_regs[CON_O0], + SIG_REGS(sc).u_regs[CON_O1], + SIG_REGS(sc).u_regs[CON_O2], + SIG_REGS(sc).u_regs[CON_O3]); + st->print_cr(" O4=" INTPTR_FORMAT " O5=" INTPTR_FORMAT + " O6=" INTPTR_FORMAT " O7=" INTPTR_FORMAT, + SIG_REGS(sc).u_regs[CON_O4], + SIG_REGS(sc).u_regs[CON_O5], + SIG_REGS(sc).u_regs[CON_O6], + SIG_REGS(sc).u_regs[CON_O7]); + + st->print_cr(" G1=" INTPTR_FORMAT " G2=" INTPTR_FORMAT + " G3=" INTPTR_FORMAT " G4=" INTPTR_FORMAT, + SIG_REGS(sc).u_regs[CON_G1], + SIG_REGS(sc).u_regs[CON_G2], + SIG_REGS(sc).u_regs[CON_G3], + SIG_REGS(sc).u_regs[CON_G4]); + st->print_cr(" G5=" INTPTR_FORMAT " G6=" INTPTR_FORMAT + " G7=" INTPTR_FORMAT " Y=" INTPTR_FORMAT, + SIG_REGS(sc).u_regs[CON_G5], + SIG_REGS(sc).u_regs[CON_G6], + SIG_REGS(sc).u_regs[CON_G7], + SIG_REGS(sc).y); + + st->print_cr(" PC=" INTPTR_FORMAT " nPC=" INTPTR_FORMAT, + SIG_PC(sc), + SIG_NPC(sc)); + st->cr(); + st->cr(); + + intptr_t *sp = (intptr_t *)os::Linux::ucontext_get_sp(uc); + st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp); + print_hex_dump(st, (address)sp, (address)(sp + 32), sizeof(intptr_t)); + st->cr(); + + // Note: it may be unsafe to inspect memory near pc. For example, pc may + // point to garbage if entry point in an nmethod is corrupted. Leave + // this at the end, and hope for the best. + address pc = os::Linux::ucontext_get_pc(uc); + st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); + print_hex_dump(st, pc - 16, pc + 16, sizeof(char)); +} + + +address os::Linux::ucontext_get_pc(ucontext_t* uc) { + return (address) SIG_PC((sigcontext*)uc); +} + +intptr_t* os::Linux::ucontext_get_sp(ucontext_t *uc) { + return (intptr_t*) + ((intptr_t)SIG_REGS((sigcontext*)uc).u_regs[CON_O6] + STACK_BIAS); +} + +// not used on Sparc +intptr_t* os::Linux::ucontext_get_fp(ucontext_t *uc) { + ShouldNotReachHere(); + return NULL; +} + +// Utility functions + +extern "C" void Fetch32PFI(); +extern "C" void Fetch32Resume(); +extern "C" void FetchNPFI(); +extern "C" void FetchNResume(); + +inline static bool checkPrefetch(sigcontext* uc, address pc) { + if (pc == (address) Fetch32PFI) { + set_cont_address(uc, address(Fetch32Resume)); + return true; + } + if (pc == (address) FetchNPFI) { + set_cont_address(uc, address(FetchNResume)); + return true; + } + return false; +} + +inline static bool checkOverflow(sigcontext* uc, + address pc, + address addr, + JavaThread* thread, + address* stub) { + // check if fault address is within thread stack + if (addr < thread->stack_base() && + addr >= thread->stack_base() - thread->stack_size()) { + // stack overflow + if (thread->in_stack_yellow_zone(addr)) { + thread->disable_stack_yellow_zone(); + if (thread->thread_state() == _thread_in_Java) { + // Throw a stack overflow exception. Guard pages will be reenabled + // while unwinding the stack. + *stub = + SharedRuntime::continuation_for_implicit_exception(thread, + pc, + SharedRuntime::STACK_OVERFLOW); + } else { + // Thread was in the vm or native code. Return and try to finish. + return true; + } + } else if (thread->in_stack_red_zone(addr)) { + // Fatal red zone violation. Disable the guard pages and fall through + // to handle_unexpected_exception way down below. + thread->disable_stack_red_zone(); + tty->print_raw_cr("An irrecoverable stack overflow has occurred."); + } else { + // Accessing stack address below sp may cause SEGV if current + // thread has MAP_GROWSDOWN stack. This should only happen when + // current thread was created by user code with MAP_GROWSDOWN flag + // and then attached to VM. See notes in os_linux.cpp. + if (thread->osthread()->expanding_stack() == 0) { + thread->osthread()->set_expanding_stack(); + if (os::Linux::manually_expand_stack(thread, addr)) { + thread->osthread()->clear_expanding_stack(); + return true; + } + thread->osthread()->clear_expanding_stack(); + } else { + fatal("recursive segv. expanding stack."); + } + } + } + return false; +} + +inline static bool checkPollingPage(address pc, address fault, address* stub) { + if (fault == os::get_polling_page()) { + *stub = SharedRuntime::get_poll_stub(pc); + return true; + } + return false; +} + +inline static bool checkByteBuffer(address pc, address* stub) { + // BugId 4454115: A read from a MappedByteBuffer can fault + // here if the underlying file has been truncated. + // Do not crash the VM in such a case. + CodeBlob* cb = CodeCache::find_blob_unsafe(pc); + nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL; + if (nm != NULL && nm->has_unsafe_access()) { + *stub = StubRoutines::handler_for_unsafe_access(); + return true; + } + return false; +} + +inline static bool checkVerifyOops(address pc, address fault, address* stub) { + if (pc >= MacroAssembler::_verify_oop_implicit_branch[0] + && pc < MacroAssembler::_verify_oop_implicit_branch[1] ) { + *stub = MacroAssembler::_verify_oop_implicit_branch[2]; + warning("fixed up memory fault in +VerifyOops at address " + INTPTR_FORMAT, fault); + return true; + } + return false; +} + +inline static bool checkFPFault(address pc, int code, + JavaThread* thread, address* stub) { + if (code == FPE_INTDIV || code == FPE_FLTDIV) { + *stub = + SharedRuntime:: + continuation_for_implicit_exception(thread, + pc, + SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO); + return true; + } + return false; +} + +inline static bool checkNullPointer(address pc, intptr_t fault, + JavaThread* thread, address* stub) { + if (!MacroAssembler::needs_explicit_null_check(fault)) { + // Determination of interpreter/vtable stub/compiled code null + // exception + *stub = + SharedRuntime:: + continuation_for_implicit_exception(thread, pc, + SharedRuntime::IMPLICIT_NULL); + return true; + } + return false; +} + +inline static bool checkFastJNIAccess(address pc, address* stub) { + address addr = JNI_FastGetField::find_slowcase_pc(pc); + if (addr != (address)-1) { + *stub = addr; + return true; + } + return false; +} + +inline static bool checkSerializePage(JavaThread* thread, address addr) { + return os::is_memory_serialize_page(thread, addr); +} + +inline static bool checkZombie(sigcontext* uc, address* pc, address* stub) { + if (nativeInstruction_at(*pc)->is_zombie()) { + // zombie method (ld [%g0],%o7 instruction) + *stub = SharedRuntime::get_handle_wrong_method_stub(); + + // At the stub it needs to look like a call from the caller of this + // method (not a call from the segv site). + *pc = (address)SIG_REGS(uc).u_regs[CON_O7]; + return true; + } + return false; +} + +inline static bool checkICMiss(sigcontext* uc, address* pc, address* stub) { +#ifdef COMPILER2 + if (nativeInstruction_at(*pc)->is_ic_miss_trap()) { +#ifdef ASSERT +#ifdef TIERED + CodeBlob* cb = CodeCache::find_blob_unsafe(pc); + assert(cb->is_compiled_by_c2(), "Wrong compiler"); +#endif // TIERED +#endif // ASSERT + // Inline cache missed and user trap "Tne G0+ST_RESERVED_FOR_USER_0+2" taken. + *stub = SharedRuntime::get_ic_miss_stub(); + // At the stub it needs to look like a call from the caller of this + // method (not a call from the segv site). + *pc = (address)SIG_REGS(uc).u_regs[CON_O7]; + return true; + } +#endif // COMPILER2 + return false; +} + +extern "C" int +JVM_handle_linux_signal(int sig, + siginfo_t* info, + void* ucVoid, + int abort_if_unrecognized) { + // in fact this isn't ucontext_t* at all, but struct sigcontext* + // but Linux porting layer uses ucontext_t, so to minimize code change + // we cast as needed + ucontext_t* ucFake = (ucontext_t*) ucVoid; + sigcontext* uc = (sigcontext*)ucVoid; + + Thread* t = ThreadLocalStorage::get_thread_slow(); + + SignalHandlerMark shm(t); + + // Note: it's not uncommon that JNI code uses signal/sigset to install + // then restore certain signal handler (e.g. to temporarily block SIGPIPE, + // or have a SIGILL handler when detecting CPU type). When that happens, + // JVM_handle_linux_signal() might be invoked with junk info/ucVoid. To + // avoid unnecessary crash when libjsig is not preloaded, try handle signals + // that do not require siginfo/ucontext first. + + if (sig == SIGPIPE || sig == SIGXFSZ) { + // allow chained handler to go first + if (os::Linux::chained_handler(sig, info, ucVoid)) { + return true; + } else { + if (PrintMiscellaneous && (WizardMode || Verbose)) { + char buf[64]; + warning("Ignoring %s - see bugs 4229104 or 646499219", + os::exception_name(sig, buf, sizeof(buf))); + } + return true; + } + } + + JavaThread* thread = NULL; + VMThread* vmthread = NULL; + if (os::Linux::signal_handlers_are_installed) { + if (t != NULL ){ + if(t->is_Java_thread()) { + thread = (JavaThread*)t; + } + else if(t->is_VM_thread()){ + vmthread = (VMThread *)t; + } + } + } + + // decide if this trap can be handled by a stub + address stub = NULL; + address pc = NULL; + address npc = NULL; + + //%note os_trap_1 + if (info != NULL && uc != NULL && thread != NULL) { + pc = address(SIG_PC(uc)); + npc = address(SIG_NPC(uc)); + + // Check to see if we caught the safepoint code in the + // process of write protecting the memory serialization page. + // It write enables the page immediately after protecting it + // so we can just return to retry the write. + if ((sig == SIGSEGV) && checkSerializePage(thread, (address)info->si_addr)) { + // Block current thread until the memory serialize page permission restored. + os::block_on_serialize_page_trap(); + return 1; + } + + if (checkPrefetch(uc, pc)) { + return 1; + } + + // Handle ALL stack overflow variations here + if (sig == SIGSEGV) { + if (checkOverflow(uc, pc, (address)info->si_addr, thread, &stub)) { + return 1; + } + } + + if (sig == SIGBUS && + thread->thread_state() == _thread_in_vm && + thread->doing_unsafe_access()) { + stub = StubRoutines::handler_for_unsafe_access(); + } + + if (thread->thread_state() == _thread_in_Java) { + do { + // Java thread running in Java code => find exception handler if any + // a fault inside compiled code, the interpreter, or a stub + + if ((sig == SIGSEGV) && checkPollingPage(pc, (address)info->si_addr, &stub)) { + break; + } + + if ((sig == SIGBUS) && checkByteBuffer(pc, &stub)) { + break; + } + + if ((sig == SIGSEGV || sig == SIGBUS) && + checkVerifyOops(pc, (address)info->si_addr, &stub)) { + break; + } + + if ((sig == SIGSEGV) && checkZombie(uc, &pc, &stub)) { + break; + } + + if ((sig == SIGILL) && checkICMiss(uc, &pc, &stub)) { + break; + } + + if ((sig == SIGFPE) && checkFPFault(pc, info->si_code, thread, &stub)) { + break; + } + + if ((sig == SIGSEGV) && + checkNullPointer(pc, (intptr_t)info->si_addr, thread, &stub)) { + break; + } + } while (0); + + // jni_fast_GetField can trap at certain pc's if a GC kicks in + // and the heap gets shrunk before the field access. + if ((sig == SIGSEGV) || (sig == SIGBUS)) { + checkFastJNIAccess(pc, &stub); + } + } + + if (stub != NULL) { + // save all thread context in case we need to restore it + thread->set_saved_exception_pc(pc); + thread->set_saved_exception_npc(npc); + set_cont_address(uc, stub); + return true; + } + } + + // signal-chaining + if (os::Linux::chained_handler(sig, info, ucVoid)) { + return true; + } + + if (!abort_if_unrecognized) { + // caller wants another chance, so give it to him + return false; + } + + if (pc == NULL && uc != NULL) { + pc = os::Linux::ucontext_get_pc((ucontext_t*)uc); + } + + // unmask current signal + sigset_t newset; + sigemptyset(&newset); + sigaddset(&newset, sig); + sigprocmask(SIG_UNBLOCK, &newset, NULL); + + VMError err(t, sig, pc, info, ucVoid); + err.report_and_die(); + + ShouldNotReachHere(); +} + +void os::Linux::init_thread_fpu_state(void) { + // Nothing to do +} + +int os::Linux::get_fpu_control_word() { + return 0; +} + +void os::Linux::set_fpu_control_word(int fpu) { + // nothing +} + +bool os::is_allocatable(size_t bytes) { +#ifdef _LP64 + return true; +#else + if (bytes < 2 * G) { + return true; + } + + char* addr = reserve_memory(bytes, NULL); + + if (addr != NULL) { + release_memory(addr, bytes); + } + + return addr != NULL; +#endif // _LP64 +} + +/////////////////////////////////////////////////////////////////////////////// +// thread stack + +size_t os::Linux::min_stack_allowed = 128 * K; + +// pthread on Ubuntu is always in floating stack mode +bool os::Linux::supports_variable_stack_size() { return true; } + +// return default stack size for thr_type +size_t os::Linux::default_stack_size(os::ThreadType thr_type) { + // default stack size (compiler thread needs larger stack) + size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M); + return s; +} + +size_t os::Linux::default_guard_size(os::ThreadType thr_type) { + // Creating guard page is very expensive. Java thread has HotSpot + // guard page, only enable glibc guard page for non-Java threads. + return (thr_type == java_thread ? 0 : page_size()); +} diff --git a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.hpp b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.hpp new file mode 100644 index 00000000000..0a88fef95e2 --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.hpp @@ -0,0 +1,46 @@ +/* + * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + + // + // NOTE: we are back in class os here, not Linux + // + static jint (*atomic_xchg_func) (jint, volatile jint*); + static jint (*atomic_cmpxchg_func) (jint, volatile jint*, jint); + static jlong (*atomic_cmpxchg_long_func)(jlong, volatile jlong*, jlong); + static jint (*atomic_add_func) (jint, volatile jint*); + static void (*fence_func) (); + + static jint atomic_xchg_bootstrap (jint, volatile jint*); + static jint atomic_cmpxchg_bootstrap (jint, volatile jint*, jint); + static jlong atomic_cmpxchg_long_bootstrap(jlong, volatile jlong*, jlong); + static jint atomic_add_bootstrap (jint, volatile jint*); + static void fence_bootstrap (); + + static void setup_fpu() {} + + static bool is_allocatable(size_t bytes); + + // Used to register dynamic code cache area with the OS + // Note: Currently only used in 64 bit Windows implementations + static bool register_code_area(char *low, char *high) { return true; } diff --git a/hotspot/src/os_cpu/linux_sparc/vm/prefetch_linux_sparc.inline.hpp b/hotspot/src/os_cpu/linux_sparc/vm/prefetch_linux_sparc.inline.hpp new file mode 100644 index 00000000000..250704ff5d9 --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/prefetch_linux_sparc.inline.hpp @@ -0,0 +1,40 @@ +/* + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#if defined(COMPILER2) || defined(_LP64) + +inline void Prefetch::read(void *loc, intx interval) { + __asm__ volatile("prefetch [%0+%1], 0" : : "r" (loc), "r" (interval) : "memory" ); +} + +inline void Prefetch::write(void *loc, intx interval) { + __asm__ volatile("prefetch [%0+%1], 2" : : "r" (loc), "r" (interval) : "memory" ); +} + +#else + +inline void Prefetch::read (void *loc, intx interval) {} +inline void Prefetch::write(void *loc, intx interval) {} + +#endif diff --git a/hotspot/src/os_cpu/linux_sparc/vm/threadLS_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/threadLS_linux_sparc.cpp new file mode 100644 index 00000000000..a2c536cfc53 --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/threadLS_linux_sparc.cpp @@ -0,0 +1,37 @@ +/* + * Copyright 1998-2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#include "incls/_precompiled.incl" +#include "incls/_threadLS_linux_sparc.cpp.incl" + +void ThreadLocalStorage::generate_code_for_get_thread() { +} + +void ThreadLocalStorage::pd_init() { + // Nothing to do +} + +void ThreadLocalStorage::pd_set_thread(Thread* thread) { + os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); +} diff --git a/hotspot/src/os_cpu/linux_sparc/vm/threadLS_linux_sparc.hpp b/hotspot/src/os_cpu/linux_sparc/vm/threadLS_linux_sparc.hpp new file mode 100644 index 00000000000..5cfa7ee8647 --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/threadLS_linux_sparc.hpp @@ -0,0 +1,28 @@ +/* + * Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +public: + static Thread* thread() { + return (Thread*) os::thread_local_storage_at(thread_index()); + } diff --git a/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp new file mode 100644 index 00000000000..1c8a030d0d7 --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.cpp @@ -0,0 +1,107 @@ +/* + * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#include "incls/_precompiled.incl" +#include "incls/_thread_linux_sparc.cpp.incl" + +// For Forte Analyzer AsyncGetCallTrace profiling support - thread is +// currently interrupted by SIGPROF +bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, + void* ucontext, + bool isInJava) { + assert(Thread::current() == this, "caller must be current thread"); + assert(this->is_Java_thread(), "must be JavaThread"); + + JavaThread* jt = (JavaThread *)this; + + if (!isInJava) { + // make_walkable flushes register windows and grabs last_Java_pc + // which can not be done if the ucontext sp matches last_Java_sp + // stack walking utilities assume last_Java_pc set if marked flushed + jt->frame_anchor()->make_walkable(jt); + } + + // If we have a walkable last_Java_frame, then we should use it + // even if isInJava == true. It should be more reliable than + // ucontext info. + if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) { + *fr_addr = jt->pd_last_frame(); + return true; + } + + ucontext_t* uc = (ucontext_t*) ucontext; + + // At this point, we don't have a walkable last_Java_frame, so + // we try to glean some information out of the ucontext. + intptr_t* ret_sp; + ExtendedPC addr = + os::fetch_frame_from_context(uc, &ret_sp, + NULL /* ret_fp only used on X86 */); + if (addr.pc() == NULL || ret_sp == NULL) { + // ucontext wasn't useful + return false; + } + + // we were running Java code when SIGPROF came in + if (isInJava) { + // If we have a last_Java_sp, then the SIGPROF signal caught us + // right when we were transitioning from _thread_in_Java to a new + // JavaThreadState. We use last_Java_sp instead of the sp from + // the ucontext since it should be more reliable. + if (jt->has_last_Java_frame()) { + ret_sp = jt->last_Java_sp(); + } + // Implied else: we don't have a last_Java_sp so we use what we + // got from the ucontext. + + frame ret_frame(ret_sp, frame::unpatchable, addr.pc()); + if (!ret_frame.safe_for_sender(jt)) { + // nothing else to try if the frame isn't good + return false; + } + *fr_addr = ret_frame; + return true; + } + + // At this point, we know we weren't running Java code. We might + // have a last_Java_sp, but we don't have a walkable frame. + // However, we might still be able to construct something useful + // if the thread was running native code. + if (jt->has_last_Java_frame()) { + assert(!jt->frame_anchor()->walkable(), "case covered above"); + + if (jt->thread_state() == _thread_in_native) { + frame ret_frame(jt->last_Java_sp(), frame::unpatchable, addr.pc()); + if (!ret_frame.safe_for_sender(jt)) { + // nothing else to try if the frame isn't good + return false; + } + *fr_addr = ret_frame; + return true; + } + } + + // nothing else to try + return false; +} diff --git a/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.hpp b/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.hpp new file mode 100644 index 00000000000..14ece634631 --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/thread_linux_sparc.hpp @@ -0,0 +1,98 @@ +/* + * Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +private: + + void pd_initialize() { + _anchor.clear(); + _base_of_stack_pointer = NULL; + } + + frame pd_last_frame() { + assert(has_last_Java_frame(), "must have last_Java_sp() when suspended"); + assert(_anchor.walkable(), "thread has not dumped its register windows yet"); + + assert(_anchor.last_Java_pc() != NULL, "Ack no pc!"); + return frame(last_Java_sp(), frame::unpatchable, _anchor.last_Java_pc()); + } + + // Sometimes the trap handler needs to record both PC and NPC. + // This is a SPARC-specific companion to Thread::set_saved_exception_pc. + address _saved_exception_npc; + + // In polling_page_safepoint_handler_blob(s) we have to tail call other + // blobs without blowing any registers. A tail call requires some + // register to jump with and we can't blow any registers, so it must + // be restored in the delay slot. 'restore' cannot be used as it + // will chop the heads off of 64-bit %o registers in the 32-bit + // build. Instead we reload the registers using G2_thread and this + // location. Must be 64bits in the 32-bit LION build. + jdouble _o_reg_temps[6]; + + // a stack pointer older than any java frame stack pointer. It is + // used to validate stack pointers in frame::next_younger_sp (it + // provides the upper bound in the range check). This is necessary + // on Solaris/SPARC since the ucontext passed to a signal handler is + // sometimes corrupt and we need a way to check the extracted sp. + intptr_t* _base_of_stack_pointer; + +public: + + static int o_reg_temps_offset_in_bytes() { return offset_of(JavaThread, _o_reg_temps); } + +#ifndef _LP64 + address o_reg_temps(int i) { return (address)&_o_reg_temps[i]; } +#endif + + static int saved_exception_npc_offset_in_bytes() { return offset_of(JavaThread,_saved_exception_npc); } + + address saved_exception_npc() { return _saved_exception_npc; } + void set_saved_exception_npc(address a) { _saved_exception_npc = a; } + + +public: + + intptr_t* base_of_stack_pointer() { return _base_of_stack_pointer; } + + void set_base_of_stack_pointer(intptr_t* base_sp) { + _base_of_stack_pointer = base_sp; + } + + void record_base_of_stack_pointer() { + intptr_t *sp = (intptr_t *)(((intptr_t)StubRoutines::Sparc::flush_callers_register_windows_func()())); + intptr_t *ysp; + while((ysp = (intptr_t*)sp[FP->sp_offset_in_saved_window()]) != NULL) { + sp = (intptr_t *)((intptr_t)ysp + STACK_BIAS); + } + _base_of_stack_pointer = sp; + } + + bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, + bool isInJava); + + // These routines are only used on cpu architectures that + // have separate register stacks (Itanium). + static bool register_stack_overflow() { return false; } + static void enable_register_stack_guard() {} + static void disable_register_stack_guard() {} diff --git a/hotspot/src/os_cpu/linux_sparc/vm/vmStructs_linux_sparc.hpp b/hotspot/src/os_cpu/linux_sparc/vm/vmStructs_linux_sparc.hpp new file mode 100644 index 00000000000..5358d213c65 --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/vmStructs_linux_sparc.hpp @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +// These are the OS and CPU-specific fields, types and integer +// constants required by the Serviceability Agent. This file is +// referenced by vmStructs.cpp. + +#define VM_STRUCTS_OS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field, last_entry) \ + \ + /******************************/ \ + /* Threads (NOTE: incomplete) */ \ + /******************************/ \ + \ + nonstatic_field(JavaThread, _base_of_stack_pointer, intptr_t*) \ + nonstatic_field(OSThread, _thread_id, pid_t) \ + nonstatic_field(OSThread, _pthread_id, pthread_t) \ + /* This must be the last entry, and must be present */ \ + last_entry() + + +#define VM_TYPES_OS_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, last_entry) \ + \ + /**********************/ \ + /* POSIX Thread IDs */ \ + /**********************/ \ + \ + declare_integer_type(pid_t) \ + declare_unsigned_integer_type(pthread_t) \ + \ + /* This must be the last entry, and must be present */ \ + last_entry() + + +#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ + \ + /************************/ \ + /* JavaThread constants */ \ + /************************/ \ + \ + declare_constant(JavaFrameAnchor::flushed) \ + \ + /* This must be the last entry, and must be present */ \ + last_entry() + +#define VM_LONG_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant, last_entry) \ + \ + /* This must be the last entry, and must be present */ \ + last_entry() diff --git a/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp new file mode 100644 index 00000000000..34bd7c82c99 --- /dev/null +++ b/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp @@ -0,0 +1,61 @@ +/* + * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +# include "incls/_precompiled.incl" +# include "incls/_vm_version_linux_sparc.cpp.incl" + +static bool detect_niagara() { + char cpu[128]; + bool rv = false; + + FILE* fp = fopen("/proc/cpuinfo", "r"); + if (fp == NULL) { + return rv; + } + + while (!feof(fp)) { + if (fscanf(fp, "cpu\t\t: %100[^\n]", &cpu) == 1) { + if (strstr(cpu, "Niagara") != NULL) { + rv = true; + } + break; + } + } + + fclose(fp); + + return rv; +} + +int VM_Version::platform_features(int features) { + // Default to generic v9 + features = generic_v9_m; + + if (detect_niagara()) { + NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Detected Linux on Niagara");) + features = niagara1_m; + } + + return features; +} diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.s b/hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.s index f243c3fb9e5..411fdcdabf0 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.s +++ b/hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.s @@ -33,7 +33,9 @@ !! by the .il "call", in some cases optimizing the code, completely eliding it, !! or by moving the code from the "call site". - + !! ASM better know we may use G6 for our own purposes + .register %g6, #ignore + .globl SafeFetch32 .align 32 .global Fetch32PFI, Fetch32Resume @@ -106,6 +108,7 @@ SpinPause: .globl _raw_thread_id .align 32 _raw_thread_id: + .register %g7, #scratch retl mov %g7, %o0 diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp index 9a4118bba05..1896130226f 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/thread_solaris_sparc.cpp @@ -50,17 +50,6 @@ bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, // even if isInJava == true. It should be more reliable than // ucontext info. if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) { -#if 0 - // This sanity check may not be needed with the new frame - // walking code. Remove it for now. - if (!jt->frame_anchor()->post_Java_state_is_pc() - && frame::next_younger_sp_or_null(last_Java_sp(), - jt->frame_anchor()->post_Java_sp()) == NULL) { - // the anchor contains an SP, but the frame is not walkable - // because post_Java_sp isn't valid relative to last_Java_sp - return false; - } -#endif *fr_addr = jt->pd_last_frame(); return true; } @@ -77,23 +66,59 @@ bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, return false; } + frame ret_frame(ret_sp, frame::unpatchable, addr.pc()); + // we were running Java code when SIGPROF came in if (isInJava) { + + + // If the frame we got is safe then it is most certainly valid + if (ret_frame.safe_for_sender(jt)) { + *fr_addr = ret_frame; + return true; + } + + // If it isn't safe then we can try several things to try and get + // a good starting point. + // + // On sparc the frames are almost certainly walkable in the sense + // of sp/fp linkages. However because of recycling of windows if + // a piece of code does multiple save's where the initial save creates + // a real frame with a return pc and the succeeding save's are used to + // simply get free registers and have no real pc then the pc linkage on these + // "inner" temporary frames will be bogus. + // Since there is in general only a nesting level like + // this one deep in general we'll try and unwind such an "inner" frame + // here ourselves and see if it makes sense + + frame unwind_frame(ret_frame.fp(), frame::unpatchable, addr.pc()); + + if (unwind_frame.safe_for_sender(jt)) { + *fr_addr = unwind_frame; + return true; + } + + // Well that didn't work. Most likely we're toast on this tick + // The previous code would try this. I think it is dubious in light + // of changes to safe_for_sender and the unwind trick above but + // if it gets us a safe frame who wants to argue. + // If we have a last_Java_sp, then the SIGPROF signal caught us // right when we were transitioning from _thread_in_Java to a new // JavaThreadState. We use last_Java_sp instead of the sp from // the ucontext since it should be more reliable. + if (jt->has_last_Java_frame()) { ret_sp = jt->last_Java_sp(); + frame ret_frame2(ret_sp, frame::unpatchable, addr.pc()); + if (ret_frame2.safe_for_sender(jt)) { + *fr_addr = ret_frame2; + return true; + } } - // Implied else: we don't have a last_Java_sp so we use what we - // got from the ucontext. - frame ret_frame(ret_sp, frame::unpatchable, addr.pc()); - if (!ret_frame.safe_for_sender(jt)) { - // nothing else to try if the frame isn't good - return false; - } + // This is the best we can do. We will only be able to decode the top frame + *fr_addr = ret_frame; return true; } @@ -105,17 +130,13 @@ bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, if (jt->has_last_Java_frame()) { assert(!jt->frame_anchor()->walkable(), "case covered above"); - if (jt->thread_state() == _thread_in_native) { - frame ret_frame(jt->last_Java_sp(), frame::unpatchable, addr.pc()); - if (!ret_frame.safe_for_sender(jt)) { - // nothing else to try if the frame isn't good - return false; - } - *fr_addr = ret_frame; - return true; - } + frame ret_frame(jt->last_Java_sp(), frame::unpatchable, addr.pc()); + *fr_addr = ret_frame; + return true; } - // nothing else to try - return false; + // nothing else to try but what we found initially + + *fr_addr = ret_frame; + return true; } diff --git a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp index 0fcf224df44..34365dfaee9 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp @@ -212,7 +212,8 @@ frame os::current_frame() { CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + frame ret; // This will be a null useless frame + return ret; } else { return os::get_sender_for_C_frame(&myframe); } diff --git a/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp index eab73273efa..06c9aed2e85 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp @@ -32,49 +32,53 @@ bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, assert(Thread::current() == this, "caller must be current thread"); assert(this->is_Java_thread(), "must be JavaThread"); - JavaThread* jt = (JavaThread *)this; - // If we have a last_Java_frame, then we should use it even if - // isInJava == true. It should be more reliable than ucontext info. + // last_Java_frame is always walkable and safe use it if we have it + if (jt->has_last_Java_frame()) { *fr_addr = jt->pd_last_frame(); return true; } - // At this point, we don't have a last_Java_frame, so - // we try to glean some information out of the ucontext - // if we were running Java code when SIGPROF came in. - if (isInJava) { - ucontext_t* uc = (ucontext_t*) ucontext; + ucontext_t* uc = (ucontext_t*) ucontext; - intptr_t* ret_fp; - intptr_t* ret_sp; - ExtendedPC addr = os::Solaris::fetch_frame_from_ucontext(this, uc, - &ret_sp, &ret_fp); - if (addr.pc() == NULL || ret_sp == NULL ) { - // ucontext wasn't useful - return false; - } + // We always want to use the initial frame we create from the ucontext as + // it certainly signals where we currently are. However that frame may not + // be safe for calling sender. In that case if we have a last_Java_frame + // then the forte walker will switch to that frame as the virtual sender + // for the frame we create here which is not sender safe. + + intptr_t* ret_fp; + intptr_t* ret_sp; + ExtendedPC addr = os::Solaris::fetch_frame_from_ucontext(this, uc, &ret_sp, &ret_fp); + + // Something would really have to be screwed up to get a NULL pc + + if (addr.pc() == NULL ) { + assert(false, "NULL pc from signal handler!"); + return false; - frame ret_frame(ret_sp, ret_fp, addr.pc()); - if (!ret_frame.safe_for_sender(jt)) { -#ifdef COMPILER2 - frame ret_frame2(ret_sp, NULL, addr.pc()); - if (!ret_frame2.safe_for_sender(jt)) { - // nothing else to try if the frame isn't good - return false; - } - ret_frame = ret_frame2; -#else - // nothing else to try if the frame isn't good - return false; -#endif /* COMPILER2 */ - } - *fr_addr = ret_frame; - return true; } - // nothing else to try - return false; + // If sp and fp are nonsense just leave them out + + if ((address)ret_sp >= jt->stack_base() || + (address)ret_sp < jt->stack_base() - jt->stack_size() ) { + + ret_sp = NULL; + ret_fp = NULL; + } else { + + // sp is reasonable is fp reasonable? + if ( (address)ret_fp >= jt->stack_base() || ret_fp < ret_sp) { + ret_fp = NULL; + } + } + + frame ret_frame(ret_sp, ret_fp, addr.pc()); + + *fr_addr = ret_frame; + return true; + } diff --git a/hotspot/src/share/tools/hsdis/Makefile b/hotspot/src/share/tools/hsdis/Makefile new file mode 100644 index 00000000000..6bdf4b8151c --- /dev/null +++ b/hotspot/src/share/tools/hsdis/Makefile @@ -0,0 +1,135 @@ +# +# Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# +# + +# Single gnu makefile for solaris, linux and windows (windows requires mks or +# cygwin). + +ifeq ($(BINUTILS),) +# Pop all the way out of the workspace to look for binutils. +# ...You probably want to override this setting. +BINUTILS = $(shell cd ../../../../..;pwd)/binutils-2.17-$(LIBARCH) +endif + +# Default arch; it is changed below as needed. +ARCH = i386 +OS = $(shell uname) + +CPPFLAGS += -I$(BINUTILS)/include -I$(BINUTILS)/bfd +CPPFLAGS += -DHOTSPOT_LIB_ARCH=\"$(LIBARCH)\" -DLIBARCH_$(LIBARCH) +CPPFLAGS += -DHOTSPOT_OS=\"$(OS)\" -DOS_$(OS) + +## OS = SunOS ## +ifeq ($(OS),SunOS) +ARCH = $(shell uname -p) +OS = solaris +CC = cc +CCFLAGS += -Kpic -g +CCFLAGS/amd64 += -xarch=amd64 +CCFLAGS/sparcv9 += -xarch=v9 +CCFLAGS += $(CCFLAGS/$(LIBARCH)) +DLDFLAGS += -G +OUTFLAGS += -o $@ +LIB_EXT = .so +else +## OS = Linux ## +ifeq ($(OS),Linux) +CPU = $(shell uname -m) +ifeq ($(CPU),ia64) +ARCH = ia64 +else +ifeq ($(CPU),x86_64) +CCFLAGS += -fPIC +endif # x86_64 +endif # ia64 +OS = linux +CC = gcc +CCFLAGS += -O +DLDFLAGS += -shared +OUTFLAGS += -o $@ +LIB_EXT = .so +CPPFLAGS += -Iinclude -Iinclude/$(OS)_$(ARCH)/ +## OS = Windows ## +else # !SunOS, !Linux => Windows +OS = win +CC = cl +#CPPFLAGS += /D"WIN32" /D"_WINDOWS" /D"DEBUG" /D"NDEBUG" +CCFLAGS += /nologo /MD /W3 /WX /O2 /Fo$(@:.dll=.obj) /Gi- +CCFLAGS += -Iinclude -Iinclude/gnu -Iinclude/$(OS)_$(ARCH) +CCFLAGS += /D"HOTSPOT_LIB_ARCH=\"$(LIBARCH)\"" +DLDFLAGS += /dll /subsystem:windows /incremental:no \ + /export:decode_instruction +OUTFLAGS += /link /out:$@ +LIB_EXT = .dll +endif # Linux +endif # SunOS + +LIBARCH = $(ARCH) +ifdef LP64 +LIBARCH64/sparc = sparcv9 +LIBARCH64/i386 = amd64 +LIBARCH64 = $(LIBARCH64/$(ARCH)) +ifneq ($(LIBARCH64),) +LIBARCH = $(LIBARCH64) +endif # LIBARCH64/$(ARCH) +endif # LP64 + +TARGET_DIR = bin/$(OS) +TARGET = $(TARGET_DIR)/hsdis-$(LIBARCH)$(LIB_EXT) + +SOURCE = hsdis.c + +LIBRARIES = $(BINUTILS)/bfd/libbfd.a \ + $(BINUTILS)/opcodes/libopcodes.a \ + $(BINUTILS)/libiberty/libiberty.a + +DEMO_TARGET = $(TARGET_DIR)/hsdis-demo-$(LIBARCH) +DEMO_SOURCE = hsdis-demo.c + +.PHONY: all clean demo both + +all: $(TARGET) demo + +both: all all64 + +%64: + $(MAKE) LP64=1 ${@:%64=%} + +demo: $(TARGET) $(DEMO_TARGET) + +$(LIBRARIES): + @echo "*** Please build binutils first; see ./README: ***" + @sed < ./README '1,/__________/d' | head -20 + @echo "..."; exit 1 + +$(TARGET): $(SOURCE) $(LIBS) $(LIBRARIES) $(TARGET_DIR) + $(CC) $(OUTFLAGS) $(CPPFLAGS) $(CCFLAGS) $(SOURCE) $(DLDFLAGS) $(LIBRARIES) + +$(DEMO_TARGET): $(DEMO_SOURCE) $(TARGET) $(TARGET_DIR) + $(CC) $(OUTFLAGS) $(CPPFLAGS) $(CCFLAGS) $(DEMO_SOURCE) $(LDFLAGS) + +$(TARGET_DIR): + [ -d $@ ] || mkdir -p $@ + +clean: + rm -rf $(TARGET_DIR) diff --git a/hotspot/src/share/tools/hsdis/README b/hotspot/src/share/tools/hsdis/README new file mode 100644 index 00000000000..76c92a44ed8 --- /dev/null +++ b/hotspot/src/share/tools/hsdis/README @@ -0,0 +1,95 @@ +Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + +This code is free software; you can redistribute it and/or modify it +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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +CA 95054 USA or visit www.sun.com if you need additional information or +have any questions. + +________________________________________________________________________ + +'hsdis': A HotSpot plugin for disassembling dynamically generated code. + +The files in this directory (Makefile, hsdis.[ch], hsdis-demo.c) +are built independently of the HotSpot JVM. + +To use the plugin with a JVM, you need a new version that can load it. +If the product mode of your JVM does not accept -XX:+PrintAssembly, +you do not have a version that is new enough. + +* Building + +To build this project you need a build of Gnu binutils to link against. +It is known to work with binutils 2.17. + +The makefile looks for this build in $BINUTILS, or (if that is not set), +in .../binutils-2.17-$LIBARCH, where LIBARCH (as in HotSpot) is one of +the jre subdirectory keywords i386, amd64, sparc, sparcv9, etc. + +To build Gnu binutils, first download a copy of the software: + http://directory.fsf.org/project/binutils/ + +Unpack the binutils tarball into an empty directory: + chdir ../../../../.. + tar -xzf - < ../binutils-2.17.tar.gz + mv binutils-2.17 binutils-2.17-i386 #or binutils-2.17-sparc + cd binutils-2.17-i386 + +From inside that directory, run configure and make: + ( export CFLAGS='-fPIC' + ./configure i386-pc-elf ) + gnumake + +(Leave out or change the argument to configure if not on an i386 system.) + +Next, untar again into another empty directory for the LP64 version: + chdir .. + tar -xzf - < ../binutils-2.17.tar.gz + mv binutils-2.17 binutils-2.17-amd64 #or binutils-2.17-sparcv9 + cd binutils-2.17-amd64 + +From inside that directory, run configure for LP64 and make: + ( export ac_cv_c_bigendian=no CFLAGS='-m64 -fPIC' LDFLAGS=-m64 + ./configure amd64-pc-elf ) + gnumake + +The -fPIC option is needed because the generated code will be +linked into the hsdid-$LIBARCH.so binary. If you miss the +option, the JVM will fail to load the disassembler. + +You probably want two builds, one for 32 and one for 64 bits. +To build the 64-bit variation of a platforn, add LP64=1 to +the make command line for hsdis. + +So, go back to the hsdis project and build: + chdir .../hsdis + gnumake + gnumake LP64=1 + +* Installing + +Products are named like bin/$OS/hsdis-$LIBARCH.so. +You can install them on your LD_LIBRARY_PATH, +or inside of your JRE next to $LIBARCH/libjvm.so. + +Now test: + export LD_LIBRARY_PATH .../hsdis/bin/solaris:$LD_LIBRARY_PATH + dargs='-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly' + dargs=$dargs' -XX:PrintAssemblyOptions=hsdis-print-bytes' + java $dargs -Xbatch CompileCommand=print,*String.hashCode HelloWorld + +If the product mode of the JVM does not accept -XX:+PrintAssembly, +you do not have a version new enough to use the hsdis plugin. diff --git a/hotspot/src/share/tools/hsdis/hsdis-demo.c b/hotspot/src/share/tools/hsdis/hsdis-demo.c new file mode 100644 index 00000000000..adea76e63d7 --- /dev/null +++ b/hotspot/src/share/tools/hsdis/hsdis-demo.c @@ -0,0 +1,223 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +/* hsdis-demo.c -- dump a range of addresses as native instructions + This demonstrates the protocol required by the HotSpot PrintAssembly option. +*/ + +#include "hsdis.h" + +#include "stdio.h" +#include "stdlib.h" +#include "string.h" + +void greet(const char*); +void disassemble(void*, void*); +void end_of_file(); + +const char* options = NULL; +int raw = 0; +int xml = 0; + +int main(int ac, char** av) { + int greeted = 0; + int i; + for (i = 1; i < ac; i++) { + const char* arg = av[i]; + if (arg[0] == '-') { + if (!strcmp(arg, "-xml")) + xml ^= 1; + else if (!strcmp(arg, "-raw")) + raw ^= 1; + else if (!strncmp(arg, "-options=", 9)) + options = arg+9; + else + { printf("Usage: %s [-xml] [name...]\n"); exit(2); } + continue; + } + greet(arg); + greeted = 1; + } + if (!greeted) + greet("world"); + printf("...And now for something completely different:\n"); + disassemble((void*) &main, (void*) &end_of_file); + printf("Cheers!\n"); +} + +void greet(const char* whom) { + printf("Hello, %s!\n", whom); +} + +void end_of_file() { } + +/* don't disassemble after this point... */ + +#include "dlfcn.h" + +#ifdef HOTSPOT_LIB_ARCH +#define LIBARCH HOTSPOT_LIB_ARCH +#endif +#ifdef HOTSPOT_OS +#define OS HOTSPOT_OS +#endif + +#define DECODE_INSTRUCTIONS_NAME "decode_instructions" +#define HSDIS_NAME "hsdis" +static void* decode_instructions_pv = 0; +static const char* hsdis_path[] = { + HSDIS_NAME".so", +#ifdef OS + "bin/"OS"/"HSDIS_NAME".so", +#endif +#ifdef LIBARCH + HSDIS_NAME"-"LIBARCH".so", +#ifdef OS + "bin/"OS"/"HSDIS_NAME"-"LIBARCH".so", +#endif +#endif + NULL +}; + +static const char* load_decode_instructions() { + void* dllib = NULL; + const char* *next_in_path = hsdis_path; + while (1) { + decode_instructions_pv = dlsym(dllib, DECODE_INSTRUCTIONS_NAME); + if (decode_instructions_pv != NULL) + return NULL; + if (dllib != NULL) + return "plugin does not defined "DECODE_INSTRUCTIONS_NAME; + for (dllib = NULL; dllib == NULL; ) { + const char* next_lib = (*next_in_path++); + if (next_lib == NULL) + return "cannot find plugin "HSDIS_NAME".so"; + dllib = dlopen(next_lib, RTLD_LAZY); + } + } +} + + +static const char* lookup(void* addr) { +#define CHECK_NAME(fn) \ + if (addr == (void*) &fn) return #fn; + + CHECK_NAME(main); + CHECK_NAME(greet); + return NULL; +} + +/* does the event match the tag, followed by a null, space, or slash? */ +#define MATCH(event, tag) \ + (!strncmp(event, tag, sizeof(tag)-1) && \ + (!event[sizeof(tag)-1] || strchr(" /", event[sizeof(tag)-1]))) + + +static const char event_cookie[] = "event_cookie"; /* demo placeholder */ +static void* handle_event(void* cookie, const char* event, void* arg) { +#define NS_DEMO "demo:" + if (cookie != event_cookie) + printf("*** bad event cookie %p != %p\n", cookie, event_cookie); + + if (xml) { + /* We could almost do a printf(event, arg), + but for the sake of a better demo, + we dress the result up as valid XML. + */ + const char* fmt = strchr(event, ' '); + int evlen = (fmt ? fmt - event : strlen(event)); + if (!fmt) { + if (event[0] != '/') { + printf("<"NS_DEMO"%.*s>", evlen, event); + } else { + printf("", evlen-1, event+1); + } + } else { + if (event[0] != '/') { + printf("<"NS_DEMO"%.*s", evlen, event); + printf(fmt, arg); + printf(">"); + } else { + printf("<"NS_DEMO"%.*s_done", evlen-1, event+1); + printf(fmt, arg); + printf("/>", evlen-1, event+1); + } + } + } + + if (MATCH(event, "insn")) { + const char* name = lookup(arg); + if (name) printf("%s:\n", name); + + /* basic action for : */ + printf(" %p\t", arg); + + } else if (MATCH(event, "/insn")) { + /* basic action for : + (none, plugin puts the newline for us + */ + + } else if (MATCH(event, "mach")) { + printf("Decoding for CPU '%s'\n", (char*) arg); + + } else if (MATCH(event, "addr")) { + /* basic action for : */ + const char* name = lookup(arg); + if (name) { + printf("&%s (%p)", name, arg); + /* return non-null to notify hsdis not to print the addr */ + return arg; + } + } + + /* null return is always safe; can mean "I ignored it" */ + return NULL; +} + +#define fprintf_callback \ + (decode_instructions_printf_callback_ftype)&fprintf + +void disassemble(void* from, void* to) { + const char* err = load_decode_instructions(); + if (err != NULL) { + printf("%s: %s\n", err, dlerror()); + exit(1); + } + printf("Decoding from %p to %p...\n", from, to); + decode_instructions_ftype decode_instructions + = (decode_instructions_ftype) decode_instructions_pv; + void* res; + if (raw && xml) { + res = (*decode_instructions)(from, to, NULL, stdout, NULL, stdout, options); + } else if (raw) { + res = (*decode_instructions)(from, to, NULL, NULL, NULL, stdout, options); + } else { + res = (*decode_instructions)(from, to, + handle_event, (void*) event_cookie, + fprintf_callback, stdout, + options); + } + if (res != to) + printf("*** Result was %p!\n", res); +} diff --git a/hotspot/src/share/tools/hsdis/hsdis.c b/hotspot/src/share/tools/hsdis/hsdis.c new file mode 100644 index 00000000000..75b7efe2638 --- /dev/null +++ b/hotspot/src/share/tools/hsdis/hsdis.c @@ -0,0 +1,499 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +/* hsdis.c -- dump a range of addresses as native instructions + This implements the plugin protocol required by the + HotSpot PrintAssembly option. +*/ + +#include "hsdis.h" + +#include +#include +#include +#include + +#ifndef bool +#define bool int +#define true 1 +#define false 0 +#endif /*bool*/ + +/* short names for stuff in hsdis.h */ +typedef decode_instructions_event_callback_ftype event_callback_t; +typedef decode_instructions_printf_callback_ftype printf_callback_t; + +/* disassemble_info.application_data object */ +struct hsdis_app_data { + /* the arguments to decode_instructions */ + uintptr_t start; uintptr_t end; + event_callback_t event_callback; void* event_stream; + printf_callback_t printf_callback; void* printf_stream; + bool losing; + + /* the architecture being disassembled */ + const char* arch_name; + const bfd_arch_info_type* arch_info; + + /* the disassembler we are going to use: */ + disassembler_ftype dfn; + struct disassemble_info dinfo; /* the actual struct! */ + + char mach_option[64]; + char insn_options[256]; +}; + +#define DECL_APP_DATA(dinfo) \ + struct hsdis_app_data* app_data = (struct hsdis_app_data*) (dinfo)->application_data + +#define DECL_EVENT_CALLBACK(app_data) \ + event_callback_t event_callback = (app_data)->event_callback; \ + void* event_stream = (app_data)->event_stream + +#define DECL_PRINTF_CALLBACK(app_data) \ + printf_callback_t printf_callback = (app_data)->printf_callback; \ + void* printf_stream = (app_data)->printf_stream + + +static void print_help(struct hsdis_app_data* app_data, + const char* msg, const char* arg); +static void setup_app_data(struct hsdis_app_data* app_data, + const char* options); +static const char* format_insn_close(const char* close, + disassemble_info* dinfo, + char* buf, size_t bufsize); + +void* +#ifdef DLL_ENTRY + DLL_ENTRY +#endif +decode_instructions(void* start_pv, void* end_pv, + event_callback_t event_callback_arg, void* event_stream_arg, + printf_callback_t printf_callback_arg, void* printf_stream_arg, + const char* options) { + struct hsdis_app_data app_data; + memset(&app_data, 0, sizeof(app_data)); + app_data.start = (uintptr_t) start_pv; + app_data.end = (uintptr_t) end_pv; + app_data.event_callback = event_callback_arg; + app_data.event_stream = event_stream_arg; + app_data.printf_callback = printf_callback_arg; + app_data.printf_stream = printf_stream_arg; + + setup_app_data(&app_data, options); + char buf[128]; + + { + /* now reload everything from app_data: */ + DECL_EVENT_CALLBACK(&app_data); + DECL_PRINTF_CALLBACK(&app_data); + uintptr_t start = app_data.start; + uintptr_t end = app_data.end; + uintptr_t p = start; + + (*event_callback)(event_stream, "insns", (void*)start); + + (*event_callback)(event_stream, "mach name='%s'", + (void*) app_data.arch_info->printable_name); + if (app_data.dinfo.bytes_per_line != 0) { + (*event_callback)(event_stream, "format bytes-per-line='%p'/", + (void*)(intptr_t) app_data.dinfo.bytes_per_line); + } + + while (p < end && !app_data.losing) { + (*event_callback)(event_stream, "insn", (void*) p); + + /* reset certain state, so we can read it with confidence */ + app_data.dinfo.insn_info_valid = 0; + app_data.dinfo.branch_delay_insns = 0; + app_data.dinfo.data_size = 0; + app_data.dinfo.insn_type = 0; + + int size = (*app_data.dfn)((bfd_vma) p, &app_data.dinfo); + + if (size > 0) p += size; + else app_data.losing = true; + + const char* insn_close = format_insn_close("/insn", &app_data.dinfo, + buf, sizeof(buf)); + (*event_callback)(event_stream, insn_close, (void*) p); + + /* follow each complete insn by a nice newline */ + (*printf_callback)(printf_stream, "\n"); + } + + (*event_callback)(event_stream, "/insns", (void*) p); + return (void*) p; + } +} + +/* take the address of the function, for luck, and also test the typedef: */ +const decode_instructions_ftype decode_instructions_address = &decode_instructions; + +static const char* format_insn_close(const char* close, + disassemble_info* dinfo, + char* buf, size_t bufsize) { + if (!dinfo->insn_info_valid) + return close; + enum dis_insn_type itype = dinfo->insn_type; + int dsize = dinfo->data_size, delays = dinfo->branch_delay_insns; + if ((itype == dis_nonbranch && (dsize | delays) == 0) + || (strlen(close) + 3*20 > bufsize)) + return close; + + const char* type = "unknown"; + switch (itype) { + case dis_nonbranch: type = NULL; break; + case dis_branch: type = "branch"; break; + case dis_condbranch: type = "condbranch"; break; + case dis_jsr: type = "jsr"; break; + case dis_condjsr: type = "condjsr"; break; + case dis_dref: type = "dref"; break; + case dis_dref2: type = "dref2"; break; + } + + strcpy(buf, close); + char* p = buf; + if (type) sprintf(p += strlen(p), " type='%s'", type); + if (dsize) sprintf(p += strlen(p), " dsize='%d'", dsize); + if (delays) sprintf(p += strlen(p), " delay='%d'", delays); + return buf; +} + +/* handler functions */ + +static int +hsdis_read_memory_func(bfd_vma memaddr, + bfd_byte* myaddr, + unsigned int length, + struct disassemble_info* dinfo) { + uintptr_t memaddr_p = (uintptr_t) memaddr; + DECL_APP_DATA(dinfo); + if (memaddr_p + length > app_data->end) { + /* read is out of bounds */ + return EIO; + } else { + memcpy(myaddr, (bfd_byte*) memaddr_p, length); + return 0; + } +} + +static void +hsdis_print_address_func(bfd_vma vma, struct disassemble_info* dinfo) { + /* the actual value to print: */ + void* addr_value = (void*) (uintptr_t) vma; + DECL_APP_DATA(dinfo); + DECL_EVENT_CALLBACK(app_data); + + /* issue the event: */ + void* result = + (*event_callback)(event_stream, "addr/", addr_value); + if (result == NULL) { + /* event declined */ + generic_print_address(vma, dinfo); + } +} + + +/* configuration */ + +static void set_optional_callbacks(struct hsdis_app_data* app_data); +static void parse_caller_options(struct hsdis_app_data* app_data, + const char* caller_options); +static const char* native_arch_name(); +static enum bfd_endian native_endian(); +static const bfd_arch_info_type* find_arch_info(const char* arch_nane); +static bfd* get_native_bfd(const bfd_arch_info_type* arch_info, + /* to avoid malloc: */ + bfd* empty_bfd, bfd_target* empty_xvec); +static void init_disassemble_info_from_bfd(struct disassemble_info* dinfo, + void *stream, + fprintf_ftype fprintf_func, + bfd* bfd, + char* disassembler_options); +static void parse_fake_insn(disassembler_ftype dfn, + struct disassemble_info* dinfo); + +static void setup_app_data(struct hsdis_app_data* app_data, + const char* caller_options) { + /* Make reasonable defaults for null callbacks. + A non-null stream for a null callback is assumed to be a FILE* for output. + Events are rendered as XML. + */ + set_optional_callbacks(app_data); + + /* Look into caller_options for anything interesting. */ + if (caller_options != NULL) + parse_caller_options(app_data, caller_options); + + /* Discover which architecture we are going to disassemble. */ + app_data->arch_name = &app_data->mach_option[0]; + if (app_data->arch_name[0] == '\0') + app_data->arch_name = native_arch_name(); + app_data->arch_info = find_arch_info(app_data->arch_name); + + /* Make a fake bfd to hold the arch. and byteorder info. */ + struct { + bfd_target empty_xvec; + bfd empty_bfd; + } buf; + bfd* native_bfd = get_native_bfd(app_data->arch_info, + /* to avoid malloc: */ + &buf.empty_bfd, &buf.empty_xvec); + init_disassemble_info_from_bfd(&app_data->dinfo, + app_data->printf_stream, + app_data->printf_callback, + native_bfd, + app_data->insn_options); + + /* Finish linking together the various callback blocks. */ + app_data->dinfo.application_data = (void*) app_data; + app_data->dfn = disassembler(native_bfd); + app_data->dinfo.print_address_func = hsdis_print_address_func; + app_data->dinfo.read_memory_func = hsdis_read_memory_func; + + if (app_data->dfn == NULL) { + const char* bad = app_data->arch_name; + static bool complained; + if (bad == &app_data->mach_option[0]) + print_help(app_data, "bad mach=%s", bad); + else if (!complained) + print_help(app_data, "bad native mach=%s; please port hsdis to this platform", bad); + complained = true; + /* must bail out */ + app_data->losing = true; + return; + } + + parse_fake_insn(app_data->dfn, &app_data->dinfo); +} + + +/* ignore all events, return a null */ +static void* null_event_callback(void* ignore_stream, const char* ignore_event, void* arg) { + return NULL; +} + +/* print all events as XML markup */ +static void* xml_event_callback(void* stream, const char* event, void* arg) { + FILE* fp = (FILE*) stream; +#define NS_PFX "dis:" + if (event[0] != '/') { + /* issue the tag, with or without a formatted argument */ + fprintf(fp, "<"NS_PFX); + fprintf(fp, event, arg); + fprintf(fp, ">"); + } else { + ++event; /* skip slash */ + const char* argp = strchr(event, ' '); + if (argp == NULL) { + /* no arguments; just issue the closing tag */ + fprintf(fp, "", event); + } else { + /* split out the closing attributes as */ + int event_prefix = (argp - event); + fprintf(fp, "<"NS_PFX"%.*s_done", event_prefix, event); + fprintf(fp, argp, arg); + fprintf(fp, "/>", event_prefix, event); + } + } + return NULL; +} + +static void set_optional_callbacks(struct hsdis_app_data* app_data) { + if (app_data->printf_callback == NULL) { + int (*fprintf_callback)(FILE*, const char*, ...) = &fprintf; + FILE* fprintf_stream = stdout; + app_data->printf_callback = (printf_callback_t) fprintf_callback; + if (app_data->printf_stream == NULL) + app_data->printf_stream = (void*) fprintf_stream; + } + if (app_data->event_callback == NULL) { + if (app_data->event_stream == NULL) + app_data->event_callback = &null_event_callback; + else + app_data->event_callback = &xml_event_callback; + } + +} + +static void parse_caller_options(struct hsdis_app_data* app_data, const char* caller_options) { + char* iop_base = app_data->insn_options; + char* iop_limit = iop_base + sizeof(app_data->insn_options) - 1; + char* iop = iop_base; + const char* p; + for (p = caller_options; p != NULL; ) { + const char* q = strchr(p, ','); + size_t plen = (q == NULL) ? strlen(p) : ((q++) - p); + if (plen == 4 && strncmp(p, "help", plen) == 0) { + print_help(app_data, NULL, NULL); + } else if (plen >= 5 && strncmp(p, "mach=", 5) == 0) { + char* mach_option = app_data->mach_option; + size_t mach_size = sizeof(app_data->mach_option); + mach_size -= 1; /*leave room for the null*/ + if (plen > mach_size) plen = mach_size; + strncpy(mach_option, p, plen); + mach_option[plen] = '\0'; + } else if (plen > 6 && strncmp(p, "hsdis-", 6)) { + // do not pass these to the next level + } else { + /* just copy it; {i386,sparc}-dis.c might like to see it */ + if (iop > iop_base && iop < iop_limit) (*iop++) = ','; + if (iop + plen > iop_limit) + plen = iop_limit - iop; + strncpy(iop, p, plen); + iop += plen; + } + p = q; + } +} + +static void print_help(struct hsdis_app_data* app_data, + const char* msg, const char* arg) { + DECL_PRINTF_CALLBACK(app_data); + if (msg != NULL) { + (*printf_callback)(printf_stream, "hsdis: "); + (*printf_callback)(printf_stream, msg, arg); + (*printf_callback)(printf_stream, "\n"); + } + (*printf_callback)(printf_stream, "hsdis output options:\n"); + if (printf_callback == (printf_callback_t) &fprintf) + disassembler_usage((FILE*) printf_stream); + else + disassembler_usage(stderr); /* better than nothing */ + (*printf_callback)(printf_stream, " mach= select disassembly mode\n"); +#if defined(LIBARCH_i386) || defined(LIBARCH_amd64) + (*printf_callback)(printf_stream, " mach=i386 select 32-bit mode\n"); + (*printf_callback)(printf_stream, " mach=x86-64 select 64-bit mode\n"); + (*printf_callback)(printf_stream, " suffix always print instruction suffix\n"); +#endif + (*printf_callback)(printf_stream, " help print this message\n"); +} + + +/* low-level bfd and arch stuff that binutils doesn't do for us */ + +static const bfd_arch_info_type* find_arch_info(const char* arch_name) { + const bfd_arch_info_type* arch_info = bfd_scan_arch(arch_name); + if (arch_info == NULL) { + extern const bfd_arch_info_type bfd_default_arch_struct; + arch_info = &bfd_default_arch_struct; + } + return arch_info; +} + +static const char* native_arch_name() { + const char* res = HOTSPOT_LIB_ARCH; +#ifdef LIBARCH_amd64 + res = "i386:x86-64"; +#endif +#ifdef LIBARCH_sparc + res = "sparc:v8plusb"; +#endif +#ifdef LIBARCH_sparc + res = "sparc:v8plusb"; +#endif +#ifdef LIBARCH_sparcv9 + res = "sparc:v9b"; +#endif + if (res == NULL) + res = "HOTSPOT_LIB_ARCH is not set in Makefile!"; + return res; +} + +static enum bfd_endian native_endian() { + int32_t endian_test = 'x'; + if (*(const char*) &endian_test == 'x') + return BFD_ENDIAN_LITTLE; + else + return BFD_ENDIAN_BIG; +} + +static bfd* get_native_bfd(const bfd_arch_info_type* arch_info, + bfd* empty_bfd, bfd_target* empty_xvec) { + memset(empty_bfd, 0, sizeof(*empty_bfd)); + memset(empty_xvec, 0, sizeof(*empty_xvec)); + empty_xvec->flavour = bfd_target_unknown_flavour; + empty_xvec->byteorder = native_endian(); + empty_bfd->xvec = empty_xvec; + empty_bfd->arch_info = arch_info; + return empty_bfd; +} + +static int read_zero_data_only(bfd_vma ignore_p, + bfd_byte* myaddr, unsigned int length, + struct disassemble_info *ignore_info) { + memset(myaddr, 0, length); + return 0; +} +static int print_to_dev_null(void* ignore_stream, const char* ignore_format, ...) { + return 0; +} + +/* Prime the pump by running the selected disassembler on a null input. + This forces the machine-specific disassembler to divulge invariant + information like bytes_per_line. + */ +static void parse_fake_insn(disassembler_ftype dfn, + struct disassemble_info* dinfo) { + typedef int (*read_memory_ftype) + (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length, + struct disassemble_info *info); + read_memory_ftype read_memory_func = dinfo->read_memory_func; + fprintf_ftype fprintf_func = dinfo->fprintf_func; + + dinfo->read_memory_func = &read_zero_data_only; + dinfo->fprintf_func = &print_to_dev_null; + (*dfn)(0, dinfo); + + // put it back: + dinfo->read_memory_func = read_memory_func; + dinfo->fprintf_func = fprintf_func; +} + +static void init_disassemble_info_from_bfd(struct disassemble_info* dinfo, + void *stream, + fprintf_ftype fprintf_func, + bfd* abfd, + char* disassembler_options) { + init_disassemble_info(dinfo, stream, fprintf_func); + + dinfo->flavour = bfd_get_flavour(abfd); + dinfo->arch = bfd_get_arch(abfd); + dinfo->mach = bfd_get_mach(abfd); + dinfo->disassembler_options = disassembler_options; + dinfo->octets_per_byte = bfd_octets_per_byte (abfd); + dinfo->skip_zeroes = sizeof(void*) * 2; + dinfo->skip_zeroes_at_end = sizeof(void*)-1; + dinfo->disassembler_needs_relocs = FALSE; + + if (bfd_big_endian(abfd)) + dinfo->display_endian = dinfo->endian = BFD_ENDIAN_BIG; + else if (bfd_little_endian(abfd)) + dinfo->display_endian = dinfo->endian = BFD_ENDIAN_LITTLE; + else + dinfo->endian = native_endian(); + + disassemble_init_for_target(dinfo); +} diff --git a/hotspot/src/share/tools/hsdis/hsdis.h b/hotspot/src/share/tools/hsdis/hsdis.h new file mode 100644 index 00000000000..df489ff0513 --- /dev/null +++ b/hotspot/src/share/tools/hsdis/hsdis.h @@ -0,0 +1,67 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +/* decode_instructions -- dump a range of addresses as native instructions + This implements the protocol required by the HotSpot PrintAssembly option. + + The starting and ending addresses are within the current process's address space. + + The option string, if not empty, is interpreted by the disassembler implementation. + + The printf callback is 'fprintf' or any other workalike. + It is called as (*printf_callback)(printf_stream, "some format...", some, format, args). + + The event callback receives an event tag (a string) and an argument (a void*). + It is called as (*event_callback)(event_stream, "tag", arg). + + Events: + begin an instruction, at a given location + end an instruction, at a given location + emit the symbolic value of an address + + A tag format is one of three basic forms: "tag", "/tag", "tag/", + where tag is a simple identifier, signifying (as in XML) a element start, + element end, and standalone element. (To render as XML, add angle brackets.) +*/ +extern +#ifdef DLL_EXPORT + DLL_EXPORT +#endif +void* decode_instructions(void* start, void* end, + void* (*event_callback)(void*, const char*, void*), + void* event_stream, + int (*printf_callback)(void*, const char*, ...), + void* printf_stream, + const char* options); + +/* convenience typedefs */ + +typedef void* (*decode_instructions_event_callback_ftype) (void*, const char*, void*); +typedef int (*decode_instructions_printf_callback_ftype) (void*, const char*, ...); +typedef void* (*decode_instructions_ftype) (void* start, void* end, + decode_instructions_event_callback_ftype event_callback, + void* event_stream, + decode_instructions_printf_callback_ftype printf_callback, + void* printf_stream, + const char* options); diff --git a/hotspot/src/share/vm/adlc/archDesc.cpp b/hotspot/src/share/vm/adlc/archDesc.cpp index 0e9088e8f45..534c62a3311 100644 --- a/hotspot/src/share/vm/adlc/archDesc.cpp +++ b/hotspot/src/share/vm/adlc/archDesc.cpp @@ -867,6 +867,7 @@ const char *ArchDesc::reg_mask(InstructForm &inForm) { Form *form = (Form*)_globalNames[result]; assert( form, "Result operand must be defined"); OperandForm *oper = form->is_operand(); + if (oper == NULL) form->dump(); assert( oper, "Result must be an OperandForm"); return reg_mask( *oper ); } @@ -908,6 +909,7 @@ const char *ArchDesc::getIdealType(const char *idealOp) { switch( last_char ) { case 'I': return "TypeInt::INT"; case 'P': return "TypePtr::BOTTOM"; + case 'N': return "TypeNarrowOop::BOTTOM"; case 'F': return "Type::FLOAT"; case 'D': return "Type::DOUBLE"; case 'L': return "TypeLong::LONG"; @@ -944,7 +946,7 @@ void ArchDesc::initBaseOpTypes() { // Create InstructForm and assign type for each ideal instruction. for ( int j = _last_machine_leaf+1; j < _last_opcode; ++j) { char *ident = (char *)NodeClassNames[j]; - if(!strcmp(ident, "ConI") || !strcmp(ident, "ConP") || + if(!strcmp(ident, "ConI") || !strcmp(ident, "ConP") || !strcmp(ident, "ConN") || !strcmp(ident, "ConF") || !strcmp(ident, "ConD") || !strcmp(ident, "ConL") || !strcmp(ident, "Con" ) || !strcmp(ident, "Bool") ) { @@ -1109,6 +1111,7 @@ void ArchDesc::buildMustCloneMap(FILE *fp_hpp, FILE *fp_cpp) { if ( strcmp(idealName,"CmpI") == 0 || strcmp(idealName,"CmpU") == 0 || strcmp(idealName,"CmpP") == 0 + || strcmp(idealName,"CmpN") == 0 || strcmp(idealName,"CmpL") == 0 || strcmp(idealName,"CmpD") == 0 || strcmp(idealName,"CmpF") == 0 diff --git a/hotspot/src/share/vm/adlc/forms.cpp b/hotspot/src/share/vm/adlc/forms.cpp index d51c7d1f95a..7bd2093851e 100644 --- a/hotspot/src/share/vm/adlc/forms.cpp +++ b/hotspot/src/share/vm/adlc/forms.cpp @@ -211,6 +211,7 @@ Form::DataType Form::ideal_to_const_type(const char *name) const { if (strcmp(name,"ConI")==0) return Form::idealI; if (strcmp(name,"ConP")==0) return Form::idealP; + if (strcmp(name,"ConN")==0) return Form::idealN; if (strcmp(name,"ConL")==0) return Form::idealL; if (strcmp(name,"ConF")==0) return Form::idealF; if (strcmp(name,"ConD")==0) return Form::idealD; @@ -256,6 +257,7 @@ Form::DataType Form::is_load_from_memory(const char *opType) const { if( strcmp(opType,"LoadPLocked")==0 ) return Form::idealP; if( strcmp(opType,"LoadLLocked")==0 ) return Form::idealL; if( strcmp(opType,"LoadP")==0 ) return Form::idealP; + if( strcmp(opType,"LoadN")==0 ) return Form::idealN; if( strcmp(opType,"LoadRange")==0 ) return Form::idealI; if( strcmp(opType,"LoadS")==0 ) return Form::idealS; if( strcmp(opType,"Load16B")==0 ) return Form::idealB; @@ -286,6 +288,7 @@ Form::DataType Form::is_store_to_memory(const char *opType) const { if( strcmp(opType,"StoreI")==0) return Form::idealI; if( strcmp(opType,"StoreL")==0) return Form::idealL; if( strcmp(opType,"StoreP")==0) return Form::idealP; + if( strcmp(opType,"StoreN")==0) return Form::idealN; if( strcmp(opType,"Store16B")==0) return Form::idealB; if( strcmp(opType,"Store8B")==0) return Form::idealB; if( strcmp(opType,"Store4B")==0) return Form::idealB; diff --git a/hotspot/src/share/vm/adlc/forms.hpp b/hotspot/src/share/vm/adlc/forms.hpp index e4f8233926a..dfa34454733 100644 --- a/hotspot/src/share/vm/adlc/forms.hpp +++ b/hotspot/src/share/vm/adlc/forms.hpp @@ -168,7 +168,8 @@ public: idealD = 5, // Double type idealB = 6, // Byte type idealC = 7, // Char type - idealS = 8 // String type + idealS = 8, // String type + idealN = 9 // Narrow oop types }; // Convert ideal name to a DataType, return DataType::none if not a 'ConX' Form::DataType ideal_to_const_type(const char *ideal_type_name) const; diff --git a/hotspot/src/share/vm/adlc/formssel.cpp b/hotspot/src/share/vm/adlc/formssel.cpp index a65882497f0..eab02499c2d 100644 --- a/hotspot/src/share/vm/adlc/formssel.cpp +++ b/hotspot/src/share/vm/adlc/formssel.cpp @@ -726,6 +726,9 @@ bool InstructForm::captures_bottom_type() const { if( _matrule && _matrule->_rChild && (!strcmp(_matrule->_rChild->_opType,"CastPP") || // new result type !strcmp(_matrule->_rChild->_opType,"CastX2P") || // new result type + !strcmp(_matrule->_rChild->_opType,"DecodeN") || + !strcmp(_matrule->_rChild->_opType,"EncodeP") || + !strcmp(_matrule->_rChild->_opType,"LoadN") || !strcmp(_matrule->_rChild->_opType,"CreateEx") || // type of exception !strcmp(_matrule->_rChild->_opType,"CheckCastPP")) ) return true; else if ( is_ideal_load() == Form::idealP ) return true; @@ -2101,6 +2104,7 @@ bool OperandForm::is_bound_register() const { if (strcmp(name,"RegF")==0) size = 1; if (strcmp(name,"RegD")==0) size = 2; if (strcmp(name,"RegL")==0) size = 2; + if (strcmp(name,"RegN")==0) size = 1; if (strcmp(name,"RegP")==0) size = globalAD->get_preproc_def("_LP64") ? 2 : 1; if (size == 0) return false; return size == reg_class->size(); @@ -2365,11 +2369,12 @@ void OperandForm::ext_format(FILE *fp, FormDict &globals, uint index) { void OperandForm::format_constant(FILE *fp, uint const_index, uint const_type) { switch(const_type) { - case Form::idealI: fprintf(fp,"st->print(\"#%%d\", _c%d);\n", const_index); break; - case Form::idealP: fprintf(fp,"_c%d->dump_on(st);\n", const_index); break; - case Form::idealL: fprintf(fp,"st->print(\"#%%lld\", _c%d);\n", const_index); break; - case Form::idealF: fprintf(fp,"st->print(\"#%%f\", _c%d);\n", const_index); break; - case Form::idealD: fprintf(fp,"st->print(\"#%%f\", _c%d);\n", const_index); break; + case Form::idealI: fprintf(fp,"st->print(\"#%%d\", _c%d);\n", const_index); break; + case Form::idealP: fprintf(fp,"_c%d->dump_on(st);\n", const_index); break; + case Form::idealN: fprintf(fp,"_c%d->dump_on(st);\n", const_index); break; + case Form::idealL: fprintf(fp,"st->print(\"#%%lld\", _c%d);\n", const_index); break; + case Form::idealF: fprintf(fp,"st->print(\"#%%f\", _c%d);\n", const_index); break; + case Form::idealD: fprintf(fp,"st->print(\"#%%f\", _c%d);\n", const_index); break; default: assert( false, "ShouldNotReachHere()"); } @@ -3300,9 +3305,9 @@ void MatchNode::output(FILE *fp) { int MatchNode::needs_ideal_memory_edge(FormDict &globals) const { static const char *needs_ideal_memory_list[] = { - "StoreI","StoreL","StoreP","StoreD","StoreF" , + "StoreI","StoreL","StoreP","StoreN","StoreD","StoreF" , "StoreB","StoreC","Store" ,"StoreFP", - "LoadI" ,"LoadL", "LoadP" ,"LoadD" ,"LoadF" , + "LoadI" ,"LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF" , "LoadB" ,"LoadC" ,"LoadS" ,"Load" , "Store4I","Store2I","Store2L","Store2D","Store4F","Store2F","Store16B", "Store8B","Store4B","Store8C","Store4C","Store2C", @@ -3311,7 +3316,7 @@ int MatchNode::needs_ideal_memory_edge(FormDict &globals) const { "LoadRange", "LoadKlass", "LoadL_unaligned", "LoadD_unaligned", "LoadPLocked", "LoadLLocked", "StorePConditional", "StoreLConditional", - "CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", + "CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN", "StoreCM", "ClearArray" }; @@ -3712,6 +3717,7 @@ bool MatchRule::is_base_register(FormDict &globals) const { if( base_operand(position, globals, result, name, opType) && (strcmp(opType,"RegI")==0 || strcmp(opType,"RegP")==0 || + strcmp(opType,"RegN")==0 || strcmp(opType,"RegL")==0 || strcmp(opType,"RegF")==0 || strcmp(opType,"RegD")==0 || diff --git a/hotspot/src/share/vm/adlc/output_c.cpp b/hotspot/src/share/vm/adlc/output_c.cpp index 037e129d1b2..168b932179c 100644 --- a/hotspot/src/share/vm/adlc/output_c.cpp +++ b/hotspot/src/share/vm/adlc/output_c.cpp @@ -1546,6 +1546,18 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) { // Build a mapping from operand index to input edges fprintf(fp," unsigned idx0 = oper_input_base();\n"); + + // The order in which inputs are added to a node is very + // strange. Store nodes get a memory input before Expand is + // called and all other nodes get it afterwards so + // oper_input_base is wrong during expansion. This code adjusts + // is so that expansion will work correctly. + bool missing_memory_edge = node->_matrule->needs_ideal_memory_edge(_globalNames) && + node->is_ideal_store() == Form::none; + if (missing_memory_edge) { + fprintf(fp," idx0--; // Adjust base because memory edge hasn't been inserted yet\n"); + } + for( i = 0; i < node->num_opnds(); i++ ) { fprintf(fp," unsigned idx%d = idx%d + num%d;\n", i+1,i,i); @@ -1600,8 +1612,10 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) { int node_mem_op = node->memory_operand(_globalNames); assert( node_mem_op != InstructForm::NO_MEMORY_OPERAND, "expand rule member needs memory but top-level inst doesn't have any" ); - // Copy memory edge - fprintf(fp," n%d->add_req(_in[1]);\t// Add memory edge\n", cnt); + if (!missing_memory_edge) { + // Copy memory edge + fprintf(fp," n%d->add_req(_in[1]);\t// Add memory edge\n", cnt); + } } // Iterate over the new instruction's operands @@ -2363,6 +2377,8 @@ void ArchDesc::defineSize(FILE *fp, InstructForm &inst) { fprintf(fp,"uint %sNode::size(PhaseRegAlloc *ra_) const {\n", inst._ident); + fprintf(fp, " assert(VerifyOops || MachNode::size(ra_) <= %s, \"bad fixed size\");\n", inst._size); + //(2) // Print the size fprintf(fp, " return (VerifyOops ? MachNode::size(ra_) : %s);\n", inst._size); @@ -3426,6 +3442,8 @@ static void path_to_constant(FILE *fp, FormDict &globals, fprintf(fp, "_leaf->get_int()"); } else if ( (strcmp(optype,"ConP") == 0) ) { fprintf(fp, "_leaf->bottom_type()->is_ptr()"); + } else if ( (strcmp(optype,"ConN") == 0) ) { + fprintf(fp, "_leaf->bottom_type()->is_narrowoop()"); } else if ( (strcmp(optype,"ConF") == 0) ) { fprintf(fp, "_leaf->getf()"); } else if ( (strcmp(optype,"ConD") == 0) ) { diff --git a/hotspot/src/share/vm/adlc/output_h.cpp b/hotspot/src/share/vm/adlc/output_h.cpp index 5429e57d954..0640f0a3250 100644 --- a/hotspot/src/share/vm/adlc/output_h.cpp +++ b/hotspot/src/share/vm/adlc/output_h.cpp @@ -203,6 +203,10 @@ static void declareConstStorage(FILE *fp, FormDict &globals, OperandForm *oper) if (i > 0) fprintf(fp,", "); fprintf(fp," const TypePtr *_c%d;\n", i); } + else if (!strcmp(type, "ConN")) { + if (i > 0) fprintf(fp,", "); + fprintf(fp," const TypeNarrowOop *_c%d;\n", i); + } else if (!strcmp(type, "ConL")) { if (i > 0) fprintf(fp,", "); fprintf(fp," jlong _c%d;\n", i); @@ -235,6 +239,10 @@ static void declareConstStorage(FILE *fp, FormDict &globals, OperandForm *oper) fprintf(fp," const TypePtr *_c%d;\n", i); i++; } + else if (!strcmp(comp->base_type(globals), "ConN")) { + fprintf(fp," const TypePtr *_c%d;\n", i); + i++; + } else if (!strcmp(comp->base_type(globals), "ConL")) { fprintf(fp," jlong _c%d;\n", i); i++; @@ -280,6 +288,7 @@ static void defineConstructor(FILE *fp, const char *name, uint num_consts, fprintf(fp,is_ideal_bool ? "BoolTest::mask c%d" : "int32 c%d", i); break; } + case Form::idealN : { fprintf(fp,"const TypeNarrowOop *c%d", i); break; } case Form::idealP : { fprintf(fp,"const TypePtr *c%d", i); break; } case Form::idealL : { fprintf(fp,"jlong c%d", i); break; } case Form::idealF : { fprintf(fp,"jfloat c%d", i); break; } @@ -302,6 +311,11 @@ static void defineConstructor(FILE *fp, const char *name, uint num_consts, fprintf(fp,"const TypePtr *c%d", i); i++; } + else if (!strcmp(comp->base_type(globals), "ConN")) { + if (i > 0) fprintf(fp,", "); + fprintf(fp,"const TypePtr *c%d", i); + i++; + } else if (!strcmp(comp->base_type(globals), "ConL")) { if (i > 0) fprintf(fp,", "); fprintf(fp,"jlong c%d", i); @@ -360,6 +374,10 @@ static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i) { fprintf(fp," _c%d->dump_on(st);\n", i); ++i; } + else if (!strcmp(ideal_type, "ConN")) { + fprintf(fp," _c%d->dump();\n", i); + ++i; + } else if (!strcmp(ideal_type, "ConL")) { fprintf(fp," st->print(\"#\" INT64_FORMAT, _c%d);\n", i); ++i; @@ -417,8 +435,13 @@ void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_ // Replacement variable const char *rep_var = oper._format->_rep_vars.iter(); // Check that it is a local name, and an operand - OperandForm *op = oper._localNames[rep_var]->is_operand(); - assert( op, "replacement variable was not found in local names"); + const Form* form = oper._localNames[rep_var]; + if (form == NULL) { + globalAD->syntax_err(oper._linenum, + "\'%s\' not found in format for %s\n", rep_var, oper._ident); + assert(form, "replacement variable was not found in local names"); + } + OperandForm *op = form->is_operand(); // Get index if register or constant if ( op->_matrule && op->_matrule->is_base_register(globals) ) { idx = oper.register_position( globals, rep_var); @@ -483,9 +506,14 @@ void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_ } else { // Replacement variable const char *rep_var = oper._format->_rep_vars.iter(); - // Check that it is a local name, and an operand - OperandForm *op = oper._localNames[rep_var]->is_operand(); - assert( op, "replacement variable was not found in local names"); + // Check that it is a local name, and an operand + const Form* form = oper._localNames[rep_var]; + if (form == NULL) { + globalAD->syntax_err(oper._linenum, + "\'%s\' not found in format for %s\n", rep_var, oper._ident); + assert(form, "replacement variable was not found in local names"); + } + OperandForm *op = form->is_operand(); // Get index if register or constant if ( op->_matrule && op->_matrule->is_base_register(globals) ) { idx = oper.register_position( globals, rep_var); @@ -1163,7 +1191,7 @@ void ArchDesc::declareClasses(FILE *fp) { if( type != NULL ) { Form::DataType data_type = oper->is_base_constant(_globalNames); // Check if we are an ideal pointer type - if( data_type == Form::idealP ) { + if( data_type == Form::idealP || data_type == Form::idealN ) { // Return the ideal type we already have: fprintf(fp," return _c0;"); } else { @@ -1291,6 +1319,16 @@ void ArchDesc::declareClasses(FILE *fp) { fprintf(fp, " return _c0->isa_oop_ptr();"); fprintf(fp, " }\n"); } + else if (!strcmp(oper->ideal_type(_globalNames), "ConN")) { + // Access the locally stored constant + fprintf(fp," virtual intptr_t constant() const {"); + fprintf(fp, " return _c0->make_oopptr()->get_con();"); + fprintf(fp, " }\n"); + // Generate query to determine if this pointer is an oop + fprintf(fp," virtual bool constant_is_oop() const {"); + fprintf(fp, " return _c0->make_oopptr()->isa_oop_ptr();"); + fprintf(fp, " }\n"); + } else if (!strcmp(oper->ideal_type(_globalNames), "ConL")) { fprintf(fp," virtual intptr_t constant() const {"); // We don't support addressing modes with > 4Gig offsets. @@ -1748,6 +1786,7 @@ void ArchDesc::declareClasses(FILE *fp) { fprintf(fp," return TypeInt::make(opnd_array(1)->constant());\n"); break; case Form::idealP: + case Form::idealN: fprintf(fp," return opnd_array(1)->type();\n",result); break; case Form::idealD: diff --git a/hotspot/src/share/vm/asm/codeBuffer.cpp b/hotspot/src/share/vm/asm/codeBuffer.cpp index a8b19abb3a7..cd88a2ab160 100644 --- a/hotspot/src/share/vm/asm/codeBuffer.cpp +++ b/hotspot/src/share/vm/asm/codeBuffer.cpp @@ -281,8 +281,10 @@ address CodeSection::target(Label& L, address branch_pc) { // Need to return a pc, doesn't matter what it is since it will be // replaced during resolution later. - // (Don't return NULL or badAddress, since branches shouldn't overflow.) - return base; + // Don't return NULL or badAddress, since branches shouldn't overflow. + // Don't return base either because that could overflow displacements + // for shorter branches. It will get checked when bound. + return branch_pc; } } @@ -947,6 +949,7 @@ void CodeComments::print_block_comment(outputStream* stream, intptr_t offset) { if (_comments != NULL) { CodeComment* c = _comments->find(offset); while (c && c->offset() == offset) { + stream->bol(); stream->print(" ;; "); stream->print_cr(c->comment()); c = c->next(); diff --git a/hotspot/src/share/vm/asm/codeBuffer.hpp b/hotspot/src/share/vm/asm/codeBuffer.hpp index 96a983c300c..87f02215d97 100644 --- a/hotspot/src/share/vm/asm/codeBuffer.hpp +++ b/hotspot/src/share/vm/asm/codeBuffer.hpp @@ -36,6 +36,7 @@ public: Verified_Entry, Frame_Complete, // Offset in the code where the frame setup is (for forte stackwalks) is complete OSR_Entry, + Dtrace_trap = OSR_Entry, // dtrace probes can never have an OSR entry so reuse it Exceptions, // Offset where exception handler lives Deopt, // Offset where deopt handler lives max_Entries }; diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index 8fe43955757..8f42fe14327 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -1074,6 +1074,43 @@ JRT_LEAF(void, Runtime1::trace_block_entry(jint block_id)) JRT_END +// Array copy return codes. +enum { + ac_failed = -1, // arraycopy failed + ac_ok = 0 // arraycopy succeeded +}; + + +template int obj_arraycopy_work(oopDesc* src, T* src_addr, + oopDesc* dst, T* dst_addr, + int length) { + + // For performance reasons, we assume we are using a card marking write + // barrier. The assert will fail if this is not the case. + // Note that we use the non-virtual inlineable variant of write_ref_array. + BarrierSet* bs = Universe::heap()->barrier_set(); + assert(bs->has_write_ref_array_opt(), + "Barrier set must have ref array opt"); + if (src == dst) { + // same object, no check + Copy::conjoint_oops_atomic(src_addr, dst_addr, length); + bs->write_ref_array(MemRegion((HeapWord*)dst_addr, + (HeapWord*)(dst_addr + length))); + return ac_ok; + } else { + klassOop bound = objArrayKlass::cast(dst->klass())->element_klass(); + klassOop stype = objArrayKlass::cast(src->klass())->element_klass(); + if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) { + // Elements are guaranteed to be subtypes, so no check necessary + Copy::conjoint_oops_atomic(src_addr, dst_addr, length); + bs->write_ref_array(MemRegion((HeapWord*)dst_addr, + (HeapWord*)(dst_addr + length))); + return ac_ok; + } + } + return ac_failed; +} + // fast and direct copy of arrays; returning -1, means that an exception may be thrown // and we did not copy anything JRT_LEAF(int, Runtime1::arraycopy(oopDesc* src, int src_pos, oopDesc* dst, int dst_pos, int length)) @@ -1081,11 +1118,6 @@ JRT_LEAF(int, Runtime1::arraycopy(oopDesc* src, int src_pos, oopDesc* dst, int d _generic_arraycopy_cnt++; // Slow-path oop array copy #endif - enum { - ac_failed = -1, // arraycopy failed - ac_ok = 0 // arraycopy succeeded - }; - if (src == NULL || dst == NULL || src_pos < 0 || dst_pos < 0 || length < 0) return ac_failed; if (!dst->is_array() || !src->is_array()) return ac_failed; if ((unsigned int) arrayOop(src)->length() < (unsigned int)src_pos + (unsigned int)length) return ac_failed; @@ -1105,30 +1137,14 @@ JRT_LEAF(int, Runtime1::arraycopy(oopDesc* src, int src_pos, oopDesc* dst, int d memmove(dst_addr, src_addr, length << l2es); return ac_ok; } else if (src->is_objArray() && dst->is_objArray()) { - oop* src_addr = objArrayOop(src)->obj_at_addr(src_pos); - oop* dst_addr = objArrayOop(dst)->obj_at_addr(dst_pos); - // For performance reasons, we assume we are using a card marking write - // barrier. The assert will fail if this is not the case. - // Note that we use the non-virtual inlineable variant of write_ref_array. - BarrierSet* bs = Universe::heap()->barrier_set(); - assert(bs->has_write_ref_array_opt(), - "Barrier set must have ref array opt"); - if (src == dst) { - // same object, no check - Copy::conjoint_oops_atomic(src_addr, dst_addr, length); - bs->write_ref_array(MemRegion((HeapWord*)dst_addr, - (HeapWord*)(dst_addr + length))); - return ac_ok; + if (UseCompressedOops) { // will need for tiered + narrowOop *src_addr = objArrayOop(src)->obj_at_addr(src_pos); + narrowOop *dst_addr = objArrayOop(dst)->obj_at_addr(dst_pos); + return obj_arraycopy_work(src, src_addr, dst, dst_addr, length); } else { - klassOop bound = objArrayKlass::cast(dst->klass())->element_klass(); - klassOop stype = objArrayKlass::cast(src->klass())->element_klass(); - if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) { - // Elements are guaranteed to be subtypes, so no check necessary - Copy::conjoint_oops_atomic(src_addr, dst_addr, length); - bs->write_ref_array(MemRegion((HeapWord*)dst_addr, - (HeapWord*)(dst_addr + length))); - return ac_ok; - } + oop *src_addr = objArrayOop(src)->obj_at_addr(src_pos); + oop *dst_addr = objArrayOop(dst)->obj_at_addr(dst_pos); + return obj_arraycopy_work(src, src_addr, dst, dst_addr, length); } } return ac_failed; diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp index 9710b8dd407..ab9b059f0ce 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp @@ -48,6 +48,7 @@ ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) : // Next line must follow and use the result of the previous line: _is_linked = _is_initialized || ik->is_linked(); _nonstatic_field_size = ik->nonstatic_field_size(); + _has_nonstatic_fields = ik->has_nonstatic_fields(); _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: _nof_implementors = ik->nof_implementors(); @@ -93,6 +94,7 @@ ciInstanceKlass::ciInstanceKlass(ciSymbol* name, _is_initialized = false; _is_linked = false; _nonstatic_field_size = -1; + _has_nonstatic_fields = false; _nonstatic_fields = NULL; _nof_implementors = -1; _loader = loader; @@ -201,7 +203,7 @@ ciInstanceKlass* ciInstanceKlass::get_canonical_holder(int offset) { assert(offset >= 0 && offset < layout_helper(), "offset must be tame"); #endif - if (offset < (instanceOopDesc::header_size() * wordSize)) { + if (offset < instanceOopDesc::base_offset_in_bytes()) { // All header offsets belong properly to java/lang/Object. return CURRENT_ENV->Object_klass(); } @@ -210,7 +212,8 @@ ciInstanceKlass* ciInstanceKlass::get_canonical_holder(int offset) { for (;;) { assert(self->is_loaded(), "must be loaded to have size"); ciInstanceKlass* super = self->super(); - if (super == NULL || !super->contains_field_offset(offset)) { + if (super == NULL || super->nof_nonstatic_fields() == 0 || + !super->contains_field_offset(offset)) { return self; } else { self = super; // return super->get_canonical_holder(offset) @@ -381,31 +384,28 @@ int ciInstanceKlass::compute_nonstatic_fields() { if (_nonstatic_fields != NULL) return _nonstatic_fields->length(); - // Size in bytes of my fields, including inherited fields. - // About equal to size_helper() - sizeof(oopDesc). - int fsize = nonstatic_field_size() * wordSize; - if (fsize == 0) { // easy shortcut + if (!has_nonstatic_fields()) { Arena* arena = CURRENT_ENV->arena(); _nonstatic_fields = new (arena) GrowableArray(arena, 0, 0, NULL); return 0; } assert(!is_java_lang_Object(), "bootstrap OK"); + // Size in bytes of my fields, including inherited fields. + int fsize = nonstatic_field_size() * wordSize; + ciInstanceKlass* super = this->super(); - int super_fsize = 0; - int super_flen = 0; GrowableArray* super_fields = NULL; - if (super != NULL) { - super_fsize = super->nonstatic_field_size() * wordSize; - super_flen = super->nof_nonstatic_fields(); + if (super != NULL && super->has_nonstatic_fields()) { + int super_fsize = super->nonstatic_field_size() * wordSize; + int super_flen = super->nof_nonstatic_fields(); super_fields = super->_nonstatic_fields; assert(super_flen == 0 || super_fields != NULL, "first get nof_fields"); - } - - // See if I am no larger than my super; if so, I can use his fields. - if (fsize == super_fsize) { - _nonstatic_fields = super_fields; - return super_fields->length(); + // See if I am no larger than my super; if so, I can use his fields. + if (fsize == super_fsize) { + _nonstatic_fields = super_fields; + return super_fields->length(); + } } GrowableArray* fields = NULL; @@ -425,11 +425,11 @@ int ciInstanceKlass::compute_nonstatic_fields() { // (In principle, they could mix with superclass fields.) fields->sort(sort_field_by_offset); #ifdef ASSERT - int last_offset = sizeof(oopDesc); + int last_offset = instanceOopDesc::base_offset_in_bytes(); for (int i = 0; i < fields->length(); i++) { ciField* field = fields->at(i); int offset = field->offset_in_bytes(); - int size = (field->_type == NULL) ? oopSize : field->size_in_bytes(); + int size = (field->_type == NULL) ? heapOopSize : field->size_in_bytes(); assert(last_offset <= offset, "no field overlap"); if (last_offset > (int)sizeof(oopDesc)) assert((offset - last_offset) < BytesPerLong, "no big holes"); diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp index d52818feca7..a843a9251ea 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.hpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.hpp @@ -35,15 +35,16 @@ class ciInstanceKlass : public ciKlass { friend class ciBytecodeStream; private: - bool _is_shared; - jobject _loader; jobject _protection_domain; + bool _is_shared; bool _is_initialized; bool _is_linked; bool _has_finalizer; bool _has_subklass; + bool _has_nonstatic_fields; + ciFlags _flags; jint _nonstatic_field_size; jint _nonstatic_oop_map_size; @@ -132,6 +133,9 @@ public: jint nonstatic_field_size() { assert(is_loaded(), "must be loaded"); return _nonstatic_field_size; } + jint has_nonstatic_fields() { + assert(is_loaded(), "must be loaded"); + return _has_nonstatic_fields; } jint nonstatic_oop_map_size() { assert(is_loaded(), "must be loaded"); return _nonstatic_oop_map_size; } @@ -164,8 +168,7 @@ public: bool has_finalizable_subclass(); bool contains_field_offset(int offset) { - return (offset/wordSize) >= instanceOopDesc::header_size() - && (offset/wordSize)-instanceOopDesc::header_size() < nonstatic_field_size(); + return instanceOopDesc::contains_field_offset(offset, nonstatic_field_size()); } // Get the instance of java.lang.Class corresponding to diff --git a/hotspot/src/share/vm/ci/ciObjectFactory.cpp b/hotspot/src/share/vm/ci/ciObjectFactory.cpp index 52612b55b0e..649b7354315 100644 --- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp @@ -121,7 +121,7 @@ void ciObjectFactory::init_shared_objects() { for (int i = T_BOOLEAN; i <= T_CONFLICT; i++) { BasicType t = (BasicType)i; - if (type2name(t) != NULL && t != T_OBJECT && t != T_ARRAY) { + if (type2name(t) != NULL && t != T_OBJECT && t != T_ARRAY && t != T_NARROWOOP) { ciType::_basic_types[t] = new (_arena) ciType(t); init_ident_of(ciType::_basic_types[t]); } diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 5b9cb524f21..580aa41ef0c 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -34,7 +34,7 @@ #define JAVA_CLASSFILE_MAGIC 0xCAFEBABE #define JAVA_MIN_SUPPORTED_VERSION 45 -#define JAVA_MAX_SUPPORTED_VERSION 50 +#define JAVA_MAX_SUPPORTED_VERSION 51 #define JAVA_MAX_SUPPORTED_MINOR_VERSION 0 // Used for two backward compatibility reasons: @@ -1359,16 +1359,25 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf // Parse additional attributes in code attribute cfs->guarantee_more(2, CHECK_(nullHandle)); // code_attributes_count u2 code_attributes_count = cfs->get_u2_fast(); - unsigned int calculated_attribute_length = sizeof(max_stack) + - sizeof(max_locals) + - sizeof(code_length) + - code_length + - sizeof(exception_table_length) + - sizeof(code_attributes_count) + - exception_table_length*(sizeof(u2) /* start_pc */+ - sizeof(u2) /* end_pc */ + - sizeof(u2) /* handler_pc */ + - sizeof(u2) /* catch_type_index */); + + unsigned int calculated_attribute_length = 0; + + if (_major_version > 45 || (_major_version == 45 && _minor_version > 2)) { + calculated_attribute_length = + sizeof(max_stack) + sizeof(max_locals) + sizeof(code_length); + } else { + // max_stack, locals and length are smaller in pre-version 45.2 classes + calculated_attribute_length = sizeof(u1) + sizeof(u1) + sizeof(u2); + } + calculated_attribute_length += + code_length + + sizeof(exception_table_length) + + sizeof(code_attributes_count) + + exception_table_length * + ( sizeof(u2) + // start_pc + sizeof(u2) + // end_pc + sizeof(u2) + // handler_pc + sizeof(u2) ); // catch_type_index while (code_attributes_count--) { cfs->guarantee_more(6, CHECK_(nullHandle)); // code_attribute_name_index, code_attribute_length @@ -2332,7 +2341,7 @@ void ClassFileParser::java_lang_Class_fix_post(int* next_nonstatic_oop_offset_pt // Incrementing next_nonstatic_oop_offset here advances the // location where the real java fields are placed. const int extra = java_lang_Class::number_of_fake_oop_fields; - (*next_nonstatic_oop_offset_ptr) += (extra * wordSize); + (*next_nonstatic_oop_offset_ptr) += (extra * heapOopSize); } @@ -2638,7 +2647,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, align_object_offset(vtable_size) + align_object_offset(itable_size)) * wordSize; next_static_double_offset = next_static_oop_offset + - (fac.static_oop_count * oopSize); + (fac.static_oop_count * heapOopSize); if ( fac.static_double_count && (Universe::field_type_should_be_aligned(T_DOUBLE) || Universe::field_type_should_be_aligned(T_LONG)) ) { @@ -2678,6 +2687,14 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, int nonstatic_byte_count = fac.nonstatic_byte_count; int nonstatic_oop_count = fac.nonstatic_oop_count; + bool super_has_nonstatic_fields = + (super_klass() != NULL && super_klass->has_nonstatic_fields()); + bool has_nonstatic_fields = super_has_nonstatic_fields || + ((nonstatic_double_count + nonstatic_word_count + + nonstatic_short_count + nonstatic_byte_count + + nonstatic_oop_count) != 0); + + // Prepare list of oops for oop maps generation. u2* nonstatic_oop_offsets; u2* nonstatic_oop_length; @@ -2694,7 +2711,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, java_lang_Class_fix_post(&next_nonstatic_field_offset); nonstatic_oop_offsets[0] = (u2)first_nonstatic_field_offset; int fake_oop_count = (( next_nonstatic_field_offset - - first_nonstatic_field_offset ) / oopSize); + first_nonstatic_field_offset ) / heapOopSize); nonstatic_oop_length [0] = (u2)fake_oop_count; nonstatic_oop_map_count = 1; nonstatic_oop_count -= fake_oop_count; @@ -2706,7 +2723,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, #ifndef PRODUCT if( PrintCompactFieldsSavings ) { next_nonstatic_double_offset = next_nonstatic_field_offset + - (nonstatic_oop_count * oopSize); + (nonstatic_oop_count * heapOopSize); if ( nonstatic_double_count > 0 ) { next_nonstatic_double_offset = align_size_up(next_nonstatic_double_offset, BytesPerLong); } @@ -2740,7 +2757,15 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, class_name() == vmSymbols::java_lang_ref_SoftReference() || class_name() == vmSymbols::java_lang_StackTraceElement() || class_name() == vmSymbols::java_lang_String() || - class_name() == vmSymbols::java_lang_Throwable()) ) { + class_name() == vmSymbols::java_lang_Throwable() || + class_name() == vmSymbols::java_lang_Boolean() || + class_name() == vmSymbols::java_lang_Character() || + class_name() == vmSymbols::java_lang_Float() || + class_name() == vmSymbols::java_lang_Double() || + class_name() == vmSymbols::java_lang_Byte() || + class_name() == vmSymbols::java_lang_Short() || + class_name() == vmSymbols::java_lang_Integer() || + class_name() == vmSymbols::java_lang_Long())) { allocation_style = 0; // Allocate oops first compact_fields = false; // Don't compact fields } @@ -2749,7 +2774,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, // Fields order: oops, longs/doubles, ints, shorts/chars, bytes next_nonstatic_oop_offset = next_nonstatic_field_offset; next_nonstatic_double_offset = next_nonstatic_oop_offset + - (nonstatic_oop_count * oopSize); + (nonstatic_oop_count * heapOopSize); } else if( allocation_style == 1 ) { // Fields order: longs/doubles, ints, shorts/chars, bytes, oops next_nonstatic_double_offset = next_nonstatic_field_offset; @@ -2766,8 +2791,18 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, int nonstatic_short_space_offset; int nonstatic_byte_space_offset; - if( nonstatic_double_count > 0 ) { - int offset = next_nonstatic_double_offset; + bool compact_into_header = (UseCompressedOops && + allocation_style == 1 && compact_fields && + !super_has_nonstatic_fields); + + if( compact_into_header || nonstatic_double_count > 0 ) { + int offset; + // Pack something in with the header if no super klass has done so. + if (compact_into_header) { + offset = oopDesc::klass_gap_offset_in_bytes(); + } else { + offset = next_nonstatic_double_offset; + } next_nonstatic_double_offset = align_size_up(offset, BytesPerLong); if( compact_fields && offset != next_nonstatic_double_offset ) { // Allocate available fields into the gap before double field. @@ -2795,12 +2830,13 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, } // Allocate oop field in the gap if there are no other fields for that. nonstatic_oop_space_offset = offset; - if( length >= oopSize && nonstatic_oop_count > 0 && + if(!compact_into_header && length >= heapOopSize && + nonstatic_oop_count > 0 && allocation_style != 0 ) { // when oop fields not first nonstatic_oop_count -= 1; nonstatic_oop_space_count = 1; // Only one will fit - length -= oopSize; - offset += oopSize; + length -= heapOopSize; + offset += heapOopSize; } } } @@ -2819,9 +2855,9 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, next_nonstatic_oop_offset = next_nonstatic_byte_offset + nonstatic_byte_count; if( nonstatic_oop_count > 0 ) { notaligned_offset = next_nonstatic_oop_offset; - next_nonstatic_oop_offset = align_size_up(next_nonstatic_oop_offset, oopSize); + next_nonstatic_oop_offset = align_size_up(next_nonstatic_oop_offset, heapOopSize); } - notaligned_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * oopSize); + notaligned_offset = next_nonstatic_oop_offset + (nonstatic_oop_count * heapOopSize); } next_nonstatic_type_offset = align_size_up(notaligned_offset, wordSize ); nonstatic_field_size = nonstatic_field_size + ((next_nonstatic_type_offset @@ -2837,7 +2873,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, switch (atype) { case STATIC_OOP: real_offset = next_static_oop_offset; - next_static_oop_offset += oopSize; + next_static_oop_offset += heapOopSize; break; case STATIC_BYTE: real_offset = next_static_byte_offset; @@ -2859,16 +2895,16 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, case NONSTATIC_OOP: if( nonstatic_oop_space_count > 0 ) { real_offset = nonstatic_oop_space_offset; - nonstatic_oop_space_offset += oopSize; + nonstatic_oop_space_offset += heapOopSize; nonstatic_oop_space_count -= 1; } else { real_offset = next_nonstatic_oop_offset; - next_nonstatic_oop_offset += oopSize; + next_nonstatic_oop_offset += heapOopSize; } // Update oop maps if( nonstatic_oop_map_count > 0 && nonstatic_oop_offsets[nonstatic_oop_map_count - 1] == - (u2)(real_offset - nonstatic_oop_length[nonstatic_oop_map_count - 1] * oopSize) ) { + (u2)(real_offset - nonstatic_oop_length[nonstatic_oop_map_count - 1] * heapOopSize) ) { // Extend current oop map nonstatic_oop_length[nonstatic_oop_map_count - 1] += 1; } else { @@ -2961,6 +2997,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, //this_klass->set_super(super_klass()); this_klass->set_class_loader(class_loader()); this_klass->set_nonstatic_field_size(nonstatic_field_size); + this_klass->set_has_nonstatic_fields(has_nonstatic_fields); this_klass->set_static_oop_field_size(fac.static_oop_count); cp->set_pool_holder(this_klass()); this_klass->set_constants(cp()); @@ -3119,7 +3156,7 @@ int ClassFileParser::compute_oop_map_size(instanceKlassHandle super, int nonstat OopMapBlock* first_map = super->start_of_nonstatic_oop_maps(); OopMapBlock* last_map = first_map + map_size - 1; - int next_offset = last_map->offset() + (last_map->length() * oopSize); + int next_offset = last_map->offset() + (last_map->length() * heapOopSize); if (next_offset == first_nonstatic_oop_offset) { // There is no gap bettwen superklass's last oop field and first // local oop field, merge maps. diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index f2f3cb5869d..713ee547520 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -25,25 +25,29 @@ # include "incls/_precompiled.incl" # include "incls/_javaClasses.cpp.incl" -// Helpful macro for computing field offsets at run time rather than hardcoding them -#define COMPUTE_OFFSET(klass_name_as_C_str, dest_offset, klass_oop, name_symbol, signature_symbol) \ -{ \ - fieldDescriptor fd; \ - instanceKlass* ik = instanceKlass::cast(klass_oop); \ - if (!ik->find_local_field(name_symbol, signature_symbol, &fd)) { \ - fatal("Invalid layout of " klass_name_as_C_str); \ - } \ - dest_offset = fd.offset(); \ +// Helpful routine for computing field offsets at run time rather than hardcoding them +static void +compute_offset(int &dest_offset, + klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol) { + fieldDescriptor fd; + instanceKlass* ik = instanceKlass::cast(klass_oop); + if (!ik->find_local_field(name_symbol, signature_symbol, &fd)) { + ResourceMark rm; + tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string()); + fatal("Invalid layout of preloaded class"); + } + dest_offset = fd.offset(); } // Same as above but for "optional" offsets that might not be present in certain JDK versions -#define COMPUTE_OPTIONAL_OFFSET(klass_name_as_C_str, dest_offset, klass_oop, name_symbol, signature_symbol) \ -{ \ - fieldDescriptor fd; \ - instanceKlass* ik = instanceKlass::cast(klass_oop); \ - if (ik->find_local_field(name_symbol, signature_symbol, &fd)) { \ - dest_offset = fd.offset(); \ - } \ +static void +compute_optional_offset(int& dest_offset, + klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol) { + fieldDescriptor fd; + instanceKlass* ik = instanceKlass::cast(klass_oop); + if (ik->find_local_field(name_symbol, signature_symbol, &fd)) { + dest_offset = fd.offset(); + } } Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) { @@ -445,7 +449,7 @@ void java_lang_Class::compute_offsets() { klassOop k = SystemDictionary::class_klass(); // The classRedefinedCount field is only present starting in 1.5, // so don't go fatal. - COMPUTE_OPTIONAL_OFFSET("java.lang.Class", classRedefinedCount_offset, + compute_optional_offset(classRedefinedCount_offset, k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature()); } @@ -499,37 +503,33 @@ void java_lang_Thread::compute_offsets() { assert(_group_offset == 0, "offsets should be initialized only once"); klassOop k = SystemDictionary::thread_klass(); - COMPUTE_OFFSET("java.lang.Thread", _name_offset, k, vmSymbols::name_name(), vmSymbols::char_array_signature()); - COMPUTE_OFFSET("java.lang.Thread", _group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature()); - COMPUTE_OFFSET("java.lang.Thread", _contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), vmSymbols::classloader_signature()); - COMPUTE_OFFSET("java.lang.Thread", _inheritedAccessControlContext_offset, k, vmSymbols::inheritedAccessControlContext_name(), vmSymbols::accesscontrolcontext_signature()); - COMPUTE_OFFSET("java.lang.Thread", _priority_offset, k, vmSymbols::priority_name(), vmSymbols::int_signature()); - COMPUTE_OFFSET("java.lang.Thread", _daemon_offset, k, vmSymbols::daemon_name(), vmSymbols::bool_signature()); - COMPUTE_OFFSET("java.lang.Thread", _eetop_offset, k, vmSymbols::eetop_name(), vmSymbols::long_signature()); - COMPUTE_OFFSET("java.lang.Thread", _stillborn_offset, k, vmSymbols::stillborn_name(), vmSymbols::bool_signature()); + compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::char_array_signature()); + compute_offset(_group_offset, k, vmSymbols::group_name(), vmSymbols::threadgroup_signature()); + compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), vmSymbols::classloader_signature()); + compute_offset(_inheritedAccessControlContext_offset, k, vmSymbols::inheritedAccessControlContext_name(), vmSymbols::accesscontrolcontext_signature()); + compute_offset(_priority_offset, k, vmSymbols::priority_name(), vmSymbols::int_signature()); + compute_offset(_daemon_offset, k, vmSymbols::daemon_name(), vmSymbols::bool_signature()); + compute_offset(_eetop_offset, k, vmSymbols::eetop_name(), vmSymbols::long_signature()); + compute_offset(_stillborn_offset, k, vmSymbols::stillborn_name(), vmSymbols::bool_signature()); // The stackSize field is only present starting in 1.4, so don't go fatal. - COMPUTE_OPTIONAL_OFFSET("java.lang.Thread", _stackSize_offset, k, vmSymbols::stackSize_name(), vmSymbols::long_signature()); + compute_optional_offset(_stackSize_offset, k, vmSymbols::stackSize_name(), vmSymbols::long_signature()); // The tid and thread_status fields are only present starting in 1.5, so don't go fatal. - COMPUTE_OPTIONAL_OFFSET("java.lang.Thread", _tid_offset, k, vmSymbols::thread_id_name(), vmSymbols::long_signature()); - COMPUTE_OPTIONAL_OFFSET("java.lang.Thread", _thread_status_offset, k, vmSymbols::thread_status_name(), vmSymbols::int_signature()); + compute_optional_offset(_tid_offset, k, vmSymbols::thread_id_name(), vmSymbols::long_signature()); + compute_optional_offset(_thread_status_offset, k, vmSymbols::thread_status_name(), vmSymbols::int_signature()); // The parkBlocker field is only present starting in 1.6, so don't go fatal. - COMPUTE_OPTIONAL_OFFSET("java.lang.Thread", _park_blocker_offset, k, vmSymbols::park_blocker_name(), vmSymbols::object_signature()); - COMPUTE_OPTIONAL_OFFSET("java.lang.Thread", _park_event_offset, k, vmSymbols::park_event_name(), + compute_optional_offset(_park_blocker_offset, k, vmSymbols::park_blocker_name(), vmSymbols::object_signature()); + compute_optional_offset(_park_event_offset, k, vmSymbols::park_event_name(), vmSymbols::long_signature()); } JavaThread* java_lang_Thread::thread(oop java_thread) { - return (JavaThread*) java_thread->obj_field(_eetop_offset); + return (JavaThread*)java_thread->address_field(_eetop_offset); } void java_lang_Thread::set_thread(oop java_thread, JavaThread* thread) { - // We are storing a JavaThread* (malloc'ed data) into a long field in the thread - // object. The store has to be 64-bit wide so we use a pointer store, but we - // cannot call oopDesc::obj_field_put since it includes a write barrier! - oop* addr = java_thread->obj_field_addr(_eetop_offset); - *addr = (oop) thread; + java_thread->address_field_put(_eetop_offset, (address)thread); } @@ -763,16 +763,16 @@ void java_lang_ThreadGroup::compute_offsets() { klassOop k = SystemDictionary::threadGroup_klass(); - COMPUTE_OFFSET("java.lang.ThreadGroup", _parent_offset, k, vmSymbols::parent_name(), vmSymbols::threadgroup_signature()); - COMPUTE_OFFSET("java.lang.ThreadGroup", _name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); - COMPUTE_OFFSET("java.lang.ThreadGroup", _threads_offset, k, vmSymbols::threads_name(), vmSymbols::thread_array_signature()); - COMPUTE_OFFSET("java.lang.ThreadGroup", _groups_offset, k, vmSymbols::groups_name(), vmSymbols::threadgroup_array_signature()); - COMPUTE_OFFSET("java.lang.ThreadGroup", _maxPriority_offset, k, vmSymbols::maxPriority_name(), vmSymbols::int_signature()); - COMPUTE_OFFSET("java.lang.ThreadGroup", _destroyed_offset, k, vmSymbols::destroyed_name(), vmSymbols::bool_signature()); - COMPUTE_OFFSET("java.lang.ThreadGroup", _daemon_offset, k, vmSymbols::daemon_name(), vmSymbols::bool_signature()); - COMPUTE_OFFSET("java.lang.ThreadGroup", _vmAllowSuspension_offset, k, vmSymbols::vmAllowSuspension_name(), vmSymbols::bool_signature()); - COMPUTE_OFFSET("java.lang.ThreadGroup", _nthreads_offset, k, vmSymbols::nthreads_name(), vmSymbols::int_signature()); - COMPUTE_OFFSET("java.lang.ThreadGroup", _ngroups_offset, k, vmSymbols::ngroups_name(), vmSymbols::int_signature()); + compute_offset(_parent_offset, k, vmSymbols::parent_name(), vmSymbols::threadgroup_signature()); + compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); + compute_offset(_threads_offset, k, vmSymbols::threads_name(), vmSymbols::thread_array_signature()); + compute_offset(_groups_offset, k, vmSymbols::groups_name(), vmSymbols::threadgroup_array_signature()); + compute_offset(_maxPriority_offset, k, vmSymbols::maxPriority_name(), vmSymbols::int_signature()); + compute_offset(_destroyed_offset, k, vmSymbols::destroyed_name(), vmSymbols::bool_signature()); + compute_offset(_daemon_offset, k, vmSymbols::daemon_name(), vmSymbols::bool_signature()); + compute_offset(_vmAllowSuspension_offset, k, vmSymbols::vmAllowSuspension_name(), vmSymbols::bool_signature()); + compute_offset(_nthreads_offset, k, vmSymbols::nthreads_name(), vmSymbols::int_signature()); + compute_offset(_ngroups_offset, k, vmSymbols::ngroups_name(), vmSymbols::int_signature()); } oop java_lang_Throwable::backtrace(oop throwable) { @@ -1015,7 +1015,6 @@ class BacktraceBuilder: public StackObj { typeArrayOop _bcis; int _index; bool _dirty; - bool _done; No_Safepoint_Verifier _nsv; public: @@ -1029,20 +1028,18 @@ class BacktraceBuilder: public StackObj { }; // constructor for new backtrace - BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL) { + BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _dirty(false) { expand(CHECK); _backtrace = _head; _index = 0; - _dirty = false; - _done = false; } void flush() { if (_dirty && _methods != NULL) { BarrierSet* bs = Universe::heap()->barrier_set(); assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt"); - bs->write_ref_array(MemRegion((HeapWord*)_methods->obj_at_addr(0), - _methods->length() * HeapWordsPerOop)); + bs->write_ref_array(MemRegion((HeapWord*)_methods->base(), + _methods->array_size())); _dirty = false; } } @@ -1086,8 +1083,9 @@ class BacktraceBuilder: public StackObj { method = mhandle(); } - // _methods->obj_at_put(_index, method); - *_methods->obj_at_addr(_index) = method; + _methods->obj_at_put(_index, method); + // bad for UseCompressedOops + // *_methods->obj_at_addr(_index) = method; _bcis->ushort_at_put(_index, bci); _index++; _dirty = true; @@ -1367,6 +1365,7 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { // Allocate java.lang.StackTraceElement instance klassOop k = SystemDictionary::stackTraceElement_klass(); + assert(k != NULL, "must be loaded in 1.4+"); instanceKlassHandle ik (THREAD, k); if (ik->should_be_initialized()) { ik->initialize(CHECK_0); @@ -1404,7 +1403,7 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { void java_lang_reflect_AccessibleObject::compute_offsets() { klassOop k = SystemDictionary::reflect_accessible_object_klass(); - COMPUTE_OFFSET("java.lang.reflect.AccessibleObject", override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature()); + compute_offset(override_offset, k, vmSymbols::override_name(), vmSymbols::bool_signature()); } jboolean java_lang_reflect_AccessibleObject::override(oop reflect) { @@ -1419,22 +1418,22 @@ void java_lang_reflect_AccessibleObject::set_override(oop reflect, jboolean valu void java_lang_reflect_Method::compute_offsets() { klassOop k = SystemDictionary::reflect_method_klass(); - COMPUTE_OFFSET("java.lang.reflect.Method", clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); - COMPUTE_OFFSET("java.lang.reflect.Method", name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); - COMPUTE_OFFSET("java.lang.reflect.Method", returnType_offset, k, vmSymbols::returnType_name(), vmSymbols::class_signature()); - COMPUTE_OFFSET("java.lang.reflect.Method", parameterTypes_offset, k, vmSymbols::parameterTypes_name(), vmSymbols::class_array_signature()); - COMPUTE_OFFSET("java.lang.reflect.Method", exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), vmSymbols::class_array_signature()); - COMPUTE_OFFSET("java.lang.reflect.Method", slot_offset, k, vmSymbols::slot_name(), vmSymbols::int_signature()); - COMPUTE_OFFSET("java.lang.reflect.Method", modifiers_offset, k, vmSymbols::modifiers_name(), vmSymbols::int_signature()); + compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); + compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); + compute_offset(returnType_offset, k, vmSymbols::returnType_name(), vmSymbols::class_signature()); + compute_offset(parameterTypes_offset, k, vmSymbols::parameterTypes_name(), vmSymbols::class_array_signature()); + compute_offset(exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), vmSymbols::class_array_signature()); + compute_offset(slot_offset, k, vmSymbols::slot_name(), vmSymbols::int_signature()); + compute_offset(modifiers_offset, k, vmSymbols::modifiers_name(), vmSymbols::int_signature()); // The generic signature and annotations fields are only present in 1.5 signature_offset = -1; annotations_offset = -1; parameter_annotations_offset = -1; annotation_default_offset = -1; - COMPUTE_OPTIONAL_OFFSET("java.lang.reflect.Method", signature_offset, k, vmSymbols::signature_name(), vmSymbols::string_signature()); - COMPUTE_OPTIONAL_OFFSET("java.lang.reflect.Method", annotations_offset, k, vmSymbols::annotations_name(), vmSymbols::byte_array_signature()); - COMPUTE_OPTIONAL_OFFSET("java.lang.reflect.Method", parameter_annotations_offset, k, vmSymbols::parameter_annotations_name(), vmSymbols::byte_array_signature()); - COMPUTE_OPTIONAL_OFFSET("java.lang.reflect.Method", annotation_default_offset, k, vmSymbols::annotation_default_name(), vmSymbols::byte_array_signature()); + compute_optional_offset(signature_offset, k, vmSymbols::signature_name(), vmSymbols::string_signature()); + compute_optional_offset(annotations_offset, k, vmSymbols::annotations_name(), vmSymbols::byte_array_signature()); + compute_optional_offset(parameter_annotations_offset, k, vmSymbols::parameter_annotations_name(), vmSymbols::byte_array_signature()); + compute_optional_offset(annotation_default_offset, k, vmSymbols::annotation_default_name(), vmSymbols::byte_array_signature()); } Handle java_lang_reflect_Method::create(TRAPS) { @@ -1582,18 +1581,18 @@ void java_lang_reflect_Method::set_annotation_default(oop method, oop value) { void java_lang_reflect_Constructor::compute_offsets() { klassOop k = SystemDictionary::reflect_constructor_klass(); - COMPUTE_OFFSET("java.lang.reflect.Constructor", clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); - COMPUTE_OFFSET("java.lang.reflect.Constructor", parameterTypes_offset, k, vmSymbols::parameterTypes_name(), vmSymbols::class_array_signature()); - COMPUTE_OFFSET("java.lang.reflect.Constructor", exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), vmSymbols::class_array_signature()); - COMPUTE_OFFSET("java.lang.reflect.Constructor", slot_offset, k, vmSymbols::slot_name(), vmSymbols::int_signature()); - COMPUTE_OFFSET("java.lang.reflect.Constructor", modifiers_offset, k, vmSymbols::modifiers_name(), vmSymbols::int_signature()); + compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); + compute_offset(parameterTypes_offset, k, vmSymbols::parameterTypes_name(), vmSymbols::class_array_signature()); + compute_offset(exceptionTypes_offset, k, vmSymbols::exceptionTypes_name(), vmSymbols::class_array_signature()); + compute_offset(slot_offset, k, vmSymbols::slot_name(), vmSymbols::int_signature()); + compute_offset(modifiers_offset, k, vmSymbols::modifiers_name(), vmSymbols::int_signature()); // The generic signature and annotations fields are only present in 1.5 signature_offset = -1; annotations_offset = -1; parameter_annotations_offset = -1; - COMPUTE_OPTIONAL_OFFSET("java.lang.reflect.Constructor", signature_offset, k, vmSymbols::signature_name(), vmSymbols::string_signature()); - COMPUTE_OPTIONAL_OFFSET("java.lang.reflect.Constructor", annotations_offset, k, vmSymbols::annotations_name(), vmSymbols::byte_array_signature()); - COMPUTE_OPTIONAL_OFFSET("java.lang.reflect.Constructor", parameter_annotations_offset, k, vmSymbols::parameter_annotations_name(), vmSymbols::byte_array_signature()); + compute_optional_offset(signature_offset, k, vmSymbols::signature_name(), vmSymbols::string_signature()); + compute_optional_offset(annotations_offset, k, vmSymbols::annotations_name(), vmSymbols::byte_array_signature()); + compute_optional_offset(parameter_annotations_offset, k, vmSymbols::parameter_annotations_name(), vmSymbols::byte_array_signature()); } Handle java_lang_reflect_Constructor::create(TRAPS) { @@ -1706,16 +1705,16 @@ void java_lang_reflect_Constructor::set_parameter_annotations(oop method, oop va void java_lang_reflect_Field::compute_offsets() { klassOop k = SystemDictionary::reflect_field_klass(); - COMPUTE_OFFSET("java.lang.reflect.Field", clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); - COMPUTE_OFFSET("java.lang.reflect.Field", name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); - COMPUTE_OFFSET("java.lang.reflect.Field", type_offset, k, vmSymbols::type_name(), vmSymbols::class_signature()); - COMPUTE_OFFSET("java.lang.reflect.Field", slot_offset, k, vmSymbols::slot_name(), vmSymbols::int_signature()); - COMPUTE_OFFSET("java.lang.reflect.Field", modifiers_offset, k, vmSymbols::modifiers_name(), vmSymbols::int_signature()); + compute_offset(clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); + compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); + compute_offset(type_offset, k, vmSymbols::type_name(), vmSymbols::class_signature()); + compute_offset(slot_offset, k, vmSymbols::slot_name(), vmSymbols::int_signature()); + compute_offset(modifiers_offset, k, vmSymbols::modifiers_name(), vmSymbols::int_signature()); // The generic signature and annotations fields are only present in 1.5 signature_offset = -1; annotations_offset = -1; - COMPUTE_OPTIONAL_OFFSET("java.lang.reflect.Field", signature_offset, k, vmSymbols::signature_name(), vmSymbols::string_signature()); - COMPUTE_OPTIONAL_OFFSET("java.lang.reflect.Field", annotations_offset, k, vmSymbols::annotations_name(), vmSymbols::byte_array_signature()); + compute_optional_offset(signature_offset, k, vmSymbols::signature_name(), vmSymbols::string_signature()); + compute_optional_offset(annotations_offset, k, vmSymbols::annotations_name(), vmSymbols::byte_array_signature()); } Handle java_lang_reflect_Field::create(TRAPS) { @@ -1815,7 +1814,7 @@ void sun_reflect_ConstantPool::compute_offsets() { klassOop k = SystemDictionary::reflect_constant_pool_klass(); // This null test can be removed post beta if (k != NULL) { - COMPUTE_OFFSET("sun.reflect.ConstantPool", _cp_oop_offset, k, vmSymbols::constantPoolOop_name(), vmSymbols::object_signature()); + compute_offset(_cp_oop_offset, k, vmSymbols::constantPoolOop_name(), vmSymbols::object_signature()); } } @@ -1845,51 +1844,46 @@ void sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets() { klassOop k = SystemDictionary::reflect_unsafe_static_field_accessor_impl_klass(); // This null test can be removed post beta if (k != NULL) { - COMPUTE_OFFSET("sun.reflect.UnsafeStaticFieldAccessorImpl", _base_offset, k, + compute_offset(_base_offset, k, vmSymbols::base_name(), vmSymbols::object_signature()); } } -oop java_lang_boxing_object::initialize_and_allocate(klassOop k, TRAPS) { - instanceKlassHandle h (THREAD, k); - if (!h->is_initialized()) h->initialize(CHECK_0); - return h->allocate_instance(THREAD); +oop java_lang_boxing_object::initialize_and_allocate(BasicType type, TRAPS) { + klassOop k = SystemDictionary::box_klass(type); + if (k == NULL) return NULL; + instanceKlassHandle h (THREAD, k); + if (!h->is_initialized()) h->initialize(CHECK_0); + return h->allocate_instance(THREAD); } oop java_lang_boxing_object::create(BasicType type, jvalue* value, TRAPS) { - oop box; + oop box = initialize_and_allocate(type, CHECK_0); + if (box == NULL) return NULL; switch (type) { case T_BOOLEAN: - box = initialize_and_allocate(SystemDictionary::boolean_klass(), CHECK_0); box->bool_field_put(value_offset, value->z); break; case T_CHAR: - box = initialize_and_allocate(SystemDictionary::char_klass(), CHECK_0); box->char_field_put(value_offset, value->c); break; case T_FLOAT: - box = initialize_and_allocate(SystemDictionary::float_klass(), CHECK_0); box->float_field_put(value_offset, value->f); break; case T_DOUBLE: - box = initialize_and_allocate(SystemDictionary::double_klass(), CHECK_0); box->double_field_put(value_offset, value->d); break; case T_BYTE: - box = initialize_and_allocate(SystemDictionary::byte_klass(), CHECK_0); box->byte_field_put(value_offset, value->b); break; case T_SHORT: - box = initialize_and_allocate(SystemDictionary::short_klass(), CHECK_0); box->short_field_put(value_offset, value->s); break; case T_INT: - box = initialize_and_allocate(SystemDictionary::int_klass(), CHECK_0); box->int_field_put(value_offset, value->i); break; case T_LONG: - box = initialize_and_allocate(SystemDictionary::long_klass(), CHECK_0); box->long_field_put(value_offset, value->j); break; default: @@ -1899,116 +1893,108 @@ oop java_lang_boxing_object::create(BasicType type, jvalue* value, TRAPS) { } +BasicType java_lang_boxing_object::basic_type(oop box) { + if (box == NULL) return T_ILLEGAL; + BasicType type = SystemDictionary::box_klass_type(box->klass()); + if (type == T_OBJECT) // 'unknown' value returned by SD::bkt + return T_ILLEGAL; + return type; +} + + BasicType java_lang_boxing_object::get_value(oop box, jvalue* value) { - klassOop k = box->klass(); - if (k == SystemDictionary::boolean_klass()) { + BasicType type = SystemDictionary::box_klass_type(box->klass()); + switch (type) { + case T_BOOLEAN: value->z = box->bool_field(value_offset); - return T_BOOLEAN; - } - if (k == SystemDictionary::char_klass()) { + break; + case T_CHAR: value->c = box->char_field(value_offset); - return T_CHAR; - } - if (k == SystemDictionary::float_klass()) { + break; + case T_FLOAT: value->f = box->float_field(value_offset); - return T_FLOAT; - } - if (k == SystemDictionary::double_klass()) { + break; + case T_DOUBLE: value->d = box->double_field(value_offset); - return T_DOUBLE; - } - if (k == SystemDictionary::byte_klass()) { + break; + case T_BYTE: value->b = box->byte_field(value_offset); - return T_BYTE; - } - if (k == SystemDictionary::short_klass()) { + break; + case T_SHORT: value->s = box->short_field(value_offset); - return T_SHORT; - } - if (k == SystemDictionary::int_klass()) { + break; + case T_INT: value->i = box->int_field(value_offset); - return T_INT; - } - if (k == SystemDictionary::long_klass()) { + break; + case T_LONG: value->j = box->long_field(value_offset); - return T_LONG; - } - return T_ILLEGAL; + break; + default: + return T_ILLEGAL; + } // end switch + return type; } BasicType java_lang_boxing_object::set_value(oop box, jvalue* value) { - klassOop k = box->klass(); - if (k == SystemDictionary::boolean_klass()) { + BasicType type = SystemDictionary::box_klass_type(box->klass()); + switch (type) { + case T_BOOLEAN: box->bool_field_put(value_offset, value->z); - return T_BOOLEAN; - } - if (k == SystemDictionary::char_klass()) { + break; + case T_CHAR: box->char_field_put(value_offset, value->c); - return T_CHAR; - } - if (k == SystemDictionary::float_klass()) { + break; + case T_FLOAT: box->float_field_put(value_offset, value->f); - return T_FLOAT; - } - if (k == SystemDictionary::double_klass()) { + break; + case T_DOUBLE: box->double_field_put(value_offset, value->d); - return T_DOUBLE; - } - if (k == SystemDictionary::byte_klass()) { + break; + case T_BYTE: box->byte_field_put(value_offset, value->b); - return T_BYTE; - } - if (k == SystemDictionary::short_klass()) { + break; + case T_SHORT: box->short_field_put(value_offset, value->s); - return T_SHORT; - } - if (k == SystemDictionary::int_klass()) { + break; + case T_INT: box->int_field_put(value_offset, value->i); - return T_INT; - } - if (k == SystemDictionary::long_klass()) { + break; + case T_LONG: box->long_field_put(value_offset, value->j); - return T_LONG; - } - return T_ILLEGAL; + break; + default: + return T_ILLEGAL; + } // end switch + return type; } // Support for java_lang_ref_Reference - -void java_lang_ref_Reference::set_referent(oop ref, oop value) { - ref->obj_field_put(referent_offset, value); -} - -oop* java_lang_ref_Reference::referent_addr(oop ref) { - return ref->obj_field_addr(referent_offset); -} - -void java_lang_ref_Reference::set_next(oop ref, oop value) { - ref->obj_field_put(next_offset, value); -} - -oop* java_lang_ref_Reference::next_addr(oop ref) { - return ref->obj_field_addr(next_offset); -} - -void java_lang_ref_Reference::set_discovered(oop ref, oop value) { - ref->obj_field_put(discovered_offset, value); -} - -oop* java_lang_ref_Reference::discovered_addr(oop ref) { - return ref->obj_field_addr(discovered_offset); -} - -oop* java_lang_ref_Reference::pending_list_lock_addr() { +oop java_lang_ref_Reference::pending_list_lock() { instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass()); - return (oop*)(((char *)ik->start_of_static_fields()) + static_lock_offset); + char *addr = (((char *)ik->start_of_static_fields()) + static_lock_offset); + if (UseCompressedOops) { + return oopDesc::load_decode_heap_oop((narrowOop *)addr); + } else { + return oopDesc::load_decode_heap_oop((oop*)addr); + } } -oop* java_lang_ref_Reference::pending_list_addr() { +HeapWord *java_lang_ref_Reference::pending_list_addr() { instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass()); - return (oop *)(((char *)ik->start_of_static_fields()) + static_pending_offset); + char *addr = (((char *)ik->start_of_static_fields()) + static_pending_offset); + // XXX This might not be HeapWord aligned, almost rather be char *. + return (HeapWord*)addr; +} + +oop java_lang_ref_Reference::pending_list() { + char *addr = (char *)pending_list_addr(); + if (UseCompressedOops) { + return oopDesc::load_decode_heap_oop((narrowOop *)addr); + } else { + return oopDesc::load_decode_heap_oop((oop*)addr); + } } @@ -2257,7 +2243,8 @@ int java_nio_Buffer::limit_offset() { void java_nio_Buffer::compute_offsets() { klassOop k = SystemDictionary::java_nio_Buffer_klass(); - COMPUTE_OFFSET("java.nio.Buffer", _limit_offset, k, vmSymbols::limit_name(), vmSymbols::int_signature()); + assert(k != NULL, "must be loaded in 1.4+"); + compute_offset(_limit_offset, k, vmSymbols::limit_name(), vmSymbols::int_signature()); } // Support for intrinsification of sun.misc.AtomicLongCSImpl.attemptUpdate @@ -2271,7 +2258,7 @@ void sun_misc_AtomicLongCSImpl::compute_offsets() { klassOop k = SystemDictionary::sun_misc_AtomicLongCSImpl_klass(); // If this class is not present, its value field offset won't be referenced. if (k != NULL) { - COMPUTE_OFFSET("sun.misc.AtomicLongCSImpl", _value_offset, k, vmSymbols::value_name(), vmSymbols::long_signature()); + compute_offset(_value_offset, k, vmSymbols::value_name(), vmSymbols::long_signature()); } } @@ -2281,7 +2268,7 @@ void java_util_concurrent_locks_AbstractOwnableSynchronizer::initialize(TRAPS) { assert(JDK_Version::is_gte_jdk16x_version(), "Must be JDK 1.6 or later"); SystemDictionary::load_abstract_ownable_synchronizer_klass(CHECK); klassOop k = SystemDictionary::abstract_ownable_synchronizer_klass(); - COMPUTE_OFFSET("java.util.concurrent.locks.AbstractOwnableSynchronizer", _owner_offset, k, + compute_offset(_owner_offset, k, vmSymbols::exclusive_owner_thread_name(), vmSymbols::thread_signature()); } @@ -2294,8 +2281,11 @@ oop java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj( // Invoked before SystemDictionary::initialize, so pre-loaded classes // are not available to determine the offset_of_static_fields. void JavaClasses::compute_hard_coded_offsets() { - const int x = wordSize; - const int header = instanceOopDesc::header_size_in_bytes(); + const int x = heapOopSize; + // Objects don't get allocated in the gap in the header with compressed oops + // for these special classes because hard coded offsets can't be conditional + // so base_offset_in_bytes() is wrong here, allocate after the header. + const int header = sizeof(instanceOopDesc); // Do the String Class java_lang_String::value_offset = java_lang_String::hc_value_offset * x + header; @@ -2441,6 +2431,36 @@ bool JavaClasses::check_static_offset(const char *klass_name, int hardcoded_offs } +bool JavaClasses::check_constant(const char *klass_name, int hardcoded_constant, const char *field_name, const char* field_sig) { + EXCEPTION_MARK; + fieldDescriptor fd; + symbolHandle klass_sym = oopFactory::new_symbol_handle(klass_name, CATCH); + klassOop k = SystemDictionary::resolve_or_fail(klass_sym, true, CATCH); + instanceKlassHandle h_klass (THREAD, k); + symbolHandle f_name = oopFactory::new_symbol_handle(field_name, CATCH); + symbolHandle f_sig = oopFactory::new_symbol_handle(field_sig, CATCH); + if (!h_klass->find_local_field(f_name(), f_sig(), &fd)) { + tty->print_cr("Static field %s.%s not found", klass_name, field_name); + return false; + } + if (!fd.is_static() || !fd.has_initial_value()) { + tty->print_cr("Static field %s.%s appears to be non-constant", klass_name, field_name); + return false; + } + if (!fd.initial_value_tag().is_int()) { + tty->print_cr("Static field %s.%s is not an int", klass_name, field_name); + return false; + } + jint field_value = fd.int_initial_value(); + if (field_value == hardcoded_constant) { + return true; + } else { + tty->print_cr("Constant value of static field %s.%s is hardcoded as %d but should really be %d.", klass_name, field_name, hardcoded_constant, field_value); + return false; + } +} + + // Check the hard-coded field offsets of all the classes in this file void JavaClasses::check_offsets() { @@ -2452,6 +2472,9 @@ void JavaClasses::check_offsets() { #define CHECK_STATIC_OFFSET(klass_name, cpp_klass_name, field_name, field_sig) \ valid &= check_static_offset(klass_name, cpp_klass_name :: static_ ## field_name ## _offset, #field_name, field_sig) +#define CHECK_CONSTANT(klass_name, cpp_klass_name, field_name, field_sig) \ + valid &= check_constant(klass_name, cpp_klass_name :: field_name, #field_name, field_sig) + // java.lang.String CHECK_OFFSET("java/lang/String", java_lang_String, value, "[C"); diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 8ac7cf883fd..0331be3e12b 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -45,9 +45,9 @@ class java_lang_String : AllStatic { private: enum { hc_value_offset = 0, - hc_offset_offset = 1, - hc_count_offset = 2, - hc_hash_offset = 3 + hc_offset_offset = 1 + //hc_count_offset = 2 -- not a word-scaled offset + //hc_hash_offset = 3 -- not a word-scaled offset }; static int value_offset; @@ -149,6 +149,9 @@ class java_lang_Class : AllStatic { // Conversion static klassOop as_klassOop(oop java_class); // Testing + static bool is_instance(oop obj) { + return obj != NULL && obj->klass() == SystemDictionary::class_klass(); + } static bool is_primitive(oop java_class); static BasicType primitive_type(oop java_class); static oop primitive_mirror(BasicType t); @@ -651,13 +654,16 @@ class java_lang_boxing_object: AllStatic { }; static int value_offset; - static oop initialize_and_allocate(klassOop klass, TRAPS); + static oop initialize_and_allocate(BasicType type, TRAPS); public: // Allocation. Returns a boxed value, or NULL for invalid type. static oop create(BasicType type, jvalue* value, TRAPS); // Accessors. Returns the basic type being boxed, or T_ILLEGAL for invalid oop. static BasicType get_value(oop box, jvalue* value); static BasicType set_value(oop box, jvalue* value); + static BasicType basic_type(oop box); + static bool is_instance(oop box) { return basic_type(box) != T_ILLEGAL; } + static bool is_instance(oop box, BasicType type) { return basic_type(box) == type; } static int value_offset_in_bytes() { return value_offset; } @@ -691,24 +697,47 @@ class java_lang_ref_Reference: AllStatic { static int number_of_fake_oop_fields; // Accessors - static oop referent(oop ref) { return *referent_addr(ref); } - static void set_referent(oop ref, oop value); - static oop* referent_addr(oop ref); - - static oop next(oop ref) { return *next_addr(ref); } - static void set_next(oop ref, oop value); - static oop* next_addr(oop ref); - - static oop discovered(oop ref) { return *discovered_addr(ref); } - static void set_discovered(oop ref, oop value); - static oop* discovered_addr(oop ref); - + static oop referent(oop ref) { + return ref->obj_field(referent_offset); + } + static void set_referent(oop ref, oop value) { + ref->obj_field_put(referent_offset, value); + } + static void set_referent_raw(oop ref, oop value) { + ref->obj_field_raw_put(referent_offset, value); + } + static HeapWord* referent_addr(oop ref) { + return ref->obj_field_addr(referent_offset); + } + static oop next(oop ref) { + return ref->obj_field(next_offset); + } + static void set_next(oop ref, oop value) { + ref->obj_field_put(next_offset, value); + } + static void set_next_raw(oop ref, oop value) { + ref->obj_field_raw_put(next_offset, value); + } + static HeapWord* next_addr(oop ref) { + return ref->obj_field_addr(next_offset); + } + static oop discovered(oop ref) { + return ref->obj_field(discovered_offset); + } + static void set_discovered(oop ref, oop value) { + ref->obj_field_put(discovered_offset, value); + } + static void set_discovered_raw(oop ref, oop value) { + ref->obj_field_raw_put(discovered_offset, value); + } + static HeapWord* discovered_addr(oop ref) { + return ref->obj_field_addr(discovered_offset); + } // Accessors for statics - static oop pending_list_lock() { return *pending_list_lock_addr(); } - static oop pending_list() { return *pending_list_addr(); } + static oop pending_list_lock(); + static oop pending_list(); - static oop* pending_list_lock_addr(); - static oop* pending_list_addr(); + static HeapWord* pending_list_addr(); }; @@ -898,6 +927,7 @@ class JavaClasses : AllStatic { private: static bool check_offset(const char *klass_name, int offset, const char *field_name, const char* field_sig) PRODUCT_RETURN0; static bool check_static_offset(const char *klass_name, int hardcoded_offset, const char *field_name, const char* field_sig) PRODUCT_RETURN0; + static bool check_constant(const char *klass_name, int constant, const char *field_name, const char* field_sig) PRODUCT_RETURN0; public: static void compute_hard_coded_offsets(); static void compute_offsets(); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index a714ef583a6..8d06a8abe90 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -37,71 +37,9 @@ int SystemDictionary::_number_of_modifications = 0; oop SystemDictionary::_system_loader_lock_obj = NULL; -klassOop SystemDictionary::_object_klass = NULL; -klassOop SystemDictionary::_string_klass = NULL; -klassOop SystemDictionary::_class_klass = NULL; -klassOop SystemDictionary::_cloneable_klass = NULL; -klassOop SystemDictionary::_classloader_klass = NULL; -klassOop SystemDictionary::_serializable_klass = NULL; -klassOop SystemDictionary::_system_klass = NULL; +klassOop SystemDictionary::_well_known_klasses[SystemDictionary::WKID_LIMIT] + = { NULL /*, NULL...*/ }; -klassOop SystemDictionary::_throwable_klass = NULL; -klassOop SystemDictionary::_error_klass = NULL; -klassOop SystemDictionary::_threaddeath_klass = NULL; -klassOop SystemDictionary::_exception_klass = NULL; -klassOop SystemDictionary::_runtime_exception_klass = NULL; -klassOop SystemDictionary::_classNotFoundException_klass = NULL; -klassOop SystemDictionary::_noClassDefFoundError_klass = NULL; -klassOop SystemDictionary::_linkageError_klass = NULL; -klassOop SystemDictionary::_classCastException_klass = NULL; -klassOop SystemDictionary::_arrayStoreException_klass = NULL; -klassOop SystemDictionary::_virtualMachineError_klass = NULL; -klassOop SystemDictionary::_outOfMemoryError_klass = NULL; -klassOop SystemDictionary::_StackOverflowError_klass = NULL; -klassOop SystemDictionary::_illegalMonitorStateException_klass = NULL; -klassOop SystemDictionary::_protectionDomain_klass = NULL; -klassOop SystemDictionary::_AccessControlContext_klass = NULL; - -klassOop SystemDictionary::_reference_klass = NULL; -klassOop SystemDictionary::_soft_reference_klass = NULL; -klassOop SystemDictionary::_weak_reference_klass = NULL; -klassOop SystemDictionary::_final_reference_klass = NULL; -klassOop SystemDictionary::_phantom_reference_klass = NULL; -klassOop SystemDictionary::_finalizer_klass = NULL; - -klassOop SystemDictionary::_thread_klass = NULL; -klassOop SystemDictionary::_threadGroup_klass = NULL; -klassOop SystemDictionary::_properties_klass = NULL; -klassOop SystemDictionary::_reflect_accessible_object_klass = NULL; -klassOop SystemDictionary::_reflect_field_klass = NULL; -klassOop SystemDictionary::_reflect_method_klass = NULL; -klassOop SystemDictionary::_reflect_constructor_klass = NULL; -klassOop SystemDictionary::_reflect_magic_klass = NULL; -klassOop SystemDictionary::_reflect_method_accessor_klass = NULL; -klassOop SystemDictionary::_reflect_constructor_accessor_klass = NULL; -klassOop SystemDictionary::_reflect_delegating_classloader_klass = NULL; -klassOop SystemDictionary::_reflect_constant_pool_klass = NULL; -klassOop SystemDictionary::_reflect_unsafe_static_field_accessor_impl_klass = NULL; - -klassOop SystemDictionary::_vector_klass = NULL; -klassOop SystemDictionary::_hashtable_klass = NULL; -klassOop SystemDictionary::_stringBuffer_klass = NULL; - -klassOop SystemDictionary::_stackTraceElement_klass = NULL; - -klassOop SystemDictionary::_java_nio_Buffer_klass = NULL; - -klassOop SystemDictionary::_sun_misc_AtomicLongCSImpl_klass = NULL; -klassOop SystemDictionary::_sun_jkernel_DownloadManager_klass = NULL; - -klassOop SystemDictionary::_boolean_klass = NULL; -klassOop SystemDictionary::_char_klass = NULL; -klassOop SystemDictionary::_float_klass = NULL; -klassOop SystemDictionary::_double_klass = NULL; -klassOop SystemDictionary::_byte_klass = NULL; -klassOop SystemDictionary::_short_klass = NULL; -klassOop SystemDictionary::_int_klass = NULL; -klassOop SystemDictionary::_long_klass = NULL; klassOop SystemDictionary::_box_klasses[T_VOID+1] = { NULL /*, NULL...*/ }; oop SystemDictionary::_java_system_loader = NULL; @@ -121,10 +59,10 @@ oop SystemDictionary::java_system_loader() { } void SystemDictionary::compute_java_system_loader(TRAPS) { - KlassHandle system_klass(THREAD, _classloader_klass); + KlassHandle system_klass(THREAD, WK_KLASS(classloader_klass)); JavaValue result(T_OBJECT); JavaCalls::call_static(&result, - KlassHandle(THREAD, _classloader_klass), + KlassHandle(THREAD, WK_KLASS(classloader_klass)), vmSymbolHandles::getSystemClassLoader_name(), vmSymbolHandles::void_classloader_signature(), CHECK); @@ -292,6 +230,15 @@ klassOop SystemDictionary::resolve_super_or_fail(symbolHandle child_name, bool is_superclass, TRAPS) { + // Try to get one of the well-known klasses. + // They are trusted, and do not participate in circularities. + if (LinkWellKnownClasses) { + klassOop k = find_well_known_klass(class_name()); + if (k != NULL) { + return k; + } + } + // Double-check, if child class is already loaded, just return super-class,interface // Don't add a placedholder if already loaded, i.e. already in system dictionary // Make sure there's a placeholder for the *child* before resolving. @@ -919,6 +866,15 @@ klassOop SystemDictionary::find_instance_or_array_klass(symbolHandle class_name, TRAPS) { klassOop k = NULL; assert(class_name() != NULL, "class name must be non NULL"); + + // Try to get one of the well-known klasses. + if (LinkWellKnownClasses) { + k = find_well_known_klass(class_name()); + if (k != NULL) { + return k; + } + } + if (FieldType::is_array(class_name())) { // The name refers to an array. Parse the name. jint dimension; @@ -942,6 +898,38 @@ klassOop SystemDictionary::find_instance_or_array_klass(symbolHandle class_name, return k; } +// Quick range check for names of well-known classes: +static symbolOop wk_klass_name_limits[2] = {NULL, NULL}; + +#ifndef PRODUCT +static int find_wkk_calls, find_wkk_probes, find_wkk_wins; +// counts for "hello world": 3983, 1616, 1075 +// => 60% hit after limit guard, 25% total win rate +#endif + +klassOop SystemDictionary::find_well_known_klass(symbolOop class_name) { + // A bounds-check on class_name will quickly get a negative result. + NOT_PRODUCT(find_wkk_calls++); + if (class_name >= wk_klass_name_limits[0] && + class_name <= wk_klass_name_limits[1]) { + NOT_PRODUCT(find_wkk_probes++); + vmSymbols::SID sid = vmSymbols::find_sid(class_name); + if (sid != vmSymbols::NO_SID) { + klassOop k = NULL; + switch (sid) { + #define WK_KLASS_CASE(name, symbol, ignore_option) \ + case vmSymbols::VM_SYMBOL_ENUM_NAME(symbol): \ + k = WK_KLASS(name); break; + WK_KLASSES_DO(WK_KLASS_CASE) + #undef WK_KLASS_CASE + } + NOT_PRODUCT(if (k != NULL) find_wkk_wins++); + return k; + } + } + return NULL; +} + // Note: this method is much like resolve_from_stream, but // updates no supplemental data structures. // TODO consolidate the two methods with a helper routine? @@ -1684,71 +1672,13 @@ void SystemDictionary::oops_do(OopClosure* f) { void SystemDictionary::preloaded_oops_do(OopClosure* f) { - f->do_oop((oop*) &_string_klass); - f->do_oop((oop*) &_object_klass); - f->do_oop((oop*) &_class_klass); - f->do_oop((oop*) &_cloneable_klass); - f->do_oop((oop*) &_classloader_klass); - f->do_oop((oop*) &_serializable_klass); - f->do_oop((oop*) &_system_klass); + f->do_oop((oop*) &wk_klass_name_limits[0]); + f->do_oop((oop*) &wk_klass_name_limits[1]); - f->do_oop((oop*) &_throwable_klass); - f->do_oop((oop*) &_error_klass); - f->do_oop((oop*) &_threaddeath_klass); - f->do_oop((oop*) &_exception_klass); - f->do_oop((oop*) &_runtime_exception_klass); - f->do_oop((oop*) &_classNotFoundException_klass); - f->do_oop((oop*) &_noClassDefFoundError_klass); - f->do_oop((oop*) &_linkageError_klass); - f->do_oop((oop*) &_classCastException_klass); - f->do_oop((oop*) &_arrayStoreException_klass); - f->do_oop((oop*) &_virtualMachineError_klass); - f->do_oop((oop*) &_outOfMemoryError_klass); - f->do_oop((oop*) &_StackOverflowError_klass); - f->do_oop((oop*) &_illegalMonitorStateException_klass); - f->do_oop((oop*) &_protectionDomain_klass); - f->do_oop((oop*) &_AccessControlContext_klass); + for (int k = (int)FIRST_WKID; k < (int)WKID_LIMIT; k++) { + f->do_oop((oop*) &_well_known_klasses[k]); + } - f->do_oop((oop*) &_reference_klass); - f->do_oop((oop*) &_soft_reference_klass); - f->do_oop((oop*) &_weak_reference_klass); - f->do_oop((oop*) &_final_reference_klass); - f->do_oop((oop*) &_phantom_reference_klass); - f->do_oop((oop*) &_finalizer_klass); - - f->do_oop((oop*) &_thread_klass); - f->do_oop((oop*) &_threadGroup_klass); - f->do_oop((oop*) &_properties_klass); - f->do_oop((oop*) &_reflect_accessible_object_klass); - f->do_oop((oop*) &_reflect_field_klass); - f->do_oop((oop*) &_reflect_method_klass); - f->do_oop((oop*) &_reflect_constructor_klass); - f->do_oop((oop*) &_reflect_magic_klass); - f->do_oop((oop*) &_reflect_method_accessor_klass); - f->do_oop((oop*) &_reflect_constructor_accessor_klass); - f->do_oop((oop*) &_reflect_delegating_classloader_klass); - f->do_oop((oop*) &_reflect_constant_pool_klass); - f->do_oop((oop*) &_reflect_unsafe_static_field_accessor_impl_klass); - - f->do_oop((oop*) &_stringBuffer_klass); - f->do_oop((oop*) &_vector_klass); - f->do_oop((oop*) &_hashtable_klass); - - f->do_oop((oop*) &_stackTraceElement_klass); - - f->do_oop((oop*) &_java_nio_Buffer_klass); - - f->do_oop((oop*) &_sun_misc_AtomicLongCSImpl_klass); - f->do_oop((oop*) &_sun_jkernel_DownloadManager_klass); - - f->do_oop((oop*) &_boolean_klass); - f->do_oop((oop*) &_char_klass); - f->do_oop((oop*) &_float_klass); - f->do_oop((oop*) &_double_klass); - f->do_oop((oop*) &_byte_klass); - f->do_oop((oop*) &_short_klass); - f->do_oop((oop*) &_int_klass); - f->do_oop((oop*) &_long_klass); { for (int i = 0; i < T_VOID+1; i++) { if (_box_klasses[i] != NULL) { @@ -1841,14 +1771,72 @@ void SystemDictionary::initialize(TRAPS) { initialize_preloaded_classes(CHECK); } +// Compact table of directions on the initialization of klasses: +static const short wk_init_info[] = { + #define WK_KLASS_INIT_INFO(name, symbol, option) \ + ( ((int)vmSymbols::VM_SYMBOL_ENUM_NAME(symbol) \ + << SystemDictionary::CEIL_LG_OPTION_LIMIT) \ + | (int)SystemDictionary::option ), + WK_KLASSES_DO(WK_KLASS_INIT_INFO) + #undef WK_KLASS_INIT_INFO + 0 +}; + +bool SystemDictionary::initialize_wk_klass(WKID id, int init_opt, TRAPS) { + assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob"); + int info = wk_init_info[id - FIRST_WKID]; + int sid = (info >> CEIL_LG_OPTION_LIMIT); + symbolHandle symbol = vmSymbolHandles::symbol_handle_at((vmSymbols::SID)sid); + klassOop* klassp = &_well_known_klasses[id]; + bool must_load = (init_opt < SystemDictionary::Opt); + bool try_load = true; + if (init_opt == SystemDictionary::Opt_Kernel) { +#ifndef KERNEL + try_load = false; +#endif //KERNEL + } + if ((*klassp) == NULL && try_load) { + if (must_load) { + (*klassp) = resolve_or_fail(symbol, true, CHECK_0); // load required class + } else { + (*klassp) = resolve_or_null(symbol, CHECK_0); // load optional klass + } + } + return ((*klassp) != NULL); +} + +void SystemDictionary::initialize_wk_klasses_until(WKID limit_id, WKID &start_id, TRAPS) { + assert((int)start_id <= (int)limit_id, "IDs are out of order!"); + for (int id = (int)start_id; id < (int)limit_id; id++) { + assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob"); + int info = wk_init_info[id - FIRST_WKID]; + int sid = (info >> CEIL_LG_OPTION_LIMIT); + int opt = (info & right_n_bits(CEIL_LG_OPTION_LIMIT)); + + initialize_wk_klass((WKID)id, opt, CHECK); + + // Update limits, so find_well_known_klass can be very fast: + symbolOop s = vmSymbols::symbol_at((vmSymbols::SID)sid); + if (wk_klass_name_limits[1] == NULL) { + wk_klass_name_limits[0] = wk_klass_name_limits[1] = s; + } else if (wk_klass_name_limits[1] < s) { + wk_klass_name_limits[1] = s; + } else if (wk_klass_name_limits[0] > s) { + wk_klass_name_limits[0] = s; + } + } +} + void SystemDictionary::initialize_preloaded_classes(TRAPS) { - assert(_object_klass == NULL, "preloaded classes should only be initialized once"); + assert(WK_KLASS(object_klass) == NULL, "preloaded classes should only be initialized once"); // Preload commonly used klasses - _object_klass = resolve_or_fail(vmSymbolHandles::java_lang_Object(), true, CHECK); - _string_klass = resolve_or_fail(vmSymbolHandles::java_lang_String(), true, CHECK); - _class_klass = resolve_or_fail(vmSymbolHandles::java_lang_Class(), true, CHECK); - debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(_class_klass)); + WKID scan = FIRST_WKID; + // first do Object, String, Class + initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(class_klass), scan, CHECK); + + debug_only(instanceKlass::verify_class_klass_nonstatic_oop_maps(WK_KLASS(class_klass))); + // Fixup mirrors for classes loaded before java.lang.Class. // These calls iterate over the objects currently in the perm gen // so calling them at this point is matters (not before when there @@ -1857,100 +1845,37 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { Universe::initialize_basic_type_mirrors(CHECK); Universe::fixup_mirrors(CHECK); - _cloneable_klass = resolve_or_fail(vmSymbolHandles::java_lang_Cloneable(), true, CHECK); - _classloader_klass = resolve_or_fail(vmSymbolHandles::java_lang_ClassLoader(), true, CHECK); - _serializable_klass = resolve_or_fail(vmSymbolHandles::java_io_Serializable(), true, CHECK); - _system_klass = resolve_or_fail(vmSymbolHandles::java_lang_System(), true, CHECK); - - _throwable_klass = resolve_or_fail(vmSymbolHandles::java_lang_Throwable(), true, CHECK); - _error_klass = resolve_or_fail(vmSymbolHandles::java_lang_Error(), true, CHECK); - _threaddeath_klass = resolve_or_fail(vmSymbolHandles::java_lang_ThreadDeath(), true, CHECK); - _exception_klass = resolve_or_fail(vmSymbolHandles::java_lang_Exception(), true, CHECK); - _runtime_exception_klass = resolve_or_fail(vmSymbolHandles::java_lang_RuntimeException(), true, CHECK); - _protectionDomain_klass = resolve_or_fail(vmSymbolHandles::java_security_ProtectionDomain(), true, CHECK); - _AccessControlContext_klass = resolve_or_fail(vmSymbolHandles::java_security_AccessControlContext(), true, CHECK); - _classNotFoundException_klass = resolve_or_fail(vmSymbolHandles::java_lang_ClassNotFoundException(), true, CHECK); - _noClassDefFoundError_klass = resolve_or_fail(vmSymbolHandles::java_lang_NoClassDefFoundError(), true, CHECK); - _linkageError_klass = resolve_or_fail(vmSymbolHandles::java_lang_LinkageError(), true, CHECK); - _classCastException_klass = resolve_or_fail(vmSymbolHandles::java_lang_ClassCastException(), true, CHECK); - _arrayStoreException_klass = resolve_or_fail(vmSymbolHandles::java_lang_ArrayStoreException(), true, CHECK); - _virtualMachineError_klass = resolve_or_fail(vmSymbolHandles::java_lang_VirtualMachineError(), true, CHECK); - _outOfMemoryError_klass = resolve_or_fail(vmSymbolHandles::java_lang_OutOfMemoryError(), true, CHECK); - _StackOverflowError_klass = resolve_or_fail(vmSymbolHandles::java_lang_StackOverflowError(), true, CHECK); - _illegalMonitorStateException_klass = resolve_or_fail(vmSymbolHandles::java_lang_IllegalMonitorStateException(), true, CHECK); + // do a bunch more: + initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(reference_klass), scan, CHECK); // Preload ref klasses and set reference types - _reference_klass = resolve_or_fail(vmSymbolHandles::java_lang_ref_Reference(), true, CHECK); - instanceKlass::cast(_reference_klass)->set_reference_type(REF_OTHER); - instanceRefKlass::update_nonstatic_oop_maps(_reference_klass); + instanceKlass::cast(WK_KLASS(reference_klass))->set_reference_type(REF_OTHER); + instanceRefKlass::update_nonstatic_oop_maps(WK_KLASS(reference_klass)); - _soft_reference_klass = resolve_or_fail(vmSymbolHandles::java_lang_ref_SoftReference(), true, CHECK); - instanceKlass::cast(_soft_reference_klass)->set_reference_type(REF_SOFT); - _weak_reference_klass = resolve_or_fail(vmSymbolHandles::java_lang_ref_WeakReference(), true, CHECK); - instanceKlass::cast(_weak_reference_klass)->set_reference_type(REF_WEAK); - _final_reference_klass = resolve_or_fail(vmSymbolHandles::java_lang_ref_FinalReference(), true, CHECK); - instanceKlass::cast(_final_reference_klass)->set_reference_type(REF_FINAL); - _phantom_reference_klass = resolve_or_fail(vmSymbolHandles::java_lang_ref_PhantomReference(), true, CHECK); - instanceKlass::cast(_phantom_reference_klass)->set_reference_type(REF_PHANTOM); - _finalizer_klass = resolve_or_fail(vmSymbolHandles::java_lang_ref_Finalizer(), true, CHECK); + initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(phantom_reference_klass), scan, CHECK); + instanceKlass::cast(WK_KLASS(soft_reference_klass))->set_reference_type(REF_SOFT); + instanceKlass::cast(WK_KLASS(weak_reference_klass))->set_reference_type(REF_WEAK); + instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL); + instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM); - _thread_klass = resolve_or_fail(vmSymbolHandles::java_lang_Thread(), true, CHECK); - _threadGroup_klass = resolve_or_fail(vmSymbolHandles::java_lang_ThreadGroup(), true, CHECK); - _properties_klass = resolve_or_fail(vmSymbolHandles::java_util_Properties(), true, CHECK); - _reflect_accessible_object_klass = resolve_or_fail(vmSymbolHandles::java_lang_reflect_AccessibleObject(), true, CHECK); - _reflect_field_klass = resolve_or_fail(vmSymbolHandles::java_lang_reflect_Field(), true, CHECK); - _reflect_method_klass = resolve_or_fail(vmSymbolHandles::java_lang_reflect_Method(), true, CHECK); - _reflect_constructor_klass = resolve_or_fail(vmSymbolHandles::java_lang_reflect_Constructor(), true, CHECK); - // Universe::is_gte_jdk14x_version() is not set up by this point. - // It's okay if these turn out to be NULL in non-1.4 JDKs. - _reflect_magic_klass = resolve_or_null(vmSymbolHandles::sun_reflect_MagicAccessorImpl(), CHECK); - _reflect_method_accessor_klass = resolve_or_null(vmSymbolHandles::sun_reflect_MethodAccessorImpl(), CHECK); - _reflect_constructor_accessor_klass = resolve_or_null(vmSymbolHandles::sun_reflect_ConstructorAccessorImpl(), CHECK); - _reflect_delegating_classloader_klass = resolve_or_null(vmSymbolHandles::sun_reflect_DelegatingClassLoader(), CHECK); - _reflect_constant_pool_klass = resolve_or_null(vmSymbolHandles::sun_reflect_ConstantPool(), CHECK); - _reflect_unsafe_static_field_accessor_impl_klass = resolve_or_null(vmSymbolHandles::sun_reflect_UnsafeStaticFieldAccessorImpl(), CHECK); + initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK); - _vector_klass = resolve_or_fail(vmSymbolHandles::java_util_Vector(), true, CHECK); - _hashtable_klass = resolve_or_fail(vmSymbolHandles::java_util_Hashtable(), true, CHECK); - _stringBuffer_klass = resolve_or_fail(vmSymbolHandles::java_lang_StringBuffer(), true, CHECK); + _box_klasses[T_BOOLEAN] = WK_KLASS(boolean_klass); + _box_klasses[T_CHAR] = WK_KLASS(char_klass); + _box_klasses[T_FLOAT] = WK_KLASS(float_klass); + _box_klasses[T_DOUBLE] = WK_KLASS(double_klass); + _box_klasses[T_BYTE] = WK_KLASS(byte_klass); + _box_klasses[T_SHORT] = WK_KLASS(short_klass); + _box_klasses[T_INT] = WK_KLASS(int_klass); + _box_klasses[T_LONG] = WK_KLASS(long_klass); + //_box_klasses[T_OBJECT] = WK_KLASS(object_klass); + //_box_klasses[T_ARRAY] = WK_KLASS(object_klass); - // It's NULL in non-1.4 JDKs. - _stackTraceElement_klass = resolve_or_null(vmSymbolHandles::java_lang_StackTraceElement(), CHECK); - - // Universe::is_gte_jdk14x_version() is not set up by this point. - // It's okay if this turns out to be NULL in non-1.4 JDKs. - _java_nio_Buffer_klass = resolve_or_null(vmSymbolHandles::java_nio_Buffer(), CHECK); - - // If this class isn't present, it won't be referenced. - _sun_misc_AtomicLongCSImpl_klass = resolve_or_null(vmSymbolHandles::sun_misc_AtomicLongCSImpl(), CHECK); #ifdef KERNEL - _sun_jkernel_DownloadManager_klass = resolve_or_null(vmSymbolHandles::sun_jkernel_DownloadManager(), CHECK); - if (_sun_jkernel_DownloadManager_klass == NULL) { + if (sun_jkernel_DownloadManager_klass() == NULL) { warning("Cannot find sun/jkernel/DownloadManager"); } #endif // KERNEL - - // Preload boxing klasses - _boolean_klass = resolve_or_fail(vmSymbolHandles::java_lang_Boolean(), true, CHECK); - _char_klass = resolve_or_fail(vmSymbolHandles::java_lang_Character(), true, CHECK); - _float_klass = resolve_or_fail(vmSymbolHandles::java_lang_Float(), true, CHECK); - _double_klass = resolve_or_fail(vmSymbolHandles::java_lang_Double(), true, CHECK); - _byte_klass = resolve_or_fail(vmSymbolHandles::java_lang_Byte(), true, CHECK); - _short_klass = resolve_or_fail(vmSymbolHandles::java_lang_Short(), true, CHECK); - _int_klass = resolve_or_fail(vmSymbolHandles::java_lang_Integer(), true, CHECK); - _long_klass = resolve_or_fail(vmSymbolHandles::java_lang_Long(), true, CHECK); - - _box_klasses[T_BOOLEAN] = _boolean_klass; - _box_klasses[T_CHAR] = _char_klass; - _box_klasses[T_FLOAT] = _float_klass; - _box_klasses[T_DOUBLE] = _double_klass; - _box_klasses[T_BYTE] = _byte_klass; - _box_klasses[T_SHORT] = _short_klass; - _box_klasses[T_INT] = _int_klass; - _box_klasses[T_LONG] = _long_klass; - //_box_klasses[T_OBJECT] = _object_klass; - //_box_klasses[T_ARRAY] = _object_klass; - { // Compute whether we should use loadClass or loadClassInternal when loading classes. methodOop method = instanceKlass::cast(classloader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature()); _has_loadClassInternal = (method != NULL); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index 519dac9a95a..4b5bc16ff38 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -64,12 +64,133 @@ class LoaderConstraintTable; class HashtableBucket; class ResolutionErrorTable; +// Certain classes are preloaded, such as java.lang.Object and java.lang.String. +// They are all "well-known", in the sense that no class loader is allowed +// to provide a different definition. +// +// These klasses must all have names defined in vmSymbols. + +#define WK_KLASS_ENUM_NAME(kname) kname##_knum + +// Each well-known class has a short klass name (like object_klass), +// a vmSymbol name (like java_lang_Object), and a flag word +// that makes some minor distinctions, like whether the klass +// is preloaded, optional, release-specific, etc. +// The order of these definitions is significant; it is the order in which +// preloading is actually performed by initialize_preloaded_classes. + +#define WK_KLASSES_DO(template) \ + /* well-known classes */ \ + template(object_klass, java_lang_Object, Pre) \ + template(string_klass, java_lang_String, Pre) \ + template(class_klass, java_lang_Class, Pre) \ + template(cloneable_klass, java_lang_Cloneable, Pre) \ + template(classloader_klass, java_lang_ClassLoader, Pre) \ + template(serializable_klass, java_io_Serializable, Pre) \ + template(system_klass, java_lang_System, Pre) \ + template(throwable_klass, java_lang_Throwable, Pre) \ + template(error_klass, java_lang_Error, Pre) \ + template(threaddeath_klass, java_lang_ThreadDeath, Pre) \ + template(exception_klass, java_lang_Exception, Pre) \ + template(runtime_exception_klass, java_lang_RuntimeException, Pre) \ + template(protectionDomain_klass, java_security_ProtectionDomain, Pre) \ + template(AccessControlContext_klass, java_security_AccessControlContext, Pre) \ + template(classNotFoundException_klass, java_lang_ClassNotFoundException, Pre) \ + template(noClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre) \ + template(linkageError_klass, java_lang_LinkageError, Pre) \ + template(ClassCastException_klass, java_lang_ClassCastException, Pre) \ + template(ArrayStoreException_klass, java_lang_ArrayStoreException, Pre) \ + template(virtualMachineError_klass, java_lang_VirtualMachineError, Pre) \ + template(OutOfMemoryError_klass, java_lang_OutOfMemoryError, Pre) \ + template(StackOverflowError_klass, java_lang_StackOverflowError, Pre) \ + template(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException, Pre) \ + template(reference_klass, java_lang_ref_Reference, Pre) \ + \ + /* Preload ref klasses and set reference types */ \ + template(soft_reference_klass, java_lang_ref_SoftReference, Pre) \ + template(weak_reference_klass, java_lang_ref_WeakReference, Pre) \ + template(final_reference_klass, java_lang_ref_FinalReference, Pre) \ + template(phantom_reference_klass, java_lang_ref_PhantomReference, Pre) \ + template(finalizer_klass, java_lang_ref_Finalizer, Pre) \ + \ + template(thread_klass, java_lang_Thread, Pre) \ + template(threadGroup_klass, java_lang_ThreadGroup, Pre) \ + template(properties_klass, java_util_Properties, Pre) \ + template(reflect_accessible_object_klass, java_lang_reflect_AccessibleObject, Pre) \ + template(reflect_field_klass, java_lang_reflect_Field, Pre) \ + template(reflect_method_klass, java_lang_reflect_Method, Pre) \ + template(reflect_constructor_klass, java_lang_reflect_Constructor, Pre) \ + \ + /* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \ + /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ + /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ + template(reflect_magic_klass, sun_reflect_MagicAccessorImpl, Opt) \ + template(reflect_method_accessor_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ + template(reflect_constructor_accessor_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ + template(reflect_delegating_classloader_klass, sun_reflect_DelegatingClassLoader, Opt) \ + template(reflect_constant_pool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ + template(reflect_unsafe_static_field_accessor_impl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ + \ + template(vector_klass, java_util_Vector, Pre) \ + template(hashtable_klass, java_util_Hashtable, Pre) \ + template(stringBuffer_klass, java_lang_StringBuffer, Pre) \ + \ + /* It's NULL in non-1.4 JDKs. */ \ + template(stackTraceElement_klass, java_lang_StackTraceElement, Opt) \ + /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ + /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ + template(java_nio_Buffer_klass, java_nio_Buffer, Opt) \ + \ + /* If this class isn't present, it won't be referenced. */ \ + template(sun_misc_AtomicLongCSImpl_klass, sun_misc_AtomicLongCSImpl, Opt) \ + \ + template(sun_jkernel_DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \ + \ + /* Preload boxing klasses */ \ + template(boolean_klass, java_lang_Boolean, Pre) \ + template(char_klass, java_lang_Character, Pre) \ + template(float_klass, java_lang_Float, Pre) \ + template(double_klass, java_lang_Double, Pre) \ + template(byte_klass, java_lang_Byte, Pre) \ + template(short_klass, java_lang_Short, Pre) \ + template(int_klass, java_lang_Integer, Pre) \ + template(long_klass, java_lang_Long, Pre) \ + /*end*/ + + class SystemDictionary : AllStatic { friend class VMStructs; friend class CompactingPermGenGen; NOT_PRODUCT(friend class instanceKlassKlass;) public: + enum WKID { + NO_WKID = 0, + + #define WK_KLASS_ENUM(name, ignore_s, ignore_o) WK_KLASS_ENUM_NAME(name), + WK_KLASSES_DO(WK_KLASS_ENUM) + #undef WK_KLASS_ENUM + + WKID_LIMIT, + + FIRST_WKID = NO_WKID + 1 + }; + + enum InitOption { + Pre, // preloaded; error if not present + + // Order is significant. Options before this point require resolve_or_fail. + // Options after this point will use resolve_or_null instead. + + Opt, // preload tried; NULL if not present + Opt_Only_JDK14NewRef, // preload tried; use only with NewReflection + Opt_Only_JDK15, // preload tried; use only with JDK1.5+ + Opt_Kernel, // preload tried only #ifdef KERNEL + OPTION_LIMIT, + CEIL_LG_OPTION_LIMIT = 4 // OPTION_LIMIT <= (1<find_start(start); - assert(result == NULL || result->blob_contains((address)start), "found wrong CodeBlob"); + // this assert is too strong because the heap code will return the + // heapblock containing start. That block can often be larger than + // the codeBlob itself. If you look up an address that is within + // the heapblock but not in the codeBlob you will assert. + // + // Most things will not lookup such bad addresses. However + // AsyncGetCallTrace can see intermediate frames and get that kind + // of invalid address and so can a developer using hsfind. + // + // The more correct answer is to return NULL if blob_contains() returns + // false. + // assert(result == NULL || result->blob_contains((address)start), "found wrong CodeBlob"); + + if (result != NULL && !result->blob_contains((address)start)) { + result = NULL; + } return result; } diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 518c0ce717d..14b10ea410c 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -27,7 +27,6 @@ #ifdef DTRACE_ENABLED - // Only bother with this argument setup if dtrace is available HS_DTRACE_PROBE_DECL8(hotspot, compiled__method__load, @@ -438,7 +437,6 @@ nmethod* nmethod::new_native_nmethod(methodHandle method, { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); int native_nmethod_size = allocation_size(code_buffer, sizeof(nmethod)); - const int dummy = -1; // Flag to force proper "operator new" CodeOffsets offsets; offsets.set_value(CodeOffsets::Verified_Entry, vep_offset); offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); @@ -461,6 +459,41 @@ nmethod* nmethod::new_native_nmethod(methodHandle method, return nm; } +#ifdef HAVE_DTRACE_H +nmethod* nmethod::new_dtrace_nmethod(methodHandle method, + CodeBuffer *code_buffer, + int vep_offset, + int trap_offset, + int frame_complete, + int frame_size) { + // create nmethod + nmethod* nm = NULL; + { + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + int nmethod_size = allocation_size(code_buffer, sizeof(nmethod)); + CodeOffsets offsets; + offsets.set_value(CodeOffsets::Verified_Entry, vep_offset); + offsets.set_value(CodeOffsets::Dtrace_trap, trap_offset); + offsets.set_value(CodeOffsets::Frame_Complete, frame_complete); + + nm = new (nmethod_size) nmethod(method(), nmethod_size, &offsets, code_buffer, frame_size); + + NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_nmethod(nm)); + if (PrintAssembly && nm != NULL) + Disassembler::decode(nm); + } + // verify nmethod + debug_only(if (nm) nm->verify();) // might block + + if (nm != NULL) { + nm->log_new_nmethod(); + } + + return nm; +} + +#endif // def HAVE_DTRACE_H + nmethod* nmethod::new_nmethod(methodHandle method, int compile_id, int entry_bci, @@ -558,6 +591,9 @@ nmethod::nmethod( _exception_offset = 0; _deoptimize_offset = 0; _orig_pc_offset = 0; +#ifdef HAVE_DTRACE_H + _trap_offset = 0; +#endif // def HAVE_DTRACE_H _stub_offset = data_offset(); _consts_offset = data_offset(); _scopes_data_offset = data_offset(); @@ -615,6 +651,90 @@ nmethod::nmethod( Events::log("Create nmethod " INTPTR_FORMAT, this); } +// For dtrace wrappers +#ifdef HAVE_DTRACE_H +nmethod::nmethod( + methodOop method, + int nmethod_size, + CodeOffsets* offsets, + CodeBuffer* code_buffer, + int frame_size) + : CodeBlob("dtrace nmethod", code_buffer, sizeof(nmethod), + nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, NULL), + _compiled_synchronized_native_basic_lock_owner_sp_offset(in_ByteSize(-1)), + _compiled_synchronized_native_basic_lock_sp_offset(in_ByteSize(-1)) +{ + { + debug_only(No_Safepoint_Verifier nsv;) + assert_locked_or_safepoint(CodeCache_lock); + + NOT_PRODUCT(_has_debug_info = false; ) + _method = method; + _entry_bci = InvocationEntryBci; + _link = NULL; + _compiler = NULL; + // We have no exception handler or deopt handler make the + // values something that will never match a pc like the nmethod vtable entry + _exception_offset = 0; + _deoptimize_offset = 0; + _trap_offset = offsets->value(CodeOffsets::Dtrace_trap); + _orig_pc_offset = 0; + _stub_offset = data_offset(); + _consts_offset = data_offset(); + _scopes_data_offset = data_offset(); + _scopes_pcs_offset = _scopes_data_offset; + _dependencies_offset = _scopes_pcs_offset; + _handler_table_offset = _dependencies_offset; + _nul_chk_table_offset = _handler_table_offset; + _nmethod_end_offset = _nul_chk_table_offset; + _compile_id = 0; // default + _comp_level = CompLevel_none; + _entry_point = instructions_begin(); + _verified_entry_point = instructions_begin() + offsets->value(CodeOffsets::Verified_Entry); + _osr_entry_point = NULL; + _exception_cache = NULL; + _pc_desc_cache.reset_to(NULL); + + flags.clear(); + flags.state = alive; + _markedForDeoptimization = 0; + + _lock_count = 0; + _stack_traversal_mark = 0; + + code_buffer->copy_oops_to(this); + debug_only(check_store();) + CodeCache::commit(this); + VTune::create_nmethod(this); + } + + if (PrintNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) { + ttyLocker ttyl; // keep the following output all in one block + // This output goes directly to the tty, not the compiler log. + // To enable tools to match it up with the compilation activity, + // be sure to tag this tty output with the compile ID. + if (xtty != NULL) { + xtty->begin_head("print_dtrace_nmethod"); + xtty->method(_method); + xtty->stamp(); + xtty->end_head(" address='" INTPTR_FORMAT "'", (intptr_t) this); + } + // print the header part first + print(); + // then print the requested information + if (PrintNMethods) { + print_code(); + } + if (PrintRelocations) { + print_relocations(); + } + if (xtty != NULL) { + xtty->tail("print_dtrace_nmethod"); + } + } + Events::log("Create nmethod " INTPTR_FORMAT, this); +} +#endif // def HAVE_DTRACE_H void* nmethod::operator new(size_t size, int nmethod_size) { // Always leave some room in the CodeCache for I2C/C2I adapters @@ -658,6 +778,9 @@ nmethod::nmethod( _link = NULL; _compiler = compiler; _orig_pc_offset = orig_pc_offset; +#ifdef HAVE_DTRACE_H + _trap_offset = 0; +#endif // def HAVE_DTRACE_H _stub_offset = instructions_offset() + code_buffer->total_offset_of(code_buffer->stubs()->start()); // Exception handler and deopt handler are in the stub section @@ -707,7 +830,9 @@ nmethod::nmethod( " entry points must be same for static methods and vice versa"); } - bool printnmethods = PrintNMethods || CompilerOracle::has_option_string(_method, "PrintNMethods"); + bool printnmethods = PrintNMethods + || CompilerOracle::should_print(_method) + || CompilerOracle::has_option_string(_method, "PrintNMethods"); if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) { print_nmethod(printnmethods); } @@ -798,7 +923,6 @@ void nmethod::print_on(outputStream* st, const char* title) const { } -#ifndef PRODUCT void nmethod::print_nmethod(bool printmethod) { ttyLocker ttyl; // keep the following output all in one block if (xtty != NULL) { @@ -831,7 +955,6 @@ void nmethod::print_nmethod(bool printmethod) { xtty->tail("print_nmethod"); } } -#endif void nmethod::set_version(int v) { @@ -1870,6 +1993,7 @@ void nmethod::check_store() { } } +#endif // PRODUCT // Printing operations @@ -1884,7 +2008,6 @@ void nmethod::print() const { } else if (is_compiled_by_c2()) { tty->print("(c2) "); } else { - assert(is_native_method(), "Who else?"); tty->print("(nm) "); } @@ -1948,6 +2071,14 @@ void nmethod::print() const { oops_size()); } +void nmethod::print_code() { + HandleMark hm; + ResourceMark m; + Disassembler::decode(this); +} + + +#ifndef PRODUCT void nmethod::print_scopes() { // Find the first pc desc for all scopes in the code and print it. @@ -1979,13 +2110,6 @@ void nmethod::print_dependencies() { } -void nmethod::print_code() { - HandleMark hm; - ResourceMark m; - Disassembler().decode(this); -} - - void nmethod::print_relocations() { ResourceMark m; // in case methods get printed via the debugger tty->print_cr("relocations:"); @@ -2021,6 +2145,7 @@ void nmethod::print_pcs() { } } +#endif // PRODUCT const char* nmethod::reloc_string_for(u_char* begin, u_char* end) { RelocIterator iter(this, begin, end); @@ -2055,7 +2180,6 @@ const char* nmethod::reloc_string_for(u_char* begin, u_char* end) { return have_one ? "other" : NULL; } - // Return a the last scope in (begin..end] ScopeDesc* nmethod::scope_desc_in(address begin, address end) { PcDesc* p = pc_desc_near(begin+1); @@ -2078,29 +2202,26 @@ void nmethod::print_code_comment_on(outputStream* st, int column, u_char* begin, address pc = base + om->offset(); if (pc > begin) { if (pc <= end) { - st->fill_to(column); - if (st == tty) { - st->print("; OopMap "); - om->print(); - tty->cr(); - } else { - st->print_cr("; OopMap #%d offset:%d", i, om->offset()); - } + st->move_to(column); + st->print("; "); + om->print_on(st); } break; } } } + + // Print any debug info present at this pc. ScopeDesc* sd = scope_desc_in(begin, end); if (sd != NULL) { - st->fill_to(column); + st->move_to(column); if (sd->bci() == SynchronizationEntryBCI) { st->print(";*synchronization entry"); } else { if (sd->method().is_null()) { - tty->print("method is NULL"); + st->print("method is NULL"); } else if (sd->method()->is_native()) { - tty->print("method is native"); + st->print("method is native"); } else { address bcp = sd->method()->bcp_from(sd->bci()); Bytecodes::Code bc = Bytecodes::java_code_at(bcp); @@ -2137,13 +2258,13 @@ void nmethod::print_code_comment_on(outputStream* st, int column, u_char* begin, } } } - st->cr(); + // Print all scopes for (;sd != NULL; sd = sd->sender()) { - st->fill_to(column); + st->move_to(column); st->print("; -"); if (sd->method().is_null()) { - tty->print("method is NULL"); + st->print("method is NULL"); } else { sd->method()->print_short_name(st); } @@ -2161,17 +2282,19 @@ void nmethod::print_code_comment_on(outputStream* st, int column, u_char* begin, const char* str = reloc_string_for(begin, end); if (str != NULL) { if (sd != NULL) st->cr(); - st->fill_to(column); + st->move_to(column); st->print("; {%s}", str); } int cont_offset = ImplicitExceptionTable(this).at(begin - instructions_begin()); if (cont_offset != 0) { - st->fill_to(column); + st->move_to(column); st->print("; implicit exception: dispatches to " INTPTR_FORMAT, instructions_begin() + cont_offset); } } +#ifndef PRODUCT + void nmethod::print_value_on(outputStream* st) const { print_on(st, "nmethod"); } diff --git a/hotspot/src/share/vm/code/nmethod.hpp b/hotspot/src/share/vm/code/nmethod.hpp index 0b1c61977e3..4cfb4b9c3f5 100644 --- a/hotspot/src/share/vm/code/nmethod.hpp +++ b/hotspot/src/share/vm/code/nmethod.hpp @@ -140,6 +140,9 @@ class nmethod : public CodeBlob { int _exception_offset; // All deoptee's will resume execution at this location described by this offset int _deoptimize_offset; +#ifdef HAVE_DTRACE_H + int _trap_offset; +#endif // def HAVE_DTRACE_H int _stub_offset; int _consts_offset; int _scopes_data_offset; @@ -211,6 +214,15 @@ class nmethod : public CodeBlob { ByteSize basic_lock_sp_offset, /* synchronized natives only */ OopMapSet* oop_maps); +#ifdef HAVE_DTRACE_H + // For native wrappers + nmethod(methodOop method, + int nmethod_size, + CodeOffsets* offsets, + CodeBuffer *code_buffer, + int frame_size); +#endif // def HAVE_DTRACE_H + // Creation support nmethod(methodOop method, int nmethod_size, @@ -272,6 +284,22 @@ class nmethod : public CodeBlob { ByteSize basic_lock_sp_offset, OopMapSet* oop_maps); +#ifdef HAVE_DTRACE_H + // The method we generate for a dtrace probe has to look + // like an nmethod as far as the rest of the system is concerned + // which is somewhat unfortunate. + static nmethod* new_dtrace_nmethod(methodHandle method, + CodeBuffer *code_buffer, + int vep_offset, + int trap_offset, + int frame_complete, + int frame_size); + + int trap_offset() const { return _trap_offset; } + address trap_address() const { return code_begin() + _trap_offset; } + +#endif // def HAVE_DTRACE_H + // accessors methodOop method() const { return _method; } AbstractCompiler* compiler() const { return _compiler; } @@ -485,8 +513,8 @@ class nmethod : public CodeBlob { void verify_interrupt_point(address interrupt_point); // printing support - void print() const PRODUCT_RETURN; - void print_code() PRODUCT_RETURN; + void print() const; + void print_code(); void print_relocations() PRODUCT_RETURN; void print_pcs() PRODUCT_RETURN; void print_scopes() PRODUCT_RETURN; @@ -495,7 +523,7 @@ class nmethod : public CodeBlob { void print_calls(outputStream* st) PRODUCT_RETURN; void print_handler_table() PRODUCT_RETURN; void print_nul_chk_table() PRODUCT_RETURN; - void print_nmethod(bool print_code) PRODUCT_RETURN; + void print_nmethod(bool print_code); void print_on(outputStream* st, const char* title) const; @@ -505,7 +533,7 @@ class nmethod : public CodeBlob { void log_state_change(int state) const; // Prints a comment for one native instruction (reloc info, pc desc) - void print_code_comment_on(outputStream* st, int column, address begin, address end) PRODUCT_RETURN; + void print_code_comment_on(outputStream* st, int column, address begin, address end); static void print_statistics() PRODUCT_RETURN; // Compiler task identification. Note that all OSR methods diff --git a/hotspot/src/share/vm/code/vmreg.cpp b/hotspot/src/share/vm/code/vmreg.cpp index 22be4b2f390..3d2aa69274d 100644 --- a/hotspot/src/share/vm/code/vmreg.cpp +++ b/hotspot/src/share/vm/code/vmreg.cpp @@ -36,7 +36,6 @@ const int VMRegImpl::register_count = ConcreteRegisterImpl::number_of_registers; // Register names const char *VMRegImpl::regName[ConcreteRegisterImpl::number_of_registers]; -#ifndef PRODUCT void VMRegImpl::print_on(outputStream* st) const { if( is_reg() ) { assert( VMRegImpl::regName[value()], "" ); @@ -48,4 +47,3 @@ void VMRegImpl::print_on(outputStream* st) const { st->print("BAD!"); } } -#endif // PRODUCT diff --git a/hotspot/src/share/vm/code/vmreg.hpp b/hotspot/src/share/vm/code/vmreg.hpp index ab77b265fe3..399cba3497b 100644 --- a/hotspot/src/share/vm/code/vmreg.hpp +++ b/hotspot/src/share/vm/code/vmreg.hpp @@ -96,7 +96,7 @@ public: intptr_t value() const {return (intptr_t) this; } - void print_on(outputStream* st) const PRODUCT_RETURN; + void print_on(outputStream* st) const; void print() const { print_on(tty); } // bias a stack slot. @@ -156,22 +156,22 @@ public: _first = ptr; } // Return true if single register, even if the pair is really just adjacent stack slots - bool is_single_reg() { + bool is_single_reg() const { return (_first->is_valid()) && (_first->value() + 1 == _second->value()); } // Return true if single stack based "register" where the slot alignment matches input alignment - bool is_adjacent_on_stack(int alignment) { + bool is_adjacent_on_stack(int alignment) const { return (_first->is_stack() && (_first->value() + 1 == _second->value()) && ((_first->value() & (alignment-1)) == 0)); } // Return true if single stack based "register" where the slot alignment matches input alignment - bool is_adjacent_aligned_on_stack(int alignment) { + bool is_adjacent_aligned_on_stack(int alignment) const { return (_first->is_stack() && (_first->value() + 1 == _second->value()) && ((_first->value() & (alignment-1)) == 0)); } // Return true if single register but adjacent stack slots do not count - bool is_single_phys_reg() { + bool is_single_phys_reg() const { return (_first->is_reg() && (_first->value() + 1 == _second->value())); } diff --git a/hotspot/src/share/vm/compiler/disassembler.cpp b/hotspot/src/share/vm/compiler/disassembler.cpp new file mode 100644 index 00000000000..3e800e9b9e7 --- /dev/null +++ b/hotspot/src/share/vm/compiler/disassembler.cpp @@ -0,0 +1,443 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +# include "incls/_precompiled.incl" +# include "incls/_disassembler.cpp.incl" + +void* Disassembler::_library = NULL; +bool Disassembler::_tried_to_load_library = false; + +// This routine is in the shared library: +Disassembler::decode_func Disassembler::_decode_instructions = NULL; + +static const char hsdis_library_name[] = "hsdis-"HOTSPOT_LIB_ARCH; +static const char decode_instructions_name[] = "decode_instructions"; + +#define COMMENT_COLUMN 40 LP64_ONLY(+8) /*could be an option*/ +#define BYTES_COMMENT ";..." /* funky byte display comment */ + +bool Disassembler::load_library() { + if (_decode_instructions != NULL) { + // Already succeeded. + return true; + } + if (_tried_to_load_library) { + // Do not try twice. + // To force retry in debugger: assign _tried_to_load_library=0 + return false; + } + // Try to load it. + char ebuf[1024]; + char buf[JVM_MAXPATHLEN]; + os::jvm_path(buf, sizeof(buf)); + int jvm_offset = -1; + { + // Match "jvm[^/]*" in jvm_path. + const char* base = buf; + const char* p = strrchr(buf, '/'); + p = strstr(p ? p : base, "jvm"); + if (p != NULL) jvm_offset = p - base; + } + if (jvm_offset >= 0) { + // Find the disassembler next to libjvm.so. + strcpy(&buf[jvm_offset], hsdis_library_name); + strcat(&buf[jvm_offset], os::dll_file_extension()); + _library = hpi::dll_load(buf, ebuf, sizeof ebuf); + } + if (_library == NULL) { + // Try a free-floating lookup. + strcpy(&buf[0], hsdis_library_name); + strcat(&buf[0], os::dll_file_extension()); + _library = hpi::dll_load(buf, ebuf, sizeof ebuf); + } + if (_library != NULL) { + _decode_instructions = CAST_TO_FN_PTR(Disassembler::decode_func, + hpi::dll_lookup(_library, decode_instructions_name)); + } + _tried_to_load_library = true; + if (_decode_instructions == NULL) { + tty->print_cr("Could not load %s; %s; %s", buf, + ((_library != NULL) + ? "entry point is missing" + : (WizardMode || PrintMiscellaneous) + ? (const char*)ebuf + : "library not loadable"), + "PrintAssembly is disabled"); + return false; + } + + // Success. + tty->print_cr("Loaded disassembler from %s", buf); + return true; +} + + +class decode_env { + private: + nmethod* _nm; + CodeBlob* _code; + outputStream* _output; + address _start, _end; + + char _option_buf[512]; + char _print_raw; + bool _print_pc; + bool _print_bytes; + address _cur_insn; + int _total_ticks; + int _bytes_per_line; // arch-specific formatting option + + static bool match(const char* event, const char* tag) { + size_t taglen = strlen(tag); + if (strncmp(event, tag, taglen) != 0) + return false; + char delim = event[taglen]; + return delim == '\0' || delim == ' ' || delim == '/' || delim == '='; + } + + void collect_options(const char* p) { + if (p == NULL || p[0] == '\0') return; + size_t opt_so_far = strlen(_option_buf); + if (opt_so_far + 1 + strlen(p) + 1 > sizeof(_option_buf)) return; + char* fillp = &_option_buf[opt_so_far]; + if (opt_so_far > 0) *fillp++ = ','; + strcat(fillp, p); + // replace white space by commas: + char* q = fillp; + while ((q = strpbrk(q, " \t\n")) != NULL) + *q++ = ','; + // Note that multiple PrintAssemblyOptions flags accumulate with \n, + // which we want to be changed to a comma... + } + + void print_insn_labels(); + void print_insn_bytes(address pc0, address pc); + void print_address(address value); + + public: + decode_env(CodeBlob* code, outputStream* output); + + address decode_instructions(address start, address end); + + void start_insn(address pc) { + _cur_insn = pc; + output()->bol(); + print_insn_labels(); + } + + void end_insn(address pc) { + address pc0 = cur_insn(); + outputStream* st = output(); + if (_print_bytes && pc > pc0) + print_insn_bytes(pc0, pc); + if (_nm != NULL) + _nm->print_code_comment_on(st, COMMENT_COLUMN, pc0, pc); + + // Output pc bucket ticks if we have any + if (total_ticks() != 0) { + address bucket_pc = FlatProfiler::bucket_start_for(pc); + if (bucket_pc != NULL && bucket_pc > pc0 && bucket_pc <= pc) { + int bucket_count = FlatProfiler::bucket_count_for(pc0); + if (bucket_count != 0) { + st->bol(); + st->print_cr("%3.1f%% [%d]", bucket_count*100.0/total_ticks(), bucket_count); + } + } + } + } + + address handle_event(const char* event, address arg); + + outputStream* output() { return _output; } + address cur_insn() { return _cur_insn; } + int total_ticks() { return _total_ticks; } + void set_total_ticks(int n) { _total_ticks = n; } + const char* options() { return _option_buf; } +}; + +decode_env::decode_env(CodeBlob* code, outputStream* output) { + memset(this, 0, sizeof(*this)); + _output = output ? output : tty; + _code = code; + if (code != NULL && code->is_nmethod()) + _nm = (nmethod*) code; + + // by default, output pc but not bytes: + _print_pc = true; + _print_bytes = false; + _bytes_per_line = Disassembler::pd_instruction_alignment(); + + // parse the global option string: + collect_options(Disassembler::pd_cpu_opts()); + collect_options(PrintAssemblyOptions); + + if (strstr(options(), "hsdis-")) { + if (strstr(options(), "hsdis-print-raw")) + _print_raw = (strstr(options(), "xml") ? 2 : 1); + if (strstr(options(), "hsdis-print-pc")) + _print_pc = !_print_pc; + if (strstr(options(), "hsdis-print-bytes")) + _print_bytes = !_print_bytes; + } + if (strstr(options(), "help")) { + tty->print_cr("PrintAssemblyOptions help:"); + tty->print_cr(" hsdis-print-raw test plugin by requesting raw output"); + tty->print_cr(" hsdis-print-raw-xml test plugin by requesting raw xml"); + tty->print_cr(" hsdis-print-pc turn off PC printing (on by default)"); + tty->print_cr(" hsdis-print-bytes turn on instruction byte output"); + tty->print_cr("combined options: %s", options()); + } +} + +address decode_env::handle_event(const char* event, address arg) { + if (match(event, "insn")) { + start_insn(arg); + } else if (match(event, "/insn")) { + end_insn(arg); + } else if (match(event, "addr")) { + if (arg != NULL) { + print_address(arg); + return arg; + } + } else if (match(event, "mach")) { + output()->print_cr("[Disassembling for mach='%s']", arg); + } else if (match(event, "format bytes-per-line")) { + _bytes_per_line = (int) (intptr_t) arg; + } else { + // ignore unrecognized markup + } + return NULL; +} + +// called by the disassembler to print out jump targets and data addresses +void decode_env::print_address(address adr) { + outputStream* st = _output; + + if (adr == NULL) { + st->print("NULL"); + return; + } + + int small_num = (int)(intptr_t)adr; + if ((intptr_t)adr == (intptr_t)small_num + && -1 <= small_num && small_num <= 9) { + st->print("%d", small_num); + return; + } + + if (Universe::is_fully_initialized()) { + if (StubRoutines::contains(adr)) { + StubCodeDesc* desc = StubCodeDesc::desc_for(adr); + if (desc == NULL) + desc = StubCodeDesc::desc_for(adr + frame::pc_return_offset); + if (desc != NULL) { + st->print("Stub::%s", desc->name()); + if (desc->begin() != adr) + st->print("%+d 0x%p",adr - desc->begin(), adr); + else if (WizardMode) st->print(" " INTPTR_FORMAT, adr); + return; + } + st->print("Stub:: " INTPTR_FORMAT, adr); + return; + } + + BarrierSet* bs = Universe::heap()->barrier_set(); + if (bs->kind() == BarrierSet::CardTableModRef && + adr == (address)((CardTableModRefBS*)(bs))->byte_map_base) { + st->print("word_map_base"); + if (WizardMode) st->print(" " INTPTR_FORMAT, (intptr_t)adr); + return; + } + + oop obj; + if (_nm != NULL + && (obj = _nm->embeddedOop_at(cur_insn())) != NULL + && (address) obj == adr) { + obj->print_value_on(st); + return; + } + } + + // Fall through to a simple numeral. + st->print(INTPTR_FORMAT, (intptr_t)adr); +} + +void decode_env::print_insn_labels() { + address p = cur_insn(); + outputStream* st = output(); + nmethod* nm = _nm; + if (nm != NULL) { + if (p == nm->entry_point()) st->print_cr("[Entry Point]"); + if (p == nm->verified_entry_point()) st->print_cr("[Verified Entry Point]"); + if (p == nm->exception_begin()) st->print_cr("[Exception Handler]"); + if (p == nm->stub_begin()) st->print_cr("[Stub Code]"); + if (p == nm->consts_begin()) st->print_cr("[Constants]"); + } + CodeBlob* cb = _code; + if (cb != NULL) { + cb->print_block_comment(st, (intptr_t)(p - cb->instructions_begin())); + } + if (_print_pc) { + st->print(" " INTPTR_FORMAT ": ", (intptr_t) p); + } +} + +void decode_env::print_insn_bytes(address pc, address pc_limit) { + outputStream* st = output(); + size_t incr = 1; + size_t perline = _bytes_per_line; + if ((size_t) Disassembler::pd_instruction_alignment() >= sizeof(int) + && !((uintptr_t)pc % sizeof(int)) + && !((uintptr_t)pc_limit % sizeof(int))) { + incr = sizeof(int); + if (perline % incr) perline += incr - (perline % incr); + } + while (pc < pc_limit) { + // tab to the desired column: + st->move_to(COMMENT_COLUMN); + address pc0 = pc; + address pc1 = pc + perline; + if (pc1 > pc_limit) pc1 = pc_limit; + for (; pc < pc1; pc += incr) { + if (pc == pc0) + st->print(BYTES_COMMENT); + else if ((uint)(pc - pc0) % sizeof(int) == 0) + st->print(" "); // put out a space on word boundaries + if (incr == sizeof(int)) + st->print("%08lx", *(int*)pc); + else st->print("%02x", (*pc)&0xFF); + } + st->cr(); + } +} + + +static void* event_to_env(void* env_pv, const char* event, void* arg) { + decode_env* env = (decode_env*) env_pv; + return env->handle_event(event, (address) arg); +} + +static int printf_to_env(void* env_pv, const char* format, ...) { + decode_env* env = (decode_env*) env_pv; + outputStream* st = env->output(); + size_t flen = strlen(format); + const char* raw = NULL; + if (flen == 0) return 0; + if (flen == 1 && format[0] == '\n') { st->bol(); return 1; } + if (flen < 2 || + strchr(format, '%') == NULL) { + raw = format; + } else if (format[0] == '%' && format[1] == '%' && + strchr(format+2, '%') == NULL) { + // happens a lot on machines with names like %foo + flen--; + raw = format+1; + } + if (raw != NULL) { + st->print_raw(raw, (int) flen); + return (int) flen; + } + va_list ap; + va_start(ap, format); + julong cnt0 = st->count(); + st->vprint(format, ap); + julong cnt1 = st->count(); + va_end(ap); + return (int)(cnt1 - cnt0); +} + +address decode_env::decode_instructions(address start, address end) { + _start = start; _end = end; + + assert((((intptr_t)start | (intptr_t)end) % Disassembler::pd_instruction_alignment() == 0), "misaligned insn addr"); + + const int show_bytes = false; // for disassembler debugging + + //_version = Disassembler::pd_cpu_version(); + + if (!Disassembler::can_decode()) { + return NULL; + } + + // decode a series of instructions and return the end of the last instruction + + if (_print_raw) { + // Print whatever the library wants to print, w/o fancy callbacks. + // This is mainly for debugging the library itself. + FILE* out = stdout; + FILE* xmlout = (_print_raw > 1 ? out : NULL); + return (address) + (*Disassembler::_decode_instructions)(start, end, + NULL, (void*) xmlout, + NULL, (void*) out, + options()); + } + + return (address) + (*Disassembler::_decode_instructions)(start, end, + &event_to_env, (void*) this, + &printf_to_env, (void*) this, + options()); +} + + +void Disassembler::decode(CodeBlob* cb, outputStream* st) { + if (!load_library()) return; + decode_env env(cb, st); + env.output()->print_cr("Decoding CodeBlob " INTPTR_FORMAT, cb); + env.decode_instructions(cb->instructions_begin(), cb->instructions_end()); +} + + +void Disassembler::decode(address start, address end, outputStream* st) { + if (!load_library()) return; + decode_env env(CodeCache::find_blob_unsafe(start), st); + env.decode_instructions(start, end); +} + +void Disassembler::decode(nmethod* nm, outputStream* st) { + if (!load_library()) return; + decode_env env(nm, st); + env.output()->print_cr("Decoding compiled method " INTPTR_FORMAT ":", nm); + env.output()->print_cr("Code:"); + + unsigned char* p = nm->instructions_begin(); + unsigned char* end = nm->instructions_end(); + + // If there has been profiling, print the buckets. + if (FlatProfiler::bucket_start_for(p) != NULL) { + unsigned char* p1 = p; + int total_bucket_count = 0; + while (p1 < end) { + unsigned char* p0 = p1; + p1 += pd_instruction_alignment(); + address bucket_pc = FlatProfiler::bucket_start_for(p1); + if (bucket_pc != NULL && bucket_pc > p0 && bucket_pc <= p1) + total_bucket_count += FlatProfiler::bucket_count_for(p0); + } + env.set_total_ticks(total_bucket_count); + } + + env.decode_instructions(p, end); +} diff --git a/hotspot/src/share/vm/compiler/disassembler.hpp b/hotspot/src/share/vm/compiler/disassembler.hpp new file mode 100644 index 00000000000..670355f070d --- /dev/null +++ b/hotspot/src/share/vm/compiler/disassembler.hpp @@ -0,0 +1,59 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +class decode_env; + +// The disassembler prints out assembly code annotated +// with Java specific information. + +class Disassembler { + friend class decode_env; + private: + // this is the type of the dll entry point: + typedef void* (*decode_func)(void* start, void* end, + void* (*event_callback)(void*, const char*, void*), + void* event_stream, + int (*printf_callback)(void*, const char*, ...), + void* printf_stream, + const char* options); + // points to the library. + static void* _library; + // bailout + static bool _tried_to_load_library; + // points to the decode function. + static decode_func _decode_instructions; + // tries to load library and return whether it succedded. + static bool load_library(); + + // Machine dependent stuff + #include "incls/_disassembler_pd.hpp.incl" + + public: + static bool can_decode() { + return (_decode_instructions != NULL) || load_library(); + } + static void decode(CodeBlob *cb, outputStream* st = NULL); + static void decode(nmethod* nm, outputStream* st = NULL); + static void decode(address begin, address end, outputStream* st = NULL); +}; diff --git a/hotspot/src/share/vm/compiler/oopMap.cpp b/hotspot/src/share/vm/compiler/oopMap.cpp index b4a85f787f8..2984d647ea8 100644 --- a/hotspot/src/share/vm/compiler/oopMap.cpp +++ b/hotspot/src/share/vm/compiler/oopMap.cpp @@ -169,11 +169,8 @@ void OopMap::set_value(VMReg reg) { } -void OopMap::set_dead(VMReg reg) { - // At this time, we only need dead entries in our OopMap when ZapDeadCompiledLocals is active. - if (ZapDeadCompiledLocals) { - set_xxx(reg, OopMapValue::dead_value, VMRegImpl::Bad()); - } +void OopMap::set_narrowoop(VMReg reg) { + set_xxx(reg, OopMapValue::narrowoop_value, VMRegImpl::Bad()); } @@ -305,7 +302,9 @@ OopMap* OopMapSet::find_map_at_offset(int pc_offset) const { } class DoNothingClosure: public OopClosure { -public: void do_oop(oop* p) {} + public: + void do_oop(oop* p) {} + void do_oop(narrowOop* p) {} }; static DoNothingClosure do_nothing; @@ -349,23 +348,21 @@ static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) { void OopMapSet::oops_do(const frame *fr, const RegisterMap* reg_map, OopClosure* f) { // add derived oops to a table - all_do(fr, reg_map, f, add_derived_oop, &do_nothing, &do_nothing); + all_do(fr, reg_map, f, add_derived_oop, &do_nothing); } void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map, OopClosure* oop_fn, void derived_oop_fn(oop*, oop*), - OopClosure* value_fn, OopClosure* dead_fn) { + OopClosure* value_fn) { CodeBlob* cb = fr->cb(); - { - assert(cb != NULL, "no codeblob"); - } + assert(cb != NULL, "no codeblob"); NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);) OopMapSet* maps = cb->oop_maps(); - OopMap* map = cb->oop_map_for_return_address(fr->pc()); - assert(map != NULL, " no ptr map found"); + OopMap* map = cb->oop_map_for_return_address(fr->pc()); + assert(map != NULL, "no ptr map found"); // handle derived pointers first (otherwise base pointer may be // changed before derived pointer offset has been collected) @@ -393,8 +390,8 @@ void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map, } } - // We want dead, value and oop oop_types - int mask = OopMapValue::oop_value | OopMapValue::value_value | OopMapValue::dead_value; + // We want coop, value and oop oop_types + int mask = OopMapValue::oop_value | OopMapValue::value_value | OopMapValue::narrowoop_value; { for (OopMapStream oms(map,mask); !oms.is_done(); oms.next()) { omv = oms.current(); @@ -402,11 +399,15 @@ void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map, if ( loc != NULL ) { if ( omv.type() == OopMapValue::oop_value ) { #ifdef ASSERT - if (COMPILER2_PRESENT(!DoEscapeAnalysis &&) !Universe::heap()->is_in_or_null(*loc)) { + if (COMPILER2_PRESENT(!DoEscapeAnalysis &&) + (((uintptr_t)loc & (sizeof(*loc)-1)) != 0) || + !Universe::heap()->is_in_or_null(*loc)) { tty->print_cr("# Found non oop pointer. Dumping state at failure"); // try to dump out some helpful debugging information trace_codeblob_maps(fr, reg_map); omv.print(); + tty->print_cr("register r"); + omv.reg()->print(); tty->print_cr("loc = %p *loc = %p\n", loc, (address)*loc); // do the real assert. assert(Universe::heap()->is_in_or_null(*loc), "found non oop pointer"); @@ -415,8 +416,17 @@ void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map, oop_fn->do_oop(loc); } else if ( omv.type() == OopMapValue::value_value ) { value_fn->do_oop(loc); - } else if ( omv.type() == OopMapValue::dead_value ) { - dead_fn->do_oop(loc); + } else if ( omv.type() == OopMapValue::narrowoop_value ) { + narrowOop *nl = (narrowOop*)loc; +#ifndef VM_LITTLE_ENDIAN + if (!omv.reg()->is_stack()) { + // compressed oops in registers only take up 4 bytes of an + // 8 byte register but they are in the wrong part of the + // word so adjust loc to point at the right place. + nl = (narrowOop*)((address)nl + 4); + } +#endif + oop_fn->do_oop(nl); } } } @@ -505,8 +515,13 @@ bool OopMap::has_derived_pointer() const { #endif // COMPILER2 } +#endif //PRODUCT -static void print_register_type(OopMapValue::oop_types x, VMReg optional, outputStream* st) { +// Printing code is present in product build for -XX:+PrintAssembly. + +static +void print_register_type(OopMapValue::oop_types x, VMReg optional, + outputStream* st) { switch( x ) { case OopMapValue::oop_value: st->print("Oop"); @@ -514,8 +529,8 @@ static void print_register_type(OopMapValue::oop_types x, VMReg optional, output case OopMapValue::value_value: st->print("Value" ); break; - case OopMapValue::dead_value: - st->print("Dead" ); + case OopMapValue::narrowoop_value: + tty->print("NarrowOop" ); break; case OopMapValue::callee_saved_value: st->print("Callers_" ); @@ -544,10 +559,12 @@ void OopMapValue::print_on(outputStream* st) const { void OopMap::print_on(outputStream* st) const { OopMapValue omv; + st->print("OopMap{"); for(OopMapStream oms((OopMap*)this); !oms.is_done(); oms.next()) { omv = oms.current(); omv.print_on(st); } + st->print("off=%d}", (int) offset()); } @@ -558,12 +575,12 @@ void OopMapSet::print_on(outputStream* st) const { for( i = 0; i < len; i++) { OopMap* m = at(i); - st->print_cr("OopMap #%d offset:%p",i,m->offset()); + st->print_cr("#%d ",i); m->print_on(st); - st->print_cr("\n"); + st->cr(); } } -#endif // !PRODUCT + //------------------------------DerivedPointerTable--------------------------- diff --git a/hotspot/src/share/vm/compiler/oopMap.hpp b/hotspot/src/share/vm/compiler/oopMap.hpp index 8b678368247..ac05d570c04 100644 --- a/hotspot/src/share/vm/compiler/oopMap.hpp +++ b/hotspot/src/share/vm/compiler/oopMap.hpp @@ -61,7 +61,7 @@ public: unused_value =0, // powers of 2, for masking OopMapStream oop_value = 1, value_value = 2, - dead_value = 4, + narrowoop_value = 4, callee_saved_value = 8, derived_oop_value= 16, stack_obj = 32 }; @@ -90,14 +90,14 @@ public: // Querying bool is_oop() { return mask_bits(value(), type_mask_in_place) == oop_value; } bool is_value() { return mask_bits(value(), type_mask_in_place) == value_value; } - bool is_dead() { return mask_bits(value(), type_mask_in_place) == dead_value; } + bool is_narrowoop() { return mask_bits(value(), type_mask_in_place) == narrowoop_value; } bool is_callee_saved() { return mask_bits(value(), type_mask_in_place) == callee_saved_value; } bool is_derived_oop() { return mask_bits(value(), type_mask_in_place) == derived_oop_value; } bool is_stack_obj() { return mask_bits(value(), type_mask_in_place) == stack_obj; } void set_oop() { set_value((value() & register_mask_in_place) | oop_value); } void set_value() { set_value((value() & register_mask_in_place) | value_value); } - void set_dead() { set_value((value() & register_mask_in_place) | dead_value); } + void set_narrowoop() { set_value((value() & register_mask_in_place) | narrowoop_value); } void set_callee_saved() { set_value((value() & register_mask_in_place) | callee_saved_value); } void set_derived_oop() { set_value((value() & register_mask_in_place) | derived_oop_value); } void set_stack_obj() { set_value((value() & register_mask_in_place) | stack_obj); } @@ -129,7 +129,7 @@ public: return reg()->reg2stack(); } - void print_on(outputStream* st) const PRODUCT_RETURN; + void print_on(outputStream* st) const; void print() const { print_on(tty); } }; @@ -176,6 +176,7 @@ class OopMap: public ResourceObj { // slots to hold 4-byte values like ints and floats in the LP64 build. void set_oop ( VMReg local); void set_value( VMReg local); + void set_narrowoop(VMReg local); void set_dead ( VMReg local); void set_callee_saved( VMReg local, VMReg caller_machine_register ); void set_derived_oop ( VMReg local, VMReg derived_from_local_register ); @@ -193,7 +194,7 @@ class OopMap: public ResourceObj { } // Printing - void print_on(outputStream* st) const PRODUCT_RETURN; + void print_on(outputStream* st) const; void print() const { print_on(tty); } }; @@ -245,10 +246,10 @@ class OopMapSet : public ResourceObj { static void all_do(const frame* fr, const RegisterMap* reg_map, OopClosure* oop_fn, void derived_oop_fn(oop* base, oop* derived), - OopClosure* value_fn, OopClosure* dead_fn); + OopClosure* value_fn); // Printing - void print_on(outputStream* st) const PRODUCT_RETURN; + void print_on(outputStream* st) const; void print() const { print_on(tty); } }; diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp index 1c6d7a54855..3115b6b1127 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp @@ -29,22 +29,34 @@ class ConcurrentMarkSweepGeneration; class CMSBitMap; class CMSMarkStack; class CMSCollector; -template class GenericTaskQueue; -typedef GenericTaskQueue OopTaskQueue; -template class GenericTaskQueueSet; -typedef GenericTaskQueueSet OopTaskQueueSet; class MarkFromRootsClosure; class Par_MarkFromRootsClosure; +// Decode the oop and call do_oop on it. +#define DO_OOP_WORK_DEFN \ + void do_oop(oop obj); \ + template inline void do_oop_work(T* p) { \ + T heap_oop = oopDesc::load_heap_oop(p); \ + if (!oopDesc::is_null(heap_oop)) { \ + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); \ + do_oop(obj); \ + } \ + } + class MarkRefsIntoClosure: public OopsInGenClosure { - const MemRegion _span; - CMSBitMap* _bitMap; - const bool _should_do_nmethods; + private: + const MemRegion _span; + CMSBitMap* _bitMap; + const bool _should_do_nmethods; + protected: + DO_OOP_WORK_DEFN public: MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap, bool should_do_nmethods); - void do_oop(oop* p); - void do_oop_nv(oop* p) { MarkRefsIntoClosure::do_oop(p); } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p) { MarkRefsIntoClosure::do_oop_work(p); } + inline void do_oop_nv(narrowOop* p) { MarkRefsIntoClosure::do_oop_work(p); } bool do_header() { return true; } virtual const bool do_nmethods() const { return _should_do_nmethods; @@ -57,15 +69,20 @@ class MarkRefsIntoClosure: public OopsInGenClosure { // A variant of the above used in certain kinds of CMS // marking verification. class MarkRefsIntoVerifyClosure: public OopsInGenClosure { - const MemRegion _span; - CMSBitMap* _verification_bm; - CMSBitMap* _cms_bm; - const bool _should_do_nmethods; + private: + const MemRegion _span; + CMSBitMap* _verification_bm; + CMSBitMap* _cms_bm; + const bool _should_do_nmethods; + protected: + DO_OOP_WORK_DEFN public: MarkRefsIntoVerifyClosure(MemRegion span, CMSBitMap* verification_bm, CMSBitMap* cms_bm, bool should_do_nmethods); - void do_oop(oop* p); - void do_oop_nv(oop* p) { MarkRefsIntoVerifyClosure::do_oop(p); } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p) { MarkRefsIntoVerifyClosure::do_oop_work(p); } + inline void do_oop_nv(narrowOop* p) { MarkRefsIntoVerifyClosure::do_oop_work(p); } bool do_header() { return true; } virtual const bool do_nmethods() const { return _should_do_nmethods; @@ -75,37 +92,40 @@ class MarkRefsIntoVerifyClosure: public OopsInGenClosure { } }; - // The non-parallel version (the parallel version appears further below). class PushAndMarkClosure: public OopClosure { - CMSCollector* _collector; - MemRegion _span; - CMSBitMap* _bit_map; - CMSBitMap* _mod_union_table; - CMSMarkStack* _mark_stack; - CMSMarkStack* _revisit_stack; - bool _concurrent_precleaning; - bool const _should_remember_klasses; + private: + CMSCollector* _collector; + MemRegion _span; + CMSBitMap* _bit_map; + CMSBitMap* _mod_union_table; + CMSMarkStack* _mark_stack; + CMSMarkStack* _revisit_stack; + bool _concurrent_precleaning; + bool const _should_remember_klasses; + protected: + DO_OOP_WORK_DEFN public: PushAndMarkClosure(CMSCollector* collector, MemRegion span, ReferenceProcessor* rp, CMSBitMap* bit_map, CMSBitMap* mod_union_table, - CMSMarkStack* mark_stack, - CMSMarkStack* revisit_stack, - bool concurrent_precleaning); - - void do_oop(oop* p); - void do_oop_nv(oop* p) { PushAndMarkClosure::do_oop(p); } + CMSMarkStack* mark_stack, + CMSMarkStack* revisit_stack, + bool concurrent_precleaning); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p) { PushAndMarkClosure::do_oop_work(p); } + inline void do_oop_nv(narrowOop* p) { PushAndMarkClosure::do_oop_work(p); } bool do_header() { return true; } Prefetch::style prefetch_style() { return Prefetch::do_read; } - const bool should_remember_klasses() const { + virtual const bool should_remember_klasses() const { return _should_remember_klasses; } - void remember_klass(Klass* k); + virtual void remember_klass(Klass* k); }; // In the parallel case, the revisit stack, the bit map and the @@ -115,12 +135,15 @@ class PushAndMarkClosure: public OopClosure { // used in the non-parallel case above is here replaced with // an OopTaskQueue structure to allow efficient work stealing. class Par_PushAndMarkClosure: public OopClosure { - CMSCollector* _collector; - MemRegion _span; - CMSBitMap* _bit_map; - OopTaskQueue* _work_queue; - CMSMarkStack* _revisit_stack; - bool const _should_remember_klasses; + private: + CMSCollector* _collector; + MemRegion _span; + CMSBitMap* _bit_map; + OopTaskQueue* _work_queue; + CMSMarkStack* _revisit_stack; + bool const _should_remember_klasses; + protected: + DO_OOP_WORK_DEFN public: Par_PushAndMarkClosure(CMSCollector* collector, MemRegion span, @@ -128,43 +151,48 @@ class Par_PushAndMarkClosure: public OopClosure { CMSBitMap* bit_map, OopTaskQueue* work_queue, CMSMarkStack* revisit_stack); - - void do_oop(oop* p); - void do_oop_nv(oop* p) { Par_PushAndMarkClosure::do_oop(p); } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p) { Par_PushAndMarkClosure::do_oop_work(p); } + inline void do_oop_nv(narrowOop* p) { Par_PushAndMarkClosure::do_oop_work(p); } bool do_header() { return true; } Prefetch::style prefetch_style() { return Prefetch::do_read; } - const bool should_remember_klasses() const { + virtual const bool should_remember_klasses() const { return _should_remember_klasses; } - void remember_klass(Klass* k); + virtual void remember_klass(Klass* k); }; - // The non-parallel version (the parallel version appears further below). class MarkRefsIntoAndScanClosure: public OopsInGenClosure { - MemRegion _span; - CMSBitMap* _bit_map; - CMSMarkStack* _mark_stack; - PushAndMarkClosure _pushAndMarkClosure; - CMSCollector* _collector; - bool _yield; + private: + MemRegion _span; + CMSBitMap* _bit_map; + CMSMarkStack* _mark_stack; + PushAndMarkClosure _pushAndMarkClosure; + CMSCollector* _collector; + Mutex* _freelistLock; + bool _yield; // Whether closure is being used for concurrent precleaning - bool _concurrent_precleaning; - Mutex* _freelistLock; + bool _concurrent_precleaning; + protected: + DO_OOP_WORK_DEFN public: MarkRefsIntoAndScanClosure(MemRegion span, ReferenceProcessor* rp, CMSBitMap* bit_map, CMSBitMap* mod_union_table, - CMSMarkStack* mark_stack, - CMSMarkStack* revisit_stack, + CMSMarkStack* mark_stack, + CMSMarkStack* revisit_stack, CMSCollector* collector, bool should_yield, bool concurrent_precleaning); - void do_oop(oop* p); - void do_oop_nv(oop* p) { MarkRefsIntoAndScanClosure::do_oop(p); } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); } + inline void do_oop_nv(narrowOop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); } bool do_header() { return true; } virtual const bool do_nmethods() const { return true; } Prefetch::style prefetch_style() { @@ -185,11 +213,14 @@ class MarkRefsIntoAndScanClosure: public OopsInGenClosure { // sycnhronized. An OopTaskQueue structure, supporting efficient // workstealing, replaces a CMSMarkStack for storing grey objects. class Par_MarkRefsIntoAndScanClosure: public OopsInGenClosure { - MemRegion _span; - CMSBitMap* _bit_map; - OopTaskQueue* _work_queue; - const uint _low_water_mark; - Par_PushAndMarkClosure _par_pushAndMarkClosure; + private: + MemRegion _span; + CMSBitMap* _bit_map; + OopTaskQueue* _work_queue; + const uint _low_water_mark; + Par_PushAndMarkClosure _par_pushAndMarkClosure; + protected: + DO_OOP_WORK_DEFN public: Par_MarkRefsIntoAndScanClosure(CMSCollector* collector, MemRegion span, @@ -197,8 +228,10 @@ class Par_MarkRefsIntoAndScanClosure: public OopsInGenClosure { CMSBitMap* bit_map, OopTaskQueue* work_queue, CMSMarkStack* revisit_stack); - void do_oop(oop* p); - void do_oop_nv(oop* p) { Par_MarkRefsIntoAndScanClosure::do_oop(p); } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); } + inline void do_oop_nv(narrowOop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); } bool do_header() { return true; } virtual const bool do_nmethods() const { return true; } Prefetch::style prefetch_style() { @@ -211,28 +244,34 @@ class Par_MarkRefsIntoAndScanClosure: public OopsInGenClosure { // following the first checkpoint. Its use is buried in // the closure MarkFromRootsClosure. class PushOrMarkClosure: public OopClosure { - CMSCollector* _collector; - MemRegion _span; - CMSBitMap* _bitMap; - CMSMarkStack* _markStack; - CMSMarkStack* _revisitStack; - HeapWord* const _finger; - MarkFromRootsClosure* const _parent; - bool const _should_remember_klasses; + private: + CMSCollector* _collector; + MemRegion _span; + CMSBitMap* _bitMap; + CMSMarkStack* _markStack; + CMSMarkStack* _revisitStack; + HeapWord* const _finger; + MarkFromRootsClosure* const + _parent; + bool const _should_remember_klasses; + protected: + DO_OOP_WORK_DEFN public: PushOrMarkClosure(CMSCollector* cms_collector, MemRegion span, CMSBitMap* bitMap, - CMSMarkStack* markStack, - CMSMarkStack* revisitStack, - HeapWord* finger, + CMSMarkStack* markStack, + CMSMarkStack* revisitStack, + HeapWord* finger, MarkFromRootsClosure* parent); - void do_oop(oop* p); - void do_oop_nv(oop* p) { PushOrMarkClosure::do_oop(p); } - const bool should_remember_klasses() const { + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p) { PushOrMarkClosure::do_oop_work(p); } + inline void do_oop_nv(narrowOop* p) { PushOrMarkClosure::do_oop_work(p); } + virtual const bool should_remember_klasses() const { return _should_remember_klasses; } - void remember_klass(Klass* k); + virtual void remember_klass(Klass* k); // Deal with a stack overflow condition void handle_stack_overflow(HeapWord* lost); private: @@ -244,6 +283,7 @@ class PushOrMarkClosure: public OopClosure { // following the first checkpoint. Its use is buried in // the closure Par_MarkFromRootsClosure. class Par_PushOrMarkClosure: public OopClosure { + private: CMSCollector* _collector; MemRegion _whole_span; MemRegion _span; // local chunk @@ -253,24 +293,29 @@ class Par_PushOrMarkClosure: public OopClosure { CMSMarkStack* _revisit_stack; HeapWord* const _finger; HeapWord** const _global_finger_addr; - Par_MarkFromRootsClosure* const _parent; - bool const _should_remember_klasses; + Par_MarkFromRootsClosure* const + _parent; + bool const _should_remember_klasses; + protected: + DO_OOP_WORK_DEFN public: Par_PushOrMarkClosure(CMSCollector* cms_collector, - MemRegion span, - CMSBitMap* bit_map, - OopTaskQueue* work_queue, - CMSMarkStack* mark_stack, - CMSMarkStack* revisit_stack, - HeapWord* finger, - HeapWord** global_finger_addr, - Par_MarkFromRootsClosure* parent); - void do_oop(oop* p); - void do_oop_nv(oop* p) { Par_PushOrMarkClosure::do_oop(p); } - const bool should_remember_klasses() const { + MemRegion span, + CMSBitMap* bit_map, + OopTaskQueue* work_queue, + CMSMarkStack* mark_stack, + CMSMarkStack* revisit_stack, + HeapWord* finger, + HeapWord** global_finger_addr, + Par_MarkFromRootsClosure* parent); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p) { Par_PushOrMarkClosure::do_oop_work(p); } + inline void do_oop_nv(narrowOop* p) { Par_PushOrMarkClosure::do_oop_work(p); } + virtual const bool should_remember_klasses() const { return _should_remember_klasses; } - void remember_klass(Klass* k); + virtual void remember_klass(Klass* k); // Deal with a stack overflow condition void handle_stack_overflow(HeapWord* lost); private: @@ -282,27 +327,36 @@ class Par_PushOrMarkClosure: public OopClosure { // This is currently used during the (weak) reference object // processing phase of the CMS final checkpoint step. class CMSKeepAliveClosure: public OopClosure { + private: CMSCollector* _collector; - MemRegion _span; + const MemRegion _span; CMSMarkStack* _mark_stack; CMSBitMap* _bit_map; + protected: + DO_OOP_WORK_DEFN public: CMSKeepAliveClosure(CMSCollector* collector, MemRegion span, CMSBitMap* bit_map, CMSMarkStack* mark_stack): _collector(collector), _span(span), _bit_map(bit_map), - _mark_stack(mark_stack) { } - - void do_oop(oop* p); - void do_oop_nv(oop* p) { CMSKeepAliveClosure::do_oop(p); } + _mark_stack(mark_stack) { + assert(!_span.is_empty(), "Empty span could spell trouble"); + } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p) { CMSKeepAliveClosure::do_oop_work(p); } + inline void do_oop_nv(narrowOop* p) { CMSKeepAliveClosure::do_oop_work(p); } }; class CMSInnerParMarkAndPushClosure: public OopClosure { + private: CMSCollector* _collector; MemRegion _span; OopTaskQueue* _work_queue; CMSBitMap* _bit_map; + protected: + DO_OOP_WORK_DEFN public: CMSInnerParMarkAndPushClosure(CMSCollector* collector, MemRegion span, CMSBitMap* bit_map, @@ -311,24 +365,32 @@ class CMSInnerParMarkAndPushClosure: public OopClosure { _span(span), _bit_map(bit_map), _work_queue(work_queue) { } - void do_oop(oop* p); - void do_oop_nv(oop* p) { CMSInnerParMarkAndPushClosure::do_oop(p); } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(p); } + inline void do_oop_nv(narrowOop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(p); } }; // A parallel (MT) version of the above, used when // reference processing is parallel; the only difference // is in the do_oop method. class CMSParKeepAliveClosure: public OopClosure { + private: CMSCollector* _collector; MemRegion _span; OopTaskQueue* _work_queue; CMSBitMap* _bit_map; - CMSInnerParMarkAndPushClosure _mark_and_push; + CMSInnerParMarkAndPushClosure + _mark_and_push; const uint _low_water_mark; void trim_queue(uint max); + protected: + DO_OOP_WORK_DEFN public: CMSParKeepAliveClosure(CMSCollector* collector, MemRegion span, CMSBitMap* bit_map, OopTaskQueue* work_queue); - void do_oop(oop* p); - void do_oop_nv(oop* p) { CMSParKeepAliveClosure::do_oop(p); } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p) { CMSParKeepAliveClosure::do_oop_work(p); } + inline void do_oop_nv(narrowOop* p) { CMSParKeepAliveClosure::do_oop_work(p); } }; diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.cpp index ead077be1e3..9fd85d6b4f1 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.cpp @@ -44,52 +44,12 @@ HeapWord* CMSPermGen::mem_allocate(size_t size) { bool lock_owned = lock->owned_by_self(); if (lock_owned) { MutexUnlocker mul(lock); - return mem_allocate_work(size); + return mem_allocate_in_gen(size, _gen); } else { - return mem_allocate_work(size); + return mem_allocate_in_gen(size, _gen); } } -HeapWord* CMSPermGen::mem_allocate_work(size_t size) { - assert(!_gen->freelistLock()->owned_by_self(), "Potetntial deadlock"); - - MutexLocker ml(Heap_lock); - HeapWord* obj = NULL; - - obj = _gen->allocate(size, false); - // Since we want to minimize pause times, we will prefer - // expanding the perm gen rather than doing a stop-world - // collection to satisfy the allocation request. - if (obj == NULL) { - // Try to expand the perm gen and allocate space. - obj = _gen->expand_and_allocate(size, false, false); - if (obj == NULL) { - // Let's see if a normal stop-world full collection will - // free up enough space. - SharedHeap::heap()->collect_locked(GCCause::_permanent_generation_full); - obj = _gen->allocate(size, false); - if (obj == NULL) { - // The collection above may have shrunk the space, so try - // to expand again and allocate space. - obj = _gen->expand_and_allocate(size, false, false); - } - if (obj == NULL) { - // We have not been able to allocate space despite a - // full stop-world collection. We now make a last-ditch collection - // attempt (in which soft refs are all aggressively freed) - // that will try to reclaim as much space as possible. - SharedHeap::heap()->collect_locked(GCCause::_last_ditch_collection); - obj = _gen->allocate(size, false); - if (obj == NULL) { - // Expand generation in case it was shrunk following the collection. - obj = _gen->expand_and_allocate(size, false, false); - } - } - } - } - return obj; -} - void CMSPermGen::compute_new_size() { _gen->compute_new_size(); } diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.hpp index e7b7096f89c..8e1d07760ab 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsPermGen.hpp @@ -29,7 +29,6 @@ class ConcurrentMarkSweepGeneration; class CMSPermGen: public PermGen { friend class VMStructs; - HeapWord* mem_allocate_work(size_t size); protected: // The "generation" view. ConcurrentMarkSweepGeneration* _gen; diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index de5611ddb7b..09d0db5e02b 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -177,7 +177,7 @@ HeapWord* CompactibleFreeListSpace::forward(oop q, size_t size, assert(q->forwardee() == NULL, "should be forwarded to NULL"); } - debug_only(MarkSweep::register_live_oop(q, adjusted_size)); + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::register_live_oop(q, adjusted_size)); compact_top += adjusted_size; // we need to update the offset table so that the beginnings of objects can be @@ -1211,7 +1211,7 @@ FreeChunk* CompactibleFreeListSpace::allocateScratch(size_t size) { return fc; } -oop CompactibleFreeListSpace::promote(oop obj, size_t obj_size, oop* ref) { +oop CompactibleFreeListSpace::promote(oop obj, size_t obj_size) { assert(obj_size == (size_t)obj->size(), "bad obj_size passed in"); assert_locked(); @@ -2116,7 +2116,6 @@ void CompactibleFreeListSpace::split(size_t from, size_t to1) { splitBirth(to2); } - void CompactibleFreeListSpace::print() const { tty->print(" CompactibleFreeListSpace"); Space::print(); @@ -2130,6 +2129,7 @@ void CompactibleFreeListSpace::prepare_for_verify() { } class VerifyAllBlksClosure: public BlkClosure { + private: const CompactibleFreeListSpace* _sp; const MemRegion _span; @@ -2137,7 +2137,7 @@ class VerifyAllBlksClosure: public BlkClosure { VerifyAllBlksClosure(const CompactibleFreeListSpace* sp, MemRegion span) : _sp(sp), _span(span) { } - size_t do_blk(HeapWord* addr) { + virtual size_t do_blk(HeapWord* addr) { size_t res; if (_sp->block_is_obj(addr)) { oop p = oop(addr); @@ -2160,12 +2160,54 @@ class VerifyAllBlksClosure: public BlkClosure { }; class VerifyAllOopsClosure: public OopClosure { + private: const CMSCollector* _collector; const CompactibleFreeListSpace* _sp; const MemRegion _span; const bool _past_remark; const CMSBitMap* _bit_map; + protected: + void do_oop(void* p, oop obj) { + if (_span.contains(obj)) { // the interior oop points into CMS heap + if (!_span.contains(p)) { // reference from outside CMS heap + // Should be a valid object; the first disjunct below allows + // us to sidestep an assertion in block_is_obj() that insists + // that p be in _sp. Note that several generations (and spaces) + // are spanned by _span (CMS heap) above. + guarantee(!_sp->is_in_reserved(obj) || + _sp->block_is_obj((HeapWord*)obj), + "Should be an object"); + guarantee(obj->is_oop(), "Should be an oop"); + obj->verify(); + if (_past_remark) { + // Remark has been completed, the object should be marked + _bit_map->isMarked((HeapWord*)obj); + } + } else { // reference within CMS heap + if (_past_remark) { + // Remark has been completed -- so the referent should have + // been marked, if referring object is. + if (_bit_map->isMarked(_collector->block_start(p))) { + guarantee(_bit_map->isMarked((HeapWord*)obj), "Marking error?"); + } + } + } + } else if (_sp->is_in_reserved(p)) { + // the reference is from FLS, and points out of FLS + guarantee(obj->is_oop(), "Should be an oop"); + obj->verify(); + } + } + + template void do_oop_work(T* p) { + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + do_oop(p, obj); + } + } + public: VerifyAllOopsClosure(const CMSCollector* collector, const CompactibleFreeListSpace* sp, MemRegion span, @@ -2173,40 +2215,8 @@ class VerifyAllOopsClosure: public OopClosure { OopClosure(), _collector(collector), _sp(sp), _span(span), _past_remark(past_remark), _bit_map(bit_map) { } - void do_oop(oop* ptr) { - oop p = *ptr; - if (p != NULL) { - if (_span.contains(p)) { // the interior oop points into CMS heap - if (!_span.contains(ptr)) { // reference from outside CMS heap - // Should be a valid object; the first disjunct below allows - // us to sidestep an assertion in block_is_obj() that insists - // that p be in _sp. Note that several generations (and spaces) - // are spanned by _span (CMS heap) above. - guarantee(!_sp->is_in_reserved(p) || _sp->block_is_obj((HeapWord*)p), - "Should be an object"); - guarantee(p->is_oop(), "Should be an oop"); - p->verify(); - if (_past_remark) { - // Remark has been completed, the object should be marked - _bit_map->isMarked((HeapWord*)p); - } - } - else { // reference within CMS heap - if (_past_remark) { - // Remark has been completed -- so the referent should have - // been marked, if referring object is. - if (_bit_map->isMarked(_collector->block_start(ptr))) { - guarantee(_bit_map->isMarked((HeapWord*)p), "Marking error?"); - } - } - } - } else if (_sp->is_in_reserved(ptr)) { - // the reference is from FLS, and points out of FLS - guarantee(p->is_oop(), "Should be an oop"); - p->verify(); - } - } - } + virtual void do_oop(oop* p) { VerifyAllOopsClosure::do_oop_work(p); } + virtual void do_oop(narrowOop* p) { VerifyAllOopsClosure::do_oop_work(p); } }; void CompactibleFreeListSpace::verify(bool ignored) const { diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp index 5eb0f41b6a1..729556baecf 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp @@ -540,7 +540,7 @@ class CompactibleFreeListSpace: public CompactibleSpace { HeapWord* allocate(size_t size); HeapWord* par_allocate(size_t size); - oop promote(oop obj, size_t obj_size, oop* ref); + oop promote(oop obj, size_t obj_size); void gc_prologue(); void gc_epilogue(); diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index eff7a042e95..8ab7bdd1b58 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -225,6 +225,34 @@ ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration( assert(_dilatation_factor >= 1.0, "from previous assert"); } + +// The field "_initiating_occupancy" represents the occupancy percentage +// at which we trigger a new collection cycle. Unless explicitly specified +// via CMSInitiating[Perm]OccupancyFraction (argument "io" below), it +// is calculated by: +// +// Let "f" be MinHeapFreeRatio in +// +// _intiating_occupancy = 100-f + +// f * (CMSTrigger[Perm]Ratio/100) +// where CMSTrigger[Perm]Ratio is the argument "tr" below. +// +// That is, if we assume the heap is at its desired maximum occupancy at the +// end of a collection, we let CMSTrigger[Perm]Ratio of the (purported) free +// space be allocated before initiating a new collection cycle. +// +void ConcurrentMarkSweepGeneration::init_initiating_occupancy(intx io, intx tr) { + assert(io <= 100 && tr >= 0 && tr <= 100, "Check the arguments"); + if (io >= 0) { + _initiating_occupancy = (double)io / 100.0; + } else { + _initiating_occupancy = ((100 - MinHeapFreeRatio) + + (double)(tr * MinHeapFreeRatio) / 100.0) + / 100.0; + } +} + + void ConcurrentMarkSweepGeneration::ref_processor_init() { assert(collector() != NULL, "no collector"); collector()->ref_processor_init(); @@ -492,7 +520,10 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, -1 /* lock-free */, "No_lock" /* dummy */), _modUnionClosure(&_modUnionTable), _modUnionClosurePar(&_modUnionTable), - _is_alive_closure(&_markBitMap), + // Adjust my span to cover old (cms) gen and perm gen + _span(cmsGen->reserved()._union(permGen->reserved())), + // Construct the is_alive_closure with _span & markBitMap + _is_alive_closure(_span, &_markBitMap), _restart_addr(NULL), _overflow_list(NULL), _preserved_oop_stack(NULL), @@ -520,8 +551,8 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, _verification_mark_bm(0, Mutex::leaf + 1, "CMS_verification_mark_bm_lock"), _completed_initialization(false), _collector_policy(cp), - _unload_classes(false), - _unloaded_classes_last_cycle(false), + _should_unload_classes(false), + _concurrent_cycles_since_last_unload(0), _sweep_estimate(CMS_SweepWeight, CMS_SweepPadding) { if (ExplicitGCInvokesConcurrentAndUnloadsClasses) { @@ -544,11 +575,6 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, _cmsGen->cmsSpace()->set_collector(this); _permGen->cmsSpace()->set_collector(this); - // Adjust my span to cover old (cms) gen and perm gen - _span = _cmsGen->reserved()._union(_permGen->reserved()); - // Initialize the span of is_alive_closure - _is_alive_closure.set_span(_span); - // Allocate MUT and marking bit map { MutexLockerEx x(_markBitMap.lock(), Mutex::_no_safepoint_check_flag); @@ -642,26 +668,11 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, } } - // "initiatingOccupancy" is the occupancy ratio at which we trigger - // a new collection cycle. Unless explicitly specified via - // CMSTriggerRatio, it is calculated by: - // Let "f" be MinHeapFreeRatio in - // - // intiatingOccupancy = 100-f + - // f * (CMSTriggerRatio/100) - // That is, if we assume the heap is at its desired maximum occupancy at the - // end of a collection, we let CMSTriggerRatio of the (purported) free - // space be allocated before initiating a new collection cycle. - if (CMSInitiatingOccupancyFraction > 0) { - _initiatingOccupancy = (double)CMSInitiatingOccupancyFraction / 100.0; - } else { - _initiatingOccupancy = ((100 - MinHeapFreeRatio) + - (double)(CMSTriggerRatio * - MinHeapFreeRatio) / 100.0) - / 100.0; - } + _cmsGen ->init_initiating_occupancy(CMSInitiatingOccupancyFraction, CMSTriggerRatio); + _permGen->init_initiating_occupancy(CMSInitiatingPermOccupancyFraction, CMSTriggerPermRatio); + // Clip CMSBootstrapOccupancy between 0 and 100. - _bootstrap_occupancy = ((double)MIN2((intx)100, MAX2((intx)0, CMSBootstrapOccupancy))) + _bootstrap_occupancy = ((double)MIN2((uintx)100, MAX2((uintx)0, CMSBootstrapOccupancy))) /(double)100; _full_gcs_since_conc_gc = 0; @@ -1213,7 +1224,7 @@ CMSCollector::allocation_limit_reached(Space* space, HeapWord* top, return NULL; } -oop ConcurrentMarkSweepGeneration::promote(oop obj, size_t obj_size, oop* ref) { +oop ConcurrentMarkSweepGeneration::promote(oop obj, size_t obj_size) { assert(obj_size == (size_t)obj->size(), "bad obj_size passed in"); // allocate, copy and if necessary update promoinfo -- // delegate to underlying space. @@ -1225,7 +1236,7 @@ oop ConcurrentMarkSweepGeneration::promote(oop obj, size_t obj_size, oop* ref) { } #endif // #ifndef PRODUCT - oop res = _cmsSpace->promote(obj, obj_size, ref); + oop res = _cmsSpace->promote(obj, obj_size); if (res == NULL) { // expand and retry size_t s = _cmsSpace->expansionSpaceRequired(obj_size); // HeapWords @@ -1236,7 +1247,7 @@ oop ConcurrentMarkSweepGeneration::promote(oop obj, size_t obj_size, oop* ref) { assert(next_gen() == NULL, "assumption, based upon which no attempt " "is made to pass on a possibly failing " "promotion to next generation"); - res = _cmsSpace->promote(obj, obj_size, ref); + res = _cmsSpace->promote(obj, obj_size); } if (res != NULL) { // See comment in allocate() about when objects should @@ -1413,7 +1424,8 @@ bool CMSCollector::shouldConcurrentCollect() { gclog_or_tty->print_cr("promotion_rate=%g", stats().promotion_rate()); gclog_or_tty->print_cr("cms_allocation_rate=%g", stats().cms_allocation_rate()); gclog_or_tty->print_cr("occupancy=%3.7f", _cmsGen->occupancy()); - gclog_or_tty->print_cr("initiatingOccupancy=%3.7f", initiatingOccupancy()); + gclog_or_tty->print_cr("initiatingOccupancy=%3.7f", _cmsGen->initiating_occupancy()); + gclog_or_tty->print_cr("initiatingPermOccupancy=%3.7f", _permGen->initiating_occupancy()); } // ------------------------------------------------------------------ @@ -1446,22 +1458,36 @@ bool CMSCollector::shouldConcurrentCollect() { // old gen want a collection cycle started. Each may use // an appropriate criterion for making this decision. // XXX We need to make sure that the gen expansion - // criterion dovetails well with this. - if (_cmsGen->shouldConcurrentCollect(initiatingOccupancy())) { + // criterion dovetails well with this. XXX NEED TO FIX THIS + if (_cmsGen->should_concurrent_collect()) { if (Verbose && PrintGCDetails) { gclog_or_tty->print_cr("CMS old gen initiated"); } return true; } - if (cms_should_unload_classes() && - _permGen->shouldConcurrentCollect(initiatingOccupancy())) { - if (Verbose && PrintGCDetails) { - gclog_or_tty->print_cr("CMS perm gen initiated"); + // We start a collection if we believe an incremental collection may fail; + // this is not likely to be productive in practice because it's probably too + // late anyway. + GenCollectedHeap* gch = GenCollectedHeap::heap(); + assert(gch->collector_policy()->is_two_generation_policy(), + "You may want to check the correctness of the following"); + if (gch->incremental_collection_will_fail()) { + if (PrintGCDetails && Verbose) { + gclog_or_tty->print("CMSCollector: collect because incremental collection will fail "); } return true; } + if (CMSClassUnloadingEnabled && _permGen->should_concurrent_collect()) { + bool res = update_should_unload_classes(); + if (res) { + if (Verbose && PrintGCDetails) { + gclog_or_tty->print_cr("CMS perm gen initiated"); + } + return true; + } + } return false; } @@ -1471,32 +1497,36 @@ void CMSCollector::clear_expansion_cause() { _permGen->clear_expansion_cause(); } -bool ConcurrentMarkSweepGeneration::shouldConcurrentCollect( - double initiatingOccupancy) { - // We should be conservative in starting a collection cycle. To - // start too eagerly runs the risk of collecting too often in the - // extreme. To collect too rarely falls back on full collections, - // which works, even if not optimum in terms of concurrent work. - // As a work around for too eagerly collecting, use the flag - // UseCMSInitiatingOccupancyOnly. This also has the advantage of - // giving the user an easily understandable way of controlling the - // collections. - // We want to start a new collection cycle if any of the following - // conditions hold: - // . our current occupancy exceeds the initiating occupancy, or - // . we recently needed to expand and have not since that expansion, - // collected, or - // . we are not using adaptive free lists and linear allocation is - // going to fail, or - // . (for old gen) incremental collection has already failed or - // may soon fail in the near future as we may not be able to absorb - // promotions. - assert_lock_strong(freelistLock()); +// We should be conservative in starting a collection cycle. To +// start too eagerly runs the risk of collecting too often in the +// extreme. To collect too rarely falls back on full collections, +// which works, even if not optimum in terms of concurrent work. +// As a work around for too eagerly collecting, use the flag +// UseCMSInitiatingOccupancyOnly. This also has the advantage of +// giving the user an easily understandable way of controlling the +// collections. +// We want to start a new collection cycle if any of the following +// conditions hold: +// . our current occupancy exceeds the configured initiating occupancy +// for this generation, or +// . we recently needed to expand this space and have not, since that +// expansion, done a collection of this generation, or +// . the underlying space believes that it may be a good idea to initiate +// a concurrent collection (this may be based on criteria such as the +// following: the space uses linear allocation and linear allocation is +// going to fail, or there is believed to be excessive fragmentation in +// the generation, etc... or ... +// [.(currently done by CMSCollector::shouldConcurrentCollect() only for +// the case of the old generation, not the perm generation; see CR 6543076): +// we may be approaching a point at which allocation requests may fail because +// we will be out of sufficient free space given allocation rate estimates.] +bool ConcurrentMarkSweepGeneration::should_concurrent_collect() const { - if (occupancy() > initiatingOccupancy) { + assert_lock_strong(freelistLock()); + if (occupancy() > initiating_occupancy()) { if (PrintGCDetails && Verbose) { gclog_or_tty->print(" %s: collect because of occupancy %f / %f ", - short_name(), occupancy(), initiatingOccupancy); + short_name(), occupancy(), initiating_occupancy()); } return true; } @@ -1510,20 +1540,9 @@ bool ConcurrentMarkSweepGeneration::shouldConcurrentCollect( } return true; } - GenCollectedHeap* gch = GenCollectedHeap::heap(); - assert(gch->collector_policy()->is_two_generation_policy(), - "You may want to check the correctness of the following"); - if (gch->incremental_collection_will_fail()) { + if (_cmsSpace->should_concurrent_collect()) { if (PrintGCDetails && Verbose) { - gclog_or_tty->print(" %s: collect because incremental collection will fail ", - short_name()); - } - return true; - } - if (!_cmsSpace->adaptive_freelists() && - _cmsSpace->linearAllocationWouldFail()) { - if (PrintGCDetails && Verbose) { - gclog_or_tty->print(" %s: collect because of linAB ", + gclog_or_tty->print(" %s: collect because cmsSpace says so ", short_name()); } return true; @@ -1970,8 +1989,9 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) { "Should have been NULL'd before baton was passed"); reset(false /* == !asynch */); _cmsGen->reset_after_compaction(); + _concurrent_cycles_since_last_unload = 0; - if (verifying() && !cms_should_unload_classes()) { + if (verifying() && !should_unload_classes()) { perm_gen_verify_bit_map()->clear_all(); } @@ -2098,6 +2118,7 @@ void CMSCollector::collect_in_background(bool clear_all_soft_refs) { { bool safepoint_check = Mutex::_no_safepoint_check_flag; MutexLockerEx hl(Heap_lock, safepoint_check); + FreelistLocker fll(this); MutexLockerEx x(CGC_lock, safepoint_check); if (_foregroundGCIsActive || !UseAsyncConcMarkSweepGC) { // The foreground collector is active or we're @@ -2112,13 +2133,9 @@ void CMSCollector::collect_in_background(bool clear_all_soft_refs) { // a new cycle. clear_expansion_cause(); } - _unloaded_classes_last_cycle = cms_should_unload_classes(); // ... from last cycle - // This controls class unloading in response to an explicit gc request. - // If ExplicitGCInvokesConcurrentAndUnloadsClasses is set, then - // we will unload classes even if CMSClassUnloadingEnabled is not set. - // See CR 6541037 and related CRs. - _unload_classes = _full_gc_requested // ... for this cycle - && ExplicitGCInvokesConcurrentAndUnloadsClasses; + // Decide if we want to enable class unloading as part of the + // ensuing concurrent GC cycle. + update_should_unload_classes(); _full_gc_requested = false; // acks all outstanding full gc requests // Signal that we are about to start a collection gch->increment_total_full_collections(); // ... starting a collection cycle @@ -3047,21 +3064,62 @@ void CMSCollector::verify_overflow_empty() const { } #endif // PRODUCT +// Decide if we want to enable class unloading as part of the +// ensuing concurrent GC cycle. We will collect the perm gen and +// unload classes if it's the case that: +// (1) an explicit gc request has been made and the flag +// ExplicitGCInvokesConcurrentAndUnloadsClasses is set, OR +// (2) (a) class unloading is enabled at the command line, and +// (b) (i) perm gen threshold has been crossed, or +// (ii) old gen is getting really full, or +// (iii) the previous N CMS collections did not collect the +// perm gen +// NOTE: Provided there is no change in the state of the heap between +// calls to this method, it should have idempotent results. Moreover, +// its results should be monotonically increasing (i.e. going from 0 to 1, +// but not 1 to 0) between successive calls between which the heap was +// not collected. For the implementation below, it must thus rely on +// the property that concurrent_cycles_since_last_unload() +// will not decrease unless a collection cycle happened and that +// _permGen->should_concurrent_collect() and _cmsGen->is_too_full() are +// themselves also monotonic in that sense. See check_monotonicity() +// below. +bool CMSCollector::update_should_unload_classes() { + _should_unload_classes = false; + // Condition 1 above + if (_full_gc_requested && ExplicitGCInvokesConcurrentAndUnloadsClasses) { + _should_unload_classes = true; + } else if (CMSClassUnloadingEnabled) { // Condition 2.a above + // Disjuncts 2.b.(i,ii,iii) above + _should_unload_classes = (concurrent_cycles_since_last_unload() >= + CMSClassUnloadingMaxInterval) + || _permGen->should_concurrent_collect() + || _cmsGen->is_too_full(); + } + return _should_unload_classes; +} + +bool ConcurrentMarkSweepGeneration::is_too_full() const { + bool res = should_concurrent_collect(); + res = res && (occupancy() > (double)CMSIsTooFullPercentage/100.0); + return res; +} + void CMSCollector::setup_cms_unloading_and_verification_state() { const bool should_verify = VerifyBeforeGC || VerifyAfterGC || VerifyDuringGC || VerifyBeforeExit; const int rso = SharedHeap::SO_Symbols | SharedHeap::SO_Strings | SharedHeap::SO_CodeCache; - if (cms_should_unload_classes()) { // Should unload classes this cycle + if (should_unload_classes()) { // Should unload classes this cycle remove_root_scanning_option(rso); // Shrink the root set appropriately set_verifying(should_verify); // Set verification state for this cycle return; // Nothing else needs to be done at this time } // Not unloading classes this cycle - assert(!cms_should_unload_classes(), "Inconsitency!"); - if ((!verifying() || cms_unloaded_classes_last_cycle()) && should_verify) { + assert(!should_unload_classes(), "Inconsitency!"); + if ((!verifying() || unloaded_classes_last_cycle()) && should_verify) { // We were not verifying, or we _were_ unloading classes in the last cycle, // AND some verification options are enabled this cycle; in this case, // we must make sure that the deadness map is allocated if not already so, @@ -3862,13 +3920,15 @@ void CMSConcMarkingTask::do_scan_and_mark(int i, CompactibleFreeListSpace* sp) { } class Par_ConcMarkingClosure: public OopClosure { + private: CMSCollector* _collector; MemRegion _span; CMSBitMap* _bit_map; CMSMarkStack* _overflow_stack; CMSMarkStack* _revisit_stack; // XXXXXX Check proper use OopTaskQueue* _work_queue; - + protected: + DO_OOP_WORK_DEFN public: Par_ConcMarkingClosure(CMSCollector* collector, OopTaskQueue* work_queue, CMSBitMap* bit_map, CMSMarkStack* overflow_stack): @@ -3877,8 +3937,8 @@ class Par_ConcMarkingClosure: public OopClosure { _work_queue(work_queue), _bit_map(bit_map), _overflow_stack(overflow_stack) { } // need to initialize revisit stack etc. - - void do_oop(oop* p); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); void trim_queue(size_t max); void handle_stack_overflow(HeapWord* lost); }; @@ -3887,11 +3947,9 @@ class Par_ConcMarkingClosure: public OopClosure { // the salient assumption here is that stolen oops must // always be initialized, so we do not need to check for // uninitialized objects before scanning here. -void Par_ConcMarkingClosure::do_oop(oop* p) { - oop this_oop = *p; - assert(this_oop->is_oop_or_null(), - "expected an oop or NULL"); - HeapWord* addr = (HeapWord*)this_oop; +void Par_ConcMarkingClosure::do_oop(oop obj) { + assert(obj->is_oop_or_null(), "expected an oop or NULL"); + HeapWord* addr = (HeapWord*)obj; // Check if oop points into the CMS generation // and is not marked if (_span.contains(addr) && !_bit_map->isMarked(addr)) { @@ -3910,7 +3968,7 @@ void Par_ConcMarkingClosure::do_oop(oop* p) { } ) if (simulate_overflow || - !(_work_queue->push(this_oop) || _overflow_stack->par_push(this_oop))) { + !(_work_queue->push(obj) || _overflow_stack->par_push(obj))) { // stack overflow if (PrintCMSStatistics != 0) { gclog_or_tty->print_cr("CMS marking stack overflow (benign) at " @@ -3927,6 +3985,9 @@ void Par_ConcMarkingClosure::do_oop(oop* p) { } } +void Par_ConcMarkingClosure::do_oop(oop* p) { Par_ConcMarkingClosure::do_oop_work(p); } +void Par_ConcMarkingClosure::do_oop(narrowOop* p) { Par_ConcMarkingClosure::do_oop_work(p); } + void Par_ConcMarkingClosure::trim_queue(size_t max) { while (_work_queue->size() > max) { oop new_oop; @@ -4026,8 +4087,8 @@ void CMSConcMarkingTask::coordinator_yield() { // // Tony 2006.06.29 for (unsigned i = 0; i < CMSCoordinatorYieldSleepCount && - ConcurrentMarkSweepThread::should_yield() && - !CMSCollector::foregroundGCIsActive(); ++i) { + ConcurrentMarkSweepThread::should_yield() && + !CMSCollector::foregroundGCIsActive(); ++i) { os::sleep(Thread::current(), 1, false); ConcurrentMarkSweepThread::acknowledge_yield_request(); } @@ -4693,7 +4754,7 @@ void CMSCollector::checkpointRootsFinalWork(bool asynch, GenCollectedHeap* gch = GenCollectedHeap::heap(); - if (cms_should_unload_classes()) { + if (should_unload_classes()) { CodeCache::gc_prologue(); } assert(haveFreelistLocks(), "must have free list locks"); @@ -4753,7 +4814,7 @@ void CMSCollector::checkpointRootsFinalWork(bool asynch, verify_work_stacks_empty(); verify_overflow_empty(); - if (cms_should_unload_classes()) { + if (should_unload_classes()) { CodeCache::gc_epilogue(); } @@ -5433,7 +5494,7 @@ class CMSRefProcTaskProxy: public AbstractGangTask { typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask; CMSCollector* _collector; CMSBitMap* _mark_bit_map; - MemRegion _span; + const MemRegion _span; OopTaskQueueSet* _task_queues; ParallelTaskTerminator _term; ProcessTask& _task; @@ -5450,7 +5511,10 @@ public: _collector(collector), _span(span), _mark_bit_map(mark_bit_map), _task_queues(task_queues), _term(total_workers, task_queues) - { } + { + assert(_collector->_span.equals(_span) && !_span.is_empty(), + "Inconsistency in _span"); + } OopTaskQueueSet* task_queues() { return _task_queues; } @@ -5467,11 +5531,12 @@ public: }; void CMSRefProcTaskProxy::work(int i) { + assert(_collector->_span.equals(_span), "Inconsistency in _span"); CMSParKeepAliveClosure par_keep_alive(_collector, _span, _mark_bit_map, work_queue(i)); CMSParDrainMarkingStackClosure par_drain_stack(_collector, _span, _mark_bit_map, work_queue(i)); - CMSIsAliveClosure is_alive_closure(_mark_bit_map); + CMSIsAliveClosure is_alive_closure(_span, _mark_bit_map); _task.work(i, is_alive_closure, par_keep_alive, par_drain_stack); if (_task.marks_oops_alive()) { do_work_steal(i, &par_drain_stack, &par_keep_alive, @@ -5623,7 +5688,7 @@ void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) { verify_work_stacks_empty(); } - if (cms_should_unload_classes()) { + if (should_unload_classes()) { { TraceTime t("class unloading", PrintGCDetails, false, gclog_or_tty); @@ -5726,7 +5791,7 @@ void CMSCollector::sweep(bool asynch) { // this cycle, we preserve the perm gen object "deadness" information // in the perm_gen_verify_bit_map. In order to do that we traverse // all blocks in perm gen and mark all dead objects. - if (verifying() && !cms_should_unload_classes()) { + if (verifying() && !should_unload_classes()) { assert(perm_gen_verify_bit_map()->sizeInBits() != 0, "Should have already been allocated"); MarkDeadObjectsClosure mdo(this, _permGen->cmsSpace(), @@ -5753,7 +5818,7 @@ void CMSCollector::sweep(bool asynch) { } // Now repeat for perm gen - if (cms_should_unload_classes()) { + if (should_unload_classes()) { CMSTokenSyncWithLocks ts(true, _permGen->freelistLock(), bitMapLock()); sweepWork(_permGen, asynch); @@ -5775,7 +5840,7 @@ void CMSCollector::sweep(bool asynch) { // already have needed locks sweepWork(_cmsGen, asynch); - if (cms_should_unload_classes()) { + if (should_unload_classes()) { sweepWork(_permGen, asynch); } // Update heap occupancy information which is used as @@ -5937,6 +6002,11 @@ void CMSCollector::sweepWork(ConcurrentMarkSweepGeneration* gen, } gen->cmsSpace()->sweep_completed(); gen->cmsSpace()->endSweepFLCensus(sweepCount()); + if (should_unload_classes()) { // unloaded classes this cycle, + _concurrent_cycles_since_last_unload = 0; // ... reset count + } else { // did not unload classes, + _concurrent_cycles_since_last_unload++; // ... increment count + } } // Reset CMS data structures (for now just the marking bit map) @@ -5983,8 +6053,8 @@ void CMSCollector::reset(bool asynch) { // See the comment in coordinator_yield() for (unsigned i = 0; i < CMSYieldSleepCount && - ConcurrentMarkSweepThread::should_yield() && - !CMSCollector::foregroundGCIsActive(); ++i) { + ConcurrentMarkSweepThread::should_yield() && + !CMSCollector::foregroundGCIsActive(); ++i) { os::sleep(Thread::current(), 1, false); ConcurrentMarkSweepThread::acknowledge_yield_request(); } @@ -6297,19 +6367,19 @@ MarkRefsIntoClosure::MarkRefsIntoClosure( assert(_bitMap->covers(_span), "_bitMap/_span mismatch"); } -void MarkRefsIntoClosure::do_oop(oop* p) { +void MarkRefsIntoClosure::do_oop(oop obj) { // if p points into _span, then mark corresponding bit in _markBitMap - oop thisOop = *p; - if (thisOop != NULL) { - assert(thisOop->is_oop(), "expected an oop"); - HeapWord* addr = (HeapWord*)thisOop; - if (_span.contains(addr)) { - // this should be made more efficient - _bitMap->mark(addr); - } + assert(obj->is_oop(), "expected an oop"); + HeapWord* addr = (HeapWord*)obj; + if (_span.contains(addr)) { + // this should be made more efficient + _bitMap->mark(addr); } } +void MarkRefsIntoClosure::do_oop(oop* p) { MarkRefsIntoClosure::do_oop_work(p); } +void MarkRefsIntoClosure::do_oop(narrowOop* p) { MarkRefsIntoClosure::do_oop_work(p); } + // A variant of the above, used for CMS marking verification. MarkRefsIntoVerifyClosure::MarkRefsIntoVerifyClosure( MemRegion span, CMSBitMap* verification_bm, CMSBitMap* cms_bm, @@ -6322,23 +6392,23 @@ MarkRefsIntoVerifyClosure::MarkRefsIntoVerifyClosure( assert(_verification_bm->covers(_span), "_verification_bm/_span mismatch"); } -void MarkRefsIntoVerifyClosure::do_oop(oop* p) { +void MarkRefsIntoVerifyClosure::do_oop(oop obj) { // if p points into _span, then mark corresponding bit in _markBitMap - oop this_oop = *p; - if (this_oop != NULL) { - assert(this_oop->is_oop(), "expected an oop"); - HeapWord* addr = (HeapWord*)this_oop; - if (_span.contains(addr)) { - _verification_bm->mark(addr); - if (!_cms_bm->isMarked(addr)) { - oop(addr)->print(); - gclog_or_tty->print_cr(" ("INTPTR_FORMAT" should have been marked)", addr); - fatal("... aborting"); - } + assert(obj->is_oop(), "expected an oop"); + HeapWord* addr = (HeapWord*)obj; + if (_span.contains(addr)) { + _verification_bm->mark(addr); + if (!_cms_bm->isMarked(addr)) { + oop(addr)->print(); + gclog_or_tty->print_cr(" (" INTPTR_FORMAT " should have been marked)", addr); + fatal("... aborting"); } } } +void MarkRefsIntoVerifyClosure::do_oop(oop* p) { MarkRefsIntoVerifyClosure::do_oop_work(p); } +void MarkRefsIntoVerifyClosure::do_oop(narrowOop* p) { MarkRefsIntoVerifyClosure::do_oop_work(p); } + ////////////////////////////////////////////////// // MarkRefsIntoAndScanClosure ////////////////////////////////////////////////// @@ -6373,13 +6443,13 @@ MarkRefsIntoAndScanClosure::MarkRefsIntoAndScanClosure(MemRegion span, // The marks are made in the marking bit map and the marking stack is // used for keeping the (newly) grey objects during the scan. // The parallel version (Par_...) appears further below. -void MarkRefsIntoAndScanClosure::do_oop(oop* p) { - oop this_oop = *p; - if (this_oop != NULL) { - assert(this_oop->is_oop(), "expected an oop"); - HeapWord* addr = (HeapWord*)this_oop; - assert(_mark_stack->isEmpty(), "post-condition (eager drainage)"); - assert(_collector->overflow_list_is_empty(), "should be empty"); +void MarkRefsIntoAndScanClosure::do_oop(oop obj) { + if (obj != NULL) { + assert(obj->is_oop(), "expected an oop"); + HeapWord* addr = (HeapWord*)obj; + assert(_mark_stack->isEmpty(), "pre-condition (eager drainage)"); + assert(_collector->overflow_list_is_empty(), + "overflow list should be empty"); if (_span.contains(addr) && !_bit_map->isMarked(addr)) { // mark bit map (object is now grey) @@ -6387,7 +6457,7 @@ void MarkRefsIntoAndScanClosure::do_oop(oop* p) { // push on marking stack (stack should be empty), and drain the // stack by applying this closure to the oops in the oops popped // from the stack (i.e. blacken the grey objects) - bool res = _mark_stack->push(this_oop); + bool res = _mark_stack->push(obj); assert(res, "Should have space to push on empty stack"); do { oop new_oop = _mark_stack->pop(); @@ -6423,6 +6493,9 @@ void MarkRefsIntoAndScanClosure::do_oop(oop* p) { } } +void MarkRefsIntoAndScanClosure::do_oop(oop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); } +void MarkRefsIntoAndScanClosure::do_oop(narrowOop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); } + void MarkRefsIntoAndScanClosure::do_yield_work() { assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(), "CMS thread should hold CMS token"); @@ -6441,9 +6514,11 @@ void MarkRefsIntoAndScanClosure::do_yield_work() { _collector->icms_wait(); // See the comment in coordinator_yield() - for (unsigned i = 0; i < CMSYieldSleepCount && - ConcurrentMarkSweepThread::should_yield() && - !CMSCollector::foregroundGCIsActive(); ++i) { + for (unsigned i = 0; + i < CMSYieldSleepCount && + ConcurrentMarkSweepThread::should_yield() && + !CMSCollector::foregroundGCIsActive(); + ++i) { os::sleep(Thread::current(), 1, false); ConcurrentMarkSweepThread::acknowledge_yield_request(); } @@ -6480,13 +6555,12 @@ Par_MarkRefsIntoAndScanClosure::Par_MarkRefsIntoAndScanClosure( // the scan phase whence they are also available for stealing by parallel // threads. Since the marking bit map is shared, updates are // synchronized (via CAS). -void Par_MarkRefsIntoAndScanClosure::do_oop(oop* p) { - oop this_oop = *p; - if (this_oop != NULL) { +void Par_MarkRefsIntoAndScanClosure::do_oop(oop obj) { + if (obj != NULL) { // Ignore mark word because this could be an already marked oop // that may be chained at the end of the overflow list. - assert(this_oop->is_oop(true /* ignore mark word */), "expected an oop"); - HeapWord* addr = (HeapWord*)this_oop; + assert(obj->is_oop(), "expected an oop"); + HeapWord* addr = (HeapWord*)obj; if (_span.contains(addr) && !_bit_map->isMarked(addr)) { // mark bit map (object will become grey): @@ -6500,7 +6574,7 @@ void Par_MarkRefsIntoAndScanClosure::do_oop(oop* p) { // queue to an appropriate length by applying this closure to // the oops in the oops popped from the stack (i.e. blacken the // grey objects) - bool res = _work_queue->push(this_oop); + bool res = _work_queue->push(obj); assert(res, "Low water mark should be less than capacity?"); trim_queue(_low_water_mark); } // Else, another thread claimed the object @@ -6508,6 +6582,9 @@ void Par_MarkRefsIntoAndScanClosure::do_oop(oop* p) { } } +void Par_MarkRefsIntoAndScanClosure::do_oop(oop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); } +void Par_MarkRefsIntoAndScanClosure::do_oop(narrowOop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); } + // This closure is used to rescan the marked objects on the dirty cards // in the mod union table and the card table proper. size_t ScanMarkedObjectsAgainCarefullyClosure::do_object_careful_m( @@ -6610,8 +6687,8 @@ void ScanMarkedObjectsAgainCarefullyClosure::do_yield_work() { // See the comment in coordinator_yield() for (unsigned i = 0; i < CMSYieldSleepCount && - ConcurrentMarkSweepThread::should_yield() && - !CMSCollector::foregroundGCIsActive(); ++i) { + ConcurrentMarkSweepThread::should_yield() && + !CMSCollector::foregroundGCIsActive(); ++i) { os::sleep(Thread::current(), 1, false); ConcurrentMarkSweepThread::acknowledge_yield_request(); } @@ -6863,13 +6940,13 @@ void MarkFromRootsClosure::scanOopsInOop(HeapWord* ptr) { assert(_markStack->isEmpty(), "should drain stack to limit stack usage"); // convert ptr to an oop preparatory to scanning - oop this_oop = oop(ptr); + oop obj = oop(ptr); // Ignore mark word in verification below, since we // may be running concurrent with mutators. - assert(this_oop->is_oop(true), "should be an oop"); + assert(obj->is_oop(true), "should be an oop"); assert(_finger <= ptr, "_finger runneth ahead"); // advance the finger to right end of this object - _finger = ptr + this_oop->size(); + _finger = ptr + obj->size(); assert(_finger > ptr, "we just incremented it above"); // On large heaps, it may take us some time to get through // the marking phase (especially if running iCMS). During @@ -6915,7 +6992,7 @@ void MarkFromRootsClosure::scanOopsInOop(HeapWord* ptr) { _span, _bitMap, _markStack, _revisitStack, _finger, this); - bool res = _markStack->push(this_oop); + bool res = _markStack->push(obj); assert(res, "Empty non-zero size stack should have space for single push"); while (!_markStack->isEmpty()) { oop new_oop = _markStack->pop(); @@ -6987,13 +7064,13 @@ void Par_MarkFromRootsClosure::scan_oops_in_oop(HeapWord* ptr) { assert(_work_queue->size() == 0, "should drain stack to limit stack usage"); // convert ptr to an oop preparatory to scanning - oop this_oop = oop(ptr); + oop obj = oop(ptr); // Ignore mark word in verification below, since we // may be running concurrent with mutators. - assert(this_oop->is_oop(true), "should be an oop"); + assert(obj->is_oop(true), "should be an oop"); assert(_finger <= ptr, "_finger runneth ahead"); // advance the finger to right end of this object - _finger = ptr + this_oop->size(); + _finger = ptr + obj->size(); assert(_finger > ptr, "we just incremented it above"); // On large heaps, it may take us some time to get through // the marking phase (especially if running iCMS). During @@ -7041,7 +7118,7 @@ void Par_MarkFromRootsClosure::scan_oops_in_oop(HeapWord* ptr) { _revisit_stack, _finger, gfa, this); - bool res = _work_queue->push(this_oop); // overflow could occur here + bool res = _work_queue->push(obj); // overflow could occur here assert(res, "Will hold once we use workqueues"); while (true) { oop new_oop; @@ -7111,15 +7188,15 @@ void MarkFromRootsVerifyClosure::do_bit(size_t offset) { assert(_mark_stack->isEmpty(), "should drain stack to limit stack usage"); // convert addr to an oop preparatory to scanning - oop this_oop = oop(addr); - assert(this_oop->is_oop(), "should be an oop"); + oop obj = oop(addr); + assert(obj->is_oop(), "should be an oop"); assert(_finger <= addr, "_finger runneth ahead"); // advance the finger to right end of this object - _finger = addr + this_oop->size(); + _finger = addr + obj->size(); assert(_finger > addr, "we just incremented it above"); // Note: the finger doesn't advance while we drain // the stack below. - bool res = _mark_stack->push(this_oop); + bool res = _mark_stack->push(obj); assert(res, "Empty non-zero size stack should have space for single push"); while (!_mark_stack->isEmpty()) { oop new_oop = _mark_stack->pop(); @@ -7142,6 +7219,8 @@ PushAndMarkVerifyClosure::PushAndMarkVerifyClosure( _mark_stack(mark_stack) { } +void PushAndMarkVerifyClosure::do_oop(oop* p) { PushAndMarkVerifyClosure::do_oop_work(p); } +void PushAndMarkVerifyClosure::do_oop(narrowOop* p) { PushAndMarkVerifyClosure::do_oop_work(p); } // Upon stack overflow, we discard (part of) the stack, // remembering the least address amongst those discarded @@ -7154,20 +7233,20 @@ void PushAndMarkVerifyClosure::handle_stack_overflow(HeapWord* lost) { _mark_stack->expand(); // expand the stack if possible } -void PushAndMarkVerifyClosure::do_oop(oop* p) { - oop this_oop = *p; - assert(this_oop->is_oop_or_null(), "expected an oop or NULL"); - HeapWord* addr = (HeapWord*)this_oop; +void PushAndMarkVerifyClosure::do_oop(oop obj) { + assert(obj->is_oop_or_null(), "expected an oop or NULL"); + HeapWord* addr = (HeapWord*)obj; if (_span.contains(addr) && !_verification_bm->isMarked(addr)) { // Oop lies in _span and isn't yet grey or black _verification_bm->mark(addr); // now grey if (!_cms_bm->isMarked(addr)) { oop(addr)->print(); - gclog_or_tty->print_cr(" ("INTPTR_FORMAT" should have been marked)", addr); + gclog_or_tty->print_cr(" (" INTPTR_FORMAT " should have been marked)", + addr); fatal("... aborting"); } - if (!_mark_stack->push(this_oop)) { // stack overflow + if (!_mark_stack->push(obj)) { // stack overflow if (PrintCMSStatistics != 0) { gclog_or_tty->print_cr("CMS marking stack overflow (benign) at " SIZE_FORMAT, _mark_stack->capacity()); @@ -7194,7 +7273,7 @@ PushOrMarkClosure::PushOrMarkClosure(CMSCollector* collector, _revisitStack(revisitStack), _finger(finger), _parent(parent), - _should_remember_klasses(collector->cms_should_unload_classes()) + _should_remember_klasses(collector->should_unload_classes()) { } Par_PushOrMarkClosure::Par_PushOrMarkClosure(CMSCollector* collector, @@ -7217,10 +7296,9 @@ Par_PushOrMarkClosure::Par_PushOrMarkClosure(CMSCollector* collector, _finger(finger), _global_finger_addr(global_finger_addr), _parent(parent), - _should_remember_klasses(collector->cms_should_unload_classes()) + _should_remember_klasses(collector->should_unload_classes()) { } - void CMSCollector::lower_restart_addr(HeapWord* low) { assert(_span.contains(low), "Out of bounds addr"); if (_restart_addr == NULL) { @@ -7256,12 +7334,10 @@ void Par_PushOrMarkClosure::handle_stack_overflow(HeapWord* lost) { _overflow_stack->expand(); // expand the stack if possible } - -void PushOrMarkClosure::do_oop(oop* p) { - oop thisOop = *p; +void PushOrMarkClosure::do_oop(oop obj) { // Ignore mark word because we are running concurrent with mutators. - assert(thisOop->is_oop_or_null(true), "expected an oop or NULL"); - HeapWord* addr = (HeapWord*)thisOop; + assert(obj->is_oop_or_null(true), "expected an oop or NULL"); + HeapWord* addr = (HeapWord*)obj; if (_span.contains(addr) && !_bitMap->isMarked(addr)) { // Oop lies in _span and isn't yet grey or black _bitMap->mark(addr); // now grey @@ -7277,7 +7353,7 @@ void PushOrMarkClosure::do_oop(oop* p) { simulate_overflow = true; } ) - if (simulate_overflow || !_markStack->push(thisOop)) { // stack overflow + if (simulate_overflow || !_markStack->push(obj)) { // stack overflow if (PrintCMSStatistics != 0) { gclog_or_tty->print_cr("CMS marking stack overflow (benign) at " SIZE_FORMAT, _markStack->capacity()); @@ -7293,11 +7369,13 @@ void PushOrMarkClosure::do_oop(oop* p) { } } -void Par_PushOrMarkClosure::do_oop(oop* p) { - oop this_oop = *p; +void PushOrMarkClosure::do_oop(oop* p) { PushOrMarkClosure::do_oop_work(p); } +void PushOrMarkClosure::do_oop(narrowOop* p) { PushOrMarkClosure::do_oop_work(p); } + +void Par_PushOrMarkClosure::do_oop(oop obj) { // Ignore mark word because we are running concurrent with mutators. - assert(this_oop->is_oop_or_null(true), "expected an oop or NULL"); - HeapWord* addr = (HeapWord*)this_oop; + assert(obj->is_oop_or_null(true), "expected an oop or NULL"); + HeapWord* addr = (HeapWord*)obj; if (_whole_span.contains(addr) && !_bit_map->isMarked(addr)) { // Oop lies in _span and isn't yet grey or black // We read the global_finger (volatile read) strictly after marking oop @@ -7326,7 +7404,7 @@ void Par_PushOrMarkClosure::do_oop(oop* p) { } ) if (simulate_overflow || - !(_work_queue->push(this_oop) || _overflow_stack->par_push(this_oop))) { + !(_work_queue->push(obj) || _overflow_stack->par_push(obj))) { // stack overflow if (PrintCMSStatistics != 0) { gclog_or_tty->print_cr("CMS marking stack overflow (benign) at " @@ -7343,6 +7421,8 @@ void Par_PushOrMarkClosure::do_oop(oop* p) { } } +void Par_PushOrMarkClosure::do_oop(oop* p) { Par_PushOrMarkClosure::do_oop_work(p); } +void Par_PushOrMarkClosure::do_oop(narrowOop* p) { Par_PushOrMarkClosure::do_oop_work(p); } PushAndMarkClosure::PushAndMarkClosure(CMSCollector* collector, MemRegion span, @@ -7360,23 +7440,18 @@ PushAndMarkClosure::PushAndMarkClosure(CMSCollector* collector, _mark_stack(mark_stack), _revisit_stack(revisit_stack), _concurrent_precleaning(concurrent_precleaning), - _should_remember_klasses(collector->cms_should_unload_classes()) + _should_remember_klasses(collector->should_unload_classes()) { assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL"); } // Grey object rescan during pre-cleaning and second checkpoint phases -- // the non-parallel version (the parallel version appears further below.) -void PushAndMarkClosure::do_oop(oop* p) { - oop this_oop = *p; - // Ignore mark word verification. If during concurrent precleaning - // the object monitor may be locked. If during the checkpoint - // phases, the object may already have been reached by a different - // path and may be at the end of the global overflow list (so - // the mark word may be NULL). - assert(this_oop->is_oop_or_null(true/* ignore mark word */), +void PushAndMarkClosure::do_oop(oop obj) { + // If _concurrent_precleaning, ignore mark word verification + assert(obj->is_oop_or_null(_concurrent_precleaning), "expected an oop or NULL"); - HeapWord* addr = (HeapWord*)this_oop; + HeapWord* addr = (HeapWord*)obj; // Check if oop points into the CMS generation // and is not marked if (_span.contains(addr) && !_bit_map->isMarked(addr)) { @@ -7391,7 +7466,7 @@ void PushAndMarkClosure::do_oop(oop* p) { simulate_overflow = true; } ) - if (simulate_overflow || !_mark_stack->push(this_oop)) { + if (simulate_overflow || !_mark_stack->push(obj)) { if (_concurrent_precleaning) { // During precleaning we can just dirty the appropriate card // in the mod union table, thus ensuring that the object remains @@ -7403,7 +7478,7 @@ void PushAndMarkClosure::do_oop(oop* p) { } else { // During the remark phase, we need to remember this oop // in the overflow list. - _collector->push_on_overflow_list(this_oop); + _collector->push_on_overflow_list(obj); _collector->_ser_pmc_remark_ovflw++; } } @@ -7422,15 +7497,17 @@ Par_PushAndMarkClosure::Par_PushAndMarkClosure(CMSCollector* collector, _bit_map(bit_map), _work_queue(work_queue), _revisit_stack(revisit_stack), - _should_remember_klasses(collector->cms_should_unload_classes()) + _should_remember_klasses(collector->should_unload_classes()) { assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL"); } +void PushAndMarkClosure::do_oop(oop* p) { PushAndMarkClosure::do_oop_work(p); } +void PushAndMarkClosure::do_oop(narrowOop* p) { PushAndMarkClosure::do_oop_work(p); } + // Grey object rescan during second checkpoint phase -- // the parallel version. -void Par_PushAndMarkClosure::do_oop(oop* p) { - oop this_oop = *p; +void Par_PushAndMarkClosure::do_oop(oop obj) { // In the assert below, we ignore the mark word because // this oop may point to an already visited object that is // on the overflow stack (in which case the mark word has @@ -7442,9 +7519,9 @@ void Par_PushAndMarkClosure::do_oop(oop* p) { // value, by the time we get to examined this failing assert in // the debugger, is_oop_or_null(false) may subsequently start // to hold. - assert(this_oop->is_oop_or_null(true), + assert(obj->is_oop_or_null(true), "expected an oop or NULL"); - HeapWord* addr = (HeapWord*)this_oop; + HeapWord* addr = (HeapWord*)obj; // Check if oop points into the CMS generation // and is not marked if (_span.contains(addr) && !_bit_map->isMarked(addr)) { @@ -7462,14 +7539,17 @@ void Par_PushAndMarkClosure::do_oop(oop* p) { simulate_overflow = true; } ) - if (simulate_overflow || !_work_queue->push(this_oop)) { - _collector->par_push_on_overflow_list(this_oop); + if (simulate_overflow || !_work_queue->push(obj)) { + _collector->par_push_on_overflow_list(obj); _collector->_par_pmc_remark_ovflw++; // imprecise OK: no need to CAS } } // Else, some other thread got there first } } +void Par_PushAndMarkClosure::do_oop(oop* p) { Par_PushAndMarkClosure::do_oop_work(p); } +void Par_PushAndMarkClosure::do_oop(narrowOop* p) { Par_PushAndMarkClosure::do_oop_work(p); } + void PushAndMarkClosure::remember_klass(Klass* k) { if (!_revisit_stack->push(oop(k))) { fatal("Revisit stack overflowed in PushAndMarkClosure"); @@ -7944,7 +8024,7 @@ size_t SweepClosure::doLiveChunk(FreeChunk* fc) { #ifdef DEBUG if (oop(addr)->klass() != NULL && - ( !_collector->cms_should_unload_classes() + ( !_collector->should_unload_classes() || oop(addr)->is_parsable())) { // Ignore mark word because we are running concurrent with mutators assert(oop(addr)->is_oop(true), "live block should be an oop"); @@ -7957,7 +8037,7 @@ size_t SweepClosure::doLiveChunk(FreeChunk* fc) { } else { // This should be an initialized object that's alive. assert(oop(addr)->klass() != NULL && - (!_collector->cms_should_unload_classes() + (!_collector->should_unload_classes() || oop(addr)->is_parsable()), "Should be an initialized object"); // Ignore mark word because we are running concurrent with mutators @@ -8163,9 +8243,8 @@ bool CMSIsAliveClosure::do_object_b(oop obj) { } // CMSKeepAliveClosure: the serial version -void CMSKeepAliveClosure::do_oop(oop* p) { - oop this_oop = *p; - HeapWord* addr = (HeapWord*)this_oop; +void CMSKeepAliveClosure::do_oop(oop obj) { + HeapWord* addr = (HeapWord*)obj; if (_span.contains(addr) && !_bit_map->isMarked(addr)) { _bit_map->mark(addr); @@ -8177,26 +8256,28 @@ void CMSKeepAliveClosure::do_oop(oop* p) { simulate_overflow = true; } ) - if (simulate_overflow || !_mark_stack->push(this_oop)) { - _collector->push_on_overflow_list(this_oop); + if (simulate_overflow || !_mark_stack->push(obj)) { + _collector->push_on_overflow_list(obj); _collector->_ser_kac_ovflw++; } } } +void CMSKeepAliveClosure::do_oop(oop* p) { CMSKeepAliveClosure::do_oop_work(p); } +void CMSKeepAliveClosure::do_oop(narrowOop* p) { CMSKeepAliveClosure::do_oop_work(p); } + // CMSParKeepAliveClosure: a parallel version of the above. // The work queues are private to each closure (thread), // but (may be) available for stealing by other threads. -void CMSParKeepAliveClosure::do_oop(oop* p) { - oop this_oop = *p; - HeapWord* addr = (HeapWord*)this_oop; +void CMSParKeepAliveClosure::do_oop(oop obj) { + HeapWord* addr = (HeapWord*)obj; if (_span.contains(addr) && !_bit_map->isMarked(addr)) { // In general, during recursive tracing, several threads // may be concurrently getting here; the first one to // "tag" it, claims it. if (_bit_map->par_mark(addr)) { - bool res = _work_queue->push(this_oop); + bool res = _work_queue->push(obj); assert(res, "Low water mark should be much less than capacity"); // Do a recursive trim in the hope that this will keep // stack usage lower, but leave some oops for potential stealers @@ -8205,6 +8286,9 @@ void CMSParKeepAliveClosure::do_oop(oop* p) { } } +void CMSParKeepAliveClosure::do_oop(oop* p) { CMSParKeepAliveClosure::do_oop_work(p); } +void CMSParKeepAliveClosure::do_oop(narrowOop* p) { CMSParKeepAliveClosure::do_oop_work(p); } + void CMSParKeepAliveClosure::trim_queue(uint max) { while (_work_queue->size() > max) { oop new_oop; @@ -8220,9 +8304,8 @@ void CMSParKeepAliveClosure::trim_queue(uint max) { } } -void CMSInnerParMarkAndPushClosure::do_oop(oop* p) { - oop this_oop = *p; - HeapWord* addr = (HeapWord*)this_oop; +void CMSInnerParMarkAndPushClosure::do_oop(oop obj) { + HeapWord* addr = (HeapWord*)obj; if (_span.contains(addr) && !_bit_map->isMarked(addr)) { if (_bit_map->par_mark(addr)) { @@ -8234,14 +8317,17 @@ void CMSInnerParMarkAndPushClosure::do_oop(oop* p) { simulate_overflow = true; } ) - if (simulate_overflow || !_work_queue->push(this_oop)) { - _collector->par_push_on_overflow_list(this_oop); + if (simulate_overflow || !_work_queue->push(obj)) { + _collector->par_push_on_overflow_list(obj); _collector->_par_kac_ovflw++; } } // Else another thread got there already } } +void CMSInnerParMarkAndPushClosure::do_oop(oop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(p); } +void CMSInnerParMarkAndPushClosure::do_oop(narrowOop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(p); } + ////////////////////////////////////////////////////////////////// // CMSExpansionCause ///////////////////////////// ////////////////////////////////////////////////////////////////// @@ -8272,12 +8358,12 @@ void CMSDrainMarkingStackClosure::do_void() { while (!_mark_stack->isEmpty() || // if stack is empty, check the overflow list _collector->take_from_overflow_list(num, _mark_stack)) { - oop this_oop = _mark_stack->pop(); - HeapWord* addr = (HeapWord*)this_oop; + oop obj = _mark_stack->pop(); + HeapWord* addr = (HeapWord*)obj; assert(_span.contains(addr), "Should be within span"); assert(_bit_map->isMarked(addr), "Should be marked"); - assert(this_oop->is_oop(), "Should be an oop"); - this_oop->oop_iterate(_keep_alive); + assert(obj->is_oop(), "Should be an oop"); + obj->oop_iterate(_keep_alive); } } diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp index f4f790ebab1..6d5546eeb95 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp @@ -435,23 +435,22 @@ class CMSStats VALUE_OBJ_CLASS_SPEC { // if the object is "live" (reachable). Used in weak // reference processing. class CMSIsAliveClosure: public BoolObjectClosure { - MemRegion _span; + const MemRegion _span; const CMSBitMap* _bit_map; friend class CMSCollector; - protected: - void set_span(MemRegion span) { _span = span; } public: - CMSIsAliveClosure(CMSBitMap* bit_map): - _bit_map(bit_map) { } - CMSIsAliveClosure(MemRegion span, CMSBitMap* bit_map): _span(span), - _bit_map(bit_map) { } + _bit_map(bit_map) { + assert(!span.is_empty(), "Empty span could spell trouble"); + } + void do_object(oop obj) { assert(false, "not to be invoked"); } + bool do_object_b(oop obj); }; @@ -535,13 +534,16 @@ class CMSCollector: public CHeapObj { // In support of ExplicitGCInvokesConcurrent static bool _full_gc_requested; unsigned int _collection_count_start; + // Should we unload classes this concurrent cycle? - // Set in response to a concurrent full gc request. - bool _unload_classes; - bool _unloaded_classes_last_cycle; + bool _should_unload_classes; + unsigned int _concurrent_cycles_since_last_unload; + unsigned int concurrent_cycles_since_last_unload() const { + return _concurrent_cycles_since_last_unload; + } // Did we (allow) unload classes in the previous concurrent cycle? - bool cms_unloaded_classes_last_cycle() const { - return _unloaded_classes_last_cycle || CMSClassUnloadingEnabled; + bool unloaded_classes_last_cycle() const { + return concurrent_cycles_since_last_unload() == 0; } // Verification support @@ -597,7 +599,7 @@ class CMSCollector: public CHeapObj { // ("Weak") Reference processing support ReferenceProcessor* _ref_processor; CMSIsAliveClosure _is_alive_closure; - // keep this textually after _markBitMap; c'tor dependency + // keep this textually after _markBitMap and _span; c'tor dependency ConcurrentMarkSweepThread* _cmsThread; // the thread doing the work ModUnionClosure _modUnionClosure; @@ -651,8 +653,6 @@ class CMSCollector: public CHeapObj { // number of full gc's since the last concurrent gc. uint _full_gcs_since_conc_gc; - // if occupancy exceeds this, start a new gc cycle - double _initiatingOccupancy; // occupancy used for bootstrapping stats double _bootstrap_occupancy; @@ -825,7 +825,6 @@ class CMSCollector: public CHeapObj { Mutex* bitMapLock() const { return _markBitMap.lock(); } static CollectorState abstract_state() { return _collectorState; } - double initiatingOccupancy() const { return _initiatingOccupancy; } bool should_abort_preclean() const; // Whether preclean should be aborted. size_t get_eden_used() const; @@ -849,11 +848,10 @@ class CMSCollector: public CHeapObj { // In support of ExplicitGCInvokesConcurrent static void request_full_gc(unsigned int full_gc_count); // Should we unload classes in a particular concurrent cycle? - bool cms_should_unload_classes() const { - assert(!_unload_classes || ExplicitGCInvokesConcurrentAndUnloadsClasses, - "Inconsistency; see CR 6541037"); - return _unload_classes || CMSClassUnloadingEnabled; + bool should_unload_classes() const { + return _should_unload_classes; } + bool update_should_unload_classes(); void direct_allocated(HeapWord* start, size_t size); @@ -1022,6 +1020,10 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { _incremental_collection_failed = false; } + // accessors + void set_expansion_cause(CMSExpansionCause::Cause v) { _expansion_cause = v;} + CMSExpansionCause::Cause expansion_cause() const { return _expansion_cause; } + private: // For parallel young-gen GC support. CMSParGCThreadState** _par_gc_thread_states; @@ -1029,10 +1031,6 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { // Reason generation was expanded CMSExpansionCause::Cause _expansion_cause; - // accessors - void set_expansion_cause(CMSExpansionCause::Cause v) { _expansion_cause = v;} - CMSExpansionCause::Cause expansion_cause() { return _expansion_cause; } - // In support of MinChunkSize being larger than min object size const double _dilatation_factor; @@ -1045,6 +1043,10 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { CollectionTypes _debug_collection_type; + // Fraction of current occupancy at which to start a CMS collection which + // will collect this generation (at least). + double _initiating_occupancy; + protected: // Grow generation by specified size (returns false if unable to grow) bool grow_by(size_t bytes); @@ -1060,6 +1062,10 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { // space. size_t max_available() const; + // getter and initializer for _initiating_occupancy field. + double initiating_occupancy() const { return _initiating_occupancy; } + void init_initiating_occupancy(intx io, intx tr); + public: ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size, int level, CardTableRS* ct, @@ -1103,7 +1109,7 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { size_t capacity() const; size_t used() const; size_t free() const; - double occupancy() { return ((double)used())/((double)capacity()); } + double occupancy() const { return ((double)used())/((double)capacity()); } size_t contiguous_available() const; size_t unsafe_max_alloc_nogc() const; @@ -1131,7 +1137,7 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { // Allocation support HeapWord* allocate(size_t size, bool tlab); HeapWord* have_lock_and_allocate(size_t size, bool tlab); - oop promote(oop obj, size_t obj_size, oop* ref); + oop promote(oop obj, size_t obj_size); HeapWord* par_allocate(size_t size, bool tlab) { return allocate(size, tlab); } @@ -1158,8 +1164,8 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { bool younger_handles_promotion_failure) const; bool should_collect(bool full, size_t size, bool tlab); - // XXXPERM - bool shouldConcurrentCollect(double initiatingOccupancy); // XXXPERM + virtual bool should_concurrent_collect() const; + virtual bool is_too_full() const; void collect(bool full, bool clear_all_soft_refs, size_t size, @@ -1294,9 +1300,8 @@ class ASConcurrentMarkSweepGeneration : public ConcurrentMarkSweepGeneration { // This closure is used to check that a certain set of oops is empty. class FalseClosure: public OopClosure { public: - void do_oop(oop* p) { - guarantee(false, "Should be an empty set"); - } + void do_oop(oop* p) { guarantee(false, "Should be an empty set"); } + void do_oop(narrowOop* p) { guarantee(false, "Should be an empty set"); } }; // This closure is used to do concurrent marking from the roots @@ -1373,6 +1378,12 @@ class PushAndMarkVerifyClosure: public OopClosure { CMSBitMap* _verification_bm; CMSBitMap* _cms_bm; CMSMarkStack* _mark_stack; + protected: + void do_oop(oop p); + template inline void do_oop_work(T *p) { + oop obj = oopDesc::load_decode_heap_oop_not_null(p); + do_oop(obj); + } public: PushAndMarkVerifyClosure(CMSCollector* cms_collector, MemRegion span, @@ -1380,6 +1391,7 @@ class PushAndMarkVerifyClosure: public OopClosure { CMSBitMap* cms_bm, CMSMarkStack* mark_stack); void do_oop(oop* p); + void do_oop(narrowOop* p); // Deal with a stack overflow condition void handle_stack_overflow(HeapWord* lost); }; diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp index c151fab332a..8dd2ca4abe4 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp @@ -267,7 +267,7 @@ inline bool CMSCollector::is_dead_obj(oop obj) const { (_permGen->cmsSpace()->is_in_reserved(addr) && _permGen->cmsSpace()->block_is_obj(addr)), "must be object"); - return cms_should_unload_classes() && + return should_unload_classes() && _collectorState == Sweeping && !_markBitMap.isMarked(addr); } diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parNew b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parNew index d0014f35822..7c926792262 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parNew +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parNew @@ -19,7 +19,7 @@ // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, // CA 95054 USA or visit www.sun.com if you need additional information or // have any questions. -// +// // asParNewGeneration.hpp adaptiveSizePolicy.hpp @@ -66,8 +66,8 @@ parNewGeneration.cpp handles.hpp parNewGeneration.cpp handles.inline.hpp parNewGeneration.cpp java.hpp parNewGeneration.cpp objArrayOop.hpp -parNewGeneration.cpp oop.pcgc.inline.hpp parNewGeneration.cpp oop.inline.hpp +parNewGeneration.cpp oop.pcgc.inline.hpp parNewGeneration.cpp parGCAllocBuffer.hpp parNewGeneration.cpp parNewGeneration.hpp parNewGeneration.cpp parOopClosures.inline.hpp @@ -80,3 +80,8 @@ parNewGeneration.cpp workgroup.hpp parNewGeneration.hpp defNewGeneration.hpp parNewGeneration.hpp parGCAllocBuffer.hpp parNewGeneration.hpp taskqueue.hpp + +parOopClosures.hpp genOopClosures.hpp + +parOopClosures.inline.hpp parNewGeneration.hpp +parOopClosures.inline.hpp parOopClosures.hpp diff --git a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge index d4cf2da6d9f..8a2a7a6127b 100644 --- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge +++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge @@ -19,7 +19,7 @@ // Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, // CA 95054 USA or visit www.sun.com if you need additional information or // have any questions. -// +// // // NOTE: DO NOT CHANGE THIS COPYRIGHT TO NEW STYLE - IT WILL BREAK makeDeps! @@ -279,6 +279,7 @@ psParallelCompact.hpp mutableSpace.hpp psParallelCompact.hpp objectStartArray.hpp psParallelCompact.hpp oop.hpp psParallelCompact.hpp parMarkBitMap.hpp +psParallelCompact.hpp psCompactionManager.hpp psParallelCompact.hpp sharedHeap.hpp psOldGen.cpp psAdaptiveSizePolicy.hpp diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.cpp b/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.cpp index faa3ce7ac7e..4a3bf249229 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.cpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.cpp @@ -32,18 +32,19 @@ ParGCAllocBuffer::ParGCAllocBuffer(size_t desired_plab_sz_) : _allocated(0), _wasted(0) { assert (min_size() > AlignmentReserve, "Inconsistency!"); + // arrayOopDesc::header_size depends on command line initialization. + FillerHeaderSize = align_object_size(arrayOopDesc::header_size(T_INT)); + AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? FillerHeaderSize : 0; } -const size_t ParGCAllocBuffer::FillerHeaderSize = - align_object_size(arrayOopDesc::header_size(T_INT)); +size_t ParGCAllocBuffer::FillerHeaderSize; // If the minimum object size is greater than MinObjAlignment, we can // end up with a shard at the end of the buffer that's smaller than // the smallest object. We can't allow that because the buffer must // look like it's full of objects when we retire it, so we make // sure we have enough space for a filler int array object. -const size_t ParGCAllocBuffer::AlignmentReserve = - oopDesc::header_size() > MinObjAlignment ? FillerHeaderSize : 0; +size_t ParGCAllocBuffer::AlignmentReserve; void ParGCAllocBuffer::retire(bool end_of_gc, bool retain) { assert(!retain || end_of_gc, "Can only retain at GC end."); diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp b/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp index 73901f2bacd..d8caac661e2 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp @@ -41,8 +41,8 @@ protected: size_t _allocated; // in HeapWord units size_t _wasted; // in HeapWord units char tail[32]; - static const size_t FillerHeaderSize; - static const size_t AlignmentReserve; + static size_t FillerHeaderSize; + static size_t AlignmentReserve; public: // Initializes the buffer to be empty, but with the given "word_sz". diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp index 2bcd31138ff..36b8bb2476b 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp @@ -104,16 +104,15 @@ void ParScanThreadState::scan_partial_array_and_push_remainder(oop old) { // must be removed. arrayOop(old)->set_length(end); } + // process our set of indices (include header in first chunk) - oop* start_addr = start == 0 ? (oop*)obj : obj->obj_at_addr(start); - oop* end_addr = obj->base() + end; // obj_at_addr(end) asserts end < length - MemRegion mr((HeapWord*)start_addr, (HeapWord*)end_addr); + // should make sure end is even (aligned to HeapWord in case of compressed oops) if ((HeapWord *)obj < young_old_boundary()) { // object is in to_space - obj->oop_iterate(&_to_space_closure, mr); + obj->oop_iterate_range(&_to_space_closure, start, end); } else { // object is in old generation - obj->oop_iterate(&_old_gen_closure, mr); + obj->oop_iterate_range(&_old_gen_closure, start, end); } } @@ -319,7 +318,6 @@ void ParScanThreadStateSet::flush() } } - ParScanClosure::ParScanClosure(ParNewGeneration* g, ParScanThreadState* par_scan_state) : OopsInGenClosure(g), _par_scan_state(par_scan_state), _g(g) @@ -328,11 +326,25 @@ ParScanClosure::ParScanClosure(ParNewGeneration* g, _boundary = _g->reserved().end(); } +void ParScanWithBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, true, false); } +void ParScanWithBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, true, false); } + +void ParScanWithoutBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, false, false); } +void ParScanWithoutBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, false, false); } + +void ParRootScanWithBarrierTwoGensClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, true, true); } +void ParRootScanWithBarrierTwoGensClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, true, true); } + +void ParRootScanWithoutBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, false, true); } +void ParRootScanWithoutBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, false, true); } + ParScanWeakRefClosure::ParScanWeakRefClosure(ParNewGeneration* g, ParScanThreadState* par_scan_state) : ScanWeakRefClosure(g), _par_scan_state(par_scan_state) -{ -} +{} + +void ParScanWeakRefClosure::do_oop(oop* p) { ParScanWeakRefClosure::do_oop_work(p); } +void ParScanWeakRefClosure::do_oop(narrowOop* p) { ParScanWeakRefClosure::do_oop_work(p); } #ifdef WIN32 #pragma warning(disable: 4786) /* identifier was truncated to '255' characters in the browser information */ @@ -475,51 +487,66 @@ ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level) ParKeepAliveClosure::ParKeepAliveClosure(ParScanWeakRefClosure* cl) : DefNewGeneration::KeepAliveClosure(cl), _par_cl(cl) {} -void -// ParNewGeneration:: -ParKeepAliveClosure::do_oop(oop* p) { - // We never expect to see a null reference being processed - // as a weak reference. - assert (*p != NULL, "expected non-null ref"); - assert ((*p)->is_oop(), "expected an oop while scanning weak refs"); +template +void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop_work(T* p) { +#ifdef ASSERT + { + assert(!oopDesc::is_null(*p), "expected non-null ref"); + oop obj = oopDesc::load_decode_heap_oop_not_null(p); + // We never expect to see a null reference being processed + // as a weak reference. + assert(obj->is_oop(), "expected an oop while scanning weak refs"); + } +#endif // ASSERT _par_cl->do_oop_nv(p); if (Universe::heap()->is_in_reserved(p)) { - _rs->write_ref_field_gc_par(p, *p); + oop obj = oopDesc::load_decode_heap_oop_not_null(p); + _rs->write_ref_field_gc_par(p, obj); } } +void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop(oop* p) { ParKeepAliveClosure::do_oop_work(p); } +void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop(narrowOop* p) { ParKeepAliveClosure::do_oop_work(p); } + // ParNewGeneration:: KeepAliveClosure::KeepAliveClosure(ScanWeakRefClosure* cl) : DefNewGeneration::KeepAliveClosure(cl) {} -void -// ParNewGeneration:: -KeepAliveClosure::do_oop(oop* p) { - // We never expect to see a null reference being processed - // as a weak reference. - assert (*p != NULL, "expected non-null ref"); - assert ((*p)->is_oop(), "expected an oop while scanning weak refs"); +template +void /*ParNewGeneration::*/KeepAliveClosure::do_oop_work(T* p) { +#ifdef ASSERT + { + assert(!oopDesc::is_null(*p), "expected non-null ref"); + oop obj = oopDesc::load_decode_heap_oop_not_null(p); + // We never expect to see a null reference being processed + // as a weak reference. + assert(obj->is_oop(), "expected an oop while scanning weak refs"); + } +#endif // ASSERT _cl->do_oop_nv(p); if (Universe::heap()->is_in_reserved(p)) { - _rs->write_ref_field_gc_par(p, *p); + oop obj = oopDesc::load_decode_heap_oop_not_null(p); + _rs->write_ref_field_gc_par(p, obj); } } -void ScanClosureWithParBarrier::do_oop(oop* p) { - oop obj = *p; - // Should we copy the obj? - if (obj != NULL) { +void /*ParNewGeneration::*/KeepAliveClosure::do_oop(oop* p) { KeepAliveClosure::do_oop_work(p); } +void /*ParNewGeneration::*/KeepAliveClosure::do_oop(narrowOop* p) { KeepAliveClosure::do_oop_work(p); } + +template void ScanClosureWithParBarrier::do_oop_work(T* p) { + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); if ((HeapWord*)obj < _boundary) { assert(!_g->to()->is_in_reserved(obj), "Scanning field twice?"); - if (obj->is_forwarded()) { - *p = obj->forwardee(); - } else { - *p = _g->DefNewGeneration::copy_to_survivor_space(obj, p); - } + oop new_obj = obj->is_forwarded() + ? obj->forwardee() + : _g->DefNewGeneration::copy_to_survivor_space(obj); + oopDesc::encode_store_heap_oop_not_null(p, new_obj); } if (_gc_barrier) { // If p points to a younger generation, mark the card. @@ -530,6 +557,9 @@ void ScanClosureWithParBarrier::do_oop(oop* p) { } } +void ScanClosureWithParBarrier::do_oop(oop* p) { ScanClosureWithParBarrier::do_oop_work(p); } +void ScanClosureWithParBarrier::do_oop(narrowOop* p) { ScanClosureWithParBarrier::do_oop_work(p); } + class ParNewRefProcTaskProxy: public AbstractGangTask { typedef AbstractRefProcTaskExecutor::ProcessTask ProcessTask; public: diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp index a41548b1a9e..19564e7b670 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp @@ -33,7 +33,6 @@ class ParEvacuateFollowersClosure; // but they must be here to allow ParScanClosure::do_oop_work to be defined // in genOopClosures.inline.hpp. - typedef OopTaskQueue ObjToScanQueue; typedef OopTaskQueueSet ObjToScanQueueSet; @@ -41,15 +40,20 @@ typedef OopTaskQueueSet ObjToScanQueueSet; const int PAR_STATS_ENABLED = 0; class ParKeepAliveClosure: public DefNewGeneration::KeepAliveClosure { + private: ParScanWeakRefClosure* _par_cl; + protected: + template void do_oop_work(T* p); public: ParKeepAliveClosure(ParScanWeakRefClosure* cl); - void do_oop(oop* p); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); }; // The state needed by thread performing parallel young-gen collection. class ParScanThreadState { friend class ParScanThreadStateSet; + private: ObjToScanQueue *_work_queue; ParGCAllocBuffer _to_space_alloc_buffer; @@ -111,7 +115,7 @@ class ParScanThreadState { ObjToScanQueueSet* work_queue_set_, size_t desired_plab_sz_, ParallelTaskTerminator& term_); -public: + public: ageTable* age_table() {return &_ageTable;} ObjToScanQueue* work_queue() { return _work_queue; } @@ -195,13 +199,13 @@ public: double elapsed() { return os::elapsedTime() - _start; } - }; class ParNewGenTask: public AbstractGangTask { - ParNewGeneration* _gen; - Generation* _next_gen; - HeapWord* _young_old_boundary; + private: + ParNewGeneration* _gen; + Generation* _next_gen; + HeapWord* _young_old_boundary; class ParScanThreadStateSet* _state_set; public: @@ -216,35 +220,44 @@ public: }; class KeepAliveClosure: public DefNewGeneration::KeepAliveClosure { + protected: + template void do_oop_work(T* p); public: KeepAliveClosure(ScanWeakRefClosure* cl); - void do_oop(oop* p); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); }; class EvacuateFollowersClosureGeneral: public VoidClosure { - GenCollectedHeap* _gch; - int _level; - OopsInGenClosure* _scan_cur_or_nonheap; - OopsInGenClosure* _scan_older; - public: - EvacuateFollowersClosureGeneral(GenCollectedHeap* gch, int level, - OopsInGenClosure* cur, - OopsInGenClosure* older); - void do_void(); + private: + GenCollectedHeap* _gch; + int _level; + OopsInGenClosure* _scan_cur_or_nonheap; + OopsInGenClosure* _scan_older; + public: + EvacuateFollowersClosureGeneral(GenCollectedHeap* gch, int level, + OopsInGenClosure* cur, + OopsInGenClosure* older); + virtual void do_void(); }; // Closure for scanning ParNewGeneration. // Same as ScanClosure, except does parallel GC barrier. class ScanClosureWithParBarrier: public ScanClosure { -public: + protected: + template void do_oop_work(T* p); + public: ScanClosureWithParBarrier(ParNewGeneration* g, bool gc_barrier); - void do_oop(oop* p); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); }; // Implements AbstractRefProcTaskExecutor for ParNew. class ParNewRefProcTaskExecutor: public AbstractRefProcTaskExecutor { -public: - + private: + ParNewGeneration& _generation; + ParScanThreadStateSet& _state_set; + public: ParNewRefProcTaskExecutor(ParNewGeneration& generation, ParScanThreadStateSet& state_set) : _generation(generation), _state_set(state_set) @@ -255,9 +268,6 @@ public: virtual void execute(EnqueueTask& task); // Switch to single threaded mode. virtual void set_single_threaded_mode(); -private: - ParNewGeneration& _generation; - ParScanThreadStateSet& _state_set; }; @@ -269,6 +279,7 @@ class ParNewGeneration: public DefNewGeneration { friend class ParNewRefProcTaskExecutor; friend class ParScanThreadStateSet; + private: // XXX use a global constant instead of 64! struct ObjToScanQueuePadded { ObjToScanQueue work_queue; @@ -314,7 +325,7 @@ class ParNewGeneration: public DefNewGeneration { // the details of the policy. virtual void adjust_desired_tenuring_threshold(); -public: + public: ParNewGeneration(ReservedSpace rs, size_t initial_byte_size, int level); ~ParNewGeneration() { diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.hpp b/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.hpp index 463127f1a7d..eac7668d939 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.hpp @@ -26,70 +26,77 @@ class ParScanThreadState; class ParNewGeneration; -template class GenericTaskQueueSet; -typedef GenericTaskQueueSet ObjToScanQueueSet; +typedef OopTaskQueueSet ObjToScanQueueSet; class ParallelTaskTerminator; class ParScanClosure: public OopsInGenClosure { -protected: + protected: ParScanThreadState* _par_scan_state; - ParNewGeneration* _g; - HeapWord* _boundary; - void do_oop_work(oop* p, - bool gc_barrier, - bool root_scan); - - void par_do_barrier(oop* p); - -public: + ParNewGeneration* _g; + HeapWord* _boundary; + template void inline par_do_barrier(T* p); + template void inline do_oop_work(T* p, + bool gc_barrier, + bool root_scan); + public: ParScanClosure(ParNewGeneration* g, ParScanThreadState* par_scan_state); }; class ParScanWithBarrierClosure: public ParScanClosure { -public: - void do_oop(oop* p) { do_oop_work(p, true, false); } - void do_oop_nv(oop* p) { do_oop_work(p, true, false); } + public: ParScanWithBarrierClosure(ParNewGeneration* g, ParScanThreadState* par_scan_state) : ParScanClosure(g, par_scan_state) {} + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); }; class ParScanWithoutBarrierClosure: public ParScanClosure { -public: + public: ParScanWithoutBarrierClosure(ParNewGeneration* g, ParScanThreadState* par_scan_state) : ParScanClosure(g, par_scan_state) {} - void do_oop(oop* p) { do_oop_work(p, false, false); } - void do_oop_nv(oop* p) { do_oop_work(p, false, false); } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); }; class ParRootScanWithBarrierTwoGensClosure: public ParScanClosure { -public: + public: ParRootScanWithBarrierTwoGensClosure(ParNewGeneration* g, ParScanThreadState* par_scan_state) : ParScanClosure(g, par_scan_state) {} - void do_oop(oop* p) { do_oop_work(p, true, true); } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); }; class ParRootScanWithoutBarrierClosure: public ParScanClosure { -public: + public: ParRootScanWithoutBarrierClosure(ParNewGeneration* g, ParScanThreadState* par_scan_state) : ParScanClosure(g, par_scan_state) {} - void do_oop(oop* p) { do_oop_work(p, false, true); } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); }; class ParScanWeakRefClosure: public ScanWeakRefClosure { -protected: + protected: ParScanThreadState* _par_scan_state; -public: + template inline void do_oop_work(T* p); + public: ParScanWeakRefClosure(ParNewGeneration* g, ParScanThreadState* par_scan_state); - void do_oop(oop* p); - void do_oop_nv(oop* p); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); }; class ParEvacuateFollowersClosure: public VoidClosure { + private: ParScanThreadState* _par_scan_state; ParScanThreadState* par_scan_state() { return _par_scan_state; } @@ -121,8 +128,7 @@ class ParEvacuateFollowersClosure: public VoidClosure { ParallelTaskTerminator* _terminator; ParallelTaskTerminator* terminator() { return _terminator; } - -public: + public: ParEvacuateFollowersClosure( ParScanThreadState* par_scan_state_, ParScanWithoutBarrierClosure* to_space_closure_, @@ -132,5 +138,5 @@ public: ParRootScanWithBarrierTwoGensClosure* old_gen_root_closure_, ObjToScanQueueSet* task_queues_, ParallelTaskTerminator* terminator_); - void do_void(); + virtual void do_void(); }; diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.inline.hpp b/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.inline.hpp index 3b38b3a2df5..d84f1289973 100644 --- a/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.inline.hpp @@ -22,10 +22,9 @@ * */ -inline void ParScanWeakRefClosure::do_oop(oop* p) -{ - oop obj = *p; - assert (obj != NULL, "null weak reference?"); +template inline void ParScanWeakRefClosure::do_oop_work(T* p) { + assert (!oopDesc::is_null(*p), "null weak reference?"); + oop obj = oopDesc::load_decode_heap_oop_not_null(p); // weak references are sometimes scanned twice; must check // that to-space doesn't already contain this object if ((HeapWord*)obj < _boundary && !_g->to()->is_in_reserved(obj)) { @@ -33,41 +32,43 @@ inline void ParScanWeakRefClosure::do_oop(oop* p) // ParScanClosure::do_oop_work). klassOop objK = obj->klass(); markOop m = obj->mark(); + oop new_obj; if (m->is_marked()) { // Contains forwarding pointer. - *p = ParNewGeneration::real_forwardee(obj); + new_obj = ParNewGeneration::real_forwardee(obj); } else { size_t obj_sz = obj->size_given_klass(objK->klass_part()); - *p = ((ParNewGeneration*)_g)->copy_to_survivor_space(_par_scan_state, - obj, obj_sz, m); + new_obj = ((ParNewGeneration*)_g)->copy_to_survivor_space(_par_scan_state, + obj, obj_sz, m); } + oopDesc::encode_store_heap_oop_not_null(p, new_obj); } } -inline void ParScanWeakRefClosure::do_oop_nv(oop* p) -{ - ParScanWeakRefClosure::do_oop(p); -} +inline void ParScanWeakRefClosure::do_oop_nv(oop* p) { ParScanWeakRefClosure::do_oop_work(p); } +inline void ParScanWeakRefClosure::do_oop_nv(narrowOop* p) { ParScanWeakRefClosure::do_oop_work(p); } -inline void ParScanClosure::par_do_barrier(oop* p) { +template inline void ParScanClosure::par_do_barrier(T* p) { assert(generation()->is_in_reserved(p), "expected ref in generation"); - oop obj = *p; - assert(obj != NULL, "expected non-null object"); + assert(!oopDesc::is_null(*p), "expected non-null object"); + oop obj = oopDesc::load_decode_heap_oop_not_null(p); // If p points to a younger generation, mark the card. if ((HeapWord*)obj < gen_boundary()) { rs()->write_ref_field_gc_par(p, obj); } } -inline void ParScanClosure::do_oop_work(oop* p, +template +inline void ParScanClosure::do_oop_work(T* p, bool gc_barrier, bool root_scan) { - oop obj = *p; assert((!Universe::heap()->is_in_reserved(p) || generation()->is_in_reserved(p)) && (generation()->level() == 0 || gc_barrier), "The gen must be right, and we must be doing the barrier " "in older generations."); - if (obj != NULL) { + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); if ((HeapWord*)obj < _boundary) { assert(!_g->to()->is_in_reserved(obj), "Scanning field twice?"); // OK, we need to ensure that it is copied. @@ -78,11 +79,14 @@ inline void ParScanClosure::do_oop_work(oop* p, // forwarded. klassOop objK = obj->klass(); markOop m = obj->mark(); + oop new_obj; if (m->is_marked()) { // Contains forwarding pointer. - *p = ParNewGeneration::real_forwardee(obj); + new_obj = ParNewGeneration::real_forwardee(obj); + oopDesc::encode_store_heap_oop_not_null(p, new_obj); } else { size_t obj_sz = obj->size_given_klass(objK->klass_part()); - *p = _g->copy_to_survivor_space(_par_scan_state, obj, obj_sz, m); + new_obj = _g->copy_to_survivor_space(_par_scan_state, obj, obj_sz, m); + oopDesc::encode_store_heap_oop_not_null(p, new_obj); if (root_scan) { // This may have pushed an object. If we have a root // category with a lot of roots, can't let the queue get too @@ -97,3 +101,9 @@ inline void ParScanClosure::do_oop_work(oop* p, } } } + +inline void ParScanWithBarrierClosure::do_oop_nv(oop* p) { ParScanClosure::do_oop_work(p, true, false); } +inline void ParScanWithBarrierClosure::do_oop_nv(narrowOop* p) { ParScanClosure::do_oop_work(p, true, false); } + +inline void ParScanWithoutBarrierClosure::do_oop_nv(oop* p) { ParScanClosure::do_oop_work(p, false, false); } +inline void ParScanWithoutBarrierClosure::do_oop_nv(narrowOop* p) { ParScanClosure::do_oop_work(p, false, false); } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp index 9857b4e6c6a..2b2c6f87c51 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp @@ -28,17 +28,16 @@ // Checks an individual oop for missing precise marks. Mark // may be either dirty or newgen. class CheckForUnmarkedOops : public OopClosure { - PSYoungGen* _young_gen; + private: + PSYoungGen* _young_gen; CardTableExtension* _card_table; - HeapWord* _unmarked_addr; - jbyte* _unmarked_card; + HeapWord* _unmarked_addr; + jbyte* _unmarked_card; - public: - CheckForUnmarkedOops( PSYoungGen* young_gen, CardTableExtension* card_table ) : - _young_gen(young_gen), _card_table(card_table), _unmarked_addr(NULL) { } - - virtual void do_oop(oop* p) { - if (_young_gen->is_in_reserved(*p) && + protected: + template void do_oop_work(T* p) { + oop obj = oopDesc::load_decode_heap_oop_not_null(p); + if (_young_gen->is_in_reserved(obj) && !_card_table->addr_is_marked_imprecise(p)) { // Don't overwrite the first missing card mark if (_unmarked_addr == NULL) { @@ -48,6 +47,13 @@ class CheckForUnmarkedOops : public OopClosure { } } + public: + CheckForUnmarkedOops(PSYoungGen* young_gen, CardTableExtension* card_table) : + _young_gen(young_gen), _card_table(card_table), _unmarked_addr(NULL) { } + + virtual void do_oop(oop* p) { CheckForUnmarkedOops::do_oop_work(p); } + virtual void do_oop(narrowOop* p) { CheckForUnmarkedOops::do_oop_work(p); } + bool has_unmarked_oop() { return _unmarked_addr != NULL; } @@ -56,7 +62,8 @@ class CheckForUnmarkedOops : public OopClosure { // Checks all objects for the existance of some type of mark, // precise or imprecise, dirty or newgen. class CheckForUnmarkedObjects : public ObjectClosure { - PSYoungGen* _young_gen; + private: + PSYoungGen* _young_gen; CardTableExtension* _card_table; public: @@ -75,7 +82,7 @@ class CheckForUnmarkedObjects : public ObjectClosure { // we test for missing precise marks first. If any are found, we don't // fail unless the object head is also unmarked. virtual void do_object(oop obj) { - CheckForUnmarkedOops object_check( _young_gen, _card_table ); + CheckForUnmarkedOops object_check(_young_gen, _card_table); obj->oop_iterate(&object_check); if (object_check.has_unmarked_oop()) { assert(_card_table->addr_is_marked_imprecise(obj), "Found unmarked young_gen object"); @@ -85,19 +92,25 @@ class CheckForUnmarkedObjects : public ObjectClosure { // Checks for precise marking of oops as newgen. class CheckForPreciseMarks : public OopClosure { - PSYoungGen* _young_gen; + private: + PSYoungGen* _young_gen; CardTableExtension* _card_table; + protected: + template void do_oop_work(T* p) { + oop obj = oopDesc::load_decode_heap_oop_not_null(p); + if (_young_gen->is_in_reserved(obj)) { + assert(_card_table->addr_is_marked_precise(p), "Found unmarked precise oop"); + _card_table->set_card_newgen(p); + } + } + public: CheckForPreciseMarks( PSYoungGen* young_gen, CardTableExtension* card_table ) : _young_gen(young_gen), _card_table(card_table) { } - virtual void do_oop(oop* p) { - if (_young_gen->is_in_reserved(*p)) { - assert(_card_table->addr_is_marked_precise(p), "Found unmarked precise oop"); - _card_table->set_card_newgen(p); - } - } + virtual void do_oop(oop* p) { CheckForPreciseMarks::do_oop_work(p); } + virtual void do_oop(narrowOop* p) { CheckForPreciseMarks::do_oop_work(p); } }; // We get passed the space_top value to prevent us from traversing into diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.hpp index 39c03a9412a..8722e0f3b28 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.hpp @@ -80,7 +80,7 @@ class CardTableExtension : public CardTableModRefBS { static bool card_is_verify(int value) { return value == verify_card; } // Card marking - void inline_write_ref_field_gc(oop* field, oop new_val) { + void inline_write_ref_field_gc(void* field, oop new_val) { jbyte* byte = byte_for(field); *byte = youngergen_card; } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp index 8088f0c5d0d..6fd50b39fc5 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp @@ -590,6 +590,31 @@ HeapWord* ParallelScavengeHeap::permanent_mem_allocate(size_t size) { full_gc_count = Universe::heap()->total_full_collections(); result = perm_gen()->allocate_permanent(size); + + if (result != NULL) { + return result; + } + + if (GC_locker::is_active_and_needs_gc()) { + // If this thread is not in a jni critical section, we stall + // the requestor until the critical section has cleared and + // GC allowed. When the critical section clears, a GC is + // initiated by the last thread exiting the critical section; so + // we retry the allocation sequence from the beginning of the loop, + // rather than causing more, now probably unnecessary, GC attempts. + JavaThread* jthr = JavaThread::current(); + if (!jthr->in_critical()) { + MutexUnlocker mul(Heap_lock); + GC_locker::stall_until_clear(); + continue; + } else { + if (CheckJNICalls) { + fatal("Possible deadlock due to allocating while" + " in jni critical section"); + } + return NULL; + } + } } if (result == NULL) { @@ -622,6 +647,12 @@ HeapWord* ParallelScavengeHeap::permanent_mem_allocate(size_t size) { if (op.prologue_succeeded()) { assert(Universe::heap()->is_in_permanent_or_null(op.result()), "result not in heap"); + // If GC was locked out during VM operation then retry allocation + // and/or stall as necessary. + if (op.gc_locked()) { + assert(op.result() == NULL, "must be NULL if gc_locked() is true"); + continue; // retry and/or stall as necessary + } // If a NULL results is being returned, an out-of-memory // will be thrown now. Clear the gc_time_limit_exceeded // flag to avoid the following situation. diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp index 6ea9b35f984..d26eec48882 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp @@ -169,8 +169,9 @@ class ParallelScavengeHeap : public CollectedHeap { size_t large_typearray_limit() { return FastAllocateSizeLimit; } bool supports_inline_contig_alloc() const { return !UseNUMA; } - HeapWord** top_addr() const { return !UseNUMA ? young_gen()->top_addr() : NULL; } - HeapWord** end_addr() const { return !UseNUMA ? young_gen()->end_addr() : NULL; } + + HeapWord** top_addr() const { return !UseNUMA ? young_gen()->top_addr() : (HeapWord**)-1; } + HeapWord** end_addr() const { return !UseNUMA ? young_gen()->end_addr() : (HeapWord**)-1; } void ensure_parsability(bool retire_tlabs); void accumulate_statistics_all_tlabs(); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp index a4f8878b2c3..994e627ed9d 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp @@ -146,7 +146,7 @@ void RefProcTaskExecutor::execute(ProcessTask& task) { ParallelScavengeHeap* heap = PSParallelCompact::gc_heap(); uint parallel_gc_threads = heap->gc_task_manager()->workers(); - TaskQueueSetSuper* qset = ParCompactionManager::chunk_array(); + ChunkTaskQueueSet* qset = ParCompactionManager::chunk_array(); ParallelTaskTerminator terminator(parallel_gc_threads, qset); GCTaskQueue* q = GCTaskQueue::create(); for(uint i=0; imark_addr(), 0); + template inline void* push_and_pop(T* p) { + oop o = oopDesc::load_decode_heap_oop_not_null(p); + Prefetch::write(o->mark_addr(), 0); // This prefetch is intended to make sure the size field of array // oops is in cache. It assumes the the object layout is // mark -> klass -> size, and that mark and klass are heapword // sized. If this should change, this prefetch will need updating! - Prefetch::write((*p)->mark_addr() + (HeapWordSize*2), 0); + Prefetch::write(o->mark_addr() + (HeapWordSize*2), 0); _prefetch_queue[_prefetch_index++] = p; _prefetch_index &= (PREFETCH_QUEUE_SIZE-1); return _prefetch_queue[_prefetch_index]; } // Stores a NULL pointer in the pop'd location. - inline oop* pop() { + inline void* pop() { _prefetch_queue[_prefetch_index++] = NULL; _prefetch_index &= (PREFETCH_QUEUE_SIZE-1); return _prefetch_queue[_prefetch_index]; diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp index 3afd47d0582..cec3a48db1a 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp @@ -168,7 +168,7 @@ void PSMarkSweepDecorator::precompact() { start_array->allocate_block(compact_top); } - debug_only(MarkSweep::register_live_oop(oop(q), size)); + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::register_live_oop(oop(q), size)); compact_top += size; assert(compact_top <= dest->space()->end(), "Exceeding space in destination"); @@ -234,7 +234,7 @@ void PSMarkSweepDecorator::precompact() { start_array->allocate_block(compact_top); } - debug_only(MarkSweep::register_live_oop(oop(q), sz)); + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::register_live_oop(oop(q), sz)); compact_top += sz; assert(compact_top <= dest->space()->end(), "Exceeding space in destination"); @@ -326,15 +326,11 @@ void PSMarkSweepDecorator::adjust_pointers() { HeapWord* end = _first_dead; while (q < end) { - debug_only(MarkSweep::track_interior_pointers(oop(q))); - + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q))); // point all the oops to the new location size_t size = oop(q)->adjust_pointers(); - - debug_only(MarkSweep::check_interior_pointers()); - - debug_only(MarkSweep::validate_live_oop(oop(q), size)); - + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers()); + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size)); q += size; } @@ -354,11 +350,11 @@ void PSMarkSweepDecorator::adjust_pointers() { Prefetch::write(q, interval); if (oop(q)->is_gc_marked()) { // q is alive - debug_only(MarkSweep::track_interior_pointers(oop(q))); + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q))); // point all the oops to the new location size_t size = oop(q)->adjust_pointers(); - debug_only(MarkSweep::check_interior_pointers()); - debug_only(MarkSweep::validate_live_oop(oop(q), size)); + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers()); + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size)); debug_only(prev_q = q); q += size; } else { @@ -392,7 +388,7 @@ void PSMarkSweepDecorator::compact(bool mangle_free_space ) { while (q < end) { size_t size = oop(q)->size(); assert(!oop(q)->is_gc_marked(), "should be unmarked (special dense prefix handling)"); - debug_only(MarkSweep::live_oop_moved_to(q, size, q)); + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::live_oop_moved_to(q, size, q)); debug_only(prev_q = q); q += size; } @@ -427,7 +423,7 @@ void PSMarkSweepDecorator::compact(bool mangle_free_space ) { Prefetch::write(compaction_top, copy_interval); // copy object and reinit its mark - debug_only(MarkSweep::live_oop_moved_to(q, size, compaction_top)); + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::live_oop_moved_to(q, size, compaction_top)); assert(q != compaction_top, "everything in this pass should be moving"); Copy::aligned_conjoint_words(q, compaction_top, size); oop(compaction_top)->init_mark(); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp index d7277b14564..98b347cf6e1 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp @@ -81,14 +81,14 @@ bool PSParallelCompact::_dwl_initialized = false; #endif // #ifdef ASSERT #ifdef VALIDATE_MARK_SWEEP -GrowableArray* PSParallelCompact::_root_refs_stack = NULL; +GrowableArray* PSParallelCompact::_root_refs_stack = NULL; GrowableArray * PSParallelCompact::_live_oops = NULL; GrowableArray * PSParallelCompact::_live_oops_moved_to = NULL; GrowableArray* PSParallelCompact::_live_oops_size = NULL; size_t PSParallelCompact::_live_oops_index = 0; size_t PSParallelCompact::_live_oops_index_at_perm = 0; -GrowableArray* PSParallelCompact::_other_refs_stack = NULL; -GrowableArray* PSParallelCompact::_adjusted_pointers = NULL; +GrowableArray* PSParallelCompact::_other_refs_stack = NULL; +GrowableArray* PSParallelCompact::_adjusted_pointers = NULL; bool PSParallelCompact::_pointer_tracking = false; bool PSParallelCompact::_root_tracking = true; @@ -811,46 +811,23 @@ ParMarkBitMap PSParallelCompact::_mark_bitmap; ParallelCompactData PSParallelCompact::_summary_data; PSParallelCompact::IsAliveClosure PSParallelCompact::_is_alive_closure; + +void PSParallelCompact::IsAliveClosure::do_object(oop p) { ShouldNotReachHere(); } +bool PSParallelCompact::IsAliveClosure::do_object_b(oop p) { return mark_bitmap()->is_marked(p); } + +void PSParallelCompact::KeepAliveClosure::do_oop(oop* p) { PSParallelCompact::KeepAliveClosure::do_oop_work(p); } +void PSParallelCompact::KeepAliveClosure::do_oop(narrowOop* p) { PSParallelCompact::KeepAliveClosure::do_oop_work(p); } + PSParallelCompact::AdjustPointerClosure PSParallelCompact::_adjust_root_pointer_closure(true); PSParallelCompact::AdjustPointerClosure PSParallelCompact::_adjust_pointer_closure(false); -void PSParallelCompact::KeepAliveClosure::do_oop(oop* p) { -#ifdef VALIDATE_MARK_SWEEP - if (ValidateMarkSweep) { - if (!Universe::heap()->is_in_reserved(p)) { - _root_refs_stack->push(p); - } else { - _other_refs_stack->push(p); - } - } -#endif - mark_and_push(_compaction_manager, p); -} +void PSParallelCompact::AdjustPointerClosure::do_oop(oop* p) { adjust_pointer(p, _is_root); } +void PSParallelCompact::AdjustPointerClosure::do_oop(narrowOop* p) { adjust_pointer(p, _is_root); } -void PSParallelCompact::mark_and_follow(ParCompactionManager* cm, - oop* p) { - assert(Universe::heap()->is_in_reserved(p), - "we should only be traversing objects here"); - oop m = *p; - if (m != NULL && mark_bitmap()->is_unmarked(m)) { - if (mark_obj(m)) { - m->follow_contents(cm); // Follow contents of the marked object - } - } -} +void PSParallelCompact::FollowStackClosure::do_void() { follow_stack(_compaction_manager); } -// Anything associated with this variable is temporary. - -void PSParallelCompact::mark_and_push_internal(ParCompactionManager* cm, - oop* p) { - // Push marked object, contents will be followed later - oop m = *p; - if (mark_obj(m)) { - // This thread marked the object and - // owns the subsequent processing of it. - cm->save_for_scanning(m); - } -} +void PSParallelCompact::MarkAndPushClosure::do_oop(oop* p) { mark_and_push(_compaction_manager, p); } +void PSParallelCompact::MarkAndPushClosure::do_oop(narrowOop* p) { mark_and_push(_compaction_manager, p); } void PSParallelCompact::post_initialize() { ParallelScavengeHeap* heap = gc_heap(); @@ -999,7 +976,7 @@ void PSParallelCompact::pre_compact(PreGCValues* pre_gc_values) DEBUG_ONLY(mark_bitmap_count = mark_bitmap_size = 0;) // Increment the invocation count - heap->increment_total_collections(); + heap->increment_total_collections(true); // We need to track unique mark sweep invocations as well. _total_invocations++; @@ -1964,7 +1941,7 @@ void PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); assert(ref_processor() != NULL, "Sanity"); - if (GC_locker::is_active()) { + if (GC_locker::check_active_before_gc()) { return; } @@ -2751,23 +2728,6 @@ void PSParallelCompact::compact_serial(ParCompactionManager* cm) { young_gen->move_and_update(cm); } -void PSParallelCompact::follow_root(ParCompactionManager* cm, oop* p) { - assert(!Universe::heap()->is_in_reserved(p), - "roots shouldn't be things within the heap"); -#ifdef VALIDATE_MARK_SWEEP - if (ValidateMarkSweep) { - guarantee(!_root_refs_stack->contains(p), "should only be in here once"); - _root_refs_stack->push(p); - } -#endif - oop m = *p; - if (m != NULL && mark_bitmap()->is_unmarked(m)) { - if (mark_obj(m)) { - m->follow_contents(cm); // Follow contents of the marked object - } - } - follow_stack(cm); -} void PSParallelCompact::follow_stack(ParCompactionManager* cm) { while(!cm->overflow_stack()->is_empty()) { @@ -2807,7 +2767,7 @@ PSParallelCompact::revisit_weak_klass_link(ParCompactionManager* cm, Klass* k) { #ifdef VALIDATE_MARK_SWEEP -void PSParallelCompact::track_adjusted_pointer(oop* p, oop newobj, bool isroot) { +void PSParallelCompact::track_adjusted_pointer(void* p, bool isroot) { if (!ValidateMarkSweep) return; @@ -2821,7 +2781,7 @@ void PSParallelCompact::track_adjusted_pointer(oop* p, oop newobj, bool isroot) if (index != -1) { int l = _root_refs_stack->length(); if (l > 0 && l - 1 != index) { - oop* last = _root_refs_stack->pop(); + void* last = _root_refs_stack->pop(); assert(last != p, "should be different"); _root_refs_stack->at_put(index, last); } else { @@ -2832,7 +2792,7 @@ void PSParallelCompact::track_adjusted_pointer(oop* p, oop newobj, bool isroot) } -void PSParallelCompact::check_adjust_pointer(oop* p) { +void PSParallelCompact::check_adjust_pointer(void* p) { _adjusted_pointers->push(p); } @@ -2840,7 +2800,8 @@ void PSParallelCompact::check_adjust_pointer(oop* p) { class AdjusterTracker: public OopClosure { public: AdjusterTracker() {}; - void do_oop(oop* o) { PSParallelCompact::check_adjust_pointer(o); } + void do_oop(oop* o) { PSParallelCompact::check_adjust_pointer(o); } + void do_oop(narrowOop* o) { PSParallelCompact::check_adjust_pointer(o); } }; @@ -2948,25 +2909,6 @@ void PSParallelCompact::print_new_location_of_heap_address(HeapWord* q) { } #endif //VALIDATE_MARK_SWEEP -void PSParallelCompact::adjust_pointer(oop* p, bool isroot) { - oop obj = *p; - VALIDATE_MARK_SWEEP_ONLY(oop saved_new_pointer = NULL); - if (obj != NULL) { - oop new_pointer = (oop) summary_data().calc_new_pointer(obj); - assert(new_pointer != NULL || // is forwarding ptr? - obj->is_shared(), // never forwarded? - "should have a new location"); - // Just always do the update unconditionally? - if (new_pointer != NULL) { - *p = new_pointer; - assert(Universe::heap()->is_in_reserved(new_pointer), - "should be in object space"); - VALIDATE_MARK_SWEEP_ONLY(saved_new_pointer = new_pointer); - } - } - VALIDATE_MARK_SWEEP_ONLY(track_adjusted_pointer(p, saved_new_pointer, isroot)); -} - // Update interior oops in the ranges of chunks [beg_chunk, end_chunk). void PSParallelCompact::update_and_deadwood_in_dense_prefix(ParCompactionManager* cm, diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp index f38ff2b985d..9566821169b 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp @@ -80,11 +80,11 @@ public: static const size_t ChunkSize; static const size_t ChunkSizeBytes; - // Mask for the bits in a size_t to get an offset within a chunk. + // Mask for the bits in a size_t to get an offset within a chunk. static const size_t ChunkSizeOffsetMask; - // Mask for the bits in a pointer to get an offset within a chunk. + // Mask for the bits in a pointer to get an offset within a chunk. static const size_t ChunkAddrOffsetMask; - // Mask for the bits in a pointer to get the address of the start of a chunk. + // Mask for the bits in a pointer to get the address of the start of a chunk. static const size_t ChunkAddrMask; static const size_t Log2BlockSize; @@ -229,7 +229,7 @@ public: // 1 bit marks the end of an object. class BlockData { - public: + public: typedef short int blk_ofs_t; blk_ofs_t offset() const { return _offset >= 0 ? _offset : -_offset; } @@ -269,7 +269,7 @@ public: return !_first_is_start_bit; } - private: + private: blk_ofs_t _offset; // This is temporary until the mark_bitmap is separated into // a start bit array and an end bit array. @@ -277,7 +277,7 @@ public: #ifdef ASSERT short _set_phase; static short _cur_phase; - public: + public: static void set_cur_phase(short v) { _cur_phase = v; } #endif }; @@ -729,48 +729,51 @@ class PSParallelCompact : AllStatic { } SpaceId; public: - // In line closure decls + // Inline closure decls // - class IsAliveClosure: public BoolObjectClosure { public: - void do_object(oop p) { assert(false, "don't call"); } - bool do_object_b(oop p) { return mark_bitmap()->is_marked(p); } + virtual void do_object(oop p); + virtual bool do_object_b(oop p); }; class KeepAliveClosure: public OopClosure { + private: ParCompactionManager* _compaction_manager; + protected: + template inline void do_oop_work(T* p); public: - KeepAliveClosure(ParCompactionManager* cm) { - _compaction_manager = cm; - } - void do_oop(oop* p); + KeepAliveClosure(ParCompactionManager* cm) : _compaction_manager(cm) { } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); }; - class FollowRootClosure: public OopsInGenClosure{ + // Current unused + class FollowRootClosure: public OopsInGenClosure { + private: ParCompactionManager* _compaction_manager; public: - FollowRootClosure(ParCompactionManager* cm) { - _compaction_manager = cm; - } - void do_oop(oop* p) { follow_root(_compaction_manager, p); } + FollowRootClosure(ParCompactionManager* cm) : _compaction_manager(cm) { } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); virtual const bool do_nmethods() const { return true; } }; class FollowStackClosure: public VoidClosure { + private: ParCompactionManager* _compaction_manager; public: - FollowStackClosure(ParCompactionManager* cm) { - _compaction_manager = cm; - } - void do_void() { follow_stack(_compaction_manager); } + FollowStackClosure(ParCompactionManager* cm) : _compaction_manager(cm) { } + virtual void do_void(); }; class AdjustPointerClosure: public OopsInGenClosure { + private: bool _is_root; public: - AdjustPointerClosure(bool is_root) : _is_root(is_root) {} - void do_oop(oop* p) { adjust_pointer(p, _is_root); } + AdjustPointerClosure(bool is_root) : _is_root(is_root) { } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); }; // Closure for verifying update of pointers. Does not @@ -805,8 +808,6 @@ class PSParallelCompact : AllStatic { friend class instanceKlassKlass; friend class RefProcTaskProxy; - static void mark_and_push_internal(ParCompactionManager* cm, oop* p); - private: static elapsedTimer _accumulated_time; static unsigned int _total_invocations; @@ -838,9 +839,9 @@ class PSParallelCompact : AllStatic { private: // Closure accessors - static OopClosure* adjust_pointer_closure() { return (OopClosure*)&_adjust_pointer_closure; } + static OopClosure* adjust_pointer_closure() { return (OopClosure*)&_adjust_pointer_closure; } static OopClosure* adjust_root_pointer_closure() { return (OopClosure*)&_adjust_root_pointer_closure; } - static BoolObjectClosure* is_alive_closure() { return (BoolObjectClosure*)&_is_alive_closure; } + static BoolObjectClosure* is_alive_closure() { return (BoolObjectClosure*)&_is_alive_closure; } static void initialize_space_info(); @@ -859,10 +860,11 @@ class PSParallelCompact : AllStatic { static void follow_stack(ParCompactionManager* cm); static void follow_weak_klass_links(ParCompactionManager* cm); - static void adjust_pointer(oop* p, bool is_root); + template static inline void adjust_pointer(T* p, bool is_root); static void adjust_root_pointer(oop* p) { adjust_pointer(p, true); } - static void follow_root(ParCompactionManager* cm, oop* p); + template + static inline void follow_root(ParCompactionManager* cm, T* p); // Compute the dense prefix for the designated space. This is an experimental // implementation currently not used in production. @@ -971,14 +973,14 @@ class PSParallelCompact : AllStatic { protected: #ifdef VALIDATE_MARK_SWEEP - static GrowableArray* _root_refs_stack; + static GrowableArray* _root_refs_stack; static GrowableArray * _live_oops; static GrowableArray * _live_oops_moved_to; static GrowableArray* _live_oops_size; static size_t _live_oops_index; static size_t _live_oops_index_at_perm; - static GrowableArray* _other_refs_stack; - static GrowableArray* _adjusted_pointers; + static GrowableArray* _other_refs_stack; + static GrowableArray* _adjusted_pointers; static bool _pointer_tracking; static bool _root_tracking; @@ -999,12 +1001,12 @@ class PSParallelCompact : AllStatic { public: class MarkAndPushClosure: public OopClosure { + private: ParCompactionManager* _compaction_manager; public: - MarkAndPushClosure(ParCompactionManager* cm) { - _compaction_manager = cm; - } - void do_oop(oop* p) { mark_and_push(_compaction_manager, p); } + MarkAndPushClosure(ParCompactionManager* cm) : _compaction_manager(cm) { } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); virtual const bool do_nmethods() const { return true; } }; @@ -1038,21 +1040,9 @@ class PSParallelCompact : AllStatic { // Marking support static inline bool mark_obj(oop obj); - static bool mark_obj(oop* p) { - if (*p != NULL) { - return mark_obj(*p); - } else { - return false; - } - } - static void mark_and_push(ParCompactionManager* cm, oop* p) { - // Check mark and maybe push on - // marking stack - oop m = *p; - if (m != NULL && mark_bitmap()->is_unmarked(m)) { - mark_and_push_internal(cm, p); - } - } + // Check mark and maybe push on marking stack + template static inline void mark_and_push(ParCompactionManager* cm, + T* p); // Compaction support. // Return true if p is in the range [beg_addr, end_addr). @@ -1127,13 +1117,17 @@ class PSParallelCompact : AllStatic { static void update_deferred_objects(ParCompactionManager* cm, SpaceId id); // Mark pointer and follow contents. - static void mark_and_follow(ParCompactionManager* cm, oop* p); + template + static inline void mark_and_follow(ParCompactionManager* cm, T* p); static ParMarkBitMap* mark_bitmap() { return &_mark_bitmap; } static ParallelCompactData& summary_data() { return _summary_data; } - static inline void adjust_pointer(oop* p) { adjust_pointer(p, false); } - static inline void adjust_pointer(oop* p, + static inline void adjust_pointer(oop* p) { adjust_pointer(p, false); } + static inline void adjust_pointer(narrowOop* p) { adjust_pointer(p, false); } + + template + static inline void adjust_pointer(T* p, HeapWord* beg_addr, HeapWord* end_addr); @@ -1147,8 +1141,8 @@ class PSParallelCompact : AllStatic { static jlong millis_since_last_gc(); #ifdef VALIDATE_MARK_SWEEP - static void track_adjusted_pointer(oop* p, oop newobj, bool isroot); - static void check_adjust_pointer(oop* p); // Adjust this pointer + static void track_adjusted_pointer(void* p, bool isroot); + static void check_adjust_pointer(void* p); static void track_interior_pointers(oop obj); static void check_interior_pointers(); @@ -1185,7 +1179,7 @@ class PSParallelCompact : AllStatic { #endif // #ifdef ASSERT }; -bool PSParallelCompact::mark_obj(oop obj) { +inline bool PSParallelCompact::mark_obj(oop obj) { const int obj_size = obj->size(); if (mark_bitmap()->mark_obj(obj, obj_size)) { _summary_data.add_obj(obj, obj_size); @@ -1195,13 +1189,94 @@ bool PSParallelCompact::mark_obj(oop obj) { } } -inline bool PSParallelCompact::print_phases() -{ +template +inline void PSParallelCompact::follow_root(ParCompactionManager* cm, T* p) { + assert(!Universe::heap()->is_in_reserved(p), + "roots shouldn't be things within the heap"); +#ifdef VALIDATE_MARK_SWEEP + if (ValidateMarkSweep) { + guarantee(!_root_refs_stack->contains(p), "should only be in here once"); + _root_refs_stack->push(p); + } +#endif + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + if (mark_bitmap()->is_unmarked(obj)) { + if (mark_obj(obj)) { + obj->follow_contents(cm); + } + } + } + follow_stack(cm); +} + +template +inline void PSParallelCompact::mark_and_follow(ParCompactionManager* cm, + T* p) { + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + if (mark_bitmap()->is_unmarked(obj)) { + if (mark_obj(obj)) { + obj->follow_contents(cm); + } + } + } +} + +template +inline void PSParallelCompact::mark_and_push(ParCompactionManager* cm, T* p) { + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + if (mark_bitmap()->is_unmarked(obj)) { + if (mark_obj(obj)) { + // This thread marked the object and owns the subsequent processing of it. + cm->save_for_scanning(obj); + } + } + } +} + +template +inline void PSParallelCompact::adjust_pointer(T* p, bool isroot) { + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + oop new_obj = (oop)summary_data().calc_new_pointer(obj); + assert(new_obj != NULL || // is forwarding ptr? + obj->is_shared(), // never forwarded? + "should be forwarded"); + // Just always do the update unconditionally? + if (new_obj != NULL) { + assert(Universe::heap()->is_in_reserved(new_obj), + "should be in object space"); + oopDesc::encode_store_heap_oop_not_null(p, new_obj); + } + } + VALIDATE_MARK_SWEEP_ONLY(track_adjusted_pointer(p, isroot)); +} + +template +inline void PSParallelCompact::KeepAliveClosure::do_oop_work(T* p) { +#ifdef VALIDATE_MARK_SWEEP + if (ValidateMarkSweep) { + if (!Universe::heap()->is_in_reserved(p)) { + _root_refs_stack->push(p); + } else { + _other_refs_stack->push(p); + } + } +#endif + mark_and_push(_compaction_manager, p); +} + +inline bool PSParallelCompact::print_phases() { return _print_phases; } -inline double PSParallelCompact::normal_distribution(double density) -{ +inline double PSParallelCompact::normal_distribution(double density) { assert(_dwl_initialized, "uninitialized"); const double squared_term = (density - _dwl_mean) / _dwl_std_dev; return _dwl_first_term * exp(-0.5 * squared_term * squared_term); @@ -1257,10 +1332,11 @@ inline bool PSParallelCompact::should_update_klass(klassOop k) { return ((HeapWord*) k) >= dense_prefix(perm_space_id); } -inline void PSParallelCompact::adjust_pointer(oop* p, +template +inline void PSParallelCompact::adjust_pointer(T* p, HeapWord* beg_addr, HeapWord* end_addr) { - if (is_in(p, beg_addr, end_addr)) { + if (is_in((HeapWord*)p, beg_addr, end_addr)) { adjust_pointer(p); } } @@ -1332,18 +1408,18 @@ class UpdateOnlyClosure: public ParMarkBitMapClosure { inline void do_addr(HeapWord* addr); }; -inline void UpdateOnlyClosure::do_addr(HeapWord* addr) { +inline void UpdateOnlyClosure::do_addr(HeapWord* addr) +{ _start_array->allocate_block(addr); oop(addr)->update_contents(compaction_manager()); } class FillClosure: public ParMarkBitMapClosure { -public: - FillClosure(ParCompactionManager* cm, PSParallelCompact::SpaceId space_id): + public: + FillClosure(ParCompactionManager* cm, PSParallelCompact::SpaceId space_id) : ParMarkBitMapClosure(PSParallelCompact::mark_bitmap(), cm), _space_id(space_id), - _start_array(PSParallelCompact::start_array(space_id)) - { + _start_array(PSParallelCompact::start_array(space_id)) { assert(_space_id == PSParallelCompact::perm_space_id || _space_id == PSParallelCompact::old_space_id, "cannot use FillClosure in the young gen"); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.cpp index 46b39edebd5..8a1893f2132 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.cpp @@ -25,7 +25,7 @@ #include "incls/_precompiled.incl" #include "incls/_psPromotionLAB.cpp.incl" -const size_t PSPromotionLAB::filler_header_size = align_object_size(typeArrayOopDesc::header_size(T_INT)); +size_t PSPromotionLAB::filler_header_size; // This is the shared initialization code. It sets up the basic pointers, // and allows enough extra space for a filler object. We call a virtual @@ -41,6 +41,10 @@ void PSPromotionLAB::initialize(MemRegion lab) { set_end(end); set_top(bottom); + // Initialize after VM starts up because header_size depends on compressed + // oops. + filler_header_size = align_object_size(typeArrayOopDesc::header_size(T_INT)); + // We can be initialized to a zero size! if (free() > 0) { if (ZapUnusedHeapArea) { diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp index fea56055377..ee8c2d78338 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp @@ -32,7 +32,7 @@ class ObjectStartArray; class PSPromotionLAB : public CHeapObj { protected: - static const size_t filler_header_size; + static size_t filler_header_size; enum LabState { needs_flush, diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp index ea31f391ad1..92a5002d80e 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp @@ -182,7 +182,7 @@ PSPromotionManager::PSPromotionManager() { claimed_stack_depth()->initialize(); queue_size = claimed_stack_depth()->max_elems(); // We want the overflow stack to be permanent - _overflow_stack_depth = new (ResourceObj::C_HEAP) GrowableArray(10, true); + _overflow_stack_depth = new (ResourceObj::C_HEAP) GrowableArray(10, true); _overflow_stack_breadth = NULL; } else { claimed_stack_breadth()->initialize(); @@ -240,6 +240,7 @@ void PSPromotionManager::reset() { #endif // PS_PM_STATS } + void PSPromotionManager::drain_stacks_depth(bool totally_drain) { assert(depth_first(), "invariant"); assert(overflow_stack_depth() != NULL, "invariant"); @@ -254,13 +255,15 @@ void PSPromotionManager::drain_stacks_depth(bool totally_drain) { #endif /* ASSERT */ do { - oop* p; + StarTask p; // Drain overflow stack first, so other threads can steal from // claimed stack while we work. while(!overflow_stack_depth()->is_empty()) { - p = overflow_stack_depth()->pop(); - process_popped_location_depth(p); + // linux compiler wants different overloaded operator= in taskqueue to + // assign to p that the other compilers don't like. + StarTask ptr = overflow_stack_depth()->pop(); + process_popped_location_depth(ptr); } if (totally_drain) { @@ -365,7 +368,7 @@ void PSPromotionManager::flush_labs() { // oop PSPromotionManager::copy_to_survivor_space(oop o, bool depth_first) { - assert(PSScavenge::should_scavenge(o), "Sanity"); + assert(PSScavenge::should_scavenge(&o), "Sanity"); oop new_obj = NULL; @@ -530,16 +533,30 @@ oop PSPromotionManager::copy_to_survivor_space(oop o, bool depth_first) { // This code must come after the CAS test, or it will print incorrect // information. if (TraceScavenge) { - gclog_or_tty->print_cr("{%s %s 0x%x -> 0x%x (%d)}", - PSScavenge::should_scavenge(new_obj) ? "copying" : "tenuring", + gclog_or_tty->print_cr("{%s %s " PTR_FORMAT " -> " PTR_FORMAT " (" SIZE_FORMAT ")}", + PSScavenge::should_scavenge(&new_obj) ? "copying" : "tenuring", new_obj->blueprint()->internal_name(), o, new_obj, new_obj->size()); - } #endif return new_obj; } +template void PSPromotionManager::process_array_chunk_work( + oop obj, + int start, int end) { + assert(start < end, "invariant"); + T* const base = (T*)objArrayOop(obj)->base(); + T* p = base + start; + T* const chunk_end = base + end; + while (p < chunk_end) { + if (PSScavenge::should_scavenge(p)) { + claim_or_forward_depth(p); + } + ++p; + } +} + void PSPromotionManager::process_array_chunk(oop old) { assert(PSChunkLargeArrays, "invariant"); assert(old->is_objArray(), "invariant"); @@ -569,15 +586,10 @@ void PSPromotionManager::process_array_chunk(oop old) { arrayOop(old)->set_length(actual_length); } - assert(start < end, "invariant"); - oop* const base = objArrayOop(obj)->base(); - oop* p = base + start; - oop* const chunk_end = base + end; - while (p < chunk_end) { - if (PSScavenge::should_scavenge(*p)) { - claim_or_forward_depth(p); - } - ++p; + if (UseCompressedOops) { + process_array_chunk_work(obj, start, end); + } else { + process_array_chunk_work(obj, start, end); } } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp index c40b016668f..b18674ea819 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp @@ -42,8 +42,6 @@ class MutableSpace; class PSOldGen; class ParCompactionManager; -#define PS_CHUNKED_ARRAY_OOP_MASK 1 - #define PS_PM_STATS 0 class PSPromotionManager : public CHeapObj { @@ -80,7 +78,7 @@ class PSPromotionManager : public CHeapObj { PrefetchQueue _prefetch_queue; OopStarTaskQueue _claimed_stack_depth; - GrowableArray* _overflow_stack_depth; + GrowableArray* _overflow_stack_depth; OopTaskQueue _claimed_stack_breadth; GrowableArray* _overflow_stack_breadth; @@ -92,13 +90,15 @@ class PSPromotionManager : public CHeapObj { uint _min_array_size_for_chunking; // Accessors - static PSOldGen* old_gen() { return _old_gen; } - static MutableSpace* young_space() { return _young_space; } + static PSOldGen* old_gen() { return _old_gen; } + static MutableSpace* young_space() { return _young_space; } inline static PSPromotionManager* manager_array(int index); + template inline void claim_or_forward_internal_depth(T* p); + template inline void claim_or_forward_internal_breadth(T* p); - GrowableArray* overflow_stack_depth() { return _overflow_stack_depth; } - GrowableArray* overflow_stack_breadth() { return _overflow_stack_breadth; } + GrowableArray* overflow_stack_depth() { return _overflow_stack_depth; } + GrowableArray* overflow_stack_breadth() { return _overflow_stack_breadth; } // On the task queues we push reference locations as well as // partially-scanned arrays (in the latter case, we push an oop to @@ -116,27 +116,37 @@ class PSPromotionManager : public CHeapObj { // (oop). We do all the necessary casting in the mask / unmask // methods to avoid sprinkling the rest of the code with more casts. - bool is_oop_masked(oop* p) { - return ((intptr_t) p & PS_CHUNKED_ARRAY_OOP_MASK) == PS_CHUNKED_ARRAY_OOP_MASK; + // These are added to the taskqueue so PS_CHUNKED_ARRAY_OOP_MASK (or any + // future masks) can't conflict with COMPRESSED_OOP_MASK +#define PS_CHUNKED_ARRAY_OOP_MASK 0x2 + + bool is_oop_masked(StarTask p) { + // If something is marked chunked it's always treated like wide oop* + return (((intptr_t)(oop*)p) & PS_CHUNKED_ARRAY_OOP_MASK) == + PS_CHUNKED_ARRAY_OOP_MASK; } oop* mask_chunked_array_oop(oop obj) { assert(!is_oop_masked((oop*) obj), "invariant"); - oop* ret = (oop*) ((intptr_t) obj | PS_CHUNKED_ARRAY_OOP_MASK); + oop* ret = (oop*) ((uintptr_t)obj | PS_CHUNKED_ARRAY_OOP_MASK); assert(is_oop_masked(ret), "invariant"); return ret; } - oop unmask_chunked_array_oop(oop* p) { + oop unmask_chunked_array_oop(StarTask p) { assert(is_oop_masked(p), "invariant"); - oop ret = oop((intptr_t) p & ~PS_CHUNKED_ARRAY_OOP_MASK); + assert(!p.is_narrow(), "chunked array oops cannot be narrow"); + oop *chunk = (oop*)p; // cast p to oop (uses conversion operator) + oop ret = oop((oop*)((uintptr_t)chunk & ~PS_CHUNKED_ARRAY_OOP_MASK)); assert(!is_oop_masked((oop*) ret), "invariant"); return ret; } + template void process_array_chunk_work(oop obj, + int start, int end); void process_array_chunk(oop old); - void push_depth(oop* p) { + template void push_depth(T* p) { assert(depth_first(), "pre-condition"); #if PS_PM_STATS @@ -175,7 +185,7 @@ class PSPromotionManager : public CHeapObj { } protected: - static OopStarTaskQueueSet* stack_array_depth() { return _stack_array_depth; } + static OopStarTaskQueueSet* stack_array_depth() { return _stack_array_depth; } static OopTaskQueueSet* stack_array_breadth() { return _stack_array_breadth; } public: @@ -227,6 +237,7 @@ class PSPromotionManager : public CHeapObj { drain_stacks_breadth(totally_drain); } } + public: void drain_stacks_cond_depth() { if (claimed_stack_depth()->size() > _target_stack_size) { drain_stacks_depth(false); @@ -256,15 +267,11 @@ class PSPromotionManager : public CHeapObj { return _depth_first; } - inline void process_popped_location_depth(oop* p); + inline void process_popped_location_depth(StarTask p); inline void flush_prefetch_queue(); - - inline void claim_or_forward_depth(oop* p); - inline void claim_or_forward_internal_depth(oop* p); - - inline void claim_or_forward_breadth(oop* p); - inline void claim_or_forward_internal_breadth(oop* p); + template inline void claim_or_forward_depth(T* p); + template inline void claim_or_forward_breadth(T* p); #if PS_PM_STATS void increment_steals(oop* p = NULL) { diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp index e900e0601cc..73cc15f32ae 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp @@ -28,64 +28,68 @@ inline PSPromotionManager* PSPromotionManager::manager_array(int index) { return _manager_array[index]; } -inline void PSPromotionManager::claim_or_forward_internal_depth(oop* p) { - if (p != NULL) { - oop o = *p; +template +inline void PSPromotionManager::claim_or_forward_internal_depth(T* p) { + if (p != NULL) { // XXX: error if p != NULL here + oop o = oopDesc::load_decode_heap_oop_not_null(p); if (o->is_forwarded()) { o = o->forwardee(); - // Card mark if (PSScavenge::is_obj_in_young((HeapWord*) o)) { PSScavenge::card_table()->inline_write_ref_field_gc(p, o); } - *p = o; + oopDesc::encode_store_heap_oop_not_null(p, o); } else { push_depth(p); } } } -inline void PSPromotionManager::claim_or_forward_internal_breadth(oop* p) { - if (p != NULL) { - oop o = *p; +template +inline void PSPromotionManager::claim_or_forward_internal_breadth(T* p) { + if (p != NULL) { // XXX: error if p != NULL here + oop o = oopDesc::load_decode_heap_oop_not_null(p); if (o->is_forwarded()) { o = o->forwardee(); } else { o = copy_to_survivor_space(o, false); } - // Card mark if (PSScavenge::is_obj_in_young((HeapWord*) o)) { PSScavenge::card_table()->inline_write_ref_field_gc(p, o); } - *p = o; + oopDesc::encode_store_heap_oop_not_null(p, o); } } inline void PSPromotionManager::flush_prefetch_queue() { assert(!depth_first(), "invariant"); - for (int i=0; i<_prefetch_queue.length(); i++) { - claim_or_forward_internal_breadth(_prefetch_queue.pop()); + for (int i = 0; i < _prefetch_queue.length(); i++) { + claim_or_forward_internal_breadth((oop*)_prefetch_queue.pop()); } } -inline void PSPromotionManager::claim_or_forward_depth(oop* p) { +template +inline void PSPromotionManager::claim_or_forward_depth(T* p) { assert(depth_first(), "invariant"); - assert(PSScavenge::should_scavenge(*p, true), "revisiting object?"); - assert(Universe::heap()->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); + assert(PSScavenge::should_scavenge(p, true), "revisiting object?"); + assert(Universe::heap()->kind() == CollectedHeap::ParallelScavengeHeap, + "Sanity"); assert(Universe::heap()->is_in(p), "pointer outside heap"); claim_or_forward_internal_depth(p); } -inline void PSPromotionManager::claim_or_forward_breadth(oop* p) { +template +inline void PSPromotionManager::claim_or_forward_breadth(T* p) { assert(!depth_first(), "invariant"); - assert(PSScavenge::should_scavenge(*p, true), "revisiting object?"); - assert(Universe::heap()->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); + assert(PSScavenge::should_scavenge(p, true), "revisiting object?"); + assert(Universe::heap()->kind() == CollectedHeap::ParallelScavengeHeap, + "Sanity"); assert(Universe::heap()->is_in(p), "pointer outside heap"); if (UsePrefetchQueue) { - claim_or_forward_internal_breadth(_prefetch_queue.push_and_pop(p)); + claim_or_forward_internal_breadth((T*)_prefetch_queue.push_and_pop(p)); } else { // This option is used for testing. The use of the prefetch // queue can delay the processing of the objects and thus @@ -106,12 +110,16 @@ inline void PSPromotionManager::claim_or_forward_breadth(oop* p) { } } -inline void PSPromotionManager::process_popped_location_depth(oop* p) { +inline void PSPromotionManager::process_popped_location_depth(StarTask p) { if (is_oop_masked(p)) { assert(PSChunkLargeArrays, "invariant"); oop const old = unmask_chunked_array_oop(p); process_array_chunk(old); } else { - PSScavenge::copy_and_push_safe_barrier(this, p); + if (p.is_narrow()) { + PSScavenge::copy_and_push_safe_barrier(this, (narrowOop*)p); + } else { + PSScavenge::copy_and_push_safe_barrier(this, (oop*)p); + } } } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp index 426337ddccb..5f960dc9ece 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp @@ -65,16 +65,18 @@ public: assert(_promotion_manager != NULL, "Sanity"); } - void do_oop(oop* p) { - assert (*p != NULL, "expected non-null ref"); - assert ((*p)->is_oop(), "expected an oop while scanning weak refs"); + template void do_oop_work(T* p) { + assert (!oopDesc::is_null(*p), "expected non-null ref"); + assert ((oopDesc::load_decode_heap_oop_not_null(p))->is_oop(), + "expected an oop while scanning weak refs"); - oop obj = oop(*p); // Weak refs may be visited more than once. - if (PSScavenge::should_scavenge(obj, _to_space)) { + if (PSScavenge::should_scavenge(p, _to_space)) { PSScavenge::copy_and_push_safe_barrier(_promotion_manager, p); } } + virtual void do_oop(oop* p) { PSKeepAliveClosure::do_oop_work(p); } + virtual void do_oop(narrowOop* p) { PSKeepAliveClosure::do_oop_work(p); } }; class PSEvacuateFollowersClosure: public VoidClosure { @@ -83,7 +85,7 @@ class PSEvacuateFollowersClosure: public VoidClosure { public: PSEvacuateFollowersClosure(PSPromotionManager* pm) : _promotion_manager(pm) {} - void do_void() { + virtual void do_void() { assert(_promotion_manager != NULL, "Sanity"); _promotion_manager->drain_stacks(true); guarantee(_promotion_manager->stacks_empty(), diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp index ff20b5bf63c..1f8ad940713 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp @@ -116,16 +116,16 @@ class PSScavenge: AllStatic { // If an attempt to promote fails, this method is invoked static void oop_promotion_failed(oop obj, markOop obj_mark); - static inline bool should_scavenge(oop p); + template static inline bool should_scavenge(T* p); // These call should_scavenge() above and, if it returns true, also check that // the object was not newly copied into to_space. The version with the bool // argument is a convenience wrapper that fetches the to_space pointer from // the heap and calls the other version (if the arg is true). - static inline bool should_scavenge(oop p, MutableSpace* to_space); - static inline bool should_scavenge(oop p, bool check_to_space); + template static inline bool should_scavenge(T* p, MutableSpace* to_space); + template static inline bool should_scavenge(T* p, bool check_to_space); - inline static void copy_and_push_safe_barrier(PSPromotionManager* pm, oop* p); + template inline static void copy_and_push_safe_barrier(PSPromotionManager* pm, T* p); // Is an object in the young generation // This assumes that the HeapWord argument is in the heap, diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp index ea61dc8f582..08b576c775e 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.inline.hpp @@ -22,28 +22,33 @@ * */ - inline void PSScavenge::save_to_space_top_before_gc() { ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); _to_space_top_before_gc = heap->young_gen()->to_space()->top(); } -inline bool PSScavenge::should_scavenge(oop p) { - return p == NULL ? false : PSScavenge::is_obj_in_young((HeapWord*) p); +template inline bool PSScavenge::should_scavenge(T* p) { + T heap_oop = oopDesc::load_heap_oop(p); + if (oopDesc::is_null(heap_oop)) return false; + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + return PSScavenge::is_obj_in_young((HeapWord*)obj); } -inline bool PSScavenge::should_scavenge(oop p, MutableSpace* to_space) { +template +inline bool PSScavenge::should_scavenge(T* p, MutableSpace* to_space) { if (should_scavenge(p)) { + oop obj = oopDesc::load_decode_heap_oop_not_null(p); // Skip objects copied to to_space since the scavenge started. - HeapWord* const addr = (HeapWord*) p; + HeapWord* const addr = (HeapWord*)obj; return addr < to_space_top_before_gc() || addr >= to_space->end(); } return false; } -inline bool PSScavenge::should_scavenge(oop p, bool check_to_space) { +template +inline bool PSScavenge::should_scavenge(T* p, bool check_to_space) { if (check_to_space) { - ParallelScavengeHeap* heap = (ParallelScavengeHeap*) Universe::heap(); + ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); return should_scavenge(p, heap->young_gen()->to_space()); } return should_scavenge(p); @@ -52,24 +57,23 @@ inline bool PSScavenge::should_scavenge(oop p, bool check_to_space) { // Attempt to "claim" oop at p via CAS, push the new obj if successful // This version tests the oop* to make sure it is within the heap before // attempting marking. +template inline void PSScavenge::copy_and_push_safe_barrier(PSPromotionManager* pm, - oop* p) { - assert(should_scavenge(*p, true), "revisiting object?"); + T* p) { + assert(should_scavenge(p, true), "revisiting object?"); - oop o = *p; - if (o->is_forwarded()) { - *p = o->forwardee(); - } else { - *p = pm->copy_to_survivor_space(o, pm->depth_first()); - } + oop o = oopDesc::load_decode_heap_oop_not_null(p); + oop new_obj = o->is_forwarded() + ? o->forwardee() + : pm->copy_to_survivor_space(o, pm->depth_first()); + oopDesc::encode_store_heap_oop_not_null(p, new_obj); // We cannot mark without test, as some code passes us pointers // that are outside the heap. - if ((!PSScavenge::is_obj_in_young((HeapWord*) p)) && + if ((!PSScavenge::is_obj_in_young((HeapWord*)p)) && Universe::heap()->is_in_reserved(p)) { - o = *p; - if (PSScavenge::is_obj_in_young((HeapWord*) o)) { - card_table()->inline_write_ref_field_gc(p, o); + if (PSScavenge::is_obj_in_young((HeapWord*)new_obj)) { + card_table()->inline_write_ref_field_gc(p, new_obj); } } } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp index 2e433358645..dd5d1045fc1 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp @@ -34,15 +34,17 @@ class PSScavengeRootsClosure: public OopClosure { private: PSPromotionManager* _promotion_manager; - public: - PSScavengeRootsClosure(PSPromotionManager* pm) : _promotion_manager(pm) { } - - virtual void do_oop(oop* p) { - if (PSScavenge::should_scavenge(*p)) { + protected: + template void do_oop_work(T *p) { + if (PSScavenge::should_scavenge(p)) { // We never card mark roots, maybe call a func without test? PSScavenge::copy_and_push_safe_barrier(_promotion_manager, p); } } + public: + PSScavengeRootsClosure(PSPromotionManager* pm) : _promotion_manager(pm) { } + void do_oop(oop* p) { PSScavengeRootsClosure::do_oop_work(p); } + void do_oop(narrowOop* p) { PSScavengeRootsClosure::do_oop_work(p); } }; void ScavengeRootsTask::do_it(GCTaskManager* manager, uint which) { @@ -135,7 +137,7 @@ void StealTask::do_it(GCTaskManager* manager, uint which) { int random_seed = 17; if (pm->depth_first()) { while(true) { - oop* p; + StarTask p; if (PSPromotionManager::steal_depth(which, &random_seed, p)) { #if PS_PM_STATS pm->increment_steals(p); @@ -164,8 +166,7 @@ void StealTask::do_it(GCTaskManager* manager, uint which) { } } } - guarantee(pm->stacks_empty(), - "stacks should be empty at this point"); + guarantee(pm->stacks_empty(), "stacks should be empty at this point"); } // diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp index 7f12cf55c55..0b21861397b 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp @@ -69,6 +69,9 @@ void VM_ParallelGCFailedPermanentAllocation::doit() { GCCauseSetter gccs(heap, _gc_cause); _result = heap->failed_permanent_mem_allocate(_size); + if (_result == NULL && GC_locker::is_active_and_needs_gc()) { + set_gc_locked(); + } notify_gc_end(); } diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp index e7d59db0bd0..ee77a7f52df 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp @@ -36,16 +36,16 @@ PreservedMark* MarkSweep::_preserved_marks = NULL; ReferenceProcessor* MarkSweep::_ref_processor = NULL; #ifdef VALIDATE_MARK_SWEEP -GrowableArray* MarkSweep::_root_refs_stack = NULL; +GrowableArray* MarkSweep::_root_refs_stack = NULL; GrowableArray * MarkSweep::_live_oops = NULL; GrowableArray * MarkSweep::_live_oops_moved_to = NULL; GrowableArray* MarkSweep::_live_oops_size = NULL; size_t MarkSweep::_live_oops_index = 0; size_t MarkSweep::_live_oops_index_at_perm = 0; -GrowableArray* MarkSweep::_other_refs_stack = NULL; -GrowableArray* MarkSweep::_adjusted_pointers = NULL; -bool MarkSweep::_pointer_tracking = false; -bool MarkSweep::_root_tracking = true; +GrowableArray* MarkSweep::_other_refs_stack = NULL; +GrowableArray* MarkSweep::_adjusted_pointers = NULL; +bool MarkSweep::_pointer_tracking = false; +bool MarkSweep::_root_tracking = true; GrowableArray* MarkSweep::_cur_gc_live_oops = NULL; GrowableArray* MarkSweep::_cur_gc_live_oops_moved_to = NULL; @@ -59,7 +59,6 @@ void MarkSweep::revisit_weak_klass_link(Klass* k) { _revisit_klass_stack->push(k); } - void MarkSweep::follow_weak_klass_links() { // All klasses on the revisit stack are marked at this point. // Update and follow all subklass, sibling and implementor links. @@ -69,44 +68,15 @@ void MarkSweep::follow_weak_klass_links() { follow_stack(); } +MarkSweep::FollowRootClosure MarkSweep::follow_root_closure; -void MarkSweep::mark_and_follow(oop* p) { - assert(Universe::heap()->is_in_reserved(p), - "we should only be traversing objects here"); - oop m = *p; - if (m != NULL && !m->mark()->is_marked()) { - mark_object(m); - m->follow_contents(); // Follow contents of the marked object - } -} - -void MarkSweep::_mark_and_push(oop* p) { - // Push marked object, contents will be followed later - oop m = *p; - mark_object(m); - _marking_stack->push(m); -} +void MarkSweep::FollowRootClosure::do_oop(oop* p) { follow_root(p); } +void MarkSweep::FollowRootClosure::do_oop(narrowOop* p) { follow_root(p); } MarkSweep::MarkAndPushClosure MarkSweep::mark_and_push_closure; -void MarkSweep::follow_root(oop* p) { - assert(!Universe::heap()->is_in_reserved(p), - "roots shouldn't be things within the heap"); -#ifdef VALIDATE_MARK_SWEEP - if (ValidateMarkSweep) { - guarantee(!_root_refs_stack->contains(p), "should only be in here once"); - _root_refs_stack->push(p); - } -#endif - oop m = *p; - if (m != NULL && !m->mark()->is_marked()) { - mark_object(m); - m->follow_contents(); // Follow contents of the marked object - } - follow_stack(); -} - -MarkSweep::FollowRootClosure MarkSweep::follow_root_closure; +void MarkSweep::MarkAndPushClosure::do_oop(oop* p) { mark_and_push(p); } +void MarkSweep::MarkAndPushClosure::do_oop(narrowOop* p) { mark_and_push(p); } void MarkSweep::follow_stack() { while (!_marking_stack->is_empty()) { @@ -118,6 +88,7 @@ void MarkSweep::follow_stack() { MarkSweep::FollowStackClosure MarkSweep::follow_stack_closure; +void MarkSweep::FollowStackClosure::do_void() { follow_stack(); } // We preserve the mark which should be replaced at the end and the location that it // will go. Note that the object that this markOop belongs to isn't currently at that @@ -142,6 +113,9 @@ void MarkSweep::preserve_mark(oop obj, markOop mark) { MarkSweep::AdjustPointerClosure MarkSweep::adjust_root_pointer_closure(true); MarkSweep::AdjustPointerClosure MarkSweep::adjust_pointer_closure(false); +void MarkSweep::AdjustPointerClosure::do_oop(oop* p) { adjust_pointer(p, _is_root); } +void MarkSweep::AdjustPointerClosure::do_oop(narrowOop* p) { adjust_pointer(p, _is_root); } + void MarkSweep::adjust_marks() { assert(_preserved_oop_stack == NULL || _preserved_oop_stack->length() == _preserved_mark_stack->length(), @@ -187,7 +161,7 @@ void MarkSweep::restore_marks() { #ifdef VALIDATE_MARK_SWEEP -void MarkSweep::track_adjusted_pointer(oop* p, oop newobj, bool isroot) { +void MarkSweep::track_adjusted_pointer(void* p, bool isroot) { if (!ValidateMarkSweep) return; @@ -201,7 +175,7 @@ void MarkSweep::track_adjusted_pointer(oop* p, oop newobj, bool isroot) { if (index != -1) { int l = _root_refs_stack->length(); if (l > 0 && l - 1 != index) { - oop* last = _root_refs_stack->pop(); + void* last = _root_refs_stack->pop(); assert(last != p, "should be different"); _root_refs_stack->at_put(index, last); } else { @@ -211,19 +185,17 @@ void MarkSweep::track_adjusted_pointer(oop* p, oop newobj, bool isroot) { } } - -void MarkSweep::check_adjust_pointer(oop* p) { +void MarkSweep::check_adjust_pointer(void* p) { _adjusted_pointers->push(p); } - class AdjusterTracker: public OopClosure { public: - AdjusterTracker() {}; - void do_oop(oop* o) { MarkSweep::check_adjust_pointer(o); } + AdjusterTracker() {} + void do_oop(oop* o) { MarkSweep::check_adjust_pointer(o); } + void do_oop(narrowOop* o) { MarkSweep::check_adjust_pointer(o); } }; - void MarkSweep::track_interior_pointers(oop obj) { if (ValidateMarkSweep) { _adjusted_pointers->clear(); @@ -234,7 +206,6 @@ void MarkSweep::track_interior_pointers(oop obj) { } } - void MarkSweep::check_interior_pointers() { if (ValidateMarkSweep) { _pointer_tracking = false; @@ -242,7 +213,6 @@ void MarkSweep::check_interior_pointers() { } } - void MarkSweep::reset_live_oop_tracking(bool at_perm) { if (ValidateMarkSweep) { guarantee((size_t)_live_oops->length() == _live_oops_index, "should be at end of live oops"); @@ -250,7 +220,6 @@ void MarkSweep::reset_live_oop_tracking(bool at_perm) { } } - void MarkSweep::register_live_oop(oop p, size_t size) { if (ValidateMarkSweep) { _live_oops->push(p); @@ -283,7 +252,6 @@ void MarkSweep::live_oop_moved_to(HeapWord* q, size_t size, } } - void MarkSweep::compaction_complete() { if (RecordMarkSweepCompaction) { GrowableArray* _tmp_live_oops = _cur_gc_live_oops; @@ -299,7 +267,6 @@ void MarkSweep::compaction_complete() { } } - void MarkSweep::print_new_location_of_heap_address(HeapWord* q) { if (!RecordMarkSweepCompaction) { tty->print_cr("Requires RecordMarkSweepCompaction to be enabled"); @@ -318,7 +285,7 @@ void MarkSweep::print_new_location_of_heap_address(HeapWord* q) { HeapWord* new_oop = _last_gc_live_oops_moved_to->at(i); size_t offset = (q - old_oop); tty->print_cr("Address " PTR_FORMAT, q); - tty->print_cr(" Was in oop " PTR_FORMAT ", size %d, at offset %d", old_oop, sz, offset); + tty->print_cr(" Was in oop " PTR_FORMAT ", size " SIZE_FORMAT ", at offset " SIZE_FORMAT, old_oop, sz, offset); tty->print_cr(" Now in oop " PTR_FORMAT ", actual address " PTR_FORMAT, new_oop, new_oop + offset); return; } @@ -328,23 +295,16 @@ void MarkSweep::print_new_location_of_heap_address(HeapWord* q) { } #endif //VALIDATE_MARK_SWEEP -MarkSweep::IsAliveClosure MarkSweep::is_alive; +MarkSweep::IsAliveClosure MarkSweep::is_alive; -void MarkSweep::KeepAliveClosure::do_oop(oop* p) { -#ifdef VALIDATE_MARK_SWEEP - if (ValidateMarkSweep) { - if (!Universe::heap()->is_in_reserved(p)) { - _root_refs_stack->push(p); - } else { - _other_refs_stack->push(p); - } - } -#endif - mark_and_push(p); -} +void MarkSweep::IsAliveClosure::do_object(oop p) { ShouldNotReachHere(); } +bool MarkSweep::IsAliveClosure::do_object_b(oop p) { return p->is_gc_marked(); } MarkSweep::KeepAliveClosure MarkSweep::keep_alive; +void MarkSweep::KeepAliveClosure::do_oop(oop* p) { MarkSweep::KeepAliveClosure::do_oop_work(p); } +void MarkSweep::KeepAliveClosure::do_oop(narrowOop* p) { MarkSweep::KeepAliveClosure::do_oop_work(p); } + void marksweep_init() { /* empty */ } #ifndef PRODUCT diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp index 8f8b681d180..d0ede4efba7 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp @@ -46,55 +46,59 @@ class ReferenceProcessor; #define VALIDATE_MARK_SWEEP_ONLY(code) #endif - // declared at end class PreservedMark; class MarkSweep : AllStatic { // - // In line closure decls + // Inline closure decls // - - class FollowRootClosure: public OopsInGenClosure{ + class FollowRootClosure: public OopsInGenClosure { public: - void do_oop(oop* p) { follow_root(p); } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); virtual const bool do_nmethods() const { return true; } }; class MarkAndPushClosure: public OopClosure { public: - void do_oop(oop* p) { mark_and_push(p); } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); virtual const bool do_nmethods() const { return true; } }; class FollowStackClosure: public VoidClosure { public: - void do_void() { follow_stack(); } + virtual void do_void(); }; class AdjustPointerClosure: public OopsInGenClosure { + private: bool _is_root; public: AdjustPointerClosure(bool is_root) : _is_root(is_root) {} - void do_oop(oop* p) { _adjust_pointer(p, _is_root); } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); }; // Used for java/lang/ref handling class IsAliveClosure: public BoolObjectClosure { public: - void do_object(oop p) { assert(false, "don't call"); } - bool do_object_b(oop p) { return p->is_gc_marked(); } + virtual void do_object(oop p); + virtual bool do_object_b(oop p); }; class KeepAliveClosure: public OopClosure { + protected: + template void do_oop_work(T* p); public: - void do_oop(oop* p); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); }; // // Friend decls // - friend class AdjustPointerClosure; friend class KeepAliveClosure; friend class VM_MarkSweep; @@ -120,14 +124,14 @@ class MarkSweep : AllStatic { static ReferenceProcessor* _ref_processor; #ifdef VALIDATE_MARK_SWEEP - static GrowableArray* _root_refs_stack; + static GrowableArray* _root_refs_stack; static GrowableArray * _live_oops; static GrowableArray * _live_oops_moved_to; static GrowableArray* _live_oops_size; static size_t _live_oops_index; static size_t _live_oops_index_at_perm; - static GrowableArray* _other_refs_stack; - static GrowableArray* _adjusted_pointers; + static GrowableArray* _other_refs_stack; + static GrowableArray* _adjusted_pointers; static bool _pointer_tracking; static bool _root_tracking; @@ -146,9 +150,8 @@ class MarkSweep : AllStatic { static GrowableArray* _last_gc_live_oops_size; #endif - // Non public closures - static IsAliveClosure is_alive; + static IsAliveClosure is_alive; static KeepAliveClosure keep_alive; // Class unloading. Update subklass/sibling/implementor links at end of marking phase. @@ -159,9 +162,9 @@ class MarkSweep : AllStatic { public: // Public closures - static FollowRootClosure follow_root_closure; - static MarkAndPushClosure mark_and_push_closure; - static FollowStackClosure follow_stack_closure; + static FollowRootClosure follow_root_closure; + static MarkAndPushClosure mark_and_push_closure; + static FollowStackClosure follow_stack_closure; static AdjustPointerClosure adjust_root_pointer_closure; static AdjustPointerClosure adjust_pointer_closure; @@ -170,39 +173,29 @@ class MarkSweep : AllStatic { // Call backs for marking static void mark_object(oop obj); - static void follow_root(oop* p); // Mark pointer and follow contents. Empty marking + // Mark pointer and follow contents. Empty marking stack afterwards. + template static inline void follow_root(T* p); + // Mark pointer and follow contents. + template static inline void mark_and_follow(T* p); + // Check mark and maybe push on marking stack + template static inline void mark_and_push(T* p); - // stack afterwards. + static void follow_stack(); // Empty marking stack. - static void mark_and_follow(oop* p); // Mark pointer and follow contents. - static void _mark_and_push(oop* p); // Mark pointer and push obj on - // marking stack. + static void preserve_mark(oop p, markOop mark); + // Save the mark word so it can be restored later + static void adjust_marks(); // Adjust the pointers in the preserved marks table + static void restore_marks(); // Restore the marks that we saved in preserve_mark + template static inline void adjust_pointer(T* p, bool isroot); - static void mark_and_push(oop* p) { // Check mark and maybe push on - // marking stack - // assert(Universe::is_reserved_heap((oop)p), "we should only be traversing objects here"); - oop m = *p; - if (m != NULL && !m->mark()->is_marked()) { - _mark_and_push(p); - } - } - - static void follow_stack(); // Empty marking stack. - - - static void preserve_mark(oop p, markOop mark); // Save the mark word so it can be restored later - static void adjust_marks(); // Adjust the pointers in the preserved marks table - static void restore_marks(); // Restore the marks that we saved in preserve_mark - - static void _adjust_pointer(oop* p, bool isroot); - - static void adjust_root_pointer(oop* p) { _adjust_pointer(p, true); } - static void adjust_pointer(oop* p) { _adjust_pointer(p, false); } + static void adjust_root_pointer(oop* p) { adjust_pointer(p, true); } + static void adjust_pointer(oop* p) { adjust_pointer(p, false); } + static void adjust_pointer(narrowOop* p) { adjust_pointer(p, false); } #ifdef VALIDATE_MARK_SWEEP - static void track_adjusted_pointer(oop* p, oop newobj, bool isroot); - static void check_adjust_pointer(oop* p); // Adjust this pointer + static void track_adjusted_pointer(void* p, bool isroot); + static void check_adjust_pointer(void* p); static void track_interior_pointers(oop obj); static void check_interior_pointers(); @@ -223,7 +216,6 @@ class MarkSweep : AllStatic { static void revisit_weak_klass_link(Klass* k); // Update subklass/sibling/implementor links at end of marking. }; - class PreservedMark VALUE_OBJ_CLASS_SPEC { private: oop _obj; diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp index 1418df7f953..c4045ee988e 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.inline.hpp @@ -22,32 +22,11 @@ * */ -inline void MarkSweep::_adjust_pointer(oop* p, bool isroot) { - oop obj = *p; - VALIDATE_MARK_SWEEP_ONLY(oop saved_new_pointer = NULL); - if (obj != NULL) { - oop new_pointer = oop(obj->mark()->decode_pointer()); - assert(new_pointer != NULL || // is forwarding ptr? - obj->mark() == markOopDesc::prototype() || // not gc marked? - (UseBiasedLocking && obj->mark()->has_bias_pattern()) || // not gc marked? - obj->is_shared(), // never forwarded? - "should contain a forwarding pointer"); - if (new_pointer != NULL) { - *p = new_pointer; - assert(Universe::heap()->is_in_reserved(new_pointer), - "should be in object space"); - VALIDATE_MARK_SWEEP_ONLY(saved_new_pointer = new_pointer); - } - } - VALIDATE_MARK_SWEEP_ONLY(track_adjusted_pointer(p, saved_new_pointer, isroot)); -} - inline void MarkSweep::mark_object(oop obj) { - #ifndef SERIALGC if (UseParallelOldGC && VerifyParallelOldWithMarkSweep) { assert(PSParallelCompact::mark_bitmap()->is_marked(obj), - "Should be marked in the marking bitmap"); + "Should be marked in the marking bitmap"); } #endif // SERIALGC @@ -60,3 +39,80 @@ inline void MarkSweep::mark_object(oop obj) { preserve_mark(obj, mark); } } + +template inline void MarkSweep::follow_root(T* p) { + assert(!Universe::heap()->is_in_reserved(p), + "roots shouldn't be things within the heap"); +#ifdef VALIDATE_MARK_SWEEP + if (ValidateMarkSweep) { + guarantee(!_root_refs_stack->contains(p), "should only be in here once"); + _root_refs_stack->push(p); + } +#endif + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + if (!obj->mark()->is_marked()) { + mark_object(obj); + obj->follow_contents(); + } + } + follow_stack(); +} + +template inline void MarkSweep::mark_and_follow(T* p) { +// assert(Universe::heap()->is_in_reserved(p), "should be in object space"); + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + if (!obj->mark()->is_marked()) { + mark_object(obj); + obj->follow_contents(); + } + } +} + +template inline void MarkSweep::mark_and_push(T* p) { +// assert(Universe::heap()->is_in_reserved(p), "should be in object space"); + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + if (!obj->mark()->is_marked()) { + mark_object(obj); + _marking_stack->push(obj); + } + } +} + +template inline void MarkSweep::adjust_pointer(T* p, bool isroot) { + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + oop new_obj = oop(obj->mark()->decode_pointer()); + assert(new_obj != NULL || // is forwarding ptr? + obj->mark() == markOopDesc::prototype() || // not gc marked? + (UseBiasedLocking && obj->mark()->has_bias_pattern()) || + // not gc marked? + obj->is_shared(), // never forwarded? + "should be forwarded"); + if (new_obj != NULL) { + assert(Universe::heap()->is_in_reserved(new_obj), + "should be in object space"); + oopDesc::encode_store_heap_oop_not_null(p, new_obj); + } + } + VALIDATE_MARK_SWEEP_ONLY(track_adjusted_pointer(p, isroot)); +} + +template inline void MarkSweep::KeepAliveClosure::do_oop_work(T* p) { +#ifdef VALIDATE_MARK_SWEEP + if (ValidateMarkSweep) { + if (!Universe::heap()->is_in_reserved(p)) { + _root_refs_stack->push(p); + } else { + _other_refs_stack->push(p); + } + } +#endif + mark_and_push(p); +} diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp index bccbcc600a1..959c4e1b6bf 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp @@ -46,9 +46,11 @@ void MutableNUMASpace::mangle_unused_area() { for (int i = 0; i < lgrp_spaces()->length(); i++) { LGRPSpace *ls = lgrp_spaces()->at(i); MutableSpace *s = ls->space(); - HeapWord *top = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom()); - if (top < s->end()) { - ls->add_invalid_region(MemRegion(top, s->end())); + if (!os::numa_has_static_binding()) { + HeapWord *top = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom()); + if (top < s->end()) { + ls->add_invalid_region(MemRegion(top, s->end())); + } } s->mangle_unused_area(); } @@ -60,42 +62,49 @@ void MutableNUMASpace::ensure_parsability() { for (int i = 0; i < lgrp_spaces()->length(); i++) { LGRPSpace *ls = lgrp_spaces()->at(i); MutableSpace *s = ls->space(); - if (!s->contains(top())) { + if (s->top() < top()) { // For all spaces preceeding the one containing top() if (s->free_in_words() > 0) { SharedHeap::fill_region_with_object(MemRegion(s->top(), s->end())); - size_t area_touched_words = pointer_delta(s->end(), s->top(), sizeof(HeapWordSize)); + size_t area_touched_words = pointer_delta(s->end(), s->top()); #ifndef ASSERT if (!ZapUnusedHeapArea) { area_touched_words = MIN2((size_t)align_object_size(typeArrayOopDesc::header_size(T_INT)), area_touched_words); } #endif - MemRegion invalid; - HeapWord *crossing_start = (HeapWord*)round_to((intptr_t)s->top(), os::vm_page_size()); - HeapWord *crossing_end = (HeapWord*)round_to((intptr_t)(s->top() + area_touched_words), - os::vm_page_size()); - if (crossing_start != crossing_end) { - // If object header crossed a small page boundary we mark the area - // as invalid rounding it to a page_size(). - HeapWord *start = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom()); - HeapWord *end = MIN2((HeapWord*)round_to((intptr_t)(s->top() + area_touched_words), page_size()), - s->end()); - invalid = MemRegion(start, end); - } + if (!os::numa_has_static_binding()) { + MemRegion invalid; + HeapWord *crossing_start = (HeapWord*)round_to((intptr_t)s->top(), os::vm_page_size()); + HeapWord *crossing_end = (HeapWord*)round_to((intptr_t)(s->top() + area_touched_words), + os::vm_page_size()); + if (crossing_start != crossing_end) { + // If object header crossed a small page boundary we mark the area + // as invalid rounding it to a page_size(). + HeapWord *start = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom()); + HeapWord *end = MIN2((HeapWord*)round_to((intptr_t)(s->top() + area_touched_words), page_size()), + s->end()); + invalid = MemRegion(start, end); + } - ls->add_invalid_region(invalid); - s->set_top(s->end()); + ls->add_invalid_region(invalid); + } } } else { + if (!os::numa_has_static_binding()) { #ifdef ASSERT - MemRegion invalid(s->top(), s->end()); - ls->add_invalid_region(invalid); -#else - if (ZapUnusedHeapArea) { MemRegion invalid(s->top(), s->end()); ls->add_invalid_region(invalid); - } else break; +#else + if (ZapUnusedHeapArea) { + MemRegion invalid(s->top(), s->end()); + ls->add_invalid_region(invalid); + } else { + return; + } #endif + } else { + return; + } } } } @@ -194,7 +203,7 @@ bool MutableNUMASpace::update_layout(bool force) { } // Bias region towards the first-touching lgrp. Set the right page sizes. -void MutableNUMASpace::bias_region(MemRegion mr) { +void MutableNUMASpace::bias_region(MemRegion mr, int lgrp_id) { HeapWord *start = (HeapWord*)round_to((intptr_t)mr.start(), page_size()); HeapWord *end = (HeapWord*)round_down((intptr_t)mr.end(), page_size()); if (end > start) { @@ -202,9 +211,13 @@ void MutableNUMASpace::bias_region(MemRegion mr) { assert((intptr_t)aligned_region.start() % page_size() == 0 && (intptr_t)aligned_region.byte_size() % page_size() == 0, "Bad alignment"); assert(region().contains(aligned_region), "Sanity"); - os::free_memory((char*)aligned_region.start(), aligned_region.byte_size()); + // First we tell the OS which page size we want in the given range. The underlying + // large page can be broken down if we require small pages. os::realign_memory((char*)aligned_region.start(), aligned_region.byte_size(), page_size()); - os::numa_make_local((char*)aligned_region.start(), aligned_region.byte_size()); + // Then we uncommit the pages in the range. + os::free_memory((char*)aligned_region.start(), aligned_region.byte_size()); + // And make them local/first-touch biased. + os::numa_make_local((char*)aligned_region.start(), aligned_region.byte_size(), lgrp_id); } } @@ -233,10 +246,12 @@ void MutableNUMASpace::update() { initialize(region(), true); } else { bool should_initialize = false; - for (int i = 0; i < lgrp_spaces()->length(); i++) { - if (!lgrp_spaces()->at(i)->invalid_region().is_empty()) { - should_initialize = true; - break; + if (!os::numa_has_static_binding()) { + for (int i = 0; i < lgrp_spaces()->length(); i++) { + if (!lgrp_spaces()->at(i)->invalid_region().is_empty()) { + should_initialize = true; + break; + } } } @@ -472,8 +487,8 @@ void MutableNUMASpace::initialize(MemRegion mr, bool clear_space) { intersection = MemRegion(new_region.start(), new_region.start()); } select_tails(new_region, intersection, &bottom_region, &top_region); - bias_region(bottom_region); - bias_region(top_region); + bias_region(bottom_region, lgrp_spaces()->at(0)->lgrp_id()); + bias_region(top_region, lgrp_spaces()->at(lgrp_spaces()->length() - 1)->lgrp_id()); } // Check if the space layout has changed significantly? @@ -545,22 +560,37 @@ void MutableNUMASpace::initialize(MemRegion mr, bool clear_space) { intersection = MemRegion(new_region.start(), new_region.start()); } - MemRegion invalid_region = ls->invalid_region().intersection(new_region); - if (!invalid_region.is_empty()) { - merge_regions(new_region, &intersection, &invalid_region); - free_region(invalid_region); + if (!os::numa_has_static_binding()) { + MemRegion invalid_region = ls->invalid_region().intersection(new_region); + // Invalid region is a range of memory that could've possibly + // been allocated on the other node. That's relevant only on Solaris where + // there is no static memory binding. + if (!invalid_region.is_empty()) { + merge_regions(new_region, &intersection, &invalid_region); + free_region(invalid_region); + ls->set_invalid_region(MemRegion()); + } } + select_tails(new_region, intersection, &bottom_region, &top_region); - free_region(bottom_region); - free_region(top_region); + + if (!os::numa_has_static_binding()) { + // If that's a system with the first-touch policy then it's enough + // to free the pages. + free_region(bottom_region); + free_region(top_region); + } else { + // In a system with static binding we have to change the bias whenever + // we reshape the heap. + bias_region(bottom_region, ls->lgrp_id()); + bias_region(top_region, ls->lgrp_id()); + } // If we clear the region, we would mangle it in debug. That would cause page // allocation in a different place. Hence setting the top directly. s->initialize(new_region, false); s->set_top(s->bottom()); - ls->set_invalid_region(MemRegion()); - set_adaptation_cycles(samples_count()); } } @@ -575,7 +605,7 @@ void MutableNUMASpace::set_top(HeapWord* value) { HeapWord *top = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom()); if (s->contains(value)) { - if (top < value && top < s->end()) { + if (!os::numa_has_static_binding() && top < value && top < s->end()) { ls->add_invalid_region(MemRegion(top, value)); } s->set_top(value); @@ -584,10 +614,10 @@ void MutableNUMASpace::set_top(HeapWord* value) { if (found_top) { s->set_top(s->bottom()); } else { - if (top < s->end()) { - ls->add_invalid_region(MemRegion(top, s->end())); - } - s->set_top(s->end()); + if (!os::numa_has_static_binding() && top < s->end()) { + ls->add_invalid_region(MemRegion(top, s->end())); + } + s->set_top(s->end()); } } } @@ -601,11 +631,23 @@ void MutableNUMASpace::clear() { } } +/* + Linux supports static memory binding, therefore the most part of the + logic dealing with the possible invalid page allocation is effectively + disabled. Besides there is no notion of the home node in Linux. A + thread is allowed to migrate freely. Although the scheduler is rather + reluctant to move threads between the nodes. We check for the current + node every allocation. And with a high probability a thread stays on + the same node for some time allowing local access to recently allocated + objects. + */ + HeapWord* MutableNUMASpace::allocate(size_t size) { - int lgrp_id = Thread::current()->lgrp_id(); - if (lgrp_id == -1) { + Thread* thr = Thread::current(); + int lgrp_id = thr->lgrp_id(); + if (lgrp_id == -1 || !os::numa_has_group_homing()) { lgrp_id = os::numa_get_group_id(); - Thread::current()->set_lgrp_id(lgrp_id); + thr->set_lgrp_id(lgrp_id); } int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals); @@ -619,31 +661,34 @@ HeapWord* MutableNUMASpace::allocate(size_t size) { MutableSpace *s = lgrp_spaces()->at(i)->space(); HeapWord *p = s->allocate(size); - if (p != NULL && s->free_in_words() < (size_t)oopDesc::header_size()) { - s->set_top(s->top() - size); - p = NULL; + if (p != NULL) { + size_t remainder = s->free_in_words(); + if (remainder < (size_t)oopDesc::header_size() && remainder > 0) { + s->set_top(s->top() - size); + p = NULL; + } } if (p != NULL) { if (top() < s->top()) { // Keep _top updated. MutableSpace::set_top(s->top()); } } - // Make the page allocation happen here. - if (p != NULL) { + // Make the page allocation happen here if there is no static binding.. + if (p != NULL && !os::numa_has_static_binding()) { for (HeapWord *i = p; i < p + size; i += os::vm_page_size() >> LogHeapWordSize) { *(int*)i = 0; } } - return p; } // This version is lock-free. HeapWord* MutableNUMASpace::cas_allocate(size_t size) { - int lgrp_id = Thread::current()->lgrp_id(); - if (lgrp_id == -1) { + Thread* thr = Thread::current(); + int lgrp_id = thr->lgrp_id(); + if (lgrp_id == -1 || !os::numa_has_group_homing()) { lgrp_id = os::numa_get_group_id(); - Thread::current()->set_lgrp_id(lgrp_id); + thr->set_lgrp_id(lgrp_id); } int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals); @@ -654,11 +699,14 @@ HeapWord* MutableNUMASpace::cas_allocate(size_t size) { } MutableSpace *s = lgrp_spaces()->at(i)->space(); HeapWord *p = s->cas_allocate(size); - if (p != NULL && s->free_in_words() < (size_t)oopDesc::header_size()) { - if (s->cas_deallocate(p, size)) { - // We were the last to allocate and created a fragment less than - // a minimal object. - p = NULL; + if (p != NULL) { + size_t remainder = pointer_delta(s->end(), p); + if (remainder < (size_t)oopDesc::header_size() && remainder > 0) { + if (s->cas_deallocate(p, size)) { + // We were the last to allocate and created a fragment less than + // a minimal object. + p = NULL; + } } } if (p != NULL) { @@ -670,8 +718,8 @@ HeapWord* MutableNUMASpace::cas_allocate(size_t size) { } } - // Make the page allocation happen here. - if (p != NULL) { + // Make the page allocation happen here if there is no static binding. + if (p != NULL && !os::numa_has_static_binding() ) { for (HeapWord *i = p; i < p + size; i += os::vm_page_size() >> LogHeapWordSize) { *(int*)i = 0; } @@ -699,6 +747,9 @@ void MutableNUMASpace::print_on(outputStream* st) const { st->print(" lgrp %d", ls->lgrp_id()); ls->space()->print_on(st); if (NUMAStats) { + for (int i = 0; i < lgrp_spaces()->length(); i++) { + lgrp_spaces()->at(i)->accumulate_statistics(page_size()); + } st->print(" local/remote/unbiased/uncommitted: %dK/%dK/%dK/%dK, large/small pages: %d/%d\n", ls->space_stats()->_local_space / K, ls->space_stats()->_remote_space / K, diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp index 5f9954fcb8b..a0fd5791ad7 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp @@ -139,8 +139,8 @@ class MutableNUMASpace : public MutableSpace { // Check if the NUMA topology has changed. Add and remove spaces if needed. // The update can be forced by setting the force parameter equal to true. bool update_layout(bool force); - // Bias region towards the first-touching lgrp. - void bias_region(MemRegion mr); + // Bias region towards the lgrp. + void bias_region(MemRegion mr, int lgrp_id); // Free pages in a given region. void free_region(MemRegion mr); // Get current chunk size. diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp index 7108f318ec0..7cab57dd727 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp @@ -144,3 +144,18 @@ void VM_GenCollectFull::doit() { gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level); notify_gc_end(); } + +void VM_GenCollectForPermanentAllocation::doit() { + JvmtiGCForAllocationMarker jgcm; + notify_gc_begin(true); + GenCollectedHeap* gch = GenCollectedHeap::heap(); + GCCauseSetter gccs(gch, _gc_cause); + gch->do_full_collection(gch->must_clear_all_soft_refs(), + gch->n_gens() - 1); + _res = gch->perm_gen()->allocate(_size, false); + assert(gch->is_in_reserved_or_null(_res), "result not in heap"); + if (_res == NULL && GC_locker::is_active_and_needs_gc()) { + set_gc_locked(); + } + notify_gc_end(); +} diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp index ee850f70e8f..7777dc71c84 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp @@ -43,6 +43,7 @@ // is specified; and also the attach "inspectheap" operation // // VM_GenCollectForAllocation +// VM_GenCollectForPermanentAllocation // VM_ParallelGCFailedAllocation // VM_ParallelGCFailedPermanentAllocation // - this operation is invoked when allocation is failed; @@ -166,3 +167,23 @@ class VM_GenCollectFull: public VM_GC_Operation { virtual VMOp_Type type() const { return VMOp_GenCollectFull; } virtual void doit(); }; + +class VM_GenCollectForPermanentAllocation: public VM_GC_Operation { + private: + HeapWord* _res; + size_t _size; // size of object to be allocated + public: + VM_GenCollectForPermanentAllocation(size_t size, + unsigned int gc_count_before, + unsigned int full_gc_count_before, + GCCause::Cause gc_cause) + : VM_GC_Operation(gc_count_before, full_gc_count_before, true), + _size(size) { + _res = NULL; + _gc_cause = gc_cause; + } + ~VM_GenCollectForPermanentAllocation() {} + virtual VMOp_Type type() const { return VMOp_GenCollectForPermanentAllocation; } + virtual void doit(); + HeapWord* result() const { return _res; } +}; diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp index c4efcc4d965..ecfab9ed6cd 100644 --- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp @@ -35,7 +35,6 @@ int CollectedHeap::_fire_out_of_memory_count = 0; CollectedHeap::CollectedHeap() : _reserved(), _barrier_set(NULL), _is_gc_active(false), _total_collections(0), _total_full_collections(0), - _max_heap_capacity(0), _gc_cause(GCCause::_no_gc), _gc_lastcause(GCCause::_no_gc) { NOT_PRODUCT(_promotion_failure_alot_count = 0;) NOT_PRODUCT(_promotion_failure_alot_gc_number = 0;) diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp index cad60b36a43..ef55f14676e 100644 --- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp @@ -53,7 +53,6 @@ class CollectedHeap : public CHeapObj { bool _is_gc_active; unsigned int _total_collections; // ... started unsigned int _total_full_collections; // ... started - size_t _max_heap_capacity; NOT_PRODUCT(volatile size_t _promotion_failure_alot_count;) NOT_PRODUCT(volatile size_t _promotion_failure_alot_gc_number;) @@ -149,10 +148,7 @@ class CollectedHeap : public CHeapObj { virtual void post_initialize() = 0; MemRegion reserved_region() const { return _reserved; } - - // Return the number of bytes currently reserved, committed, and used, - // respectively, for holding objects. - size_t reserved_obj_bytes() const { return _reserved.byte_size(); } + address base() const { return (address)reserved_region().start(); } // Future cleanup here. The following functions should specify bytes or // heapwords as part of their signature. diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp index 5344802b74a..556cd490f96 100644 --- a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp @@ -61,7 +61,10 @@ void CollectedHeap::post_allocation_install_obj_klass(KlassHandle klass, obj->set_klass(klass()); assert(!Universe::is_fully_initialized() || obj->blueprint() != NULL, "missing blueprint"); +} +// Support for jvmti and dtrace +inline void post_allocation_notify(KlassHandle klass, oop obj) { // support for JVMTI VMObjectAlloc event (no-op if not enabled) JvmtiExport::vm_object_alloc_event_collector(obj); @@ -79,18 +82,22 @@ void CollectedHeap::post_allocation_setup_obj(KlassHandle klass, post_allocation_setup_common(klass, obj, size); assert(Universe::is_bootstrapping() || !((oop)obj)->blueprint()->oop_is_array(), "must not be an array"); + // notify jvmti and dtrace + post_allocation_notify(klass, (oop)obj); } void CollectedHeap::post_allocation_setup_array(KlassHandle klass, HeapWord* obj, size_t size, int length) { - // Set array length before posting jvmti object alloc event - // in post_allocation_setup_common() assert(length >= 0, "length should be non-negative"); - ((arrayOop)obj)->set_length(length); post_allocation_setup_common(klass, obj, size); + // Must set length after installing klass as set_klass zeros the length + // field in UseCompressedOops + ((arrayOop)obj)->set_length(length); assert(((oop)obj)->blueprint()->oop_is_array(), "must be an array"); + // notify jvmti and dtrace (must be after length is set for dtrace) + post_allocation_notify(klass, (oop)obj); } HeapWord* CollectedHeap::common_mem_allocate_noinit(size_t size, bool is_noref, TRAPS) { diff --git a/hotspot/src/share/vm/includeDB_compiler1 b/hotspot/src/share/vm/includeDB_compiler1 index 37bb58ccc32..ae500d2f6d7 100644 --- a/hotspot/src/share/vm/includeDB_compiler1 +++ b/hotspot/src/share/vm/includeDB_compiler1 @@ -323,7 +323,7 @@ c1_Runtime1.cpp collectedHeap.hpp c1_Runtime1.cpp compilationPolicy.hpp c1_Runtime1.cpp compiledIC.hpp c1_Runtime1.cpp copy.hpp -c1_Runtime1.cpp disassembler_.hpp +c1_Runtime1.cpp disassembler.hpp c1_Runtime1.cpp events.hpp c1_Runtime1.cpp interfaceSupport.hpp c1_Runtime1.cpp interpreter.hpp diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 17404cec658..616a974bb20 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -191,7 +191,6 @@ array.hpp allocation.inline.hpp arrayKlass.cpp arrayKlass.hpp arrayKlass.cpp arrayKlassKlass.hpp arrayKlass.cpp arrayOop.hpp -arrayKlass.cpp collectedHeap.hpp arrayKlass.cpp collectedHeap.inline.hpp arrayKlass.cpp gcLocker.hpp arrayKlass.cpp instanceKlass.hpp @@ -211,6 +210,7 @@ arrayKlass.hpp universe.hpp arrayKlassKlass.cpp arrayKlassKlass.hpp arrayKlassKlass.cpp handles.inline.hpp arrayKlassKlass.cpp javaClasses.hpp +arrayKlassKlass.cpp markSweep.inline.hpp arrayKlassKlass.cpp oop.inline.hpp arrayKlassKlass.hpp arrayKlass.hpp @@ -244,13 +244,13 @@ assembler.hpp vm_version_.hpp assembler.inline.hpp assembler.hpp assembler.inline.hpp codeBuffer.hpp -assembler.inline.hpp disassembler_.hpp +assembler.inline.hpp disassembler.hpp assembler.inline.hpp threadLocalStorage.hpp assembler_.cpp assembler_.inline.hpp assembler_.cpp biasedLocking.hpp assembler_.cpp cardTableModRefBS.hpp -assembler_.cpp collectedHeap.hpp +assembler_.cpp collectedHeap.inline.hpp assembler_.cpp interfaceSupport.hpp assembler_.cpp interpreter.hpp assembler_.cpp objectMonitor.hpp @@ -331,9 +331,8 @@ bitMap.hpp top.hpp bitMap.inline.hpp atomic.hpp bitMap.inline.hpp bitMap.hpp -blockOffsetTable.cpp blockOffsetTable.hpp blockOffsetTable.cpp blockOffsetTable.inline.hpp -blockOffsetTable.cpp collectedHeap.hpp +blockOffsetTable.cpp collectedHeap.inline.hpp blockOffsetTable.cpp iterator.hpp blockOffsetTable.cpp java.hpp blockOffsetTable.cpp oop.inline.hpp @@ -719,6 +718,11 @@ ciObjArray.cpp ciNullObject.hpp ciObjArray.cpp ciUtilities.hpp ciObjArray.cpp objArrayOop.hpp +ciObjArray.cpp ciObjArray.hpp +ciObjArray.cpp ciNullObject.hpp +ciObjArray.cpp ciUtilities.hpp +ciObjArray.cpp objArrayOop.hpp + ciObjArrayKlass.cpp ciInstanceKlass.hpp ciObjArrayKlass.cpp ciObjArrayKlass.hpp ciObjArrayKlass.cpp ciObjArrayKlassKlass.hpp @@ -946,7 +950,7 @@ codeBlob.cpp allocation.inline.hpp codeBlob.cpp bytecode.hpp codeBlob.cpp codeBlob.hpp codeBlob.cpp codeCache.hpp -codeBlob.cpp disassembler_.hpp +codeBlob.cpp disassembler.hpp codeBlob.cpp forte.hpp codeBlob.cpp handles.inline.hpp codeBlob.cpp heap.hpp @@ -968,7 +972,7 @@ codeBlob.hpp oopMap.hpp codeBuffer.cpp codeBuffer.hpp codeBuffer.cpp copy.hpp -codeBuffer.cpp disassembler_.hpp +codeBuffer.cpp disassembler.hpp codeBuffer.hpp assembler.hpp codeBuffer.hpp oopRecorder.hpp @@ -990,6 +994,7 @@ codeCache.cpp methodOop.hpp codeCache.cpp mutexLocker.hpp codeCache.cpp nmethod.hpp codeCache.cpp objArrayOop.hpp +codeCache.cpp oop.inline.hpp codeCache.cpp pcDesc.hpp codeCache.cpp resourceArea.hpp @@ -1124,7 +1129,7 @@ compiledICHolderKlass.cpp collectedHeap.inline.hpp compiledICHolderKlass.cpp compiledICHolderKlass.hpp compiledICHolderKlass.cpp handles.inline.hpp compiledICHolderKlass.cpp javaClasses.hpp -compiledICHolderKlass.cpp markSweep.hpp +compiledICHolderKlass.cpp markSweep.inline.hpp compiledICHolderKlass.cpp oop.inline.hpp compiledICHolderKlass.cpp oop.inline2.hpp compiledICHolderKlass.cpp permGen.hpp @@ -1192,6 +1197,7 @@ constMethodKlass.cpp constMethodOop.hpp constMethodKlass.cpp gcLocker.hpp constMethodKlass.cpp handles.inline.hpp constMethodKlass.cpp interpreter.hpp +constMethodKlass.cpp markSweep.inline.hpp constMethodKlass.cpp oop.inline.hpp constMethodKlass.cpp oop.inline2.hpp constMethodKlass.cpp resourceArea.hpp @@ -1210,6 +1216,8 @@ constantPoolKlass.cpp collectedHeap.inline.hpp constantPoolKlass.cpp constantPoolKlass.hpp constantPoolKlass.cpp constantPoolOop.hpp constantPoolKlass.cpp handles.inline.hpp +constantPoolKlass.cpp javaClasses.hpp +constantPoolKlass.cpp markSweep.inline.hpp constantPoolKlass.cpp oop.inline.hpp constantPoolKlass.cpp oop.inline2.hpp constantPoolKlass.cpp oopFactory.hpp @@ -1261,7 +1269,8 @@ cpCacheKlass.cpp collectedHeap.hpp cpCacheKlass.cpp constantPoolOop.hpp cpCacheKlass.cpp cpCacheKlass.hpp cpCacheKlass.cpp handles.inline.hpp -cpCacheKlass.cpp markSweep.hpp +cpCacheKlass.cpp javaClasses.hpp +cpCacheKlass.cpp markSweep.inline.hpp cpCacheKlass.cpp oop.inline.hpp cpCacheKlass.cpp permGen.hpp @@ -1273,7 +1282,6 @@ cpCacheOop.cpp cpCacheOop.hpp cpCacheOop.cpp handles.inline.hpp cpCacheOop.cpp interpreter.hpp cpCacheOop.cpp jvmtiRedefineClassesTrace.hpp -cpCacheOop.cpp markSweep.hpp cpCacheOop.cpp markSweep.inline.hpp cpCacheOop.cpp objArrayOop.hpp cpCacheOop.cpp oop.inline.hpp @@ -1323,7 +1331,7 @@ debug.cpp codeCache.hpp debug.cpp collectedHeap.hpp debug.cpp compileBroker.hpp debug.cpp defaultStream.hpp -debug.cpp disassembler_.hpp +debug.cpp disassembler.hpp debug.cpp events.hpp debug.cpp frame.hpp debug.cpp heapDumper.hpp @@ -1385,7 +1393,6 @@ debug_.cpp top.hpp defNewGeneration.cpp collectorCounters.hpp defNewGeneration.cpp copy.hpp -defNewGeneration.cpp defNewGeneration.hpp defNewGeneration.cpp defNewGeneration.inline.hpp defNewGeneration.cpp gcLocker.inline.hpp defNewGeneration.cpp gcPolicyCounters.hpp @@ -1397,7 +1404,6 @@ defNewGeneration.cpp iterator.hpp defNewGeneration.cpp java.hpp defNewGeneration.cpp oop.inline.hpp defNewGeneration.cpp referencePolicy.hpp -defNewGeneration.cpp space.hpp defNewGeneration.cpp space.inline.hpp defNewGeneration.cpp thread_.inline.hpp @@ -1406,6 +1412,7 @@ defNewGeneration.hpp cSpaceCounters.hpp defNewGeneration.hpp generation.inline.hpp defNewGeneration.hpp generationCounters.hpp +defNewGeneration.inline.hpp cardTableRS.hpp defNewGeneration.inline.hpp defNewGeneration.hpp defNewGeneration.inline.hpp space.hpp @@ -1442,7 +1449,7 @@ deoptimization.hpp allocation.hpp deoptimization.hpp frame.inline.hpp depChecker_.cpp depChecker_.hpp -depChecker_.cpp disassembler_.hpp +depChecker_.cpp disassembler.hpp depChecker_.cpp hpi.hpp dependencies.cpp ciArrayKlass.hpp @@ -1472,21 +1479,21 @@ dictionary.hpp instanceKlass.hpp dictionary.hpp oop.hpp dictionary.hpp systemDictionary.hpp -disassemblerEnv.hpp globals.hpp +disassembler_.hpp generate_platform_dependent_include -disassembler_.cpp cardTableModRefBS.hpp -disassembler_.cpp codeCache.hpp -disassembler_.cpp collectedHeap.hpp -disassembler_.cpp depChecker_.hpp -disassembler_.cpp disassembler_.hpp -disassembler_.cpp fprofiler.hpp -disassembler_.cpp handles.inline.hpp -disassembler_.cpp hpi.hpp -disassembler_.cpp stubCodeGenerator.hpp -disassembler_.cpp stubRoutines.hpp +disassembler.cpp cardTableModRefBS.hpp +disassembler.cpp codeCache.hpp +disassembler.cpp collectedHeap.hpp +disassembler.cpp depChecker_.hpp +disassembler.cpp disassembler.hpp +disassembler.cpp fprofiler.hpp +disassembler.cpp handles.inline.hpp +disassembler.cpp hpi.hpp +disassembler.cpp stubCodeGenerator.hpp +disassembler.cpp stubRoutines.hpp -disassembler_.hpp disassemblerEnv.hpp -disassembler_.hpp os_.inline.hpp +disassembler.hpp globals.hpp +disassembler.hpp os_.inline.hpp dtraceAttacher.cpp codeCache.hpp dtraceAttacher.cpp deoptimization.hpp @@ -1495,6 +1502,30 @@ dtraceAttacher.cpp resourceArea.hpp dtraceAttacher.cpp vmThread.hpp dtraceAttacher.cpp vm_operations.hpp +dtraceJSDT.cpp allocation.hpp +dtraceJSDT.cpp codeBlob.hpp +dtraceJSDT.cpp dtraceJSDT.hpp +dtraceJSDT.cpp exceptions.hpp +dtraceJSDT.cpp globalDefinitions.hpp +dtraceJSDT.cpp javaClasses.hpp +dtraceJSDT.cpp jniHandles.hpp +dtraceJSDT.cpp jvm.h +dtraceJSDT.cpp os.hpp +dtraceJSDT.cpp utf8.hpp + +dtraceJSDT.hpp nativeInst_.hpp +dtraceJSDT.hpp nmethod.hpp + +dtraceJSDT_.cpp allocation.hpp +dtraceJSDT_.cpp codeBlob.hpp +dtraceJSDT_.cpp dtraceJSDT.hpp +dtraceJSDT_.cpp globalDefinitions.hpp +dtraceJSDT_.cpp javaClasses.hpp +dtraceJSDT_.cpp jniHandles.hpp +dtraceJSDT_.cpp jvm.h +dtraceJSDT_.cpp os.hpp +dtraceJSDT_.cpp signature.hpp + // dump is jck optional, put cpp deps in includeDB_features events.cpp allocation.inline.hpp @@ -1636,6 +1667,7 @@ frame_.inline.hpp generate_platform_dependent_include gcLocker.cpp gcLocker.inline.hpp gcLocker.cpp sharedHeap.hpp +gcLocker.cpp resourceArea.hpp gcLocker.hpp collectedHeap.hpp gcLocker.hpp genCollectedHeap.hpp @@ -1956,6 +1988,7 @@ instanceKlass.cpp javaClasses.hpp instanceKlass.cpp jvmti.h instanceKlass.cpp jvmtiExport.hpp instanceKlass.cpp jvmtiRedefineClassesTrace.hpp +instanceKlass.cpp markSweep.inline.hpp instanceKlass.cpp methodOop.hpp instanceKlass.cpp mutexLocker.hpp instanceKlass.cpp objArrayKlassKlass.hpp @@ -1991,6 +2024,7 @@ instanceKlassKlass.cpp instanceKlassKlass.hpp instanceKlassKlass.cpp instanceRefKlass.hpp instanceKlassKlass.cpp javaClasses.hpp instanceKlassKlass.cpp jvmtiExport.hpp +instanceKlassKlass.cpp markSweep.inline.hpp instanceKlassKlass.cpp objArrayKlassKlass.hpp instanceKlassKlass.cpp objArrayOop.hpp instanceKlassKlass.cpp oop.inline.hpp @@ -2012,7 +2046,7 @@ instanceRefKlass.cpp genCollectedHeap.hpp instanceRefKlass.cpp genOopClosures.inline.hpp instanceRefKlass.cpp instanceRefKlass.hpp instanceRefKlass.cpp javaClasses.hpp -instanceRefKlass.cpp markSweep.hpp +instanceRefKlass.cpp markSweep.inline.hpp instanceRefKlass.cpp oop.inline.hpp instanceRefKlass.cpp preserveException.hpp instanceRefKlass.cpp systemDictionary.hpp @@ -2396,6 +2430,7 @@ jvm.cpp classLoader.hpp jvm.cpp collectedHeap.inline.hpp jvm.cpp copy.hpp jvm.cpp defaultStream.hpp +jvm.cpp dtraceJSDT.hpp jvm.cpp events.hpp jvm.cpp handles.inline.hpp jvm.cpp histogram.hpp @@ -2492,7 +2527,7 @@ klassKlass.cpp instanceKlass.hpp klassKlass.cpp instanceOop.hpp klassKlass.cpp klassKlass.hpp klassKlass.cpp klassOop.hpp -klassKlass.cpp markSweep.hpp +klassKlass.cpp markSweep.inline.hpp klassKlass.cpp methodKlass.hpp klassKlass.cpp objArrayKlass.hpp klassKlass.cpp oop.inline.hpp @@ -2519,7 +2554,7 @@ klassVtable.cpp instanceKlass.hpp klassVtable.cpp jvmtiRedefineClassesTrace.hpp klassVtable.cpp klassOop.hpp klassVtable.cpp klassVtable.hpp -klassVtable.cpp markSweep.hpp +klassVtable.cpp markSweep.inline.hpp klassVtable.cpp methodOop.hpp klassVtable.cpp objArrayOop.hpp klassVtable.cpp oop.inline.hpp @@ -2632,6 +2667,9 @@ markOop.inline.hpp klassOop.hpp markOop.inline.hpp markOop.hpp markSweep.cpp compileBroker.hpp + +markSweep.hpp collectedHeap.hpp + memRegion.cpp globals.hpp memRegion.cpp memRegion.hpp @@ -2731,7 +2769,7 @@ methodDataKlass.cpp collectedHeap.inline.hpp methodDataKlass.cpp gcLocker.hpp methodDataKlass.cpp handles.inline.hpp methodDataKlass.cpp klassOop.hpp -methodDataKlass.cpp markSweep.hpp +methodDataKlass.cpp markSweep.inline.hpp methodDataKlass.cpp methodDataKlass.hpp methodDataKlass.cpp methodDataOop.hpp methodDataKlass.cpp oop.inline.hpp @@ -2746,7 +2784,6 @@ methodDataOop.cpp bytecodeStream.hpp methodDataOop.cpp deoptimization.hpp methodDataOop.cpp handles.inline.hpp methodDataOop.cpp linkResolver.hpp -methodDataOop.cpp markSweep.hpp methodDataOop.cpp markSweep.inline.hpp methodDataOop.cpp methodDataOop.hpp methodDataOop.cpp oop.inline.hpp @@ -2764,7 +2801,7 @@ methodKlass.cpp handles.inline.hpp methodKlass.cpp interpreter.hpp methodKlass.cpp javaClasses.hpp methodKlass.cpp klassOop.hpp -methodKlass.cpp markSweep.hpp +methodKlass.cpp markSweep.inline.hpp methodKlass.cpp methodDataOop.hpp methodKlass.cpp methodKlass.hpp methodKlass.cpp oop.inline.hpp @@ -2909,7 +2946,7 @@ nmethod.cpp codeCache.hpp nmethod.cpp compileLog.hpp nmethod.cpp compiledIC.hpp nmethod.cpp compilerOracle.hpp -nmethod.cpp disassembler_.hpp +nmethod.cpp disassembler.hpp nmethod.cpp dtrace.hpp nmethod.cpp events.hpp nmethod.cpp jvmtiRedefineClassesTrace.hpp @@ -2941,6 +2978,7 @@ objArrayKlass.cpp systemDictionary.hpp objArrayKlass.cpp universe.inline.hpp objArrayKlass.cpp vmSymbols.hpp + objArrayKlass.hpp arrayKlass.hpp objArrayKlass.hpp instanceKlass.hpp objArrayKlass.hpp specialized_oop_closures.hpp @@ -2948,6 +2986,7 @@ objArrayKlass.hpp specialized_oop_closures.hpp objArrayKlassKlass.cpp collectedHeap.inline.hpp objArrayKlassKlass.cpp instanceKlass.hpp objArrayKlassKlass.cpp javaClasses.hpp +objArrayKlassKlass.cpp markSweep.inline.hpp objArrayKlassKlass.cpp objArrayKlassKlass.hpp objArrayKlassKlass.cpp oop.inline.hpp objArrayKlassKlass.cpp oop.inline2.hpp @@ -2956,6 +2995,7 @@ objArrayKlassKlass.cpp systemDictionary.hpp objArrayKlassKlass.hpp arrayKlassKlass.hpp objArrayKlassKlass.hpp objArrayKlass.hpp +objArrayOop.cpp objArrayKlass.hpp objArrayOop.cpp objArrayOop.hpp objArrayOop.cpp oop.inline.hpp @@ -3005,7 +3045,6 @@ oop.inline.hpp generation.hpp oop.inline.hpp klass.hpp oop.inline.hpp klassOop.hpp oop.inline.hpp markOop.inline.hpp -oop.inline.hpp markSweep.hpp oop.inline.hpp markSweep.inline.hpp oop.inline.hpp oop.hpp oop.inline.hpp os.hpp @@ -3061,13 +3100,14 @@ oopMap.cpp scopeDesc.hpp oopMap.cpp signature.hpp oopMap.hpp allocation.hpp +oopMapCache.cpp jvmtiRedefineClassesTrace.hpp oopMap.hpp compressedStream.hpp oopMap.hpp growableArray.hpp oopMap.hpp vmreg.hpp oopMapCache.cpp allocation.inline.hpp -oopMapCache.cpp handles.inline.hpp oopMapCache.cpp jvmtiRedefineClassesTrace.hpp +oopMapCache.cpp handles.inline.hpp oopMapCache.cpp oop.inline.hpp oopMapCache.cpp oopMapCache.hpp oopMapCache.cpp resourceArea.hpp @@ -3174,6 +3214,7 @@ os_.cpp events.hpp os_.cpp extendedPC.hpp os_.cpp filemap.hpp os_.cpp globals.hpp +os_.cpp growableArray.hpp os_.cpp hpi.hpp os_.cpp icBuffer.hpp os_.cpp interfaceSupport.hpp @@ -3315,6 +3356,10 @@ permGen.cpp java.hpp permGen.cpp oop.inline.hpp permGen.cpp permGen.hpp permGen.cpp universe.hpp +permGen.cpp gcLocker.hpp +permGen.cpp gcLocker.inline.hpp +permGen.cpp vmGCOperations.hpp +permGen.cpp vmThread.hpp permGen.hpp gcCause.hpp permGen.hpp generation.hpp @@ -3763,7 +3808,7 @@ statSampler.hpp perfData.hpp statSampler.hpp task.hpp stubCodeGenerator.cpp assembler_.inline.hpp -stubCodeGenerator.cpp disassembler_.hpp +stubCodeGenerator.cpp disassembler.hpp stubCodeGenerator.cpp forte.hpp stubCodeGenerator.cpp oop.inline.hpp stubCodeGenerator.cpp stubCodeGenerator.hpp @@ -4530,12 +4575,13 @@ vmreg_.cpp vmreg.hpp vmreg_.hpp generate_platform_dependent_include vtableStubs.cpp allocation.inline.hpp -vtableStubs.cpp disassembler_.hpp +vtableStubs.cpp disassembler.hpp vtableStubs.cpp forte.hpp vtableStubs.cpp handles.inline.hpp vtableStubs.cpp instanceKlass.hpp vtableStubs.cpp jvmtiExport.hpp vtableStubs.cpp klassVtable.hpp +vtableStubs.cpp oop.inline.hpp vtableStubs.cpp mutexLocker.hpp vtableStubs.cpp resourceArea.hpp vtableStubs.cpp sharedRuntime.hpp diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp index 2a03dc2d6d4..547b440e177 100644 --- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -518,16 +518,16 @@ BytecodeInterpreter::run(interpreterState istate) { /* 0xC0 */ &&opc_checkcast, &&opc_instanceof, &&opc_monitorenter, &&opc_monitorexit, /* 0xC4 */ &&opc_wide, &&opc_multianewarray, &&opc_ifnull, &&opc_ifnonnull, -/* 0xC8 */ &&opc_goto_w, &&opc_jsr_w, &&opc_breakpoint, &&opc_fast_igetfield, -/* 0xCC */ &&opc_fastagetfield,&&opc_fast_aload_0, &&opc_fast_iaccess_0, &&opc__fast_aaccess_0, +/* 0xC8 */ &&opc_goto_w, &&opc_jsr_w, &&opc_breakpoint, &&opc_default, +/* 0xCC */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, -/* 0xD0 */ &&opc_fast_linearswitch, &&opc_fast_binaryswitch, &&opc_return_register_finalizer, &&opc_default, +/* 0xD0 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, /* 0xD4 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, /* 0xD8 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, /* 0xDC */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, /* 0xE0 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, -/* 0xE4 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, +/* 0xE4 */ &&opc_default, &&opc_return_register_finalizer, &&opc_default, &&opc_default, /* 0xE8 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, /* 0xEC */ &&opc_default, &&opc_default, &&opc_default, &&opc_default, diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp index 0b071feb4c7..82f73d8ac96 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp @@ -35,7 +35,10 @@ class InterpreterRuntime: AllStatic { static methodOop method(JavaThread *thread) { return last_frame(thread).interpreter_frame_method(); } static address bcp(JavaThread *thread) { return last_frame(thread).interpreter_frame_bcp(); } static void set_bcp_and_mdp(address bcp, JavaThread*thread); - static Bytecodes::Code code(JavaThread *thread) { return Bytecodes::code_at(bcp(thread)); } + static Bytecodes::Code code(JavaThread *thread) { + // pass method to avoid calling unsafe bcp_to_method (partial fix 4926272) + return Bytecodes::code_at(bcp(thread), method(thread)); + } static bool already_resolved(JavaThread *thread) { return cache_entry(thread)->is_resolved(code(thread)); } static int one_byte_index(JavaThread *thread) { return bcp(thread)[1]; } static int two_byte_index(JavaThread *thread) { return Bytes::get_Java_u2(bcp(thread) + 1); } diff --git a/hotspot/src/share/vm/memory/barrierSet.hpp b/hotspot/src/share/vm/memory/barrierSet.hpp index bc3208be68e..aa56fa9e883 100644 --- a/hotspot/src/share/vm/memory/barrierSet.hpp +++ b/hotspot/src/share/vm/memory/barrierSet.hpp @@ -54,9 +54,9 @@ public: // These functions indicate whether a particular access of the given // kinds requires a barrier. - virtual bool read_ref_needs_barrier(oop* field) = 0; + virtual bool read_ref_needs_barrier(void* field) = 0; virtual bool read_prim_needs_barrier(HeapWord* field, size_t bytes) = 0; - virtual bool write_ref_needs_barrier(oop* field, oop new_val) = 0; + virtual bool write_ref_needs_barrier(void* field, oop new_val) = 0; virtual bool write_prim_needs_barrier(HeapWord* field, size_t bytes, juint val1, juint val2) = 0; // The first four operations provide a direct implementation of the @@ -64,7 +64,7 @@ public: // directly, as appropriate. // Invoke the barrier, if any, necessary when reading the given ref field. - virtual void read_ref_field(oop* field) = 0; + virtual void read_ref_field(void* field) = 0; // Invoke the barrier, if any, necessary when reading the given primitive // "field" of "bytes" bytes in "obj". @@ -75,9 +75,9 @@ public: // (For efficiency reasons, this operation is specialized for certain // barrier types. Semantically, it should be thought of as a call to the // virtual "_work" function below, which must implement the barrier.) - inline void write_ref_field(oop* field, oop new_val); + inline void write_ref_field(void* field, oop new_val); protected: - virtual void write_ref_field_work(oop* field, oop new_val) = 0; + virtual void write_ref_field_work(void* field, oop new_val) = 0; public: // Invoke the barrier, if any, necessary when writing the "bytes"-byte diff --git a/hotspot/src/share/vm/memory/barrierSet.inline.hpp b/hotspot/src/share/vm/memory/barrierSet.inline.hpp index 082cb760968..ab89a4d4668 100644 --- a/hotspot/src/share/vm/memory/barrierSet.inline.hpp +++ b/hotspot/src/share/vm/memory/barrierSet.inline.hpp @@ -26,7 +26,7 @@ // performance-critical calls when when the barrier is the most common // card-table kind. -void BarrierSet::write_ref_field(oop* field, oop new_val) { +void BarrierSet::write_ref_field(void* field, oop new_val) { if (kind() == CardTableModRef) { ((CardTableModRefBS*)this)->inline_write_ref_field(field, new_val); } else { diff --git a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp index 8149c2ce089..fab92e0f698 100644 --- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp +++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp @@ -294,7 +294,7 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) { // Note that these versions are precise! The scanning code has to handle the // fact that the write barrier may be either precise or imprecise. -void CardTableModRefBS::write_ref_field_work(oop* field, oop newVal) { +void CardTableModRefBS::write_ref_field_work(void* field, oop newVal) { inline_write_ref_field(field, newVal); } diff --git a/hotspot/src/share/vm/memory/cardTableModRefBS.hpp b/hotspot/src/share/vm/memory/cardTableModRefBS.hpp index 393adcc951d..dcc457111df 100644 --- a/hotspot/src/share/vm/memory/cardTableModRefBS.hpp +++ b/hotspot/src/share/vm/memory/cardTableModRefBS.hpp @@ -273,7 +273,7 @@ public: // *** Barrier set functions. - inline bool write_ref_needs_barrier(oop* field, oop new_val) { + inline bool write_ref_needs_barrier(void* field, oop new_val) { // Note that this assumes the perm gen is the highest generation // in the address space return new_val != NULL && !new_val->is_perm(); @@ -285,7 +285,7 @@ public: // these functions here for performance. protected: void write_ref_field_work(oop obj, size_t offset, oop newVal); - void write_ref_field_work(oop* field, oop newVal); + void write_ref_field_work(void* field, oop newVal); public: bool has_write_ref_array_opt() { return true; } @@ -315,7 +315,7 @@ public: // *** Card-table-barrier-specific things. - inline void inline_write_ref_field(oop* field, oop newVal) { + inline void inline_write_ref_field(void* field, oop newVal) { jbyte* byte = byte_for(field); *byte = dirty_card; } diff --git a/hotspot/src/share/vm/memory/cardTableRS.cpp b/hotspot/src/share/vm/memory/cardTableRS.cpp index f389a70a40a..e84cc57f085 100644 --- a/hotspot/src/share/vm/memory/cardTableRS.cpp +++ b/hotspot/src/share/vm/memory/cardTableRS.cpp @@ -191,7 +191,7 @@ public: // prev-younger-gen ==> cur_youngergen_and_prev_nonclean_card // cur-younger-gen ==> cur_younger_gen // cur_youngergen_and_prev_nonclean_card ==> no change. -void CardTableRS::write_ref_field_gc_par(oop* field, oop new_val) { +void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) { jbyte* entry = ct_bs()->byte_for(field); do { jbyte entry_val = *entry; @@ -290,28 +290,36 @@ void CardTableRS::invalidate_or_clear(Generation* gen, bool younger, class VerifyCleanCardClosure: public OopClosure { - HeapWord* boundary; - HeapWord* begin; HeapWord* end; -public: - void do_oop(oop* p) { +private: + HeapWord* _boundary; + HeapWord* _begin; + HeapWord* _end; +protected: + template void do_oop_work(T* p) { HeapWord* jp = (HeapWord*)p; - if (jp >= begin && jp < end) { - guarantee(*p == NULL || (HeapWord*)p < boundary - || (HeapWord*)(*p) >= boundary, + if (jp >= _begin && jp < _end) { + oop obj = oopDesc::load_decode_heap_oop(p); + guarantee(obj == NULL || + (HeapWord*)p < _boundary || + (HeapWord*)obj >= _boundary, "pointer on clean card crosses boundary"); } } - VerifyCleanCardClosure(HeapWord* b, HeapWord* _begin, HeapWord* _end) : - boundary(b), begin(_begin), end(_end) {} +public: + VerifyCleanCardClosure(HeapWord* b, HeapWord* begin, HeapWord* end) : + _boundary(b), _begin(begin), _end(end) {} + virtual void do_oop(oop* p) { VerifyCleanCardClosure::do_oop_work(p); } + virtual void do_oop(narrowOop* p) { VerifyCleanCardClosure::do_oop_work(p); } }; class VerifyCTSpaceClosure: public SpaceClosure { +private: CardTableRS* _ct; HeapWord* _boundary; public: VerifyCTSpaceClosure(CardTableRS* ct, HeapWord* boundary) : _ct(ct), _boundary(boundary) {} - void do_space(Space* s) { _ct->verify_space(s, _boundary); } + virtual void do_space(Space* s) { _ct->verify_space(s, _boundary); } }; class VerifyCTGenClosure: public GenCollectedHeap::GenClosure { diff --git a/hotspot/src/share/vm/memory/cardTableRS.hpp b/hotspot/src/share/vm/memory/cardTableRS.hpp index 5d92067aa43..c2180de67d3 100644 --- a/hotspot/src/share/vm/memory/cardTableRS.hpp +++ b/hotspot/src/share/vm/memory/cardTableRS.hpp @@ -106,18 +106,18 @@ public: // closure application. void younger_refs_iterate(Generation* g, OopsInGenClosure* blk); - void inline_write_ref_field_gc(oop* field, oop new_val) { + void inline_write_ref_field_gc(void* field, oop new_val) { jbyte* byte = _ct_bs.byte_for(field); *byte = youngergen_card; } - void write_ref_field_gc_work(oop* field, oop new_val) { + void write_ref_field_gc_work(void* field, oop new_val) { inline_write_ref_field_gc(field, new_val); } // Override. Might want to devirtualize this in the same fashion as // above. Ensures that the value of the card for field says that it's // a younger card in the current collection. - virtual void write_ref_field_gc_par(oop* field, oop new_val); + virtual void write_ref_field_gc_par(void* field, oop new_val); void resize_covered_region(MemRegion new_region); diff --git a/hotspot/src/share/vm/memory/compactingPermGenGen.cpp b/hotspot/src/share/vm/memory/compactingPermGenGen.cpp index 317908b188f..78ada701405 100644 --- a/hotspot/src/share/vm/memory/compactingPermGenGen.cpp +++ b/hotspot/src/share/vm/memory/compactingPermGenGen.cpp @@ -49,9 +49,9 @@ public: // to prevent visiting any object twice. class RecursiveAdjustSharedObjectClosure : public OopClosure { -public: - void do_oop(oop* o) { - oop obj = *o; + protected: + template inline void do_oop_work(T* p) { + oop obj = oopDesc::load_decode_heap_oop_not_null(p); if (obj->is_shared_readwrite()) { if (obj->mark()->is_marked()) { obj->init_mark(); // Don't revisit this object. @@ -71,7 +71,10 @@ public: } } } - }; + } + public: + virtual void do_oop(oop* p) { RecursiveAdjustSharedObjectClosure::do_oop_work(p); } + virtual void do_oop(narrowOop* p) { RecursiveAdjustSharedObjectClosure::do_oop_work(p); } }; @@ -86,9 +89,9 @@ public: // as doing so can cause hash codes to be computed, destroying // forwarding pointers. class TraversePlaceholdersClosure : public OopClosure { - public: - void do_oop(oop* o) { - oop obj = *o; + protected: + template inline void do_oop_work(T* p) { + oop obj = oopDesc::load_decode_heap_oop_not_null(p); if (obj->klass() == Universe::symbolKlassObj() && obj->is_shared_readonly()) { symbolHandle sym((symbolOop) obj); @@ -99,6 +102,10 @@ class TraversePlaceholdersClosure : public OopClosure { } } } + public: + virtual void do_oop(oop* p) { TraversePlaceholdersClosure::do_oop_work(p); } + virtual void do_oop(narrowOop* p) { TraversePlaceholdersClosure::do_oop_work(p); } + }; diff --git a/hotspot/src/share/vm/memory/defNewGeneration.cpp b/hotspot/src/share/vm/memory/defNewGeneration.cpp index f892ffdb5ad..d13c9e9adff 100644 --- a/hotspot/src/share/vm/memory/defNewGeneration.cpp +++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp @@ -47,31 +47,9 @@ KeepAliveClosure(ScanWeakRefClosure* cl) : _cl(cl) { _rs = (CardTableRS*)rs; } -void DefNewGeneration::KeepAliveClosure::do_oop(oop* p) { - // We never expect to see a null reference being processed - // as a weak reference. - assert (*p != NULL, "expected non-null ref"); - assert ((*p)->is_oop(), "expected an oop while scanning weak refs"); +void DefNewGeneration::KeepAliveClosure::do_oop(oop* p) { DefNewGeneration::KeepAliveClosure::do_oop_work(p); } +void DefNewGeneration::KeepAliveClosure::do_oop(narrowOop* p) { DefNewGeneration::KeepAliveClosure::do_oop_work(p); } - _cl->do_oop_nv(p); - - // Card marking is trickier for weak refs. - // This oop is a 'next' field which was filled in while we - // were discovering weak references. While we might not need - // to take a special action to keep this reference alive, we - // will need to dirty a card as the field was modified. - // - // Alternatively, we could create a method which iterates through - // each generation, allowing them in turn to examine the modified - // field. - // - // We could check that p is also in an older generation, but - // dirty cards in the youngest gen are never scanned, so the - // extra check probably isn't worthwhile. - if (Universe::heap()->is_in_reserved(p)) { - _rs->inline_write_ref_field_gc(p, *p); - } -} DefNewGeneration::FastKeepAliveClosure:: FastKeepAliveClosure(DefNewGeneration* g, ScanWeakRefClosure* cl) : @@ -79,19 +57,8 @@ FastKeepAliveClosure(DefNewGeneration* g, ScanWeakRefClosure* cl) : _boundary = g->reserved().end(); } -void DefNewGeneration::FastKeepAliveClosure::do_oop(oop* p) { - assert (*p != NULL, "expected non-null ref"); - assert ((*p)->is_oop(), "expected an oop while scanning weak refs"); - - _cl->do_oop_nv(p); - - // Optimized for Defnew generation if it's the youngest generation: - // we set a younger_gen card if we have an older->youngest - // generation pointer. - if (((HeapWord*)(*p) < _boundary) && Universe::heap()->is_in_reserved(p)) { - _rs->inline_write_ref_field_gc(p, *p); - } -} +void DefNewGeneration::FastKeepAliveClosure::do_oop(oop* p) { DefNewGeneration::FastKeepAliveClosure::do_oop_work(p); } +void DefNewGeneration::FastKeepAliveClosure::do_oop(narrowOop* p) { DefNewGeneration::FastKeepAliveClosure::do_oop_work(p); } DefNewGeneration::EvacuateFollowersClosure:: EvacuateFollowersClosure(GenCollectedHeap* gch, int level, @@ -132,6 +99,9 @@ ScanClosure::ScanClosure(DefNewGeneration* g, bool gc_barrier) : _boundary = _g->reserved().end(); } +void ScanClosure::do_oop(oop* p) { ScanClosure::do_oop_work(p); } +void ScanClosure::do_oop(narrowOop* p) { ScanClosure::do_oop_work(p); } + FastScanClosure::FastScanClosure(DefNewGeneration* g, bool gc_barrier) : OopsInGenClosure(g), _g(g), _gc_barrier(gc_barrier) { @@ -139,6 +109,9 @@ FastScanClosure::FastScanClosure(DefNewGeneration* g, bool gc_barrier) : _boundary = _g->reserved().end(); } +void FastScanClosure::do_oop(oop* p) { FastScanClosure::do_oop_work(p); } +void FastScanClosure::do_oop(narrowOop* p) { FastScanClosure::do_oop_work(p); } + ScanWeakRefClosure::ScanWeakRefClosure(DefNewGeneration* g) : OopClosure(g->ref_processor()), _g(g) { @@ -146,6 +119,11 @@ ScanWeakRefClosure::ScanWeakRefClosure(DefNewGeneration* g) : _boundary = _g->reserved().end(); } +void ScanWeakRefClosure::do_oop(oop* p) { ScanWeakRefClosure::do_oop_work(p); } +void ScanWeakRefClosure::do_oop(narrowOop* p) { ScanWeakRefClosure::do_oop_work(p); } + +void FilteringClosure::do_oop(oop* p) { FilteringClosure::do_oop_work(p); } +void FilteringClosure::do_oop(narrowOop* p) { FilteringClosure::do_oop_work(p); } DefNewGeneration::DefNewGeneration(ReservedSpace rs, size_t initial_size, @@ -656,7 +634,7 @@ void DefNewGeneration::handle_promotion_failure(oop old) { } } -oop DefNewGeneration::copy_to_survivor_space(oop old, oop* from) { +oop DefNewGeneration::copy_to_survivor_space(oop old) { assert(is_in_reserved(old) && !old->is_forwarded(), "shouldn't be scavenging this oop"); size_t s = old->size(); @@ -669,7 +647,7 @@ oop DefNewGeneration::copy_to_survivor_space(oop old, oop* from) { // Otherwise try allocating obj tenured if (obj == NULL) { - obj = _next_gen->promote(old, s, from); + obj = _next_gen->promote(old, s); if (obj == NULL) { if (!HandlePromotionFailure) { // A failed promotion likely means the MaxLiveObjectEvacuationRatio flag @@ -862,3 +840,69 @@ void DefNewGeneration::print_on(outputStream* st) const { const char* DefNewGeneration::name() const { return "def new generation"; } + +// Moved from inline file as they are not called inline +CompactibleSpace* DefNewGeneration::first_compaction_space() const { + return eden(); +} + +HeapWord* DefNewGeneration::allocate(size_t word_size, + bool is_tlab) { + // This is the slow-path allocation for the DefNewGeneration. + // Most allocations are fast-path in compiled code. + // We try to allocate from the eden. If that works, we are happy. + // Note that since DefNewGeneration supports lock-free allocation, we + // have to use it here, as well. + HeapWord* result = eden()->par_allocate(word_size); + if (result != NULL) { + return result; + } + do { + HeapWord* old_limit = eden()->soft_end(); + if (old_limit < eden()->end()) { + // Tell the next generation we reached a limit. + HeapWord* new_limit = + next_gen()->allocation_limit_reached(eden(), eden()->top(), word_size); + if (new_limit != NULL) { + Atomic::cmpxchg_ptr(new_limit, eden()->soft_end_addr(), old_limit); + } else { + assert(eden()->soft_end() == eden()->end(), + "invalid state after allocation_limit_reached returned null"); + } + } else { + // The allocation failed and the soft limit is equal to the hard limit, + // there are no reasons to do an attempt to allocate + assert(old_limit == eden()->end(), "sanity check"); + break; + } + // Try to allocate until succeeded or the soft limit can't be adjusted + result = eden()->par_allocate(word_size); + } while (result == NULL); + + // If the eden is full and the last collection bailed out, we are running + // out of heap space, and we try to allocate the from-space, too. + // allocate_from_space can't be inlined because that would introduce a + // circular dependency at compile time. + if (result == NULL) { + result = allocate_from_space(word_size); + } + return result; +} + +HeapWord* DefNewGeneration::par_allocate(size_t word_size, + bool is_tlab) { + return eden()->par_allocate(word_size); +} + +void DefNewGeneration::gc_prologue(bool full) { + // Ensure that _end and _soft_end are the same in eden space. + eden()->set_soft_end(eden()->end()); +} + +size_t DefNewGeneration::tlab_capacity() const { + return eden()->capacity(); +} + +size_t DefNewGeneration::unsafe_max_tlab_alloc() const { + return unsafe_max_alloc_nogc(); +} diff --git a/hotspot/src/share/vm/memory/defNewGeneration.hpp b/hotspot/src/share/vm/memory/defNewGeneration.hpp index 289a5317e07..893afc055c7 100644 --- a/hotspot/src/share/vm/memory/defNewGeneration.hpp +++ b/hotspot/src/share/vm/memory/defNewGeneration.hpp @@ -24,6 +24,7 @@ class EdenSpace; class ContiguousSpace; +class ScanClosure; // DefNewGeneration is a young generation containing eden, from- and // to-space. @@ -155,17 +156,21 @@ protected: protected: ScanWeakRefClosure* _cl; CardTableRS* _rs; + template void do_oop_work(T* p); public: KeepAliveClosure(ScanWeakRefClosure* cl); - void do_oop(oop* p); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); }; class FastKeepAliveClosure: public KeepAliveClosure { protected: HeapWord* _boundary; + template void do_oop_work(T* p); public: FastKeepAliveClosure(DefNewGeneration* g, ScanWeakRefClosure* cl); - void do_oop(oop* p); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); }; class EvacuateFollowersClosure: public VoidClosure { @@ -206,7 +211,7 @@ protected: ContiguousSpace* from() const { return _from_space; } ContiguousSpace* to() const { return _to_space; } - inline CompactibleSpace* first_compaction_space() const; + virtual CompactibleSpace* first_compaction_space() const; // Space enquiries size_t capacity() const; @@ -226,8 +231,8 @@ protected: // Thread-local allocation buffers bool supports_tlab_allocation() const { return true; } - inline size_t tlab_capacity() const; - inline size_t unsafe_max_tlab_alloc() const; + size_t tlab_capacity() const; + size_t unsafe_max_tlab_alloc() const; // Grow the generation by the specified number of bytes. // The size of bytes is assumed to be properly aligned. @@ -265,13 +270,13 @@ protected: return result; } - inline HeapWord* allocate(size_t word_size, bool is_tlab); + HeapWord* allocate(size_t word_size, bool is_tlab); HeapWord* allocate_from_space(size_t word_size); - inline HeapWord* par_allocate(size_t word_size, bool is_tlab); + HeapWord* par_allocate(size_t word_size, bool is_tlab); // Prologue & Epilogue - inline virtual void gc_prologue(bool full); + virtual void gc_prologue(bool full); virtual void gc_epilogue(bool full); // Doesn't require additional work during GC prologue and epilogue @@ -307,7 +312,7 @@ protected: bool is_tlab, bool parallel = false); - oop copy_to_survivor_space(oop old, oop* from); + oop copy_to_survivor_space(oop old); int tenuring_threshold() { return _tenuring_threshold; } // Performance Counter support diff --git a/hotspot/src/share/vm/memory/defNewGeneration.inline.hpp b/hotspot/src/share/vm/memory/defNewGeneration.inline.hpp index dffc86b5a19..23a96984564 100644 --- a/hotspot/src/share/vm/memory/defNewGeneration.inline.hpp +++ b/hotspot/src/share/vm/memory/defNewGeneration.inline.hpp @@ -22,67 +22,60 @@ * */ -CompactibleSpace* DefNewGeneration::first_compaction_space() const { - return eden(); -} +// Methods of protected closure types -HeapWord* DefNewGeneration::allocate(size_t word_size, - bool is_tlab) { - // This is the slow-path allocation for the DefNewGeneration. - // Most allocations are fast-path in compiled code. - // We try to allocate from the eden. If that works, we are happy. - // Note that since DefNewGeneration supports lock-free allocation, we - // have to use it here, as well. - HeapWord* result = eden()->par_allocate(word_size); - if (result != NULL) { - return result; +template +inline void DefNewGeneration::KeepAliveClosure::do_oop_work(T* p) { +#ifdef ASSERT + { + // We never expect to see a null reference being processed + // as a weak reference. + assert (!oopDesc::is_null(*p), "expected non-null ref"); + oop obj = oopDesc::load_decode_heap_oop_not_null(p); + assert (obj->is_oop(), "expected an oop while scanning weak refs"); } - do { - HeapWord* old_limit = eden()->soft_end(); - if (old_limit < eden()->end()) { - // Tell the next generation we reached a limit. - HeapWord* new_limit = - next_gen()->allocation_limit_reached(eden(), eden()->top(), word_size); - if (new_limit != NULL) { - Atomic::cmpxchg_ptr(new_limit, eden()->soft_end_addr(), old_limit); - } else { - assert(eden()->soft_end() == eden()->end(), - "invalid state after allocation_limit_reached returned null"); - } - } else { - // The allocation failed and the soft limit is equal to the hard limit, - // there are no reasons to do an attempt to allocate - assert(old_limit == eden()->end(), "sanity check"); - break; - } - // Try to allocate until succeeded or the soft limit can't be adjusted - result = eden()->par_allocate(word_size); - } while (result == NULL); +#endif // ASSERT - // If the eden is full and the last collection bailed out, we are running - // out of heap space, and we try to allocate the from-space, too. - // allocate_from_space can't be inlined because that would introduce a - // circular dependency at compile time. - if (result == NULL) { - result = allocate_from_space(word_size); + _cl->do_oop_nv(p); + + // Card marking is trickier for weak refs. + // This oop is a 'next' field which was filled in while we + // were discovering weak references. While we might not need + // to take a special action to keep this reference alive, we + // will need to dirty a card as the field was modified. + // + // Alternatively, we could create a method which iterates through + // each generation, allowing them in turn to examine the modified + // field. + // + // We could check that p is also in an older generation, but + // dirty cards in the youngest gen are never scanned, so the + // extra check probably isn't worthwhile. + if (Universe::heap()->is_in_reserved(p)) { + oop obj = oopDesc::load_decode_heap_oop_not_null(p); + _rs->inline_write_ref_field_gc(p, obj); } - return result; } -HeapWord* DefNewGeneration::par_allocate(size_t word_size, - bool is_tlab) { - return eden()->par_allocate(word_size); -} +template +inline void DefNewGeneration::FastKeepAliveClosure::do_oop_work(T* p) { +#ifdef ASSERT + { + // We never expect to see a null reference being processed + // as a weak reference. + assert (!oopDesc::is_null(*p), "expected non-null ref"); + oop obj = oopDesc::load_decode_heap_oop_not_null(p); + assert (obj->is_oop(), "expected an oop while scanning weak refs"); + } +#endif // ASSERT -void DefNewGeneration::gc_prologue(bool full) { - // Ensure that _end and _soft_end are the same in eden space. - eden()->set_soft_end(eden()->end()); -} + _cl->do_oop_nv(p); -size_t DefNewGeneration::tlab_capacity() const { - return eden()->capacity(); -} - -size_t DefNewGeneration::unsafe_max_tlab_alloc() const { - return unsafe_max_alloc_nogc(); + // Optimized for Defnew generation if it's the youngest generation: + // we set a younger_gen card if we have an older->youngest + // generation pointer. + oop obj = oopDesc::load_decode_heap_oop_not_null(p); + if (((HeapWord*)obj < _boundary) && Universe::heap()->is_in_reserved(p)) { + _rs->inline_write_ref_field_gc(p, obj); + } } diff --git a/hotspot/src/share/vm/memory/dump.cpp b/hotspot/src/share/vm/memory/dump.cpp index 4f75ca8e7c9..9499336282b 100644 --- a/hotspot/src/share/vm/memory/dump.cpp +++ b/hotspot/src/share/vm/memory/dump.cpp @@ -60,9 +60,9 @@ public: hash_offset = java_lang_String::hash_offset_in_bytes(); } - void do_oop(oop* pobj) { - if (pobj != NULL) { - oop obj = *pobj; + void do_oop(oop* p) { + if (p != NULL) { + oop obj = *p; if (obj->klass() == SystemDictionary::string_klass()) { int hash; @@ -79,6 +79,7 @@ public: } } } + void do_oop(narrowOop* p) { ShouldNotReachHere(); } }; @@ -121,9 +122,8 @@ static bool mark_object(oop obj) { class MarkObjectsOopClosure : public OopClosure { public: - void do_oop(oop* pobj) { - mark_object(*pobj); - } + void do_oop(oop* p) { mark_object(*p); } + void do_oop(narrowOop* p) { ShouldNotReachHere(); } }; @@ -136,6 +136,7 @@ public: mark_object(obj); } } + void do_oop(narrowOop* pobj) { ShouldNotReachHere(); } }; @@ -554,6 +555,7 @@ public: } } } + void do_oop(narrowOop* pobj) { ShouldNotReachHere(); } }; @@ -690,6 +692,8 @@ public: ++top; } + void do_oop(narrowOop* pobj) { ShouldNotReachHere(); } + void do_int(int* p) { check_space(); *top = (oop)(intptr_t)*p; diff --git a/hotspot/src/share/vm/memory/gcLocker.cpp b/hotspot/src/share/vm/memory/gcLocker.cpp index 428a5d27553..4e770e01b36 100644 --- a/hotspot/src/share/vm/memory/gcLocker.cpp +++ b/hotspot/src/share/vm/memory/gcLocker.cpp @@ -32,6 +32,12 @@ volatile bool GC_locker::_doing_gc = false; void GC_locker::stall_until_clear() { assert(!JavaThread::current()->in_critical(), "Would deadlock"); + if (PrintJNIGCStalls && PrintGCDetails) { + ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 + gclog_or_tty->print_cr( + "Allocation failed. Thread \"%s\" is stalled by JNI critical section.", + JavaThread::current()->name()); + } MutexLocker ml(JNICritical_lock); // Wait for _needs_gc to be cleared while (GC_locker::needs_gc()) { diff --git a/hotspot/src/share/vm/memory/gcLocker.hpp b/hotspot/src/share/vm/memory/gcLocker.hpp index 00ba7ad89fd..b14b75797f1 100644 --- a/hotspot/src/share/vm/memory/gcLocker.hpp +++ b/hotspot/src/share/vm/memory/gcLocker.hpp @@ -184,7 +184,9 @@ class No_Safepoint_Verifier : public No_GC_Verifier { Thread *_thread; public: #ifdef ASSERT - No_Safepoint_Verifier(bool activated = true, bool verifygc = true ) : No_GC_Verifier(verifygc) { + No_Safepoint_Verifier(bool activated = true, bool verifygc = true ) : + No_GC_Verifier(verifygc), + _activated(activated) { _thread = Thread::current(); if (_activated) { _thread->_allow_allocation_count++; diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp index afc4f52eacf..dc3ba9b3cf3 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp @@ -624,6 +624,7 @@ public: void do_oop(oop* p) { assert((*p) == NULL || (*p)->is_perm(), "Referent should be perm."); } + void do_oop(narrowOop* p) { ShouldNotReachHere(); } }; static AssertIsPermClosure assert_is_perm_closure; @@ -1300,8 +1301,7 @@ void GenCollectedHeap::ensure_parsability(bool retire_tlabs) { oop GenCollectedHeap::handle_failed_promotion(Generation* gen, oop obj, - size_t obj_size, - oop* ref) { + size_t obj_size) { assert(obj_size == (size_t)obj->size(), "bad obj_size passed in"); HeapWord* result = NULL; diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.hpp b/hotspot/src/share/vm/memory/genCollectedHeap.hpp index b3cf2de0f4b..54dce33bb80 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.hpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.hpp @@ -35,6 +35,7 @@ class GenCollectedHeap : public SharedHeap { friend class CMSCollector; friend class GenMarkSweep; friend class VM_GenCollectForAllocation; + friend class VM_GenCollectForPermanentAllocation; friend class VM_GenCollectFull; friend class VM_GenCollectFullConcurrent; friend class VM_GC_HeapInspection; @@ -452,8 +453,7 @@ public: // gen; return the new location of obj if successful. Otherwise, return NULL. oop handle_failed_promotion(Generation* gen, oop obj, - size_t obj_size, - oop* ref); + size_t obj_size); private: // Accessor for memory state verification support diff --git a/hotspot/src/share/vm/memory/genMarkSweep.cpp b/hotspot/src/share/vm/memory/genMarkSweep.cpp index 35e074403a6..e98f6793001 100644 --- a/hotspot/src/share/vm/memory/genMarkSweep.cpp +++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp @@ -73,8 +73,7 @@ void GenMarkSweep::invoke_at_safepoint(int level, ReferenceProcessor* rp, VALIDATE_MARK_SWEEP_ONLY( if (ValidateMarkSweep) { - guarantee(_root_refs_stack->length() == 0, - "should be empty by now"); + guarantee(_root_refs_stack->length() == 0, "should be empty by now"); } ) @@ -165,9 +164,9 @@ void GenMarkSweep::allocate_stacks() { #ifdef VALIDATE_MARK_SWEEP if (ValidateMarkSweep) { - _root_refs_stack = new (ResourceObj::C_HEAP) GrowableArray(100, true); - _other_refs_stack = new (ResourceObj::C_HEAP) GrowableArray(100, true); - _adjusted_pointers = new (ResourceObj::C_HEAP) GrowableArray(100, true); + _root_refs_stack = new (ResourceObj::C_HEAP) GrowableArray(100, true); + _other_refs_stack = new (ResourceObj::C_HEAP) GrowableArray(100, true); + _adjusted_pointers = new (ResourceObj::C_HEAP) GrowableArray(100, true); _live_oops = new (ResourceObj::C_HEAP) GrowableArray(100, true); _live_oops_moved_to = new (ResourceObj::C_HEAP) GrowableArray(100, true); _live_oops_size = new (ResourceObj::C_HEAP) GrowableArray(100, true); diff --git a/hotspot/src/share/vm/memory/genOopClosures.hpp b/hotspot/src/share/vm/memory/genOopClosures.hpp index 137482c3cca..d0f142f65a3 100644 --- a/hotspot/src/share/vm/memory/genOopClosures.hpp +++ b/hotspot/src/share/vm/memory/genOopClosures.hpp @@ -28,6 +28,11 @@ class CardTableRS; class CardTableModRefBS; class DefNewGeneration; +template class GenericTaskQueue; +typedef GenericTaskQueue OopTaskQueue; +template class GenericTaskQueueSet; +typedef GenericTaskQueueSet OopTaskQueueSet; + // Closure for iterating roots from a particular generation // Note: all classes deriving from this MUST call this do_barrier // method at the end of their own do_oop method! @@ -35,13 +40,13 @@ class DefNewGeneration; class OopsInGenClosure : public OopClosure { private: - Generation* _orig_gen; // generation originally set in ctor - Generation* _gen; // generation being scanned + Generation* _orig_gen; // generation originally set in ctor + Generation* _gen; // generation being scanned protected: // Some subtypes need access. - HeapWord* _gen_boundary; // start of generation - CardTableRS* _rs; // remembered set + HeapWord* _gen_boundary; // start of generation + CardTableRS* _rs; // remembered set // For assertions Generation* generation() { return _gen; } @@ -49,7 +54,7 @@ class OopsInGenClosure : public OopClosure { // Derived classes that modify oops so that they might be old-to-young // pointers must call the method below. - void do_barrier(oop* p); + template void do_barrier(T* p); public: OopsInGenClosure() : OopClosure(NULL), @@ -75,14 +80,17 @@ class OopsInGenClosure : public OopClosure { // This closure will perform barrier store calls for ALL // pointers in scanned oops. class ScanClosure: public OopsInGenClosure { -protected: + protected: DefNewGeneration* _g; - HeapWord* _boundary; - bool _gc_barrier; -public: + HeapWord* _boundary; + bool _gc_barrier; + template inline void do_oop_work(T* p); + public: ScanClosure(DefNewGeneration* g, bool gc_barrier); - void do_oop(oop* p); - void do_oop_nv(oop* p); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); bool do_header() { return false; } Prefetch::style prefetch_style() { return Prefetch::do_write; @@ -95,14 +103,17 @@ public: // pointers into the DefNewGeneration. This is less // precise, but faster, than a ScanClosure class FastScanClosure: public OopsInGenClosure { -protected: + protected: DefNewGeneration* _g; - HeapWord* _boundary; - bool _gc_barrier; -public: + HeapWord* _boundary; + bool _gc_barrier; + template inline void do_oop_work(T* p); + public: FastScanClosure(DefNewGeneration* g, bool gc_barrier); - void do_oop(oop* p); - void do_oop_nv(oop* p); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); bool do_header() { return false; } Prefetch::style prefetch_style() { return Prefetch::do_write; @@ -110,19 +121,27 @@ public: }; class FilteringClosure: public OopClosure { - HeapWord* _boundary; + private: + HeapWord* _boundary; OopClosure* _cl; -public: + protected: + template inline void do_oop_work(T* p) { + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + if ((HeapWord*)obj < _boundary) { + _cl->do_oop(p); + } + } + } + public: FilteringClosure(HeapWord* boundary, OopClosure* cl) : OopClosure(cl->_ref_processor), _boundary(boundary), _cl(cl) {} - void do_oop(oop* p); - void do_oop_nv(oop* p) { - oop obj = *p; - if ((HeapWord*)obj < _boundary && obj != NULL) { - _cl->do_oop(p); - } - } + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p) { FilteringClosure::do_oop_work(p); } + inline void do_oop_nv(narrowOop* p) { FilteringClosure::do_oop_work(p); } bool do_header() { return false; } }; @@ -131,19 +150,26 @@ public: // OopsInGenClosure -- weak references are processed all // at once, with no notion of which generation they were in. class ScanWeakRefClosure: public OopClosure { -protected: - DefNewGeneration* _g; - HeapWord* _boundary; -public: + protected: + DefNewGeneration* _g; + HeapWord* _boundary; + template inline void do_oop_work(T* p); + public: ScanWeakRefClosure(DefNewGeneration* g); - void do_oop(oop* p); - void do_oop_nv(oop* p); + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); + inline void do_oop_nv(oop* p); + inline void do_oop_nv(narrowOop* p); }; class VerifyOopClosure: public OopClosure { -public: - void do_oop(oop* p) { - guarantee((*p)->is_oop_or_null(), "invalid oop"); + protected: + template inline void do_oop_work(T* p) { + oop obj = oopDesc::load_decode_heap_oop(p); + guarantee(obj->is_oop_or_null(), "invalid oop"); } + public: + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); static VerifyOopClosure verify_oop; }; diff --git a/hotspot/src/share/vm/memory/genOopClosures.inline.hpp b/hotspot/src/share/vm/memory/genOopClosures.inline.hpp index 3bbe7652792..a6699d74b18 100644 --- a/hotspot/src/share/vm/memory/genOopClosures.inline.hpp +++ b/hotspot/src/share/vm/memory/genOopClosures.inline.hpp @@ -38,10 +38,10 @@ inline void OopsInGenClosure::set_generation(Generation* gen) { } } -inline void OopsInGenClosure::do_barrier(oop* p) { +template inline void OopsInGenClosure::do_barrier(T* p) { assert(generation()->is_in_reserved(p), "expected ref in generation"); - oop obj = *p; - assert(obj != NULL, "expected non-null object"); + assert(!oopDesc::is_null(*p), "expected non-null object"); + oop obj = oopDesc::load_decode_heap_oop_not_null(p); // If p points to a younger generation, mark the card. if ((HeapWord*)obj < _gen_boundary) { _rs->inline_write_ref_field_gc(p, obj); @@ -49,18 +49,17 @@ inline void OopsInGenClosure::do_barrier(oop* p) { } // NOTE! Any changes made here should also be made -// in FastScanClosure::do_oop(); -inline void ScanClosure::do_oop(oop* p) { - oop obj = *p; +// in FastScanClosure::do_oop_work() +template inline void ScanClosure::do_oop_work(T* p) { + T heap_oop = oopDesc::load_heap_oop(p); // Should we copy the obj? - if (obj != NULL) { + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); if ((HeapWord*)obj < _boundary) { assert(!_g->to()->is_in_reserved(obj), "Scanning field twice?"); - if (obj->is_forwarded()) { - *p = obj->forwardee(); - } else { - *p = _g->copy_to_survivor_space(obj, p); - } + oop new_obj = obj->is_forwarded() ? obj->forwardee() + : _g->copy_to_survivor_space(obj); + oopDesc::encode_store_heap_oop_not_null(p, new_obj); } if (_gc_barrier) { // Now call parent closure @@ -69,23 +68,21 @@ inline void ScanClosure::do_oop(oop* p) { } } -inline void ScanClosure::do_oop_nv(oop* p) { - ScanClosure::do_oop(p); -} +inline void ScanClosure::do_oop_nv(oop* p) { ScanClosure::do_oop_work(p); } +inline void ScanClosure::do_oop_nv(narrowOop* p) { ScanClosure::do_oop_work(p); } // NOTE! Any changes made here should also be made -// in ScanClosure::do_oop(); -inline void FastScanClosure::do_oop(oop* p) { - oop obj = *p; +// in ScanClosure::do_oop_work() +template inline void FastScanClosure::do_oop_work(T* p) { + T heap_oop = oopDesc::load_heap_oop(p); // Should we copy the obj? - if (obj != NULL) { + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); if ((HeapWord*)obj < _boundary) { assert(!_g->to()->is_in_reserved(obj), "Scanning field twice?"); - if (obj->is_forwarded()) { - *p = obj->forwardee(); - } else { - *p = _g->copy_to_survivor_space(obj, p); - } + oop new_obj = obj->is_forwarded() ? obj->forwardee() + : _g->copy_to_survivor_space(obj); + oopDesc::encode_store_heap_oop_not_null(p, new_obj); if (_gc_barrier) { // Now call parent closure do_barrier(p); @@ -94,26 +91,22 @@ inline void FastScanClosure::do_oop(oop* p) { } } -inline void FastScanClosure::do_oop_nv(oop* p) { - FastScanClosure::do_oop(p); -} +inline void FastScanClosure::do_oop_nv(oop* p) { FastScanClosure::do_oop_work(p); } +inline void FastScanClosure::do_oop_nv(narrowOop* p) { FastScanClosure::do_oop_work(p); } // Note similarity to ScanClosure; the difference is that // the barrier set is taken care of outside this closure. -inline void ScanWeakRefClosure::do_oop(oop* p) { - oop obj = *p; - assert (obj != NULL, "null weak reference?"); +template inline void ScanWeakRefClosure::do_oop_work(T* p) { + assert(!oopDesc::is_null(*p), "null weak reference?"); + oop obj = oopDesc::load_decode_heap_oop_not_null(p); // weak references are sometimes scanned twice; must check // that to-space doesn't already contain this object if ((HeapWord*)obj < _boundary && !_g->to()->is_in_reserved(obj)) { - if (obj->is_forwarded()) { - *p = obj->forwardee(); - } else { - *p = _g->copy_to_survivor_space(obj, p); - } + oop new_obj = obj->is_forwarded() ? obj->forwardee() + : _g->copy_to_survivor_space(obj); + oopDesc::encode_store_heap_oop_not_null(p, new_obj); } } -inline void ScanWeakRefClosure::do_oop_nv(oop* p) { - ScanWeakRefClosure::do_oop(p); -} +inline void ScanWeakRefClosure::do_oop_nv(oop* p) { ScanWeakRefClosure::do_oop_work(p); } +inline void ScanWeakRefClosure::do_oop_nv(narrowOop* p) { ScanWeakRefClosure::do_oop_work(p); } diff --git a/hotspot/src/share/vm/memory/genRemSet.hpp b/hotspot/src/share/vm/memory/genRemSet.hpp index 006eab3ebb6..c2ef23061af 100644 --- a/hotspot/src/share/vm/memory/genRemSet.hpp +++ b/hotspot/src/share/vm/memory/genRemSet.hpp @@ -68,13 +68,13 @@ public: // This method is used to notify the remembered set that "new_val" has // been written into "field" by the garbage collector. - void write_ref_field_gc(oop* field, oop new_val); + void write_ref_field_gc(void* field, oop new_val); protected: - virtual void write_ref_field_gc_work(oop* field, oop new_val) = 0; + virtual void write_ref_field_gc_work(void* field, oop new_val) = 0; public: // A version of the above suitable for use by parallel collectors. - virtual void write_ref_field_gc_par(oop* field, oop new_val) = 0; + virtual void write_ref_field_gc_par(void* field, oop new_val) = 0; // Resize one of the regions covered by the remembered set. virtual void resize_covered_region(MemRegion new_region) = 0; diff --git a/hotspot/src/share/vm/memory/genRemSet.inline.hpp b/hotspot/src/share/vm/memory/genRemSet.inline.hpp index 448c18e22b5..3ae0e7f6820 100644 --- a/hotspot/src/share/vm/memory/genRemSet.inline.hpp +++ b/hotspot/src/share/vm/memory/genRemSet.inline.hpp @@ -26,7 +26,7 @@ // performance-critical call when when the rem set is the most common // card-table kind. -void GenRemSet::write_ref_field_gc(oop* field, oop new_val) { +void GenRemSet::write_ref_field_gc(void* field, oop new_val) { if (kind() == CardTableModRef) { ((CardTableRS*)this)->inline_write_ref_field_gc(field, new_val); } else { diff --git a/hotspot/src/share/vm/memory/generation.cpp b/hotspot/src/share/vm/memory/generation.cpp index d09238c193b..5ed3ec09b7b 100644 --- a/hotspot/src/share/vm/memory/generation.cpp +++ b/hotspot/src/share/vm/memory/generation.cpp @@ -171,7 +171,7 @@ bool Generation::promotion_attempt_is_safe(size_t promotion_in_bytes, } // Ignores "ref" and calls allocate(). -oop Generation::promote(oop obj, size_t obj_size, oop* ref) { +oop Generation::promote(oop obj, size_t obj_size) { assert(obj_size == (size_t)obj->size(), "bad obj_size passed in"); #ifndef PRODUCT @@ -186,7 +186,7 @@ oop Generation::promote(oop obj, size_t obj_size, oop* ref) { return oop(result); } else { GenCollectedHeap* gch = GenCollectedHeap::heap(); - return gch->handle_failed_promotion(this, obj, obj_size, ref); + return gch->handle_failed_promotion(this, obj, obj_size); } } diff --git a/hotspot/src/share/vm/memory/generation.hpp b/hotspot/src/share/vm/memory/generation.hpp index b0921e76626..2e146d53844 100644 --- a/hotspot/src/share/vm/memory/generation.hpp +++ b/hotspot/src/share/vm/memory/generation.hpp @@ -295,13 +295,7 @@ class Generation: public CHeapObj { // // The "obj_size" argument is just obj->size(), passed along so the caller can // avoid repeating the virtual call to retrieve it. - // - // The "ref" argument, if non-NULL, is the address of some reference to "obj" - // (that is "*ref == obj"); some generations may use this information to, for - // example, influence placement decisions. - // - // The default implementation ignores "ref" and calls allocate(). - virtual oop promote(oop obj, size_t obj_size, oop* ref); + virtual oop promote(oop obj, size_t obj_size); // Thread "thread_num" (0 <= i < ParalleGCThreads) wants to promote // object "obj", whose original mark word was "m", and whose size is diff --git a/hotspot/src/share/vm/memory/iterator.hpp b/hotspot/src/share/vm/memory/iterator.hpp index 29be107d681..1b92ddd4bc5 100644 --- a/hotspot/src/share/vm/memory/iterator.hpp +++ b/hotspot/src/share/vm/memory/iterator.hpp @@ -35,6 +35,8 @@ class OopClosure : public StackObj { OopClosure() : _ref_processor(NULL) { } virtual void do_oop(oop* o) = 0; virtual void do_oop_v(oop* o) { do_oop(o); } + virtual void do_oop(narrowOop* o) = 0; + virtual void do_oop_v(narrowOop* o) { do_oop(o); } // In support of post-processing of weak links of KlassKlass objects; // see KlassKlass::oop_oop_iterate(). diff --git a/hotspot/src/share/vm/memory/modRefBarrierSet.hpp b/hotspot/src/share/vm/memory/modRefBarrierSet.hpp index 85a94397732..c85a18e7ac5 100644 --- a/hotspot/src/share/vm/memory/modRefBarrierSet.hpp +++ b/hotspot/src/share/vm/memory/modRefBarrierSet.hpp @@ -37,19 +37,19 @@ public: bool has_write_ref_barrier() { return true; } bool has_write_prim_barrier() { return false; } - bool read_ref_needs_barrier(oop* field) { return false; } + bool read_ref_needs_barrier(void* field) { return false; } bool read_prim_needs_barrier(HeapWord* field, size_t bytes) { return false; } - virtual bool write_ref_needs_barrier(oop* field, oop new_val) = 0; + virtual bool write_ref_needs_barrier(void* field, oop new_val) = 0; bool write_prim_needs_barrier(HeapWord* field, size_t bytes, juint val1, juint val2) { return false; } void write_prim_field(oop obj, size_t offset, size_t bytes, juint val1, juint val2) {} - void read_ref_field(oop* field) {} + void read_ref_field(void* field) {} void read_prim_field(HeapWord* field, size_t bytes) {} protected: - virtual void write_ref_field_work(oop* field, oop new_val) = 0; + virtual void write_ref_field_work(void* field, oop new_val) = 0; public: void write_prim_field(HeapWord* field, size_t bytes, juint val1, juint val2) {} diff --git a/hotspot/src/share/vm/memory/permGen.cpp b/hotspot/src/share/vm/memory/permGen.cpp index f611cc36e1a..1c8fa9681ec 100644 --- a/hotspot/src/share/vm/memory/permGen.cpp +++ b/hotspot/src/share/vm/memory/permGen.cpp @@ -25,6 +25,70 @@ #include "incls/_precompiled.incl" #include "incls/_permGen.cpp.incl" +HeapWord* PermGen::mem_allocate_in_gen(size_t size, Generation* gen) { + MutexLocker ml(Heap_lock); + GCCause::Cause next_cause = GCCause::_permanent_generation_full; + GCCause::Cause prev_cause = GCCause::_no_gc; + + for (;;) { + HeapWord* obj = gen->allocate(size, false); + if (obj != NULL) { + return obj; + } + if (gen->capacity() < _capacity_expansion_limit || + prev_cause != GCCause::_no_gc) { + obj = gen->expand_and_allocate(size, false); + } + if (obj == NULL && prev_cause != GCCause::_last_ditch_collection) { + if (GC_locker::is_active_and_needs_gc()) { + // If this thread is not in a jni critical section, we stall + // the requestor until the critical section has cleared and + // GC allowed. When the critical section clears, a GC is + // initiated by the last thread exiting the critical section; so + // we retry the allocation sequence from the beginning of the loop, + // rather than causing more, now probably unnecessary, GC attempts. + JavaThread* jthr = JavaThread::current(); + if (!jthr->in_critical()) { + MutexUnlocker mul(Heap_lock); + // Wait for JNI critical section to be exited + GC_locker::stall_until_clear(); + continue; + } else { + if (CheckJNICalls) { + fatal("Possible deadlock due to allocating while" + " in jni critical section"); + } + return NULL; + } + } + + // Read the GC count while holding the Heap_lock + unsigned int gc_count_before = SharedHeap::heap()->total_collections(); + unsigned int full_gc_count_before = SharedHeap::heap()->total_full_collections(); + { + MutexUnlocker mu(Heap_lock); // give up heap lock, execute gets it back + VM_GenCollectForPermanentAllocation op(size, gc_count_before, full_gc_count_before, + next_cause); + VMThread::execute(&op); + if (!op.prologue_succeeded() || op.gc_locked()) { + assert(op.result() == NULL, "must be NULL if gc_locked() is true"); + continue; // retry and/or stall as necessary + } + obj = op.result(); + assert(obj == NULL || SharedHeap::heap()->is_in_reserved(obj), + "result not in heap"); + if (obj != NULL) { + return obj; + } + } + prev_cause = next_cause; + next_cause = GCCause::_last_ditch_collection; + } else { + return obj; + } + } +} + CompactingPermGen::CompactingPermGen(ReservedSpace rs, ReservedSpace shared_rs, size_t initial_byte_size, @@ -44,40 +108,7 @@ CompactingPermGen::CompactingPermGen(ReservedSpace rs, } HeapWord* CompactingPermGen::mem_allocate(size_t size) { - MutexLocker ml(Heap_lock); - HeapWord* obj = _gen->allocate(size, false); - bool tried_collection = false; - bool tried_expansion = false; - while (obj == NULL) { - if (_gen->capacity() >= _capacity_expansion_limit || tried_expansion) { - // Expansion limit reached, try collection before expanding further - // For now we force a full collection, this could be changed - SharedHeap::heap()->collect_locked(GCCause::_permanent_generation_full); - obj = _gen->allocate(size, false); - tried_collection = true; - tried_expansion = false; // ... following the collection: - // the collection may have shrunk the space. - } - if (obj == NULL && !tried_expansion) { - obj = _gen->expand_and_allocate(size, false); - tried_expansion = true; - } - if (obj == NULL && tried_collection && tried_expansion) { - // We have not been able to allocate despite a collection and - // an attempted space expansion. We now make a last-ditch collection - // attempt that will try to reclaim as much space as possible (for - // example by aggressively clearing all soft refs). - SharedHeap::heap()->collect_locked(GCCause::_last_ditch_collection); - obj = _gen->allocate(size, false); - if (obj == NULL) { - // An expansion attempt is necessary since the previous - // collection may have shrunk the space. - obj = _gen->expand_and_allocate(size, false); - } - break; - } - } - return obj; + return mem_allocate_in_gen(size, _gen); } void CompactingPermGen::compute_new_size() { diff --git a/hotspot/src/share/vm/memory/permGen.hpp b/hotspot/src/share/vm/memory/permGen.hpp index 47f16b83b0f..263a589b272 100644 --- a/hotspot/src/share/vm/memory/permGen.hpp +++ b/hotspot/src/share/vm/memory/permGen.hpp @@ -38,6 +38,8 @@ class PermGen : public CHeapObj { size_t _capacity_expansion_limit; // maximum expansion allowed without a // full gc occuring + HeapWord* mem_allocate_in_gen(size_t size, Generation* gen); + public: enum Name { MarkSweepCompact, MarkSweep, ConcurrentMarkSweep diff --git a/hotspot/src/share/vm/memory/referenceProcessor.cpp b/hotspot/src/share/vm/memory/referenceProcessor.cpp index 6aeeecd3e15..c9ba9b81c43 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.cpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp @@ -28,16 +28,32 @@ // List of discovered references. class DiscoveredList { public: - DiscoveredList() : _head(NULL), _len(0) { } - oop head() const { return _head; } - oop* head_ptr() { return &_head; } - void set_head(oop o) { _head = o; } - bool empty() const { return _head == ReferenceProcessor::_sentinelRef; } + DiscoveredList() : _len(0), _compressed_head(0), _oop_head(NULL) { } + oop head() const { + return UseCompressedOops ? oopDesc::decode_heap_oop_not_null(_compressed_head) : + _oop_head; + } + HeapWord* adr_head() { + return UseCompressedOops ? (HeapWord*)&_compressed_head : + (HeapWord*)&_oop_head; + } + void set_head(oop o) { + if (UseCompressedOops) { + // Must compress the head ptr. + _compressed_head = oopDesc::encode_heap_oop_not_null(o); + } else { + _oop_head = o; + } + } + bool empty() const { return head() == ReferenceProcessor::sentinel_ref(); } size_t length() { return _len; } void set_length(size_t len) { _len = len; } private: + // Set value depending on UseCompressedOops. This could be a template class + // but then we have to fix all the instantiations and declarations that use this class. + oop _oop_head; + narrowOop _compressed_head; size_t _len; - oop _head; }; oop ReferenceProcessor::_sentinelRef = NULL; @@ -49,11 +65,11 @@ void referenceProcessor_init() { } void ReferenceProcessor::init_statics() { - assert(_sentinelRef == NULL, "should be initialized precsiely once"); + assert(_sentinelRef == NULL, "should be initialized precisely once"); EXCEPTION_MARK; _sentinelRef = instanceKlass::cast( - SystemDictionary::object_klass())-> - allocate_permanent_instance(THREAD); + SystemDictionary::reference_klass())-> + allocate_permanent_instance(THREAD); // Initialize the master soft ref clock. java_lang_ref_SoftReference::set_clock(os::javaTimeMillis()); @@ -69,15 +85,13 @@ void ReferenceProcessor::init_statics() { "Unrecongnized RefDiscoveryPolicy"); } - -ReferenceProcessor* ReferenceProcessor::create_ref_processor( - MemRegion span, - bool atomic_discovery, - bool mt_discovery, - BoolObjectClosure* is_alive_non_header, - int parallel_gc_threads, - bool mt_processing) -{ +ReferenceProcessor* +ReferenceProcessor::create_ref_processor(MemRegion span, + bool atomic_discovery, + bool mt_discovery, + BoolObjectClosure* is_alive_non_header, + int parallel_gc_threads, + bool mt_processing) { int mt_degree = 1; if (parallel_gc_threads > 1) { mt_degree = parallel_gc_threads; @@ -93,10 +107,11 @@ ReferenceProcessor* ReferenceProcessor::create_ref_processor( return rp; } - ReferenceProcessor::ReferenceProcessor(MemRegion span, - bool atomic_discovery, bool mt_discovery, int mt_degree, - bool mt_processing) : + bool atomic_discovery, + bool mt_discovery, + int mt_degree, + bool mt_processing) : _discovering_refs(false), _enqueuing_is_done(false), _is_alive_non_header(NULL), @@ -114,10 +129,10 @@ ReferenceProcessor::ReferenceProcessor(MemRegion span, _discoveredWeakRefs = &_discoveredSoftRefs[_num_q]; _discoveredFinalRefs = &_discoveredWeakRefs[_num_q]; _discoveredPhantomRefs = &_discoveredFinalRefs[_num_q]; - assert(_sentinelRef != NULL, "_sentinelRef is NULL"); + assert(sentinel_ref() != NULL, "_sentinelRef is NULL"); // Initialized all entries to _sentinelRef for (int i = 0; i < _num_q * subclasses_of_ref; i++) { - _discoveredSoftRefs[i].set_head(_sentinelRef); + _discoveredSoftRefs[i].set_head(sentinel_ref()); _discoveredSoftRefs[i].set_length(0); } } @@ -134,16 +149,19 @@ void ReferenceProcessor::verify_no_references_recorded() { void ReferenceProcessor::weak_oops_do(OopClosure* f) { for (int i = 0; i < _num_q * subclasses_of_ref; i++) { - f->do_oop(_discoveredSoftRefs[i].head_ptr()); + if (UseCompressedOops) { + f->do_oop((narrowOop*)_discoveredSoftRefs[i].adr_head()); + } else { + f->do_oop((oop*)_discoveredSoftRefs[i].adr_head()); + } } } void ReferenceProcessor::oops_do(OopClosure* f) { - f->do_oop(&_sentinelRef); + f->do_oop(adr_sentinel_ref()); } -void ReferenceProcessor::update_soft_ref_master_clock() -{ +void ReferenceProcessor::update_soft_ref_master_clock() { // Update (advance) the soft ref master clock field. This must be done // after processing the soft ref list. jlong now = os::javaTimeMillis(); @@ -164,9 +182,7 @@ void ReferenceProcessor::update_soft_ref_master_clock() // past clock value. } - -void -ReferenceProcessor::process_discovered_references( +void ReferenceProcessor::process_discovered_references( ReferencePolicy* policy, BoolObjectClosure* is_alive, OopClosure* keep_alive, @@ -223,15 +239,13 @@ ReferenceProcessor::process_discovered_references( } } - #ifndef PRODUCT // Calculate the number of jni handles. -unsigned int ReferenceProcessor::count_jni_refs() -{ +uint ReferenceProcessor::count_jni_refs() { class AlwaysAliveClosure: public BoolObjectClosure { public: - bool do_object_b(oop obj) { return true; } - void do_object(oop obj) { assert(false, "Don't call"); } + virtual bool do_object_b(oop obj) { return true; } + virtual void do_object(oop obj) { assert(false, "Don't call"); } }; class CountHandleClosure: public OopClosure { @@ -239,9 +253,8 @@ unsigned int ReferenceProcessor::count_jni_refs() int _count; public: CountHandleClosure(): _count(0) {} - void do_oop(oop* unused) { - _count++; - } + void do_oop(oop* unused) { _count++; } + void do_oop(narrowOop* unused) { ShouldNotReachHere(); } int count() { return _count; } }; CountHandleClosure global_handle_count; @@ -262,36 +275,48 @@ void ReferenceProcessor::process_phaseJNI(BoolObjectClosure* is_alive, #endif JNIHandles::weak_oops_do(is_alive, keep_alive); // Finally remember to keep sentinel around - keep_alive->do_oop(&_sentinelRef); + keep_alive->do_oop(adr_sentinel_ref()); complete_gc->do_void(); } -bool ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor) { - NOT_PRODUCT(verify_ok_to_handle_reflists()); + +template +static bool enqueue_discovered_ref_helper(ReferenceProcessor* ref, + AbstractRefProcTaskExecutor* task_executor) { + // Remember old value of pending references list - oop* pending_list_addr = java_lang_ref_Reference::pending_list_addr(); - oop old_pending_list_value = *pending_list_addr; + T* pending_list_addr = (T*)java_lang_ref_Reference::pending_list_addr(); + T old_pending_list_value = *pending_list_addr; // Enqueue references that are not made active again, and // clear the decks for the next collection (cycle). - enqueue_discovered_reflists(pending_list_addr, task_executor); + ref->enqueue_discovered_reflists((HeapWord*)pending_list_addr, task_executor); // Do the oop-check on pending_list_addr missed in // enqueue_discovered_reflist. We should probably // do a raw oop_check so that future such idempotent // oop_stores relying on the oop-check side-effect // may be elided automatically and safely without // affecting correctness. - oop_store(pending_list_addr, *(pending_list_addr)); + oop_store(pending_list_addr, oopDesc::load_decode_heap_oop(pending_list_addr)); // Stop treating discovered references specially. - disable_discovery(); + ref->disable_discovery(); // Return true if new pending references were added return old_pending_list_value != *pending_list_addr; } +bool ReferenceProcessor::enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor) { + NOT_PRODUCT(verify_ok_to_handle_reflists()); + if (UseCompressedOops) { + return enqueue_discovered_ref_helper(this, task_executor); + } else { + return enqueue_discovered_ref_helper(this, task_executor); + } +} + void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list, - oop* pending_list_addr) { + HeapWord* pending_list_addr) { // Given a list of refs linked through the "discovered" field // (java.lang.ref.Reference.discovered) chain them through the // "next" field (java.lang.ref.Reference.next) and prepend @@ -305,19 +330,19 @@ void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list, // the next field and clearing it (except for the last // non-sentinel object which is treated specially to avoid // confusion with an active reference). - while (obj != _sentinelRef) { + while (obj != sentinel_ref()) { assert(obj->is_instanceRef(), "should be reference object"); oop next = java_lang_ref_Reference::discovered(obj); if (TraceReferenceGC && PrintGCDetails) { - gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next " INTPTR_FORMAT, - (oopDesc*) obj, (oopDesc*) next); + gclog_or_tty->print_cr(" obj " INTPTR_FORMAT "/next " INTPTR_FORMAT, + obj, next); } - assert(*java_lang_ref_Reference::next_addr(obj) == NULL, - "The reference should not be enqueued"); - if (next == _sentinelRef) { // obj is last + assert(java_lang_ref_Reference::next(obj) == NULL, + "The reference should not be enqueued"); + if (next == sentinel_ref()) { // obj is last // Swap refs_list into pendling_list_addr and // set obj's next to what we read from pending_list_addr. - oop old = (oop)Atomic::xchg_ptr(refs_list.head(), pending_list_addr); + oop old = oopDesc::atomic_exchange_oop(refs_list.head(), pending_list_addr); // Need oop_check on pending_list_addr above; // see special oop-check code at the end of // enqueue_discovered_reflists() further below. @@ -341,15 +366,14 @@ class RefProcEnqueueTask: public AbstractRefProcTaskExecutor::EnqueueTask { public: RefProcEnqueueTask(ReferenceProcessor& ref_processor, DiscoveredList discovered_refs[], - oop* pending_list_addr, + HeapWord* pending_list_addr, oop sentinel_ref, int n_queues) : EnqueueTask(ref_processor, discovered_refs, pending_list_addr, sentinel_ref, n_queues) { } - virtual void work(unsigned int work_id) - { + virtual void work(unsigned int work_id) { assert(work_id < (unsigned int)_ref_processor.num_q(), "Index out-of-bounds"); // Simplest first cut: static partitioning. int index = work_id; @@ -363,18 +387,18 @@ public: }; // Enqueue references that are not made active again -void ReferenceProcessor::enqueue_discovered_reflists(oop* pending_list_addr, +void ReferenceProcessor::enqueue_discovered_reflists(HeapWord* pending_list_addr, AbstractRefProcTaskExecutor* task_executor) { if (_processing_is_mt && task_executor != NULL) { // Parallel code RefProcEnqueueTask tsk(*this, _discoveredSoftRefs, - pending_list_addr, _sentinelRef, _num_q); + pending_list_addr, sentinel_ref(), _num_q); task_executor->execute(tsk); } else { // Serial code: call the parent class's implementation for (int i = 0; i < _num_q * subclasses_of_ref; i++) { enqueue_discovered_reflist(_discoveredSoftRefs[i], pending_list_addr); - _discoveredSoftRefs[i].set_head(_sentinelRef); + _discoveredSoftRefs[i].set_head(sentinel_ref()); _discoveredSoftRefs[i].set_length(0); } } @@ -388,14 +412,13 @@ public: BoolObjectClosure* is_alive); // End Of List. - inline bool has_next() const - { return _next != ReferenceProcessor::_sentinelRef; } + inline bool has_next() const { return _next != ReferenceProcessor::sentinel_ref(); } // Get oop to the Reference object. - inline oop obj() const { return _ref; } + inline oop obj() const { return _ref; } // Get oop to the referent object. - inline oop referent() const { return _referent; } + inline oop referent() const { return _referent; } // Returns true if referent is alive. inline bool is_referent_alive() const; @@ -417,13 +440,26 @@ public: inline void make_active() { java_lang_ref_Reference::set_next(_ref, NULL); } // Make the referent alive. - inline void make_referent_alive() { _keep_alive->do_oop(_referent_addr); } + inline void make_referent_alive() { + if (UseCompressedOops) { + _keep_alive->do_oop((narrowOop*)_referent_addr); + } else { + _keep_alive->do_oop((oop*)_referent_addr); + } + } // Update the discovered field. - inline void update_discovered() { _keep_alive->do_oop(_prev_next); } + inline void update_discovered() { + // First _prev_next ref actually points into DiscoveredList (gross). + if (UseCompressedOops) { + _keep_alive->do_oop((narrowOop*)_prev_next); + } else { + _keep_alive->do_oop((oop*)_prev_next); + } + } // NULL out referent pointer. - inline void clear_referent() { *_referent_addr = NULL; } + inline void clear_referent() { oop_store_raw(_referent_addr, NULL); } // Statistics NOT_PRODUCT( @@ -436,11 +472,11 @@ private: private: DiscoveredList& _refs_list; - oop* _prev_next; + HeapWord* _prev_next; oop _ref; - oop* _discovered_addr; + HeapWord* _discovered_addr; oop _next; - oop* _referent_addr; + HeapWord* _referent_addr; oop _referent; OopClosure* _keep_alive; BoolObjectClosure* _is_alive; @@ -457,7 +493,7 @@ inline DiscoveredListIterator::DiscoveredListIterator(DiscoveredList& refs_li OopClosure* keep_alive, BoolObjectClosure* is_alive) : _refs_list(refs_list), - _prev_next(refs_list.head_ptr()), + _prev_next(refs_list.adr_head()), _ref(refs_list.head()), #ifdef ASSERT _first_seen(refs_list.head()), @@ -471,19 +507,18 @@ inline DiscoveredListIterator::DiscoveredListIterator(DiscoveredList& refs_li _is_alive(is_alive) { } -inline bool DiscoveredListIterator::is_referent_alive() const -{ +inline bool DiscoveredListIterator::is_referent_alive() const { return _is_alive->do_object_b(_referent); } -inline void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) -{ +inline void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referent)) { _discovered_addr = java_lang_ref_Reference::discovered_addr(_ref); - assert(_discovered_addr && (*_discovered_addr)->is_oop_or_null(), + oop discovered = java_lang_ref_Reference::discovered(_ref); + assert(_discovered_addr && discovered->is_oop_or_null(), "discovered field is bad"); - _next = *_discovered_addr; + _next = discovered; _referent_addr = java_lang_ref_Reference::referent_addr(_ref); - _referent = *_referent_addr; + _referent = java_lang_ref_Reference::referent(_ref); assert(Universe::heap()->is_in_reserved_or_null(_referent), "Wrong oop found in java.lang.Reference object"); assert(allow_null_referent ? @@ -492,32 +527,32 @@ inline void DiscoveredListIterator::load_ptrs(DEBUG_ONLY(bool allow_null_referen "bad referent"); } -inline void DiscoveredListIterator::next() -{ +inline void DiscoveredListIterator::next() { _prev_next = _discovered_addr; move_to_next(); } -inline void DiscoveredListIterator::remove() -{ +inline void DiscoveredListIterator::remove() { assert(_ref->is_oop(), "Dropping a bad reference"); - // Clear the discovered_addr field so that the object does - // not look like it has been discovered. - *_discovered_addr = NULL; - // Remove Reference object from list. - *_prev_next = _next; + oop_store_raw(_discovered_addr, NULL); + // First _prev_next ref actually points into DiscoveredList (gross). + if (UseCompressedOops) { + // Remove Reference object from list. + oopDesc::encode_store_heap_oop_not_null((narrowOop*)_prev_next, _next); + } else { + // Remove Reference object from list. + oopDesc::store_heap_oop((oop*)_prev_next, _next); + } NOT_PRODUCT(_removed++); move_to_next(); } -inline void DiscoveredListIterator::move_to_next() -{ +inline void DiscoveredListIterator::move_to_next() { _ref = _next; assert(_ref != _first_seen, "cyclic ref_list found"); NOT_PRODUCT(_processed++); } - // NOTE: process_phase*() are largely similar, and at a high level // merely iterate over the extant list applying a predicate to // each of its elements and possibly removing that element from the @@ -531,13 +566,13 @@ inline void DiscoveredListIterator::move_to_next() // referents are not alive, but that should be kept alive for policy reasons. // Keep alive the transitive closure of all such referents. void -ReferenceProcessor::process_phase1(DiscoveredList& refs_list_addr, +ReferenceProcessor::process_phase1(DiscoveredList& refs_list, ReferencePolicy* policy, BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc) { assert(policy != NULL, "Must have a non-NULL policy"); - DiscoveredListIterator iter(refs_list_addr, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive); // Decide which softly reachable refs should be kept alive. while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(!discovery_is_atomic() /* allow_null_referent */)); @@ -545,7 +580,7 @@ ReferenceProcessor::process_phase1(DiscoveredList& refs_list_addr, if (referent_is_dead && !policy->should_clear_reference(iter.obj())) { if (TraceReferenceGC) { gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy", - (address)iter.obj(), iter.obj()->blueprint()->internal_name()); + iter.obj(), iter.obj()->blueprint()->internal_name()); } // Make the Reference object active again iter.make_active(); @@ -570,20 +605,19 @@ ReferenceProcessor::process_phase1(DiscoveredList& refs_list_addr, // Traverse the list and remove any Refs that are not active, or // whose referents are either alive or NULL. void -ReferenceProcessor::pp2_work(DiscoveredList& refs_list_addr, +ReferenceProcessor::pp2_work(DiscoveredList& refs_list, BoolObjectClosure* is_alive, - OopClosure* keep_alive) -{ + OopClosure* keep_alive) { assert(discovery_is_atomic(), "Error"); - DiscoveredListIterator iter(refs_list_addr, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */)); - DEBUG_ONLY(oop* next_addr = java_lang_ref_Reference::next_addr(iter.obj());) - assert(*next_addr == NULL, "Should not discover inactive Reference"); + DEBUG_ONLY(oop next = java_lang_ref_Reference::next(iter.obj());) + assert(next == NULL, "Should not discover inactive Reference"); if (iter.is_referent_alive()) { if (TraceReferenceGC) { gclog_or_tty->print_cr("Dropping strongly reachable reference (" INTPTR_FORMAT ": %s)", - (address)iter.obj(), iter.obj()->blueprint()->internal_name()); + iter.obj(), iter.obj()->blueprint()->internal_name()); } // The referent is reachable after all. // Update the referent pointer as necessary: Note that this @@ -605,25 +639,28 @@ ReferenceProcessor::pp2_work(DiscoveredList& refs_list_addr, } void -ReferenceProcessor::pp2_work_concurrent_discovery( - DiscoveredList& refs_list_addr, - BoolObjectClosure* is_alive, - OopClosure* keep_alive, - VoidClosure* complete_gc) -{ +ReferenceProcessor::pp2_work_concurrent_discovery(DiscoveredList& refs_list, + BoolObjectClosure* is_alive, + OopClosure* keep_alive, + VoidClosure* complete_gc) { assert(!discovery_is_atomic(), "Error"); - DiscoveredListIterator iter(refs_list_addr, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); - oop* next_addr = java_lang_ref_Reference::next_addr(iter.obj()); + HeapWord* next_addr = java_lang_ref_Reference::next_addr(iter.obj()); + oop next = java_lang_ref_Reference::next(iter.obj()); if ((iter.referent() == NULL || iter.is_referent_alive() || - *next_addr != NULL)) { - assert((*next_addr)->is_oop_or_null(), "bad next field"); + next != NULL)) { + assert(next->is_oop_or_null(), "bad next field"); // Remove Reference object from list iter.remove(); // Trace the cohorts iter.make_referent_alive(); - keep_alive->do_oop(next_addr); + if (UseCompressedOops) { + keep_alive->do_oop((narrowOop*)next_addr); + } else { + keep_alive->do_oop((oop*)next_addr); + } } else { iter.next(); } @@ -639,15 +676,15 @@ ReferenceProcessor::pp2_work_concurrent_discovery( } // Traverse the list and process the referents, by either -// either clearing them or keeping them (and their reachable +// clearing them or keeping them (and their reachable // closure) alive. void -ReferenceProcessor::process_phase3(DiscoveredList& refs_list_addr, +ReferenceProcessor::process_phase3(DiscoveredList& refs_list, bool clear_referent, BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc) { - DiscoveredListIterator iter(refs_list_addr, keep_alive, is_alive); + DiscoveredListIterator iter(refs_list, keep_alive, is_alive); while (iter.has_next()) { iter.update_discovered(); iter.load_ptrs(DEBUG_ONLY(false /* allow_null_referent */)); @@ -661,7 +698,7 @@ ReferenceProcessor::process_phase3(DiscoveredList& refs_list_addr, if (TraceReferenceGC) { gclog_or_tty->print_cr("Adding %sreference (" INTPTR_FORMAT ": %s) as pending", clear_referent ? "cleared " : "", - (address)iter.obj(), iter.obj()->blueprint()->internal_name()); + iter.obj(), iter.obj()->blueprint()->internal_name()); } assert(iter.obj()->is_oop(UseConcMarkSweepGC), "Adding a bad reference"); // If discovery is concurrent, we may have objects with null referents, @@ -679,15 +716,15 @@ ReferenceProcessor::process_phase3(DiscoveredList& refs_list_addr, } void -ReferenceProcessor::abandon_partial_discovered_list(DiscoveredList& ref_list) { - oop obj = ref_list.head(); - while (obj != _sentinelRef) { - oop* discovered_addr = java_lang_ref_Reference::discovered_addr(obj); - obj = *discovered_addr; - *discovered_addr = NULL; +ReferenceProcessor::abandon_partial_discovered_list(DiscoveredList& refs_list) { + oop obj = refs_list.head(); + while (obj != sentinel_ref()) { + oop discovered = java_lang_ref_Reference::discovered(obj); + java_lang_ref_Reference::set_discovered_raw(obj, NULL); + obj = discovered; } - ref_list.set_head(_sentinelRef); - ref_list.set_length(0); + refs_list.set_head(sentinel_ref()); + refs_list.set_length(0); } void @@ -777,7 +814,7 @@ void ReferenceProcessor::balance_queues(DiscoveredList ref_lists[]) // find an element to split the list on for (size_t j = 0; j < refs_to_move; ++j) { move_tail = new_head; - new_head = *java_lang_ref_Reference::discovered_addr(new_head); + new_head = java_lang_ref_Reference::discovered(new_head); } java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head()); ref_lists[to_idx].set_head(move_head); @@ -875,17 +912,17 @@ void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list) size_t length = refs_list.length(); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); - oop* next_addr = java_lang_ref_Reference::next_addr(iter.obj()); - assert((*next_addr)->is_oop_or_null(), "bad next field"); + oop next = java_lang_ref_Reference::next(iter.obj()); + assert(next->is_oop_or_null(), "bad next field"); // If referent has been cleared or Reference is not active, // drop it. - if (iter.referent() == NULL || *next_addr != NULL) { + if (iter.referent() == NULL || next != NULL) { debug_only( if (PrintGCDetails && TraceReferenceGC) { gclog_or_tty->print_cr("clean_up_discovered_list: Dropping Reference: " INTPTR_FORMAT " with next field: " INTPTR_FORMAT " and referent: " INTPTR_FORMAT, - (address)iter.obj(), (address)*next_addr, (address)iter.referent()); + iter.obj(), next, iter.referent()); } ) // Remove Reference object from list @@ -950,18 +987,21 @@ inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt) return list; } -inline void ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& list, - oop obj, oop* discovered_addr) { +inline void +ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& refs_list, + oop obj, + HeapWord* discovered_addr) { assert(_discovery_is_mt, "!_discovery_is_mt should have been handled by caller"); // First we must make sure this object is only enqueued once. CAS in a non null // discovered_addr. - oop retest = (oop)Atomic::cmpxchg_ptr(list.head(), discovered_addr, NULL); + oop retest = oopDesc::atomic_compare_exchange_oop(refs_list.head(), discovered_addr, + NULL); if (retest == NULL) { // This thread just won the right to enqueue the object. // We have separate lists for enqueueing so no synchronization // is necessary. - list.set_head(obj); - list.set_length(list.length() + 1); + refs_list.set_head(obj); + refs_list.set_length(refs_list.length() + 1); } else { // If retest was non NULL, another thread beat us to it: // The reference has already been discovered... @@ -972,7 +1012,6 @@ inline void ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& list, } } - // We mention two of several possible choices here: // #0: if the reference object is not in the "originating generation" // (or part of the heap being collected, indicated by our "span" @@ -1006,8 +1045,8 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { return false; } // We only enqueue active references. - oop* next_addr = java_lang_ref_Reference::next_addr(obj); - if (*next_addr != NULL) { + oop next = java_lang_ref_Reference::next(obj); + if (next != NULL) { return false; } @@ -1034,14 +1073,14 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { } } - oop* discovered_addr = java_lang_ref_Reference::discovered_addr(obj); - assert(discovered_addr != NULL && (*discovered_addr)->is_oop_or_null(), - "bad discovered field"); - if (*discovered_addr != NULL) { + HeapWord* discovered_addr = java_lang_ref_Reference::discovered_addr(obj); + oop discovered = java_lang_ref_Reference::discovered(obj); + assert(discovered->is_oop_or_null(), "bad discovered field"); + if (discovered != NULL) { // The reference has already been discovered... if (TraceReferenceGC) { gclog_or_tty->print_cr("Already enqueued reference (" INTPTR_FORMAT ": %s)", - (oopDesc*)obj, obj->blueprint()->internal_name()); + obj, obj->blueprint()->internal_name()); } if (RefDiscoveryPolicy == ReferentBasedDiscovery) { // assumes that an object is not processed twice; @@ -1088,7 +1127,7 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { if (_discovery_is_mt) { add_to_discovered_list_mt(*list, obj, discovered_addr); } else { - *discovered_addr = list->head(); + oop_store_raw(discovered_addr, list->head()); list->set_head(obj); list->set_length(list->length() + 1); } @@ -1106,7 +1145,7 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) { oop referent = java_lang_ref_Reference::referent(obj); if (PrintGCDetails) { gclog_or_tty->print_cr("Enqueued reference (" INTPTR_FORMAT ": %s)", - (oopDesc*) obj, obj->blueprint()->internal_name()); + obj, obj->blueprint()->internal_name()); } assert(referent->is_oop(), "Enqueued a bad referent"); } @@ -1181,17 +1220,20 @@ void ReferenceProcessor::preclean_discovered_references( // are not active (have a non-NULL next field). NOTE: For this to work // correctly, refs discovery can not be happening concurrently with this // step. -void ReferenceProcessor::preclean_discovered_reflist( - DiscoveredList& refs_list, BoolObjectClosure* is_alive, - OopClosure* keep_alive, VoidClosure* complete_gc, YieldClosure* yield) { - +void +ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list, + BoolObjectClosure* is_alive, + OopClosure* keep_alive, + VoidClosure* complete_gc, + YieldClosure* yield) { DiscoveredListIterator iter(refs_list, keep_alive, is_alive); size_t length = refs_list.length(); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); - oop* next_addr = java_lang_ref_Reference::next_addr(iter.obj()); + oop obj = iter.obj(); + oop next = java_lang_ref_Reference::next(obj); if (iter.referent() == NULL || iter.is_referent_alive() || - *next_addr != NULL) { + next != NULL) { // The referent has been cleared, or is alive, or the Reference is not // active; we need to trace and mark its cohort. if (TraceReferenceGC) { @@ -1203,7 +1245,13 @@ void ReferenceProcessor::preclean_discovered_reflist( --length; // Keep alive its cohort. iter.make_referent_alive(); - keep_alive->do_oop(next_addr); + if (UseCompressedOops) { + narrowOop* next_addr = (narrowOop*)java_lang_ref_Reference::next_addr(obj); + keep_alive->do_oop(next_addr); + } else { + oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj); + keep_alive->do_oop(next_addr); + } } else { iter.next(); } @@ -1241,7 +1289,7 @@ void ReferenceProcessor::verify_ok_to_handle_reflists() { #endif void ReferenceProcessor::verify() { - guarantee(_sentinelRef != NULL && _sentinelRef->is_oop(), "Lost _sentinelRef"); + guarantee(sentinel_ref() != NULL && sentinel_ref()->is_oop(), "Lost _sentinelRef"); } #ifndef PRODUCT @@ -1249,12 +1297,12 @@ void ReferenceProcessor::clear_discovered_references() { guarantee(!_discovering_refs, "Discovering refs?"); for (int i = 0; i < _num_q * subclasses_of_ref; i++) { oop obj = _discoveredSoftRefs[i].head(); - while (obj != _sentinelRef) { + while (obj != sentinel_ref()) { oop next = java_lang_ref_Reference::discovered(obj); java_lang_ref_Reference::set_discovered(obj, (oop) NULL); obj = next; } - _discoveredSoftRefs[i].set_head(_sentinelRef); + _discoveredSoftRefs[i].set_head(sentinel_ref()); _discoveredSoftRefs[i].set_length(0); } } diff --git a/hotspot/src/share/vm/memory/referenceProcessor.hpp b/hotspot/src/share/vm/memory/referenceProcessor.hpp index 29e2a7b7795..e11f9564509 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.hpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp @@ -45,8 +45,6 @@ class AbstractRefProcTaskExecutor; class DiscoveredList; class ReferenceProcessor : public CHeapObj { - friend class DiscoveredList; - friend class DiscoveredListIterator; protected: // End of list marker static oop _sentinelRef; @@ -70,16 +68,20 @@ class ReferenceProcessor : public CHeapObj { BoolObjectClosure* _is_alive_non_header; // The discovered ref lists themselves - int _num_q; // the MT'ness degree of the queues below - DiscoveredList* _discoveredSoftRefs; // pointer to array of oops + + // The MT'ness degree of the queues below + int _num_q; + // Arrays of lists of oops, one per thread + DiscoveredList* _discoveredSoftRefs; DiscoveredList* _discoveredWeakRefs; DiscoveredList* _discoveredFinalRefs; DiscoveredList* _discoveredPhantomRefs; public: - int num_q() { return _num_q; } + int num_q() { return _num_q; } DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; } - static oop* sentinel_ref() { return &_sentinelRef; } + static oop sentinel_ref() { return _sentinelRef; } + static oop* adr_sentinel_ref() { return &_sentinelRef; } public: // Process references with a certain reachability level. @@ -98,45 +100,45 @@ class ReferenceProcessor : public CHeapObj { // Work methods used by the method process_discovered_reflist // Phase1: keep alive all those referents that are otherwise // dead but which must be kept alive by policy (and their closure). - void process_phase1(DiscoveredList& refs_list_addr, + void process_phase1(DiscoveredList& refs_list, ReferencePolicy* policy, BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc); // Phase2: remove all those references whose referents are // reachable. - inline void process_phase2(DiscoveredList& refs_list_addr, + inline void process_phase2(DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc) { if (discovery_is_atomic()) { // complete_gc is ignored in this case for this phase - pp2_work(refs_list_addr, is_alive, keep_alive); + pp2_work(refs_list, is_alive, keep_alive); } else { assert(complete_gc != NULL, "Error"); - pp2_work_concurrent_discovery(refs_list_addr, is_alive, + pp2_work_concurrent_discovery(refs_list, is_alive, keep_alive, complete_gc); } } // Work methods in support of process_phase2 - void pp2_work(DiscoveredList& refs_list_addr, + void pp2_work(DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive); void pp2_work_concurrent_discovery( - DiscoveredList& refs_list_addr, + DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc); // Phase3: process the referents by either clearing them // or keeping them alive (and their closure) - void process_phase3(DiscoveredList& refs_list_addr, + void process_phase3(DiscoveredList& refs_list, bool clear_referent, BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc); // Enqueue references with a certain reachability level - void enqueue_discovered_reflist(DiscoveredList& refs_list, oop* pending_list_addr); + void enqueue_discovered_reflist(DiscoveredList& refs_list, HeapWord* pending_list_addr); // "Preclean" all the discovered reference lists // by removing references with strongly reachable referents. @@ -169,6 +171,8 @@ class ReferenceProcessor : public CHeapObj { // occupying the i / _num_q slot. const char* list_name(int i); + void enqueue_discovered_reflists(HeapWord* pending_list_addr, AbstractRefProcTaskExecutor* task_executor); + protected: // "Preclean" the given discovered reference list // by removing references with strongly reachable referents. @@ -179,7 +183,6 @@ class ReferenceProcessor : public CHeapObj { VoidClosure* complete_gc, YieldClosure* yield); - void enqueue_discovered_reflists(oop* pending_list_addr, AbstractRefProcTaskExecutor* task_executor); int next_id() { int id = _next_id; if (++_next_id == _num_q) { @@ -189,7 +192,7 @@ class ReferenceProcessor : public CHeapObj { } DiscoveredList* get_discovered_list(ReferenceType rt); inline void add_to_discovered_list_mt(DiscoveredList& refs_list, oop obj, - oop* discovered_addr); + HeapWord* discovered_addr); void verify_ok_to_handle_reflists() PRODUCT_RETURN; void abandon_partial_discovered_list(DiscoveredList& refs_list); @@ -477,7 +480,7 @@ class AbstractRefProcTaskExecutor::EnqueueTask { protected: EnqueueTask(ReferenceProcessor& ref_processor, DiscoveredList refs_lists[], - oop* pending_list_addr, + HeapWord* pending_list_addr, oop sentinel_ref, int n_queues) : _ref_processor(ref_processor), @@ -493,7 +496,7 @@ public: protected: ReferenceProcessor& _ref_processor; DiscoveredList* _refs_lists; - oop* _pending_list_addr; + HeapWord* _pending_list_addr; oop _sentinel_ref; int _n_queues; }; diff --git a/hotspot/src/share/vm/memory/restore.cpp b/hotspot/src/share/vm/memory/restore.cpp index a677a8517f1..0a84749bcfa 100644 --- a/hotspot/src/share/vm/memory/restore.cpp +++ b/hotspot/src/share/vm/memory/restore.cpp @@ -50,6 +50,8 @@ public: *p = obj; } + void do_oop(narrowOop* p) { ShouldNotReachHere(); } + void do_ptr(void** p) { assert(*p == NULL, "initializing previous initialized pointer."); void* obj = nextOop(); diff --git a/hotspot/src/share/vm/memory/serialize.cpp b/hotspot/src/share/vm/memory/serialize.cpp index ec4688d48ac..6f9ba38b1d6 100644 --- a/hotspot/src/share/vm/memory/serialize.cpp +++ b/hotspot/src/share/vm/memory/serialize.cpp @@ -41,17 +41,18 @@ void CompactingPermGenGen::serialize_oops(SerializeOopClosure* soc) { int tag = 0; soc->do_tag(--tag); + assert(!UseCompressedOops, "UseCompressedOops doesn't work with shared archive"); // Verify the sizes of various oops in the system. soc->do_tag(sizeof(oopDesc)); soc->do_tag(sizeof(instanceOopDesc)); soc->do_tag(sizeof(methodOopDesc)); soc->do_tag(sizeof(constMethodOopDesc)); soc->do_tag(sizeof(methodDataOopDesc)); - soc->do_tag(sizeof(arrayOopDesc)); + soc->do_tag(arrayOopDesc::base_offset_in_bytes(T_BYTE)); soc->do_tag(sizeof(constantPoolOopDesc)); soc->do_tag(sizeof(constantPoolCacheOopDesc)); - soc->do_tag(sizeof(objArrayOopDesc)); - soc->do_tag(sizeof(typeArrayOopDesc)); + soc->do_tag(objArrayOopDesc::base_offset_in_bytes(T_BYTE)); + soc->do_tag(typeArrayOopDesc::base_offset_in_bytes(T_BYTE)); soc->do_tag(sizeof(symbolOopDesc)); soc->do_tag(sizeof(klassOopDesc)); soc->do_tag(sizeof(markOopDesc)); diff --git a/hotspot/src/share/vm/memory/sharedHeap.cpp b/hotspot/src/share/vm/memory/sharedHeap.cpp index c37bbf8a242..015f9807a06 100644 --- a/hotspot/src/share/vm/memory/sharedHeap.cpp +++ b/hotspot/src/share/vm/memory/sharedHeap.cpp @@ -74,9 +74,10 @@ void SharedHeap::set_par_threads(int t) { class AssertIsPermClosure: public OopClosure { public: - void do_oop(oop* p) { + virtual void do_oop(oop* p) { assert((*p) == NULL || (*p)->is_perm(), "Referent should be perm."); } + virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } }; static AssertIsPermClosure assert_is_perm_closure; @@ -187,12 +188,13 @@ class SkipAdjustingSharedStrings: public OopClosure { public: SkipAdjustingSharedStrings(OopClosure* clo) : _clo(clo) {} - void do_oop(oop* p) { + virtual void do_oop(oop* p) { oop o = (*p); if (!o->is_shared_readwrite()) { _clo->do_oop(p); } } + virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } }; // Unmarked shared Strings in the StringTable (which got there due to diff --git a/hotspot/src/share/vm/memory/space.cpp b/hotspot/src/share/vm/memory/space.cpp index dd4392091f9..eeab52e60a0 100644 --- a/hotspot/src/share/vm/memory/space.cpp +++ b/hotspot/src/share/vm/memory/space.cpp @@ -25,6 +25,9 @@ # include "incls/_precompiled.incl" # include "incls/_space.cpp.incl" +void SpaceMemRegionOopsIterClosure::do_oop(oop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); } +void SpaceMemRegionOopsIterClosure::do_oop(narrowOop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); } + HeapWord* DirtyCardToOopClosure::get_actual_top(HeapWord* top, HeapWord* top_obj) { if (top_obj != NULL) { @@ -150,10 +153,6 @@ DirtyCardToOopClosure* Space::new_dcto_cl(OopClosure* cl, return new DirtyCardToOopClosure(this, cl, precision, boundary); } -void FilteringClosure::do_oop(oop* p) { - do_oop_nv(p); -} - HeapWord* ContiguousSpaceDCTOC::get_actual_top(HeapWord* top, HeapWord* top_obj) { if (top_obj != NULL && top_obj < (_sp->toContiguousSpace())->top()) { @@ -337,7 +336,7 @@ HeapWord* CompactibleSpace::forward(oop q, size_t size, assert(q->forwardee() == NULL, "should be forwarded to NULL"); } - debug_only(MarkSweep::register_live_oop(q, size)); + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::register_live_oop(q, size)); compact_top += size; // we need to update the offset table so that the beginnings of objects can be @@ -406,13 +405,13 @@ void Space::adjust_pointers() { if (oop(q)->is_gc_marked()) { // q is alive - debug_only(MarkSweep::track_interior_pointers(oop(q))); + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q))); // point all the oops to the new location size_t size = oop(q)->adjust_pointers(); - debug_only(MarkSweep::check_interior_pointers()); + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers()); debug_only(prev_q = q); - debug_only(MarkSweep::validate_live_oop(oop(q), size)); + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size)); q += size; } else { @@ -884,10 +883,13 @@ OffsetTableContigSpace::OffsetTableContigSpace(BlockOffsetSharedArray* sharedOff class VerifyOldOopClosure : public OopClosure { public: - oop the_obj; - bool allow_dirty; + oop _the_obj; + bool _allow_dirty; void do_oop(oop* p) { - the_obj->verify_old_oop(p, allow_dirty); + _the_obj->verify_old_oop(p, _allow_dirty); + } + void do_oop(narrowOop* p) { + _the_obj->verify_old_oop(p, _allow_dirty); } }; @@ -898,7 +900,7 @@ void OffsetTableContigSpace::verify(bool allow_dirty) const { HeapWord* p = bottom(); HeapWord* prev_p = NULL; VerifyOldOopClosure blk; // Does this do anything? - blk.allow_dirty = allow_dirty; + blk._allow_dirty = allow_dirty; int objs = 0; int blocks = 0; @@ -919,7 +921,7 @@ void OffsetTableContigSpace::verify(bool allow_dirty) const { if (objs == OBJ_SAMPLE_INTERVAL) { oop(p)->verify(); - blk.the_obj = oop(p); + blk._the_obj = oop(p); oop(p)->oop_iterate(&blk); objs = 0; } else { diff --git a/hotspot/src/share/vm/memory/space.hpp b/hotspot/src/share/vm/memory/space.hpp index e036004ce7b..37f726e5b3f 100644 --- a/hotspot/src/share/vm/memory/space.hpp +++ b/hotspot/src/share/vm/memory/space.hpp @@ -52,21 +52,24 @@ class GenRemSet; class CardTableRS; class DirtyCardToOopClosure; - // An oop closure that is circumscribed by a filtering memory region. -class SpaceMemRegionOopsIterClosure: public virtual OopClosure { - OopClosure* cl; - MemRegion mr; -public: - void do_oop(oop* p) { - if (mr.contains(p)) { - cl->do_oop(p); +class SpaceMemRegionOopsIterClosure: public OopClosure { + private: + OopClosure* _cl; + MemRegion _mr; + protected: + template void do_oop_work(T* p) { + if (_mr.contains(p)) { + _cl->do_oop(p); } } - SpaceMemRegionOopsIterClosure(OopClosure* _cl, MemRegion _mr): cl(_cl), mr(_mr) {} + public: + SpaceMemRegionOopsIterClosure(OopClosure* cl, MemRegion mr): + _cl(cl), _mr(mr) {} + virtual void do_oop(oop* p); + virtual void do_oop(narrowOop* p); }; - // A Space describes a heap area. Class Space is an abstract // base class. // @@ -279,7 +282,7 @@ protected: CardTableModRefBS::PrecisionStyle _precision; HeapWord* _boundary; // If non-NULL, process only non-NULL oops // pointing below boundary. - HeapWord* _min_done; // ObjHeadPreciseArray precision requires + HeapWord* _min_done; // ObjHeadPreciseArray precision requires // a downwards traversal; this is the // lowest location already done (or, // alternatively, the lowest address that @@ -508,7 +511,7 @@ protected: /* prefetch beyond q */ \ Prefetch::write(q, interval); \ /* size_t size = oop(q)->size(); changing this for cms for perm gen */\ - size_t size = block_size(q); \ + size_t size = block_size(q); \ compact_top = cp->space->forward(oop(q), size, cp, compact_top); \ q += size; \ end_of_live = q; \ @@ -572,147 +575,149 @@ protected: cp->space->set_compaction_top(compact_top); \ } -#define SCAN_AND_ADJUST_POINTERS(adjust_obj_size) { \ - /* adjust all the interior pointers to point at the new locations of objects \ - * Used by MarkSweep::mark_sweep_phase3() */ \ +#define SCAN_AND_ADJUST_POINTERS(adjust_obj_size) { \ + /* adjust all the interior pointers to point at the new locations of objects \ + * Used by MarkSweep::mark_sweep_phase3() */ \ \ - HeapWord* q = bottom(); \ - HeapWord* t = _end_of_live; /* Established by "prepare_for_compaction". */ \ + HeapWord* q = bottom(); \ + HeapWord* t = _end_of_live; /* Established by "prepare_for_compaction". */ \ \ - assert(_first_dead <= _end_of_live, "Stands to reason, no?"); \ + assert(_first_dead <= _end_of_live, "Stands to reason, no?"); \ \ - if (q < t && _first_dead > q && \ + if (q < t && _first_dead > q && \ !oop(q)->is_gc_marked()) { \ /* we have a chunk of the space which hasn't moved and we've \ * reinitialized the mark word during the previous pass, so we can't \ - * use is_gc_marked for the traversal. */ \ + * use is_gc_marked for the traversal. */ \ HeapWord* end = _first_dead; \ \ - while (q < end) { \ - /* I originally tried to conjoin "block_start(q) == q" to the \ - * assertion below, but that doesn't work, because you can't \ - * accurately traverse previous objects to get to the current one \ - * after their pointers (including pointers into permGen) have been \ - * updated, until the actual compaction is done. dld, 4/00 */ \ - assert(block_is_obj(q), \ - "should be at block boundaries, and should be looking at objs"); \ + while (q < end) { \ + /* I originally tried to conjoin "block_start(q) == q" to the \ + * assertion below, but that doesn't work, because you can't \ + * accurately traverse previous objects to get to the current one \ + * after their pointers (including pointers into permGen) have been \ + * updated, until the actual compaction is done. dld, 4/00 */ \ + assert(block_is_obj(q), \ + "should be at block boundaries, and should be looking at objs"); \ \ - debug_only(MarkSweep::track_interior_pointers(oop(q))); \ + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q))); \ \ - /* point all the oops to the new location */ \ - size_t size = oop(q)->adjust_pointers(); \ - size = adjust_obj_size(size); \ - \ - debug_only(MarkSweep::check_interior_pointers()); \ - \ - debug_only(MarkSweep::validate_live_oop(oop(q), size)); \ + /* point all the oops to the new location */ \ + size_t size = oop(q)->adjust_pointers(); \ + size = adjust_obj_size(size); \ \ + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers()); \ + \ + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size)); \ + \ q += size; \ - } \ + } \ \ - if (_first_dead == t) { \ - q = t; \ - } else { \ - /* $$$ This is funky. Using this to read the previously written \ - * LiveRange. See also use below. */ \ + if (_first_dead == t) { \ + q = t; \ + } else { \ + /* $$$ This is funky. Using this to read the previously written \ + * LiveRange. See also use below. */ \ q = (HeapWord*)oop(_first_dead)->mark()->decode_pointer(); \ - } \ - } \ + } \ + } \ \ const intx interval = PrefetchScanIntervalInBytes; \ \ - debug_only(HeapWord* prev_q = NULL); \ - while (q < t) { \ - /* prefetch beyond q */ \ + debug_only(HeapWord* prev_q = NULL); \ + while (q < t) { \ + /* prefetch beyond q */ \ Prefetch::write(q, interval); \ - if (oop(q)->is_gc_marked()) { \ - /* q is alive */ \ - debug_only(MarkSweep::track_interior_pointers(oop(q))); \ - /* point all the oops to the new location */ \ - size_t size = oop(q)->adjust_pointers(); \ - size = adjust_obj_size(size); \ - debug_only(MarkSweep::check_interior_pointers()); \ - debug_only(MarkSweep::validate_live_oop(oop(q), size)); \ - debug_only(prev_q = q); \ + if (oop(q)->is_gc_marked()) { \ + /* q is alive */ \ + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::track_interior_pointers(oop(q))); \ + /* point all the oops to the new location */ \ + size_t size = oop(q)->adjust_pointers(); \ + size = adjust_obj_size(size); \ + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::check_interior_pointers()); \ + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::validate_live_oop(oop(q), size)); \ + debug_only(prev_q = q); \ q += size; \ - } else { \ - /* q is not a live object, so its mark should point at the next \ - * live object */ \ - debug_only(prev_q = q); \ - q = (HeapWord*) oop(q)->mark()->decode_pointer(); \ - assert(q > prev_q, "we should be moving forward through memory"); \ - } \ - } \ + } else { \ + /* q is not a live object, so its mark should point at the next \ + * live object */ \ + debug_only(prev_q = q); \ + q = (HeapWord*) oop(q)->mark()->decode_pointer(); \ + assert(q > prev_q, "we should be moving forward through memory"); \ + } \ + } \ \ - assert(q == t, "just checking"); \ + assert(q == t, "just checking"); \ } -#define SCAN_AND_COMPACT(obj_size) { \ +#define SCAN_AND_COMPACT(obj_size) { \ /* Copy all live objects to their new location \ - * Used by MarkSweep::mark_sweep_phase4() */ \ + * Used by MarkSweep::mark_sweep_phase4() */ \ \ - HeapWord* q = bottom(); \ - HeapWord* const t = _end_of_live; \ - debug_only(HeapWord* prev_q = NULL); \ + HeapWord* q = bottom(); \ + HeapWord* const t = _end_of_live; \ + debug_only(HeapWord* prev_q = NULL); \ \ - if (q < t && _first_dead > q && \ + if (q < t && _first_dead > q && \ !oop(q)->is_gc_marked()) { \ - debug_only( \ - /* we have a chunk of the space which hasn't moved and we've reinitialized the \ - * mark word during the previous pass, so we can't use is_gc_marked for the \ - * traversal. */ \ - HeapWord* const end = _first_dead; \ - \ - while (q < end) { \ + debug_only( \ + /* we have a chunk of the space which hasn't moved and we've reinitialized \ + * the mark word during the previous pass, so we can't use is_gc_marked for \ + * the traversal. */ \ + HeapWord* const end = _first_dead; \ + \ + while (q < end) { \ size_t size = obj_size(q); \ - assert(!oop(q)->is_gc_marked(), "should be unmarked (special dense prefix handling)"); \ - debug_only(MarkSweep::live_oop_moved_to(q, size, q)); \ - debug_only(prev_q = q); \ + assert(!oop(q)->is_gc_marked(), \ + "should be unmarked (special dense prefix handling)"); \ + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::live_oop_moved_to(q, size, q)); \ + debug_only(prev_q = q); \ q += size; \ - } \ - ) /* debug_only */ \ + } \ + ) /* debug_only */ \ + \ + if (_first_dead == t) { \ + q = t; \ + } else { \ + /* $$$ Funky */ \ + q = (HeapWord*) oop(_first_dead)->mark()->decode_pointer(); \ + } \ + } \ \ - if (_first_dead == t) { \ - q = t; \ - } else { \ - /* $$$ Funky */ \ - q = (HeapWord*) oop(_first_dead)->mark()->decode_pointer(); \ - } \ - } \ - \ - const intx scan_interval = PrefetchScanIntervalInBytes; \ - const intx copy_interval = PrefetchCopyIntervalInBytes; \ - while (q < t) { \ - if (!oop(q)->is_gc_marked()) { \ - /* mark is pointer to next marked oop */ \ - debug_only(prev_q = q); \ - q = (HeapWord*) oop(q)->mark()->decode_pointer(); \ - assert(q > prev_q, "we should be moving forward through memory"); \ - } else { \ - /* prefetch beyond q */ \ + const intx scan_interval = PrefetchScanIntervalInBytes; \ + const intx copy_interval = PrefetchCopyIntervalInBytes; \ + while (q < t) { \ + if (!oop(q)->is_gc_marked()) { \ + /* mark is pointer to next marked oop */ \ + debug_only(prev_q = q); \ + q = (HeapWord*) oop(q)->mark()->decode_pointer(); \ + assert(q > prev_q, "we should be moving forward through memory"); \ + } else { \ + /* prefetch beyond q */ \ Prefetch::read(q, scan_interval); \ \ /* size and destination */ \ size_t size = obj_size(q); \ HeapWord* compaction_top = (HeapWord*)oop(q)->forwardee(); \ \ - /* prefetch beyond compaction_top */ \ + /* prefetch beyond compaction_top */ \ Prefetch::write(compaction_top, copy_interval); \ \ - /* copy object and reinit its mark */ \ - debug_only(MarkSweep::live_oop_moved_to(q, size, compaction_top)); \ - assert(q != compaction_top, "everything in this pass should be moving"); \ - Copy::aligned_conjoint_words(q, compaction_top, size); \ - oop(compaction_top)->init_mark(); \ - assert(oop(compaction_top)->klass() != NULL, "should have a class"); \ + /* copy object and reinit its mark */ \ + VALIDATE_MARK_SWEEP_ONLY(MarkSweep::live_oop_moved_to(q, size, \ + compaction_top)); \ + assert(q != compaction_top, "everything in this pass should be moving"); \ + Copy::aligned_conjoint_words(q, compaction_top, size); \ + oop(compaction_top)->init_mark(); \ + assert(oop(compaction_top)->klass() != NULL, "should have a class"); \ \ - debug_only(prev_q = q); \ + debug_only(prev_q = q); \ q += size; \ - } \ - } \ + } \ + } \ \ /* Reset space after compaction is complete */ \ - reset_after_compaction(); \ + reset_after_compaction(); \ /* We do this clear, below, since it has overloaded meanings for some */ \ /* space subtypes. For example, OffsetTableContigSpace's that were */ \ /* compacted into will have had their offset table thresholds updated */ \ diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index bbc3ee4aa15..d69016370ad 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -99,6 +99,7 @@ size_t Universe::_heap_capacity_at_last_gc; size_t Universe::_heap_used_at_last_gc; CollectedHeap* Universe::_collectedHeap = NULL; +address Universe::_heap_base = NULL; void Universe::basic_type_classes_do(void f(klassOop)) { @@ -464,7 +465,7 @@ void Universe::init_self_patching_vtbl_list(void** list, int count) { class FixupMirrorClosure: public ObjectClosure { public: - void do_object(oop obj) { + virtual void do_object(oop obj) { if (obj->is_klass()) { EXCEPTION_MARK; KlassHandle k(THREAD, klassOop(obj)); @@ -667,7 +668,7 @@ jint universe_init() { "LogHeapWordSize is incorrect."); guarantee(sizeof(oop) >= sizeof(HeapWord), "HeapWord larger than oop?"); guarantee(sizeof(oop) % sizeof(HeapWord) == 0, - "oop size is not not a multiple of HeapWord size"); + "oop size is not not a multiple of HeapWord size"); TraceTime timer("Genesis", TraceStartupTime); GC_locker::lock(); // do not allow gc during bootstrapping JavaClasses::compute_hard_coded_offsets(); @@ -759,6 +760,15 @@ jint Universe::initialize_heap() { if (status != JNI_OK) { return status; } + if (UseCompressedOops) { + // Subtract a page because something can get allocated at heap base. + // This also makes implicit null checking work, because the + // memory+1 page below heap_base needs to cause a signal. + // See needs_explicit_null_check. + // Only set the heap base for compressed oops because it indicates + // compressed oops for pstack code. + Universe::_heap_base = Universe::heap()->base() - os::vm_page_size(); + } // We will never reach the CATCH below since Exceptions::_throw will cause // the VM to exit if an exception is thrown during initialization diff --git a/hotspot/src/share/vm/memory/universe.hpp b/hotspot/src/share/vm/memory/universe.hpp index 6fd557585fa..7cf8da13b72 100644 --- a/hotspot/src/share/vm/memory/universe.hpp +++ b/hotspot/src/share/vm/memory/universe.hpp @@ -180,10 +180,13 @@ class Universe: AllStatic { // The particular choice of collected heap. static CollectedHeap* _collectedHeap; + // Base address for oop-within-java-object materialization. + // NULL if using wide oops. Doubles as heap oop null value. + static address _heap_base; // array of dummy objects used with +FullGCAlot debug_only(static objArrayOop _fullgc_alot_dummy_array;) - // index of next entry to clear + // index of next entry to clear debug_only(static int _fullgc_alot_dummy_next;) // Compiler/dispatch support @@ -323,6 +326,10 @@ class Universe: AllStatic { // The particular choice of collected heap. static CollectedHeap* heap() { return _collectedHeap; } + // For UseCompressedOops + static address heap_base() { return _heap_base; } + static address* heap_base_addr() { return &_heap_base; } + // Historic gc information static size_t get_heap_capacity_at_last_gc() { return _heap_capacity_at_last_gc; } static size_t get_heap_free_at_last_gc() { return _heap_capacity_at_last_gc - _heap_used_at_last_gc; } diff --git a/hotspot/src/share/vm/oops/arrayOop.hpp b/hotspot/src/share/vm/oops/arrayOop.hpp index 49fc566a90e..5e54a86ee93 100644 --- a/hotspot/src/share/vm/oops/arrayOop.hpp +++ b/hotspot/src/share/vm/oops/arrayOop.hpp @@ -22,34 +22,79 @@ * */ -// arrayOopDesc is the abstract baseclass for all arrays. +// arrayOopDesc is the abstract baseclass for all arrays. It doesn't +// declare pure virtual to enforce this because that would allocate a vtbl +// in each instance, which we don't want. + +// The layout of array Oops is: +// +// markOop +// klassOop // 32 bits if compressed but declared 64 in LP64. +// length // shares klass memory or allocated after declared fields. + class arrayOopDesc : public oopDesc { friend class VMStructs; - private: - int _length; // number of elements in the array + + // Interpreter/Compiler offsets + + // Header size computation. + // The header is considered the oop part of this type plus the length. + // Returns the aligned header_size_in_bytes. This is not equivalent to + // sizeof(arrayOopDesc) which should not appear in the code, except here. + static int header_size_in_bytes() { + size_t hs = UseCompressedOops ? + sizeof(arrayOopDesc) : + align_size_up(sizeof(arrayOopDesc) + sizeof(int), HeapWordSize); +#ifdef ASSERT + // make sure it isn't called before UseCompressedOops is initialized. + static size_t arrayoopdesc_hs = 0; + if (arrayoopdesc_hs == 0) arrayoopdesc_hs = hs; + assert(arrayoopdesc_hs == hs, "header size can't change"); +#endif // ASSERT + return (int)hs; + } public: - // Interpreter/Compiler offsets - static int length_offset_in_bytes() { return offset_of(arrayOopDesc, _length); } - static int base_offset_in_bytes(BasicType type) { return header_size(type) * HeapWordSize; } + // The _length field is not declared in C++. It is allocated after the + // declared nonstatic fields in arrayOopDesc if not compressed, otherwise + // it occupies the second half of the _klass field in oopDesc. + static int length_offset_in_bytes() { + return UseCompressedOops ? klass_gap_offset_in_bytes() : + sizeof(arrayOopDesc); + } + + // Returns the offset of the first element. + static int base_offset_in_bytes(BasicType type) { + return header_size(type) * HeapWordSize; + } // Returns the address of the first element. - void* base(BasicType type) const { return (void*) (((intptr_t) this) + base_offset_in_bytes(type)); } + void* base(BasicType type) const { + return (void*) (((intptr_t) this) + base_offset_in_bytes(type)); + } // Tells whether index is within bounds. bool is_within_bounds(int index) const { return 0 <= index && index < length(); } - // Accessores for instance variable - int length() const { return _length; } - void set_length(int length) { _length = length; } + // Accessors for instance variable which is not a C++ declared nonstatic + // field. + int length() const { + return *(int*)(((intptr_t)this) + length_offset_in_bytes()); + } + void set_length(int length) { + *(int*)(((intptr_t)this) + length_offset_in_bytes()) = length; + } - // Header size computation. - // Should only be called with constants as argument (will not constant fold otherwise) + // Should only be called with constants as argument + // (will not constant fold otherwise) + // Returns the header size in words aligned to the requirements of the + // array object type. static int header_size(BasicType type) { - return Universe::element_type_should_be_aligned(type) - ? align_object_size(sizeof(arrayOopDesc)/HeapWordSize) - : sizeof(arrayOopDesc)/HeapWordSize; + size_t typesize_in_bytes = header_size_in_bytes(); + return (int)(Universe::element_type_should_be_aligned(type) + ? align_object_size(typesize_in_bytes/HeapWordSize) + : typesize_in_bytes/HeapWordSize); } // This method returns the maximum length that can passed into @@ -62,7 +107,7 @@ class arrayOopDesc : public oopDesc { // We use max_jint, since object_size is internally represented by an 'int' // This gives us an upper bound of max_jint words for the size of the oop. int32_t max_words = (max_jint - header_size(type) - 2); - int elembytes = (type == T_OBJECT) ? T_OBJECT_aelem_bytes : type2aelembytes(type); + int elembytes = type2aelembytes(type); jlong len = ((jlong)max_words * HeapWordSize) / elembytes; return (len > max_jint) ? max_jint : (int32_t)len; } diff --git a/hotspot/src/share/vm/oops/constantPoolKlass.cpp b/hotspot/src/share/vm/oops/constantPoolKlass.cpp index b976187397c..229007f6208 100644 --- a/hotspot/src/share/vm/oops/constantPoolKlass.cpp +++ b/hotspot/src/share/vm/oops/constantPoolKlass.cpp @@ -29,8 +29,9 @@ constantPoolOop constantPoolKlass::allocate(int length, TRAPS) { int size = constantPoolOopDesc::object_size(length); KlassHandle klass (THREAD, as_klassOop()); constantPoolOop c = - (constantPoolOop)CollectedHeap::permanent_array_allocate(klass, size, length, CHECK_NULL); + (constantPoolOop)CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL); + c->set_length(length); c->set_tags(NULL); c->set_cache(NULL); c->set_pool_holder(NULL); @@ -54,14 +55,14 @@ constantPoolOop constantPoolKlass::allocate(int length, TRAPS) { klassOop constantPoolKlass::create_klass(TRAPS) { constantPoolKlass o; - KlassHandle klassklass(THREAD, Universe::arrayKlassKlassObj()); - arrayKlassHandle k = base_create_array_klass(o.vtbl_value(), header_size(), klassklass, CHECK_NULL); - arrayKlassHandle super (THREAD, k->super()); - complete_create_array_klass(k, super, CHECK_NULL); + KlassHandle h_this_klass(THREAD, Universe::klassKlassObj()); + KlassHandle k = base_create_klass(h_this_klass, header_size(), o.vtbl_value(), CHECK_NULL); + // Make sure size calculation is right + assert(k()->size() == align_object_size(header_size()), "wrong size for object"); + java_lang_Class::create_mirror(k, CHECK_NULL); // Allocate mirror return k(); } - int constantPoolKlass::oop_size(oop obj) const { assert(obj->is_constantPool(), "must be constantPool"); return constantPoolOop(obj)->object_size(); @@ -275,7 +276,7 @@ void constantPoolKlass::oop_print_on(oop obj, outputStream* st) { EXCEPTION_MARK; oop anObj; assert(obj->is_constantPool(), "must be constantPool"); - arrayKlass::oop_print_on(obj, st); + Klass::oop_print_on(obj, st); constantPoolOop cp = constantPoolOop(obj); // Temp. remove cache so we can do lookups with original indicies. diff --git a/hotspot/src/share/vm/oops/constantPoolKlass.hpp b/hotspot/src/share/vm/oops/constantPoolKlass.hpp index ac01a7b715d..b563f7ddd4a 100644 --- a/hotspot/src/share/vm/oops/constantPoolKlass.hpp +++ b/hotspot/src/share/vm/oops/constantPoolKlass.hpp @@ -24,7 +24,8 @@ // A constantPoolKlass is the klass of a constantPoolOop -class constantPoolKlass : public arrayKlass { +class constantPoolKlass : public Klass { + juint _alloc_size; // allocation profiling support public: // Dispatched klass operations bool oop_is_constantPool() const { return true; } @@ -44,7 +45,7 @@ class constantPoolKlass : public arrayKlass { // Sizing static int header_size() { return oopDesc::header_size() + sizeof(constantPoolKlass)/HeapWordSize; } - int object_size() const { return arrayKlass::object_size(header_size()); } + int object_size() const { return align_object_size(header_size()); } // Garbage collection void oop_follow_contents(oop obj); @@ -57,6 +58,11 @@ class constantPoolKlass : public arrayKlass { int oop_oop_iterate(oop obj, OopClosure* blk); int oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr); + // Allocation profiling support + // no idea why this is pure virtual and not in Klass ??? + juint alloc_size() const { return _alloc_size; } + void set_alloc_size(juint n) { _alloc_size = n; } + #ifndef PRODUCT public: // Printing diff --git a/hotspot/src/share/vm/oops/constantPoolOop.hpp b/hotspot/src/share/vm/oops/constantPoolOop.hpp index 3083a3240c6..b10db6bb068 100644 --- a/hotspot/src/share/vm/oops/constantPoolOop.hpp +++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp @@ -34,13 +34,14 @@ class SymbolHashMap; -class constantPoolOopDesc : public arrayOopDesc { +class constantPoolOopDesc : public oopDesc { friend class VMStructs; friend class BytecodeInterpreter; // Directly extracts an oop in the pool for fast instanceof/checkcast private: typeArrayOop _tags; // the tag array describing the constant pool's contents constantPoolCacheOop _cache; // the cache holding interpreter runtime information klassOop _pool_holder; // the corresponding class + int _length; // number of elements in the array // only set to non-zero if constant pool is merged by RedefineClasses int _orig_length; @@ -330,6 +331,14 @@ class constantPoolOopDesc : public arrayOopDesc { bool klass_name_at_matches(instanceKlassHandle k, int which); // Sizing + int length() const { return _length; } + void set_length(int length) { _length = length; } + + // Tells whether index is within bounds. + bool is_within_bounds(int index) const { + return 0 <= index && index < length(); + } + static int header_size() { return sizeof(constantPoolOopDesc)/HeapWordSize; } static int object_size(int length) { return align_object_size(header_size() + length); } int object_size() { return object_size(length()); } diff --git a/hotspot/src/share/vm/oops/cpCacheKlass.cpp b/hotspot/src/share/vm/oops/cpCacheKlass.cpp index c3f7d764f35..b57ccda8cd0 100644 --- a/hotspot/src/share/vm/oops/cpCacheKlass.cpp +++ b/hotspot/src/share/vm/oops/cpCacheKlass.cpp @@ -37,18 +37,19 @@ constantPoolCacheOop constantPoolCacheKlass::allocate(int length, TRAPS) { int size = constantPoolCacheOopDesc::object_size(length); KlassHandle klass (THREAD, as_klassOop()); constantPoolCacheOop cache = (constantPoolCacheOop) - CollectedHeap::permanent_array_allocate(klass, size, length, CHECK_NULL); + CollectedHeap::permanent_obj_allocate(klass, size, CHECK_NULL); + cache->set_length(length); cache->set_constant_pool(NULL); return cache; } - klassOop constantPoolCacheKlass::create_klass(TRAPS) { constantPoolCacheKlass o; - KlassHandle klassklass(THREAD, Universe::arrayKlassKlassObj()); - arrayKlassHandle k = base_create_array_klass(o.vtbl_value(), header_size(), klassklass, CHECK_NULL); - KlassHandle super (THREAD, k->super()); - complete_create_array_klass(k, super, CHECK_NULL); + KlassHandle h_this_klass(THREAD, Universe::klassKlassObj()); + KlassHandle k = base_create_klass(h_this_klass, header_size(), o.vtbl_value(), CHECK_NULL); + // Make sure size calculation is right + assert(k()->size() == align_object_size(header_size()), "wrong size for object"); + java_lang_Class::create_mirror(k, CHECK_NULL); // Allocate mirror return k(); } @@ -183,7 +184,7 @@ void constantPoolCacheKlass::oop_print_on(oop obj, outputStream* st) { assert(obj->is_constantPoolCache(), "obj must be constant pool cache"); constantPoolCacheOop cache = (constantPoolCacheOop)obj; // super print - arrayKlass::oop_print_on(obj, st); + Klass::oop_print_on(obj, st); // print constant pool cache entries for (int i = 0; i < cache->length(); i++) cache->entry_at(i)->print(st, i); } @@ -194,7 +195,7 @@ void constantPoolCacheKlass::oop_verify_on(oop obj, outputStream* st) { guarantee(obj->is_constantPoolCache(), "obj must be constant pool cache"); constantPoolCacheOop cache = (constantPoolCacheOop)obj; // super verify - arrayKlass::oop_verify_on(obj, st); + Klass::oop_verify_on(obj, st); // print constant pool cache entries for (int i = 0; i < cache->length(); i++) cache->entry_at(i)->verify(st); } diff --git a/hotspot/src/share/vm/oops/cpCacheKlass.hpp b/hotspot/src/share/vm/oops/cpCacheKlass.hpp index 7eb8d44577a..9c20eb9a94e 100644 --- a/hotspot/src/share/vm/oops/cpCacheKlass.hpp +++ b/hotspot/src/share/vm/oops/cpCacheKlass.hpp @@ -22,7 +22,8 @@ * */ -class constantPoolCacheKlass: public arrayKlass { +class constantPoolCacheKlass: public Klass { + juint _alloc_size; // allocation profiling support public: // Dispatched klass operations bool oop_is_constantPoolCache() const { return true; } @@ -41,8 +42,8 @@ class constantPoolCacheKlass: public arrayKlass { } // Sizing - static int header_size() { return oopDesc::header_size() + sizeof(constantPoolCacheKlass)/HeapWordSize; } - int object_size() const { return arrayKlass::object_size(header_size()); } + static int header_size() { return oopDesc::header_size() + sizeof(constantPoolCacheKlass)/HeapWordSize; } + int object_size() const { return align_object_size(header_size()); } // Garbage collection void oop_follow_contents(oop obj); @@ -55,6 +56,10 @@ class constantPoolCacheKlass: public arrayKlass { int oop_oop_iterate(oop obj, OopClosure* blk); int oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr); + // Allocation profiling support + juint alloc_size() const { return _alloc_size; } + void set_alloc_size(juint n) { _alloc_size = n; } + #ifndef PRODUCT public: // Printing diff --git a/hotspot/src/share/vm/oops/cpCacheOop.cpp b/hotspot/src/share/vm/oops/cpCacheOop.cpp index 3ffee53be23..a8f5c051ba6 100644 --- a/hotspot/src/share/vm/oops/cpCacheOop.cpp +++ b/hotspot/src/share/vm/oops/cpCacheOop.cpp @@ -218,6 +218,7 @@ class LocalOopClosure: public OopClosure { public: LocalOopClosure(void f(oop*)) { _f = f; } virtual void do_oop(oop* o) { _f(o); } + virtual void do_oop(narrowOop *o) { ShouldNotReachHere(); } }; diff --git a/hotspot/src/share/vm/oops/cpCacheOop.hpp b/hotspot/src/share/vm/oops/cpCacheOop.hpp index 55f7fcbba3a..fc810361880 100644 --- a/hotspot/src/share/vm/oops/cpCacheOop.hpp +++ b/hotspot/src/share/vm/oops/cpCacheOop.hpp @@ -286,12 +286,17 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { // is created and initialized before a class is actively used (i.e., initialized), the indivi- // dual cache entries are filled at resolution (i.e., "link") time (see also: rewriter.*). -class constantPoolCacheOopDesc: public arrayOopDesc { +class constantPoolCacheOopDesc: public oopDesc { friend class VMStructs; private: + int _length; constantPoolOop _constant_pool; // the corresponding constant pool // Sizing + debug_only(friend class ClassVerifier;) + int length() const { return _length; } + void set_length(int length) { _length = length; } + static int header_size() { return sizeof(constantPoolCacheOopDesc) / HeapWordSize; } static int object_size(int length) { return align_object_size(header_size() + length * in_words(ConstantPoolCacheEntry::size())); } int object_size() { return object_size(length()); } diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 45cd864b93f..2ce60748519 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -1255,218 +1255,298 @@ bool instanceKlass::is_dependent_nmethod(nmethod* nm) { #endif //PRODUCT -void instanceKlass::follow_static_fields() { - oop* start = start_of_static_fields(); - oop* end = start + static_oop_field_size(); - while (start < end) { - if (*start != NULL) { - assert(Universe::heap()->is_in_closed_subset(*start), - "should be in heap"); - MarkSweep::mark_and_push(start); - } - start++; +#ifdef ASSERT +template void assert_is_in(T *p) { + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop o = oopDesc::decode_heap_oop_not_null(heap_oop); + assert(Universe::heap()->is_in(o), "should be in heap"); } } +template void assert_is_in_closed_subset(T *p) { + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop o = oopDesc::decode_heap_oop_not_null(heap_oop); + assert(Universe::heap()->is_in_closed_subset(o), "should be in closed"); + } +} +template void assert_is_in_reserved(T *p) { + T heap_oop = oopDesc::load_heap_oop(p); + if (!oopDesc::is_null(heap_oop)) { + oop o = oopDesc::decode_heap_oop_not_null(heap_oop); + assert(Universe::heap()->is_in_reserved(o), "should be in reserved"); + } +} +template void assert_nothing(T *p) {} + +#else +template void assert_is_in(T *p) {} +template void assert_is_in_closed_subset(T *p) {} +template void assert_is_in_reserved(T *p) {} +template void assert_nothing(T *p) {} +#endif // ASSERT + +// +// Macros that iterate over areas of oops which are specialized on type of +// oop pointer either narrow or wide, depending on UseCompressedOops +// +// Parameters are: +// T - type of oop to point to (either oop or narrowOop) +// start_p - starting pointer for region to iterate over +// count - number of oops or narrowOops to iterate over +// do_oop - action to perform on each oop (it's arbitrary C code which +// makes it more efficient to put in a macro rather than making +// it a template function) +// assert_fn - assert function which is template function because performance +// doesn't matter when enabled. +#define InstanceKlass_SPECIALIZED_OOP_ITERATE( \ + T, start_p, count, do_oop, \ + assert_fn) \ +{ \ + T* p = (T*)(start_p); \ + T* const end = p + (count); \ + while (p < end) { \ + (assert_fn)(p); \ + do_oop; \ + ++p; \ + } \ +} + +#define InstanceKlass_SPECIALIZED_OOP_REVERSE_ITERATE( \ + T, start_p, count, do_oop, \ + assert_fn) \ +{ \ + T* const start = (T*)(start_p); \ + T* p = start + (count); \ + while (start < p) { \ + --p; \ + (assert_fn)(p); \ + do_oop; \ + } \ +} + +#define InstanceKlass_SPECIALIZED_BOUNDED_OOP_ITERATE( \ + T, start_p, count, low, high, \ + do_oop, assert_fn) \ +{ \ + T* const l = (T*)(low); \ + T* const h = (T*)(high); \ + assert(mask_bits((intptr_t)l, sizeof(T)-1) == 0 && \ + mask_bits((intptr_t)h, sizeof(T)-1) == 0, \ + "bounded region must be properly aligned"); \ + T* p = (T*)(start_p); \ + T* end = p + (count); \ + if (p < l) p = l; \ + if (end > h) end = h; \ + while (p < end) { \ + (assert_fn)(p); \ + do_oop; \ + ++p; \ + } \ +} + + +// The following macros call specialized macros, passing either oop or +// narrowOop as the specialization type. These test the UseCompressedOops +// flag. +#define InstanceKlass_OOP_ITERATE(start_p, count, \ + do_oop, assert_fn) \ +{ \ + if (UseCompressedOops) { \ + InstanceKlass_SPECIALIZED_OOP_ITERATE(narrowOop, \ + start_p, count, \ + do_oop, assert_fn) \ + } else { \ + InstanceKlass_SPECIALIZED_OOP_ITERATE(oop, \ + start_p, count, \ + do_oop, assert_fn) \ + } \ +} + +#define InstanceKlass_BOUNDED_OOP_ITERATE(start_p, count, low, high, \ + do_oop, assert_fn) \ +{ \ + if (UseCompressedOops) { \ + InstanceKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \ + start_p, count, \ + low, high, \ + do_oop, assert_fn) \ + } else { \ + InstanceKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop, \ + start_p, count, \ + low, high, \ + do_oop, assert_fn) \ + } \ +} + +#define InstanceKlass_OOP_MAP_ITERATE(obj, do_oop, assert_fn) \ +{ \ + /* Compute oopmap block range. The common case \ + is nonstatic_oop_map_size == 1. */ \ + OopMapBlock* map = start_of_nonstatic_oop_maps(); \ + OopMapBlock* const end_map = map + nonstatic_oop_map_size(); \ + if (UseCompressedOops) { \ + while (map < end_map) { \ + InstanceKlass_SPECIALIZED_OOP_ITERATE(narrowOop, \ + obj->obj_field_addr(map->offset()), map->length(), \ + do_oop, assert_fn) \ + ++map; \ + } \ + } else { \ + while (map < end_map) { \ + InstanceKlass_SPECIALIZED_OOP_ITERATE(oop, \ + obj->obj_field_addr(map->offset()), map->length(), \ + do_oop, assert_fn) \ + ++map; \ + } \ + } \ +} + +#define InstanceKlass_OOP_MAP_REVERSE_ITERATE(obj, do_oop, assert_fn) \ +{ \ + OopMapBlock* const start_map = start_of_nonstatic_oop_maps(); \ + OopMapBlock* map = start_map + nonstatic_oop_map_size(); \ + if (UseCompressedOops) { \ + while (start_map < map) { \ + --map; \ + InstanceKlass_SPECIALIZED_OOP_REVERSE_ITERATE(narrowOop, \ + obj->obj_field_addr(map->offset()), map->length(), \ + do_oop, assert_fn) \ + } \ + } else { \ + while (start_map < map) { \ + --map; \ + InstanceKlass_SPECIALIZED_OOP_REVERSE_ITERATE(oop, \ + obj->obj_field_addr(map->offset()), map->length(), \ + do_oop, assert_fn) \ + } \ + } \ +} + +#define InstanceKlass_BOUNDED_OOP_MAP_ITERATE(obj, low, high, do_oop, \ + assert_fn) \ +{ \ + /* Compute oopmap block range. The common case is \ + nonstatic_oop_map_size == 1, so we accept the \ + usually non-existent extra overhead of examining \ + all the maps. */ \ + OopMapBlock* map = start_of_nonstatic_oop_maps(); \ + OopMapBlock* const end_map = map + nonstatic_oop_map_size(); \ + if (UseCompressedOops) { \ + while (map < end_map) { \ + InstanceKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \ + obj->obj_field_addr(map->offset()), map->length(), \ + low, high, \ + do_oop, assert_fn) \ + ++map; \ + } \ + } else { \ + while (map < end_map) { \ + InstanceKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop, \ + obj->obj_field_addr(map->offset()), map->length(), \ + low, high, \ + do_oop, assert_fn) \ + ++map; \ + } \ + } \ +} + +void instanceKlass::follow_static_fields() { + InstanceKlass_OOP_ITERATE( \ + start_of_static_fields(), static_oop_field_size(), \ + MarkSweep::mark_and_push(p), \ + assert_is_in_closed_subset) +} #ifndef SERIALGC void instanceKlass::follow_static_fields(ParCompactionManager* cm) { - oop* start = start_of_static_fields(); - oop* end = start + static_oop_field_size(); - while (start < end) { - if (*start != NULL) { - assert(Universe::heap()->is_in(*start), "should be in heap"); - PSParallelCompact::mark_and_push(cm, start); - } - start++; - } + InstanceKlass_OOP_ITERATE( \ + start_of_static_fields(), static_oop_field_size(), \ + PSParallelCompact::mark_and_push(cm, p), \ + assert_is_in) } #endif // SERIALGC - void instanceKlass::adjust_static_fields() { - oop* start = start_of_static_fields(); - oop* end = start + static_oop_field_size(); - while (start < end) { - MarkSweep::adjust_pointer(start); - start++; - } + InstanceKlass_OOP_ITERATE( \ + start_of_static_fields(), static_oop_field_size(), \ + MarkSweep::adjust_pointer(p), \ + assert_nothing) } #ifndef SERIALGC void instanceKlass::update_static_fields() { - oop* const start = start_of_static_fields(); - oop* const beg_oop = start; - oop* const end_oop = start + static_oop_field_size(); - for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) { - PSParallelCompact::adjust_pointer(cur_oop); - } + InstanceKlass_OOP_ITERATE( \ + start_of_static_fields(), static_oop_field_size(), \ + PSParallelCompact::adjust_pointer(p), \ + assert_nothing) } -void -instanceKlass::update_static_fields(HeapWord* beg_addr, HeapWord* end_addr) { - oop* const start = start_of_static_fields(); - oop* const beg_oop = MAX2((oop*)beg_addr, start); - oop* const end_oop = MIN2((oop*)end_addr, start + static_oop_field_size()); - for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) { - PSParallelCompact::adjust_pointer(cur_oop); - } +void instanceKlass::update_static_fields(HeapWord* beg_addr, HeapWord* end_addr) { + InstanceKlass_BOUNDED_OOP_ITERATE( \ + start_of_static_fields(), static_oop_field_size(), \ + beg_addr, end_addr, \ + PSParallelCompact::adjust_pointer(p), \ + assert_nothing ) } #endif // SERIALGC void instanceKlass::oop_follow_contents(oop obj) { - assert (obj!=NULL, "can't follow the content of NULL object"); + assert(obj != NULL, "can't follow the content of NULL object"); obj->follow_header(); - OopMapBlock* map = start_of_nonstatic_oop_maps(); - OopMapBlock* end_map = map + nonstatic_oop_map_size(); - while (map < end_map) { - oop* start = obj->obj_field_addr(map->offset()); - oop* end = start + map->length(); - while (start < end) { - if (*start != NULL) { - assert(Universe::heap()->is_in_closed_subset(*start), - "should be in heap"); - MarkSweep::mark_and_push(start); - } - start++; - } - map++; - } + InstanceKlass_OOP_MAP_ITERATE( \ + obj, \ + MarkSweep::mark_and_push(p), \ + assert_is_in_closed_subset) } #ifndef SERIALGC void instanceKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { - assert (obj!=NULL, "can't follow the content of NULL object"); + assert(obj != NULL, "can't follow the content of NULL object"); obj->follow_header(cm); - OopMapBlock* map = start_of_nonstatic_oop_maps(); - OopMapBlock* end_map = map + nonstatic_oop_map_size(); - while (map < end_map) { - oop* start = obj->obj_field_addr(map->offset()); - oop* end = start + map->length(); - while (start < end) { - if (*start != NULL) { - assert(Universe::heap()->is_in(*start), "should be in heap"); - PSParallelCompact::mark_and_push(cm, start); - } - start++; - } - map++; - } + InstanceKlass_OOP_MAP_ITERATE( \ + obj, \ + PSParallelCompact::mark_and_push(cm, p), \ + assert_is_in) } #endif // SERIALGC -#define invoke_closure_on(start, closure, nv_suffix) { \ - oop obj = *(start); \ - if (obj != NULL) { \ - assert(Universe::heap()->is_in_closed_subset(obj), "should be in heap"); \ - (closure)->do_oop##nv_suffix(start); \ - } \ -} - // closure's do_header() method dicates whether the given closure should be // applied to the klass ptr in the object header. -#define InstanceKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ - \ -int instanceKlass::oop_oop_iterate##nv_suffix(oop obj, \ - OopClosureType* closure) { \ - SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::ik); \ - /* header */ \ - if (closure->do_header()) { \ - obj->oop_iterate_header(closure); \ - } \ - /* instance variables */ \ - OopMapBlock* map = start_of_nonstatic_oop_maps(); \ - OopMapBlock* const end_map = map + nonstatic_oop_map_size(); \ - const intx field_offset = PrefetchFieldsAhead; \ - if (field_offset > 0) { \ - while (map < end_map) { \ - oop* start = obj->obj_field_addr(map->offset()); \ - oop* const end = start + map->length(); \ - while (start < end) { \ - prefetch_beyond(start, (oop*)end, field_offset, \ - closure->prefetch_style()); \ - SpecializationStats:: \ - record_do_oop_call##nv_suffix(SpecializationStats::ik); \ - invoke_closure_on(start, closure, nv_suffix); \ - start++; \ - } \ - map++; \ - } \ - } else { \ - while (map < end_map) { \ - oop* start = obj->obj_field_addr(map->offset()); \ - oop* const end = start + map->length(); \ - while (start < end) { \ - SpecializationStats:: \ - record_do_oop_call##nv_suffix(SpecializationStats::ik); \ - invoke_closure_on(start, closure, nv_suffix); \ - start++; \ - } \ - map++; \ - } \ - } \ - return size_helper(); \ +#define InstanceKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ + \ +int instanceKlass::oop_oop_iterate##nv_suffix(oop obj, \ + OopClosureType* closure) {\ + SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::ik);\ + /* header */ \ + if (closure->do_header()) { \ + obj->oop_iterate_header(closure); \ + } \ + InstanceKlass_OOP_MAP_ITERATE( \ + obj, \ + SpecializationStats:: \ + record_do_oop_call##nv_suffix(SpecializationStats::ik); \ + (closure)->do_oop##nv_suffix(p), \ + assert_is_in_closed_subset) \ + return size_helper(); \ } -#define InstanceKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ - \ -int instanceKlass::oop_oop_iterate##nv_suffix##_m(oop obj, \ - OopClosureType* closure, \ - MemRegion mr) { \ - SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::ik); \ - /* header */ \ - if (closure->do_header()) { \ - obj->oop_iterate_header(closure, mr); \ - } \ - /* instance variables */ \ - OopMapBlock* map = start_of_nonstatic_oop_maps(); \ - OopMapBlock* const end_map = map + nonstatic_oop_map_size(); \ - HeapWord* bot = mr.start(); \ - HeapWord* top = mr.end(); \ - oop* start = obj->obj_field_addr(map->offset()); \ - HeapWord* end = MIN2((HeapWord*)(start + map->length()), top); \ - /* Find the first map entry that extends onto mr. */ \ - while (map < end_map && end <= bot) { \ - map++; \ - start = obj->obj_field_addr(map->offset()); \ - end = MIN2((HeapWord*)(start + map->length()), top); \ - } \ - if (map != end_map) { \ - /* The current map's end is past the start of "mr". Skip up to the first \ - entry on "mr". */ \ - while ((HeapWord*)start < bot) { \ - start++; \ - } \ - const intx field_offset = PrefetchFieldsAhead; \ - for (;;) { \ - if (field_offset > 0) { \ - while ((HeapWord*)start < end) { \ - prefetch_beyond(start, (oop*)end, field_offset, \ - closure->prefetch_style()); \ - invoke_closure_on(start, closure, nv_suffix); \ - start++; \ - } \ - } else { \ - while ((HeapWord*)start < end) { \ - invoke_closure_on(start, closure, nv_suffix); \ - start++; \ - } \ - } \ - /* Go to the next map. */ \ - map++; \ - if (map == end_map) { \ - break; \ - } \ - /* Otherwise, */ \ - start = obj->obj_field_addr(map->offset()); \ - if ((HeapWord*)start >= top) { \ - break; \ - } \ - end = MIN2((HeapWord*)(start + map->length()), top); \ - } \ - } \ - return size_helper(); \ +#define InstanceKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ + \ +int instanceKlass::oop_oop_iterate##nv_suffix##_m(oop obj, \ + OopClosureType* closure, \ + MemRegion mr) { \ + SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::ik);\ + if (closure->do_header()) { \ + obj->oop_iterate_header(closure, mr); \ + } \ + InstanceKlass_BOUNDED_OOP_MAP_ITERATE( \ + obj, mr.start(), mr.end(), \ + (closure)->do_oop##nv_suffix(p), \ + assert_is_in_closed_subset) \ + return size_helper(); \ } ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DEFN) @@ -1474,56 +1554,28 @@ ALL_OOP_OOP_ITERATE_CLOSURES_3(InstanceKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_3(InstanceKlass_OOP_OOP_ITERATE_DEFN_m) - void instanceKlass::iterate_static_fields(OopClosure* closure) { - oop* start = start_of_static_fields(); - oop* end = start + static_oop_field_size(); - while (start < end) { - assert(Universe::heap()->is_in_reserved_or_null(*start), "should be in heap"); - closure->do_oop(start); - start++; - } + InstanceKlass_OOP_ITERATE( \ + start_of_static_fields(), static_oop_field_size(), \ + closure->do_oop(p), \ + assert_is_in_reserved) } void instanceKlass::iterate_static_fields(OopClosure* closure, MemRegion mr) { - oop* start = start_of_static_fields(); - oop* end = start + static_oop_field_size(); - // I gather that the the static fields of reference types come first, - // hence the name of "oop_field_size", and that is what makes this safe. - assert((intptr_t)mr.start() == - align_size_up((intptr_t)mr.start(), sizeof(oop)) && - (intptr_t)mr.end() == align_size_up((intptr_t)mr.end(), sizeof(oop)), - "Memregion must be oop-aligned."); - if ((HeapWord*)start < mr.start()) start = (oop*)mr.start(); - if ((HeapWord*)end > mr.end()) end = (oop*)mr.end(); - while (start < end) { - invoke_closure_on(start, closure,_v); - start++; - } + InstanceKlass_BOUNDED_OOP_ITERATE( \ + start_of_static_fields(), static_oop_field_size(), \ + mr.start(), mr.end(), \ + (closure)->do_oop_v(p), \ + assert_is_in_closed_subset) } - int instanceKlass::oop_adjust_pointers(oop obj) { int size = size_helper(); - - // Compute oopmap block range. The common case is nonstatic_oop_map_size == 1. - OopMapBlock* map = start_of_nonstatic_oop_maps(); - OopMapBlock* const end_map = map + nonstatic_oop_map_size(); - // Iterate over oopmap blocks - while (map < end_map) { - // Compute oop range for this block - oop* start = obj->obj_field_addr(map->offset()); - oop* end = start + map->length(); - // Iterate over oops - while (start < end) { - assert(Universe::heap()->is_in_or_null(*start), "should be in heap"); - MarkSweep::adjust_pointer(start); - start++; - } - map++; - } - + InstanceKlass_OOP_MAP_ITERATE( \ + obj, \ + MarkSweep::adjust_pointer(p), \ + assert_is_in) obj->adjust_header(); return size; } @@ -1531,132 +1583,66 @@ int instanceKlass::oop_adjust_pointers(oop obj) { #ifndef SERIALGC void instanceKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) { assert(!pm->depth_first(), "invariant"); - // Compute oopmap block range. The common case is nonstatic_oop_map_size == 1. - OopMapBlock* start_map = start_of_nonstatic_oop_maps(); - OopMapBlock* map = start_map + nonstatic_oop_map_size(); - - // Iterate over oopmap blocks - while (start_map < map) { - --map; - // Compute oop range for this block - oop* start = obj->obj_field_addr(map->offset()); - oop* curr = start + map->length(); - // Iterate over oops - while (start < curr) { - --curr; - if (PSScavenge::should_scavenge(*curr)) { - assert(Universe::heap()->is_in(*curr), "should be in heap"); - pm->claim_or_forward_breadth(curr); - } - } - } + InstanceKlass_OOP_MAP_REVERSE_ITERATE( \ + obj, \ + if (PSScavenge::should_scavenge(p)) { \ + pm->claim_or_forward_breadth(p); \ + }, \ + assert_nothing ) } void instanceKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { assert(pm->depth_first(), "invariant"); - // Compute oopmap block range. The common case is nonstatic_oop_map_size == 1. - OopMapBlock* start_map = start_of_nonstatic_oop_maps(); - OopMapBlock* map = start_map + nonstatic_oop_map_size(); - - // Iterate over oopmap blocks - while (start_map < map) { - --map; - // Compute oop range for this block - oop* start = obj->obj_field_addr(map->offset()); - oop* curr = start + map->length(); - // Iterate over oops - while (start < curr) { - --curr; - if (PSScavenge::should_scavenge(*curr)) { - assert(Universe::heap()->is_in(*curr), "should be in heap"); - pm->claim_or_forward_depth(curr); - } - } - } + InstanceKlass_OOP_MAP_REVERSE_ITERATE( \ + obj, \ + if (PSScavenge::should_scavenge(p)) { \ + pm->claim_or_forward_depth(p); \ + }, \ + assert_nothing ) } int instanceKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { - // Compute oopmap block range. The common case is nonstatic_oop_map_size==1. - OopMapBlock* map = start_of_nonstatic_oop_maps(); - OopMapBlock* const end_map = map + nonstatic_oop_map_size(); - // Iterate over oopmap blocks - while (map < end_map) { - // Compute oop range for this oopmap block. - oop* const map_start = obj->obj_field_addr(map->offset()); - oop* const beg_oop = map_start; - oop* const end_oop = map_start + map->length(); - for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) { - PSParallelCompact::adjust_pointer(cur_oop); - } - ++map; - } - + InstanceKlass_OOP_MAP_ITERATE( \ + obj, \ + PSParallelCompact::adjust_pointer(p), \ + assert_nothing) return size_helper(); } int instanceKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, HeapWord* beg_addr, HeapWord* end_addr) { - // Compute oopmap block range. The common case is nonstatic_oop_map_size==1. - OopMapBlock* map = start_of_nonstatic_oop_maps(); - OopMapBlock* const end_map = map + nonstatic_oop_map_size(); - // Iterate over oopmap blocks - while (map < end_map) { - // Compute oop range for this oopmap block. - oop* const map_start = obj->obj_field_addr(map->offset()); - oop* const beg_oop = MAX2((oop*)beg_addr, map_start); - oop* const end_oop = MIN2((oop*)end_addr, map_start + map->length()); - for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) { - PSParallelCompact::adjust_pointer(cur_oop); - } - ++map; - } - + InstanceKlass_BOUNDED_OOP_MAP_ITERATE( \ + obj, beg_addr, end_addr, \ + PSParallelCompact::adjust_pointer(p), \ + assert_nothing) return size_helper(); } void instanceKlass::copy_static_fields(PSPromotionManager* pm) { assert(!pm->depth_first(), "invariant"); - // Compute oop range - oop* start = start_of_static_fields(); - oop* end = start + static_oop_field_size(); - // Iterate over oops - while (start < end) { - if (PSScavenge::should_scavenge(*start)) { - assert(Universe::heap()->is_in(*start), "should be in heap"); - pm->claim_or_forward_breadth(start); - } - start++; - } + InstanceKlass_OOP_ITERATE( \ + start_of_static_fields(), static_oop_field_size(), \ + if (PSScavenge::should_scavenge(p)) { \ + pm->claim_or_forward_breadth(p); \ + }, \ + assert_nothing ) } void instanceKlass::push_static_fields(PSPromotionManager* pm) { assert(pm->depth_first(), "invariant"); - // Compute oop range - oop* start = start_of_static_fields(); - oop* end = start + static_oop_field_size(); - // Iterate over oops - while (start < end) { - if (PSScavenge::should_scavenge(*start)) { - assert(Universe::heap()->is_in(*start), "should be in heap"); - pm->claim_or_forward_depth(start); - } - start++; - } + InstanceKlass_OOP_ITERATE( \ + start_of_static_fields(), static_oop_field_size(), \ + if (PSScavenge::should_scavenge(p)) { \ + pm->claim_or_forward_depth(p); \ + }, \ + assert_nothing ) } void instanceKlass::copy_static_fields(ParCompactionManager* cm) { - // Compute oop range - oop* start = start_of_static_fields(); - oop* end = start + static_oop_field_size(); - // Iterate over oops - while (start < end) { - if (*start != NULL) { - assert(Universe::heap()->is_in(*start), "should be in heap"); - // *start = (oop) cm->summary_data()->calc_new_pointer(*start); - PSParallelCompact::adjust_pointer(start); - } - start++; - } + InstanceKlass_OOP_ITERATE( \ + start_of_static_fields(), static_oop_field_size(), \ + PSParallelCompact::adjust_pointer(p), \ + assert_is_in) } #endif // SERIALGC @@ -1687,18 +1673,15 @@ void instanceKlass::follow_weak_klass_links( Klass::follow_weak_klass_links(is_alive, keep_alive); } - void instanceKlass::remove_unshareable_info() { Klass::remove_unshareable_info(); init_implementor(); } - static void clear_all_breakpoints(methodOop m) { m->clear_all_breakpoints(); } - void instanceKlass::release_C_heap_structures() { // Deallocate oop map cache if (_oop_map_cache != NULL) { @@ -2047,29 +2030,30 @@ void instanceKlass::oop_print_value_on(oop obj, outputStream* st) { obj->print_address_on(st); } -#endif +#endif // ndef PRODUCT const char* instanceKlass::internal_name() const { return external_name(); } - - // Verification class VerifyFieldClosure: public OopClosure { - public: - void do_oop(oop* p) { + protected: + template void do_oop_work(T* p) { guarantee(Universe::heap()->is_in_closed_subset(p), "should be in heap"); - if (!(*p)->is_oop_or_null()) { - tty->print_cr("Failed: %p -> %p",p,(address)*p); + oop obj = oopDesc::load_decode_heap_oop(p); + if (!obj->is_oop_or_null()) { + tty->print_cr("Failed: " PTR_FORMAT " -> " PTR_FORMAT, p, (address)obj); Universe::print(); guarantee(false, "boom"); } } + public: + virtual void do_oop(oop* p) { VerifyFieldClosure::do_oop_work(p); } + virtual void do_oop(narrowOop* p) { VerifyFieldClosure::do_oop_work(p); } }; - void instanceKlass::oop_verify_on(oop obj, outputStream* st) { Klass::oop_verify_on(obj, st); VerifyFieldClosure blk; @@ -2110,26 +2094,28 @@ void instanceKlass::verify_class_klass_nonstatic_oop_maps(klassOop k) { } } -#endif +#endif // ndef PRODUCT + +// JNIid class for jfieldIDs only +// Note to reviewers: +// These JNI functions are just moved over to column 1 and not changed +// in the compressed oops workspace. +JNIid::JNIid(klassOop holder, int offset, JNIid* next) { + _holder = holder; + _offset = offset; + _next = next; + debug_only(_is_static_field_id = false;) +} -/* JNIid class for jfieldIDs only */ - JNIid::JNIid(klassOop holder, int offset, JNIid* next) { - _holder = holder; - _offset = offset; - _next = next; - debug_only(_is_static_field_id = false;) - } - - - JNIid* JNIid::find(int offset) { - JNIid* current = this; - while (current != NULL) { - if (current->offset() == offset) return current; - current = current->next(); - } - return NULL; - } +JNIid* JNIid::find(int offset) { + JNIid* current = this; + while (current != NULL) { + if (current->offset() == offset) return current; + current = current->next(); + } + return NULL; +} void JNIid::oops_do(OopClosure* f) { for (JNIid* cur = this; cur != NULL; cur = cur->next()) { @@ -2138,40 +2124,40 @@ void JNIid::oops_do(OopClosure* f) { } void JNIid::deallocate(JNIid* current) { - while (current != NULL) { - JNIid* next = current->next(); - delete current; - current = next; - } - } + while (current != NULL) { + JNIid* next = current->next(); + delete current; + current = next; + } +} - void JNIid::verify(klassOop holder) { - int first_field_offset = instanceKlass::cast(holder)->offset_of_static_fields(); - int end_field_offset; - end_field_offset = first_field_offset + (instanceKlass::cast(holder)->static_field_size() * wordSize); +void JNIid::verify(klassOop holder) { + int first_field_offset = instanceKlass::cast(holder)->offset_of_static_fields(); + int end_field_offset; + end_field_offset = first_field_offset + (instanceKlass::cast(holder)->static_field_size() * wordSize); - JNIid* current = this; - while (current != NULL) { - guarantee(current->holder() == holder, "Invalid klass in JNIid"); - #ifdef ASSERT - int o = current->offset(); - if (current->is_static_field_id()) { - guarantee(o >= first_field_offset && o < end_field_offset, "Invalid static field offset in JNIid"); - } - #endif - current = current->next(); - } - } + JNIid* current = this; + while (current != NULL) { + guarantee(current->holder() == holder, "Invalid klass in JNIid"); +#ifdef ASSERT + int o = current->offset(); + if (current->is_static_field_id()) { + guarantee(o >= first_field_offset && o < end_field_offset, "Invalid static field offset in JNIid"); + } +#endif + current = current->next(); + } +} #ifdef ASSERT - void instanceKlass::set_init_state(ClassState state) { - bool good_state = as_klassOop()->is_shared() ? (_init_state <= state) - : (_init_state < state); - assert(good_state || state == allocated, "illegal state transition"); - _init_state = state; - } +void instanceKlass::set_init_state(ClassState state) { + bool good_state = as_klassOop()->is_shared() ? (_init_state <= state) + : (_init_state < state); + assert(good_state || state == allocated, "illegal state transition"); + _init_state = state; +} #endif @@ -2180,9 +2166,9 @@ void JNIid::deallocate(JNIid* current) { // Add an information node that contains weak references to the // interesting parts of the previous version of the_class. void instanceKlass::add_previous_version(instanceKlassHandle ikh, - BitMap * emcp_methods, int emcp_method_count) { + BitMap* emcp_methods, int emcp_method_count) { assert(Thread::current()->is_VM_thread(), - "only VMThread can add previous versions"); + "only VMThread can add previous versions"); if (_previous_versions == NULL) { // This is the first previous version so make some space. diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 285291dcea4..b7b71d930ff 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -180,12 +180,16 @@ class instanceKlass: public Klass { // End of the oop block. // - int _nonstatic_field_size; // number of non-static fields in this klass (including inherited fields) - int _static_field_size; // number of static fields (oop and non-oop) in this klass + // number of words used by non-static fields in this klass (including + // inherited fields but after header_size()). If fields are compressed into + // header, this can be zero so it's not the same as number of static fields. + int _nonstatic_field_size; + int _static_field_size; // number words used by static fields (oop and non-oop) in this klass int _static_oop_field_size;// number of static oop fields in this klass int _nonstatic_oop_map_size;// number of nonstatic oop-map blocks allocated at end of this klass bool _is_marked_dependent; // used for marking during flushing and deoptimization bool _rewritten; // methods rewritten. + bool _has_nonstatic_fields; // for sizing with UseCompressedOops u2 _minor_version; // minor version number of class file u2 _major_version; // major version number of class file ClassState _init_state; // state of class @@ -221,6 +225,9 @@ class instanceKlass: public Klass { friend class SystemDictionary; public: + bool has_nonstatic_fields() const { return _has_nonstatic_fields; } + void set_has_nonstatic_fields(bool b) { _has_nonstatic_fields = b; } + // field sizes int nonstatic_field_size() const { return _nonstatic_field_size; } void set_nonstatic_field_size(int size) { _nonstatic_field_size = size; } @@ -340,8 +347,7 @@ class instanceKlass: public Klass { // find a non-static or static field given its offset within the class. bool contains_field_offset(int offset) { - return ((offset/wordSize) >= instanceOopDesc::header_size() && - (offset/wordSize)-instanceOopDesc::header_size() < nonstatic_field_size()); + return instanceOopDesc::contains_field_offset(offset, nonstatic_field_size()); } bool find_local_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const; @@ -570,12 +576,21 @@ class instanceKlass: public Klass { intptr_t* start_of_itable() const { return start_of_vtable() + align_object_offset(vtable_length()); } int itable_offset_in_words() const { return start_of_itable() - (intptr_t*)as_klassOop(); } - oop* start_of_static_fields() const { return (oop*)(start_of_itable() + align_object_offset(itable_length())); } - intptr_t* end_of_itable() const { return start_of_itable() + itable_length(); } - oop* end_of_static_fields() const { return start_of_static_fields() + static_field_size(); } - int offset_of_static_fields() const { return (intptr_t)start_of_static_fields() - (intptr_t)as_klassOop(); } + // Static field offset is an offset into the Heap, should be converted by + // based on UseCompressedOop for traversal + HeapWord* start_of_static_fields() const { + return (HeapWord*)(start_of_itable() + align_object_offset(itable_length())); + } - OopMapBlock* start_of_nonstatic_oop_maps() const { return (OopMapBlock*) (start_of_static_fields() + static_field_size()); } + intptr_t* end_of_itable() const { return start_of_itable() + itable_length(); } + + int offset_of_static_fields() const { + return (intptr_t)start_of_static_fields() - (intptr_t)as_klassOop(); + } + + OopMapBlock* start_of_nonstatic_oop_maps() const { + return (OopMapBlock*) (start_of_static_fields() + static_field_size()); + } // Allocation profiling support juint alloc_size() const { return _alloc_count * size_helper(); } diff --git a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp index 144ced69e1e..f0a150408db 100644 --- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp @@ -286,17 +286,17 @@ void instanceKlassKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) { ik->copy_static_fields(pm); oop* loader_addr = ik->adr_class_loader(); - if (PSScavenge::should_scavenge(*loader_addr)) { + if (PSScavenge::should_scavenge(loader_addr)) { pm->claim_or_forward_breadth(loader_addr); } oop* pd_addr = ik->adr_protection_domain(); - if (PSScavenge::should_scavenge(*pd_addr)) { + if (PSScavenge::should_scavenge(pd_addr)) { pm->claim_or_forward_breadth(pd_addr); } oop* sg_addr = ik->adr_signers(); - if (PSScavenge::should_scavenge(*sg_addr)) { + if (PSScavenge::should_scavenge(sg_addr)) { pm->claim_or_forward_breadth(sg_addr); } @@ -309,17 +309,17 @@ void instanceKlassKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { ik->push_static_fields(pm); oop* loader_addr = ik->adr_class_loader(); - if (PSScavenge::should_scavenge(*loader_addr)) { + if (PSScavenge::should_scavenge(loader_addr)) { pm->claim_or_forward_depth(loader_addr); } oop* pd_addr = ik->adr_protection_domain(); - if (PSScavenge::should_scavenge(*pd_addr)) { + if (PSScavenge::should_scavenge(pd_addr)) { pm->claim_or_forward_depth(pd_addr); } oop* sg_addr = ik->adr_signers(); - if (PSScavenge::should_scavenge(*sg_addr)) { + if (PSScavenge::should_scavenge(sg_addr)) { pm->claim_or_forward_depth(sg_addr); } @@ -602,16 +602,18 @@ const char* instanceKlassKlass::internal_name() const { // Verification - class VerifyFieldClosure: public OopClosure { - public: - void do_oop(oop* p) { + protected: + template void do_oop_work(T* p) { guarantee(Universe::heap()->is_in(p), "should be in heap"); - guarantee((*p)->is_oop_or_null(), "should be in heap"); + oop obj = oopDesc::load_decode_heap_oop(p); + guarantee(obj->is_oop_or_null(), "should be in heap"); } + public: + virtual void do_oop(oop* p) { VerifyFieldClosure::do_oop_work(p); } + virtual void do_oop(narrowOop* p) { VerifyFieldClosure::do_oop_work(p); } }; - void instanceKlassKlass::oop_verify_on(oop obj, outputStream* st) { klassKlass::oop_verify_on(obj, st); if (!obj->partially_loaded()) { diff --git a/hotspot/src/share/vm/oops/instanceOop.hpp b/hotspot/src/share/vm/oops/instanceOop.hpp index 49cab9379d1..e0f0cca1ffa 100644 --- a/hotspot/src/share/vm/oops/instanceOop.hpp +++ b/hotspot/src/share/vm/oops/instanceOop.hpp @@ -27,5 +27,26 @@ class instanceOopDesc : public oopDesc { public: + // aligned header size. static int header_size() { return sizeof(instanceOopDesc)/HeapWordSize; } + + // If compressed, the offset of the fields of the instance may not be aligned. + static int base_offset_in_bytes() { + return UseCompressedOops ? + klass_gap_offset_in_bytes() : + sizeof(instanceOopDesc); + } + + static bool contains_field_offset(int offset, int nonstatic_field_size) { + int base_in_bytes = base_offset_in_bytes(); + if (UseCompressedOops) { + return (offset >= base_in_bytes && + // field can be embedded in header, or is after header. + (offset < (int)sizeof(instanceOopDesc) || + (offset-(int)sizeof(instanceOopDesc))/wordSize < nonstatic_field_size)); + } else { + return (offset >= base_in_bytes && + (offset-base_in_bytes)/wordSize < nonstatic_field_size); + } + } }; diff --git a/hotspot/src/share/vm/oops/instanceRefKlass.cpp b/hotspot/src/share/vm/oops/instanceRefKlass.cpp index d98ecd2cf7a..634a8c7fb9e 100644 --- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp @@ -25,23 +25,24 @@ # include "incls/_precompiled.incl" # include "incls/_instanceRefKlass.cpp.incl" -void instanceRefKlass::oop_follow_contents(oop obj) { - oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); - oop referent = *referent_addr; +template +static void specialized_oop_follow_contents(instanceRefKlass* ref, oop obj) { + T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); + oop referent = oopDesc::load_decode_heap_oop(referent_addr); debug_only( if(TraceReferenceGC && PrintGCDetails) { - gclog_or_tty->print_cr("instanceRefKlass::oop_follow_contents " INTPTR_FORMAT, (address)obj); + gclog_or_tty->print_cr("instanceRefKlass::oop_follow_contents " INTPTR_FORMAT, obj); } ) if (referent != NULL) { if (!referent->is_gc_marked() && MarkSweep::ref_processor()-> - discover_reference(obj, reference_type())) { + discover_reference(obj, ref->reference_type())) { // reference already enqueued, referent will be traversed later - instanceKlass::oop_follow_contents(obj); + ref->instanceKlass::oop_follow_contents(obj); debug_only( if(TraceReferenceGC && PrintGCDetails) { - gclog_or_tty->print_cr(" Non NULL enqueued " INTPTR_FORMAT, (address)obj); + gclog_or_tty->print_cr(" Non NULL enqueued " INTPTR_FORMAT, obj); } ) return; @@ -49,42 +50,52 @@ void instanceRefKlass::oop_follow_contents(oop obj) { // treat referent as normal oop debug_only( if(TraceReferenceGC && PrintGCDetails) { - gclog_or_tty->print_cr(" Non NULL normal " INTPTR_FORMAT, (address)obj); + gclog_or_tty->print_cr(" Non NULL normal " INTPTR_FORMAT, obj); } ) MarkSweep::mark_and_push(referent_addr); } } // treat next as normal oop. next is a link in the pending list. - oop* next_addr = java_lang_ref_Reference::next_addr(obj); + T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); debug_only( if(TraceReferenceGC && PrintGCDetails) { gclog_or_tty->print_cr(" Process next as normal " INTPTR_FORMAT, next_addr); } ) MarkSweep::mark_and_push(next_addr); - instanceKlass::oop_follow_contents(obj); + ref->instanceKlass::oop_follow_contents(obj); +} + +void instanceRefKlass::oop_follow_contents(oop obj) { + if (UseCompressedOops) { + specialized_oop_follow_contents(this, obj); + } else { + specialized_oop_follow_contents(this, obj); + } } #ifndef SERIALGC -void instanceRefKlass::oop_follow_contents(ParCompactionManager* cm, - oop obj) { - oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); - oop referent = *referent_addr; +template +static void specialized_oop_follow_contents(instanceRefKlass* ref, + ParCompactionManager* cm, + oop obj) { + T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); + oop referent = oopDesc::load_decode_heap_oop(referent_addr); debug_only( if(TraceReferenceGC && PrintGCDetails) { - gclog_or_tty->print_cr("instanceRefKlass::oop_follow_contents " INTPTR_FORMAT, (address)obj); + gclog_or_tty->print_cr("instanceRefKlass::oop_follow_contents " INTPTR_FORMAT, obj); } ) if (referent != NULL) { if (PSParallelCompact::mark_bitmap()->is_unmarked(referent) && PSParallelCompact::ref_processor()-> - discover_reference(obj, reference_type())) { + discover_reference(obj, ref->reference_type())) { // reference already enqueued, referent will be traversed later - instanceKlass::oop_follow_contents(cm, obj); + ref->instanceKlass::oop_follow_contents(cm, obj); debug_only( if(TraceReferenceGC && PrintGCDetails) { - gclog_or_tty->print_cr(" Non NULL enqueued " INTPTR_FORMAT, (address)obj); + gclog_or_tty->print_cr(" Non NULL enqueued " INTPTR_FORMAT, obj); } ) return; @@ -92,55 +103,106 @@ void instanceRefKlass::oop_follow_contents(ParCompactionManager* cm, // treat referent as normal oop debug_only( if(TraceReferenceGC && PrintGCDetails) { - gclog_or_tty->print_cr(" Non NULL normal " INTPTR_FORMAT, (address)obj); + gclog_or_tty->print_cr(" Non NULL normal " INTPTR_FORMAT, obj); } ) PSParallelCompact::mark_and_push(cm, referent_addr); } } // treat next as normal oop. next is a link in the pending list. - oop* next_addr = java_lang_ref_Reference::next_addr(obj); + T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); debug_only( if(TraceReferenceGC && PrintGCDetails) { gclog_or_tty->print_cr(" Process next as normal " INTPTR_FORMAT, next_addr); } ) PSParallelCompact::mark_and_push(cm, next_addr); - instanceKlass::oop_follow_contents(cm, obj); + ref->instanceKlass::oop_follow_contents(cm, obj); +} + +void instanceRefKlass::oop_follow_contents(ParCompactionManager* cm, + oop obj) { + if (UseCompressedOops) { + specialized_oop_follow_contents(this, cm, obj); + } else { + specialized_oop_follow_contents(this, cm, obj); + } } #endif // SERIALGC +#ifdef ASSERT +template void trace_reference_gc(const char *s, oop obj, + T* referent_addr, + T* next_addr, + T* discovered_addr) { + if(TraceReferenceGC && PrintGCDetails) { + gclog_or_tty->print_cr("%s obj " INTPTR_FORMAT, s, (address)obj); + gclog_or_tty->print_cr(" referent_addr/* " INTPTR_FORMAT " / " + INTPTR_FORMAT, referent_addr, + referent_addr ? + (address)oopDesc::load_decode_heap_oop(referent_addr) : NULL); + gclog_or_tty->print_cr(" next_addr/* " INTPTR_FORMAT " / " + INTPTR_FORMAT, next_addr, + next_addr ? (address)oopDesc::load_decode_heap_oop(next_addr) : NULL); + gclog_or_tty->print_cr(" discovered_addr/* " INTPTR_FORMAT " / " + INTPTR_FORMAT, discovered_addr, + discovered_addr ? + (address)oopDesc::load_decode_heap_oop(discovered_addr) : NULL); + } +} +#endif + +template void specialized_oop_adjust_pointers(instanceRefKlass *ref, oop obj) { + T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); + MarkSweep::adjust_pointer(referent_addr); + T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); + MarkSweep::adjust_pointer(next_addr); + T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); + MarkSweep::adjust_pointer(discovered_addr); + debug_only(trace_reference_gc("instanceRefKlass::oop_adjust_pointers", obj, + referent_addr, next_addr, discovered_addr);) +} int instanceRefKlass::oop_adjust_pointers(oop obj) { int size = size_helper(); instanceKlass::oop_adjust_pointers(obj); - oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); - MarkSweep::adjust_pointer(referent_addr); - oop* next_addr = java_lang_ref_Reference::next_addr(obj); - MarkSweep::adjust_pointer(next_addr); - oop* discovered_addr = java_lang_ref_Reference::discovered_addr(obj); - MarkSweep::adjust_pointer(discovered_addr); - -#ifdef ASSERT - if(TraceReferenceGC && PrintGCDetails) { - gclog_or_tty->print_cr("instanceRefKlass::oop_adjust_pointers obj " - INTPTR_FORMAT, (address)obj); - gclog_or_tty->print_cr(" referent_addr/* " INTPTR_FORMAT " / " - INTPTR_FORMAT, referent_addr, - referent_addr ? (address)*referent_addr : NULL); - gclog_or_tty->print_cr(" next_addr/* " INTPTR_FORMAT " / " - INTPTR_FORMAT, next_addr, - next_addr ? (address)*next_addr : NULL); - gclog_or_tty->print_cr(" discovered_addr/* " INTPTR_FORMAT " / " - INTPTR_FORMAT, discovered_addr, - discovered_addr ? (address)*discovered_addr : NULL); + if (UseCompressedOops) { + specialized_oop_adjust_pointers(this, obj); + } else { + specialized_oop_adjust_pointers(this, obj); } -#endif - return size; } +#define InstanceRefKlass_SPECIALIZED_OOP_ITERATE(T, nv_suffix, contains) \ + T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); \ + oop referent = oopDesc::load_decode_heap_oop(referent_addr); \ + if (referent != NULL && contains(referent_addr)) { \ + ReferenceProcessor* rp = closure->_ref_processor; \ + if (!referent->is_gc_marked() && (rp != NULL) && \ + rp->discover_reference(obj, reference_type())) { \ + return size; \ + } else { \ + /* treat referent as normal oop */ \ + SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\ + closure->do_oop##nv_suffix(referent_addr); \ + } \ + } \ + /* treat next as normal oop */ \ + T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); \ + if (contains(next_addr)) { \ + SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk); \ + closure->do_oop##nv_suffix(next_addr); \ + } \ + return size; \ + + +template bool contains(T *t) { return true; } + +// Macro to define instanceRefKlass::oop_oop_iterate for virtual/nonvirtual for +// all closures. Macros calling macros above for each oop size. + #define InstanceRefKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ \ int instanceRefKlass:: \ @@ -150,25 +212,11 @@ oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { \ int size = instanceKlass::oop_oop_iterate##nv_suffix(obj, closure); \ \ - oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); \ - oop referent = *referent_addr; \ - if (referent != NULL) { \ - ReferenceProcessor* rp = closure->_ref_processor; \ - if (!referent->is_gc_marked() && (rp != NULL) && \ - rp->discover_reference(obj, reference_type())) { \ - return size; \ - } else { \ - /* treat referent as normal oop */ \ - SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\ - closure->do_oop##nv_suffix(referent_addr); \ - } \ + if (UseCompressedOops) { \ + InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, contains); \ + } else { \ + InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains); \ } \ - \ - /* treat next as normal oop */ \ - oop* next_addr = java_lang_ref_Reference::next_addr(obj); \ - SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk); \ - closure->do_oop##nv_suffix(next_addr); \ - return size; \ } #define InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ @@ -180,28 +228,11 @@ oop_oop_iterate##nv_suffix##_m(oop obj, SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\ \ int size = instanceKlass::oop_oop_iterate##nv_suffix##_m(obj, closure, mr); \ - \ - oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); \ - oop referent = *referent_addr; \ - if (referent != NULL && mr.contains(referent_addr)) { \ - ReferenceProcessor* rp = closure->_ref_processor; \ - if (!referent->is_gc_marked() && (rp != NULL) && \ - rp->discover_reference(obj, reference_type())) { \ - return size; \ - } else { \ - /* treat referent as normal oop */ \ - SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\ - closure->do_oop##nv_suffix(referent_addr); \ - } \ + if (UseCompressedOops) { \ + InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, mr.contains); \ + } else { \ + InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, mr.contains); \ } \ - \ - /* treat next as normal oop */ \ - oop* next_addr = java_lang_ref_Reference::next_addr(obj); \ - if (mr.contains(next_addr)) { \ - SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\ - closure->do_oop##nv_suffix(next_addr); \ - } \ - return size; \ } ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN) @@ -209,16 +240,17 @@ ALL_OOP_OOP_ITERATE_CLOSURES_3(InstanceRefKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_3(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m) - #ifndef SERIALGC -void instanceRefKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) { +template +void specialized_oop_copy_contents(instanceRefKlass *ref, + PSPromotionManager* pm, oop obj) { assert(!pm->depth_first(), "invariant"); - oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); - if (PSScavenge::should_scavenge(*referent_addr)) { + T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); + if (PSScavenge::should_scavenge(referent_addr)) { ReferenceProcessor* rp = PSScavenge::reference_processor(); - if (rp->discover_reference(obj, reference_type())) { + if (rp->discover_reference(obj, ref->reference_type())) { // reference already enqueued, referent and next will be traversed later - instanceKlass::oop_copy_contents(pm, obj); + ref->instanceKlass::oop_copy_contents(pm, obj); return; } else { // treat referent as normal oop @@ -226,21 +258,31 @@ void instanceRefKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) { } } // treat next as normal oop - oop* next_addr = java_lang_ref_Reference::next_addr(obj); - if (PSScavenge::should_scavenge(*next_addr)) { + T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); + if (PSScavenge::should_scavenge(next_addr)) { pm->claim_or_forward_breadth(next_addr); } - instanceKlass::oop_copy_contents(pm, obj); + ref->instanceKlass::oop_copy_contents(pm, obj); } -void instanceRefKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { +void instanceRefKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) { + if (UseCompressedOops) { + specialized_oop_copy_contents(this, pm, obj); + } else { + specialized_oop_copy_contents(this, pm, obj); + } +} + +template +void specialized_oop_push_contents(instanceRefKlass *ref, + PSPromotionManager* pm, oop obj) { assert(pm->depth_first(), "invariant"); - oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); - if (PSScavenge::should_scavenge(*referent_addr)) { + T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); + if (PSScavenge::should_scavenge(referent_addr)) { ReferenceProcessor* rp = PSScavenge::reference_processor(); - if (rp->discover_reference(obj, reference_type())) { + if (rp->discover_reference(obj, ref->reference_type())) { // reference already enqueued, referent and next will be traversed later - instanceKlass::oop_push_contents(pm, obj); + ref->instanceKlass::oop_push_contents(pm, obj); return; } else { // treat referent as normal oop @@ -248,71 +290,68 @@ void instanceRefKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { } } // treat next as normal oop - oop* next_addr = java_lang_ref_Reference::next_addr(obj); - if (PSScavenge::should_scavenge(*next_addr)) { + T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); + if (PSScavenge::should_scavenge(next_addr)) { pm->claim_or_forward_depth(next_addr); } - instanceKlass::oop_push_contents(pm, obj); + ref->instanceKlass::oop_push_contents(pm, obj); +} + +void instanceRefKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { + if (UseCompressedOops) { + specialized_oop_push_contents(this, pm, obj); + } else { + specialized_oop_push_contents(this, pm, obj); + } +} + +template +void specialized_oop_update_pointers(instanceRefKlass *ref, + ParCompactionManager* cm, oop obj) { + T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); + PSParallelCompact::adjust_pointer(referent_addr); + T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); + PSParallelCompact::adjust_pointer(next_addr); + T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); + PSParallelCompact::adjust_pointer(discovered_addr); + debug_only(trace_reference_gc("instanceRefKlass::oop_update_ptrs", obj, + referent_addr, next_addr, discovered_addr);) } int instanceRefKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { instanceKlass::oop_update_pointers(cm, obj); - - oop* referent_addr = java_lang_ref_Reference::referent_addr(obj); - PSParallelCompact::adjust_pointer(referent_addr); - oop* next_addr = java_lang_ref_Reference::next_addr(obj); - PSParallelCompact::adjust_pointer(next_addr); - oop* discovered_addr = java_lang_ref_Reference::discovered_addr(obj); - PSParallelCompact::adjust_pointer(discovered_addr); - -#ifdef ASSERT - if(TraceReferenceGC && PrintGCDetails) { - gclog_or_tty->print_cr("instanceRefKlass::oop_update_pointers obj " - INTPTR_FORMAT, (oopDesc*) obj); - gclog_or_tty->print_cr(" referent_addr/* " INTPTR_FORMAT " / " - INTPTR_FORMAT, referent_addr, - referent_addr ? (oopDesc*) *referent_addr : NULL); - gclog_or_tty->print_cr(" next_addr/* " INTPTR_FORMAT " / " - INTPTR_FORMAT, next_addr, - next_addr ? (oopDesc*) *next_addr : NULL); - gclog_or_tty->print_cr(" discovered_addr/* " INTPTR_FORMAT " / " - INTPTR_FORMAT, discovered_addr, - discovered_addr ? (oopDesc*) *discovered_addr : NULL); + if (UseCompressedOops) { + specialized_oop_update_pointers(this, cm, obj); + } else { + specialized_oop_update_pointers(this, cm, obj); } -#endif - return size_helper(); } + +template void +specialized_oop_update_pointers(ParCompactionManager* cm, oop obj, + HeapWord* beg_addr, HeapWord* end_addr) { + T* p; + T* referent_addr = p = (T*)java_lang_ref_Reference::referent_addr(obj); + PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); + T* next_addr = p = (T*)java_lang_ref_Reference::next_addr(obj); + PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); + T* discovered_addr = p = (T*)java_lang_ref_Reference::discovered_addr(obj); + PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); + debug_only(trace_reference_gc("instanceRefKlass::oop_update_ptrs", obj, + referent_addr, next_addr, discovered_addr);) +} + int instanceRefKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, HeapWord* beg_addr, HeapWord* end_addr) { instanceKlass::oop_update_pointers(cm, obj, beg_addr, end_addr); - - oop* p; - oop* referent_addr = p = java_lang_ref_Reference::referent_addr(obj); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - oop* next_addr = p = java_lang_ref_Reference::next_addr(obj); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - oop* discovered_addr = p = java_lang_ref_Reference::discovered_addr(obj); - PSParallelCompact::adjust_pointer(p, beg_addr, end_addr); - -#ifdef ASSERT - if(TraceReferenceGC && PrintGCDetails) { - gclog_or_tty->print_cr("instanceRefKlass::oop_update_pointers obj " - INTPTR_FORMAT, (oopDesc*) obj); - gclog_or_tty->print_cr(" referent_addr/* " INTPTR_FORMAT " / " - INTPTR_FORMAT, referent_addr, - referent_addr ? (oopDesc*) *referent_addr : NULL); - gclog_or_tty->print_cr(" next_addr/* " INTPTR_FORMAT " / " - INTPTR_FORMAT, next_addr, - next_addr ? (oopDesc*) *next_addr : NULL); - gclog_or_tty->print_cr(" discovered_addr/* " INTPTR_FORMAT " / " - INTPTR_FORMAT, discovered_addr, - discovered_addr ? (oopDesc*) *discovered_addr : NULL); + if (UseCompressedOops) { + specialized_oop_update_pointers(cm, obj, beg_addr, end_addr); + } else { + specialized_oop_update_pointers(cm, obj, beg_addr, end_addr); } -#endif - return size_helper(); } #endif // SERIALGC @@ -338,7 +377,7 @@ void instanceRefKlass::update_nonstatic_oop_maps(klassOop k) { // offset 2 (words) and has 4 map entries. debug_only(int offset = java_lang_ref_Reference::referent_offset); debug_only(int length = ((java_lang_ref_Reference::discovered_offset - - java_lang_ref_Reference::referent_offset)/wordSize) + 1); + java_lang_ref_Reference::referent_offset)/heapOopSize) + 1); if (UseSharedSpaces) { assert(map->offset() == java_lang_ref_Reference::queue_offset && @@ -368,22 +407,35 @@ void instanceRefKlass::oop_verify_on(oop obj, outputStream* st) { if (referent != NULL) { guarantee(referent->is_oop(), "referent field heap failed"); - if (gch != NULL && !gch->is_in_youngest(obj)) + if (gch != NULL && !gch->is_in_youngest(obj)) { // We do a specific remembered set check here since the referent // field is not part of the oop mask and therefore skipped by the // regular verify code. - obj->verify_old_oop(java_lang_ref_Reference::referent_addr(obj), true); + if (UseCompressedOops) { + narrowOop* referent_addr = (narrowOop*)java_lang_ref_Reference::referent_addr(obj); + obj->verify_old_oop(referent_addr, true); + } else { + oop* referent_addr = (oop*)java_lang_ref_Reference::referent_addr(obj); + obj->verify_old_oop(referent_addr, true); + } + } } // Verify next field oop next = java_lang_ref_Reference::next(obj); if (next != NULL) { - guarantee(next->is_oop(), "next field verify failed"); + guarantee(next->is_oop(), "next field verify fa iled"); guarantee(next->is_instanceRef(), "next field verify failed"); if (gch != NULL && !gch->is_in_youngest(obj)) { // We do a specific remembered set check here since the next field is // not part of the oop mask and therefore skipped by the regular // verify code. - obj->verify_old_oop(java_lang_ref_Reference::next_addr(obj), true); + if (UseCompressedOops) { + narrowOop* next_addr = (narrowOop*)java_lang_ref_Reference::next_addr(obj); + obj->verify_old_oop(next_addr, true); + } else { + oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj); + obj->verify_old_oop(next_addr, true); + } } } } diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 33e800a3cd5..04d350197bf 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -542,11 +542,10 @@ void Klass::oop_verify_on(oop obj, outputStream* st) { void Klass::oop_verify_old_oop(oop obj, oop* p, bool allow_dirty) { /* $$$ I think this functionality should be handled by verification of - RememberedSet::verify_old_oop(obj, p, allow_dirty, false); - the card table. */ } +void Klass::oop_verify_old_oop(oop obj, narrowOop* p, bool allow_dirty) { } #ifndef PRODUCT diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index 76473cba3ee..d8aac3de60d 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -757,6 +757,7 @@ class Klass : public Klass_vtbl { virtual const char* internal_name() const = 0; virtual void oop_verify_on(oop obj, outputStream* st); virtual void oop_verify_old_oop(oop obj, oop* p, bool allow_dirty); + virtual void oop_verify_old_oop(oop obj, narrowOop* p, bool allow_dirty); // tells whether obj is partially constructed (gc during class loading) virtual bool oop_partially_loaded(oop obj) const { return false; } virtual void oop_set_partially_loaded(oop obj) {}; diff --git a/hotspot/src/share/vm/oops/klassVtable.cpp b/hotspot/src/share/vm/oops/klassVtable.cpp index 84ce0c58a62..447d6e92958 100644 --- a/hotspot/src/share/vm/oops/klassVtable.cpp +++ b/hotspot/src/share/vm/oops/klassVtable.cpp @@ -1118,8 +1118,8 @@ void klassItable::setup_itable_offset_table(instanceKlassHandle klass) { itableOffsetEntry* ioe = (itableOffsetEntry*)klass->start_of_itable(); itableMethodEntry* ime = (itableMethodEntry*)(ioe + nof_interfaces); intptr_t* end = klass->end_of_itable(); - assert((oop*)(ime + nof_methods) <= klass->start_of_static_fields(), "wrong offset calculation (1)"); - assert((oop*)(end) == (oop*)(ime + nof_methods), "wrong offset calculation (2)"); + assert((oop*)(ime + nof_methods) <= (oop*)klass->start_of_static_fields(), "wrong offset calculation (1)"); + assert((oop*)(end) == (oop*)(ime + nof_methods), "wrong offset calculation (2)"); // Visit all interfaces and initialize itable offset table SetupItableClosure sic((address)klass->as_klassOop(), ioe, ime); diff --git a/hotspot/src/share/vm/oops/markOop.hpp b/hotspot/src/share/vm/oops/markOop.hpp index 155fb163895..ac42fef74f2 100644 --- a/hotspot/src/share/vm/oops/markOop.hpp +++ b/hotspot/src/share/vm/oops/markOop.hpp @@ -89,7 +89,7 @@ class markOopDesc: public oopDesc { enum { age_bits = 4, lock_bits = 2, biased_lock_bits = 1, - max_hash_bits = BitsPerOop - age_bits - lock_bits - biased_lock_bits, + max_hash_bits = BitsPerWord - age_bits - lock_bits - biased_lock_bits, hash_bits = max_hash_bits > 31 ? 31 : max_hash_bits, epoch_bits = 2 }; diff --git a/hotspot/src/share/vm/oops/methodDataKlass.cpp b/hotspot/src/share/vm/oops/methodDataKlass.cpp index f3ee24122b0..feddbddb06e 100644 --- a/hotspot/src/share/vm/oops/methodDataKlass.cpp +++ b/hotspot/src/share/vm/oops/methodDataKlass.cpp @@ -95,6 +95,7 @@ void methodDataKlass::oop_follow_contents(ParCompactionManager* cm, } #endif // SERIALGC + int methodDataKlass::oop_oop_iterate(oop obj, OopClosure* blk) { assert (obj->is_methodData(), "object must be method data"); methodDataOop m = methodDataOop(obj); @@ -113,7 +114,6 @@ int methodDataKlass::oop_oop_iterate(oop obj, OopClosure* blk) { return size; } - int methodDataKlass::oop_oop_iterate_m(oop obj, OopClosure* blk, MemRegion mr) { assert (obj->is_methodData(), "object must be method data"); methodDataOop m = methodDataOop(obj); @@ -158,14 +158,14 @@ void methodDataKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) { assert (obj->is_methodData(), "object must be method data"); methodDataOop m = methodDataOop(obj); // This should never point into the young gen. - assert(!PSScavenge::should_scavenge(oop(*m->adr_method())), "Sanity"); + assert(!PSScavenge::should_scavenge(m->adr_method()), "Sanity"); } void methodDataKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { assert (obj->is_methodData(), "object must be method data"); methodDataOop m = methodDataOop(obj); // This should never point into the young gen. - assert(!PSScavenge::should_scavenge(oop(*m->adr_method())), "Sanity"); + assert(!PSScavenge::should_scavenge(m->adr_method()), "Sanity"); } int methodDataKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { diff --git a/hotspot/src/share/vm/oops/methodOop.cpp b/hotspot/src/share/vm/oops/methodOop.cpp index dfe9dee8560..cb1ad91807e 100644 --- a/hotspot/src/share/vm/oops/methodOop.cpp +++ b/hotspot/src/share/vm/oops/methodOop.cpp @@ -430,11 +430,11 @@ bool methodOopDesc::can_be_statically_bound() const { bool methodOopDesc::is_accessor() const { if (code_size() != 5) return false; if (size_of_parameters() != 1) return false; - if (Bytecodes::java_code_at(code_base()+0) != Bytecodes::_aload_0 ) return false; - if (Bytecodes::java_code_at(code_base()+1) != Bytecodes::_getfield) return false; - Bytecodes::Code ret_bc = Bytecodes::java_code_at(code_base()+4); - if (Bytecodes::java_code_at(code_base()+4) != Bytecodes::_areturn && - Bytecodes::java_code_at(code_base()+4) != Bytecodes::_ireturn ) return false; + methodOop m = (methodOop)this; // pass to code_at() to avoid method_from_bcp + if (Bytecodes::java_code_at(code_base()+0, m) != Bytecodes::_aload_0 ) return false; + if (Bytecodes::java_code_at(code_base()+1, m) != Bytecodes::_getfield) return false; + if (Bytecodes::java_code_at(code_base()+4, m) != Bytecodes::_areturn && + Bytecodes::java_code_at(code_base()+4, m) != Bytecodes::_ireturn ) return false; return true; } @@ -672,9 +672,6 @@ void methodOopDesc::link_method(methodHandle h_method, TRAPS) { } address methodOopDesc::make_adapters(methodHandle mh, TRAPS) { - // If running -Xint we need no adapters. - if (Arguments::mode() == Arguments::_int) return NULL; - // Adapters for compiled code are made eagerly here. They are fairly // small (generally < 100 bytes) and quick to make (and cached and shared) // so making them eagerly shouldn't be too expensive. @@ -888,10 +885,11 @@ bool methodOopDesc::load_signature_classes(methodHandle m, TRAPS) { symbolHandle name (THREAD, sym); klassOop klass = SystemDictionary::resolve_or_null(name, class_loader, protection_domain, THREAD); - // We are loading classes eagerly. If a ClassNotFoundException was generated, - // be sure to ignore it. + // We are loading classes eagerly. If a ClassNotFoundException or + // a LinkageError was generated, be sure to ignore it. if (HAS_PENDING_EXCEPTION) { - if (PENDING_EXCEPTION->is_a(SystemDictionary::classNotFoundException_klass())) { + if (PENDING_EXCEPTION->is_a(SystemDictionary::classNotFoundException_klass()) || + PENDING_EXCEPTION->is_a(SystemDictionary::linkageError_klass())) { CLEAR_PENDING_EXCEPTION; } else { return false; @@ -954,7 +952,7 @@ extern "C" { // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array static void reorder_based_on_method_index(objArrayOop methods, objArrayOop annotations, - oop* temp_array) { + GrowableArray* temp_array) { if (annotations == NULL) { return; } @@ -962,12 +960,15 @@ static void reorder_based_on_method_index(objArrayOop methods, int length = methods->length(); int i; // Copy to temp array - memcpy(temp_array, annotations->obj_at_addr(0), length * sizeof(oop)); + temp_array->clear(); + for (i = 0; i < length; i++) { + temp_array->append(annotations->obj_at(i)); + } // Copy back using old method indices for (i = 0; i < length; i++) { methodOop m = (methodOop) methods->obj_at(i); - annotations->obj_at_put(i, temp_array[m->method_idnum()]); + annotations->obj_at_put(i, temp_array->at(m->method_idnum())); } } @@ -996,7 +997,7 @@ void methodOopDesc::sort_methods(objArrayOop methods, // Use a simple bubble sort for small number of methods since // qsort requires a functional pointer call for each comparison. - if (length < 8) { + if (UseCompressedOops || length < 8) { bool sorted = true; for (int i=length-1; i>0; i--) { for (int j=0; jobj_at_addr(0), length, oopSize, compare); + qsort(methods->base(), length, heapOopSize, compare); } // Sort annotations if necessary @@ -1021,8 +1025,9 @@ void methodOopDesc::sort_methods(objArrayOop methods, assert(methods_parameter_annotations == NULL || methods_parameter_annotations->length() == methods->length(), ""); assert(methods_default_annotations == NULL || methods_default_annotations->length() == methods->length(), ""); if (do_annotations) { + ResourceMark rm; // Allocate temporary storage - oop* temp_array = NEW_RESOURCE_ARRAY(oop, length); + GrowableArray* temp_array = new GrowableArray(length); reorder_based_on_method_index(methods, methods_annotations, temp_array); reorder_based_on_method_index(methods, methods_parameter_annotations, temp_array); reorder_based_on_method_index(methods, methods_default_annotations, temp_array); diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp index e83ecd7bf71..193249bcf8e 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp @@ -80,6 +80,56 @@ oop objArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) { return h_array(); } +// Either oop or narrowOop depending on UseCompressedOops. +template void objArrayKlass::do_copy(arrayOop s, T* src, + arrayOop d, T* dst, int length, TRAPS) { + + const size_t word_len = objArrayOopDesc::array_size(length); + + // For performance reasons, we assume we are using a card marking write + // barrier. The assert will fail if this is not the case. + BarrierSet* bs = Universe::heap()->barrier_set(); + assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt"); + + if (s == d) { + // since source and destination are equal we do not need conversion checks. + assert(length > 0, "sanity check"); + Copy::conjoint_oops_atomic(src, dst, length); + } else { + // We have to make sure all elements conform to the destination array + klassOop bound = objArrayKlass::cast(d->klass())->element_klass(); + klassOop stype = objArrayKlass::cast(s->klass())->element_klass(); + if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) { + // elements are guaranteed to be subtypes, so no check necessary + Copy::conjoint_oops_atomic(src, dst, length); + } else { + // slow case: need individual subtype checks + // note: don't use obj_at_put below because it includes a redundant store check + T* from = src; + T* end = from + length; + for (T* p = dst; from < end; from++, p++) { + // XXX this is going to be slow. + T element = *from; + if (oopDesc::is_null(element) || + Klass::cast(oopDesc::decode_heap_oop_not_null(element)->klass())->is_subtype_of(bound)) { + *p = *from; + } else { + // We must do a barrier to cover the partial copy. + const size_t pd = pointer_delta(p, dst, (size_t)heapOopSize); + // pointer delta is scaled to number of elements (length field in + // objArrayOop) which we assume is 32 bit. + assert(pd == (size_t)(int)pd, "length field overflow"); + const size_t done_word_len = objArrayOopDesc::array_size((int)pd); + bs->write_ref_array(MemRegion((HeapWord*)dst, done_word_len)); + THROW(vmSymbols::java_lang_ArrayStoreException()); + return; + } + } + } + } + bs->write_ref_array(MemRegion((HeapWord*)dst, word_len)); +} + void objArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) { assert(s->is_objArray(), "must be obj array"); @@ -105,48 +155,15 @@ void objArrayKlass::copy_array(arrayOop s, int src_pos, arrayOop d, if (length==0) { return; } - - oop* const src = objArrayOop(s)->obj_at_addr(src_pos); - oop* const dst = objArrayOop(d)->obj_at_addr(dst_pos); - const size_t word_len = length * HeapWordsPerOop; - - // For performance reasons, we assume we are using a card marking write - // barrier. The assert will fail if this is not the case. - BarrierSet* bs = Universe::heap()->barrier_set(); - assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt"); - - if (s == d) { - // since source and destination are equal we do not need conversion checks. - assert(length > 0, "sanity check"); - Copy::conjoint_oops_atomic(src, dst, length); + if (UseCompressedOops) { + narrowOop* const src = objArrayOop(s)->obj_at_addr(src_pos); + narrowOop* const dst = objArrayOop(d)->obj_at_addr(dst_pos); + do_copy(s, src, d, dst, length, CHECK); } else { - // We have to make sure all elements conform to the destination array - klassOop bound = objArrayKlass::cast(d->klass())->element_klass(); - klassOop stype = objArrayKlass::cast(s->klass())->element_klass(); - if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) { - // elements are guaranteed to be subtypes, so no check necessary - Copy::conjoint_oops_atomic(src, dst, length); - } else { - // slow case: need individual subtype checks - // note: don't use obj_at_put below because it includes a redundant store check - oop* from = src; - oop* end = from + length; - for (oop* p = dst; from < end; from++, p++) { - oop element = *from; - if (element == NULL || Klass::cast(element->klass())->is_subtype_of(bound)) { - *p = element; - } else { - // We must do a barrier to cover the partial copy. - const size_t done_word_len = pointer_delta(p, dst, oopSize) * - HeapWordsPerOop; - bs->write_ref_array(MemRegion((HeapWord*)dst, done_word_len)); - THROW(vmSymbols::java_lang_ArrayStoreException()); - return; - } - } - } + oop* const src = objArrayOop(s)->obj_at_addr(src_pos); + oop* const dst = objArrayOop(d)->obj_at_addr(dst_pos); + do_copy (s, src, d, dst, length, CHECK); } - bs->write_ref_array(MemRegion((HeapWord*)dst, word_len)); } @@ -242,49 +259,75 @@ bool objArrayKlass::compute_is_subtype_of(klassOop k) { return element_klass()->klass_part()->is_subtype_of(oak->element_klass()); } - void objArrayKlass::initialize(TRAPS) { Klass::cast(bottom_klass())->initialize(THREAD); // dispatches to either instanceKlass or typeArrayKlass } +#define ObjArrayKlass_SPECIALIZED_OOP_ITERATE(T, a, p, do_oop) \ +{ \ + T* p = (T*)(a)->base(); \ + T* const end = p + (a)->length(); \ + while (p < end) { \ + do_oop; \ + p++; \ + } \ +} + +#define ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(T, a, p, low, high, do_oop) \ +{ \ + T* const l = (T*)(low); \ + T* const h = (T*)(high); \ + T* p = (T*)(a)->base(); \ + T* end = p + (a)->length(); \ + if (p < l) p = l; \ + if (end > h) end = h; \ + while (p < end) { \ + do_oop; \ + ++p; \ + } \ +} + +#define ObjArrayKlass_OOP_ITERATE(a, p, do_oop) \ + if (UseCompressedOops) { \ + ObjArrayKlass_SPECIALIZED_OOP_ITERATE(narrowOop, \ + a, p, do_oop) \ + } else { \ + ObjArrayKlass_SPECIALIZED_OOP_ITERATE(oop, \ + a, p, do_oop) \ + } + +#define ObjArrayKlass_BOUNDED_OOP_ITERATE(a, p, low, high, do_oop) \ + if (UseCompressedOops) { \ + ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \ + a, p, low, high, do_oop) \ + } else { \ + ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop, \ + a, p, low, high, do_oop) \ + } void objArrayKlass::oop_follow_contents(oop obj) { assert (obj->is_array(), "obj must be array"); - arrayOop a = arrayOop(obj); + objArrayOop a = objArrayOop(obj); a->follow_header(); - oop* base = (oop*)a->base(T_OBJECT); - oop* const end = base + a->length(); - while (base < end) { - if (*base != NULL) - // we call mark_and_follow here to avoid excessive marking stack usage - MarkSweep::mark_and_follow(base); - base++; - } + ObjArrayKlass_OOP_ITERATE( \ + a, p, \ + /* we call mark_and_follow here to avoid excessive marking stack usage */ \ + MarkSweep::mark_and_follow(p)) } #ifndef SERIALGC void objArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { assert (obj->is_array(), "obj must be array"); - arrayOop a = arrayOop(obj); + objArrayOop a = objArrayOop(obj); a->follow_header(cm); - oop* base = (oop*)a->base(T_OBJECT); - oop* const end = base + a->length(); - while (base < end) { - if (*base != NULL) - // we call mark_and_follow here to avoid excessive marking stack usage - PSParallelCompact::mark_and_follow(cm, base); - base++; - } + ObjArrayKlass_OOP_ITERATE( \ + a, p, \ + /* we call mark_and_follow here to avoid excessive marking stack usage */ \ + PSParallelCompact::mark_and_follow(cm, p)) } #endif // SERIALGC -#define invoke_closure_on(base, closure, nv_suffix) { \ - if (*(base) != NULL) { \ - (closure)->do_oop##nv_suffix(base); \ - } \ -} - #define ObjArrayKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ \ int objArrayKlass::oop_oop_iterate##nv_suffix(oop obj, \ @@ -298,21 +341,7 @@ int objArrayKlass::oop_oop_iterate##nv_suffix(oop obj, if (closure->do_header()) { \ a->oop_iterate_header(closure); \ } \ - oop* base = a->base(); \ - oop* const end = base + a->length(); \ - const intx field_offset = PrefetchFieldsAhead; \ - if (field_offset > 0) { \ - while (base < end) { \ - prefetch_beyond(base, end, field_offset, closure->prefetch_style()); \ - invoke_closure_on(base, closure, nv_suffix); \ - base++; \ - } \ - } else { \ - while (base < end) { \ - invoke_closure_on(base, closure, nv_suffix); \ - base++; \ - } \ - } \ + ObjArrayKlass_OOP_ITERATE(a, p, (closure)->do_oop##nv_suffix(p)) \ return size; \ } @@ -330,28 +359,43 @@ int objArrayKlass::oop_oop_iterate##nv_suffix##_m(oop obj, if (closure->do_header()) { \ a->oop_iterate_header(closure, mr); \ } \ - oop* bottom = (oop*)mr.start(); \ - oop* top = (oop*)mr.end(); \ - oop* base = a->base(); \ - oop* end = base + a->length(); \ - if (base < bottom) { \ - base = bottom; \ - } \ - if (end > top) { \ - end = top; \ - } \ - const intx field_offset = PrefetchFieldsAhead; \ - if (field_offset > 0) { \ - while (base < end) { \ - prefetch_beyond(base, end, field_offset, closure->prefetch_style()); \ - invoke_closure_on(base, closure, nv_suffix); \ - base++; \ + ObjArrayKlass_BOUNDED_OOP_ITERATE( \ + a, p, mr.start(), mr.end(), (closure)->do_oop##nv_suffix(p)) \ + return size; \ +} + +// Like oop_oop_iterate but only iterates over a specified range and only used +// for objArrayOops. +#define ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r(OopClosureType, nv_suffix) \ + \ +int objArrayKlass::oop_oop_iterate_range##nv_suffix(oop obj, \ + OopClosureType* closure, \ + int start, int end) { \ + SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::oa); \ + assert(obj->is_array(), "obj must be array"); \ + objArrayOop a = objArrayOop(obj); \ + /* Get size before changing pointers. */ \ + /* Don't call size() or oop_size() since that is a virtual call */ \ + int size = a->object_size(); \ + if (UseCompressedOops) { \ + HeapWord* low = start == 0 ? (HeapWord*)a : (HeapWord*)a->obj_at_addr(start);\ + /* this might be wierd if end needs to be aligned on HeapWord boundary */ \ + HeapWord* high = (HeapWord*)((narrowOop*)a->base() + end); \ + MemRegion mr(low, high); \ + if (closure->do_header()) { \ + a->oop_iterate_header(closure, mr); \ } \ + ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \ + a, p, low, high, (closure)->do_oop##nv_suffix(p)) \ } else { \ - while (base < end) { \ - invoke_closure_on(base, closure, nv_suffix); \ - base++; \ + HeapWord* low = start == 0 ? (HeapWord*)a : (HeapWord*)a->obj_at_addr(start); \ + HeapWord* high = (HeapWord*)((oop*)a->base() + end); \ + MemRegion mr(low, high); \ + if (closure->do_header()) { \ + a->oop_iterate_header(closure, mr); \ } \ + ObjArrayKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop, \ + a, p, low, high, (closure)->do_oop##nv_suffix(p)) \ } \ return size; \ } @@ -360,6 +404,8 @@ ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_3(ObjArrayKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_3(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_m) +ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r) +ALL_OOP_OOP_ITERATE_CLOSURES_3(ObjArrayKlass_OOP_OOP_ITERATE_DEFN_r) int objArrayKlass::oop_adjust_pointers(oop obj) { assert(obj->is_objArray(), "obj must be obj array"); @@ -368,12 +414,7 @@ int objArrayKlass::oop_adjust_pointers(oop obj) { // Don't call size() or oop_size() since that is a virtual call. int size = a->object_size(); a->adjust_header(); - oop* base = a->base(); - oop* const end = base + a->length(); - while (base < end) { - MarkSweep::adjust_pointer(base); - base++; - } + ObjArrayKlass_OOP_ITERATE(a, p, MarkSweep::adjust_pointer(p)) return size; } @@ -381,51 +422,27 @@ int objArrayKlass::oop_adjust_pointers(oop obj) { void objArrayKlass::oop_copy_contents(PSPromotionManager* pm, oop obj) { assert(!pm->depth_first(), "invariant"); assert(obj->is_objArray(), "obj must be obj array"); - // Compute oop range - oop* curr = objArrayOop(obj)->base(); - oop* end = curr + objArrayOop(obj)->length(); - // assert(align_object_size(end - (oop*)obj) == oop_size(obj), "checking size"); - assert(align_object_size(pointer_delta(end, obj, sizeof(oop*))) - == oop_size(obj), "checking size"); - - // Iterate over oops - while (curr < end) { - if (PSScavenge::should_scavenge(*curr)) { - pm->claim_or_forward_breadth(curr); - } - ++curr; - } + ObjArrayKlass_OOP_ITERATE( \ + objArrayOop(obj), p, \ + if (PSScavenge::should_scavenge(p)) { \ + pm->claim_or_forward_breadth(p); \ + }) } void objArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { assert(pm->depth_first(), "invariant"); assert(obj->is_objArray(), "obj must be obj array"); - // Compute oop range - oop* curr = objArrayOop(obj)->base(); - oop* end = curr + objArrayOop(obj)->length(); - // assert(align_object_size(end - (oop*)obj) == oop_size(obj), "checking size"); - assert(align_object_size(pointer_delta(end, obj, sizeof(oop*))) - == oop_size(obj), "checking size"); - - // Iterate over oops - while (curr < end) { - if (PSScavenge::should_scavenge(*curr)) { - pm->claim_or_forward_depth(curr); - } - ++curr; - } + ObjArrayKlass_OOP_ITERATE( \ + objArrayOop(obj), p, \ + if (PSScavenge::should_scavenge(p)) { \ + pm->claim_or_forward_depth(p); \ + }) } int objArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) { assert (obj->is_objArray(), "obj must be obj array"); objArrayOop a = objArrayOop(obj); - - oop* const base = a->base(); - oop* const beg_oop = base; - oop* const end_oop = base + a->length(); - for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) { - PSParallelCompact::adjust_pointer(cur_oop); - } + ObjArrayKlass_OOP_ITERATE(a, p, PSParallelCompact::adjust_pointer(p)) return a->object_size(); } @@ -433,13 +450,9 @@ int objArrayKlass::oop_update_pointers(ParCompactionManager* cm, oop obj, HeapWord* beg_addr, HeapWord* end_addr) { assert (obj->is_objArray(), "obj must be obj array"); objArrayOop a = objArrayOop(obj); - - oop* const base = a->base(); - oop* const beg_oop = MAX2((oop*)beg_addr, base); - oop* const end_oop = MIN2((oop*)end_addr, base + a->length()); - for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) { - PSParallelCompact::adjust_pointer(cur_oop); - } + ObjArrayKlass_BOUNDED_OOP_ITERATE( \ + a, p, beg_addr, end_addr, \ + PSParallelCompact::adjust_pointer(p)) return a->object_size(); } #endif // SERIALGC @@ -509,3 +522,4 @@ void objArrayKlass::oop_verify_old_oop(oop obj, oop* p, bool allow_dirty) { RememberedSet::verify_old_oop(obj, p, allow_dirty, true); */ } +void objArrayKlass::oop_verify_old_oop(oop obj, narrowOop* p, bool allow_dirty) {} diff --git a/hotspot/src/share/vm/oops/objArrayKlass.hpp b/hotspot/src/share/vm/oops/objArrayKlass.hpp index a2915ef0d17..6fabe837bc8 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.hpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.hpp @@ -63,6 +63,11 @@ class objArrayKlass : public arrayKlass { // Compute class loader oop class_loader() const { return Klass::cast(bottom_klass())->class_loader(); } + private: + // Either oop or narrowOop depending on UseCompressedOops. + // must be called from within objArrayKlass.cpp + template void do_copy(arrayOop s, T* src, arrayOop d, + T* dst, int length, TRAPS); protected: // Returns the objArrayKlass for n'th dimension. virtual klassOop array_klass_impl(bool or_null, int n, TRAPS); @@ -101,7 +106,9 @@ class objArrayKlass : public arrayKlass { #define ObjArrayKlass_OOP_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \ int oop_oop_iterate##nv_suffix(oop obj, OopClosureType* blk); \ int oop_oop_iterate##nv_suffix##_m(oop obj, OopClosureType* blk, \ - MemRegion mr); + MemRegion mr); \ + int oop_oop_iterate_range##nv_suffix(oop obj, OopClosureType* blk, \ + int start, int end); ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayKlass_OOP_OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_3(ObjArrayKlass_OOP_OOP_ITERATE_DECL) @@ -124,5 +131,6 @@ class objArrayKlass : public arrayKlass { const char* internal_name() const; void oop_verify_on(oop obj, outputStream* st); void oop_verify_old_oop(oop obj, oop* p, bool allow_dirty); + void oop_verify_old_oop(oop obj, narrowOop* p, bool allow_dirty); }; diff --git a/hotspot/src/share/vm/oops/objArrayOop.cpp b/hotspot/src/share/vm/oops/objArrayOop.cpp index c339e2cd8fc..c1ae6830a8e 100644 --- a/hotspot/src/share/vm/oops/objArrayOop.cpp +++ b/hotspot/src/share/vm/oops/objArrayOop.cpp @@ -25,4 +25,12 @@ # include "incls/_precompiled.incl" # include "incls/_objArrayOop.cpp.incl" -// <> +#define ObjArrayOop_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ + \ +int objArrayOopDesc::oop_iterate_range(OopClosureType* blk, int start, int end) { \ + SpecializationStats::record_call(); \ + return ((objArrayKlass*)blueprint())->oop_oop_iterate_range##nv_suffix(this, blk, start, end); \ +} + +ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayOop_OOP_ITERATE_DEFN) +ALL_OOP_OOP_ITERATE_CLOSURES_3(ObjArrayOop_OOP_ITERATE_DEFN) diff --git a/hotspot/src/share/vm/oops/objArrayOop.hpp b/hotspot/src/share/vm/oops/objArrayOop.hpp index b61d7d4d6ba..6f12c0f1fa1 100644 --- a/hotspot/src/share/vm/oops/objArrayOop.hpp +++ b/hotspot/src/share/vm/oops/objArrayOop.hpp @@ -26,20 +26,67 @@ // Evaluating "String arg[10]" will create an objArrayOop. class objArrayOopDesc : public arrayOopDesc { - public: - // Accessing - oop obj_at(int index) const { return *obj_at_addr(index); } - void obj_at_put(int index, oop value) { oop_store(obj_at_addr(index), value); } - oop* base() const { return (oop*) arrayOopDesc::base(T_OBJECT); } + friend class objArrayKlass; + friend class Runtime1; + friend class psPromotionManager; - // Sizing - static int header_size() { return arrayOopDesc::header_size(T_OBJECT); } - static int object_size(int length) { return align_object_size(header_size() + length); } - int object_size() { return object_size(length()); } - - // Returns the address of the index'th element - oop* obj_at_addr(int index) const { + template T* obj_at_addr(int index) const { assert(is_within_bounds(index), "index out of bounds"); - return &base()[index]; + return &((T*)base())[index]; } + + public: + // base is the address following the header. + HeapWord* base() const { return (HeapWord*) arrayOopDesc::base(T_OBJECT); } + + // Accessing + oop obj_at(int index) const { + // With UseCompressedOops decode the narrow oop in the objArray to an + // uncompressed oop. Otherwise this is simply a "*" operator. + if (UseCompressedOops) { + return load_decode_heap_oop(obj_at_addr(index)); + } else { + return load_decode_heap_oop(obj_at_addr(index)); + } + } + + void obj_at_put(int index, oop value) { + if (UseCompressedOops) { + oop_store(obj_at_addr(index), value); + } else { + oop_store(obj_at_addr(index), value); + } + } + // Sizing + static int header_size() { return arrayOopDesc::header_size(T_OBJECT); } + int object_size() { return object_size(length()); } + int array_size() { return array_size(length()); } + + static int object_size(int length) { + // This returns the object size in HeapWords. + return align_object_size(header_size() + array_size(length)); + } + + // Give size of objArrayOop in HeapWords minus the header + static int array_size(int length) { + // Without UseCompressedOops, this is simply: + // oop->length() * HeapWordsPerOop; + // With narrowOops, HeapWordsPerOop is 1/2 or equal 0 as an integer. + // The oop elements are aligned up to wordSize + const int HeapWordsPerOop = heapOopSize/HeapWordSize; + if (HeapWordsPerOop > 0) { + return length * HeapWordsPerOop; + } else { + const int OopsPerHeapWord = HeapWordSize/heapOopSize; + int word_len = align_size_up(length, OopsPerHeapWord)/OopsPerHeapWord; + return word_len; + } + } + + // special iterators for index ranges, returns size of object +#define ObjArrayOop_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \ + int oop_iterate_range(OopClosureType* blk, int start, int end); + + ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayOop_OOP_ITERATE_DECL) + ALL_OOP_OOP_ITERATE_CLOSURES_3(ObjArrayOop_OOP_ITERATE_DECL) }; diff --git a/hotspot/src/share/vm/oops/oop.cpp b/hotspot/src/share/vm/oops/oop.cpp index 6fbecdaf391..badba6d4fc5 100644 --- a/hotspot/src/share/vm/oops/oop.cpp +++ b/hotspot/src/share/vm/oops/oop.cpp @@ -105,10 +105,14 @@ void oopDesc::verify() { } +// XXX verify_old_oop doesn't do anything (should we remove?) void oopDesc::verify_old_oop(oop* p, bool allow_dirty) { blueprint()->oop_verify_old_oop(this, p, allow_dirty); } +void oopDesc::verify_old_oop(narrowOop* p, bool allow_dirty) { + blueprint()->oop_verify_old_oop(this, p, allow_dirty); +} bool oopDesc::partially_loaded() { return blueprint()->oop_partially_loaded(this); @@ -130,3 +134,6 @@ intptr_t oopDesc::slow_identity_hash() { } VerifyOopClosure VerifyOopClosure::verify_oop; + +void VerifyOopClosure::do_oop(oop* p) { VerifyOopClosure::do_oop_work(p); } +void VerifyOopClosure::do_oop(narrowOop* p) { VerifyOopClosure::do_oop_work(p); } diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp index 2c4b07d5491..eb7959096d0 100644 --- a/hotspot/src/share/vm/oops/oop.hpp +++ b/hotspot/src/share/vm/oops/oop.hpp @@ -30,12 +30,12 @@ // no virtual functions allowed // store into oop with store check -void oop_store(oop* p, oop v); -void oop_store(volatile oop* p, oop v); +template void oop_store(T* p, oop v); +template void oop_store(volatile T* p, oop v); // store into oop without store check -void oop_store_without_check(oop* p, oop v); -void oop_store_without_check(volatile oop* p, oop v); +template void oop_store_without_check(T* p, oop v); +template void oop_store_without_check(volatile T* p, oop v); extern bool always_do_update_barrier; @@ -55,7 +55,10 @@ class oopDesc { friend class VMStructs; private: volatile markOop _mark; - klassOop _klass; + union _metadata { + wideKlassOop _klass; + narrowOop _compressed_klass; + } _metadata; // Fast access to barrier set. Must be initialized. static BarrierSet* _bs; @@ -73,16 +76,16 @@ class oopDesc { // objects during a GC) -- requires a valid klass pointer void init_mark(); - klassOop klass() const { return _klass; } - oop* klass_addr() const { return (oop*) &_klass; } + klassOop klass() const; + oop* klass_addr(); + narrowOop* compressed_klass_addr(); void set_klass(klassOop k); // For when the klass pointer is being used as a linked list "next" field. void set_klass_to_list_ptr(oop k); - // size of object header - static int header_size() { return sizeof(oopDesc)/HeapWordSize; } - static int header_size_in_bytes() { return sizeof(oopDesc); } + // size of object header, aligned to platform wordSize + static int header_size() { return sizeof(oopDesc)/HeapWordSize; } Klass* blueprint() const; @@ -119,7 +122,6 @@ class oopDesc { private: // field addresses in oop - // byte/char/bool/short fields are always stored as full words void* field_base(int offset) const; jbyte* byte_field_addr(int offset) const; @@ -130,13 +132,70 @@ class oopDesc { jlong* long_field_addr(int offset) const; jfloat* float_field_addr(int offset) const; jdouble* double_field_addr(int offset) const; + address* address_field_addr(int offset) const; public: - // need this as public for garbage collection - oop* obj_field_addr(int offset) const; + // Need this as public for garbage collection. + template T* obj_field_addr(int offset) const; + // Oop encoding heap max + static const uint64_t OopEncodingHeapMax = + (uint64_t(max_juint) + 1) << LogMinObjAlignmentInBytes; + + static bool is_null(oop obj); + static bool is_null(narrowOop obj); + + // Decode an oop pointer from a narrowOop if compressed. + // These are overloaded for oop and narrowOop as are the other functions + // below so that they can be called in template functions. + static oop decode_heap_oop_not_null(oop v); + static oop decode_heap_oop_not_null(narrowOop v); + static oop decode_heap_oop(oop v); + static oop decode_heap_oop(narrowOop v); + + // Encode an oop pointer to a narrow oop. The or_null versions accept + // null oop pointer, others do not in order to eliminate the + // null checking branches. + static narrowOop encode_heap_oop_not_null(oop v); + static narrowOop encode_heap_oop(oop v); + + // Load an oop out of the Java heap + static narrowOop load_heap_oop(narrowOop* p); + static oop load_heap_oop(oop* p); + + // Load an oop out of Java heap and decode it to an uncompressed oop. + static oop load_decode_heap_oop_not_null(narrowOop* p); + static oop load_decode_heap_oop_not_null(oop* p); + static oop load_decode_heap_oop(narrowOop* p); + static oop load_decode_heap_oop(oop* p); + + // Store an oop into the heap. + static void store_heap_oop(narrowOop* p, narrowOop v); + static void store_heap_oop(oop* p, oop v); + + // Encode oop if UseCompressedOops and store into the heap. + static void encode_store_heap_oop_not_null(narrowOop* p, oop v); + static void encode_store_heap_oop_not_null(oop* p, oop v); + static void encode_store_heap_oop(narrowOop* p, oop v); + static void encode_store_heap_oop(oop* p, oop v); + + static void release_store_heap_oop(volatile narrowOop* p, narrowOop v); + static void release_store_heap_oop(volatile oop* p, oop v); + + static void release_encode_store_heap_oop_not_null(volatile narrowOop* p, oop v); + static void release_encode_store_heap_oop_not_null(volatile oop* p, oop v); + static void release_encode_store_heap_oop(volatile narrowOop* p, oop v); + static void release_encode_store_heap_oop(volatile oop* p, oop v); + + static oop atomic_exchange_oop(oop exchange_value, volatile HeapWord *dest); + static oop atomic_compare_exchange_oop(oop exchange_value, + volatile HeapWord *dest, + oop compare_value); + + // Access to fields in a instanceOop through these methods. oop obj_field(int offset) const; void obj_field_put(int offset, oop value); + void obj_field_raw_put(int offset, oop value); jbyte byte_field(int offset) const; void byte_field_put(int offset, jbyte contents); @@ -162,6 +221,9 @@ class oopDesc { jdouble double_field(int offset) const; void double_field_put(int offset, jdouble contents); + address address_field(int offset) const; + void address_field_put(int offset, address contents); + oop obj_field_acquire(int offset) const; void release_obj_field_put(int offset, oop value); @@ -207,6 +269,7 @@ class oopDesc { void verify_on(outputStream* st); void verify(); void verify_old_oop(oop* p, bool allow_dirty); + void verify_old_oop(narrowOop* p, bool allow_dirty); // tells whether this oop is partially constructed (gc during class loading) bool partially_loaded(); @@ -228,8 +291,8 @@ class oopDesc { bool is_gc_marked() const; // Apply "MarkSweep::mark_and_push" to (the address of) every non-NULL // reference field in "this". - void follow_contents(); - void follow_header(); + void follow_contents(void); + void follow_header(void); #ifndef SERIALGC // Parallel Scavenge @@ -317,6 +380,7 @@ class oopDesc { void set_displaced_mark(markOop m); // for code generation - static int klass_offset_in_bytes() { return offset_of(oopDesc, _klass); } static int mark_offset_in_bytes() { return offset_of(oopDesc, _mark); } + static int klass_offset_in_bytes() { return offset_of(oopDesc, _metadata._klass); } + static int klass_gap_offset_in_bytes(); }; diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index f01dede106b..222c0d4c262 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -25,7 +25,6 @@ // Implementation of all inlined member functions defined in oop.hpp // We need a separate file to avoid circular references - inline void oopDesc::release_set_mark(markOop m) { OrderAccess::release_store_ptr(&_mark, m); } @@ -34,17 +33,54 @@ inline markOop oopDesc::cas_set_mark(markOop new_mark, markOop old_mark) { return (markOop) Atomic::cmpxchg_ptr(new_mark, &_mark, old_mark); } +inline klassOop oopDesc::klass() const { + if (UseCompressedOops) { + return (klassOop)decode_heap_oop_not_null(_metadata._compressed_klass); + // can be NULL in CMS, but isn't supported on CMS yet. + } else { + return _metadata._klass; + } +} + +inline int oopDesc::klass_gap_offset_in_bytes() { + assert(UseCompressedOops, "only applicable to compressed headers"); + return oopDesc::klass_offset_in_bytes() + sizeof(narrowOop); +} + +inline oop* oopDesc::klass_addr() { + // Only used internally and with CMS and will not work with + // UseCompressedOops + assert(!UseCompressedOops, "only supported with uncompressed oops"); + return (oop*) &_metadata._klass; +} + +inline narrowOop* oopDesc::compressed_klass_addr() { + assert(UseCompressedOops, "only called by compressed oops"); + return (narrowOop*) &_metadata._compressed_klass; +} + inline void oopDesc::set_klass(klassOop k) { // since klasses are promoted no store check is needed assert(Universe::is_bootstrapping() || k != NULL, "must be a real klassOop"); assert(Universe::is_bootstrapping() || k->is_klass(), "not a klassOop"); - oop_store_without_check((oop*) &_klass, (oop) k); + if (UseCompressedOops) { + // zero the gap when the klass is set, by zeroing the pointer sized + // part of the union. + _metadata._klass = NULL; + oop_store_without_check(compressed_klass_addr(), (oop)k); + } else { + oop_store_without_check(klass_addr(), (oop) k); + } } inline void oopDesc::set_klass_to_list_ptr(oop k) { // This is only to be used during GC, for from-space objects, so no // barrier is needed. - _klass = (klassOop)k; + if (UseCompressedOops) { + _metadata._compressed_klass = encode_heap_oop_not_null(k); + } else { + _metadata._klass = (klassOop)k; + } } inline void oopDesc::init_mark() { set_mark(markOopDesc::prototype_for_object(this)); } @@ -70,7 +106,7 @@ inline bool oopDesc::is_compiledICHolder() const { return blueprint()->oop_is_ inline void* oopDesc::field_base(int offset) const { return (void*)&((char*)this)[offset]; } -inline oop* oopDesc::obj_field_addr(int offset) const { return (oop*) field_base(offset); } +template inline T* oopDesc::obj_field_addr(int offset) const { return (T*)field_base(offset); } inline jbyte* oopDesc::byte_field_addr(int offset) const { return (jbyte*) field_base(offset); } inline jchar* oopDesc::char_field_addr(int offset) const { return (jchar*) field_base(offset); } inline jboolean* oopDesc::bool_field_addr(int offset) const { return (jboolean*)field_base(offset); } @@ -79,9 +115,158 @@ inline jshort* oopDesc::short_field_addr(int offset) const { return (jshort*) inline jlong* oopDesc::long_field_addr(int offset) const { return (jlong*) field_base(offset); } inline jfloat* oopDesc::float_field_addr(int offset) const { return (jfloat*) field_base(offset); } inline jdouble* oopDesc::double_field_addr(int offset) const { return (jdouble*) field_base(offset); } +inline address* oopDesc::address_field_addr(int offset) const { return (address*) field_base(offset); } -inline oop oopDesc::obj_field(int offset) const { return *obj_field_addr(offset); } -inline void oopDesc::obj_field_put(int offset, oop value) { oop_store(obj_field_addr(offset), value); } + +// Functions for getting and setting oops within instance objects. +// If the oops are compressed, the type passed to these overloaded functions +// is narrowOop. All functions are overloaded so they can be called by +// template functions without conditionals (the compiler instantiates via +// the right type and inlines the appopriate code). + +inline bool oopDesc::is_null(oop obj) { return obj == NULL; } +inline bool oopDesc::is_null(narrowOop obj) { return obj == 0; } + +// Algorithm for encoding and decoding oops from 64 bit pointers to 32 bit +// offset from the heap base. Saving the check for null can save instructions +// in inner GC loops so these are separated. + +inline narrowOop oopDesc::encode_heap_oop_not_null(oop v) { + assert(!is_null(v), "oop value can never be zero"); + address heap_base = Universe::heap_base(); + uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)heap_base, 1)); + assert(OopEncodingHeapMax > pd, "change encoding max if new encoding"); + uint64_t result = pd >> LogMinObjAlignmentInBytes; + assert((result & CONST64(0xffffffff00000000)) == 0, "narrow oop overflow"); + return (narrowOop)result; +} + +inline narrowOop oopDesc::encode_heap_oop(oop v) { + return (is_null(v)) ? (narrowOop)0 : encode_heap_oop_not_null(v); +} + +inline oop oopDesc::decode_heap_oop_not_null(narrowOop v) { + assert(!is_null(v), "narrow oop value can never be zero"); + address heap_base = Universe::heap_base(); + return (oop)(void*)((uintptr_t)heap_base + ((uintptr_t)v << LogMinObjAlignmentInBytes)); +} + +inline oop oopDesc::decode_heap_oop(narrowOop v) { + return is_null(v) ? (oop)NULL : decode_heap_oop_not_null(v); +} + +inline oop oopDesc::decode_heap_oop_not_null(oop v) { return v; } +inline oop oopDesc::decode_heap_oop(oop v) { return v; } + +// Load an oop out of the Java heap as is without decoding. +// Called by GC to check for null before decoding. +inline oop oopDesc::load_heap_oop(oop* p) { return *p; } +inline narrowOop oopDesc::load_heap_oop(narrowOop* p) { return *p; } + +// Load and decode an oop out of the Java heap into a wide oop. +inline oop oopDesc::load_decode_heap_oop_not_null(oop* p) { return *p; } +inline oop oopDesc::load_decode_heap_oop_not_null(narrowOop* p) { + return decode_heap_oop_not_null(*p); +} + +// Load and decode an oop out of the heap accepting null +inline oop oopDesc::load_decode_heap_oop(oop* p) { return *p; } +inline oop oopDesc::load_decode_heap_oop(narrowOop* p) { + return decode_heap_oop(*p); +} + +// Store already encoded heap oop into the heap. +inline void oopDesc::store_heap_oop(oop* p, oop v) { *p = v; } +inline void oopDesc::store_heap_oop(narrowOop* p, narrowOop v) { *p = v; } + +// Encode and store a heap oop. +inline void oopDesc::encode_store_heap_oop_not_null(narrowOop* p, oop v) { + *p = encode_heap_oop_not_null(v); +} +inline void oopDesc::encode_store_heap_oop_not_null(oop* p, oop v) { *p = v; } + +// Encode and store a heap oop allowing for null. +inline void oopDesc::encode_store_heap_oop(narrowOop* p, oop v) { + *p = encode_heap_oop(v); +} +inline void oopDesc::encode_store_heap_oop(oop* p, oop v) { *p = v; } + +// Store heap oop as is for volatile fields. +inline void oopDesc::release_store_heap_oop(volatile oop* p, oop v) { + OrderAccess::release_store_ptr(p, v); +} +inline void oopDesc::release_store_heap_oop(volatile narrowOop* p, + narrowOop v) { + OrderAccess::release_store(p, v); +} + +inline void oopDesc::release_encode_store_heap_oop_not_null( + volatile narrowOop* p, oop v) { + // heap oop is not pointer sized. + OrderAccess::release_store(p, encode_heap_oop_not_null(v)); +} + +inline void oopDesc::release_encode_store_heap_oop_not_null( + volatile oop* p, oop v) { + OrderAccess::release_store_ptr(p, v); +} + +inline void oopDesc::release_encode_store_heap_oop(volatile oop* p, + oop v) { + OrderAccess::release_store_ptr(p, v); +} +inline void oopDesc::release_encode_store_heap_oop( + volatile narrowOop* p, oop v) { + OrderAccess::release_store(p, encode_heap_oop(v)); +} + + +// These functions are only used to exchange oop fields in instances, +// not headers. +inline oop oopDesc::atomic_exchange_oop(oop exchange_value, volatile HeapWord *dest) { + if (UseCompressedOops) { + // encode exchange value from oop to T + narrowOop val = encode_heap_oop(exchange_value); + narrowOop old = (narrowOop)Atomic::xchg(val, (narrowOop*)dest); + // decode old from T to oop + return decode_heap_oop(old); + } else { + return (oop)Atomic::xchg_ptr(exchange_value, (oop*)dest); + } +} + +inline oop oopDesc::atomic_compare_exchange_oop(oop exchange_value, + volatile HeapWord *dest, + oop compare_value) { + if (UseCompressedOops) { + // encode exchange and compare value from oop to T + narrowOop val = encode_heap_oop(exchange_value); + narrowOop cmp = encode_heap_oop(compare_value); + + narrowOop old = (narrowOop) Atomic::cmpxchg(val, (narrowOop*)dest, cmp); + // decode old from T to oop + return decode_heap_oop(old); + } else { + return (oop)Atomic::cmpxchg_ptr(exchange_value, (oop*)dest, compare_value); + } +} + +// In order to put or get a field out of an instance, must first check +// if the field has been compressed and uncompress it. +inline oop oopDesc::obj_field(int offset) const { + return UseCompressedOops ? + load_decode_heap_oop(obj_field_addr(offset)) : + load_decode_heap_oop(obj_field_addr(offset)); +} +inline void oopDesc::obj_field_put(int offset, oop value) { + UseCompressedOops ? oop_store(obj_field_addr(offset), value) : + oop_store(obj_field_addr(offset), value); +} +inline void oopDesc::obj_field_raw_put(int offset, oop value) { + UseCompressedOops ? + encode_store_heap_oop(obj_field_addr(offset), value) : + encode_store_heap_oop(obj_field_addr(offset), value); +} inline jbyte oopDesc::byte_field(int offset) const { return (jbyte) *byte_field_addr(offset); } inline void oopDesc::byte_field_put(int offset, jbyte contents) { *byte_field_addr(offset) = (jint) contents; } @@ -107,8 +292,21 @@ inline void oopDesc::float_field_put(int offset, jfloat contents) { *float_fie inline jdouble oopDesc::double_field(int offset) const { return *double_field_addr(offset); } inline void oopDesc::double_field_put(int offset, jdouble contents) { *double_field_addr(offset) = contents; } -inline oop oopDesc::obj_field_acquire(int offset) const { return (oop)OrderAccess::load_ptr_acquire(obj_field_addr(offset)); } -inline void oopDesc::release_obj_field_put(int offset, oop value) { oop_store((volatile oop*)obj_field_addr(offset), value); } +inline address oopDesc::address_field(int offset) const { return *address_field_addr(offset); } +inline void oopDesc::address_field_put(int offset, address contents) { *address_field_addr(offset) = contents; } + +inline oop oopDesc::obj_field_acquire(int offset) const { + return UseCompressedOops ? + decode_heap_oop((narrowOop) + OrderAccess::load_acquire(obj_field_addr(offset))) + : decode_heap_oop((oop) + OrderAccess::load_ptr_acquire(obj_field_addr(offset))); +} +inline void oopDesc::release_obj_field_put(int offset, oop value) { + UseCompressedOops ? + oop_store((volatile narrowOop*)obj_field_addr(offset), value) : + oop_store((volatile oop*) obj_field_addr(offset), value); +} inline jbyte oopDesc::byte_field_acquire(int offset) const { return OrderAccess::load_acquire(byte_field_addr(offset)); } inline void oopDesc::release_byte_field_put(int offset, jbyte contents) { OrderAccess::release_store(byte_field_addr(offset), contents); } @@ -134,7 +332,6 @@ inline void oopDesc::release_float_field_put(int offset, jfloat contents) { Or inline jdouble oopDesc::double_field_acquire(int offset) const { return OrderAccess::load_acquire(double_field_addr(offset)); } inline void oopDesc::release_double_field_put(int offset, jdouble contents) { OrderAccess::release_store(double_field_addr(offset), contents); } - inline int oopDesc::size_given_klass(Klass* klass) { int lh = klass->layout_helper(); int s = lh >> LogHeapWordSize; // deliver size scaled by wordSize @@ -200,7 +397,7 @@ inline int oopDesc::size_given_klass(Klass* klass) { // technique) we will need to suitably modify the assertion. assert((s == klass->oop_size(this)) || (((UseParNewGC || UseParallelGC) && - Universe::heap()->is_gc_active()) && + Universe::heap()->is_gc_active()) && (is_typeArray() || (is_objArray() && is_forwarded()))), "wrong array object size"); @@ -224,52 +421,58 @@ inline bool oopDesc::is_parsable() { return blueprint()->oop_is_parsable(this); } - -inline void update_barrier_set(oop *p, oop v) { +inline void update_barrier_set(void* p, oop v) { assert(oopDesc::bs() != NULL, "Uninitialized bs in oop!"); oopDesc::bs()->write_ref_field(p, v); } - -inline void oop_store(oop* p, oop v) { +template inline void oop_store(T* p, oop v) { if (always_do_update_barrier) { - oop_store((volatile oop*)p, v); + oop_store((volatile T*)p, v); } else { - *p = v; + oopDesc::encode_store_heap_oop(p, v); update_barrier_set(p, v); } } -inline void oop_store(volatile oop* p, oop v) { +template inline void oop_store(volatile T* p, oop v) { // Used by release_obj_field_put, so use release_store_ptr. - OrderAccess::release_store_ptr(p, v); - update_barrier_set((oop *)p, v); + oopDesc::release_encode_store_heap_oop(p, v); + update_barrier_set((void*)p, v); } -inline void oop_store_without_check(oop* p, oop v) { - // XXX YSR FIX ME!!! - if (always_do_update_barrier) { - oop_store(p, v); - } else { - assert(!Universe::heap()->barrier_set()->write_ref_needs_barrier(p, v), - "oop store without store check failed"); - *p = v; - } -} - -// When it absolutely has to get there. -inline void oop_store_without_check(volatile oop* p, oop v) { +template inline void oop_store_without_check(T* p, oop v) { // XXX YSR FIX ME!!! if (always_do_update_barrier) { oop_store(p, v); } else { - assert(!Universe::heap()->barrier_set()-> - write_ref_needs_barrier((oop *)p, v), + assert(!Universe::heap()->barrier_set()->write_ref_needs_barrier(p, v), "oop store without store check failed"); - OrderAccess::release_store_ptr(p, v); + oopDesc::encode_store_heap_oop(p, v); } } +// When it absolutely has to get there. +template inline void oop_store_without_check(volatile T* p, oop v) { + // XXX YSR FIX ME!!! + if (always_do_update_barrier) { + oop_store(p, v); + } else { + assert(!Universe::heap()->barrier_set()->write_ref_needs_barrier((T*)p, v), + "oop store without store check failed"); + oopDesc::release_encode_store_heap_oop(p, v); + } +} + +// Should replace *addr = oop assignments where addr type depends on UseCompressedOops +// (without having to remember the function name this calls). +inline void oop_store_raw(HeapWord* addr, oop value) { + if (UseCompressedOops) { + oopDesc::encode_store_heap_oop((narrowOop*)addr, value); + } else { + oopDesc::encode_store_heap_oop((oop*)addr, value); + } +} // Used only for markSweep, scavenging inline bool oopDesc::is_gc_marked() const { @@ -340,15 +543,17 @@ inline bool oopDesc::is_unlocked_oop() const { if (!Universe::heap()->is_in_reserved(this)) return false; return mark()->is_unlocked(); } - - #endif // PRODUCT inline void oopDesc::follow_header() { - MarkSweep::mark_and_push((oop*)&_klass); + if (UseCompressedOops) { + MarkSweep::mark_and_push(compressed_klass_addr()); + } else { + MarkSweep::mark_and_push(klass_addr()); + } } -inline void oopDesc::follow_contents() { +inline void oopDesc::follow_contents(void) { assert (is_gc_marked(), "should be marked"); blueprint()->oop_follow_contents(this); } @@ -362,7 +567,6 @@ inline bool oopDesc::is_forwarded() const { return mark()->is_marked(); } - // Used by scavengers inline void oopDesc::forward_to(oop p) { assert(Universe::heap()->is_in_reserved(p), @@ -384,8 +588,9 @@ inline bool oopDesc::cas_forward_to(oop p, markOop compare) { // Note that the forwardee is not the same thing as the displaced_mark. // The forwardee is used when copying during scavenge and mark-sweep. // It does need to clear the low two locking- and GC-related bits. -inline oop oopDesc::forwardee() const { return (oop) mark()->decode_pointer(); } - +inline oop oopDesc::forwardee() const { + return (oop) mark()->decode_pointer(); +} inline bool oopDesc::has_displaced_mark() const { return mark()->has_displaced_mark_helper(); @@ -432,17 +637,24 @@ inline intptr_t oopDesc::identity_hash() { } } - inline void oopDesc::oop_iterate_header(OopClosure* blk) { - blk->do_oop((oop*)&_klass); + if (UseCompressedOops) { + blk->do_oop(compressed_klass_addr()); + } else { + blk->do_oop(klass_addr()); + } } - inline void oopDesc::oop_iterate_header(OopClosure* blk, MemRegion mr) { - if (mr.contains(&_klass)) blk->do_oop((oop*)&_klass); + if (UseCompressedOops) { + if (mr.contains(compressed_klass_addr())) { + blk->do_oop(compressed_klass_addr()); + } + } else { + if (mr.contains(klass_addr())) blk->do_oop(klass_addr()); + } } - inline int oopDesc::adjust_pointers() { debug_only(int check_size = size()); int s = blueprint()->oop_adjust_pointers(this); @@ -451,7 +663,11 @@ inline int oopDesc::adjust_pointers() { } inline void oopDesc::adjust_header() { - MarkSweep::adjust_pointer((oop*)&_klass); + if (UseCompressedOops) { + MarkSweep::adjust_pointer(compressed_klass_addr()); + } else { + MarkSweep::adjust_pointer(klass_addr()); + } } #define OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ diff --git a/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp b/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp index 13f93e27d5b..1db005569f8 100644 --- a/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp @@ -67,8 +67,8 @@ inline void oopDesc::update_contents(ParCompactionManager* cm, // update_header(); // The klass has moved. Is the location of the klass // within the limits? - if ((((HeapWord*)&_klass) >= begin_limit) && - (((HeapWord*)&_klass) < end_limit)) { + if ((((HeapWord*)&_metadata._klass) >= begin_limit) && + (((HeapWord*)&_metadata._klass) < end_limit)) { set_klass(updated_klass); } @@ -89,7 +89,11 @@ inline void oopDesc::follow_contents(ParCompactionManager* cm) { // Used by parallel old GC. inline void oopDesc::follow_header(ParCompactionManager* cm) { - PSParallelCompact::mark_and_push(cm, (oop*)&_klass); + if (UseCompressedOops) { + PSParallelCompact::mark_and_push(cm, compressed_klass_addr()); + } else { + PSParallelCompact::mark_and_push(cm, klass_addr()); + } } inline oop oopDesc::forward_to_atomic(oop p) { @@ -114,9 +118,18 @@ inline oop oopDesc::forward_to_atomic(oop p) { } inline void oopDesc::update_header() { - PSParallelCompact::adjust_pointer((oop*)&_klass); + if (UseCompressedOops) { + PSParallelCompact::adjust_pointer(compressed_klass_addr()); + } else { + PSParallelCompact::adjust_pointer(klass_addr()); + } } inline void oopDesc::update_header(HeapWord* beg_addr, HeapWord* end_addr) { - PSParallelCompact::adjust_pointer((oop*)&_klass, beg_addr, end_addr); + if (UseCompressedOops) { + PSParallelCompact::adjust_pointer(compressed_klass_addr(), + beg_addr, end_addr); + } else { + PSParallelCompact::adjust_pointer(klass_addr(), beg_addr, end_addr); + } } diff --git a/hotspot/src/share/vm/oops/oopsHierarchy.hpp b/hotspot/src/share/vm/oops/oopsHierarchy.hpp index 6aab383bb6f..32c9823272e 100644 --- a/hotspot/src/share/vm/oops/oopsHierarchy.hpp +++ b/hotspot/src/share/vm/oops/oopsHierarchy.hpp @@ -26,21 +26,25 @@ // This hierarchy is a representation hierarchy, i.e. if A is a superclass // of B, A's representation is a prefix of B's representation. +typedef juint narrowOop; // Offset instead of address for an oop within a java object +typedef class klassOopDesc* wideKlassOop; // to keep SA happy and unhandled oop + // detector happy. + #ifndef CHECK_UNHANDLED_OOPS -typedef class oopDesc* oop; +typedef class oopDesc* oop; typedef class instanceOopDesc* instanceOop; -typedef class methodOopDesc* methodOop; -typedef class constMethodOopDesc* constMethodOop; -typedef class methodDataOopDesc* methodDataOop; -typedef class arrayOopDesc* arrayOop; -typedef class constantPoolOopDesc* constantPoolOop; -typedef class constantPoolCacheOopDesc* constantPoolCacheOop; -typedef class objArrayOopDesc* objArrayOop; -typedef class typeArrayOopDesc* typeArrayOop; -typedef class symbolOopDesc* symbolOop; -typedef class klassOopDesc* klassOop; -typedef class markOopDesc* markOop; +typedef class methodOopDesc* methodOop; +typedef class constMethodOopDesc* constMethodOop; +typedef class methodDataOopDesc* methodDataOop; +typedef class arrayOopDesc* arrayOop; +typedef class objArrayOopDesc* objArrayOop; +typedef class typeArrayOopDesc* typeArrayOop; +typedef class constantPoolOopDesc* constantPoolOop; +typedef class constantPoolCacheOopDesc* constantPoolCacheOop; +typedef class symbolOopDesc* symbolOop; +typedef class klassOopDesc* klassOop; +typedef class markOopDesc* markOop; typedef class compiledICHolderOopDesc* compiledICHolderOop; #else @@ -172,9 +176,9 @@ class arrayKlassKlass; class objArrayKlassKlass; class typeArrayKlassKlass; class arrayKlass; -class constantPoolKlass; -class constantPoolCacheKlass; class objArrayKlass; class typeArrayKlass; -class symbolKlass; +class constantPoolKlass; +class constantPoolCacheKlass; +class symbolKlass; class compiledICHolderKlass; diff --git a/hotspot/src/share/vm/opto/addnode.cpp b/hotspot/src/share/vm/opto/addnode.cpp index 2369792a1bf..35e3846ce16 100644 --- a/hotspot/src/share/vm/opto/addnode.cpp +++ b/hotspot/src/share/vm/opto/addnode.cpp @@ -70,9 +70,14 @@ static bool commute( Node *add, int con_left, int con_right ) { // Convert "Load+x" into "x+Load". // Now check for loads - if( in2->is_Load() ) return false; - // Left is a Load and Right is not; move it right. - if( in1->is_Load() ) { + if (in2->is_Load()) { + if (!in1->is_Load()) { + // already x+Load to return + return false; + } + // both are loads, so fall through to sort inputs by idx + } else if( in1->is_Load() ) { + // Left is a Load and Right is not; move it right. add->swap_edges(1, 2); return true; } diff --git a/hotspot/src/share/vm/opto/buildOopMap.cpp b/hotspot/src/share/vm/opto/buildOopMap.cpp index 2116c404dda..8d3adc78d71 100644 --- a/hotspot/src/share/vm/opto/buildOopMap.cpp +++ b/hotspot/src/share/vm/opto/buildOopMap.cpp @@ -315,6 +315,26 @@ OopMap *OopFlow::build_oop_map( Node *n, int max_reg, PhaseRegAlloc *regalloc, i } } + } else if( t->isa_narrowoop() ) { + assert( !OptoReg::is_valid(_callees[reg]), "oop can't be callee save" ); + // Check for a legal reg name in the oopMap and bailout if it is not. + if (!omap->legal_vm_reg_name(r)) { + regalloc->C->record_method_not_compilable("illegal oopMap register name"); + continue; + } + if( mcall ) { + // Outgoing argument GC mask responsibility belongs to the callee, + // not the caller. Inspect the inputs to the call, to see if + // this live-range is one of them. + uint cnt = mcall->tf()->domain()->cnt(); + uint j; + for( j = TypeFunc::Parms; j < cnt; j++) + if( mcall->in(j) == def ) + break; // reaching def is an argument oop + if( j < cnt ) // arg oops dont go in GC map + continue; // Continue on to the next register + } + omap->set_narrowoop(r); } else if( OptoReg::is_valid(_callees[reg])) { // callee-save? // It's a callee-save value assert( dup_check[_callees[reg]]==0, "trying to callee save same reg twice" ); diff --git a/hotspot/src/share/vm/opto/callnode.hpp b/hotspot/src/share/vm/opto/callnode.hpp index a6cc8e5280e..daa572e78a8 100644 --- a/hotspot/src/share/vm/opto/callnode.hpp +++ b/hotspot/src/share/vm/opto/callnode.hpp @@ -725,7 +725,8 @@ public: // Conservatively small estimate of offset of first non-header byte. int minimum_header_size() { - return is_AllocateArray() ? sizeof(arrayOopDesc) : sizeof(oopDesc); + return is_AllocateArray() ? arrayOopDesc::base_offset_in_bytes(T_BYTE) : + instanceOopDesc::base_offset_in_bytes(); } // Return the corresponding initialization barrier (or null if none). diff --git a/hotspot/src/share/vm/opto/cfgnode.cpp b/hotspot/src/share/vm/opto/cfgnode.cpp index f68e117b2c0..30ab6a59eed 100644 --- a/hotspot/src/share/vm/opto/cfgnode.cpp +++ b/hotspot/src/share/vm/opto/cfgnode.cpp @@ -848,7 +848,7 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const { // Until we have harmony between classes and interfaces in the type // lattice, we must tread carefully around phis which implicitly // convert the one to the other. - const TypeInstPtr* ttip = _type->isa_instptr(); + const TypeInstPtr* ttip = _type->isa_narrowoop() ? _type->isa_narrowoop()->make_oopptr()->isa_instptr() :_type->isa_instptr(); bool is_intf = false; if (ttip != NULL) { ciKlass* k = ttip->klass(); @@ -867,7 +867,7 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const { // of all the input types. The lattice is not distributive in // such cases. Ward off asserts in type.cpp by refusing to do // meets between interfaces and proper classes. - const TypeInstPtr* tiip = ti->isa_instptr(); + const TypeInstPtr* tiip = ti->isa_narrowoop() ? ti->is_narrowoop()->make_oopptr()->isa_instptr() : ti->isa_instptr(); if (tiip) { bool ti_is_intf = false; ciKlass* k = tiip->klass(); @@ -924,12 +924,15 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const { // class-typed Phi and an interface flows in, it's possible that the meet & // join report an interface back out. This isn't possible but happens // because the type system doesn't interact well with interfaces. - const TypeInstPtr *jtip = jt->isa_instptr(); + const TypeInstPtr *jtip = jt->isa_narrowoop() ? jt->isa_narrowoop()->make_oopptr()->isa_instptr() : jt->isa_instptr(); if( jtip && ttip ) { if( jtip->is_loaded() && jtip->klass()->is_interface() && - ttip->is_loaded() && !ttip->klass()->is_interface() ) + ttip->is_loaded() && !ttip->klass()->is_interface() ) { // Happens in a CTW of rt.jar, 320-341, no extra flags - { assert(ft == ttip->cast_to_ptr_type(jtip->ptr()), ""); jt = ft; } + assert(ft == ttip->cast_to_ptr_type(jtip->ptr()) || + ft->isa_narrowoop() && ft->isa_narrowoop()->make_oopptr() == ttip->cast_to_ptr_type(jtip->ptr()), ""); + jt = ft; + } } if (jt != ft && jt->base() == ft->base()) { if (jt->isa_int() && @@ -1416,7 +1419,8 @@ PhiNode::LoopSafety PhiNode::simple_data_loop_check(Node *in) const { // Check inputs of phi's inputs also. // It is much less expensive then full graph walk. uint cnt = in->req(); - for (uint i = 1; i < cnt; ++i) { + uint i = (in->is_Proj() && !in->is_CFG()) ? 0 : 1; + for (; i < cnt; ++i) { Node* m = in->in(i); if (m == (Node*)this) return UnsafeLoop; // Unsafe loop @@ -1464,7 +1468,8 @@ bool PhiNode::is_unsafe_data_reference(Node *in) const { while (nstack.size() != 0) { Node* n = nstack.pop(); uint cnt = n->req(); - for (uint i = 1; i < cnt; i++) { // Only data paths + uint i = (n->is_Proj() && !n->is_CFG()) ? 0 : 1; + for (; i < cnt; i++) { Node* m = n->in(i); if (m == (Node*)this) { return true; // Data loop @@ -2014,6 +2019,28 @@ Node *CreateExNode::Identity( PhaseTransform *phase ) { } //============================================================================= +//------------------------------Value------------------------------------------ +// Check for being unreachable. +const Type *NeverBranchNode::Value( PhaseTransform *phase ) const { + if (!in(0) || in(0)->is_top()) return Type::TOP; + return bottom_type(); +} + +//------------------------------Ideal------------------------------------------ +// Check for no longer being part of a loop +Node *NeverBranchNode::Ideal(PhaseGVN *phase, bool can_reshape) { + if (can_reshape && !in(0)->is_Loop()) { + // Dead code elimination can sometimes delete this projection so + // if it's not there, there's nothing to do. + Node* fallthru = proj_out(0); + if (fallthru != NULL) { + phase->is_IterGVN()->subsume_node(fallthru, in(0)); + } + return phase->C->top(); + } + return NULL; +} + #ifndef PRODUCT void NeverBranchNode::format( PhaseRegAlloc *ra_, outputStream *st) const { st->print("%s", Name()); diff --git a/hotspot/src/share/vm/opto/cfgnode.hpp b/hotspot/src/share/vm/opto/cfgnode.hpp index 0c4eedb9b99..f4c4b0e2fae 100644 --- a/hotspot/src/share/vm/opto/cfgnode.hpp +++ b/hotspot/src/share/vm/opto/cfgnode.hpp @@ -244,6 +244,8 @@ public: MultiBranchNode( uint required ) : MultiNode(required) { init_class_id(Class_MultiBranch); } + // returns required number of users to be well formed. + virtual int required_outcnt() const = 0; }; //------------------------------IfNode----------------------------------------- @@ -333,6 +335,7 @@ public: virtual const Type *bottom_type() const { return TypeTuple::IFBOTH; } virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual const Type *Value( PhaseTransform *phase ) const; + virtual int required_outcnt() const { return 2; } virtual const RegMask &out_RegMask() const; void dominated_by(Node* prev_dom, PhaseIterGVN* igvn); int is_range_check(Node* &range, Node* &index, jint &offset); @@ -391,6 +394,7 @@ public: virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual const Type *bottom_type() const; virtual bool pinned() const { return true; } + virtual int required_outcnt() const { return _size; } }; //------------------------------JumpNode--------------------------------------- @@ -504,7 +508,9 @@ public: virtual int Opcode() const; virtual bool pinned() const { return true; }; virtual const Type *bottom_type() const { return TypeTuple::IFBOTH; } - + virtual const Type *Value( PhaseTransform *phase ) const; + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual int required_outcnt() const { return 2; } virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { } virtual uint size(PhaseRegAlloc *ra_) const { return 0; } #ifndef PRODUCT diff --git a/hotspot/src/share/vm/opto/chaitin.cpp b/hotspot/src/share/vm/opto/chaitin.cpp index 33ca24ba5b6..bc31285bf56 100644 --- a/hotspot/src/share/vm/opto/chaitin.cpp +++ b/hotspot/src/share/vm/opto/chaitin.cpp @@ -682,6 +682,7 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) { break; case Op_RegF: case Op_RegI: + case Op_RegN: case Op_RegFlags: case 0: // not an ideal register lrg.set_num_regs(1); diff --git a/hotspot/src/share/vm/opto/classes.hpp b/hotspot/src/share/vm/opto/classes.hpp index 0c5f53ba307..e61bdd73168 100644 --- a/hotspot/src/share/vm/opto/classes.hpp +++ b/hotspot/src/share/vm/opto/classes.hpp @@ -64,6 +64,7 @@ macro(CMoveF) macro(CMoveI) macro(CMoveL) macro(CMoveP) +macro(CmpN) macro(CmpD) macro(CmpD3) macro(CmpF) @@ -77,7 +78,9 @@ macro(CmpU) macro(CompareAndSwapI) macro(CompareAndSwapL) macro(CompareAndSwapP) +macro(CompareAndSwapN) macro(Con) +macro(ConN) macro(ConD) macro(ConF) macro(ConI) @@ -100,6 +103,7 @@ macro(CosD) macro(CountedLoop) macro(CountedLoopEnd) macro(CreateEx) +macro(DecodeN) macro(DivD) macro(DivF) macro(DivI) @@ -107,6 +111,7 @@ macro(DivL) macro(DivMod) macro(DivModI) macro(DivModL) +macro(EncodeP) macro(ExpD) macro(FastLock) macro(FastUnlock) @@ -133,6 +138,7 @@ macro(LoadL_unaligned) macro(LoadPLocked) macro(LoadLLocked) macro(LoadP) +macro(LoadN) macro(LoadRange) macro(LoadS) macro(Lock) @@ -158,6 +164,7 @@ macro(MoveL2D) macro(MoveD2L) macro(MulD) macro(MulF) +macro(MulHiL) macro(MulI) macro(MulL) macro(Multi) @@ -201,6 +208,7 @@ macro(StoreF) macro(StoreI) macro(StoreL) macro(StoreP) +macro(StoreN) macro(StrComp) macro(SubD) macro(SubF) diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 3fe43b53095..6559cb4c621 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -456,7 +456,15 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr } TraceTime t1("Total compilation time", &_t_totalCompilation, TimeCompiler, TimeCompiler2); TraceTime t2(NULL, &_t_methodCompilation, TimeCompiler, false); - set_print_assembly(PrintOptoAssembly || _method->should_print_assembly()); + bool print_opto_assembly = PrintOptoAssembly || _method->has_option("PrintOptoAssembly"); + if (!print_opto_assembly) { + bool print_assembly = (PrintAssembly || _method->should_print_assembly()); + if (print_assembly && !Disassembler::can_decode()) { + tty->print_cr("PrintAssembly request changed to PrintOptoAssembly"); + print_opto_assembly = true; + } + } + set_print_assembly(print_opto_assembly); #endif if (ProfileTraps) { @@ -1023,6 +1031,10 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const { tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,ta->klass(),false,offset, ta->instance_id()); } // Arrays of known objects become arrays of unknown objects. + if (ta->elem()->isa_narrowoop() && ta->elem() != TypeNarrowOop::BOTTOM) { + const TypeAry *tary = TypeAry::make(TypeNarrowOop::BOTTOM, ta->size()); + tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,NULL,false,offset, ta->instance_id()); + } if (ta->elem()->isa_oopptr() && ta->elem() != TypeInstPtr::BOTTOM) { const TypeAry *tary = TypeAry::make(TypeInstPtr::BOTTOM, ta->size()); tj = ta = TypeAryPtr::make(ptr,ta->const_oop(),tary,NULL,false,offset, ta->instance_id()); @@ -1061,7 +1073,7 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const { } // Canonicalize the holder of this field ciInstanceKlass *k = to->klass()->as_instance_klass(); - if (offset >= 0 && offset < oopDesc::header_size() * wordSize) { + if (offset >= 0 && offset < instanceOopDesc::base_offset_in_bytes()) { // First handle header references such as a LoadKlassNode, even if the // object's klass is unloaded at compile time (4965979). tj = to = TypeInstPtr::make(TypePtr::BotPTR, env()->Object_klass(), false, NULL, offset, to->instance_id()); @@ -1302,7 +1314,7 @@ Compile::AliasType* Compile::find_alias_type(const TypePtr* adr_type, bool no_cr // Check for final instance fields. const TypeInstPtr* tinst = flat->isa_instptr(); - if (tinst && tinst->offset() >= oopDesc::header_size() * wordSize) { + if (tinst && tinst->offset() >= instanceOopDesc::base_offset_in_bytes()) { ciInstanceKlass *k = tinst->klass()->as_instance_klass(); ciField* field = k->get_field_by_offset(tinst->offset(), false); // Set field() and is_rewritable() attributes. @@ -1723,6 +1735,8 @@ void Compile::dump_asm(int *pcs, uint pc_limit) { starts_bundle = '+'; } + if (WizardMode) n->dump(); + if( !n->is_Region() && // Dont print in the Assembly !n->is_Phi() && // a few noisely useless nodes !n->is_Proj() && @@ -1747,6 +1761,8 @@ void Compile::dump_asm(int *pcs, uint pc_limit) { // then back up and print it if (valid_bundle_info(n) && node_bundling(n)->use_unconditional_delay()) { assert(delay != NULL, "no unconditional delay instruction"); + if (WizardMode) delay->dump(); + if (node_bundling(delay)->starts_bundle()) starts_bundle = '+'; if (pcs && n->_idx < pc_limit) @@ -1811,7 +1827,7 @@ struct Final_Reshape_Counts : public StackObj { static bool oop_offset_is_sane(const TypeInstPtr* tp) { ciInstanceKlass *k = tp->klass()->as_instance_klass(); // Make sure the offset goes inside the instance layout. - return (uint)tp->offset() < (uint)(oopDesc::header_size() + k->nonstatic_field_size())*wordSize; + return k->contains_field_offset(tp->offset()); // Note that OffsetBot and OffsetTop are very negative. } @@ -1938,7 +1954,9 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) { case Op_CompareAndSwapI: case Op_CompareAndSwapL: case Op_CompareAndSwapP: + case Op_CompareAndSwapN: case Op_StoreP: + case Op_StoreN: case Op_LoadB: case Op_LoadC: case Op_LoadI: @@ -1948,6 +1966,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) { case Op_LoadPLocked: case Op_LoadLLocked: case Op_LoadP: + case Op_LoadN: case Op_LoadRange: case Op_LoadS: { handle_mem: @@ -1962,10 +1981,6 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) { #endif break; } - case Op_If: - case Op_CountedLoopEnd: - fpu._tests.push(n); // Collect CFG split points - break; case Op_AddP: { // Assert sane base pointers const Node *addp = n->in(AddPNode::Address); @@ -2064,10 +2079,12 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &fpu ) { default: assert( !n->is_Call(), "" ); assert( !n->is_Mem(), "" ); - if( n->is_If() || n->is_PCTable() ) - fpu._tests.push(n); // Collect CFG split points break; } + + // Collect CFG split points + if (n->is_MultiBranch()) + fpu._tests.push(n); } //------------------------------final_graph_reshaping_walk--------------------- @@ -2146,19 +2163,18 @@ bool Compile::final_graph_reshaping() { // Check for unreachable (from below) code (i.e., infinite loops). for( uint i = 0; i < fpu._tests.size(); i++ ) { - Node *n = fpu._tests[i]; - assert( n->is_PCTable() || n->is_If(), "either PCTables or IfNodes" ); - // Get number of CFG targets; 2 for IfNodes or _size for PCTables. + MultiBranchNode *n = fpu._tests[i]->as_MultiBranch(); + // Get number of CFG targets. // Note that PCTables include exception targets after calls. - uint expected_kids = n->is_PCTable() ? n->as_PCTable()->_size : 2; - if (n->outcnt() != expected_kids) { + uint required_outcnt = n->required_outcnt(); + if (n->outcnt() != required_outcnt) { // Check for a few special cases. Rethrow Nodes never take the // 'fall-thru' path, so expected kids is 1 less. if (n->is_PCTable() && n->in(0) && n->in(0)->in(0)) { if (n->in(0)->in(0)->is_Call()) { CallNode *call = n->in(0)->in(0)->as_Call(); if (call->entry_point() == OptoRuntime::rethrow_stub()) { - expected_kids--; // Rethrow always has 1 less kid + required_outcnt--; // Rethrow always has 1 less kid } else if (call->req() > TypeFunc::Parms && call->is_CallDynamicJava()) { // Check for null receiver. In such case, the optimizer has @@ -2168,7 +2184,7 @@ bool Compile::final_graph_reshaping() { Node *arg0 = call->in(TypeFunc::Parms); if (arg0->is_Type() && arg0->as_Type()->type()->higher_equal(TypePtr::NULL_PTR)) { - expected_kids--; + required_outcnt--; } } else if (call->entry_point() == OptoRuntime::new_array_Java() && call->req() > TypeFunc::Parms+1 && @@ -2179,13 +2195,13 @@ bool Compile::final_graph_reshaping() { Node *arg1 = call->in(TypeFunc::Parms+1); if (arg1->is_Type() && arg1->as_Type()->type()->join(TypeInt::POS)->empty()) { - expected_kids--; + required_outcnt--; } } } } - // Recheck with a better notion of 'expected_kids' - if (n->outcnt() != expected_kids) { + // Recheck with a better notion of 'required_outcnt' + if (n->outcnt() != required_outcnt) { record_method_not_compilable("malformed control flow"); return true; // Not all targets reachable! } diff --git a/hotspot/src/share/vm/opto/connode.cpp b/hotspot/src/share/vm/opto/connode.cpp index de3eed6f0e2..c542ce397e4 100644 --- a/hotspot/src/share/vm/opto/connode.cpp +++ b/hotspot/src/share/vm/opto/connode.cpp @@ -35,6 +35,7 @@ uint ConNode::hash() const { //------------------------------make------------------------------------------- ConNode *ConNode::make( Compile* C, const Type *t ) { + if (t->isa_narrowoop()) return new (C, 1) ConNNode( t->is_narrowoop() ); switch( t->basic_type() ) { case T_INT: return new (C, 1) ConINode( t->is_int() ); case T_ARRAY: return new (C, 1) ConPNode( t->is_aryptr() ); @@ -461,7 +462,8 @@ static bool can_cause_alias(Node *n, PhaseTransform *phase) { possible_alias = n->is_Phi() || opc == Op_CheckCastPP || opc == Op_StorePConditional || - opc == Op_CompareAndSwapP; + opc == Op_CompareAndSwapP || + opc == Op_CompareAndSwapN; } return possible_alias; } @@ -549,6 +551,73 @@ Node *CheckCastPPNode::Ideal(PhaseGVN *phase, bool can_reshape){ return (in(0) && remove_dead_region(phase, can_reshape)) ? this : NULL; } + +Node* DecodeNNode::Identity(PhaseTransform* phase) { + const Type *t = phase->type( in(1) ); + if( t == Type::TOP ) return in(1); + + if (in(1)->Opcode() == Op_EncodeP) { + // (DecodeN (EncodeP p)) -> p + return in(1)->in(1); + } + return this; +} + +const Type *DecodeNNode::Value( PhaseTransform *phase ) const { + if (phase->type( in(1) ) == TypeNarrowOop::NULL_PTR) { + return TypePtr::NULL_PTR; + } + return bottom_type(); +} + +Node* DecodeNNode::decode(PhaseGVN* phase, Node* value) { + if (value->Opcode() == Op_EncodeP) { + // (DecodeN (EncodeP p)) -> p + return value->in(1); + } + const Type* newtype = value->bottom_type(); + if (newtype == TypeNarrowOop::NULL_PTR) { + return phase->transform(new (phase->C, 1) ConPNode(TypePtr::NULL_PTR)); + } else { + return phase->transform(new (phase->C, 2) DecodeNNode(value, newtype->is_narrowoop()->make_oopptr())); + } +} + +Node* EncodePNode::Identity(PhaseTransform* phase) { + const Type *t = phase->type( in(1) ); + if( t == Type::TOP ) return in(1); + + if (in(1)->Opcode() == Op_DecodeN) { + // (EncodeP (DecodeN p)) -> p + return in(1)->in(1); + } + return this; +} + +const Type *EncodePNode::Value( PhaseTransform *phase ) const { + if (phase->type( in(1) ) == TypePtr::NULL_PTR) { + return TypeNarrowOop::NULL_PTR; + } + return bottom_type(); +} + +Node* EncodePNode::encode(PhaseGVN* phase, Node* value) { + if (value->Opcode() == Op_DecodeN) { + // (EncodeP (DecodeN p)) -> p + return value->in(1); + } + const Type* newtype = value->bottom_type(); + if (newtype == TypePtr::NULL_PTR) { + return phase->transform(new (phase->C, 1) ConNNode(TypeNarrowOop::NULL_PTR)); + } else if (newtype->isa_oopptr()) { + return phase->transform(new (phase->C, 2) EncodePNode(value, newtype->is_oopptr()->make_narrowoop())); + } else { + ShouldNotReachHere(); + return NULL; // to make C++ compiler happy. + } +} + + //============================================================================= //------------------------------Identity--------------------------------------- Node *Conv2BNode::Identity( PhaseTransform *phase ) { diff --git a/hotspot/src/share/vm/opto/connode.hpp b/hotspot/src/share/vm/opto/connode.hpp index 1c1b96a19a0..247a364c845 100644 --- a/hotspot/src/share/vm/opto/connode.hpp +++ b/hotspot/src/share/vm/opto/connode.hpp @@ -78,6 +78,20 @@ public: }; +//------------------------------ConNNode-------------------------------------- +// Simple narrow oop constants +class ConNNode : public ConNode { +public: + ConNNode( const TypeNarrowOop *t ) : ConNode(t) {} + virtual int Opcode() const; + + static ConNNode* make( Compile *C, ciObject* con ) { + return new (C, 1) ConNNode( TypeNarrowOop::make_from_constant(con) ); + } + +}; + + //------------------------------ConLNode--------------------------------------- // Simple long constants class ConLNode : public ConNode { @@ -225,10 +239,7 @@ public: // cast pointer to pointer (different type) class CastPPNode: public ConstraintCastNode { public: - CastPPNode (Node *n, const Type *t ): ConstraintCastNode(n, t) { - // Only CastPP is safe. CastII can cause optimizer loops. - init_flags(Flag_is_dead_loop_safe); - } + CastPPNode (Node *n, const Type *t ): ConstraintCastNode(n, t) {} virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegP; } virtual Node *Ideal_DU_postCCP( PhaseCCP * ); @@ -240,10 +251,10 @@ class CheckCastPPNode: public TypeNode { public: CheckCastPPNode( Node *c, Node *n, const Type *t ) : TypeNode(t,2) { init_class_id(Class_CheckCastPP); - init_flags(Flag_is_dead_loop_safe); init_req(0, c); init_req(1, n); } + virtual Node *Identity( PhaseTransform *phase ); virtual const Type *Value( PhaseTransform *phase ) const; virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); @@ -254,6 +265,45 @@ public: //virtual Node *Ideal_DU_postCCP( PhaseCCP * ); }; + +//------------------------------EncodeP-------------------------------- +// Encodes an oop pointers into its compressed form +// Takes an extra argument which is the real heap base as a long which +// may be useful for code generation in the backend. +class EncodePNode : public TypeNode { + public: + EncodePNode(Node* value, const Type* type): + TypeNode(type, 2) { + init_req(0, NULL); + init_req(1, value); + } + virtual int Opcode() const; + virtual Node *Identity( PhaseTransform *phase ); + virtual const Type *Value( PhaseTransform *phase ) const; + virtual uint ideal_reg() const { return Op_RegN; } + + static Node* encode(PhaseGVN* phase, Node* value); +}; + +//------------------------------DecodeN-------------------------------- +// Converts a narrow oop into a real oop ptr. +// Takes an extra argument which is the real heap base as a long which +// may be useful for code generation in the backend. +class DecodeNNode : public TypeNode { + public: + DecodeNNode(Node* value, const Type* type): + TypeNode(type, 2) { + init_req(0, NULL); + init_req(1, value); + } + virtual int Opcode() const; + virtual Node *Identity( PhaseTransform *phase ); + virtual const Type *Value( PhaseTransform *phase ) const; + virtual uint ideal_reg() const { return Op_RegP; } + + static Node* decode(PhaseGVN* phase, Node* value); +}; + //------------------------------Conv2BNode------------------------------------- // Convert int/pointer to a Boolean. Map zero to zero, all else to 1. class Conv2BNode : public Node { diff --git a/hotspot/src/share/vm/opto/divnode.cpp b/hotspot/src/share/vm/opto/divnode.cpp index 5443495ff95..d05ef9fd316 100644 --- a/hotspot/src/share/vm/opto/divnode.cpp +++ b/hotspot/src/share/vm/opto/divnode.cpp @@ -30,70 +30,86 @@ #include "incls/_divnode.cpp.incl" #include -// Implement the integer constant divide -> long multiply transform found in -// "Division by Invariant Integers using Multiplication" -// by Granlund and Montgomery -static Node *transform_int_divide_to_long_multiply( PhaseGVN *phase, Node *dividend, int divisor ) { +//----------------------magic_int_divide_constants----------------------------- +// Compute magic multiplier and shift constant for converting a 32 bit divide +// by constant into a multiply/shift/add series. Return false if calculations +// fail. +// +// Borrowed almost verbatum from Hacker's Delight by Henry S. Warren, Jr. with +// minor type name and parameter changes. +static bool magic_int_divide_constants(jint d, jint &M, jint &s) { + int32_t p; + uint32_t ad, anc, delta, q1, r1, q2, r2, t; + const uint32_t two31 = 0x80000000L; // 2**31. + + ad = ABS(d); + if (d == 0 || d == 1) return false; + t = two31 + ((uint32_t)d >> 31); + anc = t - 1 - t%ad; // Absolute value of nc. + p = 31; // Init. p. + q1 = two31/anc; // Init. q1 = 2**p/|nc|. + r1 = two31 - q1*anc; // Init. r1 = rem(2**p, |nc|). + q2 = two31/ad; // Init. q2 = 2**p/|d|. + r2 = two31 - q2*ad; // Init. r2 = rem(2**p, |d|). + do { + p = p + 1; + q1 = 2*q1; // Update q1 = 2**p/|nc|. + r1 = 2*r1; // Update r1 = rem(2**p, |nc|). + if (r1 >= anc) { // (Must be an unsigned + q1 = q1 + 1; // comparison here). + r1 = r1 - anc; + } + q2 = 2*q2; // Update q2 = 2**p/|d|. + r2 = 2*r2; // Update r2 = rem(2**p, |d|). + if (r2 >= ad) { // (Must be an unsigned + q2 = q2 + 1; // comparison here). + r2 = r2 - ad; + } + delta = ad - r2; + } while (q1 < delta || (q1 == delta && r1 == 0)); + + M = q2 + 1; + if (d < 0) M = -M; // Magic number and + s = p - 32; // shift amount to return. + + return true; +} + +//--------------------------transform_int_divide------------------------------- +// Convert a division by constant divisor into an alternate Ideal graph. +// Return NULL if no transformation occurs. +static Node *transform_int_divide( PhaseGVN *phase, Node *dividend, jint divisor ) { // Check for invalid divisors - assert( divisor != 0 && divisor != min_jint && divisor != 1, - "bad divisor for transforming to long multiply" ); + assert( divisor != 0 && divisor != min_jint, + "bad divisor for transforming to long multiply" ); - // Compute l = ceiling(log2(d)) - // presumes d is more likely small bool d_pos = divisor >= 0; - int d = d_pos ? divisor : -divisor; - unsigned ud = (unsigned)d; + jint d = d_pos ? divisor : -divisor; const int N = 32; - int l = log2_intptr(d-1)+1; - int sh_post = l; - - const uint64_t U1 = (uint64_t)1; - - // Cliff pointed out how to prevent overflow (from the paper) - uint64_t m_low = (((U1 << l) - ud) << N) / ud + (U1 << N); - uint64_t m_high = ((((U1 << l) - ud) << N) + (U1 << (l+1))) / ud + (U1 << N); - - // Reduce to lowest terms - for ( ; sh_post > 0; sh_post-- ) { - uint64_t m_low_1 = m_low >> 1; - uint64_t m_high_1 = m_high >> 1; - if ( m_low_1 >= m_high_1 ) - break; - m_low = m_low_1; - m_high = m_high_1; - } // Result - Node *q; + Node *q = NULL; - // division by +/- 1 if (d == 1) { - // Filtered out as identity above - if (d_pos) - return NULL; - - // Just negate the value - else { + // division by +/- 1 + if (!d_pos) { + // Just negate the value q = new (phase->C, 3) SubINode(phase->intcon(0), dividend); } - } - - // division by +/- a power of 2 - else if ( is_power_of_2(d) ) { + } else if ( is_power_of_2(d) ) { + // division by +/- a power of 2 // See if we can simply do a shift without rounding bool needs_rounding = true; const Type *dt = phase->type(dividend); const TypeInt *dti = dt->isa_int(); - - // we don't need to round a positive dividend - if (dti && dti->_lo >= 0) + if (dti && dti->_lo >= 0) { + // we don't need to round a positive dividend needs_rounding = false; - - // An AND mask of sufficient size clears the low bits and - // I can avoid rounding. - else if( dividend->Opcode() == Op_AndI ) { + } else if( dividend->Opcode() == Op_AndI ) { + // An AND mask of sufficient size clears the low bits and + // I can avoid rounding. const TypeInt *andconi = phase->type( dividend->in(2) )->isa_int(); if( andconi && andconi->is_con(-d) ) { dividend = dividend->in(1); @@ -102,47 +118,271 @@ static Node *transform_int_divide_to_long_multiply( PhaseGVN *phase, Node *divid } // Add rounding to the shift to handle the sign bit - if( needs_rounding ) { - Node *t1 = phase->transform(new (phase->C, 3) RShiftINode(dividend, phase->intcon(l - 1))); - Node *t2 = phase->transform(new (phase->C, 3) URShiftINode(t1, phase->intcon(N - l))); - dividend = phase->transform(new (phase->C, 3) AddINode(dividend, t2)); + int l = log2_intptr(d-1)+1; + if (needs_rounding) { + // Divide-by-power-of-2 can be made into a shift, but you have to do + // more math for the rounding. You need to add 0 for positive + // numbers, and "i-1" for negative numbers. Example: i=4, so the + // shift is by 2. You need to add 3 to negative dividends and 0 to + // positive ones. So (-7+3)>>2 becomes -1, (-4+3)>>2 becomes -1, + // (-2+3)>>2 becomes 0, etc. + + // Compute 0 or -1, based on sign bit + Node *sign = phase->transform(new (phase->C, 3) RShiftINode(dividend, phase->intcon(N - 1))); + // Mask sign bit to the low sign bits + Node *round = phase->transform(new (phase->C, 3) URShiftINode(sign, phase->intcon(N - l))); + // Round up before shifting + dividend = phase->transform(new (phase->C, 3) AddINode(dividend, round)); } + // Shift for division q = new (phase->C, 3) RShiftINode(dividend, phase->intcon(l)); - if (!d_pos) + if (!d_pos) { q = new (phase->C, 3) SubINode(phase->intcon(0), phase->transform(q)); + } + } else { + // Attempt the jint constant divide -> multiply transform found in + // "Division by Invariant Integers using Multiplication" + // by Granlund and Montgomery + // See also "Hacker's Delight", chapter 10 by Warren. + + jint magic_const; + jint shift_const; + if (magic_int_divide_constants(d, magic_const, shift_const)) { + Node *magic = phase->longcon(magic_const); + Node *dividend_long = phase->transform(new (phase->C, 2) ConvI2LNode(dividend)); + + // Compute the high half of the dividend x magic multiplication + Node *mul_hi = phase->transform(new (phase->C, 3) MulLNode(dividend_long, magic)); + + if (magic_const < 0) { + mul_hi = phase->transform(new (phase->C, 3) RShiftLNode(mul_hi, phase->intcon(N))); + mul_hi = phase->transform(new (phase->C, 2) ConvL2INode(mul_hi)); + + // The magic multiplier is too large for a 32 bit constant. We've adjusted + // it down by 2^32, but have to add 1 dividend back in after the multiplication. + // This handles the "overflow" case described by Granlund and Montgomery. + mul_hi = phase->transform(new (phase->C, 3) AddINode(dividend, mul_hi)); + + // Shift over the (adjusted) mulhi + if (shift_const != 0) { + mul_hi = phase->transform(new (phase->C, 3) RShiftINode(mul_hi, phase->intcon(shift_const))); + } + } else { + // No add is required, we can merge the shifts together. + mul_hi = phase->transform(new (phase->C, 3) RShiftLNode(mul_hi, phase->intcon(N + shift_const))); + mul_hi = phase->transform(new (phase->C, 2) ConvL2INode(mul_hi)); + } + + // Get a 0 or -1 from the sign of the dividend. + Node *addend0 = mul_hi; + Node *addend1 = phase->transform(new (phase->C, 3) RShiftINode(dividend, phase->intcon(N-1))); + + // If the divisor is negative, swap the order of the input addends; + // this has the effect of negating the quotient. + if (!d_pos) { + Node *temp = addend0; addend0 = addend1; addend1 = temp; + } + + // Adjust the final quotient by subtracting -1 (adding 1) + // from the mul_hi. + q = new (phase->C, 3) SubINode(addend0, addend1); + } } - // division by something else - else if (m_high < (U1 << (N-1))) { - Node *t1 = phase->transform(new (phase->C, 2) ConvI2LNode(dividend)); - Node *t2 = phase->transform(new (phase->C, 3) MulLNode(t1, phase->longcon(m_high))); - Node *t3 = phase->transform(new (phase->C, 3) RShiftLNode(t2, phase->intcon(sh_post+N))); - Node *t4 = phase->transform(new (phase->C, 2) ConvL2INode(t3)); - Node *t5 = phase->transform(new (phase->C, 3) RShiftINode(dividend, phase->intcon(N-1))); + return q; +} - q = new (phase->C, 3) SubINode(d_pos ? t4 : t5, d_pos ? t5 : t4); +//---------------------magic_long_divide_constants----------------------------- +// Compute magic multiplier and shift constant for converting a 64 bit divide +// by constant into a multiply/shift/add series. Return false if calculations +// fail. +// +// Borrowed almost verbatum from Hacker's Delight by Henry S. Warren, Jr. with +// minor type name and parameter changes. Adjusted to 64 bit word width. +static bool magic_long_divide_constants(jlong d, jlong &M, jint &s) { + int64_t p; + uint64_t ad, anc, delta, q1, r1, q2, r2, t; + const uint64_t two63 = 0x8000000000000000LL; // 2**63. + + ad = ABS(d); + if (d == 0 || d == 1) return false; + t = two63 + ((uint64_t)d >> 63); + anc = t - 1 - t%ad; // Absolute value of nc. + p = 63; // Init. p. + q1 = two63/anc; // Init. q1 = 2**p/|nc|. + r1 = two63 - q1*anc; // Init. r1 = rem(2**p, |nc|). + q2 = two63/ad; // Init. q2 = 2**p/|d|. + r2 = two63 - q2*ad; // Init. r2 = rem(2**p, |d|). + do { + p = p + 1; + q1 = 2*q1; // Update q1 = 2**p/|nc|. + r1 = 2*r1; // Update r1 = rem(2**p, |nc|). + if (r1 >= anc) { // (Must be an unsigned + q1 = q1 + 1; // comparison here). + r1 = r1 - anc; + } + q2 = 2*q2; // Update q2 = 2**p/|d|. + r2 = 2*r2; // Update r2 = rem(2**p, |d|). + if (r2 >= ad) { // (Must be an unsigned + q2 = q2 + 1; // comparison here). + r2 = r2 - ad; + } + delta = ad - r2; + } while (q1 < delta || (q1 == delta && r1 == 0)); + + M = q2 + 1; + if (d < 0) M = -M; // Magic number and + s = p - 64; // shift amount to return. + + return true; +} + +//---------------------long_by_long_mulhi-------------------------------------- +// Generate ideal node graph for upper half of a 64 bit x 64 bit multiplication +static Node *long_by_long_mulhi( PhaseGVN *phase, Node *dividend, jlong magic_const) { + // If the architecture supports a 64x64 mulhi, there is + // no need to synthesize it in ideal nodes. + if (Matcher::has_match_rule(Op_MulHiL)) { + Node *v = phase->longcon(magic_const); + return new (phase->C, 3) MulHiLNode(dividend, v); } - // This handles that case where m_high is >= 2**(N-1). In that case, - // we subtract out 2**N from the multiply and add it in later as - // "dividend" in the equation (t5). This case computes the same result - // as the immediately preceeding case, save that rounding and overflow - // are accounted for. - else { - Node *t1 = phase->transform(new (phase->C, 2) ConvI2LNode(dividend)); - Node *t2 = phase->transform(new (phase->C, 3) MulLNode(t1, phase->longcon(m_high - (U1 << N)))); - Node *t3 = phase->transform(new (phase->C, 3) RShiftLNode(t2, phase->intcon(N))); - Node *t4 = phase->transform(new (phase->C, 2) ConvL2INode(t3)); - Node *t5 = phase->transform(new (phase->C, 3) AddINode(dividend, t4)); - Node *t6 = phase->transform(new (phase->C, 3) RShiftINode(t5, phase->intcon(sh_post))); - Node *t7 = phase->transform(new (phase->C, 3) RShiftINode(dividend, phase->intcon(N-1))); + const int N = 64; - q = new (phase->C, 3) SubINode(d_pos ? t6 : t7, d_pos ? t7 : t6); + Node *u_hi = phase->transform(new (phase->C, 3) RShiftLNode(dividend, phase->intcon(N / 2))); + Node *u_lo = phase->transform(new (phase->C, 3) AndLNode(dividend, phase->longcon(0xFFFFFFFF))); + + Node *v_hi = phase->longcon(magic_const >> N/2); + Node *v_lo = phase->longcon(magic_const & 0XFFFFFFFF); + + Node *hihi_product = phase->transform(new (phase->C, 3) MulLNode(u_hi, v_hi)); + Node *hilo_product = phase->transform(new (phase->C, 3) MulLNode(u_hi, v_lo)); + Node *lohi_product = phase->transform(new (phase->C, 3) MulLNode(u_lo, v_hi)); + Node *lolo_product = phase->transform(new (phase->C, 3) MulLNode(u_lo, v_lo)); + + Node *t1 = phase->transform(new (phase->C, 3) URShiftLNode(lolo_product, phase->intcon(N / 2))); + Node *t2 = phase->transform(new (phase->C, 3) AddLNode(hilo_product, t1)); + Node *t3 = phase->transform(new (phase->C, 3) RShiftLNode(t2, phase->intcon(N / 2))); + Node *t4 = phase->transform(new (phase->C, 3) AndLNode(t2, phase->longcon(0xFFFFFFFF))); + Node *t5 = phase->transform(new (phase->C, 3) AddLNode(t4, lohi_product)); + Node *t6 = phase->transform(new (phase->C, 3) RShiftLNode(t5, phase->intcon(N / 2))); + Node *t7 = phase->transform(new (phase->C, 3) AddLNode(t3, hihi_product)); + + return new (phase->C, 3) AddLNode(t7, t6); +} + + +//--------------------------transform_long_divide------------------------------ +// Convert a division by constant divisor into an alternate Ideal graph. +// Return NULL if no transformation occurs. +static Node *transform_long_divide( PhaseGVN *phase, Node *dividend, jlong divisor ) { + // Check for invalid divisors + assert( divisor != 0L && divisor != min_jlong, + "bad divisor for transforming to long multiply" ); + + bool d_pos = divisor >= 0; + jlong d = d_pos ? divisor : -divisor; + const int N = 64; + + // Result + Node *q = NULL; + + if (d == 1) { + // division by +/- 1 + if (!d_pos) { + // Just negate the value + q = new (phase->C, 3) SubLNode(phase->longcon(0), dividend); + } + } else if ( is_power_of_2_long(d) ) { + + // division by +/- a power of 2 + + // See if we can simply do a shift without rounding + bool needs_rounding = true; + const Type *dt = phase->type(dividend); + const TypeLong *dtl = dt->isa_long(); + + if (dtl && dtl->_lo > 0) { + // we don't need to round a positive dividend + needs_rounding = false; + } else if( dividend->Opcode() == Op_AndL ) { + // An AND mask of sufficient size clears the low bits and + // I can avoid rounding. + const TypeLong *andconl = phase->type( dividend->in(2) )->isa_long(); + if( andconl && andconl->is_con(-d)) { + dividend = dividend->in(1); + needs_rounding = false; + } + } + + // Add rounding to the shift to handle the sign bit + int l = log2_long(d-1)+1; + if (needs_rounding) { + // Divide-by-power-of-2 can be made into a shift, but you have to do + // more math for the rounding. You need to add 0 for positive + // numbers, and "i-1" for negative numbers. Example: i=4, so the + // shift is by 2. You need to add 3 to negative dividends and 0 to + // positive ones. So (-7+3)>>2 becomes -1, (-4+3)>>2 becomes -1, + // (-2+3)>>2 becomes 0, etc. + + // Compute 0 or -1, based on sign bit + Node *sign = phase->transform(new (phase->C, 3) RShiftLNode(dividend, phase->intcon(N - 1))); + // Mask sign bit to the low sign bits + Node *round = phase->transform(new (phase->C, 3) URShiftLNode(sign, phase->intcon(N - l))); + // Round up before shifting + dividend = phase->transform(new (phase->C, 3) AddLNode(dividend, round)); + } + + // Shift for division + q = new (phase->C, 3) RShiftLNode(dividend, phase->intcon(l)); + + if (!d_pos) { + q = new (phase->C, 3) SubLNode(phase->longcon(0), phase->transform(q)); + } + } else { + // Attempt the jlong constant divide -> multiply transform found in + // "Division by Invariant Integers using Multiplication" + // by Granlund and Montgomery + // See also "Hacker's Delight", chapter 10 by Warren. + + jlong magic_const; + jint shift_const; + if (magic_long_divide_constants(d, magic_const, shift_const)) { + // Compute the high half of the dividend x magic multiplication + Node *mul_hi = phase->transform(long_by_long_mulhi(phase, dividend, magic_const)); + + // The high half of the 128-bit multiply is computed. + if (magic_const < 0) { + // The magic multiplier is too large for a 64 bit constant. We've adjusted + // it down by 2^64, but have to add 1 dividend back in after the multiplication. + // This handles the "overflow" case described by Granlund and Montgomery. + mul_hi = phase->transform(new (phase->C, 3) AddLNode(dividend, mul_hi)); + } + + // Shift over the (adjusted) mulhi + if (shift_const != 0) { + mul_hi = phase->transform(new (phase->C, 3) RShiftLNode(mul_hi, phase->intcon(shift_const))); + } + + // Get a 0 or -1 from the sign of the dividend. + Node *addend0 = mul_hi; + Node *addend1 = phase->transform(new (phase->C, 3) RShiftLNode(dividend, phase->intcon(N-1))); + + // If the divisor is negative, swap the order of the input addends; + // this has the effect of negating the quotient. + if (!d_pos) { + Node *temp = addend0; addend0 = addend1; addend1 = temp; + } + + // Adjust the final quotient by subtracting -1 (adding 1) + // from the mul_hi. + q = new (phase->C, 3) SubLNode(addend0, addend1); + } } - return (q); + return q; } //============================================================================= @@ -164,7 +404,7 @@ Node *DivINode::Ideal(PhaseGVN *phase, bool can_reshape) { const TypeInt *ti = t->isa_int(); if( !ti ) return NULL; if( !ti->is_con() ) return NULL; - int i = ti->get_con(); // Get divisor + jint i = ti->get_con(); // Get divisor if (i == 0) return NULL; // Dividing by zero constant does not idealize @@ -173,7 +413,7 @@ Node *DivINode::Ideal(PhaseGVN *phase, bool can_reshape) { // Dividing by MININT does not optimize as a power-of-2 shift. if( i == min_jint ) return NULL; - return transform_int_divide_to_long_multiply( phase, in(1), i ); + return transform_int_divide( phase, in(1), i ); } //------------------------------Value------------------------------------------ @@ -255,85 +495,22 @@ Node *DivLNode::Ideal( PhaseGVN *phase, bool can_reshape) { if (in(0) && remove_dead_region(phase, can_reshape)) return this; const Type *t = phase->type( in(2) ); - if( t == TypeLong::ONE ) // Identity? + if( t == TypeLong::ONE ) // Identity? return NULL; // Skip it - const TypeLong *ti = t->isa_long(); - if( !ti ) return NULL; - if( !ti->is_con() ) return NULL; - jlong i = ti->get_con(); // Get divisor - if( i ) set_req(0, NULL); // Dividing by a not-zero constant; no faulting + const TypeLong *tl = t->isa_long(); + if( !tl ) return NULL; + if( !tl->is_con() ) return NULL; + jlong l = tl->get_con(); // Get divisor + + if (l == 0) return NULL; // Dividing by zero constant does not idealize + + set_req(0,NULL); // Dividing by a not-zero constant; no faulting // Dividing by MININT does not optimize as a power-of-2 shift. - if( i == min_jlong ) return NULL; + if( l == min_jlong ) return NULL; - // Check for negative power of 2 divisor, if so, negate it and set a flag - // to indicate result needs to be negated. Note that negating the dividend - // here does not work when it has the value MININT - Node *dividend = in(1); - bool negate_res = false; - if (is_power_of_2_long(-i)) { - i = -i; // Flip divisor - negate_res = true; - } - - // Check for power of 2 - if (!is_power_of_2_long(i)) // Is divisor a power of 2? - return NULL; // Not a power of 2 - - // Compute number of bits to shift - int log_i = log2_long(i); - - // See if we can simply do a shift without rounding - bool needs_rounding = true; - const Type *dt = phase->type(dividend); - const TypeLong *dtl = dt->isa_long(); - - if (dtl && dtl->_lo > 0) { - // we don't need to round a positive dividend - needs_rounding = false; - } else if( dividend->Opcode() == Op_AndL ) { - // An AND mask of sufficient size clears the low bits and - // I can avoid rounding. - const TypeLong *andconi = phase->type( dividend->in(2) )->isa_long(); - if( andconi && - andconi->is_con() && - andconi->get_con() == -i ) { - dividend = dividend->in(1); - needs_rounding = false; - } - } - - if (!needs_rounding) { - Node *result = new (phase->C, 3) RShiftLNode(dividend, phase->intcon(log_i)); - if (negate_res) { - result = phase->transform(result); - result = new (phase->C, 3) SubLNode(phase->longcon(0), result); - } - return result; - } - - // Divide-by-power-of-2 can be made into a shift, but you have to do - // more math for the rounding. You need to add 0 for positive - // numbers, and "i-1" for negative numbers. Example: i=4, so the - // shift is by 2. You need to add 3 to negative dividends and 0 to - // positive ones. So (-7+3)>>2 becomes -1, (-4+3)>>2 becomes -1, - // (-2+3)>>2 becomes 0, etc. - - // Compute 0 or -1, based on sign bit - Node *sign = phase->transform(new (phase->C, 3) RShiftLNode(dividend,phase->intcon(63))); - // Mask sign bit to the low sign bits - Node *round = phase->transform(new (phase->C, 3) AndLNode(sign,phase->longcon(i-1))); - // Round up before shifting - Node *sum = phase->transform(new (phase->C, 3) AddLNode(dividend,round)); - // Shift for division - Node *result = new (phase->C, 3) RShiftLNode(sum, phase->intcon(log_i)); - if (negate_res) { - result = phase->transform(result); - result = new (phase->C, 3) SubLNode(phase->longcon(0), result); - } - - return result; + return transform_long_divide( phase, in(1), l ); } //------------------------------Value------------------------------------------ @@ -421,7 +598,7 @@ const Type *DivFNode::Value( PhaseTransform *phase ) const { // x/x == 1, we ignore 0/0. // Note: if t1 and t2 are zero then result is NaN (JVMS page 213) - // does not work for variables because of NaN's + // Does not work for variables because of NaN's if( phase->eqv( in(1), in(2) ) && t1->base() == Type::FloatCon) if (!g_isnan(t1->getf()) && g_isfinite(t1->getf()) && t1->getf() != 0.0) // could be negative ZERO or NaN return TypeF::ONE; @@ -491,7 +668,7 @@ Node *DivFNode::Ideal(PhaseGVN *phase, bool can_reshape) { //============================================================================= //------------------------------Value------------------------------------------ // An DivDNode divides its inputs. The third input is a Control input, used to -// prvent hoisting the divide above an unsafe test. +// prevent hoisting the divide above an unsafe test. const Type *DivDNode::Value( PhaseTransform *phase ) const { // Either input is TOP ==> the result is TOP const Type *t1 = phase->type( in(1) ); @@ -615,10 +792,10 @@ Node *ModINode::Ideal(PhaseGVN *phase, bool can_reshape) { hook->init_req(0, x); // Add a use to x to prevent him from dying // Generate code to reduce X rapidly to nearly 2^k-1. for( int i = 0; i < trip_count; i++ ) { - Node *xl = phase->transform( new (phase->C, 3) AndINode(x,divisor) ); - Node *xh = phase->transform( new (phase->C, 3) RShiftINode(x,phase->intcon(k)) ); // Must be signed - x = phase->transform( new (phase->C, 3) AddINode(xh,xl) ); - hook->set_req(0, x); + Node *xl = phase->transform( new (phase->C, 3) AndINode(x,divisor) ); + Node *xh = phase->transform( new (phase->C, 3) RShiftINode(x,phase->intcon(k)) ); // Must be signed + x = phase->transform( new (phase->C, 3) AddINode(xh,xl) ); + hook->set_req(0, x); } // Generate sign-fixup code. Was original value positive? @@ -675,18 +852,21 @@ Node *ModINode::Ideal(PhaseGVN *phase, bool can_reshape) { hook->init_req(0, in(1)); // Divide using the transform from DivI to MulL - Node *divide = phase->transform( transform_int_divide_to_long_multiply( phase, in(1), pos_con ) ); + Node *result = transform_int_divide( phase, in(1), pos_con ); + if (result != NULL) { + Node *divide = phase->transform(result); - // Re-multiply, using a shift if this is a power of two - Node *mult = NULL; + // Re-multiply, using a shift if this is a power of two + Node *mult = NULL; - if( log2_con >= 0 ) - mult = phase->transform( new (phase->C, 3) LShiftINode( divide, phase->intcon( log2_con ) ) ); - else - mult = phase->transform( new (phase->C, 3) MulINode( divide, phase->intcon( pos_con ) ) ); + if( log2_con >= 0 ) + mult = phase->transform( new (phase->C, 3) LShiftINode( divide, phase->intcon( log2_con ) ) ); + else + mult = phase->transform( new (phase->C, 3) MulINode( divide, phase->intcon( pos_con ) ) ); - // Finally, subtract the multiplied divided value from the original - Node *result = new (phase->C, 3) SubINode( in(1), mult ); + // Finally, subtract the multiplied divided value from the original + result = new (phase->C, 3) SubINode( in(1), mult ); + } // Now remove the bogus extra edges used to keep things alive if (can_reshape) { @@ -748,73 +928,126 @@ Node *ModLNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Get the modulus const Type *t = phase->type( in(2) ); if( t == Type::TOP ) return NULL; - const TypeLong *ti = t->is_long(); + const TypeLong *tl = t->is_long(); // Check for useless control input // Check for excluding mod-zero case - if( in(0) && (ti->_hi < 0 || ti->_lo > 0) ) { + if( in(0) && (tl->_hi < 0 || tl->_lo > 0) ) { set_req(0, NULL); // Yank control input return this; } // See if we are MOD'ing by 2^k or 2^k-1. - if( !ti->is_con() ) return NULL; - jlong con = ti->get_con(); - bool m1 = false; - if( !is_power_of_2_long(con) ) { // Not 2^k - if( !is_power_of_2_long(con+1) ) // Not 2^k-1? - return NULL; // No interesting mod hacks - m1 = true; // Found 2^k-1 - con++; // Convert to 2^k form - } - uint k = log2_long(con); // Extract k + if( !tl->is_con() ) return NULL; + jlong con = tl->get_con(); + + Node *hook = new (phase->C, 1) Node(1); // Expand mod - if( !m1 ) { // Case 2^k - } else { // Case 2^k-1 + if( con >= 0 && con < max_jlong && is_power_of_2_long(con+1) ) { + uint k = log2_long(con); // Extract k + // Basic algorithm by David Detlefs. See fastmod_long.java for gory details. // Used to help a popular random number generator which does a long-mod // of 2^31-1 and shows up in SpecJBB and SciMark. static int unroll_factor[] = { 999, 999, 61, 30, 20, 15, 12, 10, 8, 7, 6, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 /*past here we assume 1 forever*/}; int trip_count = 1; if( k < ARRAY_SIZE(unroll_factor)) trip_count = unroll_factor[k]; - if( trip_count > 4 ) return NULL; // Too much unrolling - if (ConditionalMoveLimit == 0) return NULL; // cmov is required - Node *x = in(1); // Value being mod'd - Node *divisor = in(2); // Also is mask + // If the unroll factor is not too large, and if conditional moves are + // ok, then use this case + if( trip_count <= 5 && ConditionalMoveLimit != 0 ) { + Node *x = in(1); // Value being mod'd + Node *divisor = in(2); // Also is mask - Node *hook = new (phase->C, 1) Node(x); - // Generate code to reduce X rapidly to nearly 2^k-1. - for( int i = 0; i < trip_count; i++ ) { + hook->init_req(0, x); // Add a use to x to prevent him from dying + // Generate code to reduce X rapidly to nearly 2^k-1. + for( int i = 0; i < trip_count; i++ ) { Node *xl = phase->transform( new (phase->C, 3) AndLNode(x,divisor) ); Node *xh = phase->transform( new (phase->C, 3) RShiftLNode(x,phase->intcon(k)) ); // Must be signed x = phase->transform( new (phase->C, 3) AddLNode(xh,xl) ); hook->set_req(0, x); // Add a use to x to prevent him from dying - } - // Generate sign-fixup code. Was original value positive? - // long hack_res = (i >= 0) ? divisor : CONST64(1); - Node *cmp1 = phase->transform( new (phase->C, 3) CmpLNode( in(1), phase->longcon(0) ) ); - Node *bol1 = phase->transform( new (phase->C, 2) BoolNode( cmp1, BoolTest::ge ) ); - Node *cmov1= phase->transform( new (phase->C, 4) CMoveLNode(bol1, phase->longcon(1), divisor, TypeLong::LONG) ); - // if( x >= hack_res ) x -= divisor; - Node *sub = phase->transform( new (phase->C, 3) SubLNode( x, divisor ) ); - Node *cmp2 = phase->transform( new (phase->C, 3) CmpLNode( x, cmov1 ) ); - Node *bol2 = phase->transform( new (phase->C, 2) BoolNode( cmp2, BoolTest::ge ) ); - // Convention is to not transform the return value of an Ideal - // since Ideal is expected to return a modified 'this' or a new node. - Node *cmov2= new (phase->C, 4) CMoveLNode(bol2, x, sub, TypeLong::LONG); - // cmov2 is now the mod + } - // Now remove the bogus extra edges used to keep things alive - if (can_reshape) { - phase->is_IterGVN()->remove_dead_node(hook); - } else { - hook->set_req(0, NULL); // Just yank bogus edge during Parse phase + // Generate sign-fixup code. Was original value positive? + // long hack_res = (i >= 0) ? divisor : CONST64(1); + Node *cmp1 = phase->transform( new (phase->C, 3) CmpLNode( in(1), phase->longcon(0) ) ); + Node *bol1 = phase->transform( new (phase->C, 2) BoolNode( cmp1, BoolTest::ge ) ); + Node *cmov1= phase->transform( new (phase->C, 4) CMoveLNode(bol1, phase->longcon(1), divisor, TypeLong::LONG) ); + // if( x >= hack_res ) x -= divisor; + Node *sub = phase->transform( new (phase->C, 3) SubLNode( x, divisor ) ); + Node *cmp2 = phase->transform( new (phase->C, 3) CmpLNode( x, cmov1 ) ); + Node *bol2 = phase->transform( new (phase->C, 2) BoolNode( cmp2, BoolTest::ge ) ); + // Convention is to not transform the return value of an Ideal + // since Ideal is expected to return a modified 'this' or a new node. + Node *cmov2= new (phase->C, 4) CMoveLNode(bol2, x, sub, TypeLong::LONG); + // cmov2 is now the mod + + // Now remove the bogus extra edges used to keep things alive + if (can_reshape) { + phase->is_IterGVN()->remove_dead_node(hook); + } else { + hook->set_req(0, NULL); // Just yank bogus edge during Parse phase + } + return cmov2; } - return cmov2; } - return NULL; + + // Fell thru, the unroll case is not appropriate. Transform the modulo + // into a long multiply/int multiply/subtract case + + // Cannot handle mod 0, and min_jint isn't handled by the transform + if( con == 0 || con == min_jlong ) return NULL; + + // Get the absolute value of the constant; at this point, we can use this + jlong pos_con = (con >= 0) ? con : -con; + + // integer Mod 1 is always 0 + if( pos_con == 1 ) return new (phase->C, 1) ConLNode(TypeLong::ZERO); + + int log2_con = -1; + + // If this is a power of two, they maybe we can mask it + if( is_power_of_2_long(pos_con) ) { + log2_con = log2_long(pos_con); + + const Type *dt = phase->type(in(1)); + const TypeLong *dtl = dt->isa_long(); + + // See if this can be masked, if the dividend is non-negative + if( dtl && dtl->_lo >= 0 ) + return ( new (phase->C, 3) AndLNode( in(1), phase->longcon( pos_con-1 ) ) ); + } + + // Save in(1) so that it cannot be changed or deleted + hook->init_req(0, in(1)); + + // Divide using the transform from DivI to MulL + Node *result = transform_long_divide( phase, in(1), pos_con ); + if (result != NULL) { + Node *divide = phase->transform(result); + + // Re-multiply, using a shift if this is a power of two + Node *mult = NULL; + + if( log2_con >= 0 ) + mult = phase->transform( new (phase->C, 3) LShiftLNode( divide, phase->intcon( log2_con ) ) ); + else + mult = phase->transform( new (phase->C, 3) MulLNode( divide, phase->longcon( pos_con ) ) ); + + // Finally, subtract the multiplied divided value from the original + result = new (phase->C, 3) SubLNode( in(1), mult ); + } + + // Now remove the bogus extra edges used to keep things alive + if (can_reshape) { + phase->is_IterGVN()->remove_dead_node(hook); + } else { + hook->set_req(0, NULL); // Just yank bogus edge during Parse phase + } + + // return the value + return result; } //------------------------------Value------------------------------------------ @@ -872,56 +1105,32 @@ const Type *ModFNode::Value( PhaseTransform *phase ) const { (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) ) return bot; - // If either is a NaN, return an input NaN - if( g_isnan(t1->getf()) ) return t1; - if( g_isnan(t2->getf()) ) return t2; - - // It is not worth trying to constant fold this stuff! - return Type::FLOAT; - - /* - // If dividend is infinity or divisor is zero, or both, the result is NaN - if( !g_isfinite(t1->getf()) || ((t2->getf() == 0.0) || (jint_cast(t2->getf()) == 0x80000000)) ) - - // X MOD infinity = X - if( !g_isfinite(t2->getf()) && !g_isnan(t2->getf()) ) return t1; - // 0 MOD finite = dividend (positive or negative zero) - // Not valid for: NaN MOD any; any MOD nan; 0 MOD 0; or for 0 MOD NaN - // NaNs are handled previously. - if( !(t2->getf() == 0.0) && !((int)t2->getf() == 0x80000000)) { - if (((t1->getf() == 0.0) || ((int)t1->getf() == 0x80000000)) && g_isfinite(t2->getf()) ) { - return t1; - } + // If either number is not a constant, we know nothing. + if ((t1->base() != Type::FloatCon) || (t2->base() != Type::FloatCon)) { + return Type::FLOAT; // note: x%x can be either NaN or 0 } - // X MOD X is 0 - // Does not work for variables because of NaN's - if( phase->eqv( in(1), in(2) ) && t1->base() == Type::FloatCon) - if (!g_isnan(t1->getf()) && (t1->getf() != 0.0) && ((int)t1->getf() != 0x80000000)) { - if(t1->getf() < 0.0) { - float result = jfloat_cast(0x80000000); - return TypeF::make( result ); - } - else - return TypeF::ZERO; - } - // If both numbers are not constants, we know nothing. - if( (t1->base() != Type::FloatCon) || (t2->base() != Type::FloatCon) ) + float f1 = t1->getf(); + float f2 = t2->getf(); + jint x1 = jint_cast(f1); // note: *(int*)&f1, not just (int)f1 + jint x2 = jint_cast(f2); + + // If either is a NaN, return an input NaN + if (g_isnan(f1)) return t1; + if (g_isnan(f2)) return t2; + + // If an operand is infinity or the divisor is +/- zero, punt. + if (!g_isfinite(f1) || !g_isfinite(f2) || x2 == 0 || x2 == min_jint) return Type::FLOAT; // We must be modulo'ing 2 float constants. // Make sure that the sign of the fmod is equal to the sign of the dividend - float result = (float)fmod( t1->getf(), t2->getf() ); - float dividend = t1->getf(); - if( (dividend < 0.0) || ((int)dividend == 0x80000000) ) { - if( result > 0.0 ) - result = 0.0 - result; - else if( result == 0.0 ) { - result = jfloat_cast(0x80000000); - } + jint xr = jint_cast(fmod(f1, f2)); + if ((x1 ^ xr) < 0) { + xr ^= min_jint; } - return TypeF::make( result ); - */ + + return TypeF::make(jfloat_cast(xr)); } @@ -940,33 +1149,32 @@ const Type *ModDNode::Value( PhaseTransform *phase ) const { (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) ) return bot; - // If either is a NaN, return an input NaN - if( g_isnan(t1->getd()) ) return t1; - if( g_isnan(t2->getd()) ) return t2; - // X MOD infinity = X - if( !g_isfinite(t2->getd())) return t1; - // 0 MOD finite = dividend (positive or negative zero) - // Not valid for: NaN MOD any; any MOD nan; 0 MOD 0; or for 0 MOD NaN - // NaNs are handled previously. - if( !(t2->getd() == 0.0) ) { - if( t1->getd() == 0.0 && g_isfinite(t2->getd()) ) { - return t1; - } + // If either number is not a constant, we know nothing. + if ((t1->base() != Type::DoubleCon) || (t2->base() != Type::DoubleCon)) { + return Type::DOUBLE; // note: x%x can be either NaN or 0 } - // X MOD X is 0 - // does not work for variables because of NaN's - if( phase->eqv( in(1), in(2) ) && t1->base() == Type::DoubleCon ) - if (!g_isnan(t1->getd()) && t1->getd() != 0.0) - return TypeD::ZERO; + double f1 = t1->getd(); + double f2 = t2->getd(); + jlong x1 = jlong_cast(f1); // note: *(long*)&f1, not just (long)f1 + jlong x2 = jlong_cast(f2); + // If either is a NaN, return an input NaN + if (g_isnan(f1)) return t1; + if (g_isnan(f2)) return t2; - // If both numbers are not constants, we know nothing. - if( (t1->base() != Type::DoubleCon) || (t2->base() != Type::DoubleCon) ) + // If an operand is infinity or the divisor is +/- zero, punt. + if (!g_isfinite(f1) || !g_isfinite(f2) || x2 == 0 || x2 == min_jlong) return Type::DOUBLE; // We must be modulo'ing 2 double constants. - return TypeD::make( fmod( t1->getd(), t2->getd() ) ); + // Make sure that the sign of the fmod is equal to the sign of the dividend + jlong xr = jlong_cast(fmod(f1, f2)); + if ((x1 ^ xr) < 0) { + xr ^= min_jlong; + } + + return TypeD::make(jdouble_cast(xr)); } //============================================================================= diff --git a/hotspot/src/share/vm/opto/escape.cpp b/hotspot/src/share/vm/opto/escape.cpp index 0ea97731bb2..93a49b94127 100644 --- a/hotspot/src/share/vm/opto/escape.cpp +++ b/hotspot/src/share/vm/opto/escape.cpp @@ -215,6 +215,10 @@ void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase VectorSet visited(Thread::current()->resource_area()); GrowableArray worklist; +#ifdef ASSERT + Node *orig_n = n; +#endif + n = n->uncast(); PointsToNode npt = _nodes->at_grow(n->_idx); @@ -223,8 +227,14 @@ void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase ptset.set(n->_idx); return; } - assert(npt._node != NULL, "unregistered node"); - +#ifdef ASSERT + if (npt._node == NULL) { + if (orig_n != n) + orig_n->dump(); + n->dump(); + assert(npt._node != NULL, "unregistered node"); + } +#endif worklist.push(n->_idx); while(worklist.length() > 0) { int ni = worklist.pop(); @@ -256,39 +266,51 @@ void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase } } -void ConnectionGraph::remove_deferred(uint ni) { - VectorSet visited(Thread::current()->resource_area()); +void ConnectionGraph::remove_deferred(uint ni, GrowableArray* deferred_edges, VectorSet* visited) { + // This method is most expensive during ConnectionGraph construction. + // Reuse vectorSet and an additional growable array for deferred edges. + deferred_edges->clear(); + visited->Clear(); uint i = 0; PointsToNode *ptn = ptnode_adr(ni); - while(i < ptn->edge_count()) { + // Mark current edges as visited and move deferred edges to separate array. + while (i < ptn->edge_count()) { uint t = ptn->edge_target(i); - PointsToNode *ptt = ptnode_adr(t); - if (ptn->edge_type(i) != PointsToNode::DeferredEdge) { - i++; - } else { +#ifdef ASSERT + assert(!visited->test_set(t), "expecting no duplications"); +#else + visited->set(t); +#endif + if (ptn->edge_type(i) == PointsToNode::DeferredEdge) { ptn->remove_edge(t, PointsToNode::DeferredEdge); - if(!visited.test_set(t)) { - for (uint j = 0; j < ptt->edge_count(); j++) { - uint n1 = ptt->edge_target(j); - PointsToNode *pt1 = ptnode_adr(n1); - switch(ptt->edge_type(j)) { - case PointsToNode::PointsToEdge: - add_pointsto_edge(ni, n1); - if(n1 == _phantom_object) { - // Special case - field set outside (globally escaping). - ptn->set_escape_state(PointsToNode::GlobalEscape); - } - break; - case PointsToNode::DeferredEdge: - add_deferred_edge(ni, n1); - break; - case PointsToNode::FieldEdge: - assert(false, "invalid connection graph"); - break; + deferred_edges->append(t); + } else { + i++; + } + } + for (int next = 0; next < deferred_edges->length(); ++next) { + uint t = deferred_edges->at(next); + PointsToNode *ptt = ptnode_adr(t); + for (uint j = 0; j < ptt->edge_count(); j++) { + uint n1 = ptt->edge_target(j); + if (visited->test_set(n1)) + continue; + switch(ptt->edge_type(j)) { + case PointsToNode::PointsToEdge: + add_pointsto_edge(ni, n1); + if(n1 == _phantom_object) { + // Special case - field set outside (globally escaping). + ptn->set_escape_state(PointsToNode::GlobalEscape); } - } + break; + case PointsToNode::DeferredEdge: + deferred_edges->append(n1); + break; + case PointsToNode::FieldEdge: + assert(false, "invalid connection graph"); + break; } } } @@ -1243,8 +1265,10 @@ void ConnectionGraph::compute_escape() { } VectorSet ptset(Thread::current()->resource_area()); - GrowableArray alloc_worklist; - GrowableArray worklist; + GrowableArray alloc_worklist; + GrowableArray worklist; + GrowableArray deferred_edges; + VectorSet visited(Thread::current()->resource_area()); // remove deferred edges from the graph and collect // information we will need for type splitting @@ -1254,7 +1278,7 @@ void ConnectionGraph::compute_escape() { PointsToNode::NodeType nt = ptn->node_type(); Node *n = ptn->_node; if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) { - remove_deferred(ni); + remove_deferred(ni, &deferred_edges, &visited); if (n->is_AddP()) { // If this AddP computes an address which may point to more that one // object, nothing the address points to can be scalar replaceable. @@ -1704,6 +1728,8 @@ void ConnectionGraph::record_for_escape_analysis(Node *n, PhaseTransform *phase) } case Op_CastPP: case Op_CheckCastPP: + case Op_EncodeP: + case Op_DecodeN: { add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false); int ti = n->in(1)->_idx; @@ -1731,6 +1757,18 @@ void ConnectionGraph::record_for_escape_analysis(Node *n, PhaseTransform *phase) add_node(n, PointsToNode::JavaObject, es, true); break; } + case Op_ConN: + { + // assume all narrow oop constants globally escape except for null + PointsToNode::EscapeState es; + if (phase->type(n) == TypeNarrowOop::NULL_PTR) + es = PointsToNode::NoEscape; + else + es = PointsToNode::GlobalEscape; + + add_node(n, PointsToNode::JavaObject, es, true); + break; + } case Op_CreateEx: { // assume that all exception objects globally escape @@ -1743,9 +1781,10 @@ void ConnectionGraph::record_for_escape_analysis(Node *n, PhaseTransform *phase) break; } case Op_LoadP: + case Op_LoadN: { const Type *t = phase->type(n); - if (t->isa_ptr() == NULL) { + if (!t->isa_narrowoop() && t->isa_ptr() == NULL) { _processed.set(n->_idx); return; } @@ -1835,8 +1874,12 @@ void ConnectionGraph::record_for_escape_analysis(Node *n, PhaseTransform *phase) break; } case Op_StoreP: + case Op_StoreN: { const Type *adr_type = phase->type(n->in(MemNode::Address)); + if (adr_type->isa_narrowoop()) { + adr_type = adr_type->is_narrowoop()->make_oopptr(); + } if (adr_type->isa_oopptr()) { add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false); } else { @@ -1858,8 +1901,12 @@ void ConnectionGraph::record_for_escape_analysis(Node *n, PhaseTransform *phase) } case Op_StorePConditional: case Op_CompareAndSwapP: + case Op_CompareAndSwapN: { const Type *adr_type = phase->type(n->in(MemNode::Address)); + if (adr_type->isa_narrowoop()) { + adr_type = adr_type->is_narrowoop()->make_oopptr(); + } if (adr_type->isa_oopptr()) { add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false); } else { @@ -1915,6 +1962,8 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { } case Op_CastPP: case Op_CheckCastPP: + case Op_EncodeP: + case Op_DecodeN: { int ti = n->in(1)->_idx; if (_nodes->adr_at(ti)->node_type() == PointsToNode::JavaObject) { @@ -1941,10 +1990,11 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { break; } case Op_LoadP: + case Op_LoadN: { const Type *t = phase->type(n); #ifdef ASSERT - if (t->isa_ptr() == NULL) + if (!t->isa_narrowoop() && t->isa_ptr() == NULL) assert(false, "Op_LoadP"); #endif @@ -2025,11 +2075,16 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) { break; } case Op_StoreP: + case Op_StoreN: case Op_StorePConditional: case Op_CompareAndSwapP: + case Op_CompareAndSwapN: { Node *adr = n->in(MemNode::Address); const Type *adr_type = phase->type(adr); + if (adr_type->isa_narrowoop()) { + adr_type = adr_type->is_narrowoop()->make_oopptr(); + } #ifdef ASSERT if (!adr_type->isa_oopptr()) assert(phase->type(adr) == TypeRawPtr::NOTNULL, "Op_StoreP"); diff --git a/hotspot/src/share/vm/opto/escape.hpp b/hotspot/src/share/vm/opto/escape.hpp index a7552b2c3ae..1d2c83511e7 100644 --- a/hotspot/src/share/vm/opto/escape.hpp +++ b/hotspot/src/share/vm/opto/escape.hpp @@ -269,7 +269,7 @@ private: // Remove outgoing deferred edges from the node referenced by "ni". // Any outgoing edges from the target of the deferred edge are copied // to "ni". - void remove_deferred(uint ni); + void remove_deferred(uint ni, GrowableArray* deferred_edges, VectorSet* visited); Node_Array _node_map; // used for bookeeping during type splitting // Used for the following purposes: diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index d44caf2e3bc..49e05b8425e 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -1328,7 +1328,7 @@ Node* GraphKit::make_load(Node* ctl, Node* adr, const Type* t, BasicType bt, if (require_atomic_access && bt == T_LONG) { ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t); } else { - ld = LoadNode::make(C, ctl, mem, adr, adr_type, t, bt); + ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt); } return _gvn.transform(ld); } @@ -1344,7 +1344,7 @@ Node* GraphKit::store_to_memory(Node* ctl, Node* adr, Node *val, BasicType bt, if (require_atomic_access && bt == T_LONG) { st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val); } else { - st = StoreNode::make(C, ctl, mem, adr, adr_type, val, bt); + st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt); } st = _gvn.transform(st); set_memory(st, adr_idx); diff --git a/hotspot/src/share/vm/opto/idealKit.cpp b/hotspot/src/share/vm/opto/idealKit.cpp index ae65319f091..437fc105a37 100644 --- a/hotspot/src/share/vm/opto/idealKit.cpp +++ b/hotspot/src/share/vm/opto/idealKit.cpp @@ -345,7 +345,7 @@ Node* IdealKit::load(Node* ctl, if (require_atomic_access && bt == T_LONG) { ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t); } else { - ld = LoadNode::make(C, ctl, mem, adr, adr_type, t, bt); + ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt); } return transform(ld); } @@ -361,7 +361,7 @@ Node* IdealKit::store(Node* ctl, Node* adr, Node *val, BasicType bt, if (require_atomic_access && bt == T_LONG) { st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val); } else { - st = StoreNode::make(C, ctl, mem, adr, adr_type, val, bt); + st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt); } st = transform(st); set_memory(st, adr_idx); diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 5b0ddae9955..13c3d774cff 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -110,6 +110,7 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe case Op_LoadI: case Op_LoadL: case Op_LoadP: + case Op_LoadN: case Op_LoadS: case Op_LoadKlass: case Op_LoadRange: @@ -124,6 +125,7 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe case Op_StoreI: case Op_StoreL: case Op_StoreP: + case Op_StoreN: was_store = true; // Memory op is a store op // Stores will have their address in slot 2 (memory in slot 1). // If the value being nul-checked is in another slot, it means we @@ -627,6 +629,10 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, int *ready_cnt, Vect // of the phi to be scheduled first. The select() method breaks // ties in scheduling by worklist order. delay.push(m); + } else if (m->is_Mach() && m->as_Mach()->ideal_Opcode() == Op_CreateEx) { + // Force the CreateEx to the top of the list so it's processed + // first and ends up at the start of the block. + worklist.insert(0, m); } else { worklist.push(m); // Then on to worklist! } diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index b0587edfc3b..2e7688ed939 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -1847,7 +1847,7 @@ bool LibraryCallKit::inline_unsafe_access(bool is_native_ptr, bool is_store, Bas // See if it is a narrow oop array. if (adr_type->isa_aryptr()) { - if (adr_type->offset() >= objArrayOopDesc::header_size() * wordSize) { + if (adr_type->offset() >= objArrayOopDesc::base_offset_in_bytes(type)) { const TypeOopPtr *elem_type = adr_type->is_aryptr()->elem()->isa_oopptr(); if (elem_type != NULL) { sharpened_klass = elem_type->klass(); @@ -2164,10 +2164,19 @@ bool LibraryCallKit::inline_unsafe_CAS(BasicType type) { cas = _gvn.transform(new (C, 5) CompareAndSwapLNode(control(), mem, adr, newval, oldval)); break; case T_OBJECT: - // reference stores need a store barrier. + // reference stores need a store barrier. // (They don't if CAS fails, but it isn't worth checking.) pre_barrier(control(), base, adr, alias_idx, newval, value_type, T_OBJECT); - cas = _gvn.transform(new (C, 5) CompareAndSwapPNode(control(), mem, adr, newval, oldval)); +#ifdef _LP64 + if (adr->bottom_type()->is_narrow()) { + cas = _gvn.transform(new (C, 5) CompareAndSwapNNode(control(), mem, adr, + EncodePNode::encode(&_gvn, newval), + EncodePNode::encode(&_gvn, oldval))); + } else +#endif + { + cas = _gvn.transform(new (C, 5) CompareAndSwapPNode(control(), mem, adr, newval, oldval)); + } post_barrier(control(), cas, base, adr, alias_idx, newval, T_OBJECT, true); break; default: @@ -3824,7 +3833,15 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) { Node* size = _gvn.transform(alloc_siz); // Exclude the header. - int base_off = sizeof(oopDesc); + int base_off = instanceOopDesc::base_offset_in_bytes(); + if (UseCompressedOops) { + // copy the header gap though. + Node* sptr = basic_plus_adr(src, base_off); + Node* dptr = basic_plus_adr(dest, base_off); + Node* sval = make_load(control(), sptr, TypeInt::INT, T_INT, raw_adr_type); + store_to_memory(control(), dptr, sval, T_INT, raw_adr_type); + base_off += sizeof(int); + } src = basic_plus_adr(src, base_off); dest = basic_plus_adr(dest, base_off); end = basic_plus_adr(end, size); @@ -4389,7 +4406,7 @@ LibraryCallKit::generate_arraycopy(const TypePtr* adr_type, // Let's see if we need card marks: if (alloc != NULL && use_ReduceInitialCardMarks()) { // If we do not need card marks, copy using the jint or jlong stub. - copy_type = LP64_ONLY(T_LONG) NOT_LP64(T_INT); + copy_type = LP64_ONLY(UseCompressedOops ? T_INT : T_LONG) NOT_LP64(T_INT); assert(type2aelembytes(basic_elem_type) == type2aelembytes(copy_type), "sizes agree"); } @@ -4715,23 +4732,25 @@ LibraryCallKit::generate_clear_array(const TypePtr* adr_type, int to_clear = (bump_bit | clear_low); // Align up mod 8, then store a jint zero unconditionally // just before the mod-8 boundary. - // This would only fail if the first array element were immediately - // after the length field, and were also at an even offset mod 8. - assert(((abase + bump_bit) & ~to_clear) - BytesPerInt - >= arrayOopDesc::length_offset_in_bytes() + BytesPerInt, - "store must not trash length field"); - - // Bump 'start' up to (or past) the next jint boundary: - start = _gvn.transform( new(C,3) AddXNode(start, MakeConX(bump_bit)) ); + if (((abase + bump_bit) & ~to_clear) - bump_bit + < arrayOopDesc::length_offset_in_bytes() + BytesPerInt) { + bump_bit = 0; + assert((abase & to_clear) == 0, "array base must be long-aligned"); + } else { + // Bump 'start' up to (or past) the next jint boundary: + start = _gvn.transform( new(C,3) AddXNode(start, MakeConX(bump_bit)) ); + assert((abase & clear_low) == 0, "array base must be int-aligned"); + } // Round bumped 'start' down to jlong boundary in body of array. start = _gvn.transform( new(C,3) AndXNode(start, MakeConX(~to_clear)) ); - // Store a zero to the immediately preceding jint: - Node* x1 = _gvn.transform( new(C,3) AddXNode(start, MakeConX(-BytesPerInt)) ); - Node* p1 = basic_plus_adr(dest, x1); - mem = StoreNode::make(C, control(), mem, p1, adr_type, intcon(0), T_INT); - mem = _gvn.transform(mem); + if (bump_bit != 0) { + // Store a zero to the immediately preceding jint: + Node* x1 = _gvn.transform( new(C,3) AddXNode(start, MakeConX(-bump_bit)) ); + Node* p1 = basic_plus_adr(dest, x1); + mem = StoreNode::make(_gvn, control(), mem, p1, adr_type, intcon(0), T_INT); + mem = _gvn.transform(mem); + } } - Node* end = dest_size; // pre-rounded mem = ClearArrayNode::clear_memory(control(), mem, dest, start, end, &_gvn); diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp index de54863b5ba..780766fb854 100644 --- a/hotspot/src/share/vm/opto/loopTransform.cpp +++ b/hotspot/src/share/vm/opto/loopTransform.cpp @@ -1513,7 +1513,8 @@ void IdealLoopTree::adjust_loop_exit_prob( PhaseIdealLoop *phase ) { (bol->in(1)->Opcode() == Op_StoreLConditional ) || (bol->in(1)->Opcode() == Op_CompareAndSwapI ) || (bol->in(1)->Opcode() == Op_CompareAndSwapL ) || - (bol->in(1)->Opcode() == Op_CompareAndSwapP ))) + (bol->in(1)->Opcode() == Op_CompareAndSwapP ) || + (bol->in(1)->Opcode() == Op_CompareAndSwapN ))) return; // Allocation loops RARELY take backedge // Find the OTHER exit path from the IF Node* ex = iff->proj_out(1-test_con); diff --git a/hotspot/src/share/vm/opto/loopUnswitch.cpp b/hotspot/src/share/vm/opto/loopUnswitch.cpp index fcba517e8b2..5f384b60b43 100644 --- a/hotspot/src/share/vm/opto/loopUnswitch.cpp +++ b/hotspot/src/share/vm/opto/loopUnswitch.cpp @@ -51,6 +51,9 @@ bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const { if( !LoopUnswitching ) { return false; } + if (!_head->is_Loop()) { + return false; + } uint nodes_left = MaxNodeLimit - phase->C->unique(); if (2 * _body.size() > nodes_left) { return false; // Too speculative if running low on nodes. diff --git a/hotspot/src/share/vm/opto/loopopts.cpp b/hotspot/src/share/vm/opto/loopopts.cpp index 6535c552907..52dc89266ff 100644 --- a/hotspot/src/share/vm/opto/loopopts.cpp +++ b/hotspot/src/share/vm/opto/loopopts.cpp @@ -2257,6 +2257,9 @@ bool PhaseIdealLoop::is_valid_clone_loop_form( IdealLoopTree *loop, Node_List& p // bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) { + if (!loop->_head->is_Loop()) { + return false; } + LoopNode *head = loop->_head->as_Loop(); if (head->is_partial_peel_loop() || head->partial_peel_has_failed()) { diff --git a/hotspot/src/share/vm/opto/machnode.cpp b/hotspot/src/share/vm/opto/machnode.cpp index 8b88f00b5fe..70815a2804a 100644 --- a/hotspot/src/share/vm/opto/machnode.cpp +++ b/hotspot/src/share/vm/opto/machnode.cpp @@ -263,6 +263,13 @@ const Node* MachNode::get_base_and_disp(intptr_t &offset, const TypePtr* &adr_ty // See if it adds up to a base + offset. if (index != NULL) { if (!index->is_Con()) { + const TypeNarrowOop* narrowoop = index->bottom_type()->isa_narrowoop(); + if (narrowoop != NULL) { + // Memory references through narrow oops have a + // funny base so grab the type from the index. + adr_type = narrowoop->make_oopptr(); + return NULL; + } disp = Type::OffsetBot; } else if (disp != Type::OffsetBot) { const TypeX* ti = index->bottom_type()->isa_intptr_t(); diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index bc785ab3562..d537c1d6c6e 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -584,7 +584,7 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray is_loaded()) { field_type = TypeInstPtr::BOTTOM; } else if (field != NULL && field->is_constant()) { @@ -597,6 +597,10 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray as_klass()); } + if (UseCompressedOops) { + field_type = field_type->is_oopptr()->make_narrowoop(); + basic_elem_type = T_NARROWOOP; + } } else { field_type = Type::get_const_basic_type(basic_elem_type); } @@ -659,6 +663,13 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray isa_narrowoop()) { + // Enable "DecodeN(EncodeP(Allocate)) --> Allocate" transformation + // to be able scalar replace the allocation. + _igvn.set_delay_transform(false); + field_val = DecodeNNode::decode(&_igvn, field_val); + _igvn.set_delay_transform(true); + } sfpt->add_req(field_val); } JVMState *jvms = sfpt->jvms(); @@ -819,7 +830,7 @@ void PhaseMacroExpand::set_eden_pointers(Node* &eden_top_adr, Node* &eden_end_ad Node* PhaseMacroExpand::make_load(Node* ctl, Node* mem, Node* base, int offset, const Type* value_type, BasicType bt) { Node* adr = basic_plus_adr(base, offset); const TypePtr* adr_type = TypeRawPtr::BOTTOM; - Node* value = LoadNode::make(C, ctl, mem, adr, adr_type, value_type, bt); + Node* value = LoadNode::make(_igvn, ctl, mem, adr, adr_type, value_type, bt); transform_later(value); return value; } @@ -827,7 +838,7 @@ Node* PhaseMacroExpand::make_load(Node* ctl, Node* mem, Node* base, int offset, Node* PhaseMacroExpand::make_store(Node* ctl, Node* mem, Node* base, int offset, Node* value, BasicType bt) { Node* adr = basic_plus_adr(base, offset); - mem = StoreNode::make(C, ctl, mem, adr, NULL, value, bt); + mem = StoreNode::make(_igvn, ctl, mem, adr, NULL, value, bt); transform_later(mem); return mem; } @@ -1270,6 +1281,13 @@ PhaseMacroExpand::initialize_object(AllocateNode* alloc, mark_node = makecon(TypeRawPtr::make((address)markOopDesc::prototype())); } rawmem = make_store(control, rawmem, object, oopDesc::mark_offset_in_bytes(), mark_node, T_ADDRESS); + + if (UseCompressedOops) { + Node *zeronode = makecon(TypeInt::ZERO); + // store uncompressed 0 into klass ptr to zero out gap. The gap is + // used for primitive fields and has to be zeroed. + rawmem = make_store(control, rawmem, object, oopDesc::klass_gap_offset_in_bytes(), zeronode, T_INT); + } rawmem = make_store(control, rawmem, object, oopDesc::klass_offset_in_bytes(), klass_node, T_OBJECT); int header_size = alloc->minimum_header_size(); // conservatively small @@ -1277,7 +1295,7 @@ PhaseMacroExpand::initialize_object(AllocateNode* alloc, if (length != NULL) { // Arrays need length field rawmem = make_store(control, rawmem, object, arrayOopDesc::length_offset_in_bytes(), length, T_INT); // conservatively small header size: - header_size = sizeof(arrayOopDesc); + header_size = arrayOopDesc::base_offset_in_bytes(T_BYTE); ciKlass* k = _igvn.type(klass_node)->is_klassptr()->klass(); if (k->is_array_klass()) // we know the exact header size in most cases: header_size = Klass::layout_helper_header_size(k->layout_helper()); @@ -1306,7 +1324,6 @@ PhaseMacroExpand::initialize_object(AllocateNode* alloc, rawmem = init->complete_stores(control, rawmem, object, header_size, size_in_bytes, &_igvn); } - // We have no more use for this link, since the AllocateNode goes away: init->set_req(InitializeNode::RawAddress, top()); // (If we keep the link, it just confuses the register allocator, @@ -1705,6 +1722,8 @@ bool PhaseMacroExpand::expand_macro_nodes() { assert(C->macro_count() < macro_count, "must have deleted a node from macro list"); if (C->failing()) return true; } + + _igvn.set_delay_transform(false); _igvn.optimize(); return false; } diff --git a/hotspot/src/share/vm/opto/macro.hpp b/hotspot/src/share/vm/opto/macro.hpp index 47e30ef8fa8..06e28119d5b 100644 --- a/hotspot/src/share/vm/opto/macro.hpp +++ b/hotspot/src/share/vm/opto/macro.hpp @@ -110,7 +110,9 @@ private: Node* length); public: - PhaseMacroExpand(PhaseIterGVN &igvn) : Phase(Macro_Expand), _igvn(igvn) {} + PhaseMacroExpand(PhaseIterGVN &igvn) : Phase(Macro_Expand), _igvn(igvn) { + _igvn.set_delay_transform(true); + } bool expand_macro_nodes(); }; diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 7d9cd51eff6..0374d7c7a0d 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -30,7 +30,7 @@ OptoReg::Name OptoReg::c_frame_pointer; const int Matcher::base2reg[Type::lastype] = { - Node::NotAMachineReg,0,0, Op_RegI, Op_RegL, 0, + Node::NotAMachineReg,0,0, Op_RegI, Op_RegL, 0, Op_RegN, Node::NotAMachineReg, Node::NotAMachineReg, /* tuple, array */ Op_RegP, Op_RegP, Op_RegP, Op_RegP, Op_RegP, Op_RegP, /* the pointers */ 0, 0/*abio*/, @@ -70,12 +70,14 @@ Matcher::Matcher( Node_List &proj_list ) : C->set_matcher(this); idealreg2spillmask[Op_RegI] = NULL; + idealreg2spillmask[Op_RegN] = NULL; idealreg2spillmask[Op_RegL] = NULL; idealreg2spillmask[Op_RegF] = NULL; idealreg2spillmask[Op_RegD] = NULL; idealreg2spillmask[Op_RegP] = NULL; idealreg2debugmask[Op_RegI] = NULL; + idealreg2debugmask[Op_RegN] = NULL; idealreg2debugmask[Op_RegL] = NULL; idealreg2debugmask[Op_RegF] = NULL; idealreg2debugmask[Op_RegD] = NULL; @@ -366,17 +368,19 @@ static RegMask *init_input_masks( uint size, RegMask &ret_adr, RegMask &fp ) { void Matcher::init_first_stack_mask() { // Allocate storage for spill masks as masks for the appropriate load type. - RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask)*10); - idealreg2spillmask[Op_RegI] = &rms[0]; - idealreg2spillmask[Op_RegL] = &rms[1]; - idealreg2spillmask[Op_RegF] = &rms[2]; - idealreg2spillmask[Op_RegD] = &rms[3]; - idealreg2spillmask[Op_RegP] = &rms[4]; - idealreg2debugmask[Op_RegI] = &rms[5]; - idealreg2debugmask[Op_RegL] = &rms[6]; - idealreg2debugmask[Op_RegF] = &rms[7]; - idealreg2debugmask[Op_RegD] = &rms[8]; - idealreg2debugmask[Op_RegP] = &rms[9]; + RegMask *rms = (RegMask*)C->comp_arena()->Amalloc_D(sizeof(RegMask)*12); + idealreg2spillmask[Op_RegN] = &rms[0]; + idealreg2spillmask[Op_RegI] = &rms[1]; + idealreg2spillmask[Op_RegL] = &rms[2]; + idealreg2spillmask[Op_RegF] = &rms[3]; + idealreg2spillmask[Op_RegD] = &rms[4]; + idealreg2spillmask[Op_RegP] = &rms[5]; + idealreg2debugmask[Op_RegN] = &rms[6]; + idealreg2debugmask[Op_RegI] = &rms[7]; + idealreg2debugmask[Op_RegL] = &rms[8]; + idealreg2debugmask[Op_RegF] = &rms[9]; + idealreg2debugmask[Op_RegD] = &rms[10]; + idealreg2debugmask[Op_RegP] = &rms[11]; OptoReg::Name i; @@ -399,6 +403,10 @@ void Matcher::init_first_stack_mask() { C->FIRST_STACK_mask().set_AllStack(); // Make spill masks. Registers for their class, plus FIRST_STACK_mask. +#ifdef _LP64 + *idealreg2spillmask[Op_RegN] = *idealreg2regmask[Op_RegN]; + idealreg2spillmask[Op_RegN]->OR(C->FIRST_STACK_mask()); +#endif *idealreg2spillmask[Op_RegI] = *idealreg2regmask[Op_RegI]; idealreg2spillmask[Op_RegI]->OR(C->FIRST_STACK_mask()); *idealreg2spillmask[Op_RegL] = *idealreg2regmask[Op_RegL]; @@ -413,6 +421,7 @@ void Matcher::init_first_stack_mask() { // Make up debug masks. Any spill slot plus callee-save registers. // Caller-save registers are assumed to be trashable by the various // inline-cache fixup routines. + *idealreg2debugmask[Op_RegN]= *idealreg2spillmask[Op_RegN]; *idealreg2debugmask[Op_RegI]= *idealreg2spillmask[Op_RegI]; *idealreg2debugmask[Op_RegL]= *idealreg2spillmask[Op_RegL]; *idealreg2debugmask[Op_RegF]= *idealreg2spillmask[Op_RegF]; @@ -428,6 +437,7 @@ void Matcher::init_first_stack_mask() { if( _register_save_policy[i] == 'C' || _register_save_policy[i] == 'A' || (_register_save_policy[i] == 'E' && exclude_soe) ) { + idealreg2debugmask[Op_RegN]->Remove(i); idealreg2debugmask[Op_RegI]->Remove(i); // Exclude save-on-call idealreg2debugmask[Op_RegL]->Remove(i); // registers from debug idealreg2debugmask[Op_RegF]->Remove(i); // masks @@ -661,6 +671,9 @@ void Matcher::init_spill_mask( Node *ret ) { set_shared(fp); // Compute generic short-offset Loads +#ifdef _LP64 + MachNode *spillCP = match_tree(new (C, 3) LoadNNode(NULL,mem,fp,atp,TypeInstPtr::BOTTOM)); +#endif MachNode *spillI = match_tree(new (C, 3) LoadINode(NULL,mem,fp,atp)); MachNode *spillL = match_tree(new (C, 3) LoadLNode(NULL,mem,fp,atp)); MachNode *spillF = match_tree(new (C, 3) LoadFNode(NULL,mem,fp,atp)); @@ -670,6 +683,9 @@ void Matcher::init_spill_mask( Node *ret ) { spillD != NULL && spillP != NULL, ""); // Get the ADLC notion of the right regmask, for each basic type. +#ifdef _LP64 + idealreg2regmask[Op_RegN] = &spillCP->out_RegMask(); +#endif idealreg2regmask[Op_RegI] = &spillI->out_RegMask(); idealreg2regmask[Op_RegL] = &spillL->out_RegMask(); idealreg2regmask[Op_RegF] = &spillF->out_RegMask(); @@ -1227,6 +1243,13 @@ static bool match_into_reg( const Node *n, Node *m, Node *control, int i, bool s if( j == max_scan ) // No post-domination before scan end? return true; // Then break the match tree up } + + if (m->Opcode() == Op_DecodeN && m->outcnt() == 2) { + // These are commonly used in address expressions and can + // efficiently fold into them in some cases but because they are + // consumed by AddP they commonly have two users. + if (m->raw_out(0) == m->raw_out(1) && m->raw_out(0)->Opcode() == Op_AddP) return false; + } } // Not forceably cloning. If shared, put it into a register. @@ -1714,6 +1737,7 @@ void Matcher::find_shared( Node *n ) { case Op_StoreI: case Op_StoreL: case Op_StoreP: + case Op_StoreN: case Op_Store16B: case Op_Store8B: case Op_Store4B: @@ -1739,6 +1763,7 @@ void Matcher::find_shared( Node *n ) { case Op_LoadL: case Op_LoadS: case Op_LoadP: + case Op_LoadN: case Op_LoadRange: case Op_LoadD_unaligned: case Op_LoadL_unaligned: @@ -1853,7 +1878,8 @@ void Matcher::find_shared( Node *n ) { case Op_StoreLConditional: case Op_CompareAndSwapI: case Op_CompareAndSwapL: - case Op_CompareAndSwapP: { // Convert trinary to binary-tree + case Op_CompareAndSwapP: + case Op_CompareAndSwapN: { // Convert trinary to binary-tree Node *newval = n->in(MemNode::ValueIn ); Node *oldval = n->in(LoadStoreNode::ExpectedIn); Node *pair = new (C, 3) BinaryNode( oldval, newval ); @@ -1905,22 +1931,25 @@ void Matcher::collect_null_checks( Node *proj ) { // During matching If's have Bool & Cmp side-by-side BoolNode *b = iff->in(1)->as_Bool(); Node *cmp = iff->in(2); - if( cmp->Opcode() == Op_CmpP ) { - if( cmp->in(2)->bottom_type() == TypePtr::NULL_PTR ) { + int opc = cmp->Opcode(); + if (opc != Op_CmpP && opc != Op_CmpN) return; - if( proj->Opcode() == Op_IfTrue ) { - extern int all_null_checks_found; - all_null_checks_found++; - if( b->_test._test == BoolTest::ne ) { - _null_check_tests.push(proj); - _null_check_tests.push(cmp->in(1)); - } - } else { - assert( proj->Opcode() == Op_IfFalse, "" ); - if( b->_test._test == BoolTest::eq ) { - _null_check_tests.push(proj); - _null_check_tests.push(cmp->in(1)); - } + const Type* ct = cmp->in(2)->bottom_type(); + if (ct == TypePtr::NULL_PTR || + (opc == Op_CmpN && ct == TypeNarrowOop::NULL_PTR)) { + + if( proj->Opcode() == Op_IfTrue ) { + extern int all_null_checks_found; + all_null_checks_found++; + if( b->_test._test == BoolTest::ne ) { + _null_check_tests.push(proj); + _null_check_tests.push(cmp->in(1)); + } + } else { + assert( proj->Opcode() == Op_IfFalse, "" ); + if( b->_test._test == BoolTest::eq ) { + _null_check_tests.push(proj); + _null_check_tests.push(cmp->in(1)); } } } @@ -2038,6 +2067,7 @@ bool Matcher::post_store_load_barrier(const Node *vmb) { xop == Op_FastLock || xop == Op_CompareAndSwapL || xop == Op_CompareAndSwapP || + xop == Op_CompareAndSwapN || xop == Op_CompareAndSwapI) return true; diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index 2757803031f..b28c37b7821 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -603,6 +603,10 @@ Node *MemNode::Ideal_DU_postCCP( PhaseCCP *ccp ) { adr = adr->in(AddPNode::Base); continue; + case Op_DecodeN: // No change to NULL-ness, so peek thru + adr = adr->in(1); + continue; + case Op_CastPP: // If the CastPP is useless, just peek on through it. if( ccp->type(adr) == ccp->type(adr->in(1)) ) { @@ -659,6 +663,7 @@ Node *MemNode::Ideal_DU_postCCP( PhaseCCP *ccp ) { case Op_CastX2P: // no null checks on native pointers case Op_Parm: // 'this' pointer is not null case Op_LoadP: // Loading from within a klass + case Op_LoadN: // Loading from within a klass case Op_LoadKlass: // Loading from within a klass case Op_ConP: // Loading from a klass case Op_CreateEx: // Sucking up the guts of an exception oop @@ -723,7 +728,9 @@ void LoadNode::dump_spec(outputStream *st) const { //----------------------------LoadNode::make----------------------------------- // Polymorphic factory method: -LoadNode *LoadNode::make( Compile *C, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt ) { +Node *LoadNode::make( PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const TypePtr* adr_type, const Type *rt, BasicType bt ) { + Compile* C = gvn.C; + // sanity check the alias category against the created node type assert(!(adr_type->isa_oopptr() && adr_type->offset() == oopDesc::klass_offset_in_bytes()), @@ -741,7 +748,24 @@ LoadNode *LoadNode::make( Compile *C, Node *ctl, Node *mem, Node *adr, const Typ case T_FLOAT: return new (C, 3) LoadFNode(ctl, mem, adr, adr_type, rt ); case T_DOUBLE: return new (C, 3) LoadDNode(ctl, mem, adr, adr_type, rt ); case T_ADDRESS: return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_ptr() ); - case T_OBJECT: return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr()); + case T_OBJECT: +#ifdef _LP64 + if (adr->bottom_type()->is_narrow()) { + const TypeNarrowOop* narrowtype; + if (rt->isa_narrowoop()) { + narrowtype = rt->is_narrowoop(); + } else { + narrowtype = rt->is_oopptr()->make_narrowoop(); + } + Node* load = gvn.transform(new (C, 3) LoadNNode(ctl, mem, adr, adr_type, narrowtype)); + + return DecodeNNode::decode(&gvn, load); + } else +#endif + { + assert(!adr->bottom_type()->is_narrow(), "should have got back a narrow oop"); + return new (C, 3) LoadPNode(ctl, mem, adr, adr_type, rt->is_oopptr()); + } } ShouldNotReachHere(); return (LoadNode*)NULL; @@ -1797,7 +1821,9 @@ Node* LoadRangeNode::Identity( PhaseTransform *phase ) { //============================================================================= //---------------------------StoreNode::make----------------------------------- // Polymorphic factory method: -StoreNode* StoreNode::make( Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt ) { +StoreNode* StoreNode::make( PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt ) { + Compile* C = gvn.C; + switch (bt) { case T_BOOLEAN: case T_BYTE: return new (C, 4) StoreBNode(ctl, mem, adr, adr_type, val); @@ -1808,7 +1834,19 @@ StoreNode* StoreNode::make( Compile *C, Node* ctl, Node* mem, Node* adr, const T case T_FLOAT: return new (C, 4) StoreFNode(ctl, mem, adr, adr_type, val); case T_DOUBLE: return new (C, 4) StoreDNode(ctl, mem, adr, adr_type, val); case T_ADDRESS: - case T_OBJECT: return new (C, 4) StorePNode(ctl, mem, adr, adr_type, val); + case T_OBJECT: +#ifdef _LP64 + if (adr->bottom_type()->is_narrow() || + (UseCompressedOops && val->bottom_type()->isa_klassptr() && + adr->bottom_type()->isa_rawptr())) { + const TypePtr* type = val->bottom_type()->is_ptr(); + Node* cp = EncodePNode::encode(&gvn, val); + return new (C, 4) StoreNNode(ctl, mem, adr, adr_type, cp); + } else +#endif + { + return new (C, 4) StorePNode(ctl, mem, adr, adr_type, val); + } } ShouldNotReachHere(); return (StoreNode*)NULL; @@ -2190,7 +2228,7 @@ Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest, Node* adr = new (C, 4) AddPNode(dest, dest, phase->MakeConX(offset)); adr = phase->transform(adr); const TypePtr* atp = TypeRawPtr::BOTTOM; - mem = StoreNode::make(C, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT); + mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT); mem = phase->transform(mem); offset += BytesPerInt; } @@ -2253,7 +2291,7 @@ Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest, Node* adr = new (C, 4) AddPNode(dest, dest, phase->MakeConX(done_offset)); adr = phase->transform(adr); const TypePtr* atp = TypeRawPtr::BOTTOM; - mem = StoreNode::make(C, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT); + mem = StoreNode::make(*phase, ctl, mem, adr, atp, phase->zerocon(T_INT), T_INT); mem = phase->transform(mem); done_offset += BytesPerInt; } @@ -2610,9 +2648,7 @@ int InitializeNode::captured_store_insertion_point(intptr_t start, assert(allocation() != NULL, "must be present"); // no negatives, no header fields: - if (start < (intptr_t) sizeof(oopDesc)) return FAIL; - if (start < (intptr_t) sizeof(arrayOopDesc) && - start < (intptr_t) allocation()->minimum_header_size()) return FAIL; + if (start < (intptr_t) allocation()->minimum_header_size()) return FAIL; // after a certain size, we bail out on tracking all the stores: intptr_t ti_limit = (TrackedInitializationLimit * HeapWordSize); @@ -2949,14 +2985,14 @@ InitializeNode::coalesce_subword_stores(intptr_t header_size, if (!split) { ++new_long; off[nst] = offset; - st[nst++] = StoreNode::make(C, ctl, zmem, adr, atp, + st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp, phase->longcon(con), T_LONG); } else { // Omit either if it is a zero. if (con0 != 0) { ++new_int; off[nst] = offset; - st[nst++] = StoreNode::make(C, ctl, zmem, adr, atp, + st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp, phase->intcon(con0), T_INT); } if (con1 != 0) { @@ -2964,7 +3000,7 @@ InitializeNode::coalesce_subword_stores(intptr_t header_size, offset += BytesPerInt; adr = make_raw_address(offset, phase); off[nst] = offset; - st[nst++] = StoreNode::make(C, ctl, zmem, adr, atp, + st[nst++] = StoreNode::make(*phase, ctl, zmem, adr, atp, phase->intcon(con1), T_INT); } } @@ -3072,9 +3108,10 @@ Node* InitializeNode::complete_stores(Node* rawctl, Node* rawmem, Node* rawptr, Node* zmem = zero_memory(); // initially zero memory state Node* inits = zmem; // accumulating a linearized chain of inits #ifdef ASSERT - intptr_t last_init_off = sizeof(oopDesc); // previous init offset - intptr_t last_init_end = sizeof(oopDesc); // previous init offset+size - intptr_t last_tile_end = sizeof(oopDesc); // previous tile offset+size + intptr_t first_offset = allocation()->minimum_header_size(); + intptr_t last_init_off = first_offset; // previous init offset + intptr_t last_init_end = first_offset; // previous init offset+size + intptr_t last_tile_end = first_offset; // previous tile offset+size #endif intptr_t zeroes_done = header_size; @@ -3209,7 +3246,8 @@ Node* InitializeNode::complete_stores(Node* rawctl, Node* rawmem, Node* rawptr, bool InitializeNode::stores_are_sane(PhaseTransform* phase) { if (is_complete()) return true; // stores could be anything at this point - intptr_t last_off = sizeof(oopDesc); + assert(allocation() != NULL, "must be present"); + intptr_t last_off = allocation()->minimum_header_size(); for (uint i = InitializeNode::RawStores; i < req(); i++) { Node* st = in(i); intptr_t st_off = get_store_offset(st, phase); diff --git a/hotspot/src/share/vm/opto/memnode.hpp b/hotspot/src/share/vm/opto/memnode.hpp index 711aae534f4..0cc63b8efe6 100644 --- a/hotspot/src/share/vm/opto/memnode.hpp +++ b/hotspot/src/share/vm/opto/memnode.hpp @@ -137,7 +137,8 @@ public: } // Polymorphic factory method: - static LoadNode* make( Compile *C, Node *c, Node *mem, Node *adr, const TypePtr* at, const Type *rt, BasicType bt ); + static Node* make( PhaseGVN& gvn, Node *c, Node *mem, Node *adr, + const TypePtr* at, const Type *rt, BasicType bt ); virtual uint hash() const; // Check the type @@ -330,6 +331,29 @@ public: virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM; } }; + +//------------------------------LoadNNode-------------------------------------- +// Load a narrow oop from memory (either object or array) +class LoadNNode : public LoadNode { +public: + LoadNNode( Node *c, Node *mem, Node *adr, const TypePtr *at, const Type* t ) + : LoadNode(c,mem,adr,at,t) {} + virtual int Opcode() const; + virtual uint ideal_reg() const { return Op_RegN; } + virtual int store_Opcode() const { return Op_StoreN; } + virtual BasicType memory_type() const { return T_NARROWOOP; } + // depends_only_on_test is almost always true, and needs to be almost always + // true to enable key hoisting & commoning optimizations. However, for the + // special case of RawPtr loads from TLS top & end, the control edge carries + // the dependence preventing hoisting past a Safepoint instead of the memory + // edge. (An unfortunate consequence of having Safepoints not set Raw + // Memory; itself an unfortunate consequence of having Nodes which produce + // results (new raw memory state) inside of loops preventing all manner of + // other optimizations). Basically, it's ugly but so is the alternative. + // See comment in macro.cpp, around line 125 expand_allocate_common(). + virtual bool depends_only_on_test() const { return adr_type() != TypeRawPtr::BOTTOM; } +}; + //------------------------------LoadKlassNode---------------------------------- // Load a Klass from an object class LoadKlassNode : public LoadPNode { @@ -376,7 +400,8 @@ public: } // Polymorphic factory method: - static StoreNode* make( Compile *C, Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val, BasicType bt ); + static StoreNode* make( PhaseGVN& gvn, Node *c, Node *mem, Node *adr, + const TypePtr* at, Node *val, BasicType bt ); virtual uint hash() const; // Check the type @@ -488,6 +513,15 @@ public: virtual BasicType memory_type() const { return T_ADDRESS; } }; +//------------------------------StoreNNode------------------------------------- +// Store narrow oop to memory +class StoreNNode : public StoreNode { +public: + StoreNNode( Node *c, Node *mem, Node *adr, const TypePtr* at, Node *val ) : StoreNode(c,mem,adr,at,val) {} + virtual int Opcode() const; + virtual BasicType memory_type() const { return T_NARROWOOP; } +}; + //------------------------------StoreCMNode----------------------------------- // Store card-mark byte to memory for CM // The last StoreCM before a SafePoint must be preserved and occur after its "oop" store @@ -600,6 +634,13 @@ public: virtual int Opcode() const; }; +//------------------------------CompareAndSwapNNode--------------------------- +class CompareAndSwapNNode : public LoadStoreNode { +public: + CompareAndSwapNNode( Node *c, Node *mem, Node *adr, Node *val, Node *ex) : LoadStoreNode(c, mem, adr, val, ex) { } + virtual int Opcode() const; +}; + //------------------------------ClearArray------------------------------------- class ClearArrayNode: public Node { public: diff --git a/hotspot/src/share/vm/opto/mulnode.cpp b/hotspot/src/share/vm/opto/mulnode.cpp index 146c432feae..feab38ce64c 100644 --- a/hotspot/src/share/vm/opto/mulnode.cpp +++ b/hotspot/src/share/vm/opto/mulnode.cpp @@ -364,6 +364,25 @@ const Type *MulDNode::mul_ring(const Type *t0, const Type *t1) const { return TypeD::make( t0->getd() * t1->getd() ); } +//============================================================================= +//------------------------------Value------------------------------------------ +const Type *MulHiLNode::Value( PhaseTransform *phase ) const { + // Either input is TOP ==> the result is TOP + const Type *t1 = phase->type( in(1) ); + const Type *t2 = phase->type( in(2) ); + if( t1 == Type::TOP ) return Type::TOP; + if( t2 == Type::TOP ) return Type::TOP; + + // Either input is BOTTOM ==> the result is the local BOTTOM + const Type *bot = bottom_type(); + if( (t1 == bot) || (t2 == bot) || + (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) ) + return bot; + + // It is not worth trying to constant fold this stuff! + return TypeLong::LONG; +} + //============================================================================= //------------------------------mul_ring--------------------------------------- // Supplied function returns the product of the inputs IN THE CURRENT RING. diff --git a/hotspot/src/share/vm/opto/mulnode.hpp b/hotspot/src/share/vm/opto/mulnode.hpp index 380e35a89ec..decaf5aa89c 100644 --- a/hotspot/src/share/vm/opto/mulnode.hpp +++ b/hotspot/src/share/vm/opto/mulnode.hpp @@ -133,6 +133,16 @@ public: virtual uint ideal_reg() const { return Op_RegD; } }; +//-------------------------------MulHiLNode------------------------------------ +// Upper 64 bits of a 64 bit by 64 bit multiply +class MulHiLNode : public Node { +public: + MulHiLNode( Node *in1, Node *in2 ) : Node(0,in1,in2) {} + virtual int Opcode() const; + virtual const Type *Value( PhaseTransform *phase ) const; + const Type *bottom_type() const { return TypeLong::LONG; } + virtual uint ideal_reg() const { return Op_RegL; } +}; //------------------------------AndINode--------------------------------------- // Logically AND 2 integers. Included with the MUL nodes because it inherits diff --git a/hotspot/src/share/vm/opto/multnode.hpp b/hotspot/src/share/vm/opto/multnode.hpp index 34a573ffcd3..8c17f9d45f6 100644 --- a/hotspot/src/share/vm/opto/multnode.hpp +++ b/hotspot/src/share/vm/opto/multnode.hpp @@ -61,6 +61,9 @@ public: : Node( src ), _con(con), _is_io_use(io_use) { init_class_id(Class_Proj); + // Optimistic setting. Need additional checks in Node::is_dead_loop_safe(). + if (con != TypeFunc::Memory || src->is_Start()) + init_flags(Flag_is_dead_loop_safe); debug_only(check_con()); } const uint _con; // The field in the tuple we are projecting diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp index 93a91a1c639..d3c2c65f8f3 100644 --- a/hotspot/src/share/vm/opto/node.cpp +++ b/hotspot/src/share/vm/opto/node.cpp @@ -1264,6 +1264,12 @@ intptr_t Node::get_ptr() const { return ((ConPNode*)this)->type()->is_ptr()->get_con(); } +// Get a narrow oop constant from a ConNNode. +intptr_t Node::get_narrowcon() const { + assert( Opcode() == Op_ConN, "" ); + return ((ConNNode*)this)->type()->is_narrowoop()->get_con(); +} + // Get a long constant from a ConNode. // Return a default value if there is no apparent constant here. const TypeLong* Node::find_long_type() const { diff --git a/hotspot/src/share/vm/opto/node.hpp b/hotspot/src/share/vm/opto/node.hpp index a66292c508a..dc44aab22c8 100644 --- a/hotspot/src/share/vm/opto/node.hpp +++ b/hotspot/src/share/vm/opto/node.hpp @@ -741,8 +741,9 @@ public: bool is_Goto() const { return (_flags & Flag_is_Goto) != 0; } // The data node which is safe to leave in dead loop during IGVN optimization. bool is_dead_loop_safe() const { - return is_Phi() || is_Proj() || - (_flags & (Flag_is_dead_loop_safe | Flag_is_Con)) != 0; + return is_Phi() || (is_Proj() && in(0) == NULL) || + ((_flags & (Flag_is_dead_loop_safe | Flag_is_Con)) != 0 && + (!is_Proj() || !in(0)->is_Allocate())); } // is_Copy() returns copied edge index (0 or 1) @@ -923,6 +924,7 @@ public: // These guys are called by code generated by ADLC: intptr_t get_ptr() const; + intptr_t get_narrowcon() const; jdouble getd() const; jfloat getf() const; diff --git a/hotspot/src/share/vm/opto/opcodes.cpp b/hotspot/src/share/vm/opto/opcodes.cpp index 533cff06c79..ddf5d40665e 100644 --- a/hotspot/src/share/vm/opto/opcodes.cpp +++ b/hotspot/src/share/vm/opto/opcodes.cpp @@ -29,6 +29,7 @@ const char *NodeClassNames[] = { "Node", "Set", + "RegN", "RegI", "RegP", "RegF", diff --git a/hotspot/src/share/vm/opto/opcodes.hpp b/hotspot/src/share/vm/opto/opcodes.hpp index 7c3e38a15d6..530f9e2cbd8 100644 --- a/hotspot/src/share/vm/opto/opcodes.hpp +++ b/hotspot/src/share/vm/opto/opcodes.hpp @@ -27,6 +27,7 @@ enum Opcodes { Op_Node = 0, macro(Set) // Instruction selection match rule + macro(RegN) // Machine narrow oop register macro(RegI) // Machine integer register macro(RegP) // Machine pointer register macro(RegF) // Machine float register diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index d66a68741da..c515f2e32b9 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -67,12 +67,16 @@ Node* Parse::array_addressing(BasicType type, int vals, const Type* *result2) { const Type* elemtype = arytype->elem(); if (UseUniqueSubclasses && result2 != NULL) { - const TypeInstPtr* toop = elemtype->isa_instptr(); + const Type* el = elemtype; + if (elemtype->isa_narrowoop()) { + el = elemtype->is_narrowoop()->make_oopptr(); + } + const TypeInstPtr* toop = el->isa_instptr(); if (toop) { if (toop->klass()->as_instance_klass()->unique_concrete_subklass()) { // If we load from "AbstractClass[]" we must see "ConcreteSubClass". const Type* subklass = Type::get_const_type(toop->klass()); - elemtype = subklass->join(elemtype); + elemtype = subklass->join(el); } } } @@ -101,10 +105,19 @@ Node* Parse::array_addressing(BasicType type, int vals, const Type* *result2) { if (GenerateRangeChecks && need_range_check) { // Range is constant in array-oop, so we can use the original state of mem Node* len = load_array_length(ary); - // Test length vs index (standard trick using unsigned compare) - Node* chk = _gvn.transform( new (C, 3) CmpUNode(idx, len) ); - BoolTest::mask btest = BoolTest::lt; - Node* tst = _gvn.transform( new (C, 2) BoolNode(chk, btest) ); + Node* tst; + if (sizetype->_hi <= 0) { + // If the greatest array bound is negative, we can conclude that we're + // compiling unreachable code, but the unsigned compare trick used below + // only works with non-negative lengths. Instead, hack "tst" to be zero so + // the uncommon_trap path will always be taken. + tst = _gvn.intcon(0); + } else { + // Test length vs index (standard trick using unsigned compare) + Node* chk = _gvn.transform( new (C, 3) CmpUNode(idx, len) ); + BoolTest::mask btest = BoolTest::lt; + tst = _gvn.transform( new (C, 2) BoolNode(chk, btest) ); + } // Branch to failure if out of bounds { BuildCutout unless(this, tst, PROB_MAX); if (C->allow_range_check_smearing()) { diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index d32053ce299..3c0e0ff3186 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -365,7 +365,7 @@ Node* Parse::expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, in const intptr_t header = arrayOopDesc::base_offset_in_bytes(T_OBJECT); for (jint i = 0; i < length_con; i++) { Node* elem = expand_multianewarray(array_klass_1, &lengths[1], ndimensions-1); - intptr_t offset = header + ((intptr_t)i << LogBytesPerWord); + intptr_t offset = header + ((intptr_t)i << LogBytesPerHeapOop); Node* eaddr = basic_plus_adr(array, offset); store_oop_to_array(control(), array, eaddr, adr_type, elem, elemtype, T_OBJECT); } @@ -408,7 +408,7 @@ void Parse::do_multianewarray() { jint dim_con = find_int_con(length[j], -1); expand_fanout *= dim_con; expand_count += expand_fanout; // count the level-J sub-arrays - if (dim_con < 0 + if (dim_con <= 0 || dim_con > expand_limit || expand_count > expand_limit) { expand_count = 0; diff --git a/hotspot/src/share/vm/opto/phaseX.cpp b/hotspot/src/share/vm/opto/phaseX.cpp index f462fe7d230..e58577451b6 100644 --- a/hotspot/src/share/vm/opto/phaseX.cpp +++ b/hotspot/src/share/vm/opto/phaseX.cpp @@ -744,20 +744,23 @@ void PhaseGVN::dead_loop_check( Node *n ) { //============================================================================= //------------------------------PhaseIterGVN----------------------------------- // Initialize hash table to fresh and clean for +VerifyOpto -PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(igvn,dummy), _worklist( ) { +PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn, const char *dummy ) : PhaseGVN(igvn,dummy), _worklist( ), + _delay_transform(false) { } //------------------------------PhaseIterGVN----------------------------------- // Initialize with previous PhaseIterGVN info; used by PhaseCCP PhaseIterGVN::PhaseIterGVN( PhaseIterGVN *igvn ) : PhaseGVN(igvn), - _worklist( igvn->_worklist ) + _worklist( igvn->_worklist ), + _delay_transform(igvn->_delay_transform) { } //------------------------------PhaseIterGVN----------------------------------- // Initialize with previous PhaseGVN info from Parser PhaseIterGVN::PhaseIterGVN( PhaseGVN *gvn ) : PhaseGVN(gvn), - _worklist(*C->for_igvn()) + _worklist(*C->for_igvn()), + _delay_transform(false) { uint max; @@ -953,6 +956,12 @@ Node* PhaseIterGVN::register_new_node_with_optimizer(Node* n, Node* orig) { //------------------------------transform-------------------------------------- // Non-recursive: idealize Node 'n' with respect to its inputs and its value Node *PhaseIterGVN::transform( Node *n ) { + if (_delay_transform) { + // Register the node but don't optimize for now + register_new_node_with_optimizer(n); + return n; + } + // If brand new node, make space in type array, and give it a type. ensure_type_or_null(n); if (type_or_null(n) == NULL) { diff --git a/hotspot/src/share/vm/opto/phaseX.hpp b/hotspot/src/share/vm/opto/phaseX.hpp index ed5526ea0b2..e040ccc8b02 100644 --- a/hotspot/src/share/vm/opto/phaseX.hpp +++ b/hotspot/src/share/vm/opto/phaseX.hpp @@ -383,6 +383,10 @@ public: // Phase for iteratively performing local, pessimistic GVN-style optimizations. // and ideal transformations on the graph. class PhaseIterGVN : public PhaseGVN { + private: + bool _delay_transform; // When true simply register the node when calling transform + // instead of actually optimizing it + // Idealize old Node 'n' with respect to its inputs and its value virtual Node *transform_old( Node *a_node ); protected: @@ -446,6 +450,10 @@ public: subsume_node(old, nn); } + void set_delay_transform(bool delay) { + _delay_transform = delay; + } + #ifndef PRODUCT protected: // Sub-quadratic implementation of VerifyIterativeGVN. diff --git a/hotspot/src/share/vm/opto/subnode.cpp b/hotspot/src/share/vm/opto/subnode.cpp index 2fc00289233..53413dfbfeb 100644 --- a/hotspot/src/share/vm/opto/subnode.cpp +++ b/hotspot/src/share/vm/opto/subnode.cpp @@ -735,6 +735,75 @@ Node *CmpPNode::Ideal( PhaseGVN *phase, bool can_reshape ) { return this; } +//============================================================================= +//------------------------------sub-------------------------------------------- +// Simplify an CmpN (compare 2 pointers) node, based on local information. +// If both inputs are constants, compare them. +const Type *CmpNNode::sub( const Type *t1, const Type *t2 ) const { + const TypePtr *r0 = t1->is_narrowoop()->make_oopptr(); // Handy access + const TypePtr *r1 = t2->is_narrowoop()->make_oopptr(); + + // Undefined inputs makes for an undefined result + if( TypePtr::above_centerline(r0->_ptr) || + TypePtr::above_centerline(r1->_ptr) ) + return Type::TOP; + + if (r0 == r1 && r0->singleton()) { + // Equal pointer constants (klasses, nulls, etc.) + return TypeInt::CC_EQ; + } + + // See if it is 2 unrelated classes. + const TypeOopPtr* p0 = r0->isa_oopptr(); + const TypeOopPtr* p1 = r1->isa_oopptr(); + if (p0 && p1) { + ciKlass* klass0 = p0->klass(); + bool xklass0 = p0->klass_is_exact(); + ciKlass* klass1 = p1->klass(); + bool xklass1 = p1->klass_is_exact(); + int kps = (p0->isa_klassptr()?1:0) + (p1->isa_klassptr()?1:0); + if (klass0 && klass1 && + kps != 1 && // both or neither are klass pointers + !klass0->is_interface() && // do not trust interfaces + !klass1->is_interface()) { + // See if neither subclasses the other, or if the class on top + // is precise. In either of these cases, the compare must fail. + if (klass0->equals(klass1) || // if types are unequal but klasses are + !klass0->is_java_klass() || // types not part of Java language? + !klass1->is_java_klass()) { // types not part of Java language? + // Do nothing; we know nothing for imprecise types + } else if (klass0->is_subtype_of(klass1)) { + // If klass1's type is PRECISE, then we can fail. + if (xklass1) return TypeInt::CC_GT; + } else if (klass1->is_subtype_of(klass0)) { + // If klass0's type is PRECISE, then we can fail. + if (xklass0) return TypeInt::CC_GT; + } else { // Neither subtypes the other + return TypeInt::CC_GT; // ...so always fail + } + } + } + + // Known constants can be compared exactly + // Null can be distinguished from any NotNull pointers + // Unknown inputs makes an unknown result + if( r0->singleton() ) { + intptr_t bits0 = r0->get_con(); + if( r1->singleton() ) + return bits0 == r1->get_con() ? TypeInt::CC_EQ : TypeInt::CC_GT; + return ( r1->_ptr == TypePtr::NotNull && bits0==0 ) ? TypeInt::CC_GT : TypeInt::CC; + } else if( r1->singleton() ) { + intptr_t bits1 = r1->get_con(); + return ( r0->_ptr == TypePtr::NotNull && bits1==0 ) ? TypeInt::CC_GT : TypeInt::CC; + } else + return TypeInt::CC; +} + +//------------------------------Ideal------------------------------------------ +Node *CmpNNode::Ideal( PhaseGVN *phase, bool can_reshape ) { + return NULL; +} + //============================================================================= //------------------------------Value------------------------------------------ // Simplify an CmpF (compare 2 floats ) node, based on local information. diff --git a/hotspot/src/share/vm/opto/subnode.hpp b/hotspot/src/share/vm/opto/subnode.hpp index 4992a59c555..8d01e2328d2 100644 --- a/hotspot/src/share/vm/opto/subnode.hpp +++ b/hotspot/src/share/vm/opto/subnode.hpp @@ -163,6 +163,16 @@ public: virtual const Type *sub( const Type *, const Type * ) const; }; +//------------------------------CmpNNode-------------------------------------- +// Compare 2 narrow oop values, returning condition codes (-1, 0 or 1). +class CmpNNode : public CmpNode { +public: + CmpNNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {} + virtual int Opcode() const; + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual const Type *sub( const Type *, const Type * ) const; +}; + //------------------------------CmpLNode--------------------------------------- // Compare 2 long values, returning condition codes (-1, 0 or 1). class CmpLNode : public CmpNode { diff --git a/hotspot/src/share/vm/opto/superword.cpp b/hotspot/src/share/vm/opto/superword.cpp index 625acd85efa..5e3a7bb70e1 100644 --- a/hotspot/src/share/vm/opto/superword.cpp +++ b/hotspot/src/share/vm/opto/superword.cpp @@ -65,6 +65,11 @@ void SuperWord::transform_loop(IdealLoopTree* lpt) { Node *cl_exit = cl->loopexit(); if (cl_exit->in(0) != lpt->_head) return; + // Make sure the are no extra control users of the loop backedge + if (cl->back_control()->outcnt() != 1) { + return; + } + // Check for pre-loop ending with CountedLoopEnd(Bool(Cmp(x,Opaque1(limit)))) CountedLoopEndNode* pre_end = get_pre_loop_end(cl); if (pre_end == NULL) return; @@ -1419,6 +1424,7 @@ int SuperWord::memory_alignment(MemNode* s, int iv_adjust_in_bytes) { //---------------------------container_type--------------------------- // Smallest type containing range of values const Type* SuperWord::container_type(const Type* t) { + if (t->isa_narrowoop()) t = t->is_narrowoop()->make_oopptr(); if (t->isa_aryptr()) { t = t->is_aryptr()->elem(); } diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index 333fb476b0f..0715ef22a46 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -40,6 +40,7 @@ const BasicType Type::_basic_type[Type::lastype] = { T_INT, // Int T_LONG, // Long T_VOID, // Half + T_NARROWOOP, // NarrowOop T_ILLEGAL, // Tuple T_ARRAY, // Array @@ -279,15 +280,6 @@ void Type::Initialize_shared(Compile* current) { TypeRawPtr::BOTTOM = TypeRawPtr::make( TypePtr::BotPTR ); TypeRawPtr::NOTNULL= TypeRawPtr::make( TypePtr::NotNull ); - mreg2type[Op_Node] = Type::BOTTOM; - mreg2type[Op_Set ] = 0; - mreg2type[Op_RegI] = TypeInt::INT; - mreg2type[Op_RegP] = TypePtr::BOTTOM; - mreg2type[Op_RegF] = Type::FLOAT; - mreg2type[Op_RegD] = Type::DOUBLE; - mreg2type[Op_RegL] = TypeLong::LONG; - mreg2type[Op_RegFlags] = TypeInt::CC; - const Type **fmembar = TypeTuple::fields(0); TypeTuple::MEMBAR = TypeTuple::make(TypeFunc::Parms+0, fmembar); @@ -305,6 +297,19 @@ void Type::Initialize_shared(Compile* current) { false, 0, oopDesc::klass_offset_in_bytes()); TypeOopPtr::BOTTOM = TypeOopPtr::make(TypePtr::BotPTR, OffsetBot); + TypeNarrowOop::NULL_PTR = TypeNarrowOop::make( TypePtr::NULL_PTR ); + TypeNarrowOop::BOTTOM = TypeNarrowOop::make( TypeInstPtr::BOTTOM ); + + mreg2type[Op_Node] = Type::BOTTOM; + mreg2type[Op_Set ] = 0; + mreg2type[Op_RegN] = TypeNarrowOop::BOTTOM; + mreg2type[Op_RegI] = TypeInt::INT; + mreg2type[Op_RegP] = TypePtr::BOTTOM; + mreg2type[Op_RegF] = Type::FLOAT; + mreg2type[Op_RegD] = Type::DOUBLE; + mreg2type[Op_RegL] = TypeLong::LONG; + mreg2type[Op_RegFlags] = TypeInt::CC; + TypeAryPtr::RANGE = TypeAryPtr::make( TypePtr::BotPTR, TypeAry::make(Type::BOTTOM,TypeInt::POS), current->env()->Object_klass(), false, arrayOopDesc::length_offset_in_bytes()); // There is no shared klass for Object[]. See note in TypeAryPtr::klass(). TypeAryPtr::OOPS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInstPtr::BOTTOM,TypeInt::POS), NULL /*ciArrayKlass::make(o)*/, false, Type::OffsetBot); @@ -316,6 +321,7 @@ void Type::Initialize_shared(Compile* current) { TypeAryPtr::FLOATS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::FLOAT ,TypeInt::POS), ciTypeArrayKlass::make(T_FLOAT), true, Type::OffsetBot); TypeAryPtr::DOUBLES = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::DOUBLE ,TypeInt::POS), ciTypeArrayKlass::make(T_DOUBLE), true, Type::OffsetBot); + TypeAryPtr::_array_body_type[T_NARROWOOP] = NULL; // what should this be? TypeAryPtr::_array_body_type[T_OBJECT] = TypeAryPtr::OOPS; TypeAryPtr::_array_body_type[T_ARRAY] = TypeAryPtr::OOPS; // arrays are stored in oop arrays TypeAryPtr::_array_body_type[T_BYTE] = TypeAryPtr::BYTES; @@ -345,6 +351,7 @@ void Type::Initialize_shared(Compile* current) { longpair[1] = TypeLong::LONG; TypeTuple::LONG_PAIR = TypeTuple::make(2, longpair); + _const_basic_type[T_NARROWOOP] = TypeNarrowOop::BOTTOM; _const_basic_type[T_BOOLEAN] = TypeInt::BOOL; _const_basic_type[T_CHAR] = TypeInt::CHAR; _const_basic_type[T_BYTE] = TypeInt::BYTE; @@ -359,6 +366,7 @@ void Type::Initialize_shared(Compile* current) { _const_basic_type[T_ADDRESS] = TypeRawPtr::BOTTOM; // both interpreter return addresses & random raw ptrs _const_basic_type[T_CONFLICT]= Type::BOTTOM; // why not? + _zero_type[T_NARROWOOP] = TypeNarrowOop::NULL_PTR; _zero_type[T_BOOLEAN] = TypeInt::ZERO; // false == 0 _zero_type[T_CHAR] = TypeInt::ZERO; // '\0' == 0 _zero_type[T_BYTE] = TypeInt::ZERO; // 0x00 == 0 @@ -400,6 +408,10 @@ void Type::Initialize(Compile* current) { Type* t = (Type*)i._value; tdic->Insert(t,t); // New Type, insert into Type table } + +#ifdef ASSERT + verify_lastype(); +#endif } //------------------------------hashcons--------------------------------------- @@ -467,7 +479,19 @@ bool Type::is_nan() const { // Compute the MEET of two types. NOT virtual. It enforces that meet is // commutative and the lattice is symmetric. const Type *Type::meet( const Type *t ) const { + if (isa_narrowoop() && t->isa_narrowoop()) { + const Type* result = is_narrowoop()->make_oopptr()->meet(t->is_narrowoop()->make_oopptr()); + if (result->isa_oopptr()) { + return result->isa_oopptr()->make_narrowoop(); + } else if (result == TypePtr::NULL_PTR) { + return TypeNarrowOop::NULL_PTR; + } else { + return result; + } + } + const Type *mt = xmeet(t); + if (isa_narrowoop() || t->isa_narrowoop()) return mt; #ifdef ASSERT assert( mt == t->xmeet(this), "meet not commutative" ); const Type* dual_join = mt->_dual; @@ -556,6 +580,9 @@ const Type *Type::xmeet( const Type *t ) const { case AryPtr: return t->xmeet(this); + case NarrowOop: + return t->xmeet(this); + case Bad: // Type check default: // Bogus type not in lattice typerr(t); @@ -613,6 +640,7 @@ const Type::TYPES Type::dual_type[Type::lastype] = { Bad, // Int - handled in v-call Bad, // Long - handled in v-call Half, // Half + Bad, // NarrowOop - handled in v-call Bad, // Tuple - handled in v-call Bad, // Array - handled in v-call @@ -668,11 +696,14 @@ void Type::dump_on(outputStream *st) const { ResourceMark rm; Dict d(cmpkey,hashkey); // Stop recursive type dumping dump2(d,1, st); + if (isa_ptr() && is_ptr()->is_narrow()) { + st->print(" [narrow]"); + } } //------------------------------data------------------------------------------- const char * const Type::msg[Type::lastype] = { - "bad","control","top","int:","long:","half", + "bad","control","top","int:","long:","half", "narrowoop:", "tuple:", "aryptr", "anyptr:", "rawptr:", "java:", "inst:", "ary:", "klass:", "func", "abIO", "return_address", "memory", @@ -735,7 +766,7 @@ void Type::typerr( const Type *t ) const { //------------------------------isa_oop_ptr------------------------------------ // Return true if type is an oop pointer type. False for raw pointers. static char isa_oop_ptr_tbl[Type::lastype] = { - 0,0,0,0,0,0,0/*tuple*/, 0/*ary*/, + 0,0,0,0,0,0,0/*narrowoop*/,0/*tuple*/, 0/*ary*/, 0/*anyptr*/,0/*rawptr*/,1/*OopPtr*/,1/*InstPtr*/,1/*AryPtr*/,1/*KlassPtr*/, 0/*func*/,0,0/*return_address*/,0, /*floats*/0,0,0, /*doubles*/0,0,0, @@ -1051,6 +1082,7 @@ const Type *TypeInt::xmeet( const Type *t ) const { case DoubleTop: case DoubleCon: case DoubleBot: + case NarrowOop: case Bottom: // Ye Olde Default return Type::BOTTOM; default: // All else is a mistake @@ -1718,6 +1750,9 @@ inline const TypeInt* normalize_array_size(const TypeInt* size) { //------------------------------make------------------------------------------- const TypeAry *TypeAry::make( const Type *elem, const TypeInt *size) { + if (UseCompressedOops && elem->isa_oopptr()) { + elem = elem->is_oopptr()->make_narrowoop(); + } size = normalize_array_size(size); return (TypeAry*)(new TypeAry(elem,size))->hashcons(); } @@ -1800,14 +1835,28 @@ bool TypeAry::ary_must_be_exact() const { // In such cases, an array built on this ary must have no subclasses. if (_elem == BOTTOM) return false; // general array not exact if (_elem == TOP ) return false; // inverted general array not exact - const TypeOopPtr* toop = _elem->isa_oopptr(); + const TypeOopPtr* toop = NULL; + if (UseCompressedOops) { + const TypeNarrowOop* noop = _elem->isa_narrowoop(); + if (noop) toop = noop->make_oopptr()->isa_oopptr(); + } else { + toop = _elem->isa_oopptr(); + } if (!toop) return true; // a primitive type, like int ciKlass* tklass = toop->klass(); if (tklass == NULL) return false; // unloaded class if (!tklass->is_loaded()) return false; // unloaded class - const TypeInstPtr* tinst = _elem->isa_instptr(); + const TypeInstPtr* tinst; + if (_elem->isa_narrowoop()) + tinst = _elem->is_narrowoop()->make_oopptr()->isa_instptr(); + else + tinst = _elem->isa_instptr(); if (tinst) return tklass->as_instance_klass()->is_final(); - const TypeAryPtr* tap = _elem->isa_aryptr(); + const TypeAryPtr* tap; + if (_elem->isa_narrowoop()) + tap = _elem->is_narrowoop()->make_oopptr()->isa_aryptr(); + else + tap = _elem->isa_aryptr(); if (tap) return tap->ary()->ary_must_be_exact(); return false; } @@ -1864,6 +1913,7 @@ const Type *TypePtr::xmeet( const Type *t ) const { case DoubleTop: case DoubleCon: case DoubleBot: + case NarrowOop: case Bottom: // Ye Olde Default return Type::BOTTOM; case Top: @@ -2455,6 +2505,10 @@ const TypePtr *TypeOopPtr::add_offset( int offset ) const { return make( _ptr, xadd_offset(offset) ); } +const TypeNarrowOop* TypeOopPtr::make_narrowoop() const { + return TypeNarrowOop::make(this); +} + int TypeOopPtr::meet_instance(int iid) const { if (iid == 0) { return (_instance_id < 0) ? _instance_id : UNKNOWN_INSTANCE; @@ -2607,6 +2661,7 @@ const Type *TypeInstPtr::xmeet( const Type *t ) const { case DoubleTop: case DoubleCon: case DoubleBot: + case NarrowOop: case Bottom: // Ye Olde Default return Type::BOTTOM; case Top: @@ -3021,6 +3076,9 @@ static jint max_array_length(BasicType etype) { jint res = cache; if (res == 0) { switch (etype) { + case T_NARROWOOP: + etype = T_OBJECT; + break; case T_CONFLICT: case T_ILLEGAL: case T_VOID: @@ -3093,6 +3151,7 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const { case DoubleTop: case DoubleCon: case DoubleBot: + case NarrowOop: case Bottom: // Ye Olde Default return Type::BOTTOM; case Top: @@ -3292,6 +3351,124 @@ const TypePtr *TypeAryPtr::add_offset( int offset ) const { } +//============================================================================= +const TypeNarrowOop *TypeNarrowOop::BOTTOM; +const TypeNarrowOop *TypeNarrowOop::NULL_PTR; + + +const TypeNarrowOop* TypeNarrowOop::make(const TypePtr* type) { + return (const TypeNarrowOop*)(new TypeNarrowOop(type))->hashcons(); +} + +//------------------------------hash------------------------------------------- +// Type-specific hashing function. +int TypeNarrowOop::hash(void) const { + return _ooptype->hash() + 7; +} + + +bool TypeNarrowOop::eq( const Type *t ) const { + const TypeNarrowOop* tc = t->isa_narrowoop(); + if (tc != NULL) { + if (_ooptype->base() != tc->_ooptype->base()) { + return false; + } + return tc->_ooptype->eq(_ooptype); + } + return false; +} + +bool TypeNarrowOop::singleton(void) const { // TRUE if type is a singleton + return _ooptype->singleton(); +} + +bool TypeNarrowOop::empty(void) const { + return _ooptype->empty(); +} + +//------------------------------meet------------------------------------------- +// Compute the MEET of two types. It returns a new Type object. +const Type *TypeNarrowOop::xmeet( const Type *t ) const { + // Perform a fast test for common case; meeting the same types together. + if( this == t ) return this; // Meeting same type-rep? + + + // Current "this->_base" is OopPtr + switch (t->base()) { // switch on original type + + case Int: // Mixing ints & oops happens when javac + case Long: // reuses local variables + case FloatTop: + case FloatCon: + case FloatBot: + case DoubleTop: + case DoubleCon: + case DoubleBot: + case Bottom: // Ye Olde Default + return Type::BOTTOM; + case Top: + return this; + + case NarrowOop: { + const Type* result = _ooptype->xmeet(t->is_narrowoop()->make_oopptr()); + if (result->isa_ptr()) { + return TypeNarrowOop::make(result->is_ptr()); + } + return result; + } + + default: // All else is a mistake + typerr(t); + + case RawPtr: + case AnyPtr: + case OopPtr: + case InstPtr: + case KlassPtr: + case AryPtr: + typerr(t); + return Type::BOTTOM; + + } // End of switch +} + +const Type *TypeNarrowOop::xdual() const { // Compute dual right now. + const TypePtr* odual = _ooptype->dual()->is_ptr(); + return new TypeNarrowOop(odual); +} + +const Type *TypeNarrowOop::filter( const Type *kills ) const { + if (kills->isa_narrowoop()) { + const Type* ft =_ooptype->filter(kills->is_narrowoop()->_ooptype); + if (ft->empty()) + return Type::TOP; // Canonical empty value + if (ft->isa_ptr()) { + return make(ft->isa_ptr()); + } + return ft; + } else if (kills->isa_ptr()) { + const Type* ft = _ooptype->join(kills); + if (ft->empty()) + return Type::TOP; // Canonical empty value + return ft; + } else { + return Type::TOP; + } +} + + +intptr_t TypeNarrowOop::get_con() const { + return _ooptype->get_con(); +} + +#ifndef PRODUCT +void TypeNarrowOop::dump2( Dict & d, uint depth, outputStream *st ) const { + tty->print("narrowoop: "); + _ooptype->dump2(d, depth, st); +} +#endif + + //============================================================================= // Convenience common pre-built types. @@ -3341,28 +3518,33 @@ ciKlass* TypeAryPtr::klass() const { ciKlass* k_ary = NULL; const TypeInstPtr *tinst; const TypeAryPtr *tary; + const Type* el = elem(); + if (el->isa_narrowoop()) { + el = el->is_narrowoop()->make_oopptr(); + } + // Get element klass - if ((tinst = elem()->isa_instptr()) != NULL) { + if ((tinst = el->isa_instptr()) != NULL) { // Compute array klass from element klass k_ary = ciObjArrayKlass::make(tinst->klass()); - } else if ((tary = elem()->isa_aryptr()) != NULL) { + } else if ((tary = el->isa_aryptr()) != NULL) { // Compute array klass from element klass ciKlass* k_elem = tary->klass(); // If element type is something like bottom[], k_elem will be null. if (k_elem != NULL) k_ary = ciObjArrayKlass::make(k_elem); - } else if ((elem()->base() == Type::Top) || - (elem()->base() == Type::Bottom)) { + } else if ((el->base() == Type::Top) || + (el->base() == Type::Bottom)) { // element type of Bottom occurs from meet of basic type // and object; Top occurs when doing join on Bottom. // Leave k_ary at NULL. } else { // Cannot compute array klass directly from basic type, // since subtypes of TypeInt all have basic type T_INT. - assert(!elem()->isa_int(), + assert(!el->isa_int(), "integral arrays must be pre-equipped with a class"); // Compute array klass directly from basic type - k_ary = ciTypeArrayKlass::make(elem()->basic_type()); + k_ary = ciTypeArrayKlass::make(el->basic_type()); } if( this != TypeAryPtr::OOPS ) @@ -3710,7 +3892,7 @@ void TypeFunc::dump2( Dict &d, uint depth, outputStream *st ) const { //------------------------------print_flattened-------------------------------- // Print a 'flattened' signature static const char * const flat_type_msg[Type::lastype] = { - "bad","control","top","int","long","_", + "bad","control","top","int","long","_", "narrowoop", "tuple:", "array:", "ptr", "rawptr", "ptr", "ptr", "ptr", "ptr", "func", "abIO", "return_address", "mem", diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index c68205f8880..194d3438fa3 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -41,6 +41,7 @@ class TypeD; class TypeF; class TypeInt; class TypeLong; +class TypeNarrowOop; class TypeAry; class TypeTuple; class TypePtr; @@ -64,6 +65,7 @@ public: Int, // Integer range (lo-hi) Long, // Long integer range (lo-hi) Half, // Placeholder half of doubleword + NarrowOop, // Compressed oop pointer Tuple, // Method signature or object layout Array, // Array types @@ -188,6 +190,11 @@ public: // Currently, it also works around limitations involving interface types. virtual const Type *filter( const Type *kills ) const; + // Returns true if this pointer points at memory which contains a + // compressed oop references. In 32-bit builds it's non-virtual + // since we don't support compressed oops at all in the mode. + LP64_ONLY(virtual) bool is_narrow() const { return false; } + // Convenience access float getf() const; double getd() const; @@ -204,15 +211,18 @@ public: const TypeAry *is_ary() const; // Array, NOT array pointer const TypePtr *is_ptr() const; // Asserts it is a ptr type const TypePtr *isa_ptr() const; // Returns NULL if not ptr type - const TypeRawPtr *is_rawptr() const; // NOT Java oop - const TypeOopPtr *isa_oopptr() const; // Returns NULL if not ptr type - const TypeKlassPtr *isa_klassptr() const; // Returns NULL if not KlassPtr - const TypeKlassPtr *is_klassptr() const; // assert if not KlassPtr - const TypeOopPtr *is_oopptr() const; // Java-style GC'd pointer - const TypeInstPtr *isa_instptr() const; // Returns NULL if not InstPtr - const TypeInstPtr *is_instptr() const; // Instance - const TypeAryPtr *isa_aryptr() const; // Returns NULL if not AryPtr - const TypeAryPtr *is_aryptr() const; // Array oop + const TypeRawPtr *isa_rawptr() const; // NOT Java oop + const TypeRawPtr *is_rawptr() const; // Asserts is rawptr + const TypeNarrowOop *is_narrowoop() const; // Java-style GC'd pointer + const TypeNarrowOop *isa_narrowoop() const; // Returns NULL if not oop ptr type + const TypeOopPtr *isa_oopptr() const; // Returns NULL if not oop ptr type + const TypeOopPtr *is_oopptr() const; // Java-style GC'd pointer + const TypeKlassPtr *isa_klassptr() const; // Returns NULL if not KlassPtr + const TypeKlassPtr *is_klassptr() const; // assert if not KlassPtr + const TypeInstPtr *isa_instptr() const; // Returns NULL if not InstPtr + const TypeInstPtr *is_instptr() const; // Instance + const TypeAryPtr *isa_aryptr() const; // Returns NULL if not AryPtr + const TypeAryPtr *is_aryptr() const; // Array oop virtual bool is_finite() const; // Has a finite value virtual bool is_nan() const; // Is not a number (NaN) @@ -432,6 +442,7 @@ public: // Check for single integer int is_con() const { return _lo==_hi; } + bool is_con(int i) const { return is_con() && _lo == i; } jlong get_con() const { assert( is_con(), "" ); return _lo; } virtual bool is_finite() const; // Has a finite value @@ -540,6 +551,7 @@ public: // Otherwise the _base will indicate which subset of pointers is affected, // and the class will be inherited from. class TypePtr : public Type { + friend class TypeNarrowOop; public: enum PTR { TopPTR, AnyNull, Constant, Null, NotNull, BotPTR, lastPTR }; protected: @@ -701,6 +713,15 @@ public: virtual const TypePtr *add_offset( int offset ) const; + // returns the equivalent compressed version of this pointer type + virtual const TypeNarrowOop* make_narrowoop() const; + +#ifdef _LP64 + virtual bool is_narrow() const { + return (UseCompressedOops && _offset != 0); + } +#endif + virtual const Type *xmeet( const Type *t ) const; virtual const Type *xdual() const; // Compute dual right now. @@ -822,6 +843,12 @@ public: virtual const Type *xmeet( const Type *t ) const; virtual const Type *xdual() const; // Compute dual right now. +#ifdef _LP64 + virtual bool is_narrow() const { + return (UseCompressedOops && klass() != NULL && _offset != 0); + } +#endif + // Convenience common pre-built types. static const TypeAryPtr *RANGE; static const TypeAryPtr *OOPS; @@ -874,6 +901,18 @@ public: virtual const Type *xmeet( const Type *t ) const; virtual const Type *xdual() const; // Compute dual right now. +#ifdef _LP64 + // Perm objects don't use compressed references, except for static fields + // which are currently compressed + virtual bool is_narrow() const { + if (UseCompressedOops && _offset != 0 && _klass->is_instance_klass()) { + ciInstanceKlass* ik = _klass->as_instance_klass(); + return ik != NULL && ik->get_field_by_offset(_offset, true) != NULL; + } + return false; + } +#endif + // Convenience common pre-built types. static const TypeKlassPtr* OBJECT; // Not-null object klass or below static const TypeKlassPtr* OBJECT_OR_NULL; // Maybe-null version of same @@ -882,6 +921,56 @@ public: #endif }; +//------------------------------TypeNarrowOop---------------------------------------- +// A compressed reference to some kind of Oop. This type wraps around +// a preexisting TypeOopPtr and forwards most of it's operations to +// the underlying type. It's only real purpose is to track the +// oopness of the compressed oop value when we expose the conversion +// between the normal and the compressed form. +class TypeNarrowOop : public Type { +protected: + const TypePtr* _ooptype; + + TypeNarrowOop( const TypePtr* ooptype): Type(NarrowOop), + _ooptype(ooptype) { + assert(ooptype->offset() == 0 || + ooptype->offset() == OffsetBot || + ooptype->offset() == OffsetTop, "no real offsets"); + } +public: + virtual bool eq( const Type *t ) const; + virtual int hash() const; // Type specific hashing + virtual bool singleton(void) const; // TRUE if type is a singleton + + virtual const Type *xmeet( const Type *t ) const; + virtual const Type *xdual() const; // Compute dual right now. + + virtual intptr_t get_con() const; + + // Do not allow interface-vs.-noninterface joins to collapse to top. + virtual const Type *filter( const Type *kills ) const; + + virtual bool empty(void) const; // TRUE if type is vacuous + + static const TypeNarrowOop *make( const TypePtr* type); + + static const TypeNarrowOop* make_from_constant(ciObject* con) { + return make(TypeOopPtr::make_from_constant(con)); + } + + // returns the equivalent oopptr type for this compressed pointer + virtual const TypePtr *make_oopptr() const { + return _ooptype; + } + + static const TypeNarrowOop *BOTTOM; + static const TypeNarrowOop *NULL_PTR; + +#ifndef PRODUCT + virtual void dump2( Dict &d, uint depth, outputStream *st ) const; +#endif +}; + //------------------------------TypeFunc--------------------------------------- // Class of Array Types class TypeFunc : public Type { @@ -1002,6 +1091,10 @@ inline const TypeOopPtr *Type::isa_oopptr() const { return (_base >= OopPtr && _base <= KlassPtr) ? (TypeOopPtr*)this : NULL; } +inline const TypeRawPtr *Type::isa_rawptr() const { + return (_base == RawPtr) ? (TypeRawPtr*)this : NULL; +} + inline const TypeRawPtr *Type::is_rawptr() const { assert( _base == RawPtr, "Not a raw pointer" ); return (TypeRawPtr*)this; @@ -1025,6 +1118,17 @@ inline const TypeAryPtr *Type::is_aryptr() const { return (TypeAryPtr*)this; } +inline const TypeNarrowOop *Type::is_narrowoop() const { + // OopPtr is the first and KlassPtr the last, with no non-oops between. + assert(_base == NarrowOop, "Not a narrow oop" ) ; + return (TypeNarrowOop*)this; +} + +inline const TypeNarrowOop *Type::isa_narrowoop() const { + // OopPtr is the first and KlassPtr the last, with no non-oops between. + return (_base == NarrowOop) ? (TypeNarrowOop*)this : NULL; +} + inline const TypeKlassPtr *Type::isa_klassptr() const { return (_base == KlassPtr) ? (TypeKlassPtr*)this : NULL; } diff --git a/hotspot/src/share/vm/prims/forte.cpp b/hotspot/src/share/vm/prims/forte.cpp index efda11f6a7a..70f785d80b4 100644 --- a/hotspot/src/share/vm/prims/forte.cpp +++ b/hotspot/src/share/vm/prims/forte.cpp @@ -25,6 +25,20 @@ # include "incls/_precompiled.incl" # include "incls/_forte.cpp.incl" +// These name match the names reported by the forte quality kit +enum { + ticks_no_Java_frame = 0, + ticks_no_class_load = -1, + ticks_GC_active = -2, + ticks_unknown_not_Java = -3, + ticks_not_walkable_not_Java = -4, + ticks_unknown_Java = -5, + ticks_not_walkable_Java = -6, + ticks_unknown_state = -7, + ticks_thread_exit = -8, + ticks_deopt = -9, + ticks_safepoint = -10 +}; //------------------------------------------------------- @@ -41,297 +55,29 @@ class vframeStreamForte : public vframeStreamCommon { }; -static void forte_is_walkable_compiled_frame(frame* fr, RegisterMap* map, +static void is_decipherable_compiled_frame(frame* fr, RegisterMap* map, bool* is_compiled_p, bool* is_walkable_p); -static bool forte_is_walkable_interpreted_frame(frame* fr, - methodOop* method_p, int* bci_p); +static bool is_decipherable_interpreted_frame(JavaThread* thread, + frame* fr, + methodOop* method_p, + int* bci_p); -// A Forte specific version of frame:safe_for_sender(). -static bool forte_safe_for_sender(frame* fr, JavaThread *thread) { - bool ret_value = false; // be pessimistic - -#ifdef COMPILER2 -#if defined(IA32) || defined(AMD64) - { - // This check is the same as the standard safe_for_sender() - // on IA32 or AMD64 except that NULL FP values are tolerated - // for C2. - address sp = (address)fr->sp(); - address fp = (address)fr->fp(); - ret_value = sp != NULL && sp <= thread->stack_base() && - sp >= thread->stack_base() - thread->stack_size() && - (fp == NULL || (fp <= thread->stack_base() && - fp >= thread->stack_base() - thread->stack_size())); - - // We used to use standard safe_for_sender() when we are supposed - // to be executing Java code. However, that prevents us from - // walking some intrinsic stacks so now we have to be more refined. - // If we passed the above check and we have a NULL frame pointer - // and we are supposed to be executing Java code, then we have a - // couple of more checks to make. - if (ret_value && fp == NULL && (thread->thread_state() == _thread_in_Java - || thread->thread_state() == _thread_in_Java_trans)) { - - if (fr->is_interpreted_frame()) { - // interpreted frames don't really have a NULL frame pointer - return false; - } else if (CodeCache::find_blob(fr->pc()) == NULL) { - // the NULL frame pointer should be associated with generated code - return false; - } - } - } - -#else // !(IA32 || AMD64) - ret_value = fr->safe_for_sender(thread); -#endif // IA32 || AMD64 - -#else // !COMPILER2 - ret_value = fr->safe_for_sender(thread); -#endif // COMPILER2 - - if (!ret_value) { - return ret_value; // not safe, nothing more to do - } - - address sp1; - -#ifdef SPARC - // On Solaris SPARC, when a compiler frame has an interpreted callee - // the _interpreter_sp_adjustment field contains the adjustment to - // this frame's SP made by that interpreted callee. - // For AsyncGetCallTrace(), we need to verify that the resulting SP - // is valid for the specified thread's stack. - sp1 = (address)fr->sp(); - address sp2 = (address)fr->unextended_sp(); - - // If the second SP is NULL, then the _interpreter_sp_adjustment - // field simply adjusts this frame's SP to NULL and the frame is - // not safe. This strange value can be set in the frame constructor - // when our peek into the interpreted callee's adjusted value for - // this frame's SP finds a NULL. This can happen when SIGPROF - // catches us while we are creating the interpreter frame. - // - if (sp2 == NULL || - - // If the two SPs are different, then _interpreter_sp_adjustment - // is non-zero and we need to validate the second SP. We invert - // the range check from frame::safe_for_sender() and bail out - // if the second SP is not safe. - (sp1 != sp2 && !(sp2 <= thread->stack_base() - && sp2 >= (thread->stack_base() - thread->stack_size())))) { - return false; - } -#endif // SPARC - - if (fr->is_entry_frame()) { - // This frame thinks it is an entry frame; we need to validate - // the JavaCallWrapper pointer. - // Note: frame::entry_frame_is_first() assumes that the - // JavaCallWrapper has a non-NULL _anchor field. We don't - // check that here (yet) since we've never seen a failure - // due to a NULL _anchor field. - // Update: Originally this check was done only for SPARC. However, - // this failure has now been seen on C2 C86. I have no reason to - // believe that this is not a general issue so I'm enabling the - // check for all compilers on all supported platforms. -#ifdef COMPILER2 -#if defined(IA32) || defined(AMD64) - if (fr->fp() == NULL) { - // C2 X86 allows NULL frame pointers, but if we have one then - // we cannot call entry_frame_call_wrapper(). - return false; - } -#endif // IA32 || AMD64 -#endif // COMPILER2 - - sp1 = (address)fr->entry_frame_call_wrapper(); - // We invert the range check from frame::safe_for_sender() and - // bail out if the JavaCallWrapper * is not safe. - if (!(sp1 <= thread->stack_base() - && sp1 >= (thread->stack_base() - thread->stack_size()))) { - return false; - } - } - - return ret_value; -} -// Unknown compiled frames have caused assertion failures on Solaris -// X86. This code also detects unknown compiled frames on Solaris -// SPARC, but no assertion failures have been observed. However, I'm -// paranoid so I'm enabling this code whenever we have a compiler. -// -// Returns true if the specified frame is an unknown compiled frame -// and false otherwise. -static bool is_unknown_compiled_frame(frame* fr, JavaThread *thread) { - bool ret_value = false; // be optimistic +vframeStreamForte::vframeStreamForte(JavaThread *jt, + frame fr, + bool stop_at_java_call_stub) : vframeStreamCommon(jt) { - // This failure mode only occurs when the thread is in state - // _thread_in_Java so we are okay for this check for any other - // thread state. - // - // Note: _thread_in_Java does not always mean that the thread - // is executing Java code. AsyncGetCallTrace() has caught - // threads executing in JRT_LEAF() routines when the state - // will also be _thread_in_Java. - if (thread->thread_state() != _thread_in_Java) { - return ret_value; - } - - // This failure mode only occurs with compiled frames so we are - // okay for this check for both entry and interpreted frames. - if (fr->is_entry_frame() || fr->is_interpreted_frame()) { - return ret_value; - } - - // This failure mode only occurs when the compiled frame's PC - // is in the code cache so we are okay for this check if the - // PC is not in the code cache. - CodeBlob* cb = CodeCache::find_blob(fr->pc()); - if (cb == NULL) { - return ret_value; - } - - // We have compiled code in the code cache so it is time for - // the final check: let's see if any frame type is set - ret_value = !( - // is_entry_frame() is checked above - // testers that are a subset of is_entry_frame(): - // is_first_frame() - fr->is_java_frame() - // testers that are a subset of is_java_frame(): - // is_interpreted_frame() - // is_compiled_frame() - || fr->is_native_frame() - || fr->is_runtime_frame() - || fr->is_safepoint_blob_frame() - ); - - // If there is no frame type set, then we have an unknown compiled - // frame and sender() should not be called on it. - - return ret_value; -} - -#define DebugNonSafepoints_IS_CLEARED \ - (!FLAG_IS_DEFAULT(DebugNonSafepoints) && !DebugNonSafepoints) - -// if -XX:-DebugNonSafepoints, then top-frame will be skipped -vframeStreamForte::vframeStreamForte(JavaThread *jt, frame fr, - bool stop_at_java_call_stub) : vframeStreamCommon(jt) { _stop_at_java_call_stub = stop_at_java_call_stub; + _frame = fr; - if (!DebugNonSafepoints_IS_CLEARED) { - // decode the top frame fully - // (usual case, if JVMTI is enabled) - _frame = fr; - } else { - // skip top frame, as it may not be at safepoint - // For AsyncGetCallTrace(), we extracted as much info from the top - // frame as we could in forte_is_walkable_frame(). We also verified - // forte_safe_for_sender() so this sender() call is safe. - _frame = fr.sender(&_reg_map); - } + // We must always have a valid frame to start filling - if (jt->thread_state() == _thread_in_Java && !fr.is_first_frame()) { - bool sender_check = false; // assume sender is not safe + bool filled_in = fill_from_frame(); - if (forte_safe_for_sender(&_frame, jt)) { - // If the initial sender frame is safe, then continue on with other - // checks. The unsafe sender frame has been seen on Solaris X86 - // with both Compiler1 and Compiler2. It has not been seen on - // Solaris SPARC, but seems like a good sanity check to have - // anyway. + assert(filled_in, "invariant"); - // SIGPROF caught us in Java code and the current frame is not the - // first frame so we should sanity check the sender frame. It is - // possible for SIGPROF to catch us in the middle of making a call. - // When that happens the current frame is actually a combination of - // the real sender and some of the new call's info. We can't find - // the real sender with such a current frame and things can get - // confused. - // - // This sanity check has caught problems with the sender frame on - // Solaris SPARC. So far Solaris X86 has not had a failure here. - sender_check = _frame.is_entry_frame() - // testers that are a subset of is_entry_frame(): - // is_first_frame() - || _frame.is_java_frame() - // testers that are a subset of is_java_frame(): - // is_interpreted_frame() - // is_compiled_frame() - || _frame.is_native_frame() - || _frame.is_runtime_frame() - || _frame.is_safepoint_blob_frame() - ; - - // We need an additional sanity check on an initial interpreted - // sender frame. This interpreted frame needs to be both walkable - // and have a valid BCI. This is yet another variant of SIGPROF - // catching us in the middle of making a call. - if (sender_check && _frame.is_interpreted_frame()) { - methodOop method = NULL; - int bci = -1; - - if (!forte_is_walkable_interpreted_frame(&_frame, &method, &bci) - || bci == -1) { - sender_check = false; - } - } - - // We need an additional sanity check on an initial compiled - // sender frame. This compiled frame also needs to be walkable. - // This is yet another variant of SIGPROF catching us in the - // middle of making a call. - if (sender_check && !_frame.is_interpreted_frame()) { - bool is_compiled, is_walkable; - - forte_is_walkable_compiled_frame(&_frame, &_reg_map, - &is_compiled, &is_walkable); - if (is_compiled && !is_walkable) { - sender_check = false; - } - } - } - - if (!sender_check) { - // nothing else to try if we can't recognize the sender - _mode = at_end_mode; - return; - } - } - - int loop_count = 0; - int loop_max = MaxJavaStackTraceDepth * 2; - - while (!fill_from_frame()) { - _frame = _frame.sender(&_reg_map); - -#ifdef COMPILER2 -#if defined(IA32) || defined(AMD64) - // Stress testing on C2 X86 has shown a periodic problem with - // the sender() call below. The initial _frame that we have on - // entry to the loop has already passed forte_safe_for_sender() - // so we only check frames after it. - if (!forte_safe_for_sender(&_frame, _thread)) { - _mode = at_end_mode; - return; - } -#endif // IA32 || AMD64 -#endif // COMPILER2 - - if (++loop_count >= loop_max) { - // We have looped more than twice the number of possible - // Java frames. This indicates that we are trying to walk - // a stack that is in the middle of being constructed and - // it is self referential. - _mode = at_end_mode; - return; - } - } } @@ -358,95 +104,57 @@ void vframeStreamForte::forte_next() { do { -#if defined(COMPILER1) && defined(SPARC) - bool prevIsInterpreted = _frame.is_interpreted_frame(); -#endif // COMPILER1 && SPARC + loop_count++; + + // By the time we get here we should never see unsafe but better + // safe then segv'd + + if (loop_count > loop_max || !_frame.safe_for_sender(_thread)) { + _mode = at_end_mode; + return; + } _frame = _frame.sender(&_reg_map); - if (!forte_safe_for_sender(&_frame, _thread)) { - _mode = at_end_mode; - return; - } - -#if defined(COMPILER1) && defined(SPARC) - if (prevIsInterpreted) { - // previous callee was interpreted and may require a special check - if (_frame.is_compiled_frame() && _frame.cb()->is_compiled_by_c1()) { - // compiled sender called interpreted callee so need one more check - bool is_compiled, is_walkable; - - // sanity check the compiled sender frame - forte_is_walkable_compiled_frame(&_frame, &_reg_map, - &is_compiled, &is_walkable); - assert(is_compiled, "sanity check"); - if (!is_walkable) { - // compiled sender frame is not walkable so bail out - _mode = at_end_mode; - return; - } - } - } -#endif // COMPILER1 && SPARC - - if (++loop_count >= loop_max) { - // We have looped more than twice the number of possible - // Java frames. This indicates that we are trying to walk - // a stack that is in the middle of being constructed and - // it is self referential. - _mode = at_end_mode; - return; - } } while (!fill_from_frame()); } -// Determine if 'fr' is a walkable, compiled frame. -// *is_compiled_p is set to true if the frame is compiled and if it -// is, then *is_walkable_p is set to true if it is also walkable. -static void forte_is_walkable_compiled_frame(frame* fr, RegisterMap* map, - bool* is_compiled_p, bool* is_walkable_p) { +// Determine if 'fr' is a decipherable compiled frame. We are already +// assured that fr is for a java nmethod. - *is_compiled_p = false; - *is_walkable_p = false; +static bool is_decipherable_compiled_frame(frame* fr) { - CodeBlob* cb = CodeCache::find_blob(fr->pc()); - if (cb != NULL && - cb->is_nmethod() && - ((nmethod*)cb)->is_java_method()) { - // frame is compiled and executing a Java method - *is_compiled_p = true; + assert(fr->cb() != NULL && fr->cb()->is_nmethod(), "invariant"); + nmethod* nm = (nmethod*) fr->cb(); + assert(nm->is_java_method(), "invariant"); - // Increment PC because the PcDesc we want is associated with - // the *end* of the instruction, and pc_desc_near searches - // forward to the first matching PC after the probe PC. - PcDesc* pc_desc = NULL; - if (!DebugNonSafepoints_IS_CLEARED) { - // usual case: look for any safepoint near the sampled PC - address probe_pc = fr->pc() + 1; - pc_desc = ((nmethod*) cb)->pc_desc_near(probe_pc); - } else { - // reduced functionality: only recognize PCs immediately after calls - pc_desc = ((nmethod*) cb)->pc_desc_at(fr->pc()); + // First try and find an exact PcDesc + + PcDesc* pc_desc = nm->pc_desc_at(fr->pc()); + + // Did we find a useful PcDesc? + if (pc_desc != NULL && + pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) { + + address probe_pc = fr->pc() + 1; + pc_desc = nm->pc_desc_near(probe_pc); + + // Now do we have a useful PcDesc? + + if (pc_desc != NULL && + pc_desc->scope_decode_offset() == DebugInformationRecorder::serialized_null) { + // No debug information available for this pc + // vframeStream would explode if we try and walk the frames. + return false; } - if (pc_desc != NULL && (pc_desc->scope_decode_offset() - == DebugInformationRecorder::serialized_null)) { - pc_desc = NULL; - } - if (pc_desc != NULL) { - // it has a PcDesc so the frame is also walkable - *is_walkable_p = true; - if (!DebugNonSafepoints_IS_CLEARED) { - // Normalize the PC to the one associated exactly with - // this PcDesc, so that subsequent stack-walking queries - // need not be approximate: - fr->set_pc(pc_desc->real_pc((nmethod*) cb)); - } - } - // Implied else: this compiled frame has no PcDesc, i.e., contains - // a frameless stub such as C1 method exit, so it is not walkable. + + // This PcDesc is useful however we must adjust the frame's pc + // so that the vframeStream lookups will use this same pc + + fr->set_pc(pc_desc->real_pc(nm)); } - // Implied else: this isn't a compiled frame so it isn't a - // walkable, compiled frame. + + return true; } // Determine if 'fr' is a walkable interpreted frame. Returns false @@ -457,159 +165,189 @@ static void forte_is_walkable_compiled_frame(frame* fr, RegisterMap* map, // Note: this method returns true when a valid Java method is found // even if a valid BCI cannot be found. -static bool forte_is_walkable_interpreted_frame(frame* fr, - methodOop* method_p, int* bci_p) { +static bool is_decipherable_interpreted_frame(JavaThread* thread, + frame* fr, + methodOop* method_p, + int* bci_p) { assert(fr->is_interpreted_frame(), "just checking"); // top frame is an interpreted frame // check if it is walkable (i.e. valid methodOop and valid bci) - if (fr->is_interpreted_frame_valid()) { - if (fr->fp() != NULL) { - // access address in order not to trigger asserts that - // are built in interpreter_frame_method function - methodOop method = *fr->interpreter_frame_method_addr(); - if (Universe::heap()->is_valid_method(method)) { - intptr_t bcx = fr->interpreter_frame_bcx(); - int bci = method->validate_bci_from_bcx(bcx); - // note: bci is set to -1 if not a valid bci - *method_p = method; - *bci_p = bci; - return true; - } - } + + // Because we may be racing a gc thread the method and/or bci + // of a valid interpreter frame may look bad causing us to + // fail the is_interpreted_frame_valid test. If the thread + // is in any of the following states we are assured that the + // frame is in fact valid and we must have hit the race. + + JavaThreadState state = thread->thread_state(); + bool known_valid = (state == _thread_in_native || + state == _thread_in_vm || + state == _thread_blocked ); + + if (known_valid || fr->is_interpreted_frame_valid(thread)) { + + // The frame code should completely validate the frame so that + // references to methodOop and bci are completely safe to access + // If they aren't the frame code should be fixed not this + // code. However since gc isn't locked out the values could be + // stale. This is a race we can never completely win since we can't + // lock out gc so do one last check after retrieving their values + // from the frame for additional safety + + methodOop method = fr->interpreter_frame_method(); + + // We've at least found a method. + // NOTE: there is something to be said for the approach that + // if we don't find a valid bci then the method is not likely + // a valid method. Then again we may have caught an interpreter + // frame in the middle of construction and the bci field is + // not yet valid. + + *method_p = method; + + // See if gc may have invalidated method since we validated frame + + if (!Universe::heap()->is_valid_method(method)) return false; + + intptr_t bcx = fr->interpreter_frame_bcx(); + + int bci = method->validate_bci_from_bcx(bcx); + + // note: bci is set to -1 if not a valid bci + *bci_p = bci; + return true; } + return false; } -// Determine if 'fr' can be used to find a walkable frame. Returns -// false if a walkable frame cannot be found. *walkframe_p, *method_p, -// and *bci_p are not set when false is returned. Returns true if a -// walkable frame is returned via *walkframe_p. *method_p is non-NULL -// if the returned frame was executing a Java method. *bci_p is != -1 -// if a valid BCI in the Java method could be found. +// Determine if 'fr' can be used to find an initial Java frame. +// Return false if it can not find a fully decipherable Java frame +// (in other words a frame that isn't safe to use in a vframe stream). +// Obviously if it can't even find a Java frame false will also be returned. +// +// If we find a Java frame decipherable or not then by definition we have +// identified a method and that will be returned to the caller via method_p. +// If we can determine a bci that is returned also. (Hmm is it possible +// to return a method and bci and still return false? ) +// +// The initial Java frame we find (if any) is return via initial_frame_p. // -// *walkframe_p will be used by vframeStreamForte as the initial -// frame for walking the stack. Currently the initial frame is -// skipped by vframeStreamForte because we inherited the logic from -// the vframeStream class. This needs to be revisited in the future. -static bool forte_is_walkable_frame(JavaThread* thread, frame* fr, - frame* walkframe_p, methodOop* method_p, int* bci_p) { - if (!forte_safe_for_sender(fr, thread) - || is_unknown_compiled_frame(fr, thread) - ) { - // If the initial frame is not safe, then bail out. So far this - // has only been seen on Solaris X86 with Compiler2, but it seems - // like a great initial sanity check. - return false; - } +static bool find_initial_Java_frame(JavaThread* thread, + frame* fr, + frame* initial_frame_p, + methodOop* method_p, + int* bci_p) { - if (fr->is_first_frame()) { - // If initial frame is frame from StubGenerator and there is no - // previous anchor, there are no java frames yet - return false; - } + // It is possible that for a frame containing an nmethod + // we can capture the method but no bci. If we get no + // bci the frame isn't walkable but the method is usable. + // Therefore we init the returned methodOop to NULL so the + // caller can make the distinction. + + *method_p = NULL; + + // On the initial call to this method the frame we get may not be + // recognizable to us. This should only happen if we are in a JRT_LEAF + // or something called by a JRT_LEAF method. - if (fr->is_interpreted_frame()) { - if (forte_is_walkable_interpreted_frame(fr, method_p, bci_p)) { - *walkframe_p = *fr; - return true; - } - return false; - } - // At this point we have something other than a first frame or an - // interpreted frame. - methodOop method = NULL; frame candidate = *fr; - // If we loop more than twice the number of possible Java - // frames, then this indicates that we are trying to walk - // a stack that is in the middle of being constructed and - // it is self referential. So far this problem has only - // been seen on Solaris X86 Compiler2, but it seems like - // a good robustness fix for all platforms. + // If the starting frame we were given has no codeBlob associated with + // it see if we can find such a frame because only frames with codeBlobs + // are possible Java frames. - int loop_count; - int loop_max = MaxJavaStackTraceDepth * 2; - - for (loop_count = 0; loop_count < loop_max; loop_count++) { - // determine if the candidate frame is executing a Java method - if (CodeCache::contains(candidate.pc())) { - // candidate is a compiled frame or stub routine - CodeBlob* cb = CodeCache::find_blob(candidate.pc()); - - if (cb->is_nmethod()) { - method = ((nmethod *)cb)->method(); - } - } // end if CodeCache has our PC + if (fr->cb() == NULL) { + // See if we can find a useful frame + int loop_count; + int loop_max = MaxJavaStackTraceDepth * 2; RegisterMap map(thread, false); - // we have a Java frame that seems reasonable - if (method != NULL && candidate.is_java_frame() - && candidate.sp() != NULL && candidate.pc() != NULL) { - // we need to sanity check the candidate further - bool is_compiled, is_walkable; - - forte_is_walkable_compiled_frame(&candidate, &map, &is_compiled, - &is_walkable); - if (is_compiled) { - // At this point, we know we have a compiled Java frame with - // method information that we want to return. We don't check - // the is_walkable flag here because that flag pertains to - // vframeStreamForte work that is done after we are done here. - break; - } + for (loop_count = 0; loop_count < loop_max; loop_count++) { + if (!candidate.safe_for_sender(thread)) return false; + candidate = candidate.sender(&map); + if (candidate.cb() != NULL) break; } - - // At this point, the candidate doesn't work so try the sender. - - // For AsyncGetCallTrace() we cannot assume there is a sender - // for the initial frame. The initial forte_safe_for_sender() call - // and check for is_first_frame() is done on entry to this method. - candidate = candidate.sender(&map); - if (!forte_safe_for_sender(&candidate, thread)) { - -#ifdef COMPILER2 -#if defined(IA32) || defined(AMD64) - // C2 on X86 can use the ebp register as a general purpose register - // which can cause the candidate to fail theforte_safe_for_sender() - // above. We try one more time using a NULL frame pointer (fp). - - candidate = frame(candidate.sp(), NULL, candidate.pc()); - if (!forte_safe_for_sender(&candidate, thread)) { -#endif // IA32 || AMD64 -#endif // COMPILER2 - - return false; - -#ifdef COMPILER2 -#if defined(IA32) || defined(AMD64) - } // end forte_safe_for_sender retry with NULL fp -#endif // IA32 || AMD64 -#endif // COMPILER2 - - } // end first forte_safe_for_sender check - - if (candidate.is_first_frame() - || is_unknown_compiled_frame(&candidate, thread)) { - return false; - } - } // end for loop_count - - if (method == NULL) { - // If we didn't get any method info from the candidate, then - // we have nothing to return so bail out. - return false; + if (candidate.cb() == NULL) return false; } - *walkframe_p = candidate; - *method_p = method; - *bci_p = -1; - return true; + // We have a frame known to be in the codeCache + // We will hopefully be able to figure out something to do with it. + int loop_count; + int loop_max = MaxJavaStackTraceDepth * 2; + RegisterMap map(thread, false); + + for (loop_count = 0; loop_count < loop_max; loop_count++) { + + if (candidate.is_first_frame()) { + // If initial frame is frame from StubGenerator and there is no + // previous anchor, there are no java frames associated with a method + return false; + } + + if (candidate.is_interpreted_frame()) { + if (is_decipherable_interpreted_frame(thread, &candidate, method_p, bci_p)) { + *initial_frame_p = candidate; + return true; + } + + // Hopefully we got some data + return false; + } + + if (candidate.cb()->is_nmethod()) { + + nmethod* nm = (nmethod*) candidate.cb(); + *method_p = nm->method(); + + // If the frame isn't fully decipherable then the default + // value for the bci is a signal that we don't have a bci. + // If we have a decipherable frame this bci value will + // not be used. + + *bci_p = -1; + + *initial_frame_p = candidate; + + // Native wrapper code is trivial to decode by vframeStream + + if (nm->is_native_method()) return true; + + // If it isn't decipherable then we have found a pc that doesn't + // have a PCDesc that can get us a bci however we did find + // a method + + if (!is_decipherable_compiled_frame(&candidate)) { + return false; + } + + // is_decipherable_compiled_frame may modify candidate's pc + *initial_frame_p = candidate; + + return true; + } + + // Must be some stub frame that we don't care about + + if (!candidate.safe_for_sender(thread)) return false; + candidate = candidate.sender(&map); + + // If it isn't in the code cache something is wrong + // since once we find a frame in the code cache they + // all should be there. + + if (candidate.cb() == NULL) return false; + + } + + return false; + } @@ -627,10 +365,12 @@ typedef struct { } ASGCT_CallTrace; static void forte_fill_call_trace_given_top(JavaThread* thd, - ASGCT_CallTrace* trace, int depth, frame top_frame) { + ASGCT_CallTrace* trace, + int depth, + frame top_frame) { NoHandleMark nhm; - frame walkframe; + frame initial_Java_frame; methodOop method; int bci; int count; @@ -638,48 +378,51 @@ static void forte_fill_call_trace_given_top(JavaThread* thd, count = 0; assert(trace->frames != NULL, "trace->frames must be non-NULL"); - if (!forte_is_walkable_frame(thd, &top_frame, &walkframe, &method, &bci)) { - // return if no walkable frame is found - return; - } + bool fully_decipherable = find_initial_Java_frame(thd, &top_frame, &initial_Java_frame, &method, &bci); + + // The frame might not be walkable but still recovered a method + // (e.g. an nmethod with no scope info for the pc + + if (method == NULL) return; CollectedHeap* ch = Universe::heap(); - if (method != NULL) { - // The method is not stored GC safe so see if GC became active - // after we entered AsyncGetCallTrace() and before we try to - // use the methodOop. - // Yes, there is still a window after this check and before - // we use methodOop below, but we can't lock out GC so that - // has to be an acceptable risk. - if (!ch->is_valid_method(method)) { - trace->num_frames = -2; - return; - } - - if (DebugNonSafepoints_IS_CLEARED) { - // Take whatever method the top-frame decoder managed to scrape up. - // We look further at the top frame only if non-safepoint - // debugging information is available. - count++; - trace->num_frames = count; - trace->frames[0].method_id = method->find_jmethod_id_or_null(); - if (!method->is_native()) { - trace->frames[0].lineno = bci; - } else { - trace->frames[0].lineno = -3; - } - } - } - - // check has_last_Java_frame() after looking at the top frame - // which may be an interpreted Java frame. - if (!thd->has_last_Java_frame() && method == NULL) { - trace->num_frames = 0; + // The method is not stored GC safe so see if GC became active + // after we entered AsyncGetCallTrace() and before we try to + // use the methodOop. + // Yes, there is still a window after this check and before + // we use methodOop below, but we can't lock out GC so that + // has to be an acceptable risk. + if (!ch->is_valid_method(method)) { + trace->num_frames = ticks_GC_active; // -2 return; } - vframeStreamForte st(thd, walkframe, false); + // We got a Java frame however it isn't fully decipherable + // so it won't necessarily be safe to use it for the + // initial frame in the vframe stream. + + if (!fully_decipherable) { + // Take whatever method the top-frame decoder managed to scrape up. + // We look further at the top frame only if non-safepoint + // debugging information is available. + count++; + trace->num_frames = count; + trace->frames[0].method_id = method->find_jmethod_id_or_null(); + if (!method->is_native()) { + trace->frames[0].lineno = bci; + } else { + trace->frames[0].lineno = -3; + } + + if (!initial_Java_frame.safe_for_sender(thd)) return; + + RegisterMap map(thd, false); + initial_Java_frame = initial_Java_frame.sender(&map); + } + + vframeStreamForte st(thd, initial_Java_frame, false); + for (; !st.at_end() && count < depth; st.forte_next(), count++) { bci = st.bci(); method = st.method(); @@ -693,7 +436,7 @@ static void forte_fill_call_trace_given_top(JavaThread* thd, if (!ch->is_valid_method(method)) { // we throw away everything we've gathered in this sample since // none of it is safe - trace->num_frames = -2; + trace->num_frames = ticks_GC_active; // -2 return; } @@ -765,6 +508,11 @@ static void forte_fill_call_trace_given_top(JavaThread* thd, extern "C" { void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { + +// This is if'd out because we no longer use thread suspension. +// However if someone wanted to backport this to a 5.0 jvm then this +// code would be important. +#if 0 if (SafepointSynchronize::is_synchronizing()) { // The safepoint mechanism is trying to synchronize all the threads. // Since this can involve thread suspension, it is not safe for us @@ -774,9 +522,10 @@ void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { // are suspended while holding a resource and another thread blocks // on that resource in the SIGPROF handler, then we will have a // three-thread deadlock (VMThread, this thread, the other thread). - trace->num_frames = -10; + trace->num_frames = ticks_safepoint; // -10 return; } +#endif JavaThread* thread; @@ -785,13 +534,13 @@ void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { thread->is_exiting()) { // bad env_id, thread has exited or thread is exiting - trace->num_frames = -8; + trace->num_frames = ticks_thread_exit; // -8 return; } if (thread->in_deopt_handler()) { // thread is in the deoptimization handler so return no frames - trace->num_frames = -9; + trace->num_frames = ticks_deopt; // -9 return; } @@ -799,12 +548,12 @@ void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { "AsyncGetCallTrace must be called by the current interrupted thread"); if (!JvmtiExport::should_post_class_load()) { - trace->num_frames = -1; + trace->num_frames = ticks_no_class_load; // -1 return; } if (Universe::heap()->is_gc_active()) { - trace->num_frames = -2; + trace->num_frames = ticks_GC_active; // -2 return; } @@ -827,14 +576,22 @@ void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { // param isInJava == false - indicate we aren't in Java code if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, false)) { - if (!thread->has_last_Java_frame()) { - trace->num_frames = 0; // no Java frames - } else { - trace->num_frames = -3; // unknown frame - } + trace->num_frames = ticks_unknown_not_Java; // -3 unknown frame } else { - trace->num_frames = -4; // non walkable frame by default - forte_fill_call_trace_given_top(thread, trace, depth, fr); + if (!thread->has_last_Java_frame()) { + trace->num_frames = 0; // No Java frames + } else { + trace->num_frames = ticks_not_walkable_not_Java; // -4 non walkable frame by default + forte_fill_call_trace_given_top(thread, trace, depth, fr); + + // This assert would seem to be valid but it is not. + // It would be valid if we weren't possibly racing a gc + // thread. A gc thread can make a valid interpreted frame + // look invalid. It's a small window but it does happen. + // The assert is left here commented out as a reminder. + // assert(trace->num_frames != ticks_not_walkable_not_Java, "should always be walkable"); + + } } } break; @@ -845,16 +602,16 @@ void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { // param isInJava == true - indicate we are in Java code if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, true)) { - trace->num_frames = -5; // unknown frame + trace->num_frames = ticks_unknown_Java; // -5 unknown frame } else { - trace->num_frames = -6; // non walkable frame by default + trace->num_frames = ticks_not_walkable_Java; // -6, non walkable frame by default forte_fill_call_trace_given_top(thread, trace, depth, fr); } } break; default: // Unknown thread state - trace->num_frames = -7; + trace->num_frames = ticks_unknown_state; // -7 break; } } diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index 6f31afc986e..91fb8cb3c17 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -135,7 +135,10 @@ intptr_t jfieldIDWorkaround::encode_klass_hash(klassOop k, intptr_t offset) { if (offset <= small_offset_mask) { klassOop field_klass = k; klassOop super_klass = Klass::cast(field_klass)->super(); - while (instanceKlass::cast(super_klass)->contains_field_offset(offset)) { + // With compressed oops the most super class with nonstatic fields would + // be the owner of fields embedded in the header. + while (instanceKlass::cast(super_klass)->has_nonstatic_fields() && + instanceKlass::cast(super_klass)->contains_field_offset(offset)) { field_klass = super_klass; // super contains the field also super_klass = Klass::cast(field_klass)->super(); } diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 9a2cbf3676c..deaba3a9ed7 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -4168,6 +4168,36 @@ JVM_ENTRY(jboolean, JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fid, jlong o return res == oldVal; JVM_END +// DTrace /////////////////////////////////////////////////////////////////// + +JVM_ENTRY(jint, JVM_DTraceGetVersion(JNIEnv* env)) + JVMWrapper("JVM_DTraceGetVersion"); + return (jint)JVM_TRACING_DTRACE_VERSION; +JVM_END + +JVM_ENTRY(jlong,JVM_DTraceActivate( + JNIEnv* env, jint version, jstring module_name, jint providers_count, + JVM_DTraceProvider* providers)) + JVMWrapper("JVM_DTraceActivate"); + return DTraceJSDT::activate( + version, module_name, providers_count, providers, CHECK_0); +JVM_END + +JVM_ENTRY(jboolean,JVM_DTraceIsProbeEnabled(JNIEnv* env, jmethodID method)) + JVMWrapper("JVM_DTraceIsProbeEnabled"); + return DTraceJSDT::is_probe_enabled(method); +JVM_END + +JVM_ENTRY(void,JVM_DTraceDispose(JNIEnv* env, jlong handle)) + JVMWrapper("JVM_DTraceDispose"); + DTraceJSDT::dispose(handle); +JVM_END + +JVM_ENTRY(jboolean,JVM_DTraceIsSupported(JNIEnv* env)) + JVMWrapper("JVM_DTraceIsSupported"); + return DTraceJSDT::is_supported(); +JVM_END + // Returns an array of all live Thread objects (VM internal JavaThreads, // jvmti agent threads, and JNI attaching threads are skipped) // See CR 6404306 regarding JNI attaching threads @@ -4496,3 +4526,4 @@ JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t i #endif // KERNEL } JVM_END + diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index a8012ce8b54..feaf0d4a13f 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -606,6 +606,83 @@ JVM_SupportsCX8(void); JNIEXPORT jboolean JNICALL JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fldID, jlong oldVal, jlong newVal); +/* + * com.sun.dtrace.jsdt support + */ + +#define JVM_TRACING_DTRACE_VERSION 1 + +/* + * Structure to pass one probe description to JVM. + * + * The VM will overwrite the definition of the referenced method with + * code that will fire the probe. + */ +typedef struct { + jmethodID method; + jstring function; + jstring name; + void* reserved[4]; // for future use +} JVM_DTraceProbe; + +/** + * Encapsulates the stability ratings for a DTrace provider field + */ +typedef struct { + jint nameStability; + jint dataStability; + jint dependencyClass; +} JVM_DTraceInterfaceAttributes; + +/* + * Structure to pass one provider description to JVM + */ +typedef struct { + jstring name; + JVM_DTraceProbe* probes; + jint probe_count; + JVM_DTraceInterfaceAttributes providerAttributes; + JVM_DTraceInterfaceAttributes moduleAttributes; + JVM_DTraceInterfaceAttributes functionAttributes; + JVM_DTraceInterfaceAttributes nameAttributes; + JVM_DTraceInterfaceAttributes argsAttributes; + void* reserved[4]; // for future use +} JVM_DTraceProvider; + +/* + * Get the version number the JVM was built with + */ +JNIEXPORT jint JNICALL +JVM_DTraceGetVersion(JNIEnv* env); + +/* + * Register new probe with given signature, return global handle + * + * The version passed in is the version that the library code was + * built with. + */ +JNIEXPORT jlong JNICALL +JVM_DTraceActivate(JNIEnv* env, jint version, jstring module_name, + jint providers_count, JVM_DTraceProvider* providers); + +/* + * Check JSDT probe + */ +JNIEXPORT jboolean JNICALL +JVM_DTraceIsProbeEnabled(JNIEnv* env, jmethodID method); + +/* + * Destroy custom DOF + */ +JNIEXPORT void JNICALL +JVM_DTraceDispose(JNIEnv* env, jlong handle); + +/* + * Check to see if DTrace is supported by OS + */ +JNIEXPORT jboolean JNICALL +JVM_DTraceIsSupported(JNIEnv* env); + /************************************************************************* PART 2: Support for the Verifier and Class File Format Checker ************************************************************************/ diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp index 23e46ede884..30d9fee4611 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp @@ -2662,6 +2662,7 @@ class SimpleRootsClosure : public OopClosure { _continue = CallbackInvoker::report_simple_root(kind, o); } + virtual void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } }; // A supporting closure used to process JNI locals @@ -2704,6 +2705,7 @@ class JNILocalRootsClosure : public OopClosure { // invoke the callback _continue = CallbackInvoker::report_jni_local_root(_thread_tag, _tid, _depth, _method, o); } + virtual void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } }; @@ -2878,9 +2880,11 @@ inline bool VM_HeapWalkOperation::iterate_over_type_array(oop o) { } // verify that a static oop field is in range -static inline bool verify_static_oop(instanceKlass* ik, oop* obj_p) { - oop* start = ik->start_of_static_fields(); - oop* end = start + ik->static_oop_field_size(); +static inline bool verify_static_oop(instanceKlass* ik, + klassOop k, int offset) { + address obj_p = (address)k + offset; + address start = (address)ik->start_of_static_fields(); + address end = start + (ik->static_oop_field_size() * heapOopSize); assert(end >= start, "sanity check"); if (obj_p >= start && obj_p < end) { @@ -2981,10 +2985,8 @@ inline bool VM_HeapWalkOperation::iterate_over_class(klassOop k) { ClassFieldDescriptor* field = field_map->field_at(i); char type = field->field_type(); if (!is_primitive_field_type(type)) { - address addr = (address)k + field->field_offset(); - oop* f = (oop*)addr; - assert(verify_static_oop(ik, f), "sanity check"); - oop fld_o = *f; + oop fld_o = k->obj_field(field->field_offset()); + assert(verify_static_oop(ik, k, field->field_offset()), "sanity check"); if (fld_o != NULL) { int slot = field->field_index(); if (!CallbackInvoker::report_static_field_reference(mirror, fld_o, slot)) { @@ -3026,9 +3028,7 @@ inline bool VM_HeapWalkOperation::iterate_over_object(oop o) { ClassFieldDescriptor* field = field_map->field_at(i); char type = field->field_type(); if (!is_primitive_field_type(type)) { - address addr = (address)o + field->field_offset(); - oop* f = (oop*)addr; - oop fld_o = *f; + oop fld_o = o->obj_field(field->field_offset()); if (fld_o != NULL) { // reflection code may have a reference to a klassOop. // - see sun.reflect.UnsafeStaticFieldAccessorImpl and sun.misc.Unsafe diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index adea250987c..899a99296be 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -100,7 +100,7 @@ inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) { assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset"); if (byte_offset == (jint)byte_offset) { void* ptr_plus_disp = (address)p + byte_offset; - assert((void*)p->obj_field_addr((jint)byte_offset) == ptr_plus_disp, + assert((void*)p->obj_field_addr((jint)byte_offset) == ptr_plus_disp, "raw [ptr+disp] must be consistent with oop::field_base"); } } @@ -146,13 +146,36 @@ jint Unsafe_invocation_key_to_method_slot(jint key) { *(volatile type_name*)index_oop_from_field_offset_long(p, offset) = x; \ OrderAccess::fence(); +// Macros for oops that check UseCompressedOops + +#define GET_OOP_FIELD(obj, offset, v) \ + oop p = JNIHandles::resolve(obj); \ + oop v; \ + if (UseCompressedOops) { \ + narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset); \ + v = oopDesc::decode_heap_oop(n); \ + } else { \ + v = *(oop*)index_oop_from_field_offset_long(p, offset); \ + } + +#define GET_OOP_FIELD_VOLATILE(obj, offset, v) \ + oop p = JNIHandles::resolve(obj); \ + volatile oop v; \ + if (UseCompressedOops) { \ + volatile narrowOop n = *(volatile narrowOop*)index_oop_from_field_offset_long(p, offset); \ + v = oopDesc::decode_heap_oop(n); \ + } else { \ + v = *(volatile oop*)index_oop_from_field_offset_long(p, offset); \ + } + + // Get/SetObject must be special-cased, since it works with handles. // The xxx140 variants for backward compatibility do not allow a full-width offset. UNSAFE_ENTRY(jobject, Unsafe_GetObject140(JNIEnv *env, jobject unsafe, jobject obj, jint offset)) UnsafeWrapper("Unsafe_GetObject"); if (obj == NULL) THROW_0(vmSymbols::java_lang_NullPointerException()); - GET_FIELD(obj, offset, oop, v); + GET_OOP_FIELD(obj, offset, v) return JNIHandles::make_local(env, v); UNSAFE_END @@ -162,11 +185,21 @@ UNSAFE_ENTRY(void, Unsafe_SetObject140(JNIEnv *env, jobject unsafe, jobject obj, oop x = JNIHandles::resolve(x_h); //SET_FIELD(obj, offset, oop, x); oop p = JNIHandles::resolve(obj); - if (x != NULL) { - // If there is a heap base pointer, we are obliged to emit a store barrier. - oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); + if (UseCompressedOops) { + if (x != NULL) { + // If there is a heap base pointer, we are obliged to emit a store barrier. + oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x); + } else { + narrowOop n = oopDesc::encode_heap_oop_not_null(x); + *(narrowOop*)index_oop_from_field_offset_long(p, offset) = n; + } } else { - *(oop*)index_oop_from_field_offset_long(p, offset) = x; + if (x != NULL) { + // If there is a heap base pointer, we are obliged to emit a store barrier. + oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); + } else { + *(oop*)index_oop_from_field_offset_long(p, offset) = x; + } } UNSAFE_END @@ -175,7 +208,7 @@ UNSAFE_END // That is, it should be in the range [0, MAX_OBJECT_SIZE]. UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) UnsafeWrapper("Unsafe_GetObject"); - GET_FIELD(obj, offset, oop, v); + GET_OOP_FIELD(obj, offset, v) return JNIHandles::make_local(env, v); UNSAFE_END @@ -183,12 +216,16 @@ UNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jl UnsafeWrapper("Unsafe_SetObject"); oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); - oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); + if (UseCompressedOops) { + oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x); + } else { + oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); + } UNSAFE_END UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) UnsafeWrapper("Unsafe_GetObjectVolatile"); - GET_FIELD_VOLATILE(obj, offset, oop, v); + GET_OOP_FIELD_VOLATILE(obj, offset, v) return JNIHandles::make_local(env, v); UNSAFE_END @@ -196,7 +233,11 @@ UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject UnsafeWrapper("Unsafe_SetObjectVolatile"); oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); - oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); + if (UseCompressedOops) { + oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x); + } else { + oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); + } OrderAccess::fence(); UNSAFE_END @@ -311,7 +352,11 @@ UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject UnsafeWrapper("Unsafe_SetOrderedObject"); oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); - oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); + if (UseCompressedOops) { + oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x); + } else { + oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); + } OrderAccess::fence(); UNSAFE_END @@ -647,7 +692,7 @@ static void getBaseAndScale(int& base, int& scale, jclass acls, TRAPS) { THROW(vmSymbols::java_lang_InvalidClassException()); } else if (k->klass_part()->oop_is_objArray()) { base = arrayOopDesc::base_offset_in_bytes(T_OBJECT); - scale = oopSize; + scale = heapOopSize; } else if (k->klass_part()->oop_is_typeArray()) { typeArrayKlass* tak = typeArrayKlass::cast(k); base = tak->array_header_in_bytes(); @@ -845,11 +890,11 @@ UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, oop x = JNIHandles::resolve(x_h); oop e = JNIHandles::resolve(e_h); oop p = JNIHandles::resolve(obj); - intptr_t* addr = (intptr_t *)index_oop_from_field_offset_long(p, offset); - intptr_t res = Atomic::cmpxchg_ptr((intptr_t)x, addr, (intptr_t)e); - jboolean success = (res == (intptr_t)e); + HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset); + oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e); + jboolean success = (res == e); if (success) - update_barrier_set((oop*)addr, x); + update_barrier_set((void*)addr, x); return success; UNSAFE_END diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index a02fa09832f..aa8331bfd40 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1125,6 +1125,11 @@ void Arguments::set_cms_and_parnew_gc_flags() { } } +inline uintx max_heap_for_compressed_oops() { + LP64_ONLY(return oopDesc::OopEncodingHeapMax - MaxPermSize - os::vm_page_size()); + NOT_LP64(return DefaultMaxRAM); +} + bool Arguments::should_auto_select_low_pause_collector() { if (UseAutoGCSelectPolicy && !FLAG_IS_DEFAULT(MaxGCPauseMillis) && @@ -1163,6 +1168,31 @@ void Arguments::set_ergonomics_flags() { no_shared_spaces(); } } + +#ifdef _LP64 + // Compressed Headers do not work with CMS, which uses a bit in the klass + // field offset to determine free list chunk markers. + // Check that UseCompressedOops can be set with the max heap size allocated + // by ergonomics. + if (!UseConcMarkSweepGC && MaxHeapSize <= max_heap_for_compressed_oops()) { + if (FLAG_IS_DEFAULT(UseCompressedOops)) { + FLAG_SET_ERGO(bool, UseCompressedOops, true); + } + } else { + if (UseCompressedOops && !FLAG_IS_DEFAULT(UseCompressedOops)) { + // If specified, give a warning + if (UseConcMarkSweepGC){ + warning("Compressed Oops does not work with CMS"); + } else { + warning( + "Max heap size too large for Compressed Oops"); + } + FLAG_SET_DEFAULT(UseCompressedOops, false); + } + } + // Also checks that certain machines are slower with compressed oops + // in vm_version initialization code. +#endif // _LP64 } void Arguments::set_parallel_gc_flags() { @@ -1180,7 +1210,10 @@ void Arguments::set_parallel_gc_flags() { if (FLAG_IS_DEFAULT(MaxHeapSize)) { const uint64_t reasonable_fraction = os::physical_memory() / DefaultMaxRAMFraction; - const uint64_t maximum_size = (uint64_t) DefaultMaxRAM; + const uint64_t maximum_size = (uint64_t) + (FLAG_IS_DEFAULT(DefaultMaxRAM) && UseCompressedOops ? + MIN2(max_heap_for_compressed_oops(), DefaultMaxRAM) : + DefaultMaxRAM); size_t reasonable_max = (size_t) os::allocatable_physical_memory(reasonable_fraction); if (reasonable_max > maximum_size) { diff --git a/hotspot/src/share/vm/runtime/atomic.cpp b/hotspot/src/share/vm/runtime/atomic.cpp index 299d2b00af6..847cf086196 100644 --- a/hotspot/src/share/vm/runtime/atomic.cpp +++ b/hotspot/src/share/vm/runtime/atomic.cpp @@ -44,3 +44,15 @@ jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte* dest, jbyte compare_ } return cur_as_bytes[offset]; } + +unsigned Atomic::xchg(unsigned int exchange_value, volatile unsigned int* dest) { + assert(sizeof(unsigned int) == sizeof(jint), "more work to do"); + return (unsigned int)Atomic::xchg((jint)exchange_value, (volatile jint*)dest); +} + +unsigned Atomic::cmpxchg(unsigned int exchange_value, + volatile unsigned int* dest, unsigned int compare_value) { + assert(sizeof(unsigned int) == sizeof(jint), "more work to do"); + return (unsigned int)Atomic::cmpxchg((jint)exchange_value, (volatile jint*)dest, + (jint)compare_value); +} diff --git a/hotspot/src/share/vm/runtime/atomic.hpp b/hotspot/src/share/vm/runtime/atomic.hpp index cfbda4ba7f7..a8b7dfa7ab9 100644 --- a/hotspot/src/share/vm/runtime/atomic.hpp +++ b/hotspot/src/share/vm/runtime/atomic.hpp @@ -55,7 +55,10 @@ class Atomic : AllStatic { static void dec_ptr(volatile void* dest); // Performs atomic exchange of *dest with exchange_value. Returns old prior value of *dest. - static jint xchg (jint exchange_value, volatile jint* dest); + static jint xchg(jint exchange_value, volatile jint* dest); + static unsigned int xchg(unsigned int exchange_value, + volatile unsigned int* dest); + static intptr_t xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest); static void* xchg_ptr(void* exchange_value, volatile void* dest); @@ -65,6 +68,11 @@ class Atomic : AllStatic { static jbyte cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value); static jint cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value); static jlong cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value); + + static unsigned int cmpxchg(unsigned int exchange_value, + volatile unsigned int* dest, + unsigned int compare_value); + static intptr_t cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* dest, intptr_t compare_value); static void* cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value); }; diff --git a/hotspot/src/share/vm/runtime/dtraceJSDT.cpp b/hotspot/src/share/vm/runtime/dtraceJSDT.cpp new file mode 100644 index 00000000000..57095dec4ed --- /dev/null +++ b/hotspot/src/share/vm/runtime/dtraceJSDT.cpp @@ -0,0 +1,117 @@ +/* + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +#include "incls/_precompiled.incl" +#include "incls/_dtraceJSDT.cpp.incl" + +#ifdef HAVE_DTRACE_H + +jlong DTraceJSDT::activate( + jint version, jstring module_name, jint providers_count, + JVM_DTraceProvider* providers, TRAPS) { + + size_t count = 0; + RegisteredProbes* probes = NULL; + + if (!is_supported()) { + return 0; + } + + assert(module_name != NULL, "valid module name"); + assert(providers != NULL, "valid provider array"); + + for (int i = 0; i < providers_count; ++i) { + count += providers[i].probe_count; + } + probes = new RegisteredProbes(count); + count = 0; + + for (int i = 0; i < providers_count; ++i) { + assert(providers[i].name != NULL, "valid provider name"); + assert(providers[i].probe_count == 0 || providers[i].probes != NULL, + "valid probe count"); + for (int j = 0; j < providers[i].probe_count; ++j) { + JVM_DTraceProbe* probe = &(providers[i].probes[j]); + assert(probe != NULL, "valid probe"); + assert(probe->method != NULL, "valid method"); + assert(probe->name != NULL, "valid probe name"); + assert(probe->function != NULL, "valid probe function spec"); + methodHandle h_method = + methodHandle(THREAD, JNIHandles::resolve_jmethod_id(probe->method)); + nmethod* nm = AdapterHandlerLibrary::create_dtrace_nmethod(h_method); + h_method()->set_not_compilable(CompLevel_highest_tier); + h_method()->set_code(h_method, nm); + probes->nmethod_at_put(count++, nm); + } + } + + int handle = pd_activate((void*)probes, + module_name, providers_count, providers); + if (handle <= 0) { + delete probes; + THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), + "Unable to register DTrace probes (internal error)."); + } + probes->set_helper_handle(handle); + return RegisteredProbes::toOpaqueProbes(probes); +} + +jboolean DTraceJSDT::is_probe_enabled(jmethodID method) { + methodOop m = JNIHandles::resolve_jmethod_id(method); + return nativeInstruction_at(m->code()->trap_address())->is_dtrace_trap(); +} + +void DTraceJSDT::dispose(OpaqueProbes probes) { + RegisteredProbes* p = RegisteredProbes::toRegisteredProbes(probes); + if (probes != -1 && p != NULL) { + pd_dispose(p->helper_handle()); + delete p; + } +} + +jboolean DTraceJSDT::is_supported() { + return pd_is_supported(); +} + +#else // HAVE_DTRACE_H + +jlong DTraceJSDT::activate( + jint version, jstring module_name, jint providers_count, + JVM_DTraceProvider* providers, TRAPS) { + return 0; +} + +jboolean DTraceJSDT::is_probe_enabled(jmethodID method) { + return false; +} + +void DTraceJSDT::dispose(OpaqueProbes probes) { + return; +} + +jboolean DTraceJSDT::is_supported() { + return false; +} + +#endif // ndef HAVE_DTRACE_H diff --git a/hotspot/src/share/vm/runtime/dtraceJSDT.hpp b/hotspot/src/share/vm/runtime/dtraceJSDT.hpp new file mode 100644 index 00000000000..37b18b04f00 --- /dev/null +++ b/hotspot/src/share/vm/runtime/dtraceJSDT.hpp @@ -0,0 +1,89 @@ +/* + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +class RegisteredProbes; +typedef jlong OpaqueProbes; + +class DTraceJSDT : AllStatic { + private: + + static int pd_activate(void* moduleBaseAddress, jstring module, + jint providers_count, JVM_DTraceProvider* providers); + static void pd_dispose(int handle); + static jboolean pd_is_supported(); + + public: + + static OpaqueProbes activate( + jint version, jstring module_name, jint providers_count, + JVM_DTraceProvider* providers, TRAPS); + static jboolean is_probe_enabled(jmethodID method); + static void dispose(OpaqueProbes handle); + static jboolean is_supported(); +}; + +class RegisteredProbes : public CHeapObj { + private: + nmethod** _nmethods; // all the probe methods + size_t _count; // number of probe methods + int _helper_handle; // DTrace-assigned identifier + + public: + RegisteredProbes(size_t count) { + _count = count; + _nmethods = NEW_C_HEAP_ARRAY(nmethod*, count); + } + + ~RegisteredProbes() { + for (size_t i = 0; i < _count; ++i) { + // Let the sweeper reclaim it + _nmethods[i]->make_not_entrant(); + _nmethods[i]->method()->clear_code(); + } + FREE_C_HEAP_ARRAY(nmethod*, _nmethods); + _nmethods = NULL; + _count = 0; + } + + static RegisteredProbes* toRegisteredProbes(OpaqueProbes p) { + return (RegisteredProbes*)(intptr_t)p; + } + + static OpaqueProbes toOpaqueProbes(RegisteredProbes* p) { + return (OpaqueProbes)(intptr_t)p; + } + + void set_helper_handle(int handle) { _helper_handle = handle; } + int helper_handle() const { return _helper_handle; } + + nmethod* nmethod_at(size_t i) { + assert(i >= 0 && i < _count, "bad nmethod index"); + return _nmethods[i]; + } + + void nmethod_at_put(size_t i, nmethod* nm) { + assert(i >= 0 && i < _count, "bad nmethod index"); + _nmethods[i] = nm; + } +}; diff --git a/hotspot/src/share/vm/runtime/fprofiler.cpp b/hotspot/src/share/vm/runtime/fprofiler.cpp index 89d9cbaa204..31f11617824 100644 --- a/hotspot/src/share/vm/runtime/fprofiler.cpp +++ b/hotspot/src/share/vm/runtime/fprofiler.cpp @@ -924,29 +924,23 @@ void FlatProfilerTask::task() { FlatProfiler::record_thread_ticks(); } -void ThreadProfiler::record_interpreted_tick(frame fr, TickPosition where, int* ticks) { +void ThreadProfiler::record_interpreted_tick(JavaThread* thread, frame fr, TickPosition where, int* ticks) { FlatProfiler::all_int_ticks++; if (!FlatProfiler::full_profile()) { return; } - if (!fr.is_interpreted_frame_valid()) { + if (!fr.is_interpreted_frame_valid(thread)) { // tick came at a bad time interpreter_ticks += 1; FlatProfiler::interpreter_ticks += 1; return; } - methodOop method = NULL; - if (fr.fp() != NULL) { - method = *fr.interpreter_frame_method_addr(); - } - if (!Universe::heap()->is_valid_method(method)) { - // tick came at a bad time, stack frame not initialized correctly - interpreter_ticks += 1; - FlatProfiler::interpreter_ticks += 1; - return; - } + // The frame has been fully validated so we can trust the method and bci + + methodOop method = *fr.interpreter_frame_method_addr(); + interpreted_update(method, where); // update byte code table @@ -997,7 +991,7 @@ void ThreadProfiler::record_tick_for_running_frame(JavaThread* thread, frame fr) // The tick happend in real code -> non VM code if (fr.is_interpreted_frame()) { interval_data_ref()->inc_interpreted(); - record_interpreted_tick(fr, tp_code, FlatProfiler::bytecode_ticks); + record_interpreted_tick(thread, fr, tp_code, FlatProfiler::bytecode_ticks); return; } @@ -1028,7 +1022,7 @@ void ThreadProfiler::record_tick_for_calling_frame(JavaThread* thread, frame fr) // The tick happend in VM code interval_data_ref()->inc_native(); if (fr.is_interpreted_frame()) { - record_interpreted_tick(fr, tp_native, FlatProfiler::bytecode_ticks_stub); + record_interpreted_tick(thread, fr, tp_native, FlatProfiler::bytecode_ticks_stub); return; } if (CodeCache::contains(fr.pc())) { diff --git a/hotspot/src/share/vm/runtime/fprofiler.hpp b/hotspot/src/share/vm/runtime/fprofiler.hpp index 5c288d2e576..371358dca13 100644 --- a/hotspot/src/share/vm/runtime/fprofiler.hpp +++ b/hotspot/src/share/vm/runtime/fprofiler.hpp @@ -135,7 +135,7 @@ private: ProfilerNode** table; private: - void record_interpreted_tick(frame fr, TickPosition where, int* ticks); + void record_interpreted_tick(JavaThread* thread, frame fr, TickPosition where, int* ticks); void record_compiled_tick (JavaThread* thread, frame fr, TickPosition where); void interpreted_update(methodOop method, TickPosition where); void compiled_update (methodOop method, TickPosition where); diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index efc74a36128..4db33fc54a3 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -1153,9 +1153,8 @@ oop* frame::oopmapreg_to_location(VMReg reg, const RegisterMap* reg_map) const { // If it is passed in a register, it got spilled in the stub frame. return (oop *)reg_map->location(reg); } else { - int sp_offset_in_stack_slots = reg->reg2stack(); - int sp_offset = sp_offset_in_stack_slots >> (LogBytesPerWord - LogBytesPerInt); - return (oop *)&unextended_sp()[sp_offset]; + int sp_offset_in_bytes = reg->reg2stack() * VMRegImpl::stack_slot_size; + return (oop*)(((address)unextended_sp()) + sp_offset_in_bytes); } } @@ -1331,8 +1330,7 @@ void frame::zap_dead_compiled_locals(JavaThread* thread, const RegisterMap* reg_ ResourceMark rm(thread); assert(_cb != NULL, "sanity check"); if (_cb->oop_maps() != NULL) { - OopMapSet::all_do(this, reg_map, &_check_oop, check_derived_oop, - &_check_value, &_zap_dead); + OopMapSet::all_do(this, reg_map, &_check_oop, check_derived_oop, &_check_value); } } diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index 5c695457063..ec13e57a296 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -108,7 +108,7 @@ class frame VALUE_OBJ_CLASS_SPEC { bool is_first_frame() const; // oldest frame? (has no sender) bool is_first_java_frame() const; // same for Java frame - bool is_interpreted_frame_valid() const; // performs sanity checks on interpreted frames. + bool is_interpreted_frame_valid(JavaThread* thread) const; // performs sanity checks on interpreted frames. // tells whether this frame is marked for deoptimization bool should_be_deoptimized() const; @@ -250,7 +250,7 @@ class frame VALUE_OBJ_CLASS_SPEC { oop interpreter_callee_receiver(symbolHandle signature) { return *interpreter_callee_receiver_addr(signature); } - oop *interpreter_callee_receiver_addr(symbolHandle signature); + oop* interpreter_callee_receiver_addr(symbolHandle signature); // expression stack (may go up or down, direction == 1 or -1) @@ -402,19 +402,25 @@ class frame VALUE_OBJ_CLASS_SPEC { # ifdef ENABLE_ZAP_DEAD_LOCALS private: class CheckValueClosure: public OopClosure { - public: void do_oop(oop* p); + public: + void do_oop(oop* p); + void do_oop(narrowOop* p) { ShouldNotReachHere(); } }; static CheckValueClosure _check_value; class CheckOopClosure: public OopClosure { - public: void do_oop(oop* p); + public: + void do_oop(oop* p); + void do_oop(narrowOop* p) { ShouldNotReachHere(); } }; static CheckOopClosure _check_oop; static void check_derived_oop(oop* base, oop* derived); class ZapDeadClosure: public OopClosure { - public: void do_oop(oop* p); + public: + void do_oop(oop* p); + void do_oop(narrowOop* p) { ShouldNotReachHere(); } }; static ZapDeadClosure _zap_dead; diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp index 139fe1c41f5..ffd62d14a66 100644 --- a/hotspot/src/share/vm/runtime/globals.cpp +++ b/hotspot/src/share/vm/runtime/globals.cpp @@ -29,7 +29,8 @@ RUNTIME_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \ MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \ MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG, \ - MATERIALIZE_MANAGEABLE_FLAG, MATERIALIZE_PRODUCT_RW_FLAG) + MATERIALIZE_MANAGEABLE_FLAG, MATERIALIZE_PRODUCT_RW_FLAG, \ + MATERIALIZE_LP64_PRODUCT_FLAG) RUNTIME_OS_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \ MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \ @@ -68,18 +69,20 @@ void Flag::print_on(outputStream* st) { if (is_uintx()) st->print("%-16lu", get_uintx()); if (is_ccstr()) { const char* cp = get_ccstr(); - const char* eol; - while ((eol = strchr(cp, '\n')) != NULL) { - char format_buffer[FORMAT_BUFFER_LEN]; - size_t llen = pointer_delta(eol, cp, sizeof(char)); - jio_snprintf(format_buffer, FORMAT_BUFFER_LEN, - "%%." SIZE_FORMAT "s", llen); - st->print(format_buffer, cp); - st->cr(); - cp = eol+1; - st->print("%5s %-35s += ", "", name); + if (cp != NULL) { + const char* eol; + while ((eol = strchr(cp, '\n')) != NULL) { + char format_buffer[FORMAT_BUFFER_LEN]; + size_t llen = pointer_delta(eol, cp, sizeof(char)); + jio_snprintf(format_buffer, FORMAT_BUFFER_LEN, + "%%." SIZE_FORMAT "s", llen); + st->print(format_buffer, cp); + st->cr(); + cp = eol+1; + st->print("%5s %-35s += ", "", name); + } + st->print("%-16s", cp); } - st->print("%-16s", cp); } st->print(" %s", kind); st->cr(); @@ -94,18 +97,21 @@ void Flag::print_as_flag(outputStream* st) { st->print("-XX:%s=" UINTX_FORMAT, name, get_uintx()); } else if (is_ccstr()) { st->print("-XX:%s=", name); - // Need to turn embedded '\n's back into separate arguments - // Not so efficient to print one character at a time, - // but the choice is to do the transformation to a buffer - // and print that. And this need not be efficient. - for (const char* cp = get_ccstr(); *cp != '\0'; cp += 1) { - switch (*cp) { - default: - st->print("%c", *cp); - break; - case '\n': - st->print(" -XX:%s=", name); - break; + const char* cp = get_ccstr(); + if (cp != NULL) { + // Need to turn embedded '\n's back into separate arguments + // Not so efficient to print one character at a time, + // but the choice is to do the transformation to a buffer + // and print that. And this need not be efficient. + for (; *cp != '\0'; cp += 1) { + switch (*cp) { + default: + st->print("%c", *cp); + break; + case '\n': + st->print(" -XX:%s=", name); + break; + } } } } else { @@ -132,6 +138,12 @@ void Flag::print_as_flag(outputStream* st) { #define RUNTIME_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{notproduct}", DEFAULT }, #endif +#ifdef _LP64 + #define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{lp64_product}", DEFAULT }, +#else + #define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) /* flag is constant */ +#endif // _LP64 + #define C1_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, "{C1 product}", DEFAULT }, #define C1_PD_PRODUCT_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, "{C1 pd product}", DEFAULT }, #ifdef PRODUCT @@ -160,7 +172,7 @@ void Flag::print_as_flag(outputStream* st) { static Flag flagTable[] = { - RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT) + RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT, RUNTIME_LP64_PRODUCT_FLAG_STRUCT) RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT) #ifdef COMPILER1 C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, C1_PD_DEVELOP_FLAG_STRUCT, C1_PRODUCT_FLAG_STRUCT, C1_PD_PRODUCT_FLAG_STRUCT, C1_NOTPRODUCT_FLAG_STRUCT) diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 1a46a00b7d9..5b2c1fda1d6 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -237,7 +237,6 @@ class CommandLineFlags { #define falseInTiered true #endif - // develop flags are settable / visible only during development and are constant in the PRODUCT version // product flags are always settable / visible // notproduct flags are settable / visible only during development and are not declared in the PRODUCT version @@ -286,7 +285,11 @@ class CommandLineFlags { // Note that when there is a need to support develop flags to be writeable, // it can be done in the same way as product_rw. -#define RUNTIME_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, manageable, product_rw) \ +#define RUNTIME_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct, manageable, product_rw, lp64_product) \ + \ + lp64_product(bool, UseCompressedOops, false, \ + "Use 32-bit object references in 64-bit VM. " \ + "lp64_product means flag is always constant in 32 bit VM") \ \ /* UseMembar is theoretically a temp flag used for memory barrier \ * removal testing. It was supposed to be removed before FCS but has \ @@ -668,16 +671,19 @@ class CommandLineFlags { notproduct(bool, PrintCompilation2, false, \ "Print additional statistics per compilation") \ \ - notproduct(bool, PrintAdapterHandlers, false, \ + diagnostic(bool, PrintAdapterHandlers, false, \ "Print code generated for i2c/c2i adapters") \ \ - develop(bool, PrintAssembly, false, \ - "Print assembly code") \ + diagnostic(bool, PrintAssembly, false, \ + "Print assembly code (using external disassembler.so)") \ \ - develop(bool, PrintNMethods, false, \ + diagnostic(ccstr, PrintAssemblyOptions, false, \ + "Options string passed to disassembler.so") \ + \ + diagnostic(bool, PrintNMethods, false, \ "Print assembly code for nmethods when generated") \ \ - develop(bool, PrintNativeNMethods, false, \ + diagnostic(bool, PrintNativeNMethods, false, \ "Print assembly code for native nmethods when generated") \ \ develop(bool, PrintDebugInfo, false, \ @@ -702,7 +708,7 @@ class CommandLineFlags { develop(bool, PrintCodeCache2, false, \ "Print detailed info on the compiled_code cache when exiting") \ \ - develop(bool, PrintStubCode, false, \ + diagnostic(bool, PrintStubCode, false, \ "Print generated stub code") \ \ product(bool, StackTraceInThrowable, true, \ @@ -773,6 +779,9 @@ class CommandLineFlags { product(bool, ClassUnloading, true, \ "Do unloading of classes") \ \ + diagnostic(bool, LinkWellKnownClasses, true, \ + "Resolve a well known class as soon as its name is seen") \ + \ develop(bool, DisableStartThread, false, \ "Disable starting of additional Java threads " \ "(for debugging only)") \ @@ -1319,6 +1328,10 @@ class CommandLineFlags { product(bool, CMSClassUnloadingEnabled, false, \ "Whether class unloading enabled when using CMS GC") \ \ + product(uintx, CMSClassUnloadingMaxInterval, 0, \ + "When CMS class unloading is enabled, the maximum CMS cycle count"\ + " for which classes may not be unloaded") \ + \ product(bool, CMSCompactWhenClearAllSoftRefs, true, \ "Compact when asked to collect CMS gen with clear_all_soft_refs") \ \ @@ -1504,17 +1517,30 @@ class CommandLineFlags { "Percentage of MinHeapFreeRatio in CMS generation that is " \ " allocated before a CMS collection cycle commences") \ \ - product(intx, CMSBootstrapOccupancy, 50, \ + product(intx, CMSTriggerPermRatio, 80, \ + "Percentage of MinHeapFreeRatio in the CMS perm generation that" \ + " is allocated before a CMS collection cycle commences, that " \ + " also collects the perm generation") \ + \ + product(uintx, CMSBootstrapOccupancy, 50, \ "Percentage CMS generation occupancy at which to " \ " initiate CMS collection for bootstrapping collection stats") \ \ product(intx, CMSInitiatingOccupancyFraction, -1, \ "Percentage CMS generation occupancy to start a CMS collection " \ - " cycle (A negative value means that CMSTirggerRatio is used)") \ + " cycle (A negative value means that CMSTriggerRatio is used)") \ + \ + product(intx, CMSInitiatingPermOccupancyFraction, -1, \ + "Percentage CMS perm generation occupancy to start a CMScollection"\ + " cycle (A negative value means that CMSTriggerPermRatio is used)")\ \ product(bool, UseCMSInitiatingOccupancyOnly, false, \ "Only use occupancy as a crierion for starting a CMS collection") \ \ + product(intx, CMSIsTooFullPercentage, 98, \ + "An absolute ceiling above which CMS will always consider the" \ + " perm gen ripe for collection") \ + \ develop(bool, CMSTestInFreeList, false, \ "Check if the coalesced range is already in the " \ "free lists as claimed.") \ @@ -1902,6 +1928,10 @@ class CommandLineFlags { develop(bool, IgnoreLibthreadGPFault, false, \ "Suppress workaround for libthread GP fault") \ \ + product(bool, PrintJNIGCStalls, false, \ + "Print diagnostic message when GC is stalled" \ + "by JNI critical section") \ + \ /* JVMTI heap profiling */ \ \ diagnostic(bool, TraceJVMTIObjectTagging, false, \ @@ -2250,7 +2280,7 @@ class CommandLineFlags { product_pd(bool, RewriteFrequentPairs, \ "Rewrite frequently used bytecode pairs into a single bytecode") \ \ - product(bool, PrintInterpreter, false, \ + diagnostic(bool, PrintInterpreter, false, \ "Prints the generated interpreter code") \ \ product(bool, UseInterpreter, true, \ @@ -2300,7 +2330,7 @@ class CommandLineFlags { develop(bool, PrintBytecodePairHistogram, false, \ "Print histogram of the executed bytecode pairs") \ \ - develop(bool, PrintSignatureHandlers, false, \ + diagnostic(bool, PrintSignatureHandlers, false, \ "Print code generated for native method signature handlers") \ \ develop(bool, VerifyOops, false, \ @@ -3165,6 +3195,9 @@ class CommandLineFlags { product(bool, RelaxAccessControlCheck, false, \ "Relax the access control checks in the verifier") \ \ + diagnostic(bool, PrintDTraceDOF, false, \ + "Print the DTrace DOF passed to the system for JSDT probes") \ + \ product(bool, UseVMInterruptibleIO, true, \ "(Unstable, Solaris-specific) Thread interrupt before or with " \ "EINTR for I/O operations results in OS_INTRPT") @@ -3189,6 +3222,12 @@ class CommandLineFlags { #define DECLARE_PD_DEVELOPER_FLAG(type, name, doc) extern "C" type name; #define DECLARE_NOTPRODUCT_FLAG(type, name, value, doc) extern "C" type name; #endif +// Special LP64 flags, product only needed for now. +#ifdef _LP64 +#define DECLARE_LP64_PRODUCT_FLAG(type, name, value, doc) extern "C" type name; +#else +#define DECLARE_LP64_PRODUCT_FLAG(type, name, value, doc) const type name = value; +#endif // _LP64 // Implementation macros #define MATERIALIZE_PRODUCT_FLAG(type, name, value, doc) type name = value; @@ -3205,7 +3244,12 @@ class CommandLineFlags { #define MATERIALIZE_PD_DEVELOPER_FLAG(type, name, doc) type name = pd_##name; #define MATERIALIZE_NOTPRODUCT_FLAG(type, name, value, doc) type name = value; #endif +#ifdef _LP64 +#define MATERIALIZE_LP64_PRODUCT_FLAG(type, name, value, doc) type name = value; +#else +#define MATERIALIZE_LP64_PRODUCT_FLAG(type, name, value, doc) /* flag is constant */ +#endif // _LP64 -RUNTIME_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG) +RUNTIME_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG, DECLARE_LP64_PRODUCT_FLAG) RUNTIME_OS_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG) diff --git a/hotspot/src/share/vm/runtime/globals_extension.hpp b/hotspot/src/share/vm/runtime/globals_extension.hpp index d6cc1cf58d0..ffb8071b250 100644 --- a/hotspot/src/share/vm/runtime/globals_extension.hpp +++ b/hotspot/src/share/vm/runtime/globals_extension.hpp @@ -41,6 +41,11 @@ #define RUNTIME_PD_DEVELOP_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), #define RUNTIME_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), #endif +#ifdef _LP64 +#define RUNTIME_LP64_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), +#else +#define RUNTIME_LP64_PRODUCT_FLAG_MEMBER(type, name, value, doc) /* flag is constant */ +#endif // _LP64 #define C1_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), #define C1_PD_PRODUCT_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), @@ -71,7 +76,9 @@ typedef enum { RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, - RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER) + RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, + RUNTIME_PRODUCT_RW_FLAG_MEMBER, + RUNTIME_LP64_PRODUCT_FLAG_MEMBER) RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER) @@ -116,6 +123,11 @@ typedef enum { #define C1_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), #define C1_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), #endif +#ifdef _LP64 +#define RUNTIME_LP64_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), +#else +#define RUNTIME_LP64_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) /* flag is constant */ +#endif // _LP64 #define C2_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), @@ -137,7 +149,8 @@ typedef enum { RUNTIME_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE, RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE, RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE, - RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE) + RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE, + RUNTIME_LP64_PRODUCT_FLAG_MEMBER_WITH_TYPE) RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE, RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE, RUNTIME_PRODUCT_FLAG_MEMBER_WITH_TYPE, RUNTIME_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE, RUNTIME_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE, diff --git a/hotspot/src/share/vm/runtime/hpi.cpp b/hotspot/src/share/vm/runtime/hpi.cpp index 18e4e797623..1b8e361df86 100644 --- a/hotspot/src/share/vm/runtime/hpi.cpp +++ b/hotspot/src/share/vm/runtime/hpi.cpp @@ -27,7 +27,8 @@ extern "C" { static void unimplemented_panic(const char *fmt, ...) { - Unimplemented(); + // mitigate testing damage from bug 6626677 + warning("hpi::unimplemented_panic called"); } static void unimplemented_monitorRegister(sys_mon_t *mid, char *info_str) { diff --git a/hotspot/src/share/vm/runtime/init.cpp b/hotspot/src/share/vm/runtime/init.cpp index b93099ecb8b..dfadab63012 100644 --- a/hotspot/src/share/vm/runtime/init.cpp +++ b/hotspot/src/share/vm/runtime/init.cpp @@ -27,7 +27,6 @@ // Initialization done by VM thread in vm_init_globals() void check_ThreadShadow(); -void check_basic_types(); void eventlog_init(); void mutex_init(); void chunkpool_init(); @@ -73,7 +72,7 @@ void ostream_exit(); void vm_init_globals() { check_ThreadShadow(); - check_basic_types(); + basic_types_init(); eventlog_init(); mutex_init(); chunkpool_init(); diff --git a/hotspot/src/share/vm/runtime/jniHandles.cpp b/hotspot/src/share/vm/runtime/jniHandles.cpp index 05078c5591b..6f91a4daef4 100644 --- a/hotspot/src/share/vm/runtime/jniHandles.cpp +++ b/hotspot/src/share/vm/runtime/jniHandles.cpp @@ -206,9 +206,10 @@ private: int _count; public: CountHandleClosure(): _count(0) {} - void do_oop(oop* unused) { + virtual void do_oop(oop* unused) { _count++; } + virtual void do_oop(narrowOop* unused) { ShouldNotReachHere(); } int count() { return _count; } }; @@ -230,9 +231,10 @@ void JNIHandles::print_on(outputStream* st) { class VerifyHandleClosure: public OopClosure { public: - void do_oop(oop* root) { + virtual void do_oop(oop* root) { (*root)->verify(); } + virtual void do_oop(narrowOop* root) { ShouldNotReachHere(); } }; void JNIHandles::verify() { diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 59a057193b0..547b25d434c 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -33,6 +33,7 @@ class JavaThread; class Event; class DLL; class FileHandle; +template class GrowableArray; // %%%%% Moved ThreadState, START_FN, OSThread to new osThread.hpp. -- Rose @@ -206,7 +207,9 @@ class os: AllStatic { static void realign_memory(char *addr, size_t bytes, size_t alignment_hint); // NUMA-specific interface - static void numa_make_local(char *addr, size_t bytes); + static bool numa_has_static_binding(); + static bool numa_has_group_homing(); + static void numa_make_local(char *addr, size_t bytes, int lgrp_hint); static void numa_make_global(char *addr, size_t bytes); static size_t numa_get_groups_num(); static size_t numa_get_leaf_groups(int *ids, size_t size); diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index b0e8a996822..ebe0899a148 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -500,7 +500,8 @@ bool Reflection::verify_field_access(klassOop current_class, if (!protected_restriction) { // See if current_class is a subclass of field_class if (Klass::cast(current_class)->is_subclass_of(field_class)) { - if (current_class == resolved_class || + if (access.is_static() || // static fields are ok, see 6622385 + current_class == resolved_class || field_class == resolved_class || Klass::cast(current_class)->is_subclass_of(resolved_class) || Klass::cast(resolved_class)->is_subclass_of(current_class)) { diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 6f2fa5be969..59219cda39d 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -1748,11 +1748,6 @@ int AdapterHandlerLibrary::get_create_adapter_index(methodHandle method) { // _fingerprints array (it is not safe for concurrent readers and a single // writer: this can be fixed if it becomes a problem). - // Shouldn't be here if running -Xint - if (Arguments::mode() == Arguments::_int) { - ShouldNotReachHere(); - } - // Get the address of the ic_miss handlers before we grab the // AdapterHandlerLibrary_lock. This fixes bug 6236259 which // was caused by the initialization of the stubs happening @@ -1997,6 +1992,64 @@ nmethod *AdapterHandlerLibrary::create_native_wrapper(methodHandle method) { return nm; } +#ifdef HAVE_DTRACE_H +// Create a dtrace nmethod for this method. The wrapper converts the +// java compiled calling convention to the native convention, makes a dummy call +// (actually nops for the size of the call instruction, which become a trap if +// probe is enabled). The returns to the caller. Since this all looks like a +// leaf no thread transition is needed. + +nmethod *AdapterHandlerLibrary::create_dtrace_nmethod(methodHandle method) { + ResourceMark rm; + nmethod* nm = NULL; + + if (PrintCompilation) { + ttyLocker ttyl; + tty->print("--- n%s "); + method->print_short_name(tty); + if (method->is_static()) { + tty->print(" (static)"); + } + tty->cr(); + } + + { + // perform the work while holding the lock, but perform any printing + // outside the lock + MutexLocker mu(AdapterHandlerLibrary_lock); + // See if somebody beat us to it + nm = method->code(); + if (nm) { + return nm; + } + + // Improve alignment slightly + u_char* buf = (u_char*) + (((intptr_t)_buffer + CodeEntryAlignment-1) & ~(CodeEntryAlignment-1)); + CodeBuffer buffer(buf, AdapterHandlerLibrary_size); + // Need a few relocation entries + double locs_buf[20]; + buffer.insts()->initialize_shared_locs( + (relocInfo*)locs_buf, sizeof(locs_buf) / sizeof(relocInfo)); + MacroAssembler _masm(&buffer); + + // Generate the compiled-to-native wrapper code + nm = SharedRuntime::generate_dtrace_nmethod(&_masm, method); + } + return nm; +} + +// the dtrace method needs to convert java lang string to utf8 string. +void SharedRuntime::get_utf(oopDesc* src, address dst) { + typeArrayOop jlsValue = java_lang_String::value(src); + int jlsOffset = java_lang_String::offset(src); + int jlsLen = java_lang_String::length(src); + jchar* jlsPos = (jlsLen == 0) ? NULL : + jlsValue->char_at_addr(jlsOffset); + (void) UNICODE::as_utf8(jlsPos, jlsLen, (char *)dst, max_dtrace_string_size); +} +#endif // ndef HAVE_DTRACE_H + // ------------------------------------------------------------------------- // Java-Java calling convention // (what you use when Java calls Java) @@ -2176,6 +2229,8 @@ JRT_END #ifndef PRODUCT bool AdapterHandlerLibrary::contains(CodeBlob* b) { + if (_handlers == NULL) return false; + for (int i = 0 ; i < _handlers->length() ; i++) { AdapterHandlerEntry* a = get_entry(i); if ( a != NULL && b == CodeCache::find_blob(a->get_i2c_entry()) ) return true; diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.hpp b/hotspot/src/share/vm/runtime/sharedRuntime.hpp index b2138d0a703..22bb552ddc9 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp @@ -59,6 +59,10 @@ class SharedRuntime: AllStatic { #endif // !PRODUCT public: + + // max bytes for each dtrace string parameter + enum { max_dtrace_string_size = 256 }; + // The following arithmetic routines are used on platforms that do // not have machine instructions to implement their functionality. // Do not remove these. @@ -258,9 +262,6 @@ class SharedRuntime: AllStatic { public: - - static void create_native_wrapper (JavaThread* thread, methodOop method); - // Read the array of BasicTypes from a Java signature, and compute where // compiled Java code would like to put the results. Values in reg_lo and // reg_hi refer to 4-byte quantities. Values less than SharedInfo::stack0 are @@ -354,6 +355,19 @@ class SharedRuntime: AllStatic { VMRegPair *regs, BasicType ret_type ); +#ifdef HAVE_DTRACE_H + // Generate a dtrace wrapper for a given method. The method takes arguments + // in the Java compiled code convention, marshals them to the native + // convention (handlizes oops, etc), transitions to native, makes the call, + // returns to java state (possibly blocking), unhandlizes any result and + // returns. + static nmethod *generate_dtrace_nmethod(MacroAssembler* masm, + methodHandle method); + + // dtrace support to convert a Java string to utf8 + static void get_utf(oopDesc* src, address dst); +#endif // def HAVE_DTRACE_H + // A compiled caller has just called the interpreter, but compiled code // exists. Patch the caller so he no longer calls into the interpreter. static void fixup_callers_callsite(methodOopDesc* moop, address ret_pc); @@ -492,42 +506,55 @@ class AdapterHandlerEntry : public CHeapObj { address _c2i_unverified_entry; public: + + // The name we give all buffer blobs + static const char* name; + AdapterHandlerEntry(address i2c_entry, address c2i_entry, address c2i_unverified_entry): _i2c_entry(i2c_entry), _c2i_entry(c2i_entry), _c2i_unverified_entry(c2i_unverified_entry) { } - // The name we give all buffer blobs - static const char* name; address get_i2c_entry() { return _i2c_entry; } address get_c2i_entry() { return _c2i_entry; } address get_c2i_unverified_entry() { return _c2i_unverified_entry; } + void relocate(address new_base); #ifndef PRODUCT void print(); #endif /* PRODUCT */ }; - class AdapterHandlerLibrary: public AllStatic { private: + static u_char _buffer[]; // the temporary code buffer + static GrowableArray* _fingerprints; // the fingerprint collection + static GrowableArray * _handlers; // the corresponding handlers enum { AbstractMethodHandler = 1 // special handler for abstract methods }; - static GrowableArray* _fingerprints; // the fingerprint collection - static GrowableArray * _handlers; // the corresponding handlers - static u_char _buffer[]; // the temporary code buffer static void initialize(); - static AdapterHandlerEntry* get_entry( int index ) { return _handlers->at(index); } static int get_create_adapter_index(methodHandle method); - static address get_i2c_entry( int index ) { return get_entry(index)->get_i2c_entry(); } - static address get_c2i_entry( int index ) { return get_entry(index)->get_c2i_entry(); } - static address get_c2i_unverified_entry( int index ) { return get_entry(index)->get_c2i_unverified_entry(); } + static address get_i2c_entry( int index ) { + return get_entry(index)->get_i2c_entry(); + } + static address get_c2i_entry( int index ) { + return get_entry(index)->get_c2i_entry(); + } + static address get_c2i_unverified_entry( int index ) { + return get_entry(index)->get_c2i_unverified_entry(); + } public: + static AdapterHandlerEntry* get_entry( int index ) { return _handlers->at(index); } static nmethod* create_native_wrapper(methodHandle method); - static AdapterHandlerEntry* get_adapter(methodHandle method) { return get_entry(get_create_adapter_index(method)); } + static AdapterHandlerEntry* get_adapter(methodHandle method) { + return get_entry(get_create_adapter_index(method)); + } +#ifdef HAVE_DTRACE_H + static nmethod* create_dtrace_nmethod (methodHandle method); +#endif // HAVE_DTRACE_H #ifndef PRODUCT static void print_handler(CodeBlob* b); diff --git a/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp b/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp index bbdd6898b75..9b54e95eaa1 100644 --- a/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp +++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp @@ -69,7 +69,6 @@ StubCodeGenerator::StubCodeGenerator(CodeBuffer* code) { _first_stub = _last_stub = NULL; } -#ifndef PRODUCT extern "C" { static int compare_cdesc(const void* void_a, const void* void_b) { int ai = (*((StubCodeDesc**) void_a))->index(); @@ -77,10 +76,8 @@ extern "C" { return ai - bi; } } -#endif StubCodeGenerator::~StubCodeGenerator() { -#ifndef PRODUCT if (PrintStubCode) { CodeBuffer* cbuf = _masm->code(); CodeBlob* blob = CodeCache::find_blob_unsafe(cbuf->insts()->start()); @@ -105,7 +102,6 @@ StubCodeGenerator::~StubCodeGenerator() { tty->cr(); } } -#endif //PRODUCT } diff --git a/hotspot/src/share/vm/runtime/vframe.hpp b/hotspot/src/share/vm/runtime/vframe.hpp index 2b1b827b1fd..670e6c5d192 100644 --- a/hotspot/src/share/vm/runtime/vframe.hpp +++ b/hotspot/src/share/vm/runtime/vframe.hpp @@ -416,6 +416,48 @@ inline bool vframeStreamCommon::fill_from_frame() { int decode_offset; if (pc_desc == NULL) { // Should not happen, but let fill_from_compiled_frame handle it. + + // If we are trying to walk the stack of a thread that is not + // at a safepoint (like AsyncGetCallTrace would do) then this is an + // acceptable result. [ This is assuming that safe_for_sender + // is so bullet proof that we can trust the frames it produced. ] + // + // So if we see that the thread is not safepoint safe + // then simply produce the method and a bci of zero + // and skip the possibility of decoding any inlining that + // may be present. That is far better than simply stopping (or + // asserting. If however the thread is safepoint safe this + // is the sign of a compiler bug and we'll let + // fill_from_compiled_frame handle it. + + + JavaThreadState state = _thread->thread_state(); + + // in_Java should be good enough to test safepoint safety + // if state were say in_Java_trans then we'd expect that + // the pc would have already been slightly adjusted to + // one that would produce a pcDesc since the trans state + // would be one that might in fact anticipate a safepoint + + if (state == _thread_in_Java ) { + // This will get a method a zero bci and no inlining. + // Might be nice to have a unique bci to signify this + // particular case but for now zero will do. + + fill_from_compiled_native_frame(); + + // There is something to be said for setting the mode to + // at_end_mode to prevent trying to walk further up the + // stack. There is evidence that if we walk any further + // that we could produce a bad stack chain. However until + // we see evidence that allowing this causes us to find + // frames bad enough to cause segv's or assertion failures + // we don't do it as while we may get a bad call chain the + // probability is much higher (several magnitudes) that we + // get good data. + + return true; + } decode_offset = DebugInformationRecorder::serialized_null; } else { decode_offset = pc_desc->scope_decode_offset(); diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index fbc42430386..561389eaa92 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -71,7 +71,8 @@ static inline uint64_t cast_uint64_t(size_t x) /******************************************************************/ \ \ volatile_nonstatic_field(oopDesc, _mark, markOop) \ - nonstatic_field(oopDesc, _klass, klassOop) \ + volatile_nonstatic_field(oopDesc, _metadata._klass, wideKlassOop) \ + volatile_nonstatic_field(oopDesc, _metadata._compressed_klass, narrowOop) \ static_field(oopDesc, _bs, BarrierSet*) \ nonstatic_field(arrayKlass, _dimension, int) \ nonstatic_field(arrayKlass, _higher_dimension, klassOop) \ @@ -79,13 +80,14 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(arrayKlass, _vtable_len, int) \ nonstatic_field(arrayKlass, _alloc_size, juint) \ nonstatic_field(arrayKlass, _component_mirror, oop) \ - nonstatic_field(arrayOopDesc, _length, int) \ nonstatic_field(compiledICHolderKlass, _alloc_size, juint) \ nonstatic_field(compiledICHolderOopDesc, _holder_method, methodOop) \ nonstatic_field(compiledICHolderOopDesc, _holder_klass, klassOop) \ nonstatic_field(constantPoolOopDesc, _tags, typeArrayOop) \ nonstatic_field(constantPoolOopDesc, _cache, constantPoolCacheOop) \ nonstatic_field(constantPoolOopDesc, _pool_holder, klassOop) \ + nonstatic_field(constantPoolOopDesc, _length, int) \ + nonstatic_field(constantPoolCacheOopDesc, _length, int) \ nonstatic_field(constantPoolCacheOopDesc, _constant_pool, constantPoolOop) \ nonstatic_field(instanceKlass, _array_klasses, klassOop) \ nonstatic_field(instanceKlass, _methods, objArrayOop) \ @@ -261,6 +263,7 @@ static inline uint64_t cast_uint64_t(size_t x) static_field(Universe, _bootstrapping, bool) \ static_field(Universe, _fully_initialized, bool) \ static_field(Universe, _verify_count, int) \ + static_field(Universe, _heap_base, address) \ \ /**********************************************************************************/ \ /* Generation and Space hierarchies */ \ @@ -305,8 +308,6 @@ static inline uint64_t cast_uint64_t(size_t x) nonstatic_field(SharedHeap, _perm_gen, PermGen*) \ nonstatic_field(CollectedHeap, _barrier_set, BarrierSet*) \ nonstatic_field(CollectedHeap, _is_gc_active, bool) \ - nonstatic_field(CollectedHeap, _max_heap_capacity, size_t) \ - \ nonstatic_field(CompactibleSpace, _compaction_top, HeapWord*) \ nonstatic_field(CompactibleSpace, _first_dead, HeapWord*) \ nonstatic_field(CompactibleSpace, _end_of_live, HeapWord*) \ @@ -452,40 +453,40 @@ static inline uint64_t cast_uint64_t(size_t x) static_field(SystemDictionary, _shared_dictionary, Dictionary*) \ static_field(SystemDictionary, _system_loader_lock_obj, oop) \ static_field(SystemDictionary, _loader_constraints, LoaderConstraintTable*) \ - static_field(SystemDictionary, _object_klass, klassOop) \ - static_field(SystemDictionary, _string_klass, klassOop) \ - static_field(SystemDictionary, _class_klass, klassOop) \ - static_field(SystemDictionary, _cloneable_klass, klassOop) \ - static_field(SystemDictionary, _classloader_klass, klassOop) \ - static_field(SystemDictionary, _serializable_klass, klassOop) \ - static_field(SystemDictionary, _system_klass, klassOop) \ - static_field(SystemDictionary, _throwable_klass, klassOop) \ - static_field(SystemDictionary, _threaddeath_klass, klassOop) \ - static_field(SystemDictionary, _error_klass, klassOop) \ - static_field(SystemDictionary, _exception_klass, klassOop) \ - static_field(SystemDictionary, _runtime_exception_klass, klassOop) \ - static_field(SystemDictionary, _classNotFoundException_klass, klassOop) \ - static_field(SystemDictionary, _noClassDefFoundError_klass, klassOop) \ - static_field(SystemDictionary, _linkageError_klass, klassOop) \ - static_field(SystemDictionary, _classCastException_klass, klassOop) \ - static_field(SystemDictionary, _arrayStoreException_klass, klassOop) \ - static_field(SystemDictionary, _virtualMachineError_klass, klassOop) \ - static_field(SystemDictionary, _outOfMemoryError_klass, klassOop) \ - static_field(SystemDictionary, _StackOverflowError_klass, klassOop) \ - static_field(SystemDictionary, _protectionDomain_klass, klassOop) \ - static_field(SystemDictionary, _AccessControlContext_klass, klassOop) \ - static_field(SystemDictionary, _reference_klass, klassOop) \ - static_field(SystemDictionary, _soft_reference_klass, klassOop) \ - static_field(SystemDictionary, _weak_reference_klass, klassOop) \ - static_field(SystemDictionary, _final_reference_klass, klassOop) \ - static_field(SystemDictionary, _phantom_reference_klass, klassOop) \ - static_field(SystemDictionary, _finalizer_klass, klassOop) \ - static_field(SystemDictionary, _thread_klass, klassOop) \ - static_field(SystemDictionary, _threadGroup_klass, klassOop) \ - static_field(SystemDictionary, _properties_klass, klassOop) \ - static_field(SystemDictionary, _stringBuffer_klass, klassOop) \ - static_field(SystemDictionary, _vector_klass, klassOop) \ - static_field(SystemDictionary, _hashtable_klass, klassOop) \ + static_field(SystemDictionary, WK_KLASS(object_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(string_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(class_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(cloneable_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(classloader_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(serializable_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(system_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(throwable_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(threaddeath_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(error_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(exception_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(runtime_exception_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(classNotFoundException_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(noClassDefFoundError_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(linkageError_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(ClassCastException_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(ArrayStoreException_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(virtualMachineError_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(OutOfMemoryError_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(StackOverflowError_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(protectionDomain_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(AccessControlContext_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(reference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(soft_reference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(weak_reference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(final_reference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(phantom_reference_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(finalizer_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(thread_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(threadGroup_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(properties_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(stringBuffer_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(vector_klass), klassOop) \ + static_field(SystemDictionary, WK_KLASS(hashtable_klass), klassOop) \ static_field(SystemDictionary, _box_klasses[0], klassOop) \ static_field(SystemDictionary, _java_system_loader, oop) \ \ @@ -912,12 +913,12 @@ static inline uint64_t cast_uint64_t(size_t x) declare_type(arrayKlass, Klass) \ declare_type(arrayKlassKlass, klassKlass) \ declare_type(arrayOopDesc, oopDesc) \ - declare_type(compiledICHolderKlass, Klass) \ - declare_type(compiledICHolderOopDesc, oopDesc) \ - declare_type(constantPoolKlass, arrayKlass) \ - declare_type(constantPoolOopDesc, arrayOopDesc) \ - declare_type(constantPoolCacheKlass, arrayKlass) \ - declare_type(constantPoolCacheOopDesc, arrayOopDesc) \ + declare_type(compiledICHolderKlass, Klass) \ + declare_type(compiledICHolderOopDesc, oopDesc) \ + declare_type(constantPoolKlass, Klass) \ + declare_type(constantPoolOopDesc, oopDesc) \ + declare_type(constantPoolCacheKlass, Klass) \ + declare_type(constantPoolCacheOopDesc, oopDesc) \ declare_type(instanceKlass, Klass) \ declare_type(instanceKlassKlass, klassKlass) \ declare_type(instanceOopDesc, oopDesc) \ @@ -949,9 +950,11 @@ static inline uint64_t cast_uint64_t(size_t x) declare_oop_type(klassOop) \ declare_oop_type(markOop) \ declare_oop_type(methodOop) \ - declare_oop_type(methodDataOop) \ + declare_oop_type(methodDataOop) \ declare_oop_type(objArrayOop) \ declare_oop_type(oop) \ + declare_oop_type(narrowOop) \ + declare_oop_type(wideKlassOop) \ declare_oop_type(constMethodOop) \ declare_oop_type(symbolOop) \ declare_oop_type(typeArrayOop) \ @@ -1307,6 +1310,7 @@ static inline uint64_t cast_uint64_t(size_t x) /* Object sizes */ \ /****************/ \ \ + declare_constant(oopSize) \ declare_constant(LogBytesPerWord) \ declare_constant(BytesPerLong) \ \ @@ -1314,7 +1318,9 @@ static inline uint64_t cast_uint64_t(size_t x) /* Object alignment */ \ /********************/ \ \ + declare_constant(MinObjAlignment) \ declare_constant(MinObjAlignmentInBytes) \ + declare_constant(LogMinObjAlignmentInBytes) \ \ /********************************************/ \ /* Generation and Space Hierarchy Constants */ \ @@ -1361,7 +1367,6 @@ static inline uint64_t cast_uint64_t(size_t x) \ declare_constant(HeapWordSize) \ declare_constant(LogHeapWordSize) \ - declare_constant(HeapWordsPerOop) \ \ /* constants from PermGen::Name enum */ \ \ @@ -1610,7 +1615,7 @@ static inline uint64_t cast_uint64_t(size_t x) declare_constant(OopMapValue::unused_value) \ declare_constant(OopMapValue::oop_value) \ declare_constant(OopMapValue::value_value) \ - declare_constant(OopMapValue::dead_value) \ + declare_constant(OopMapValue::narrowoop_value) \ declare_constant(OopMapValue::callee_saved_value) \ declare_constant(OopMapValue::derived_oop_value) \ \ diff --git a/hotspot/src/share/vm/runtime/vm_operations.hpp b/hotspot/src/share/vm/runtime/vm_operations.hpp index 778a46dd718..54264ad0dde 100644 --- a/hotspot/src/share/vm/runtime/vm_operations.hpp +++ b/hotspot/src/share/vm/runtime/vm_operations.hpp @@ -49,6 +49,7 @@ template(GenCollectFull) \ template(GenCollectFullConcurrent) \ template(GenCollectForAllocation) \ + template(GenCollectForPermanentAllocation) \ template(ParallelGCFailedAllocation) \ template(ParallelGCFailedPermanentAllocation) \ template(ParallelGCSystemGC) \ diff --git a/hotspot/src/share/vm/services/heapDumper.cpp b/hotspot/src/share/vm/services/heapDumper.cpp index afb7d9cbb14..1a30c05b5c1 100644 --- a/hotspot/src/share/vm/services/heapDumper.cpp +++ b/hotspot/src/share/vm/services/heapDumper.cpp @@ -670,8 +670,12 @@ void DumperSupport::dump_field_value(DumpWriter* writer, char type, address addr switch (type) { case JVM_SIGNATURE_CLASS : case JVM_SIGNATURE_ARRAY : { - oop* f = (oop*)addr; - oop o = *f; + oop o; + if (UseCompressedOops) { + o = oopDesc::load_decode_heap_oop((narrowOop*)addr); + } else { + o = oopDesc::load_decode_heap_oop((oop*)addr); + } // reflection and sun.misc.Unsafe classes may have a reference to a // klassOop so filter it out. @@ -1077,6 +1081,7 @@ class SymbolTableDumper : public OopClosure { public: SymbolTableDumper(DumpWriter* writer) { _writer = writer; } void do_oop(oop* obj_p); + void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } }; void SymbolTableDumper::do_oop(oop* obj_p) { @@ -1106,6 +1111,7 @@ class JNILocalsDumper : public OopClosure { _thread_serial_num = thread_serial_num; } void do_oop(oop* obj_p); + void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } }; @@ -1133,6 +1139,7 @@ class JNIGlobalsDumper : public OopClosure { _writer = writer; } void do_oop(oop* obj_p); + void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } }; void JNIGlobalsDumper::do_oop(oop* obj_p) { @@ -1164,6 +1171,7 @@ class MonitorUsedDumper : public OopClosure { writer()->write_u1(HPROF_GC_ROOT_MONITOR_USED); writer()->write_objectID(*obj_p); } + void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } }; @@ -1178,6 +1186,7 @@ class StickyClassDumper : public OopClosure { _writer = writer; } void do_oop(oop* obj_p); + void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); } }; void StickyClassDumper::do_oop(oop* obj_p) { diff --git a/hotspot/src/share/vm/services/threadService.cpp b/hotspot/src/share/vm/services/threadService.cpp index 80dcb486c33..396f6204de9 100644 --- a/hotspot/src/share/vm/services/threadService.cpp +++ b/hotspot/src/share/vm/services/threadService.cpp @@ -541,6 +541,7 @@ bool ThreadStackTrace::is_owned_monitor_on_stack(oop object) { Handle ThreadStackTrace::allocate_fill_stack_trace_element_array(TRAPS) { klassOop k = SystemDictionary::stackTraceElement_klass(); + assert(k != NULL, "must be loaded in 1.4+"); instanceKlassHandle ik(THREAD, k); // Allocate an array of java/lang/StackTraceElement object diff --git a/hotspot/src/share/vm/utilities/copy.hpp b/hotspot/src/share/vm/utilities/copy.hpp index 1bbea38ad66..f3f84d0f21e 100644 --- a/hotspot/src/share/vm/utilities/copy.hpp +++ b/hotspot/src/share/vm/utilities/copy.hpp @@ -148,11 +148,19 @@ class Copy : AllStatic { // oops, conjoint, atomic on each oop static void conjoint_oops_atomic(oop* from, oop* to, size_t count) { - assert_params_ok(from, to, LogBytesPerOop); + assert_params_ok(from, to, LogBytesPerHeapOop); assert_non_zero(count); pd_conjoint_oops_atomic(from, to, count); } + // overloaded for UseCompressedOops + static void conjoint_oops_atomic(narrowOop* from, narrowOop* to, size_t count) { + assert(sizeof(narrowOop) == sizeof(jint), "this cast is wrong"); + assert_params_ok(from, to, LogBytesPerInt); + assert_non_zero(count); + pd_conjoint_jints_atomic((jint*)from, (jint*)to, count); + } + // Copy a span of memory. If the span is an integral number of aligned // longs, words, or ints, copy those units atomically. // The largest atomic transfer unit is 8 bytes, or the largest power @@ -188,7 +196,7 @@ class Copy : AllStatic { // oops, conjoint array, atomic on each oop static void arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) { - assert_params_ok(from, to, LogBytesPerOop); + assert_params_ok(from, to, LogBytesPerHeapOop); assert_non_zero(count); pd_arrayof_conjoint_oops(from, to, count); } diff --git a/hotspot/src/share/vm/utilities/debug.cpp b/hotspot/src/share/vm/utilities/debug.cpp index 8eb84cddcf5..05360107789 100644 --- a/hotspot/src/share/vm/utilities/debug.cpp +++ b/hotspot/src/share/vm/utilities/debug.cpp @@ -669,6 +669,7 @@ public: tty->print_cr("0x%08x", o); } } + void do_oop(narrowOop* o) { ShouldNotReachHere(); } }; diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.cpp b/hotspot/src/share/vm/utilities/globalDefinitions.cpp index 89373ef2894..acb8875acca 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.cpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.cpp @@ -24,18 +24,23 @@ # include "incls/_precompiled.incl" # include "incls/_globalDefinitions.cpp.incl" - - // Basic error support +// Info for oops within a java object. Defaults are zero so +// things will break badly if incorrectly initialized. +int heapOopSize = 0; +int LogBytesPerHeapOop = 0; +int LogBitsPerHeapOop = 0; +int BytesPerHeapOop = 0; +int BitsPerHeapOop = 0; + void basic_fatal(const char* msg) { fatal(msg); } - // Something to help porters sleep at night -void check_basic_types() { +void basic_types_init() { #ifdef ASSERT #ifdef _LP64 assert(min_intx == (intx)CONST64(0x8000000000000000), "correct constant"); @@ -92,6 +97,7 @@ void check_basic_types() { case T_LONG: case T_OBJECT: case T_ADDRESS: // random raw pointer + case T_NARROWOOP: // compressed pointer case T_CONFLICT: // might as well support a bottom type case T_VOID: // padding or other unaddressed word // layout type must map to itself @@ -134,11 +140,30 @@ void check_basic_types() { os::java_to_os_priority[9] = JavaPriority9_To_OSPriority; if(JavaPriority10_To_OSPriority != -1 ) os::java_to_os_priority[10] = JavaPriority10_To_OSPriority; + + // Set the size of basic types here (after argument parsing but before + // stub generation). + if (UseCompressedOops) { + // Size info for oops within java objects is fixed + heapOopSize = jintSize; + LogBytesPerHeapOop = LogBytesPerInt; + LogBitsPerHeapOop = LogBitsPerInt; + BytesPerHeapOop = BytesPerInt; + BitsPerHeapOop = BitsPerInt; + } else { + heapOopSize = oopSize; + LogBytesPerHeapOop = LogBytesPerWord; + LogBitsPerHeapOop = LogBitsPerWord; + BytesPerHeapOop = BytesPerWord; + BitsPerHeapOop = BitsPerWord; + } + _type2aelembytes[T_OBJECT] = heapOopSize; + _type2aelembytes[T_ARRAY] = heapOopSize; } // Map BasicType to signature character -char type2char_tab[T_CONFLICT+1]={ 0, 0, 0, 0, 'Z', 'C', 'F', 'D', 'B', 'S', 'I', 'J', 'L', '[', 'V', 0, 0}; +char type2char_tab[T_CONFLICT+1]={ 0, 0, 0, 0, 'Z', 'C', 'F', 'D', 'B', 'S', 'I', 'J', 'L', '[', 'V', 0, 0, 0}; // Map BasicType to Java type name const char* type2name_tab[T_CONFLICT+1] = { @@ -155,6 +180,7 @@ const char* type2name_tab[T_CONFLICT+1] = { "array", "void", "*address*", + "*narrowoop*", "*conflict*" }; @@ -170,7 +196,7 @@ BasicType name2type(const char* name) { // Map BasicType to size in words -int type2size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, -1}; +int type2size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, 1, -1}; BasicType type2field[T_CONFLICT+1] = { (BasicType)0, // 0, @@ -189,7 +215,8 @@ BasicType type2field[T_CONFLICT+1] = { T_OBJECT, // T_ARRAY = 13, T_VOID, // T_VOID = 14, T_ADDRESS, // T_ADDRESS = 15, - T_CONFLICT // T_CONFLICT = 16, + T_NARROWOOP, // T_NARROWOOP= 16, + T_CONFLICT // T_CONFLICT = 17, }; @@ -210,7 +237,8 @@ BasicType type2wfield[T_CONFLICT+1] = { T_OBJECT, // T_ARRAY = 13, T_VOID, // T_VOID = 14, T_ADDRESS, // T_ADDRESS = 15, - T_CONFLICT // T_CONFLICT = 16, + T_NARROWOOP, // T_NARROWOOP = 16, + T_CONFLICT // T_CONFLICT = 17, }; @@ -231,7 +259,8 @@ int _type2aelembytes[T_CONFLICT+1] = { T_ARRAY_aelem_bytes, // T_ARRAY = 13, 0, // T_VOID = 14, T_OBJECT_aelem_bytes, // T_ADDRESS = 15, - 0 // T_CONFLICT = 16, + T_NARROWOOP_aelem_bytes,// T_NARROWOOP= 16, + 0 // T_CONFLICT = 17, }; #ifdef ASSERT @@ -245,7 +274,7 @@ int type2aelembytes(BasicType t, bool allow_address) { // The following code is mostly taken from JVM typedefs_md.h and system_md.c -static const jlong high_bit = (jlong)1 << (jlong)63; +static const jlong high_bit = (jlong)1 << (jlong)63; static const jlong other_bits = ~high_bit; jlong float2long(jfloat f) { diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index 0feceb5deee..c46312f49d7 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -59,23 +59,26 @@ const int LongAlignmentMask = (1 << LogBytesPerLong) - 1; const int WordsPerLong = 2; // Number of stack entries for longs -const int oopSize = sizeof(char*); +const int oopSize = sizeof(char*); // Full-width oop +extern int heapOopSize; // Oop within a java object const int wordSize = sizeof(char*); const int longSize = sizeof(jlong); const int jintSize = sizeof(jint); const int size_tSize = sizeof(size_t); -// Size of a char[] needed to represent a jint as a string in decimal. -const int jintAsStringSize = 12; +const int BytesPerOop = BytesPerWord; // Full-width oop -const int LogBytesPerOop = LogBytesPerWord; -const int LogBitsPerOop = LogBitsPerWord; -const int BytesPerOop = 1 << LogBytesPerOop; -const int BitsPerOop = 1 << LogBitsPerOop; +extern int LogBytesPerHeapOop; // Oop within a java object +extern int LogBitsPerHeapOop; +extern int BytesPerHeapOop; +extern int BitsPerHeapOop; const int BitsPerJavaInteger = 32; const int BitsPerSize_t = size_tSize * BitsPerByte; +// Size of a char[] needed to represent a jint as a string in decimal. +const int jintAsStringSize = 12; + // In fact this should be // log2_intptr(sizeof(class JavaThread)) - log2_intptr(64); // see os::set_memory_serialize_page() @@ -99,14 +102,14 @@ private: }; // HeapWordSize must be 2^LogHeapWordSize. -const int HeapWordSize = sizeof(HeapWord); +const int HeapWordSize = sizeof(HeapWord); #ifdef _LP64 -const int LogHeapWordSize = 3; +const int LogHeapWordSize = 3; #else -const int LogHeapWordSize = 2; +const int LogHeapWordSize = 2; #endif -const int HeapWordsPerOop = oopSize / HeapWordSize; -const int HeapWordsPerLong = BytesPerLong / HeapWordSize; +const int HeapWordsPerLong = BytesPerLong / HeapWordSize; +const int LogHeapWordsPerLong = LogBytesPerLong - LogHeapWordSize; // The larger HeapWordSize for 64bit requires larger heaps // for the same application running in 64bit. See bug 4967770. @@ -284,6 +287,9 @@ const int MinObjAlignment = HeapWordsPerLong; const int MinObjAlignmentInBytes = MinObjAlignment * HeapWordSize; const int MinObjAlignmentInBytesMask = MinObjAlignmentInBytes - 1; +const int LogMinObjAlignment = LogHeapWordsPerLong; +const int LogMinObjAlignmentInBytes = LogMinObjAlignment + LogHeapWordSize; + // Machine dependent stuff #include "incls/_globalDefinitions_pd.hpp.incl" @@ -371,7 +377,7 @@ union jlong_accessor { jlong long_value; }; -void check_basic_types(); // cannot define here; uses assert +void basic_types_init(); // cannot define here; uses assert // NOTE: replicated in SA in vm/agent/sun/jvm/hotspot/runtime/BasicType.java @@ -388,7 +394,8 @@ enum BasicType { T_ARRAY = 13, T_VOID = 14, T_ADDRESS = 15, - T_CONFLICT = 16, // for stack value type with conflicting contents + T_NARROWOOP= 16, + T_CONFLICT = 17, // for stack value type with conflicting contents T_ILLEGAL = 99 }; @@ -438,6 +445,7 @@ enum BasicTypeSize { T_LONG_size = 2, T_OBJECT_size = 1, T_ARRAY_size = 1, + T_NARROWOOP_size = 1, T_VOID_size = 0 }; @@ -465,6 +473,7 @@ enum ArrayElementSize { T_OBJECT_aelem_bytes = 4, T_ARRAY_aelem_bytes = 4, #endif + T_NARROWOOP_aelem_bytes = 4, T_VOID_aelem_bytes = 0 }; @@ -881,7 +890,7 @@ inline int log2_long(jlong x) { i++; p *= 2; } // p = 2^(i+1) && x < p (i.e., 2^i <= x < 2^(i+1)) - // (if p = 0 then overflow occured and i = 31) + // (if p = 0 then overflow occured and i = 63) return i; } diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index 1543ff7d715..f50e8ba0a07 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -52,8 +52,9 @@ void outputStream::update_position(const char* s, size_t len) { _precount += _position + 1; _position = 0; } else if (ch == '\t') { - _position += 8; - _precount -= 7; // invariant: _precount + _position == total count + int tw = 8 - (_position & 7); + _position += tw; + _precount -= tw-1; // invariant: _precount + _position == total count } else { _position += 1; } @@ -133,7 +134,17 @@ void outputStream::vprint_cr(const char* format, va_list argptr) { } void outputStream::fill_to(int col) { - while (position() < col) sp(); + int need_fill = col - position(); + sp(need_fill); +} + +void outputStream::move_to(int col, int slop, int min_space) { + if (position() >= col + slop) + cr(); + int need_fill = col - position(); + if (need_fill < min_space) + need_fill = min_space; + sp(need_fill); } void outputStream::put(char ch) { @@ -142,8 +153,23 @@ void outputStream::put(char ch) { write(buf, 1); } -void outputStream::sp() { - this->write(" ", 1); +#define SP_USE_TABS false + +void outputStream::sp(int count) { + if (count < 0) return; + if (SP_USE_TABS && count >= 8) { + int target = position() + count; + while (count >= 8) { + this->write("\t", 1); + count -= 8; + } + count = target - position(); + } + while (count > 0) { + int nw = (count > 8) ? 8 : count; + this->write(" ", nw); + count -= nw; + } } void outputStream::cr() { diff --git a/hotspot/src/share/vm/utilities/ostream.hpp b/hotspot/src/share/vm/utilities/ostream.hpp index 3d50c69888e..7232b485096 100644 --- a/hotspot/src/share/vm/utilities/ostream.hpp +++ b/hotspot/src/share/vm/utilities/ostream.hpp @@ -59,6 +59,7 @@ class outputStream : public ResourceObj { int indentation() const { return _indentation; } void set_indentation(int i) { _indentation = i; } void fill_to(int col); + void move_to(int col, int slop = 6, int min_space = 2); // sizing int width() const { return _width; } @@ -78,7 +79,7 @@ class outputStream : public ResourceObj { void print_raw_cr(const char* str) { write(str, strlen(str)); cr(); } void print_raw_cr(const char* str, int len){ write(str, len); cr(); } void put(char ch); - void sp(); + void sp(int count = 1); void cr(); void bol() { if (_position > 0) cr(); } diff --git a/hotspot/src/share/vm/utilities/taskqueue.hpp b/hotspot/src/share/vm/utilities/taskqueue.hpp index 7fa983f8237..6e883d9e673 100644 --- a/hotspot/src/share/vm/utilities/taskqueue.hpp +++ b/hotspot/src/share/vm/utilities/taskqueue.hpp @@ -490,7 +490,31 @@ typedef oop Task; typedef GenericTaskQueue OopTaskQueue; typedef GenericTaskQueueSet OopTaskQueueSet; -typedef oop* StarTask; + +#define COMPRESSED_OOP_MASK 1 + +// This is a container class for either an oop* or a narrowOop*. +// Both are pushed onto a task queue and the consumer will test is_narrow() +// to determine which should be processed. +class StarTask { + void* _holder; // either union oop* or narrowOop* + public: + StarTask(narrowOop *p) { _holder = (void *)((uintptr_t)p | COMPRESSED_OOP_MASK); } + StarTask(oop *p) { _holder = (void*)p; } + StarTask() { _holder = NULL; } + operator oop*() { return (oop*)_holder; } + operator narrowOop*() { + return (narrowOop*)((uintptr_t)_holder & ~COMPRESSED_OOP_MASK); + } + + // Operators to preserve const/volatile in assignments required by gcc + void operator=(const volatile StarTask& t) volatile { _holder = t._holder; } + + bool is_narrow() const { + return (((uintptr_t)_holder & COMPRESSED_OOP_MASK) != 0); + } +}; + typedef GenericTaskQueue OopStarTaskQueue; typedef GenericTaskQueueSet OopStarTaskQueueSet; diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index 81b95462553..f8df9042128 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -332,11 +332,12 @@ void VMError::report(outputStream* st) { // VM version st->print_cr("#"); - st->print_cr("# Java VM: %s (%s %s %s)", + st->print_cr("# Java VM: %s (%s %s %s %s)", Abstract_VM_Version::vm_name(), Abstract_VM_Version::vm_release(), Abstract_VM_Version::vm_info_string(), - Abstract_VM_Version::vm_platform_string() + Abstract_VM_Version::vm_platform_string(), + UseCompressedOops ? "compressed oops" : "" ); STEP(60, "(printing problematic frame)") diff --git a/hotspot/test/compiler/6646019/Test.java b/hotspot/test/compiler/6646019/Test.java new file mode 100644 index 00000000000..e724394ff57 --- /dev/null +++ b/hotspot/test/compiler/6646019/Test.java @@ -0,0 +1,51 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +/* + * @test + * @bug 6646019 + * @summary array subscript expressions become top() with -d64 + * @run main/othervm -Xcomp -XX:CompileOnly=Test.test Test +*/ + + +public class Test { + final static int i = 2076285318; + long l = 2; + short s; + + public static void main(String[] args) { + Test t = new Test(); + try { t.test(); } + catch (Throwable e) { + if (t.l != 5) { + System.out.println("Fails: " + t.l + " != 5"); + } + } + } + + private void test() { + l = 5; + l = (new short[(byte)-2])[(byte)(l = i)]; + } +} diff --git a/hotspot/test/compiler/6646020/Tester.java b/hotspot/test/compiler/6646020/Tester.java new file mode 100644 index 00000000000..1035a7bd8eb --- /dev/null +++ b/hotspot/test/compiler/6646020/Tester.java @@ -0,0 +1,886 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6646020 + * @summary assert(in_bb(n),"must be in block") in -Xcomp mode + */ + +/* Complexity upper bound: 3361 ops */ + +class Tester_Class_0 { + static byte var_1; + + + public Tester_Class_0() + { + "".length(); + { + var_1 = (var_1 = (new byte[(byte)'D'])[(byte)2.40457E38F]); + var_1 = (var_1 = (byte)1.738443503665377E307); + var_1 = (var_1 = (byte)1237144669662298112L); + } + var_1 = "baldh".equalsIgnoreCase("") ? (var_1 = (byte)7.2932087E37F) : (byte)3909726578709910528L; + var_1 = (var_1 = (var_1 = (var_1 = (byte)7.223761846153971E307))); + var_1 = (var_1 = (var_1 = (var_1 = (var_1 = (byte)((short)7860452029249754112L + (byte)1.7374232546809952E308))))); + var_1 = (!true ? (var_1 = (byte)4359229782598970368L) : (short)(byte)1.7509836746850026E308) >= 'P' ? (var_1 = (byte)3.275114793095594E307) : (byte)(- ((byte)1.5595572E38F) / 8.2971296E37F); + byte var_9 = (true ? true : (false ? true : false)) ? (var_1 = (var_1 = (byte)9.928434E37F)) : (var_1 = (byte)9.785060633966518E307); + final byte var_10 = 53; + var_9 <<= (true | true) & (((var_10 == "".substring(2001075014).compareToIgnoreCase("rhbytggv") ? !true : ! !true) ? !false : false) ? !true & true : !false) ? var_10 : var_10; + var_9 <<= - (var_9 -= - ~6397182310329038848L >> (char)955837891 << (short)- - -8.4452034E37F >> + ~5485157895941338112L); + --var_9; + var_9 >>= 'V'; + var_9 -= (new char[var_10])[var_9]; + double var_11; + var_11 = (var_11 = (new int[var_9 = (var_9 %= 684423748)])[var_9]); + var_9 /= 'q'; + var_9 *= ~var_9 | (short)1.7667766368850557E308 - "w".trim().charAt(- (var_9 /= + (var_11 = 'q'))); + if (var_10 <= 605036859609030656L | !false & false) + { + var_9 >>>= false ^ false ? (new short[var_10])[var_10] : (short)1013619326108001280L; + } + else + { + var_11 = var_9; + } + var_9 -= 'X'; + var_9 *= 'E'; + { + var_9 ^= (new short[var_9])[var_9 >>>= 'c']; + } + var_11 = 4315867074042433536L; + double var_12 = 1.2183900219527627E308; + var_9 <<= (false ? !false : false) ? '\\' : 'D'; + } + + + + + private final long func_0() + { + float var_2 = 0F; + var_1 = (var_1 = (var_1 = (byte)((short)1.4106931056021857E308 % var_2))); + for (new String(); true & (! !true ^ !false | false) && var_2 < 1; var_1 = (var_1 = (var_1 = (var_1 = (byte)1183673628639185920L)))) + { + var_1 = true | false ? (var_1 = (byte)1.6263855E37F) : (byte)'O'; + var_2++; + "fui".toUpperCase(); + final int var_3 = (var_1 = (var_1 = (byte)'i')) + (byte)2008561384 / (byte)1.4413369179905006E308; + } + var_1 = (var_1 = false ^ false ? (byte)2.3850814E38F : (byte)4.42887E37F); + final float var_4 = 3.052265E38F; + var_1 = (var_1 = (var_1 = (var_1 = (var_1 = (byte)'o')))); + long var_5; + var_1 = (var_1 = (byte)((var_1 = (byte)1913212786) * (var_1 = (byte)var_2))); + var_5 = (short)3.2024069E38F * (short)(var_5 = 'Q'); + var_5 = (false ? true : false) ? (short)1098137179 : (byte)~695765814858203136L; + var_1 = (var_1 = true & false ^ true ? (byte)1662737306 : (byte)'r'); + { + (true ? "a" : "lymivj".toString()).codePointCount((short)3.032349E38F + (var_1 = (var_1 = (var_1 = (var_1 = (byte)1.3159799E37F)))), (byte)2.0898819853138264E307 & (new short[(byte)(short)var_2])[var_1 = (byte)(short)4.859332921376913E307]); + } + double var_6; + var_6 = 1359078277; + final float var_7 = 3.5952457E37F; + var_5 = ('u' | 9005660398910009344L) << 'j'; + int var_8; + var_5 = (!false || true & !false) && false ? (byte)1836342254 : (byte)1.4836203E38F; + var_1 = (var_1 = (var_1 = (var_1 = (byte)1.5824984701060493E308))); + var_1 = (var_1 = (var_1 = (byte)~ (var_1 = (var_1 = (var_1 = (byte)var_7))))); + return +9.067416E37F <= (true | true ^ false ? (var_1 = (byte)(short)1.5243446E38F) : (var_1 = (byte)1.6893049E37F)) ? (byte)~4408841475280588800L - (var_5 = (var_1 = (byte)2.1542209E38F)) : (var_8 = (short)var_4); + } + + protected final static double func_1(final char arg_0, final long arg_1) + { + var_1 = (short)8779631802405542912L << 'x' <= arg_0 ? (byte)+9.96859509852443E307 : (var_1 = (var_1 = (byte)(short)5.218454879223281E307)); + return 5.57437404144192E307; + } + + double func_2(byte arg_0, final boolean arg_1, Object arg_2) + { + arg_2 = arg_1 != arg_1 ? "wq" : "w"; + arg_2 = arg_2; + if (arg_1) + { + arg_2 = false & arg_1 ? "hasmp" : (arg_2 = arg_2); + } + else + { + arg_2 = "lcquv"; + } + arg_0 -= arg_1 ^ false ? (arg_0 |= (short)arg_0) : (~3462197988186869760L | 7274210797196514304L) % - - + +130998764279904256L; + arg_0 &= (true ? - - ~7861994999369861120L << 'l' : 'c') * 1246069704; + return (arg_1 ? 9.311174E37F : 1.7085558737202237E308) * 1168887722; + } + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_0.var_1 = "; result += Tester.Printer.print(var_1); + result += ""; + result += "\n]"; + return result; + } +} + + +final class Tester_Class_1 extends Tester_Class_0 { + static Object var_13; + final static boolean var_14 = false | (false ? false : true); + Object var_15; + static byte var_16; + final long var_17 = (long)(-9.40561658911133E307 - (short)2.2016736E38F) ^ (char)1099667310; + static boolean var_18; + static float var_19; + final static byte var_20 = 123; + static byte var_21 = var_1 = (var_1 = var_20); + final static float var_22 = 1.5415572E38F; + + + public Tester_Class_1() + { + char[][] var_39; + boolean var_40 = false | !var_14; + if (var_14) + { + final String[] var_41 = (new String[var_21][var_20])[var_21 *= var_21]; + var_15 = (new Tester_Class_0[var_20])[var_20]; + --var_21; + int var_42; + } + else + { + var_19 = (short)325110146; + } + var_40 &= true; + var_13 = (((new Tester_Class_1[var_21 |= (new char[var_20])[var_21]])[var_21]).var_15 = (new String[var_21][var_20][var_20])[var_21 >>= (byte)(int)var_22]); + var_15 = "m"; + } + + + + + + protected final static Tester_Class_0 func_0(final char arg_0, boolean arg_1) + { + final short var_23 = false ? (short)2.2956268E38F : var_20; + { + ((new Tester_Class_1[var_21])[var_20]).var_15 = ((new Tester_Class_0[var_20][var_21])[var_21])[var_20]; + } + var_19 = var_23; + { + var_21++; + --var_21; + var_13 = (false ? arg_1 : arg_1) ? "" : "aianteahl"; + arg_1 ^= ! (var_14 ? var_14 : !var_14); + } + (arg_1 ? "rq" : "certd").trim(); + arg_1 ^= 's' < var_22; + var_19 = 'T'; + var_19 = var_14 ? --var_21 : var_20; + var_19 = (var_21 >>>= ~ -1559436447128426496L >> 88912720393932800L) | (new char[var_20][var_21])[var_21][var_20]; + short var_24 = 7601; + if (arg_1) + { + var_13 = (new Tester_Class_0[var_20])[var_21]; + } + else + { + var_19 = var_23; + } + var_19 = var_24; + var_19 = 174274929356416000L; + return arg_1 ? (Tester_Class_0)(new Object[var_20])[var_21 >>>= - ((byte)6471979169965446144L)] : (new Tester_Class_0[var_21])[var_20]; + } + + private static int func_1(final Object arg_0, final boolean arg_1) + { + var_19 = 'N'; + var_13 = "ftspm".toUpperCase(); + var_18 = arg_1 ? !arg_1 : var_14; + var_19 = var_21 % 'j'; + { + var_13 = new short[var_21 >>= 8019540572802872320L]; + } + final Tester_Class_0 var_25 = arg_1 ? ((short)1.3614569631193786E308 >= (short)var_20 ? func_0('O', true) : (Tester_Class_0)arg_0) : func_0('e', false); + "cltpxrg".offsetByCodePoints((new short[var_20])[(byte)'F'] & var_20, 942627356); + final Object var_26 = ((new Tester_Class_1[var_21])[var_20]).var_15 = arg_0; + { + var_21 |= 'H'; + } + var_19 = 4705089801895780352L; + var_19 = (var_18 = arg_1 & false) ? var_20 : (! (~var_21 > var_22) ? (new short[var_20])[var_21] : (short)3904907750551380992L); + var_18 = false; + { + var_18 = "aoy".startsWith("ia", 18060804); + if (true) + { + final short var_27 = 4832; + } + else + { + var_18 = (var_18 = arg_1) ? !false : !var_14; + } + var_18 = (var_18 = var_14); + var_19 = 'L'; + } + func_0((false ? ! ((var_21 -= 4.670301365216022E307) > 1.1839209E37F) : (var_18 = false)) ? 's' : 'R', 'Z' > - ((long)var_21) << 2585724390819764224L & var_25.func_2(var_21, false, var_13 = var_25) != 4918861136400833536L); + double var_28 = 0; + var_21 %= -var_28; + for (byte var_29 = 91; arg_1 && (var_28 < 1 && false); var_19 = var_20) + { + var_19 = (var_18 = arg_1) & (var_18 = false) ? 'm' : '['; + var_28++; + var_18 = var_14; + var_21 += (short)1363703973; + } + var_19 = (var_19 = var_22); + var_18 = (var_18 = false | false ? 1743087391 <= (var_21 >>= 8790741242417599488L) : !arg_1); + var_18 = true | true; + --var_21; + var_18 = !var_14 & false; + "mt".indexOf(var_14 ? new String("fpu") : "awivb", (var_14 ? !true : (var_18 = var_14)) ? + ++var_21 : ~var_20); + return (short)(new float[var_21--])[var_21] & ((var_18 = false) ? (var_21 *= 'N') : var_20 + (short)1680927063794178048L) & 1839004800; + } + + protected static int func_2(Tester_Class_0[][] arg_0) + { + ((new Tester_Class_1[var_20][var_21])[var_20][var_20]).var_15 = ((new int[var_21][var_21][(byte)var_22])[var_21 <<= var_20])[var_20]; + ((new Tester_Class_1[var_20])[var_20]).var_15 = "d"; + int var_30 = 0; + "joxjgpywp".lastIndexOf(1834367264 >> var_21, (byte)7.572305E37F >>> (false ? (short)2.3909862E38F : + - +3939434849912855552L)); + while (var_14 | false ^ var_14 && (var_30 < 1 && true)) + { + var_1 = var_20; + var_30++; + var_13 = new float[var_21][--var_21]; + boolean var_31; + } + var_19 = ((new Tester_Class_1[var_21])[var_20]).var_17 <= (~2158227803735181312L & 6001748808824762368L) ? (short)var_20 : var_20; + var_18 = (var_18 = true); + return (byte)(new short[var_20])[var_20] >>> ((new char[var_21][var_21])[var_21 |= 6074708801143703552L])[var_20]; + } + + private final String func_3(boolean arg_0, short arg_1, short arg_2) + { + var_13 = (Tester_Class_0)((arg_0 ^= arg_0) ? (var_13 = (var_15 = (var_15 = "grfphyrs"))) : (var_13 = new Object[var_21 *= ']'])); + if (true & ! (arg_0 ^= !arg_0 | true)) + { + boolean var_32 = true; + var_19 = --arg_1; + arg_2 <<= var_21; + } + else + { + arg_0 |= false; + } + var_21 >>>= arg_1; + final float var_33 = 2.5500976E38F; + return ""; + } + + private static String func_4(final double arg_0, final Object arg_1, final short[] arg_2, final char arg_3) + { + float var_34; + var_21++; + ((new Tester_Class_1[var_20])[var_20]).var_15 = false ? arg_1 : arg_1; + var_13 = arg_1; + var_19 = var_22; + var_13 = new long[var_21 /= 1038797776 + var_21][--var_21]; + ++var_21; + var_18 = false && false; + var_21--; + "".lastIndexOf("kjro"); + final int var_35 = (var_21 <<= var_21--) * var_21--; + if ("kohilkx".startsWith("gy", var_35)) + { + var_34 = 2.0849673E37F; + } + else + { + double var_36 = arg_0; + } + var_34 = (var_21 /= var_20); + { + func_2(new Tester_Class_0[var_20][var_21]); + var_34 = var_20 * (- ~5805881602002385920L / arg_3) << (short)~8041668398152312832L; + var_13 = (var_13 = "qfwbfdf"); + } + ((new Tester_Class_1[var_20])[var_21 += var_20]).var_15 = false ? func_0(arg_3, var_14) : func_0('J', var_18 = var_14); + var_18 = (var_18 = var_14) & var_14; + if ((new boolean[var_21])[var_21 >>= 121380821]) + { + var_34 = 1382979413; + } + else + { + var_34 = (var_20 & var_20) + (true ? 'I' : arg_3); + } + byte var_37; + ((new Tester_Class_1[var_20][var_21])[var_14 ^ var_14 | !var_14 ? var_20 : var_20][var_21 ^= (short)1692053070 & + ~7232298887878750208L - 1512699919]).var_15 = arg_2; + byte var_38 = 1; + var_38 -= arg_0; + var_34 = arg_3; + return var_14 ? "" : "xgkr".toUpperCase(); + } + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_1.var_1 = "; result += Tester.Printer.print(var_1); + result += "\n"; + result += "Tester_Class_1.var_16 = "; result += Tester.Printer.print(var_16); + result += "\n"; + result += "Tester_Class_1.var_20 = "; result += Tester.Printer.print(var_20); + result += "\n"; + result += "Tester_Class_1.var_21 = "; result += Tester.Printer.print(var_21); + result += "\n"; + result += "Tester_Class_1.var_14 = "; result += Tester.Printer.print(var_14); + result += "\n"; + result += "Tester_Class_1.var_18 = "; result += Tester.Printer.print(var_18); + result += "\n"; + result += "Tester_Class_1.var_17 = "; result += Tester.Printer.print(var_17); + result += "\n"; + result += "Tester_Class_1.var_19 = "; result += Tester.Printer.print(var_19); + result += "\n"; + result += "Tester_Class_1.var_22 = "; result += Tester.Printer.print(var_22); + result += "\n"; + result += "Tester_Class_1.var_13 = "; result += Tester.Printer.print(var_13); + result += "\n"; + result += "Tester_Class_1.var_15 = "; result += Tester.Printer.print(var_15); + result += ""; + result += "\n]"; + return result; + } +} + + +class Tester_Class_2 extends Tester_Class_0 { + final int var_43 = 1600723343; + static long var_44 = ~1297640037857117184L; + static String var_45 = "ejaglds"; + double var_46; + static float var_47 = 7.9423827E37F; + static Tester_Class_1[][] var_48; + + + public Tester_Class_2() + { + var_45 = (var_45 = "nkulkweqt"); + var_47 %= (new char[Tester_Class_1.var_21 >>= (short)Tester_Class_1.var_20])[Tester_Class_1.var_20]; + { + Tester_Class_1.var_18 = Tester_Class_1.var_14; + } + var_47 %= 1.559461406041646E308; + var_44 -= Tester_Class_1.var_21++ & ((new Tester_Class_1[Tester_Class_1.var_20])[Tester_Class_1.var_20]).var_17; + var_44 *= false ? (short)Tester_Class_1.var_20 : (short)var_47; + Tester_Class_1.var_13 = (new Tester_Class_1().var_15 = new char[Tester_Class_1.var_20]); + var_46 = 'i'; + double var_49 = var_46 = false ? (var_47 *= (var_46 = var_43)) : Tester_Class_1.var_20; + var_49 += 'k'; + } + + + + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_2.var_43 = "; result += Tester.Printer.print(var_43); + result += "\n"; + result += "Tester_Class_2.var_48 = "; result += Tester.Printer.print(var_48); + result += "\n"; + result += "Tester_Class_2.var_44 = "; result += Tester.Printer.print(var_44); + result += "\n"; + result += "Tester_Class_2.var_46 = "; result += Tester.Printer.print(var_46); + result += "\n"; + result += "Tester_Class_2.var_47 = "; result += Tester.Printer.print(var_47); + result += "\n"; + result += "Tester_Class_2.var_1 = "; result += Tester.Printer.print(var_1); + result += "\n"; + result += "Tester_Class_2.var_45 = "; result += Tester.Printer.print(var_45); + result += ""; + result += "\n]"; + return result; + } +} + + +class Tester_Class_3 extends Tester_Class_0 { + byte var_50; + int var_51; + static double var_52; + static boolean var_53 = true; + long var_54; + static short var_55; + short var_56; + + + public Tester_Class_3() + { + var_53 |= false; + (Tester_Class_2.var_45 = "gpbcgq").replaceAll("m".concat(Tester_Class_2.var_45 = "q"), Tester_Class_2.var_45).indexOf(Tester_Class_2.var_45 = "d"); + Tester_Class_2.var_45 = Tester_Class_2.var_45; + double var_68 = 0; + Tester_Class_1.var_19 = (var_55 = Tester_Class_1.var_20); + do + { + var_53 ^= 'T' > Tester_Class_1.var_21-- & (var_53 |= Tester_Class_1.var_14); + Tester_Class_2.var_44 >>= (char)3.928497616986412E307; + var_68++; + new Tester_Class_2().func_2(Tester_Class_1.var_20, !var_53 & Tester_Class_1.var_14, Tester_Class_1.var_13 = (Tester_Class_2.var_45 = Tester_Class_2.var_45)); + } while ((((var_56 = (short)1161292485) != 'M' ? var_53 : Tester_Class_1.var_14) ? Tester_Class_1.var_14 ^ true : var_53) && var_68 < 1); + Tester_Class_2.var_45 = Tester_Class_2.var_45; + ((Tester_Class_1)(Tester_Class_1.var_13 = new Tester_Class_2())).var_15 = Tester_Class_2.var_45; + var_55 = func_1() | ((Tester_Class_1.var_18 = var_53) | (var_53 |= Tester_Class_1.var_14) | Tester_Class_1.var_14 | !Tester_Class_1.var_14) || false ? (short)Tester_Class_2.var_44 : (var_56 = (var_56 = (short)'[')); + var_52 = (var_51 = (var_55 = Tester_Class_1.var_20)); + double var_69 = 0; + Tester_Class_2.var_44 |= (Tester_Class_1.var_14 ? (Tester_Class_2)(Tester_Class_1.var_13 = (Tester_Class_2)(Tester_Class_1.var_13 = Tester_Class_2.var_45)) : (Tester_Class_2)(Tester_Class_0)(Tester_Class_1.var_13 = Tester_Class_2.var_45)).var_43; + do + { + var_51 = 495861255; + var_69++; + } while (var_69 < 3); + Tester_Class_2.var_47 -= Tester_Class_1.var_20; + Tester_Class_2.var_47 %= '['; + } + + + + + static Object func_0(final Tester_Class_0 arg_0, String arg_1, final float arg_2, final long arg_3) + { + (!var_53 | (var_53 &= var_53) ^ false ? new Tester_Class_1() : (Tester_Class_1)(new Tester_Class_0[Tester_Class_1.var_21])[Tester_Class_1.var_21]).var_15 = Tester_Class_1.var_14 ? new Tester_Class_1() : new Tester_Class_1(); + Tester_Class_2.var_47 /= !var_53 || var_53 ? (short)(((Tester_Class_2)arg_0).var_46 = (new char[Tester_Class_1.var_21][Tester_Class_1.var_21])[Tester_Class_1.var_20][Tester_Class_1.var_20]) : Tester_Class_1.var_21; + return (new Object[Tester_Class_1.var_21])[Tester_Class_1.var_21]; + } + + boolean func_1() + { + { + Tester_Class_1.var_21 >>= (var_56 = (Tester_Class_1.var_21 |= (Tester_Class_1.var_21 -= Tester_Class_1.var_20))); + Tester_Class_2.var_45 = "w"; + var_51 = Tester_Class_1.var_21; + Object var_57; + ((Tester_Class_2)(Tester_Class_0)((new Object[Tester_Class_1.var_21][Tester_Class_1.var_21])[Tester_Class_1.var_20])[Tester_Class_1.var_20]).var_46 = (var_52 = 1.3957085765622284E308); + } + Tester_Class_1.var_21 &= (var_55 = (byte)(Tester_Class_1.var_14 ? -Tester_Class_1.var_20 : 4290961666344782848L)); + Tester_Class_2.var_45 = Tester_Class_2.var_45; + var_51 = (var_53 ^= ((var_53 &= Tester_Class_1.var_14) ? 'J' : 'M') > (var_56 = Tester_Class_1.var_21)) && (var_53 = Tester_Class_1.var_14) ? (Tester_Class_1.var_21 &= ~Tester_Class_1.var_20) : Tester_Class_1.var_20; + { + final Tester_Class_1 var_58 = (Tester_Class_1)(Tester_Class_0)(Tester_Class_1.var_13 = (new Object[Tester_Class_1.var_21])[Tester_Class_1.var_20]); + Object var_59; + Tester_Class_1.var_21 |= 'X'; + var_53 ^= Tester_Class_1.var_14; + } + int var_60 = 0; + var_53 |= var_53; + for (char var_61 = 'i'; (Tester_Class_1.var_14 ? false : Tester_Class_1.var_14) | (true | Tester_Class_1.var_14) && var_60 < 1; var_53 &= !Tester_Class_1.var_14) + { + var_51 = var_61; + var_60++; + var_61 &= (new short[Tester_Class_1.var_20][Tester_Class_1.var_20])[Tester_Class_1.var_20][Tester_Class_1.var_21]; + Tester_Class_2.var_45 = "vsuy"; + } + Tester_Class_2 var_62 = ((var_53 &= Tester_Class_1.var_14 | Tester_Class_1.var_14 || Tester_Class_1.var_14) ? Tester_Class_1.var_14 : "hgwne".startsWith("etyhd", var_60)) ? (var_53 ? (Tester_Class_2)(Tester_Class_1.var_13 = "uyiaxtqc") : (Tester_Class_2)(Tester_Class_1.var_13 = Tester_Class_2.var_45)) : new Tester_Class_2(); + var_62 = var_62; + float var_63; + Object var_64; + Tester_Class_2.var_44 <<= 'v'; + String var_65; + { + var_51 = Tester_Class_1.var_21; + } + var_55 = true ? (var_56 = Tester_Class_1.var_20) : (var_55 = Tester_Class_1.var_20); + var_56 = Tester_Class_1.var_21; + Tester_Class_1.var_21 |= var_60; + Object var_66; + Tester_Class_2 var_67; + return true & Tester_Class_1.var_14 ^ (false ? var_53 : var_53); + } + + public String toString() + { + String result = "[\n"; + result += "Tester_Class_3.var_51 = "; result += Tester.Printer.print(var_51); + result += "\n"; + result += "Tester_Class_3.var_54 = "; result += Tester.Printer.print(var_54); + result += "\n"; + result += "Tester_Class_3.var_52 = "; result += Tester.Printer.print(var_52); + result += "\n"; + result += "Tester_Class_3.var_55 = "; result += Tester.Printer.print(var_55); + result += "\n"; + result += "Tester_Class_3.var_56 = "; result += Tester.Printer.print(var_56); + result += "\n"; + result += "Tester_Class_3.var_1 = "; result += Tester.Printer.print(var_1); + result += "\n"; + result += "Tester_Class_3.var_50 = "; result += Tester.Printer.print(var_50); + result += "\n"; + result += "Tester_Class_3.var_53 = "; result += Tester.Printer.print(var_53); + result += ""; + result += "\n]"; + return result; + } +} + +public class Tester { + final long var_70 = Tester_Class_2.var_44; + int var_71; + static double var_72; + static short var_73 = (Tester_Class_3.var_53 &= (Tester_Class_3.var_53 ^= Tester_Class_3.var_53)) ? (short)(byte)(Tester_Class_3.var_55 = Tester_Class_1.var_20) : (Tester_Class_3.var_55 = Tester_Class_1.var_20); + final static short var_74 = (Tester_Class_3.var_53 &= Tester_Class_3.var_53) ? (Tester_Class_3.var_53 ? var_73 : var_73++) : (var_73 *= (Tester_Class_1.var_21 |= var_73)); + float var_75; + + + protected final Tester_Class_2 func_0() + { + Tester_Class_1.var_21 ^= ~Tester_Class_1.var_21; + if (false) + { + ((Tester_Class_3)(new Object[Tester_Class_1.var_21])[Tester_Class_1.var_21 -= + + (Tester_Class_2.var_44 >>>= Tester_Class_1.var_21)]).var_50 = (Tester_Class_1.var_21 &= (var_71 = 554295231)); + } + else + { + Tester_Class_2.var_47 += 'H'; + } + final Tester_Class_0 var_76 = ((new Tester_Class_0[Tester_Class_1.var_20][Tester_Class_1.var_21])[Tester_Class_1.var_20])[Tester_Class_1.var_20]; + (Tester_Class_1.var_14 ? (Tester_Class_2)var_76 : (Tester_Class_2)var_76).var_46 = (var_73 %= var_74 / (((new Tester_Class_2[Tester_Class_1.var_20])[Tester_Class_1.var_21 |= Tester_Class_1.var_20]).var_46 = Tester_Class_1.var_22)); + var_73 |= ((Tester_Class_2)(Tester_Class_1.var_13 = var_76)).var_43 | Tester_Class_1.var_20; + return new Tester_Class_2(); + } + + private static Tester_Class_3 func_1(byte arg_0, Tester_Class_1 arg_1, Tester_Class_1 arg_2, final int arg_3) + { + arg_0 <<= '`'; + return false ? (Tester_Class_3)(Tester_Class_0)(arg_1.var_15 = (arg_1 = arg_2)) : (Tester_Class_3)((new Tester_Class_0[Tester_Class_1.var_20][arg_0])[Tester_Class_1.var_20])[Tester_Class_1.var_20]; + } + + public static String execute() + { + try { + Tester t = new Tester(); + try { t.test(); } + catch(Throwable e) { } + try { return t.toString(); } + catch (Throwable e) { return "Error during result conversion to String"; } + } catch (Throwable e) { return "Error during test execution"; } + } + + public static void main(String[] args) + { + for (int i = 0; i < 20000; i++) { + Tester t = new Tester(); + try { t.test(); } + catch(Throwable e) { } + if (t.var_71 != 0 || + t.var_70 != -1297640037857117185L || + t.var_72 != 0.0 || + t.var_75 != 0.0 || + t.var_73 != -1 || + t.var_74 != 15129) { + throw new InternalError("wrong answer"); + } + } + } + + private void test() + { + long var_77 = 0L; + var_73 /= (Tester_Class_2.var_47 = 'D' | 'Q'); + Tester_Class_2.var_47 *= 't'; + while (var_77 < 36) + { + var_73 += Tester_Class_1.var_22; + Tester_Class_2.var_47 += Tester_Class_1.var_20; + var_77++; + Tester_Class_2.var_45 = ""; + Tester_Class_2.var_45 = (Tester_Class_2.var_45 = Tester_Class_2.var_45); + } + if (Tester_Class_3.var_53 |= false) + { + int var_78 = 0; + (false ? "idipdjrln" : "l").startsWith(Tester_Class_2.var_45); + while ((Tester_Class_3.var_53 |= (Tester_Class_3.var_53 &= ! (Tester_Class_1.var_18 = true)) | Tester_Class_3.var_53) && (var_78 < 15 && (Tester_Class_3.var_53 &= Tester_Class_1.var_14))) + { + Tester_Class_2.var_44 <<= 'b'; + var_78++; + var_72 = var_74; + var_71 = (char)6792782617594333184L; + } + float var_79 = Tester_Class_2.var_47 /= 1.5148047552641134E308; + ((new boolean[Tester_Class_1.var_20])[Tester_Class_1.var_21 <= (Tester_Class_1.var_21 -= 9.675021723726166E307) / - + (var_72 = 4.3844763012510596E307) ? (byte)(Tester_Class_2.var_44 += ~Tester_Class_1.var_21) : (Tester_Class_1.var_21 += 1.7430965313164616E308)] ? (Tester_Class_2)(new Tester_Class_1().var_15 = func_0()) : new Tester_Class_2()).var_46 = (var_72 = (Tester_Class_1.var_21 *= 'j')); + Tester_Class_1.var_13 = (new Tester_Class_3[Tester_Class_1.var_21 >>>= var_78][Tester_Class_1.var_21])[Tester_Class_1.var_21][Tester_Class_1.var_20]; + } + else + { + long var_80 = 0L; + ((Tester_Class_2)(Tester_Class_1.var_13 = new long[Tester_Class_1.var_21])).var_46 = 'r'; + do + { + final float var_81 = 7.3633934E37F; + var_80++; + var_73 ^= Tester_Class_2.var_44; + } while (Tester_Class_3.var_53 && var_80 < 4); + Tester_Class_1.var_18 = Tester_Class_2.var_47 >= var_73; + Tester_Class_2.var_45 = "xvodcylp"; + Tester_Class_2.var_45.codePointCount("indreb".charAt(+(new byte[Tester_Class_1.var_20][Tester_Class_1.var_20])[Tester_Class_1.var_21][Tester_Class_1.var_21]) * ~ (Tester_Class_1.var_21 %= (var_71 = --var_73)), ((Tester_Class_3.var_53 ^= Tester_Class_2.var_45.equalsIgnoreCase("rkxwa")) || Tester_Class_2.var_47 <= (Tester_Class_2.var_47 %= -var_80) ? (Tester_Class_1.var_21 ^= var_70) : var_73) & (var_71 = 'k')); + Tester_Class_1.var_13 = ((new long[Tester_Class_1.var_21][Tester_Class_1.var_20][Tester_Class_1.var_21])[Tester_Class_1.var_21])[Tester_Class_1.var_21]; + } + var_73 <<= (Tester_Class_1.var_18 = false) ? 't' : (false ? 'E' : 'u'); + var_73++; + int var_82 = 0; + Tester_Class_1.var_13 = func_1(Tester_Class_1.var_20, new Tester_Class_1(), (new Tester_Class_1[Tester_Class_1.var_21])[Tester_Class_1.var_21], 'M' & var_74); + "gdrlrsubb".substring(12438522, var_82); + Tester_Class_2.var_44 |= (((new Tester_Class_3[Tester_Class_1.var_21][Tester_Class_1.var_21])[Tester_Class_1.var_21 >>= 7993744087962264576L][Tester_Class_1.var_21]).var_51 = Tester_Class_3.var_53 ? 'B' : '['); + final long var_83 = ~ (4544638910183665664L << (((Tester_Class_3)((new Tester_Class_0[Tester_Class_1.var_20][Tester_Class_1.var_21])[Tester_Class_1.var_21])[Tester_Class_1.var_21]).var_56 = (Tester_Class_3.var_53 &= Tester_Class_3.var_53) ? Tester_Class_1.var_21 : Tester_Class_1.var_20)); + Tester_Class_2.var_45 = Tester_Class_2.var_45; + while (var_82 < 2 && Tester_Class_3.var_53 & (Tester_Class_3.var_53 ^= !false)) + { + (Tester_Class_3.var_53 ? "xqeisnyf" : (Tester_Class_2.var_45 = (Tester_Class_2.var_45 = (Tester_Class_2.var_45 = Tester_Class_2.var_45)))).concat(Tester_Class_2.var_45 = "i"); + var_82++; + boolean var_84 = false; + Tester_Class_2.var_45 = Tester_Class_2.var_45; + } + var_71 = ~Tester_Class_2.var_44 != Tester_Class_2.var_44-- ? (var_73 = var_73) : (var_73 >>>= var_73); + char var_85; + Tester_Class_3.var_53 |= (Tester_Class_3.var_53 ^= true); + int var_86 = 0; + Tester_Class_1.var_21 %= (var_73 | (Tester_Class_1.var_21 *= 9.831691E37F)) * (Tester_Class_1.var_21 += 6784278051481715712L); + while (Tester_Class_3.var_53 && (var_86 < 24 && ((((Tester_Class_3.var_53 ^= true) ? Tester_Class_3.var_53 : Tester_Class_1.var_14) ? !Tester_Class_3.var_53 : Tester_Class_3.var_53) ? (Tester_Class_1.var_18 = Tester_Class_3.var_53) : Tester_Class_1.var_14 || true))) + { + final byte var_87 = (byte)((false & true ? Tester_Class_1.var_20 : 257407175) & 4242055901066916864L * (var_73 *= 1621204618) / ((((Tester_Class_1)(new Object[(byte)4.925362697409246E307])[Tester_Class_1.var_21]).var_17 ^ (var_71 = var_86)) & 1859382584)); + var_86++; + Tester_Class_2.var_45 = (Tester_Class_2.var_45 = (Tester_Class_2.var_45 = "arceo")); + float var_88; + } + "a".lastIndexOf(var_71 = Tester_Class_3.var_53 ^ false ? (var_71 = 1058420888) : Tester_Class_1.var_20); + int var_89 = 0; + { + var_71 = 661164411; + } + boolean var_90; + --var_73; + Tester_Class_2.var_45.concat(Tester_Class_2.var_45); + { + var_85 = (Tester_Class_3.var_53 ? Tester_Class_3.var_53 : Tester_Class_3.var_53) ? 'R' : '['; + } + ((new Tester_Class_2[Tester_Class_1.var_21][Tester_Class_1.var_21])[Tester_Class_1.var_20][Tester_Class_1.var_20]).var_46 = Tester_Class_1.var_20; + final float var_91 = ((new Tester_Class_0[Tester_Class_1.var_21][Tester_Class_1.var_21])[Tester_Class_1.var_20][Tester_Class_1.var_21 -= Tester_Class_1.var_21]).equals(((new Tester_Class_1[Tester_Class_1.var_20])[Tester_Class_1.var_21]).var_15 = (Tester_Class_2.var_45 = Tester_Class_2.var_45)) ? (var_71 = Tester_Class_1.var_20) : 2.2259766E38F + Tester_Class_2.var_44; + Tester_Class_2.var_47 *= ((Tester_Class_2)(Tester_Class_0)(Tester_Class_1.var_13 = Tester_Class_2.var_45)).var_43; + Tester_Class_2.var_45 = Tester_Class_2.var_45; + Tester_Class_3.var_53 &= Tester_Class_1.var_14; + while (Tester_Class_1.var_20 >= ++Tester_Class_1.var_21 && var_89 < 2) + { + Tester_Class_1.var_13 = (Tester_Class_3)(new Tester_Class_0[Tester_Class_1.var_21])[Tester_Class_1.var_21]; + var_89++; + if (true) + { + Tester_Class_3.var_53 |= true; + break; + } + else + { + Tester_Class_2 var_92; + } + ((Tester_Class_3)((Tester_Class_3.var_53 |= Tester_Class_3.var_53) ? (new Tester_Class_1().var_15 = (Tester_Class_0)(Tester_Class_1.var_13 = new boolean[Tester_Class_1.var_20][Tester_Class_1.var_21])) : new Tester_Class_0[Tester_Class_1.var_21][Tester_Class_1.var_21])).var_54 = (Tester_Class_1.var_21 = (Tester_Class_1.var_21 /= (Tester_Class_2.var_44 |= (int)(Tester_Class_1.var_21 >>>= var_82)))); + ((Tester_Class_3)(Tester_Class_1.var_13 = (new Tester_Class_1().var_15 = new Tester_Class_1()))).var_51 = Tester_Class_1.var_20; + final char var_93 = 'u'; + ((Tester_Class_2)(new Tester_Class_1().var_15 = (Tester_Class_2.var_45 = Tester_Class_2.var_45))).var_46 = var_93; + Tester_Class_2.var_45.toUpperCase(); + Tester_Class_2.var_45 = "mhk"; + (true | false ? new Tester_Class_1() : (new Tester_Class_1[Tester_Class_1.var_20])[Tester_Class_1.var_20]).var_15 = (Tester_Class_1)(((new Tester_Class_1[Tester_Class_1.var_21 |= Tester_Class_1.var_20][Tester_Class_1.var_21])[Tester_Class_1.var_21][Tester_Class_1.var_21]).var_15 = (Tester_Class_1.var_13 = (Tester_Class_1)(Tester_Class_1.var_13 = (Tester_Class_2.var_45 = "ofkbg")))); + } + float var_94 = 0F; + Tester_Class_2.var_44 |= (var_73 >>>= (var_85 = (var_85 = 'j'))); + Tester_Class_3.var_52 = 1835242863964218368L; + do + { + int var_95 = 1361237611; + var_94++; + Tester_Class_3.var_53 ^= (Tester_Class_3.var_53 |= Tester_Class_1.var_14); + } while (var_94 < 16); + { + var_73 = var_73--; + Tester_Class_2.var_45 = (Tester_Class_1.var_14 ? Tester_Class_1.var_14 : !false) ? "oaxg" : "igdnja"; + } + ((new Tester_Class_1[Tester_Class_1.var_21])[Tester_Class_1.var_21]).equals(new Tester_Class_1().var_15 = (Tester_Class_2.var_45 = "agdnue").charAt(1416972150) != Tester_Class_2.var_47 ? new Tester_Class_1() : new Tester_Class_1()); + byte var_96 = Tester_Class_1.var_21 >>>= (var_85 = (var_85 = '`')); + Tester_Class_2.var_45 = ""; + Tester_Class_2.var_47 += Tester_Class_2.var_47; + Tester_Class_2.var_45 = Tester_Class_2.var_45; + } + public String toString() + { + String result = "[\n"; + result += "Tester.var_71 = "; result += Printer.print(var_71); + result += "\n"; + result += "Tester.var_70 = "; result += Printer.print(var_70); + result += "\n"; + result += "Tester.var_72 = "; result += Printer.print(var_72); + result += "\n"; + result += "Tester.var_75 = "; result += Printer.print(var_75); + result += "\n"; + result += "Tester.var_73 = "; result += Printer.print(var_73); + result += "\n"; + result += "Tester.var_74 = "; result += Printer.print(var_74); + result += ""; + result += "\n]"; + return result; + } + static class Printer + { + public static String print(boolean arg) { return String.valueOf(arg); } + public static String print(byte arg) { return String.valueOf(arg); } + public static String print(short arg) { return String.valueOf(arg); } + public static String print(char arg) { return String.valueOf((int)arg); } + public static String print(int arg) { return String.valueOf(arg); } + public static String print(long arg) { return String.valueOf(arg); } + public static String print(float arg) { return String.valueOf(arg); } + public static String print(double arg) { return String.valueOf(arg); } + + + public static String print(Object arg) + { + return print_r(new java.util.Stack(), arg); + } + + private static String print_r(java.util.Stack visitedObjects, Object arg) + { + String result = ""; + if (arg == null) + result += "null"; + else + if (arg.getClass().isArray()) + { + for (int i = 0; i < visitedObjects.size(); i++) + if (visitedObjects.elementAt(i) == arg) return ""; + + visitedObjects.push(arg); + + final String delimiter = ", "; + result += "["; + + if (arg instanceof Object[]) + { + Object[] array = (Object[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print_r(visitedObjects, array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof boolean[]) + { + boolean[] array = (boolean[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof byte[]) + { + byte[] array = (byte[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof short[]) + { + short[] array = (short[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof char[]) + { + char[] array = (char[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof int[]) + { + int[] array = (int[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof long[]) + { + long[] array = (long[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof float[]) + { + float[] array = (float[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + else + if (arg instanceof double[]) + { + double[] array = (double[]) arg; + for (int i = 0; i < array.length; i++) + { + result += print(array[i]); + if (i < array.length - 1) result += delimiter; + } + } + + result += "]"; + visitedObjects.pop(); + + } else + { + result += arg.toString(); + } + + return result; + } + } +} + + diff --git a/hotspot/test/compiler/6663848/Tester.java b/hotspot/test/compiler/6663848/Tester.java new file mode 100644 index 00000000000..c2e797967a3 --- /dev/null +++ b/hotspot/test/compiler/6663848/Tester.java @@ -0,0 +1,478 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6663848 + * @summary assert(i < Max(),"oob") + */ + +/* Complexity upper bound: 296055 ops */ + +final class Tester_Class_0 { + byte var_1; + static double var_2; + String var_3; + char var_4 = 'n'; + static int var_5; + String var_6; + final long var_7 = 4161100809902398464L; + static String var_8 = "a"; + + + public Tester_Class_0() + { + switch (((false ^ !"n".startsWith("kmmhtohv", 553985525) ? true : false) ? 'k' : (var_4 *= - (var_2 = 3.1182935E38F))) - (~2013121027650726912L >= 2.929692E38F / (var_1 = (byte)4.2723157E37F) ? var_4 | (short)var_7 : ~ ((byte)"".indexOf("yuno", 4922080)))) + { + case 125: + + case ']': + + case 6: + var_5 = (false ? false : 3708707602755734528L >= 1648075631) ? var_4 : (false ? var_4 : ++var_4); + break; + + case 46: + Object var_15; + ++var_4; + float var_16 = 3.1085987E38F; + var_5 = 'h'; + var_1 = true ? (byte)9.482988718680618E307 : (false && false ? (byte)var_7 : (byte)6793807430041920512L); + final byte var_17 = var_1 = (337740577 ^ ~8932537004307666944L) / (short)var_16 - (byte)var_7 << var_7 > ~1539422023641354240L ? (false ? (byte)var_4 : (byte)9.302678E37F) : (byte)(var_5 = (byte)1.3007792E38F); + var_15 = "an"; + break; + + case 29: + var_3 = (var_6 = (var_8 = "kgc")); + break; + + case 60: + + } + char var_18; + ((new Tester_Class_0[var_1 = (byte)(var_2 = 93813743)])[var_1 = (byte)var_4]).var_1 = (var_1 = (var_1 = (byte)5.1405316E37F)); + var_8 = var_8; + float var_19 = 0F; + var_2 = var_4; + do + { + var_4 >>= var_7; + var_19++; + var_4 %= true ? (short)7643330105057892352L : (short)1.1014013E38F; + } while (var_19 < 2 && (! (true & (!true && false)) && true)); + var_4++; + int var_20 = 0; + var_4 = ~var_7 == (var_1 = (byte)var_7) | (float)var_20 <= 'H' ? 'r' : (var_4 |= (byte)var_4); + for (var_6 = (var_8 = "wqmnvxava"); (false ? (short)+ ~3540350558052792320L : + ~ ~3244965056572428288L - (var_4 *= 8.314953959831226E307)) <= +9.34280058703911E307 && var_20 < 6; var_2 = 3.0507823E38F) + { + var_2 = ~ ((byte)844279629935048704L) ^ (var_19 <= (false ? '\\' : 'B') ? (byte)(short)(var_1 = (byte)(short)var_19) : (var_1 = (var_1 = (var_1 = (byte)'T')))); + var_20++; + var_5 = (short)(var_7 >>> (! !true & true ? 'D' : (var_4 -= 1.1444072012663494E308))); + (var_6 = "jnjbrmaus").compareTo(var_3 = false ? "pfmv" : (var_8 = var_8)); + } + var_2 = func_0(1248385981, 'V' != '[' ? (short)1.0082348960424545E308 : (byte)var_4, new double[var_1 = (byte)'p'][(byte)var_19], 1.3646683639847343E308); + var_5 = (var_1 = (var_1 = (true ^ false ? "bfh".startsWith(var_8) : true || !true) | false ? (byte)(var_2 = - ~var_7) : (var_1 = (byte)var_19))); + var_3 = (var_3 = "dn"); + var_2 = false ? (var_1 = (byte)9.136750130102702E307) : var_7; + } + + + + + final short func_0(int arg_0, short arg_1, double[][] arg_2, double arg_3) + { + double[][] var_9 = arg_2; + arg_0 <<= true ? (byte)- +1.1174307E37F : (var_1 = (byte)911334714); + switch ("touoh".endsWith(var_8) ^ ! ! (++var_4 != 1.8567045E38F) ? (var_4 <<= arg_1) : 'E') + { + case 'a': + + case 46: + + case 's': + + case 50: + ((new Tester_Class_0[(byte)arg_0][(byte)- (- + - - + - +1.775205E38F - (arg_1 |= 'Z'))])[var_1 = (var_1 = (byte)4.020531E37F)][var_1 = (var_1 = (byte)883328311549528064L)]).var_4 &= (var_6 = var_8).charAt(arg_0); + var_3 = false ? var_8 : "amfijbpwa"; + var_4 -= -1.4699719646972257E308; + var_2 = (var_1 = (byte)(arg_1 += 1.6757431E38F)); + var_1 = (var_1 = (var_1 = (byte)+1.4416583523884388E308)); + final Object var_10 = (new Object[(byte)(arg_1 += var_4)])[var_1 = (byte)- +1.0281942E38F]; + arg_1 = arg_1; + break; + + case 7: + var_8 = var_8 + var_8; + break; + + case 'N': + + case 'V': + + case 56: + + case 'I': + + } + arg_0 &= arg_1; + var_3 = false ? var_8 : "vpaj"; + var_4 = (var_4 *= arg_1); + arg_3 *= (var_4 = var_4); + final char var_11 = true ? var_4 : (char)(var_4 << (var_1 = (byte)(arg_1 &= arg_0))); + boolean var_12; + var_4 ^= '`'; + "nkj".startsWith(var_6 = "wrcnrdd"); + var_1 = (byte)~var_7; + var_6 = (var_8 = "ul"); + return (var_12 = 3548576322219573248L <= var_4++ & ((var_12 = !true) || (var_12 = !false | false))) ? arg_1-- : (var_1 = (byte)+ (var_2 = 2.7633542E38F)); + } + + protected final void func_1(final String arg_0, Object arg_1, short arg_2) + { + arg_2 *= ~8267766955221100544L; + arg_1 = (var_6 = var_8); + arg_2 <<= false ? (var_1 = (var_1 = (var_1 = (byte)1.6645553629318776E308))) : arg_2; + } + + protected final static float func_2(byte arg_0, final String arg_1) + { + var_8 = arg_1; + char var_13 = ((new Tester_Class_0[arg_0 |= ']'])[arg_0]).var_4--; + var_5 = 907889433; + { + var_13 ^= (var_5 = var_13); + } + var_8 = arg_1; + var_5 = (byte)1759688161; + var_8 = (new String[arg_0 >>>= (short)1072761211])[arg_0]; + return 5.108221E37F; + } + + private static boolean func_3(boolean arg_0, final boolean arg_1) + { + var_2 = ((new Tester_Class_0[(byte)(short)'H'])[(byte)(short)(var_2 = (short)'k')]).var_4; + if (false) + { + var_8 = "cl"; + } + else + { + final byte[] var_14 = new byte[true ? (byte)(- ((byte)9.760296114722793E307) | ~1867374212153383936L) : (byte)(short)'Q']; + var_2 = (float)~3838271533006646272L / (- ~ ~1786841397228277760L ^ ~3695911615719734272L & 'Z'); + } + { + var_8 = var_8; + } + ((new Tester_Class_0[(byte)(var_2 = (short)~ - +4818709334539164672L)])[(byte)'W']).var_1 = true || false & arg_0 ^ (arg_1 ^ arg_0 ? arg_0 : (arg_0 ^= true)) ? (byte)1.5309163701271477E308 : (byte)3.0904342E38F; + ((new Tester_Class_0[(byte)756871578277111808L][(byte)+ + -3.0687752E38F])[(byte)'f'][(byte)1544156315]).var_6 = (var_8 = "vqey"); + return arg_1; + } + + public final char func_4(short arg_0) + { + { + var_6 = (var_3 = "hjtjar"); + var_1 = false ? (byte)4.02486350499973E307 : (byte)1.3222663E38F; + } + var_1 = (new byte[var_1 = (var_1 = (byte)1770517884)])[var_1 = (byte)arg_0]; + var_4++; + --arg_0; + var_5 = true ? 'D' : (var_4 ^= (var_5 = 134858941)); + return (char)~ (7273058621469586432L << (byte)3.1756883E38F ^ (false ? (byte)(var_5 = var_4) : (arg_0 >>= 6165812289376474112L))) < (2046127339 ^ + ((byte)arg_0)) ? (!false ? (var_4 %= 1.8187417377124746E307) : (var_4 *= 445936805)) : var_4; + } + +} + + +class Tester_Class_1 { + Tester_Class_0[][] var_21; + static long var_22 = 6671342492736446464L; + float var_23 = 2.9329673E38F; + final int var_24 = 1834862519; + int var_25 = 69920645; + static char var_26; + static Object var_27; + static int var_28 = Tester_Class_0.var_5 = false ? 'U' : (var_26 = (var_26 = 'R')); + + + public Tester_Class_1() + { + (false ? (Tester_Class_0)(var_27 = Tester_Class_0.var_8) : (Tester_Class_0)(var_27 = "a")).var_1 = (short)(var_23 %= var_23) >= (byte)1217257602 | var_25 == (char)(var_23 += var_23) ? (byte)new Tester_Class_0().var_4-- : ((true | false) ^ !false ? (byte)6.122806E37F : (byte)1.084542872057614E308); + Tester_Class_0.var_2 = new Tester_Class_0().var_7; + --var_22; + boolean var_32 = ! ((new Tester_Class_0().var_1 = (((new Tester_Class_0[(byte)var_22])[(byte)var_23]).var_1 = false ? (byte)(var_23 = var_28) : (byte)1.5858707076311894E308)) != (char)+var_23); + var_25 -= (true ? (byte)5.488240359086226E307 : (((Tester_Class_0)(var_27 = Tester_Class_0.var_8)).var_1 = (byte)'L')) * (Tester_Class_0.var_2 = 7.045106259776882E307); + Object var_33 = (var_32 ^= var_32) ? (var_27 = (Tester_Class_0.var_8 = (Tester_Class_0.var_8 = "gaemnaep"))) : (new Tester_Class_0[(byte)'g'])[(byte)(short)271735827]; + byte var_34 = var_32 ? (byte)((Tester_Class_0)var_33).var_7 : ((var_32 &= true) ? (byte)(Tester_Class_0.var_2 = 1.6975344767401616E307) : (byte)- ((double)var_22)); + Tester_Class_0.var_2 = 1.4644308179397427E308; + var_28 /= (short)1681483575; + Tester_Class_0.var_2 = (var_34 <<= (var_25 ^= ~ (var_22 |= (var_22 = var_22)))); + var_23 *= (char)(var_28 *= var_32 ? var_34 ^ --var_34 : 3220732582528450560L); + if ((((Tester_Class_0)var_33).var_4 &= var_34) != (short)var_28) + { + Tester_Class_0.var_8 = ((false ? (Tester_Class_0)var_33 : (Tester_Class_0)var_33).var_6 = Tester_Class_0.var_8); + } + else + { + var_33 = false | (var_32 ^= true) ? ((new Tester_Class_0[var_34][var_34])[var_34])[var_34] : (Tester_Class_0)var_33; + } + if (false) + { + var_22 = 107656877775594496L; + } + else + { + ((var_32 &= (var_32 |= var_32)) || (var_23 /= var_25) == (Tester_Class_0.var_2 = 7649348100017113088L) ? (new Tester_Class_0[var_34])[var_34] : (Tester_Class_0)var_33).var_4 >>>= (((new Tester_Class_0[var_34])[var_34 <<= 'C']).var_6 = (((Tester_Class_0)(var_33 = (var_33 = var_33))).var_6 = ++var_28 > var_23 ? "qgq" : (Tester_Class_0.var_8 = Tester_Class_0.var_8))).equalsIgnoreCase(Tester_Class_0.var_8) ? var_34++ : ++var_34; + } + String[][] var_35; + Tester_Class_0.var_8 = Tester_Class_0.var_8; + var_27 = (new Tester_Class_0[var_34][var_34 /= 226411329])[false ? --var_34 : (var_34 /= 1.7237614E38F)][var_34]; + var_23 %= var_25; + } + + + + protected Object clone() + { + var_28 >>>= (new Tester_Class_0().var_1 = (byte)new Tester_Class_0().var_4); + ((Tester_Class_0)(var_27 = (Tester_Class_0.var_8 = (Tester_Class_0.var_8 = (Tester_Class_0.var_8 = "ybndugrur"))))).var_3 = Tester_Class_0.var_8; + var_22--; + new Tester_Class_0().var_4 -= (new Tester_Class_0().var_1 = (byte)'O'); + { + short var_29 = 12378; + } + Tester_Class_0.var_8 = "fd"; + "".lastIndexOf("bgsxwmil"); + new Tester_Class_0().var_6 = (Tester_Class_0.var_2 = -1.7590174497347678E308) == (var_26 = 'o') | true && !false ? Tester_Class_0.var_8 : (((Tester_Class_0)(var_27 = "")).var_6 = Tester_Class_0.var_8); + return var_27 = (var_27 = (var_27 = (var_27 = (Tester_Class_0.var_8 = Tester_Class_0.var_8).substring(var_24)))); + } + + public boolean equals(Object obj) + { + --var_28; + var_23 /= +var_23 * -6025098819014877184L / 3.3957492E38F / (short)'i'; + Tester_Class_0.var_2 = 3.0420988E38F * ((short)var_23 <= (var_23 %= 8.761205585617465E307) % + -1.2374670294031777E308 ? (var_23 = 'P') : (float)+ +1.0313120780554142E308); + (7489001532003495936L >= 'C' ? (Tester_Class_0)obj : (Tester_Class_0)(var_27 = obj)).func_4((short)(float)(byte)(float)(Tester_Class_0.var_2 = 1601763635)); + (var_23 * 2.2882572E38F <= (short)var_25 * (true || false ? (short)~ ((byte)1.1382317160718865E307) : (Tester_Class_0.var_2 = 7.909133507918336E307)) ? (Tester_Class_0)obj : (Tester_Class_0)obj).var_4++; + boolean var_30 = true; + var_27 = new Tester_Class_0(); + final String var_31 = "aiqnc"; + return 1.1357028E38F + (var_30 ? (Tester_Class_0)(var_27 = obj) : (Tester_Class_0)obj).var_7 == 3.860172628750592E306; + } + + +} + +public class Tester { + final static long var_36 = (4.4957056E37F < Tester_Class_1.var_22 + 281107777128915968L ? (Tester_Class_1.var_26 = 't') : (char)Tester_Class_1.var_28) - (4654994097042818048L | (byte)(Tester_Class_0.var_2 = (short)(Tester_Class_1.var_26 = ']'))) ^ 349774342780012544L; + + + static long func_0(final Tester_Class_1 arg_0, long arg_1) + { + ((Tester_Class_0)(Tester_Class_1.var_27 = (Tester_Class_0)(Tester_Class_1.var_27 = Tester_Class_0.var_8))).var_4 |= --new Tester_Class_0().var_4; + return Tester_Class_1.var_22 &= new Tester_Class_0().var_4; + } + + protected Tester_Class_1 func_1(final boolean arg_0, Object arg_1) + { + Tester_Class_0.var_2 = (short)Tester_Class_1.var_22; + ((arg_0 ? (byte)8.639448452214698E307 : ((Tester_Class_1)arg_1).var_24) <= ((Tester_Class_1)(Tester_Class_1.var_27 = new float[(byte)Tester_Class_1.var_22])).var_25++ ? (Tester_Class_0)arg_1 : (Tester_Class_0)(arg_1 = (Tester_Class_1.var_27 = (Tester_Class_0)arg_1))).var_3 = (Tester_Class_0.var_8 = "pgfdbinj"); + arg_1 = (new Tester_Class_0[((Tester_Class_0)arg_1).var_1 = (byte)1.0730194668655324E308])[(byte)'l']; + Tester_Class_0.var_8 = Tester_Class_0.var_8; + Tester_Class_1.var_27 = arg_0 & (true | !true) ? (Tester_Class_1)arg_1 : (Tester_Class_1)arg_1; + Tester_Class_1.var_28 += arg_0 ? (byte)(Tester_Class_0.var_8.compareToIgnoreCase(Tester_Class_0.var_8) % (Tester_Class_1.var_28 %= 2.2770412E38F)) : (byte)((byte)(short)Tester_Class_1.var_28 ^ var_36); + Tester_Class_1.var_28 <<= ((Tester_Class_0)arg_1).var_4; + return arg_0 ? (false ^ false ? (Tester_Class_1)arg_1 : (Tester_Class_1)arg_1) : (Tester_Class_1)arg_1; + } + + protected final static String[][] func_2(final double arg_0) + { + Tester_Class_0.var_2 = (((Tester_Class_1.var_22 = ((Tester_Class_1)(Tester_Class_1.var_27 = "")).var_25++) != + ((byte)(Tester_Class_0.var_2 = - ((byte)2.690435E38F))) ? (Tester_Class_1)(Tester_Class_1.var_27 = "twoj") : (new Tester_Class_1[(byte)'n'])[(byte)- ((byte)'p')]).var_25 /= (new short[false ? (byte)arg_0 : (byte)3.1713847E38F])[(byte)(short)((Tester_Class_0)(Tester_Class_1.var_27 = (Tester_Class_1.var_27 = "fi"))).var_7]); + { + ((new Tester_Class_1[(byte)9.709543613377303E307])[((Tester_Class_0)(Tester_Class_1.var_27 = (Tester_Class_0.var_8 = "efwkox"))).var_1 = (byte)7789404846284517376L]).var_23 *= (((new Tester_Class_0[(byte)'J'][(byte)++Tester_Class_1.var_28])[(byte)Tester_Class_1.var_28][(byte)(Tester_Class_1.var_28 = 1677818267)]).var_1 = false || true ? (byte)1.4659824E38F : (byte)(Tester_Class_1.var_26 = 'T')); + } + Tester_Class_0.var_2 = !true | !false | false & ! (!true & (true ^ false)) ? (byte)(Tester_Class_1.var_26 = 'l') : (short)(arg_0 * (char)(byte)Tester_Class_1.var_28); + Tester_Class_1.var_28 <<= false ^ (! ! (!false | ! !true | true) | (Tester_Class_0.var_2 = arg_0) == 245171309) ? (byte)arg_0 : (short)Tester_Class_1.var_22; + { + ((Tester_Class_1)(true ? (Tester_Class_1.var_27 = "axpbpadi") : Tester_Class_0.var_8)).var_23 = ((Tester_Class_1)(Tester_Class_1.var_27 = (new Tester_Class_0[(byte)1.1668668415637981E308][(byte)1.4116134699564312E308])[(byte)-7.4415765E37F][(byte)5156322492367086592L])).var_25; + } + final double var_37 = 1.6970877829548446E308; + --(Tester_Class_1.var_28 == (byte)((byte)arg_0 + (byte)1.1632396E38F) ? (Tester_Class_0)(Tester_Class_1.var_27 = "vluk") : (Tester_Class_0)(Tester_Class_1.var_27 = (Tester_Class_0.var_8 = "pfki"))).var_4; + Tester_Class_1.var_22--; + return new String[new Tester_Class_0().var_1 = (((Tester_Class_0)(Tester_Class_1.var_27 = "filxvch")).var_1 = (byte)var_36)][new Tester_Class_0().var_1 = (byte)'C']; + } + + final short func_3(byte arg_0, final short arg_1) + { + ((Tester_Class_0)(Tester_Class_1.var_27 = (Tester_Class_0.var_8 = "oenvgqdit"))).var_6 = Tester_Class_0.var_8; + new Tester_Class_0().var_4 >>>= + -var_36; + Tester_Class_0.var_2 = (((new Tester_Class_1[arg_0])[arg_0 %= ++Tester_Class_1.var_28]).var_25 &= Tester_Class_1.var_22); + ((new Tester_Class_1[arg_0])[arg_0 |= 1942533325]).var_23 %= arg_0 < arg_0 ? 'm' : 'N'; + float var_38; + ((new Tester_Class_1[arg_0])[arg_0]).var_23 /= (((new Tester_Class_1[arg_0][arg_0])[arg_0 |= 'N'])[arg_0 <<= - ((byte)- (Tester_Class_0.var_2 = 3.3324301E38F))]).var_23; + return true ? arg_1 : arg_1; + } + + private String func_4() + { + if (true) + { + ((Tester_Class_0)(Tester_Class_1.var_27 = (Tester_Class_1.var_27 = (Tester_Class_1.var_27 = Tester_Class_0.var_8)))).var_1 = (byte)6.4527776E37F; + ((Tester_Class_0)(Tester_Class_1.var_27 = new char[(byte)1.5121402849337185E307])).var_4 >>= - ((byte)3.3631582E37F) + (Tester_Class_1.var_28 /= 2.813947549586372E307); + } + else + { + { + Tester_Class_1.var_22 *= 1.6498653E36F; + } + Tester_Class_0.var_2 = + ((byte)7.750601265069686E307) > (short)(byte)3131520439106527232L ? (short)4699552681135671296L : (short)Tester_Class_1.var_22; + Tester_Class_1.var_22++; + ((Tester_Class_1)(new Object[(byte)6.231994821505742E307])[(byte)Tester_Class_1.var_22]).var_23 %= 30526551; + { + Tester_Class_0.var_2 = ((Tester_Class_1)(Tester_Class_1.var_27 = new short[(byte)9.628297E37F])).var_25; + } + Tester_Class_1.var_28 /= (byte)(false ^ Tester_Class_0.var_8.equalsIgnoreCase(Tester_Class_0.var_8) ? (byte)2.689633745095358E307 : (short)1.2532476E38F); + float var_39; + long[] var_40 = new long[((Tester_Class_0)(Tester_Class_1.var_27 = Tester_Class_0.var_8)).var_1 = (((Tester_Class_0)(Tester_Class_1.var_27 = (Tester_Class_0.var_8 = Tester_Class_0.var_8))).var_1 = (byte)(1.8335008E38F % (true | false ? (short)Tester_Class_1.var_22 : (byte)'P')))]; + } + Tester_Class_0.var_2 = (((new Tester_Class_0[((Tester_Class_0)(Tester_Class_1.var_27 = "inufeoe")).var_1 = (byte)(short)'M'])[(byte)(Tester_Class_0.var_2 = + - -2.274269E38F)]).var_1 = (((Tester_Class_0)(Tester_Class_1.var_27 = "c")).var_1 = (byte)'Z')); + Tester_Class_0.var_8 = (Tester_Class_0.var_8 = Tester_Class_0.var_8); + return "rkvffvlf"; + } + + final char func_5(final char arg_0, final Object[] arg_1, final double arg_2, Object arg_3) + { + arg_3 = true && Tester_Class_1.var_22 < (((Tester_Class_0)arg_3).var_1 = (((Tester_Class_0)(Tester_Class_1.var_27 = arg_3)).var_1 = (byte)arg_2)) ? "dgmwbkv" : Tester_Class_0.var_8; + (true ? (Tester_Class_1)arg_3 : (Tester_Class_1)arg_3).var_23 -= (Tester_Class_0.var_2 = arg_0); + arg_3 = (new String[(byte)arg_2])[(byte)-2.797633529863769E307]; + (false ^ !false ^ (!true && true) ? (Tester_Class_0)arg_3 : (Tester_Class_0)arg_3).var_4 -= (new char[((Tester_Class_0)arg_3).var_1 = (((Tester_Class_0)arg_3).var_1 = (((Tester_Class_0)arg_3).var_1 = (byte)2.433897E38F))])[((Tester_Class_0)arg_3).var_1 = (byte)+7.036923762392132E307]; + Tester_Class_0.var_8 = Tester_Class_0.var_8; + Tester_Class_0.var_2 = true ^ +((Tester_Class_1)(arg_3 = "o")).var_23 <= arg_2 ? (short)Tester_Class_1.var_22 : (((Tester_Class_0)arg_3).var_1 = (byte)1.9730195E38F); + (false ? (Tester_Class_0)arg_3 : (Tester_Class_0)arg_3).var_6 = "bpjqfacys"; + ((new Tester_Class_0[((Tester_Class_0)arg_3).var_1 = (byte)1969581340][((Tester_Class_0)arg_3).var_1 = (byte)(Tester_Class_0.var_2 = arg_0)])[((Tester_Class_0)arg_3).var_1 = (byte)(Tester_Class_0.var_2 = 4044194664687833088L)][((Tester_Class_0)arg_3).var_1 = (byte)((Tester_Class_1)arg_3).var_24]).var_1 = (false ? (byte)+ ((byte)1.2689328633821032E305) == arg_2 : false) ? (byte)arg_2 : (((Tester_Class_0)arg_3).var_1 = (byte)1586517741); + return (func_3(((Tester_Class_0)arg_3).var_1 = (byte)Tester_Class_1.var_28, (short)(byte)- +func_1(true, arg_3).var_23) > 1882532904 ? (short)2.6362656E38F >= (char)2.445034E38F & false : var_36 > Tester_Class_1.var_22) ? ((new Tester_Class_0[(byte)1.2074529E38F][(byte)'N'])[(byte)1.3365433211782782E308][(byte)Tester_Class_1.var_28]).var_4 : 'O'; + } + + private final static Tester_Class_1 func_6(String arg_0, String arg_1) + { + Tester_Class_1.var_22 += ((new Tester_Class_0[(byte)4.1707075152824266E306])[(byte)(short)(((Tester_Class_0)(Tester_Class_1.var_27 = "tmyiha")).var_4 &= 'e')]).var_4; + return (new Tester_Class_1[((Tester_Class_0)(Tester_Class_1.var_27 = arg_1)).var_1 = (byte)2.8419246E38F][(byte)Tester_Class_1.var_22])[((Tester_Class_0)(Tester_Class_1.var_27 = (Tester_Class_1.var_27 = arg_0))).var_1 = (((Tester_Class_0)(Tester_Class_1.var_27 = (Tester_Class_0.var_8 = "nvyfpdyms"))).var_1 = (byte)Tester_Class_1.var_22--)][((Tester_Class_0)(Tester_Class_1.var_27 = "kklsnsnia")).var_1 = (byte)'[']; + } + + double func_7(Object arg_0, final String arg_1) + { + if (false) + { + ((Tester_Class_0)arg_0).var_1 = (byte)'Z'; + } + else + { + ((Tester_Class_0)arg_0).var_3 = Tester_Class_0.var_8; + } + float var_41 = (true ? (new Tester_Class_1[((Tester_Class_0)arg_0).var_1 = (byte)var_36])[((Tester_Class_0)arg_0).var_1 = (byte)Tester_Class_1.var_22] : (Tester_Class_1)arg_0).var_23 /= 'n'; + ++Tester_Class_1.var_22; + return true ^ +func_6(arg_1, Tester_Class_0.var_8).var_23 < ~6945306015697774592L & (Tester_Class_1.var_28 |= var_36) <= var_36 ? + -1.4330949313452472E308 - -6602331706844466176L : Tester_Class_1.var_28; + } + + private final static byte func_8(final Object arg_0, double arg_1, final double arg_2, double arg_3) + { + ((Tester_Class_1)arg_0).var_23 = (short)(!false && (new boolean[(byte)2.2566308E38F])[((Tester_Class_0)arg_0).var_1 = (byte)((Tester_Class_1)arg_0).var_25] ? arg_2 : 3.0315489414155014E307); + short var_42 = (new short[((Tester_Class_0)arg_0).var_1 = (((Tester_Class_0)arg_0).var_1 = (byte)var_36)])[(byte)arg_2]; + Tester_Class_1.var_22 <<= ((new Tester_Class_0[(byte)var_42])[((Tester_Class_0)arg_0).var_1 = (byte)'X']).var_4; + (false ? new Tester_Class_0() : new Tester_Class_0()).var_4 *= 6.636831399350763E307; + (true & false ^ !((Tester_Class_1)arg_0).equals(arg_0) ? (Tester_Class_0)arg_0 : (Tester_Class_0)arg_0).var_4 <<= (Tester_Class_1.var_22 >>>= (Tester_Class_1.var_28 -= Tester_Class_1.var_28)) / 1064434; + int var_43; + final Object var_44 = Tester_Class_1.var_27 = new byte[((Tester_Class_0)arg_0).var_1 = (byte)+arg_2]; + ((Tester_Class_0)var_44).var_1 = (byte)arg_1; + Tester_Class_1 var_45 = (3582921389614857216L != 2.132918E38F / Tester_Class_1.var_22 % (((Tester_Class_1)var_44).var_23 %= var_42--) ? false : false ^ !false) ? func_6(((Tester_Class_0)arg_0).var_6 = Tester_Class_0.var_8, Tester_Class_0.var_8 = Tester_Class_0.var_8) : (Tester_Class_1)arg_0; + arg_1 *= false ? (false ? (byte)var_45.var_23 : (byte)var_45.var_24) : (byte)8158132319185776640L; + Tester_Class_0.var_8 = (new Tester_Class_0().var_6 = "gvxkyj"); + Tester_Class_1.var_27 = "bkfbu"; + arg_1 *= (((Tester_Class_0)arg_0).var_4 += new Tester_Class_0().var_4); + Tester_Class_0 var_46 = (false ? false && - (((Tester_Class_0)arg_0).var_1 = (byte)var_45.var_24) > var_45.var_23 - arg_2 : ("fn".startsWith(Tester_Class_0.var_8) && false) & !true) ? (Tester_Class_0)arg_0 : (Tester_Class_0)arg_0; + return var_46.var_1 = (var_46.var_1 = (var_46.var_1 = (byte)var_45.var_23)); + } + + public static void main(String[] args) + { + for (int i = 0; i < 100000; i++) { + Tester t = new Tester(); + try { + t.test(); + } catch(Throwable e) { + } + if (t.var_36 != -4918908939899620363L) { + throw new InternalError(t.var_36 + " != -4918908939899620363"); + } + } + } + + private void test() + { + ((Tester_Class_0)(Tester_Class_1.var_27 = new Tester_Class_0())).var_4 &= new Tester_Class_0().var_4 >>> (short)new Tester_Class_1().var_25; + Tester_Class_1.var_22 <<= Tester_Class_1.var_22; + Tester_Class_1.var_27 = ((true | ! !false) & false ? ! !true : 6.5017485E37F == (short)(Tester_Class_1.var_22 &= 'h')) ? (Tester_Class_1.var_27 = new Tester_Class_1()) : new Tester_Class_1(); + (1.252611E37F < (((new Tester_Class_0[(byte)'X'])[(byte)6.916916470825763E307]).var_4 /= (byte)Tester_Class_1.var_28 < (new short[(byte)7.626803503643197E307])[(byte)var_36] ? (short)new Tester_Class_0().var_4 : (short)(byte)Tester_Class_1.var_22) ? (true ? new Tester_Class_0() : new Tester_Class_0()) : (true ? new Tester_Class_0() : (Tester_Class_0)(Tester_Class_1.var_27 = Tester_Class_0.var_8))).var_4 ^= Tester_Class_1.var_28++; + (true ? new Tester_Class_1() : func_1(true, Tester_Class_1.var_27 = "jjgccelm")).var_23 -= (- - + + +1.2976166388790213E308 != ((!true ^ ! !true) & (short)(Tester_Class_1.var_28 &= var_36) <= (Tester_Class_1.var_26 = 'C') ? 1163089569715148800L : 8.591879058615699E307) ? (new Tester_Class_0().var_1 = (new Tester_Class_0().var_1 = (byte)2.7209893E38F)) : (!false ^ ! !false ? (short)'x' : (short)'a')) + 7620981797791666176L; + new Tester_Class_0().var_4 ^= 8777687662500669440L; + final String[] var_47 = new String[((1864097118983963648L | (Tester_Class_1.var_26 = '[')) < + (new Tester_Class_1().var_23 += --new Tester_Class_0().var_4) ? ! !true : false) ? (new Tester_Class_0().var_1 = (new Tester_Class_0().var_1 = (byte)2.6448988E38F)) : (byte)Tester_Class_1.var_22]; + long var_48 = 0L; + Tester_Class_0.var_2 = "nwcmc".codePointAt("wgcdlmd".compareTo("jyt")); + do + { + Tester_Class_1.var_22 += new Tester_Class_0().var_4; + var_48++; + Tester_Class_1.var_27 = false ? "dfvpqs" : Tester_Class_0.var_8; + new Tester_Class_0().var_1 = (new Tester_Class_0().var_1 = (new byte[(byte)2.2825838E38F])[(byte)4.2446597794703817E307]); + } while ((true ? !false : false & !false) && (var_48 < 117 && true)); + int var_49 = 0; + Tester_Class_1.var_26 = 'I'; + short var_50; + while (var_49 < 225 && ('U' | ~ ((byte)9.556538701292864E306)) < var_49) + { + var_50 = (var_50 = ((byte)1.2016701369644112E308 != (var_50 = (short)1.2518271E38F) ^ !true ? !true : false) ? (short)6.629572378442352E307 : (byte)'O'); + var_49++; + var_50 = true ? (byte)Tester_Class_1.var_22 : (byte)(Tester_Class_1.var_22 = (byte)var_48); + byte var_51; + short var_52; + } + Tester_Class_1.var_27 = Tester_Class_0.var_8 + "r"; + var_50 = (var_50 = true ^ ! (!false ^ false) ? (byte)573442894 : (byte)2.1479471E38F); + ((var_50 = (short)'w') >= (new Tester_Class_0().var_1 = (byte)5.148172E37F) & true ? new Tester_Class_0() : new Tester_Class_0()).var_4 >>= true ? (new Tester_Class_0().var_4 /= (byte)Tester_Class_1.var_28) : (Tester_Class_1.var_26 = '^'); + float var_53; + (func_6(Tester_Class_0.var_8, Tester_Class_0.var_8).var_24 <= (var_50 = (var_50 = (short)var_48)) ^ !true | true & true | true ^ false ? (Tester_Class_1)(Tester_Class_1.var_27 = Tester_Class_0.var_8) : new Tester_Class_1()).var_23 /= ((new Tester_Class_0[(byte)1.6656795E38F])[new Tester_Class_0().var_1 = (byte)1.212530193895014E308]).var_4; + long var_54 = 0L; + Object var_55; + (true | --new Tester_Class_0().var_4 == 2898909413610959872L & true == true ? func_6(Tester_Class_0.var_8, Tester_Class_0.var_8) : new Tester_Class_1()).var_23 %= 7471272661059674112L; + while (false & (false | 5.7300464E37F != (short)(Tester_Class_0.var_2 = (short)var_36)) && var_54 < 293) + { + func_6(Tester_Class_0.var_8 = "wts", Tester_Class_0.var_8 = (Tester_Class_0.var_8 = Tester_Class_0.var_8)).var_25 |= (Tester_Class_1.var_22 ^= (var_50 = (byte)1.0904691577897794E308)); + var_54++; + (false ? func_6(Tester_Class_0.var_8, "inujn") : func_6(Tester_Class_0.var_8, Tester_Class_0.var_8 = Tester_Class_0.var_8)).var_23 /= (Tester_Class_0.var_2 = (var_50 = (((Tester_Class_0)(var_55 = Tester_Class_0.var_8)).var_1 = (byte)(short)Tester_Class_1.var_28))); + Tester_Class_0.var_8 = Tester_Class_0.var_8; + } + var_50 = func_3(new Tester_Class_0().var_1 = (new Tester_Class_0().var_1 = (byte)var_36), var_50 = (var_50 = (var_50 = (byte)var_36))); + Tester_Class_1.var_22++; + Tester_Class_1.var_28 <<= 'Y'; + } +} diff --git a/jdk/.hgtags b/jdk/.hgtags index 6eaa20bbab7..3bcfa342d46 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -1,2 +1,3 @@ 37a05a11f281b4d238e2f9e7ebb67c63f64d0e77 jdk7-b24 75fca0b0ab83ab1392e615910cea020f66535390 jdk7-b25 +fb57027902e04ecafceae31a605e69b436c23d57 jdk7-b26 diff --git a/jdk/make/com/sun/Makefile b/jdk/make/com/sun/Makefile index de9f1a77932..10a8642c817 100644 --- a/jdk/make/com/sun/Makefile +++ b/jdk/make/com/sun/Makefile @@ -41,7 +41,7 @@ endif # Omit mirror since it's built with the apt tool. SUBDIRS = $(SCRIPT_SUBDIR) image security crypto/provider jndi jmx \ java inputmethods org xml rowset net/httpserver net/ssl demo \ - tools jarsigner + tools jarsigner tracing all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/tracing/Makefile b/jdk/make/com/sun/tracing/Makefile new file mode 100644 index 00000000000..166aee38db4 --- /dev/null +++ b/jdk/make/com/sun/tracing/Makefile @@ -0,0 +1,46 @@ +# +# Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# +# Makefile for building tracing classes +# + +BUILDDIR = ../../.. +PACKAGE = com.sun.tracing +PRODUCT = sun +include $(BUILDDIR)/common/Defs.gmk + +SUBDIRS = dtrace +all build: + $(SUBDIRS-loop) +clean clobber:: + $(SUBDIRS-loop) + +AUTO_FILES_JAVA_DIRS = com/sun/tracing + +# +# Rules. +# +include $(BUILDDIR)/common/Classes.gmk diff --git a/jdk/make/com/sun/tracing/dtrace/Makefile b/jdk/make/com/sun/tracing/dtrace/Makefile new file mode 100644 index 00000000000..73e61aa817d --- /dev/null +++ b/jdk/make/com/sun/tracing/dtrace/Makefile @@ -0,0 +1,39 @@ +# +# Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# +# Makefile for building dtrace extension +# +BUILDDIR = ../../../.. +PACKAGE = com.sun.tracing.dtrace +PRODUCT = sun +include $(BUILDDIR)/common/Defs.gmk + +AUTO_FILES_JAVA_DIRS = com/sun/tracing/dtrace + +# +# Rules. +# +include $(BUILDDIR)/common/Classes.gmk diff --git a/jdk/make/docs/Makefile b/jdk/make/docs/Makefile index 328244b9a97..5a5b496da51 100644 --- a/jdk/make/docs/Makefile +++ b/jdk/make/docs/Makefile @@ -272,6 +272,28 @@ SMARTCARDIO_DOCTITLE = "Java$(TRADEMARK) Smart Card I/O" SMARTCARDIO_JAVADOCHEADER = "Java Smart Card I/O" # SMARTCARDIO_PKGS is located in NON_CORE_PKGS.gmk +# +# Variables used by TRACING target +# + +TRACING_SOURCEPATH = $(TOPDIR)/src/share/classes +TRACING_DOCDIR = $(DOCSDIR)/jre/api/tracing + +TRACING_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ + -encoding ascii \ + -nodeprecatedlist \ + -d $(TRACING_DOCDIR) \ + -sourcepath $(TRACING_SOURCEPATH) \ + -windowtitle $(TRACING_WINDOWTITLE) \ + -doctitle $(TRACING_DOCTITLE) \ + -header $(TRACING_JAVADOCHEADER) \ + -linkoffline ../../../../../api $(DOCSDIR)/api/ + +TRACING_WINDOWTITLE = "Tracing" +TRACING_DOCTITLE = "Java$(TRADEMARK) Platform Tracing" +TRACING_JAVADOCHEADER = "Platform Tracing" +# TRACING_PKGS is located in NON_CORE_PKGS.gmk + # # Variables used by HTTPSERVER target # @@ -420,6 +442,7 @@ ALL_OTHER_TARGETS = \ jaasdocs \ jgssdocs \ smartcardiodocs \ + tracingdocs \ httpserverdocs \ mgmtdocs \ attachdocs \ @@ -585,6 +608,14 @@ smartcardiodocs: $(JAVADOC_CMD) $(SMARTCARDIO_JAVADOCFLAGS) \ $(SMARTCARDIO_PKGS) +.PHONY: tracingdocs +tracingdocs: + @# ######## api-tracing ############################ + $(RM) -r $(TRACING_DOCDIR) + $(MKDIR) -p $(TRACING_DOCDIR) + $(JAVADOC) $(TRACING_JAVADOCFLAGS) \ + $(TRACING_PKGS) + .PHONY: httpserverdocs httpserverdocs: @# ######## api-httpserver ####################### diff --git a/jdk/make/docs/NON_CORE_PKGS.gmk b/jdk/make/docs/NON_CORE_PKGS.gmk index f40add34314..8c78c6ed78d 100644 --- a/jdk/make/docs/NON_CORE_PKGS.gmk +++ b/jdk/make/docs/NON_CORE_PKGS.gmk @@ -84,6 +84,9 @@ TREEAPI_PKGS = com.sun.source.tree \ SMARTCARDIO_PKGS = javax.smartcardio +TRACING_PKGS = com.sun.tracing \ + com.sun.tracing.dtrace + # non-core packages in rt.jar NON_CORE_PKGS = $(DOMAPI_PKGS) \ $(MGMT_PKGS) \ @@ -91,4 +94,5 @@ NON_CORE_PKGS = $(DOMAPI_PKGS) \ $(JGSS_PKGS) \ $(OLD_JSSE_PKGS) \ $(HTTPSERVER_PKGS) \ - $(SMARTCARDIO_PKGS) + $(SMARTCARDIO_PKGS) \ + $(TRACING_PKGS) diff --git a/jdk/make/java/sun_nio/FILES_java.gmk b/jdk/make/java/sun_nio/FILES_java.gmk index d7ca6cd93b1..13f4fe88d27 100644 --- a/jdk/make/java/sun_nio/FILES_java.gmk +++ b/jdk/make/java/sun_nio/FILES_java.gmk @@ -33,6 +33,7 @@ FILES_java = \ sun/nio/cs/AbstractCharsetProvider.java \ sun/nio/cs/HistoricallyNamedCharset.java \ sun/nio/cs/Surrogate.java \ + sun/nio/cs/CharsetMapping.java \ sun/nio/cs/SingleByteEncoder.java \ sun/nio/cs/SingleByteDecoder.java \ sun/nio/cs/UnicodeEncoder.java \ diff --git a/jdk/make/sun/Makefile b/jdk/make/sun/Makefile index 588957b8542..0ce9014e7e1 100644 --- a/jdk/make/sun/Makefile +++ b/jdk/make/sun/Makefile @@ -63,7 +63,7 @@ SUBDIRS = jar security javazic misc net audio $(RENDER_SUBDIR) image \ $(HEADLESS_SUBDIR) $(DGA_SUBDIR) \ font jpeg cmm applet rmi beans $(JDBC_SUBDIR) \ jawt text nio launcher management $(ORG_SUBDIR) \ - native2ascii serialver tools jconsole + native2ascii serialver tools jconsole tracing all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/sun/nio/Makefile b/jdk/make/sun/nio/Makefile index c18e55a5cc7..c8e8e37cbb4 100644 --- a/jdk/make/sun/nio/Makefile +++ b/jdk/make/sun/nio/Makefile @@ -1,5 +1,5 @@ # -# Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -73,11 +73,21 @@ build: $(CHARSETS_JAR) SERVICE_DESCRIPTION = java.nio.charset.spi.CharsetProvider SERVICE_DESCRIPTION_PATH = META-INF/services/$(SERVICE_DESCRIPTION) +GENCSDATASRC = $(BUILDDIR)/tools/CharsetMapping +FILES_MAP = $(GENCSDATASRC)/sjis0213.map +FILES_DAT = $(CLASSDESTDIR)/sun/nio/cs/ext/sjis0213.dat +CHARSETMAPPING_JARFILE = $(BUILDTOOLJARDIR)/charsetmapping.jar + +$(FILES_DAT): $(FILES_MAP) + @$(prep-target) + $(BOOT_JAVA_CMD) -jar $(CHARSETMAPPING_JARFILE) \ + $(FILES_MAP) $(FILES_DAT) + $(CLASSDESTDIR)/$(SERVICE_DESCRIPTION_PATH): \ $(SHARE_SRC)/classes/sun/nio/cs/ext/$(SERVICE_DESCRIPTION_PATH) $(install-file) -$(CHARSETS_JAR): $(FILES_class) $(CLASSDESTDIR)/$(SERVICE_DESCRIPTION_PATH) +$(CHARSETS_JAR): $(FILES_class) $(CLASSDESTDIR)/$(SERVICE_DESCRIPTION_PATH) $(FILES_DAT) $(BOOT_JAR_CMD) cf $(CHARSETS_JAR) \ -C $(CLASSDESTDIR) sun \ -C $(CLASSDESTDIR) $(SERVICE_DESCRIPTION_PATH) \ diff --git a/jdk/make/sun/tracing/Makefile b/jdk/make/sun/tracing/Makefile new file mode 100644 index 00000000000..5c3711f0054 --- /dev/null +++ b/jdk/make/sun/tracing/Makefile @@ -0,0 +1,46 @@ +# +# Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# +# Makefile for building tracing package implementation classes +# + +BUILDDIR = ../.. +PACKAGE = sun.tracing +PRODUCT = sun +include $(BUILDDIR)/common/Defs.gmk + +SUBDIRS = dtrace +all build: + $(SUBDIRS-loop) +clean clobber:: + $(SUBDIRS-loop) + +AUTO_FILES_JAVA_DIRS = sun/tracing + +# +# Rules. +# +include $(BUILDDIR)/common/Classes.gmk diff --git a/jdk/make/sun/tracing/dtrace/Makefile b/jdk/make/sun/tracing/dtrace/Makefile new file mode 100644 index 00000000000..cf0dc9a978f --- /dev/null +++ b/jdk/make/sun/tracing/dtrace/Makefile @@ -0,0 +1,79 @@ +# +# Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# +# Makefile for building dtrace extension +# +BUILDDIR = ../../.. +PACKAGE = sun.tracing.dtrace +LIBRARY = jsdt +PRODUCT = sun +include $(BUILDDIR)/common/Defs.gmk + +# +# Use mapfile +# +FILES_m = mapfile-vers +include $(BUILDDIR)/common/Mapfile-vers.gmk + +NATIVE_DTRACE_DIR=native/sun/tracing/dtrace + +SRCDIR=$(SHARE_SRC)/$(NATIVE_DTRACE_DIR) +PSRCDIR=$(PLATFORM_SRC)/$(NATIVE_DTRACE_DIR) + +FILES_c = JVM.c jvm_symbols_md.c + +FILES_java = \ + sun/tracing/dtrace/Activation.java \ + sun/tracing/dtrace/DTraceProvider.java \ + sun/tracing/dtrace/DTraceProbe.java \ + sun/tracing/dtrace/DTraceProviderFactory.java \ + sun/tracing/dtrace/JVM.java + +FILES_export = $(FILES_java) + +ifeq ($(PLATFORM), linux) +OTHER_LDLIBS += -ldl +endif + +# +# Use JNI for generating header files +# +JAVAHFLAGS += -jni + +# +# Don't need to link against -ljava +# +JAVALIB= + +# +# Rules. +# +include $(BUILDDIR)/common/Library.gmk + +# +# Add to ambient vpath so we pick up the library files +# +vpath %.c $(SRCDIR):$(PSRCDIR) diff --git a/jdk/make/sun/tracing/dtrace/mapfile-vers b/jdk/make/sun/tracing/dtrace/mapfile-vers new file mode 100644 index 00000000000..5ace1629f5f --- /dev/null +++ b/jdk/make/sun/tracing/dtrace/mapfile-vers @@ -0,0 +1,37 @@ +# +# Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# Define library interface. + +SUNWprivate_1.1 { + global: + Java_sun_tracing_dtrace_JVM_isSupported0; + Java_sun_tracing_dtrace_JVM_activate0; + Java_sun_tracing_dtrace_JVM_dispose0; + Java_sun_tracing_dtrace_JVM_isEnabled0; + Java_sun_tracing_dtrace_JVM_defineClass0; + local: + *; +}; diff --git a/jdk/make/tools/CharsetMapping/Makefile b/jdk/make/tools/CharsetMapping/Makefile new file mode 100644 index 00000000000..3ac068201cf --- /dev/null +++ b/jdk/make/tools/CharsetMapping/Makefile @@ -0,0 +1,43 @@ +# +# Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# +# Makefile for building the charsetmapping tool +# + +BUILDDIR = ../.. +PACKAGE = build.tools.charsetmapping +PRODUCT = tools +PROGRAM = charsetmapping +include $(BUILDDIR)/common/Defs.gmk + +BUILDTOOL_SOURCE_ROOT = $(BUILDDIR)/tools/src +BUILDTOOL_MAIN = $(PKGDIR)/GenerateMapping.java + +# +# Build tool jar rules. +# +include $(BUILDDIR)/common/BuildToolJar.gmk + diff --git a/jdk/make/tools/CharsetMapping/sjis0213.map b/jdk/make/tools/CharsetMapping/sjis0213.map new file mode 100644 index 00000000000..48b65d3bdc4 --- /dev/null +++ b/jdk/make/tools/CharsetMapping/sjis0213.map @@ -0,0 +1,11471 @@ +## Shift_JIS-2004 (JIS X 0213:2004 Appendix 1) vs Unicode mapping table +## +## Date: 13 May 2006 +## License: +## Copyright (C) 2001 earthian@tama.or.jp, All Rights Reserved. +## Copyright (C) 2001 I'O, All Rights Reserved. +## Copyright (C) 2006 Project X0213, All Rights Reserved. +## You can use, modify, distribute this table freely. +## Note: +## [1983] JIS codepoint defined by JIS X 0208-1983 +## [1990] JIS codepoint defined by JIS X 0208-1990 +## [2000] JIS codepoint defined by JIS X 0213:2000 +## [2004] JIS codepoint defined by JIS X 0213:2004 +## [Unicode3.1] UCS codepoint defined by Unicode 3.1 +## [Unicode3.2] UCS codepoint defined by Unicode 3.2 +## Fullwidth UCS fullwidth form (U+Fxxx) +## Windows Windows (CP932) mapping +## Some 0213 character can't represent by one UCS character. +## In this table, such characters are described as 'U+xxxx+xxxx'. +## +## +## (1)Added JIS0213 entries +## (2)Updated 2 entries +## 0x81b0 -> u+ff5e +## 0x815f -> u+ff3c +## +## JIS Unicode Name Note +## +## Note: Block f09f--f0fc has been moved to the correct(sorted) position +## +## GDB=1 GC=2 GCC=3> +## +# +# sjis0201 +# +0x20 U+0020 # SPACE +0x21 U+0021 # EXCLAMATION MARK +0x22 U+0022 # QUOTATION MARK +0x23 U+0023 # NUMBER SIGN +0x24 U+0024 # DOLLAR SIGN +0x25 U+0025 # PERCENT SIGN +0x26 U+0026 # AMPERSAND +0x27 U+0027 # APOSTROPHE +0x28 U+0028 # LEFT PARENTHESIS +0x29 U+0029 # RIGHT PARENTHESIS +0x2A U+002A # ASTERISK +0x2B U+002B # PLUS SIGN +0x2C U+002C # COMMA +0x2D U+002D # HYPHEN-MINUS +0x2E U+002E # FULL STOP +0x2F U+002F # SOLIDUS +0x30 U+0030 # DIGIT ZERO +0x31 U+0031 # DIGIT ONE +0x32 U+0032 # DIGIT TWO +0x33 U+0033 # DIGIT THREE +0x34 U+0034 # DIGIT FOUR +0x35 U+0035 # DIGIT FIVE +0x36 U+0036 # DIGIT SIX +0x37 U+0037 # DIGIT SEVEN +0x38 U+0038 # DIGIT EIGHT +0x39 U+0039 # DIGIT NINE +0x3A U+003A # COLON +0x3B U+003B # SEMICOLON +0x3C U+003C # LESS-THAN SIGN +0x3D U+003D # EQUALS SIGN +0x3E U+003E # GREATER-THAN SIGN +0x3F U+003F # QUESTION MARK +0x40 U+0040 # COMMERCIAL AT +0x41 U+0041 # LATIN CAPITAL LETTER A +0x42 U+0042 # LATIN CAPITAL LETTER B +0x43 U+0043 # LATIN CAPITAL LETTER C +0x44 U+0044 # LATIN CAPITAL LETTER D +0x45 U+0045 # LATIN CAPITAL LETTER E +0x46 U+0046 # LATIN CAPITAL LETTER F +0x47 U+0047 # LATIN CAPITAL LETTER G +0x48 U+0048 # LATIN CAPITAL LETTER H +0x49 U+0049 # LATIN CAPITAL LETTER I +0x4A U+004A # LATIN CAPITAL LETTER J +0x4B U+004B # LATIN CAPITAL LETTER K +0x4C U+004C # LATIN CAPITAL LETTER L +0x4D U+004D # LATIN CAPITAL LETTER M +0x4E U+004E # LATIN CAPITAL LETTER N +0x4F U+004F # LATIN CAPITAL LETTER O +0x50 U+0050 # LATIN CAPITAL LETTER P +0x51 U+0051 # LATIN CAPITAL LETTER Q +0x52 U+0052 # LATIN CAPITAL LETTER R +0x53 U+0053 # LATIN CAPITAL LETTER S +0x54 U+0054 # LATIN CAPITAL LETTER T +0x55 U+0055 # LATIN CAPITAL LETTER U +0x56 U+0056 # LATIN CAPITAL LETTER V +0x57 U+0057 # LATIN CAPITAL LETTER W +0x58 U+0058 # LATIN CAPITAL LETTER X +0x59 U+0059 # LATIN CAPITAL LETTER Y +0x5A U+005A # LATIN CAPITAL LETTER Z +0x5B U+005B # LEFT SQUARE BRACKET +0x5C U+005C # YEN SIGN +0x5D U+005D # RIGHT SQUARE BRACKET +0x5E U+005E # CIRCUMFLEX ACCENT +0x5F U+005F # LOW LINE +0x60 U+0060 # GRAVE ACCENT +0x61 U+0061 # LATIN SMALL LETTER A +0x62 U+0062 # LATIN SMALL LETTER B +0x63 U+0063 # LATIN SMALL LETTER C +0x64 U+0064 # LATIN SMALL LETTER D +0x65 U+0065 # LATIN SMALL LETTER E +0x66 U+0066 # LATIN SMALL LETTER F +0x67 U+0067 # LATIN SMALL LETTER G +0x68 U+0068 # LATIN SMALL LETTER H +0x69 U+0069 # LATIN SMALL LETTER I +0x6A U+006A # LATIN SMALL LETTER J +0x6B U+006B # LATIN SMALL LETTER K +0x6C U+006C # LATIN SMALL LETTER L +0x6D U+006D # LATIN SMALL LETTER M +0x6E U+006E # LATIN SMALL LETTER N +0x6F U+006F # LATIN SMALL LETTER O +0x70 U+0070 # LATIN SMALL LETTER P +0x71 U+0071 # LATIN SMALL LETTER Q +0x72 U+0072 # LATIN SMALL LETTER R +0x73 U+0073 # LATIN SMALL LETTER S +0x74 U+0074 # LATIN SMALL LETTER T +0x75 U+0075 # LATIN SMALL LETTER U +0x76 U+0076 # LATIN SMALL LETTER V +0x77 U+0077 # LATIN SMALL LETTER W +0x78 U+0078 # LATIN SMALL LETTER X +0x79 U+0079 # LATIN SMALL LETTER Y +0x7A U+007A # LATIN SMALL LETTER Z +0x7B U+007B # LEFT CURLY BRACKET +0x7C U+007C # VERTICAL LINE +0x7D U+007D # RIGHT CURLY BRACKET +0x7E U+007E # OVERLINE +0x7F U+007F # DELETE +0xA1 U+FF61 # HALFWIDTH IDEOGRAPHIC FULL STOP +0xA2 U+FF62 # HALFWIDTH LEFT CORNER BRACKET +0xA3 U+FF63 # HALFWIDTH RIGHT CORNER BRACKET +0xA4 U+FF64 # HALFWIDTH IDEOGRAPHIC COMMA +0xA5 U+FF65 # HALFWIDTH KATAKANA MIDDLE DOT +0xA6 U+FF66 # HALFWIDTH KATAKANA LETTER WO +0xA7 U+FF67 # HALFWIDTH KATAKANA LETTER SMALL A +0xA8 U+FF68 # HALFWIDTH KATAKANA LETTER SMALL I +0xA9 U+FF69 # HALFWIDTH KATAKANA LETTER SMALL U +0xAA U+FF6A # HALFWIDTH KATAKANA LETTER SMALL E +0xAB U+FF6B # HALFWIDTH KATAKANA LETTER SMALL O +0xAC U+FF6C # HALFWIDTH KATAKANA LETTER SMALL YA +0xAD U+FF6D # HALFWIDTH KATAKANA LETTER SMALL YU +0xAE U+FF6E # HALFWIDTH KATAKANA LETTER SMALL YO +0xAF U+FF6F # HALFWIDTH KATAKANA LETTER SMALL TU +0xB0 U+FF70 # HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK +0xB1 U+FF71 # HALFWIDTH KATAKANA LETTER A +0xB2 U+FF72 # HALFWIDTH KATAKANA LETTER I +0xB3 U+FF73 # HALFWIDTH KATAKANA LETTER U +0xB4 U+FF74 # HALFWIDTH KATAKANA LETTER E +0xB5 U+FF75 # HALFWIDTH KATAKANA LETTER O +0xB6 U+FF76 # HALFWIDTH KATAKANA LETTER KA +0xB7 U+FF77 # HALFWIDTH KATAKANA LETTER KI +0xB8 U+FF78 # HALFWIDTH KATAKANA LETTER KU +0xB9 U+FF79 # HALFWIDTH KATAKANA LETTER KE +0xBA U+FF7A # HALFWIDTH KATAKANA LETTER KO +0xBB U+FF7B # HALFWIDTH KATAKANA LETTER SA +0xBC U+FF7C # HALFWIDTH KATAKANA LETTER SI +0xBD U+FF7D # HALFWIDTH KATAKANA LETTER SU +0xBE U+FF7E # HALFWIDTH KATAKANA LETTER SE +0xBF U+FF7F # HALFWIDTH KATAKANA LETTER SO +0xC0 U+FF80 # HALFWIDTH KATAKANA LETTER TA +0xC1 U+FF81 # HALFWIDTH KATAKANA LETTER TI +0xC2 U+FF82 # HALFWIDTH KATAKANA LETTER TU +0xC3 U+FF83 # HALFWIDTH KATAKANA LETTER TE +0xC4 U+FF84 # HALFWIDTH KATAKANA LETTER TO +0xC5 U+FF85 # HALFWIDTH KATAKANA LETTER NA +0xC6 U+FF86 # HALFWIDTH KATAKANA LETTER NI +0xC7 U+FF87 # HALFWIDTH KATAKANA LETTER NU +0xC8 U+FF88 # HALFWIDTH KATAKANA LETTER NE +0xC9 U+FF89 # HALFWIDTH KATAKANA LETTER NO +0xCA U+FF8A # HALFWIDTH KATAKANA LETTER HA +0xCB U+FF8B # HALFWIDTH KATAKANA LETTER HI +0xCC U+FF8C # HALFWIDTH KATAKANA LETTER HU +0xCD U+FF8D # HALFWIDTH KATAKANA LETTER HE +0xCE U+FF8E # HALFWIDTH KATAKANA LETTER HO +0xCF U+FF8F # HALFWIDTH KATAKANA LETTER MA +0xD0 U+FF90 # HALFWIDTH KATAKANA LETTER MI +0xD1 U+FF91 # HALFWIDTH KATAKANA LETTER MU +0xD2 U+FF92 # HALFWIDTH KATAKANA LETTER ME +0xD3 U+FF93 # HALFWIDTH KATAKANA LETTER MO +0xD4 U+FF94 # HALFWIDTH KATAKANA LETTER YA +0xD5 U+FF95 # HALFWIDTH KATAKANA LETTER YU +0xD6 U+FF96 # HALFWIDTH KATAKANA LETTER YO +0xD7 U+FF97 # HALFWIDTH KATAKANA LETTER RA +0xD8 U+FF98 # HALFWIDTH KATAKANA LETTER RI +0xD9 U+FF99 # HALFWIDTH KATAKANA LETTER RU +0xDA U+FF9A # HALFWIDTH KATAKANA LETTER RE +0xDB U+FF9B # HALFWIDTH KATAKANA LETTER RO +0xDC U+FF9C # HALFWIDTH KATAKANA LETTER WA +0xDD U+FF9D # HALFWIDTH KATAKANA LETTER N +0xDE U+FF9E # HALFWIDTH KATAKANA VOICED SOUND MARK +0xDF U+FF9F # HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK +# +# sjis0213 +# +0x8140 U+3000 # IDEOGRAPHIC SPACE +0x8141 U+3001 # IDEOGRAPHIC COMMA +0x8142 U+3002 # IDEOGRAPHIC FULL STOP +0x8143 U+FF0C # FULLWIDTH COMMA +0x8144 U+FF0E # FULLWIDTH FULL STOP +0x8145 U+30FB # KATAKANA MIDDLE DOT +0x8146 U+FF1A # FULLWIDTH COLON +0x8147 U+FF1B # FULLWIDTH SEMICOLON +0x8148 U+FF1F # FULLWIDTH QUESTION MARK +0x8149 U+FF01 # FULLWIDTH EXCLAMATION MARK +0x814A U+309B # KATAKANA-HIRAGANA VOICED SOUND MARK +0x814B U+309C # KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK +0x814C U+00B4 # ACUTE ACCENT +0x814D U+FF40 # FULLWIDTH GRAVE ACCENT +0x814E U+00A8 # DIAERESIS +0x814F U+FF3E # FULLWIDTH CIRCUMFLEX ACCENT +0x8150 U+FFE3 # FULLWIDTH MACRON +0x8151 U+FF3F # FULLWIDTH LOW LINE +0x8152 U+30FD # KATAKANA ITERATION MARK +0x8153 U+30FE # KATAKANA VOICED ITERATION MARK +0x8154 U+309D # HIRAGANA ITERATION MARK +0x8155 U+309E # HIRAGANA VOICED ITERATION MARK +0x8156 U+3003 # DITTO MARK +0x8157 U+4EDD # +0x8158 U+3005 # IDEOGRAPHIC ITERATION MARK +0x8159 U+3006 # IDEOGRAPHIC CLOSING MARK +0x815A U+3007 # IDEOGRAPHIC NUMBER ZERO +0x815B U+30FC # KATAKANA-HIRAGANA PROLONGED SOUND MARK +0x815C U+2014 # EM DASH Windows: U+2015 +0x815D U+2010 # HYPHEN +0x815E U+FF0F # FULLWIDTH SOLIDUS +#0x815F U+005C # REVERSE SOLIDUS Fullwidth: U+FF3C +0x815F U+FF3C # REVERSE SOLIDUS Fullwidth: U+FF3C +0x8160 U+301C # WAVE DASH Windows: U+FF5E +0x8161 U+2016 # DOUBLE VERTICAL LINE Windows: U+2225 +0x8162 U+FF5C # FULLWIDTH VERTICAL LINE +0x8163 U+2026 # HORIZONTAL ELLIPSIS +0x8164 U+2025 # TWO DOT LEADER +0x8165 U+2018 # LEFT SINGLE QUOTATION MARK +0x8166 U+2019 # RIGHT SINGLE QUOTATION MARK +0x8167 U+201C # LEFT DOUBLE QUOTATION MARK +0x8168 U+201D # RIGHT DOUBLE QUOTATION MARK +0x8169 U+FF08 # FULLWIDTH LEFT PARENTHESIS +0x816A U+FF09 # FULLWIDTH RIGHT PARENTHESIS +0x816B U+3014 # LEFT TORTOISE SHELL BRACKET +0x816C U+3015 # RIGHT TORTOISE SHELL BRACKET +0x816D U+FF3B # FULLWIDTH LEFT SQUARE BRACKET +0x816E U+FF3D # FULLWIDTH RIGHT SQUARE BRACKET +0x816F U+FF5B # FULLWIDTH LEFT CURLY BRACKET +0x8170 U+FF5D # FULLWIDTH RIGHT CURLY BRACKET +0x8171 U+3008 # LEFT ANGLE BRACKET +0x8172 U+3009 # RIGHT ANGLE BRACKET +0x8173 U+300A # LEFT DOUBLE ANGLE BRACKET +0x8174 U+300B # RIGHT DOUBLE ANGLE BRACKET +0x8175 U+300C # LEFT CORNER BRACKET +0x8176 U+300D # RIGHT CORNER BRACKET +0x8177 U+300E # LEFT WHITE CORNER BRACKET +0x8178 U+300F # RIGHT WHITE CORNER BRACKET +0x8179 U+3010 # LEFT BLACK LENTICULAR BRACKET +0x817A U+3011 # RIGHT BLACK LENTICULAR BRACKET +0x817B U+FF0B # FULLWIDTH PLUS SIGN +0x817C U+2212 # MINUS SIGN Windows: U+FF0D +0x817D U+00B1 # PLUS-MINUS SIGN +0x817E U+00D7 # MULTIPLICATION SIGN +0x8180 U+00F7 # DIVISION SIGN +0x8181 U+FF1D # FULLWIDTH EQUALS SIGN +0x8182 U+2260 # NOT EQUAL TO +0x8183 U+FF1C # FULLWIDTH LESS-THAN SIGN +0x8184 U+FF1E # FULLWIDTH GREATER-THAN SIGN +0x8185 U+2266 # LESS-THAN OVER EQUAL TO +0x8186 U+2267 # GREATER-THAN OVER EQUAL TO +0x8187 U+221E # INFINITY +0x8188 U+2234 # THEREFORE +0x8189 U+2642 # MALE SIGN +0x818A U+2640 # FEMALE SIGN +0x818B U+00B0 # DEGREE SIGN +0x818C U+2032 # PRIME +0x818D U+2033 # DOUBLE PRIME +0x818E U+2103 # DEGREE CELSIUS +0x818F U+FFE5 # FULLWIDTH YEN SIGN +0x8190 U+FF04 # FULLWIDTH DOLLAR SIGN +0x8191 U+00A2 # CENT SIGN Windows: U+FFE0 +0x8192 U+00A3 # POUND SIGN Windows: U+FFE1 +0x8193 U+FF05 # FULLWIDTH PERCENT SIGN +0x8194 U+FF03 # FULLWIDTH NUMBER SIGN +0x8195 U+FF06 # FULLWIDTH AMPERSAND +0x8196 U+FF0A # FULLWIDTH ASTERISK +0x8197 U+FF20 # FULLWIDTH COMMERCIAL AT +0x8198 U+00A7 # SECTION SIGN +0x8199 U+2606 # WHITE STAR +0x819A U+2605 # BLACK STAR +0x819B U+25CB # WHITE CIRCLE +0x819C U+25CF # BLACK CIRCLE +0x819D U+25CE # BULLSEYE +0x819E U+25C7 # WHITE DIAMOND +0x819F U+25C6 # BLACK DIAMOND +0x81A0 U+25A1 # WHITE SQUARE +0x81A1 U+25A0 # BLACK SQUARE +0x81A2 U+25B3 # WHITE UP-POINTING TRIANGLE +0x81A3 U+25B2 # BLACK UP-POINTING TRIANGLE +0x81A4 U+25BD # WHITE DOWN-POINTING TRIANGLE +0x81A5 U+25BC # BLACK DOWN-POINTING TRIANGLE +0x81A6 U+203B # REFERENCE MARK +0x81A7 U+3012 # POSTAL MARK +0x81A8 U+2192 # RIGHTWARDS ARROW +0x81A9 U+2190 # LEFTWARDS ARROW +0x81AA U+2191 # UPWARDS ARROW +0x81AB U+2193 # DOWNWARDS ARROW +0x81AC U+3013 # GETA MARK +0x81AD U+FF07 # FULLWIDTH APOSTROPHE +0x81AE U+FF02 # FULLWIDTH QUOTATION MARK [2000] +0x81AF U+FF0D # FULLWIDTH HYPHEN-MINUS [2000] +#0x81B0 U+007E # TILDE [2000] Fullwidth: U+FF5E +0x81B0 U+FF5E # TILDE [2000] Fullwidth: U+FF5E +0x81B1 U+3033 # VERTICAL KANA REPEAT MARK UPPER HALF [2000] +0x81B2 U+3034 # VERTICAL KANA REPEAT WITH VOICED SOUND MARK UPPER HALF [2000] +0x81B3 U+3035 # VERTICAL KANA REPEAT MARK LOWER HALF [2000] +0x81B4 U+303B # VERTICAL IDEOGRAPHIC ITERATION MARK [2000] [Unicode3.2] +0x81B5 U+303C # MASU MARK [2000] [Unicode3.2] +0x81B6 U+30FF # KATAKANA DIGRAPH KOTO [2000] [Unicode3.2] +0x81B7 U+309F # HIRAGANA DIGRAPH YORI [2000] [Unicode3.2] +0x81B8 U+2208 # ELEMENT OF [1983] +0x81B9 U+220B # CONTAINS AS MEMBER [1983] +0x81BA U+2286 # SUBSET OF OR EQUAL TO [1983] +0x81BB U+2287 # SUPERSET OF OR EQUAL TO [1983] +0x81BC U+2282 # SUBSET OF [1983] +0x81BD U+2283 # SUPERSET OF [1983] +0x81BE U+222A # UNION [1983] +0x81BF U+2229 # INTERSECTION [1983] +0x81C0 U+2284 # NOT A SUBSET OF [2000] +0x81C1 U+2285 # NOT A SUPERSET OF [2000] +0x81C2 U+228A # SUBSET OF WITH NOT EQUAL TO [2000] +0x81C3 U+228B # SUPERSET OF WITH NOT EQUAL TO [2000] +0x81C4 U+2209 # NOT AN ELEMENT OF [2000] +0x81C5 U+2205 # EMPTY SET [2000] +0x81C6 U+2305 # PROJECTIVE [2000] +0x81C7 U+2306 # PERSPECTIVE [2000] +0x81C8 U+2227 # LOGICAL AND [1983] +0x81C9 U+2228 # LOGICAL OR [1983] +0x81CA U+00AC # NOT SIGN [1983] Windows: U+FFE2 +0x81CB U+21D2 # RIGHTWARDS DOUBLE ARROW [1983] +0x81CC U+21D4 # LEFT RIGHT DOUBLE ARROW [1983] +0x81CD U+2200 # FOR ALL [1983] +0x81CE U+2203 # THERE EXISTS [1983] +0x81CF U+2295 # CIRCLED PLUS [2000] +0x81D0 U+2296 # CIRCLED MINUS [2000] +0x81D1 U+2297 # CIRCLED TIMES [2000] +0x81D2 U+2225 # PARALLEL TO [2000] +0x81D3 U+2226 # NOT PARALLEL TO [2000] +0x81D4 U+FF5F # FULLWIDTH LEFT WHITE PARENTHESIS [2000] [Unicode3.2] +0x81D5 U+FF60 # FULLWIDTH RIGHT WHITE PARENTHESIS [2000] [Unicode3.2] +0x81D6 U+3018 # LEFT WHITE TORTOISE SHELL BRACKET [2000] +0x81D7 U+3019 # RIGHT WHITE TORTOISE SHELL BRACKET [2000] +0x81D8 U+3016 # LEFT WHITE LENTICULAR BRACKET [2000] +0x81D9 U+3017 # RIGHT WHITE LENTICULAR BRACKET [2000] +0x81DA U+2220 # ANGLE [1983] +0x81DB U+22A5 # UP TACK [1983] +0x81DC U+2312 # ARC [1983] +0x81DD U+2202 # PARTIAL DIFFERENTIAL [1983] +0x81DE U+2207 # NABLA [1983] +0x81DF U+2261 # IDENTICAL TO [1983] +0x81E0 U+2252 # APPROXIMATELY EQUAL TO OR THE IMAGE OF [1983] +0x81E1 U+226A # MUCH LESS-THAN [1983] +0x81E2 U+226B # MUCH GREATER-THAN [1983] +0x81E3 U+221A # SQUARE ROOT [1983] +0x81E4 U+223D # REVERSED TILDE [1983] +0x81E5 U+221D # PROPORTIONAL TO [1983] +0x81E6 U+2235 # BECAUSE [1983] +0x81E7 U+222B # INTEGRAL [1983] +0x81E8 U+222C # DOUBLE INTEGRAL [1983] +0x81E9 U+2262 # NOT IDENTICAL TO [2000] +0x81EA U+2243 # ASYMPTOTICALLY EQUAL TO [2000] +0x81EB U+2245 # APPROXIMATELY EQUAL TO [2000] +0x81EC U+2248 # ALMOST EQUAL TO [2000] +0x81ED U+2276 # LESS-THAN OR GREATER-THAN [2000] +0x81EE U+2277 # GREATER-THAN OR LESS-THAN [2000] +0x81EF U+2194 # LEFT RIGHT ARROW [2000] +0x81F0 U+212B # ANGSTROM SIGN [1983] +0x81F1 U+2030 # PER MILLE SIGN [1983] +0x81F2 U+266F # MUSIC SHARP SIGN [1983] +0x81F3 U+266D # MUSIC FLAT SIGN [1983] +0x81F4 U+266A # EIGHTH NOTE [1983] +0x81F5 U+2020 # DAGGER [1983] +0x81F6 U+2021 # DOUBLE DAGGER [1983] +0x81F7 U+00B6 # PILCROW SIGN [1983] +0x81F8 U+266E # MUSIC NATURAL SIGN [2000] +0x81F9 U+266B # BEAMED EIGHTH NOTES [2000] +0x81FA U+266C # BEAMED SIXTEENTH NOTES [2000] +0x81FB U+2669 # QUARTER NOTE [2000] +0x81FC U+25EF # LARGE CIRCLE [1983] +0x8240 U+25B7 # WHITE RIGHT-POINTING TRIANGLE [2000] +0x8241 U+25B6 # BLACK RIGHT-POINTING TRIANGLE [2000] +0x8242 U+25C1 # WHITE LEFT-POINTING TRIANGLE [2000] +0x8243 U+25C0 # BLACK LEFT-POINTING TRIANGLE [2000] +0x8244 U+2197 # NORTH EAST ARROW [2000] +0x8245 U+2198 # SOUTH EAST ARROW [2000] +0x8246 U+2196 # NORTH WEST ARROW [2000] +0x8247 U+2199 # SOUTH WEST ARROW [2000] +0x8248 U+21C4 # RIGHTWARDS ARROW OVER LEFTWARDS ARROW [2000] +0x8249 U+21E8 # RIGHTWARDS WHITE ARROW [2000] +0x824A U+21E6 # LEFTWARDS WHITE ARROW [2000] +0x824B U+21E7 # UPWARDS WHITE ARROW [2000] +0x824C U+21E9 # DOWNWARDS WHITE ARROW [2000] +0x824D U+2934 # ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS [2000] [Unicode3.2] +0x824E U+2935 # ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS [2000] [Unicode3.2] +0x824F U+FF10 # FULLWIDTH DIGIT ZERO +0x8250 U+FF11 # FULLWIDTH DIGIT ONE +0x8251 U+FF12 # FULLWIDTH DIGIT TWO +0x8252 U+FF13 # FULLWIDTH DIGIT THREE +0x8253 U+FF14 # FULLWIDTH DIGIT FOUR +0x8254 U+FF15 # FULLWIDTH DIGIT FIVE +0x8255 U+FF16 # FULLWIDTH DIGIT SIX +0x8256 U+FF17 # FULLWIDTH DIGIT SEVEN +0x8257 U+FF18 # FULLWIDTH DIGIT EIGHT +0x8258 U+FF19 # FULLWIDTH DIGIT NINE +0x8259 U+29BF # CIRCLED BULLET [2000] [Unicode3.2] +0x825A U+25C9 # FISHEYE [2000] +0x825B U+303D # PART ALTERNATION MARK [2000] [Unicode3.2] +0x825C U+FE46 # WHITE SESAME DOT [2000] [Unicode3.2] +0x825D U+FE45 # SESAME DOT [2000] [Unicode3.2] +0x825E U+25E6 # WHITE BULLET [2000] +0x825F U+2022 # BULLET [2000] +0x8260 U+FF21 # FULLWIDTH LATIN CAPITAL LETTER A +0x8261 U+FF22 # FULLWIDTH LATIN CAPITAL LETTER B +0x8262 U+FF23 # FULLWIDTH LATIN CAPITAL LETTER C +0x8263 U+FF24 # FULLWIDTH LATIN CAPITAL LETTER D +0x8264 U+FF25 # FULLWIDTH LATIN CAPITAL LETTER E +0x8265 U+FF26 # FULLWIDTH LATIN CAPITAL LETTER F +0x8266 U+FF27 # FULLWIDTH LATIN CAPITAL LETTER G +0x8267 U+FF28 # FULLWIDTH LATIN CAPITAL LETTER H +0x8268 U+FF29 # FULLWIDTH LATIN CAPITAL LETTER I +0x8269 U+FF2A # FULLWIDTH LATIN CAPITAL LETTER J +0x826A U+FF2B # FULLWIDTH LATIN CAPITAL LETTER K +0x826B U+FF2C # FULLWIDTH LATIN CAPITAL LETTER L +0x826C U+FF2D # FULLWIDTH LATIN CAPITAL LETTER M +0x826D U+FF2E # FULLWIDTH LATIN CAPITAL LETTER N +0x826E U+FF2F # FULLWIDTH LATIN CAPITAL LETTER O +0x826F U+FF30 # FULLWIDTH LATIN CAPITAL LETTER P +0x8270 U+FF31 # FULLWIDTH LATIN CAPITAL LETTER Q +0x8271 U+FF32 # FULLWIDTH LATIN CAPITAL LETTER R +0x8272 U+FF33 # FULLWIDTH LATIN CAPITAL LETTER S +0x8273 U+FF34 # FULLWIDTH LATIN CAPITAL LETTER T +0x8274 U+FF35 # FULLWIDTH LATIN CAPITAL LETTER U +0x8275 U+FF36 # FULLWIDTH LATIN CAPITAL LETTER V +0x8276 U+FF37 # FULLWIDTH LATIN CAPITAL LETTER W +0x8277 U+FF38 # FULLWIDTH LATIN CAPITAL LETTER X +0x8278 U+FF39 # FULLWIDTH LATIN CAPITAL LETTER Y +0x8279 U+FF3A # FULLWIDTH LATIN CAPITAL LETTER Z +0x827A U+2213 # MINUS-OR-PLUS SIGN [2000] +0x827B U+2135 # ALEF SYMBOL [2000] +0x827C U+210F # PLANCK CONSTANT OVER TWO PI [2000] +0x827D U+33CB # SQUARE HP [2000] +0x827E U+2113 # SCRIPT SMALL L [2000] +0x8280 U+2127 # INVERTED OHM SIGN [2000] +0x8281 U+FF41 # FULLWIDTH LATIN SMALL LETTER A +0x8282 U+FF42 # FULLWIDTH LATIN SMALL LETTER B +0x8283 U+FF43 # FULLWIDTH LATIN SMALL LETTER C +0x8284 U+FF44 # FULLWIDTH LATIN SMALL LETTER D +0x8285 U+FF45 # FULLWIDTH LATIN SMALL LETTER E +0x8286 U+FF46 # FULLWIDTH LATIN SMALL LETTER F +0x8287 U+FF47 # FULLWIDTH LATIN SMALL LETTER G +0x8288 U+FF48 # FULLWIDTH LATIN SMALL LETTER H +0x8289 U+FF49 # FULLWIDTH LATIN SMALL LETTER I +0x828A U+FF4A # FULLWIDTH LATIN SMALL LETTER J +0x828B U+FF4B # FULLWIDTH LATIN SMALL LETTER K +0x828C U+FF4C # FULLWIDTH LATIN SMALL LETTER L +0x828D U+FF4D # FULLWIDTH LATIN SMALL LETTER M +0x828E U+FF4E # FULLWIDTH LATIN SMALL LETTER N +0x828F U+FF4F # FULLWIDTH LATIN SMALL LETTER O +0x8290 U+FF50 # FULLWIDTH LATIN SMALL LETTER P +0x8291 U+FF51 # FULLWIDTH LATIN SMALL LETTER Q +0x8292 U+FF52 # FULLWIDTH LATIN SMALL LETTER R +0x8293 U+FF53 # FULLWIDTH LATIN SMALL LETTER S +0x8294 U+FF54 # FULLWIDTH LATIN SMALL LETTER T +0x8295 U+FF55 # FULLWIDTH LATIN SMALL LETTER U +0x8296 U+FF56 # FULLWIDTH LATIN SMALL LETTER V +0x8297 U+FF57 # FULLWIDTH LATIN SMALL LETTER W +0x8298 U+FF58 # FULLWIDTH LATIN SMALL LETTER X +0x8299 U+FF59 # FULLWIDTH LATIN SMALL LETTER Y +0x829A U+FF5A # FULLWIDTH LATIN SMALL LETTER Z +0x829B U+30A0 # KATAKANA-HIRAGANA DOUBLE HYPHEN [2000] [Unicode3.2] +0x829C U+2013 # EN DASH [2000] +0x829D U+29FA # DOUBLE PLUS [2000] [Unicode3.2] +0x829E U+29FB # TRIPLE PLUS [2000] [Unicode3.2] +0x829F U+3041 # HIRAGANA LETTER SMALL A +0x82A0 U+3042 # HIRAGANA LETTER A +0x82A1 U+3043 # HIRAGANA LETTER SMALL I +0x82A2 U+3044 # HIRAGANA LETTER I +0x82A3 U+3045 # HIRAGANA LETTER SMALL U +0x82A4 U+3046 # HIRAGANA LETTER U +0x82A5 U+3047 # HIRAGANA LETTER SMALL E +0x82A6 U+3048 # HIRAGANA LETTER E +0x82A7 U+3049 # HIRAGANA LETTER SMALL O +0x82A8 U+304A # HIRAGANA LETTER O +0x82A9 U+304B # HIRAGANA LETTER KA +0x82AA U+304C # HIRAGANA LETTER GA +0x82AB U+304D # HIRAGANA LETTER KI +0x82AC U+304E # HIRAGANA LETTER GI +0x82AD U+304F # HIRAGANA LETTER KU +0x82AE U+3050 # HIRAGANA LETTER GU +0x82AF U+3051 # HIRAGANA LETTER KE +0x82B0 U+3052 # HIRAGANA LETTER GE +0x82B1 U+3053 # HIRAGANA LETTER KO +0x82B2 U+3054 # HIRAGANA LETTER GO +0x82B3 U+3055 # HIRAGANA LETTER SA +0x82B4 U+3056 # HIRAGANA LETTER ZA +0x82B5 U+3057 # HIRAGANA LETTER SI +0x82B6 U+3058 # HIRAGANA LETTER ZI +0x82B7 U+3059 # HIRAGANA LETTER SU +0x82B8 U+305A # HIRAGANA LETTER ZU +0x82B9 U+305B # HIRAGANA LETTER SE +0x82BA U+305C # HIRAGANA LETTER ZE +0x82BB U+305D # HIRAGANA LETTER SO +0x82BC U+305E # HIRAGANA LETTER ZO +0x82BD U+305F # HIRAGANA LETTER TA +0x82BE U+3060 # HIRAGANA LETTER DA +0x82BF U+3061 # HIRAGANA LETTER TI +0x82C0 U+3062 # HIRAGANA LETTER DI +0x82C1 U+3063 # HIRAGANA LETTER SMALL TU +0x82C2 U+3064 # HIRAGANA LETTER TU +0x82C3 U+3065 # HIRAGANA LETTER DU +0x82C4 U+3066 # HIRAGANA LETTER TE +0x82C5 U+3067 # HIRAGANA LETTER DE +0x82C6 U+3068 # HIRAGANA LETTER TO +0x82C7 U+3069 # HIRAGANA LETTER DO +0x82C8 U+306A # HIRAGANA LETTER NA +0x82C9 U+306B # HIRAGANA LETTER NI +0x82CA U+306C # HIRAGANA LETTER NU +0x82CB U+306D # HIRAGANA LETTER NE +0x82CC U+306E # HIRAGANA LETTER NO +0x82CD U+306F # HIRAGANA LETTER HA +0x82CE U+3070 # HIRAGANA LETTER BA +0x82CF U+3071 # HIRAGANA LETTER PA +0x82D0 U+3072 # HIRAGANA LETTER HI +0x82D1 U+3073 # HIRAGANA LETTER BI +0x82D2 U+3074 # HIRAGANA LETTER PI +0x82D3 U+3075 # HIRAGANA LETTER HU +0x82D4 U+3076 # HIRAGANA LETTER BU +0x82D5 U+3077 # HIRAGANA LETTER PU +0x82D6 U+3078 # HIRAGANA LETTER HE +0x82D7 U+3079 # HIRAGANA LETTER BE +0x82D8 U+307A # HIRAGANA LETTER PE +0x82D9 U+307B # HIRAGANA LETTER HO +0x82DA U+307C # HIRAGANA LETTER BO +0x82DB U+307D # HIRAGANA LETTER PO +0x82DC U+307E # HIRAGANA LETTER MA +0x82DD U+307F # HIRAGANA LETTER MI +0x82DE U+3080 # HIRAGANA LETTER MU +0x82DF U+3081 # HIRAGANA LETTER ME +0x82E0 U+3082 # HIRAGANA LETTER MO +0x82E1 U+3083 # HIRAGANA LETTER SMALL YA +0x82E2 U+3084 # HIRAGANA LETTER YA +0x82E3 U+3085 # HIRAGANA LETTER SMALL YU +0x82E4 U+3086 # HIRAGANA LETTER YU +0x82E5 U+3087 # HIRAGANA LETTER SMALL YO +0x82E6 U+3088 # HIRAGANA LETTER YO +0x82E7 U+3089 # HIRAGANA LETTER RA +0x82E8 U+308A # HIRAGANA LETTER RI +0x82E9 U+308B # HIRAGANA LETTER RU +0x82EA U+308C # HIRAGANA LETTER RE +0x82EB U+308D # HIRAGANA LETTER RO +0x82EC U+308E # HIRAGANA LETTER SMALL WA +0x82ED U+308F # HIRAGANA LETTER WA +0x82EE U+3090 # HIRAGANA LETTER WI +0x82EF U+3091 # HIRAGANA LETTER WE +0x82F0 U+3092 # HIRAGANA LETTER WO +0x82F1 U+3093 # HIRAGANA LETTER N +0x82F2 U+3094 # HIRAGANA LETTER VU [2000] +0x82F3 U+3095 # HIRAGANA LETTER SMALL KA [2000] [Unicode3.2] +0x82F4 U+3096 # HIRAGANA LETTER SMALL KE [2000] [Unicode3.2] +0x82F5 U+304B+309A # [2000] +0x82F6 U+304D+309A # [2000] +0x82F7 U+304F+309A # [2000] +0x82F8 U+3051+309A # [2000] +0x82F9 U+3053+309A # [2000] +0x82FA # +0x82FB # +0x82FC # +0x8340 U+30A1 # KATAKANA LETTER SMALL A +0x8341 U+30A2 # KATAKANA LETTER A +0x8342 U+30A3 # KATAKANA LETTER SMALL I +0x8343 U+30A4 # KATAKANA LETTER I +0x8344 U+30A5 # KATAKANA LETTER SMALL U +0x8345 U+30A6 # KATAKANA LETTER U +0x8346 U+30A7 # KATAKANA LETTER SMALL E +0x8347 U+30A8 # KATAKANA LETTER E +0x8348 U+30A9 # KATAKANA LETTER SMALL O +0x8349 U+30AA # KATAKANA LETTER O +0x834A U+30AB # KATAKANA LETTER KA +0x834B U+30AC # KATAKANA LETTER GA +0x834C U+30AD # KATAKANA LETTER KI +0x834D U+30AE # KATAKANA LETTER GI +0x834E U+30AF # KATAKANA LETTER KU +0x834F U+30B0 # KATAKANA LETTER GU +0x8350 U+30B1 # KATAKANA LETTER KE +0x8351 U+30B2 # KATAKANA LETTER GE +0x8352 U+30B3 # KATAKANA LETTER KO +0x8353 U+30B4 # KATAKANA LETTER GO +0x8354 U+30B5 # KATAKANA LETTER SA +0x8355 U+30B6 # KATAKANA LETTER ZA +0x8356 U+30B7 # KATAKANA LETTER SI +0x8357 U+30B8 # KATAKANA LETTER ZI +0x8358 U+30B9 # KATAKANA LETTER SU +0x8359 U+30BA # KATAKANA LETTER ZU +0x835A U+30BB # KATAKANA LETTER SE +0x835B U+30BC # KATAKANA LETTER ZE +0x835C U+30BD # KATAKANA LETTER SO +0x835D U+30BE # KATAKANA LETTER ZO +0x835E U+30BF # KATAKANA LETTER TA +0x835F U+30C0 # KATAKANA LETTER DA +0x8360 U+30C1 # KATAKANA LETTER TI +0x8361 U+30C2 # KATAKANA LETTER DI +0x8362 U+30C3 # KATAKANA LETTER SMALL TU +0x8363 U+30C4 # KATAKANA LETTER TU +0x8364 U+30C5 # KATAKANA LETTER DU +0x8365 U+30C6 # KATAKANA LETTER TE +0x8366 U+30C7 # KATAKANA LETTER DE +0x8367 U+30C8 # KATAKANA LETTER TO +0x8368 U+30C9 # KATAKANA LETTER DO +0x8369 U+30CA # KATAKANA LETTER NA +0x836A U+30CB # KATAKANA LETTER NI +0x836B U+30CC # KATAKANA LETTER NU +0x836C U+30CD # KATAKANA LETTER NE +0x836D U+30CE # KATAKANA LETTER NO +0x836E U+30CF # KATAKANA LETTER HA +0x836F U+30D0 # KATAKANA LETTER BA +0x8370 U+30D1 # KATAKANA LETTER PA +0x8371 U+30D2 # KATAKANA LETTER HI +0x8372 U+30D3 # KATAKANA LETTER BI +0x8373 U+30D4 # KATAKANA LETTER PI +0x8374 U+30D5 # KATAKANA LETTER HU +0x8375 U+30D6 # KATAKANA LETTER BU +0x8376 U+30D7 # KATAKANA LETTER PU +0x8377 U+30D8 # KATAKANA LETTER HE +0x8378 U+30D9 # KATAKANA LETTER BE +0x8379 U+30DA # KATAKANA LETTER PE +0x837A U+30DB # KATAKANA LETTER HO +0x837B U+30DC # KATAKANA LETTER BO +0x837C U+30DD # KATAKANA LETTER PO +0x837D U+30DE # KATAKANA LETTER MA +0x837E U+30DF # KATAKANA LETTER MI +0x8380 U+30E0 # KATAKANA LETTER MU +0x8381 U+30E1 # KATAKANA LETTER ME +0x8382 U+30E2 # KATAKANA LETTER MO +0x8383 U+30E3 # KATAKANA LETTER SMALL YA +0x8384 U+30E4 # KATAKANA LETTER YA +0x8385 U+30E5 # KATAKANA LETTER SMALL YU +0x8386 U+30E6 # KATAKANA LETTER YU +0x8387 U+30E7 # KATAKANA LETTER SMALL YO +0x8388 U+30E8 # KATAKANA LETTER YO +0x8389 U+30E9 # KATAKANA LETTER RA +0x838A U+30EA # KATAKANA LETTER RI +0x838B U+30EB # KATAKANA LETTER RU +0x838C U+30EC # KATAKANA LETTER RE +0x838D U+30ED # KATAKANA LETTER RO +0x838E U+30EE # KATAKANA LETTER SMALL WA +0x838F U+30EF # KATAKANA LETTER WA +0x8390 U+30F0 # KATAKANA LETTER WI +0x8391 U+30F1 # KATAKANA LETTER WE +0x8392 U+30F2 # KATAKANA LETTER WO +0x8393 U+30F3 # KATAKANA LETTER N +0x8394 U+30F4 # KATAKANA LETTER VU +0x8395 U+30F5 # KATAKANA LETTER SMALL KA +0x8396 U+30F6 # KATAKANA LETTER SMALL KE +0x8397 U+30AB+309A # [2000] +0x8398 U+30AD+309A # [2000] +0x8399 U+30AF+309A # [2000] +0x839A U+30B1+309A # [2000] +0x839B U+30B3+309A # [2000] +0x839C U+30BB+309A # [2000] +0x839D U+30C4+309A # [2000] +0x839E U+30C8+309A # [2000] +0x839F U+0391 # GREEK CAPITAL LETTER ALPHA +0x83A0 U+0392 # GREEK CAPITAL LETTER BETA +0x83A1 U+0393 # GREEK CAPITAL LETTER GAMMA +0x83A2 U+0394 # GREEK CAPITAL LETTER DELTA +0x83A3 U+0395 # GREEK CAPITAL LETTER EPSILON +0x83A4 U+0396 # GREEK CAPITAL LETTER ZETA +0x83A5 U+0397 # GREEK CAPITAL LETTER ETA +0x83A6 U+0398 # GREEK CAPITAL LETTER THETA +0x83A7 U+0399 # GREEK CAPITAL LETTER IOTA +0x83A8 U+039A # GREEK CAPITAL LETTER KAPPA +0x83A9 U+039B # GREEK CAPITAL LETTER LAMDA +0x83AA U+039C # GREEK CAPITAL LETTER MU +0x83AB U+039D # GREEK CAPITAL LETTER NU +0x83AC U+039E # GREEK CAPITAL LETTER XI +0x83AD U+039F # GREEK CAPITAL LETTER OMICRON +0x83AE U+03A0 # GREEK CAPITAL LETTER PI +0x83AF U+03A1 # GREEK CAPITAL LETTER RHO +0x83B0 U+03A3 # GREEK CAPITAL LETTER SIGMA +0x83B1 U+03A4 # GREEK CAPITAL LETTER TAU +0x83B2 U+03A5 # GREEK CAPITAL LETTER UPSILON +0x83B3 U+03A6 # GREEK CAPITAL LETTER PHI +0x83B4 U+03A7 # GREEK CAPITAL LETTER CHI +0x83B5 U+03A8 # GREEK CAPITAL LETTER PSI +0x83B6 U+03A9 # GREEK CAPITAL LETTER OMEGA +0x83B7 U+2664 # WHITE SPADE SUIT [2000] +0x83B8 U+2660 # BLACK SPADE SUIT [2000] +0x83B9 U+2662 # WHITE DIAMOND SUIT [2000] +0x83BA U+2666 # BLACK DIAMOND SUIT [2000] +0x83BB U+2661 # WHITE HEART SUIT [2000] +0x83BC U+2665 # BLACK HEART SUIT [2000] +0x83BD U+2667 # WHITE CLUB SUIT [2000] +0x83BE U+2663 # BLACK CLUB SUIT [2000] +0x83BF U+03B1 # GREEK SMALL LETTER ALPHA +0x83C0 U+03B2 # GREEK SMALL LETTER BETA +0x83C1 U+03B3 # GREEK SMALL LETTER GAMMA +0x83C2 U+03B4 # GREEK SMALL LETTER DELTA +0x83C3 U+03B5 # GREEK SMALL LETTER EPSILON +0x83C4 U+03B6 # GREEK SMALL LETTER ZETA +0x83C5 U+03B7 # GREEK SMALL LETTER ETA +0x83C6 U+03B8 # GREEK SMALL LETTER THETA +0x83C7 U+03B9 # GREEK SMALL LETTER IOTA +0x83C8 U+03BA # GREEK SMALL LETTER KAPPA +0x83C9 U+03BB # GREEK SMALL LETTER LAMDA +0x83CA U+03BC # GREEK SMALL LETTER MU +0x83CB U+03BD # GREEK SMALL LETTER NU +0x83CC U+03BE # GREEK SMALL LETTER XI +0x83CD U+03BF # GREEK SMALL LETTER OMICRON +0x83CE U+03C0 # GREEK SMALL LETTER PI +0x83CF U+03C1 # GREEK SMALL LETTER RHO +0x83D0 U+03C3 # GREEK SMALL LETTER SIGMA +0x83D1 U+03C4 # GREEK SMALL LETTER TAU +0x83D2 U+03C5 # GREEK SMALL LETTER UPSILON +0x83D3 U+03C6 # GREEK SMALL LETTER PHI +0x83D4 U+03C7 # GREEK SMALL LETTER CHI +0x83D5 U+03C8 # GREEK SMALL LETTER PSI +0x83D6 U+03C9 # GREEK SMALL LETTER OMEGA +0x83D7 U+03C2 # GREEK SMALL LETTER FINAL SIGMA [2000] +0x83D8 U+24F5 # DOUBLE CIRCLED DIGIT ONE [2000] [Unicode3.2] +0x83D9 U+24F6 # DOUBLE CIRCLED DIGIT TWO [2000] [Unicode3.2] +0x83DA U+24F7 # DOUBLE CIRCLED DIGIT THREE [2000] [Unicode3.2] +0x83DB U+24F8 # DOUBLE CIRCLED DIGIT FOUR [2000] [Unicode3.2] +0x83DC U+24F9 # DOUBLE CIRCLED DIGIT FIVE [2000] [Unicode3.2] +0x83DD U+24FA # DOUBLE CIRCLED DIGIT SIX [2000] [Unicode3.2] +0x83DE U+24FB # DOUBLE CIRCLED DIGIT SEVEN [2000] [Unicode3.2] +0x83DF U+24FC # DOUBLE CIRCLED DIGIT EIGHT [2000] [Unicode3.2] +0x83E0 U+24FD # DOUBLE CIRCLED DIGIT NINE [2000] [Unicode3.2] +0x83E1 U+24FE # DOUBLE CIRCLED NUMBER TEN [2000] [Unicode3.2] +0x83E2 U+2616 # WHITE SHOGI PIECE [2000] [Unicode3.2] +0x83E3 U+2617 # BLACK SHOGI PIECE [2000] [Unicode3.2] +0x83E4 U+3020 # POSTAL MARK FACE [2000] +0x83E5 U+260E # BLACK TELEPHONE [2000] +0x83E6 U+2600 # BLACK SUN WITH RAYS [2000] +0x83E7 U+2601 # CLOUD [2000] +0x83E8 U+2602 # UMBRELLA [2000] +0x83E9 U+2603 # SNOWMAN [2000] +0x83EA U+2668 # HOT SPRINGS [2000] +0x83EB U+25B1 # WHITE PARALLELOGRAM [2000] +0x83EC U+31F0 # KATAKANA LETTER SMALL KU [2000] [Unicode3.2] +0x83ED U+31F1 # KATAKANA LETTER SMALL SI [2000] [Unicode3.2] +0x83EE U+31F2 # KATAKANA LETTER SMALL SU [2000] [Unicode3.2] +0x83EF U+31F3 # KATAKANA LETTER SMALL TO [2000] [Unicode3.2] +0x83F0 U+31F4 # KATAKANA LETTER SMALL NU [2000] [Unicode3.2] +0x83F1 U+31F5 # KATAKANA LETTER SMALL HA [2000] [Unicode3.2] +0x83F2 U+31F6 # KATAKANA LETTER SMALL HI [2000] [Unicode3.2] +0x83F3 U+31F7 # KATAKANA LETTER SMALL HU [2000] [Unicode3.2] +0x83F4 U+31F8 # KATAKANA LETTER SMALL HE [2000] [Unicode3.2] +0x83F5 U+31F9 # KATAKANA LETTER SMALL HO [2000] [Unicode3.2] +0x83F6 U+31F7+309A # [2000] +0x83F7 U+31FA # KATAKANA LETTER SMALL MU [2000] [Unicode3.2] +0x83F8 U+31FB # KATAKANA LETTER SMALL RA [2000] [Unicode3.2] +0x83F9 U+31FC # KATAKANA LETTER SMALL RI [2000] [Unicode3.2] +0x83FA U+31FD # KATAKANA LETTER SMALL RU [2000] [Unicode3.2] +0x83FB U+31FE # KATAKANA LETTER SMALL RE [2000] [Unicode3.2] +0x83FC U+31FF # KATAKANA LETTER SMALL RO [2000] [Unicode3.2] +0x8440 U+0410 # CYRILLIC CAPITAL LETTER A +0x8441 U+0411 # CYRILLIC CAPITAL LETTER BE +0x8442 U+0412 # CYRILLIC CAPITAL LETTER VE +0x8443 U+0413 # CYRILLIC CAPITAL LETTER GHE +0x8444 U+0414 # CYRILLIC CAPITAL LETTER DE +0x8445 U+0415 # CYRILLIC CAPITAL LETTER IE +0x8446 U+0401 # CYRILLIC CAPITAL LETTER IO +0x8447 U+0416 # CYRILLIC CAPITAL LETTER ZHE +0x8448 U+0417 # CYRILLIC CAPITAL LETTER ZE +0x8449 U+0418 # CYRILLIC CAPITAL LETTER I +0x844A U+0419 # CYRILLIC CAPITAL LETTER SHORT I +0x844B U+041A # CYRILLIC CAPITAL LETTER KA +0x844C U+041B # CYRILLIC CAPITAL LETTER EL +0x844D U+041C # CYRILLIC CAPITAL LETTER EM +0x844E U+041D # CYRILLIC CAPITAL LETTER EN +0x844F U+041E # CYRILLIC CAPITAL LETTER O +0x8450 U+041F # CYRILLIC CAPITAL LETTER PE +0x8451 U+0420 # CYRILLIC CAPITAL LETTER ER +0x8452 U+0421 # CYRILLIC CAPITAL LETTER ES +0x8453 U+0422 # CYRILLIC CAPITAL LETTER TE +0x8454 U+0423 # CYRILLIC CAPITAL LETTER U +0x8455 U+0424 # CYRILLIC CAPITAL LETTER EF +0x8456 U+0425 # CYRILLIC CAPITAL LETTER HA +0x8457 U+0426 # CYRILLIC CAPITAL LETTER TSE +0x8458 U+0427 # CYRILLIC CAPITAL LETTER CHE +0x8459 U+0428 # CYRILLIC CAPITAL LETTER SHA +0x845A U+0429 # CYRILLIC CAPITAL LETTER SHCHA +0x845B U+042A # CYRILLIC CAPITAL LETTER HARD SIGN +0x845C U+042B # CYRILLIC CAPITAL LETTER YERU +0x845D U+042C # CYRILLIC CAPITAL LETTER SOFT SIGN +0x845E U+042D # CYRILLIC CAPITAL LETTER E +0x845F U+042E # CYRILLIC CAPITAL LETTER YU +0x8460 U+042F # CYRILLIC CAPITAL LETTER YA +0x8461 U+23BE # DENTISTRY SYMBOL LIGHT VERTICAL AND TOP RIGHT [2000] [Unicode3.2] +0x8462 U+23BF # DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM RIGHT [2000] [Unicode3.2] +0x8463 U+23C0 # DENTISTRY SYMBOL LIGHT VERTICAL WITH CIRCLE [2000] [Unicode3.2] +0x8464 U+23C1 # DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE [2000] [Unicode3.2] +0x8465 U+23C2 # DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE [2000] [Unicode3.2] +0x8466 U+23C3 # DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE [2000] [Unicode3.2] +0x8467 U+23C4 # DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH TRIANGLE [2000] [Unicode3.2] +0x8468 U+23C5 # DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH TRIANGLE [2000] [Unicode3.2] +0x8469 U+23C6 # DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE [2000] [Unicode3.2] +0x846A U+23C7 # DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH WAVE [2000] [Unicode3.2] +0x846B U+23C8 # DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH WAVE [2000] [Unicode3.2] +0x846C U+23C9 # DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL [2000] [Unicode3.2] +0x846D U+23CA # DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL [2000] [Unicode3.2] +0x846E U+23CB # DENTISTRY SYMBOL LIGHT VERTICAL AND TOP LEFT [2000] [Unicode3.2] +0x846F U+23CC # DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM LEFT [2000] [Unicode3.2] +0x8470 U+0430 # CYRILLIC SMALL LETTER A +0x8471 U+0431 # CYRILLIC SMALL LETTER BE +0x8472 U+0432 # CYRILLIC SMALL LETTER VE +0x8473 U+0433 # CYRILLIC SMALL LETTER GHE +0x8474 U+0434 # CYRILLIC SMALL LETTER DE +0x8475 U+0435 # CYRILLIC SMALL LETTER IE +0x8476 U+0451 # CYRILLIC SMALL LETTER IO +0x8477 U+0436 # CYRILLIC SMALL LETTER ZHE +0x8478 U+0437 # CYRILLIC SMALL LETTER ZE +0x8479 U+0438 # CYRILLIC SMALL LETTER I +0x847A U+0439 # CYRILLIC SMALL LETTER SHORT I +0x847B U+043A # CYRILLIC SMALL LETTER KA +0x847C U+043B # CYRILLIC SMALL LETTER EL +0x847D U+043C # CYRILLIC SMALL LETTER EM +0x847E U+043D # CYRILLIC SMALL LETTER EN +0x8480 U+043E # CYRILLIC SMALL LETTER O +0x8481 U+043F # CYRILLIC SMALL LETTER PE +0x8482 U+0440 # CYRILLIC SMALL LETTER ER +0x8483 U+0441 # CYRILLIC SMALL LETTER ES +0x8484 U+0442 # CYRILLIC SMALL LETTER TE +0x8485 U+0443 # CYRILLIC SMALL LETTER U +0x8486 U+0444 # CYRILLIC SMALL LETTER EF +0x8487 U+0445 # CYRILLIC SMALL LETTER HA +0x8488 U+0446 # CYRILLIC SMALL LETTER TSE +0x8489 U+0447 # CYRILLIC SMALL LETTER CHE +0x848A U+0448 # CYRILLIC SMALL LETTER SHA +0x848B U+0449 # CYRILLIC SMALL LETTER SHCHA +0x848C U+044A # CYRILLIC SMALL LETTER HARD SIGN +0x848D U+044B # CYRILLIC SMALL LETTER YERU +0x848E U+044C # CYRILLIC SMALL LETTER SOFT SIGN +0x848F U+044D # CYRILLIC SMALL LETTER E +0x8490 U+044E # CYRILLIC SMALL LETTER YU +0x8491 U+044F # CYRILLIC SMALL LETTER YA +0x8492 U+30F7 # KATAKANA LETTER VA [2000] +0x8493 U+30F8 # KATAKANA LETTER VI [2000] +0x8494 U+30F9 # KATAKANA LETTER VE [2000] +0x8495 U+30FA # KATAKANA LETTER VO [2000] +0x8496 U+22DA # LESS-THAN EQUAL TO OR GREATER-THAN [2000] +0x8497 U+22DB # GREATER-THAN EQUAL TO OR LESS-THAN [2000] +0x8498 U+2153 # VULGAR FRACTION ONE THIRD [2000] +0x8499 U+2154 # VULGAR FRACTION TWO THIRDS [2000] +0x849A U+2155 # VULGAR FRACTION ONE FIFTH [2000] +0x849B U+2713 # CHECK MARK [2000] +0x849C U+2318 # PLACE OF INTEREST SIGN [2000] +0x849D U+2423 # OPEN BOX [2000] +0x849E U+23CE # RETURN SYMBOL [2000] [Unicode3.2] +0x849F U+2500 # BOX DRAWINGS LIGHT HORIZONTAL [1983] +0x84A0 U+2502 # BOX DRAWINGS LIGHT VERTICAL [1983] +0x84A1 U+250C # BOX DRAWINGS LIGHT DOWN AND RIGHT [1983] +0x84A2 U+2510 # BOX DRAWINGS LIGHT DOWN AND LEFT [1983] +0x84A3 U+2518 # BOX DRAWINGS LIGHT UP AND LEFT [1983] +0x84A4 U+2514 # BOX DRAWINGS LIGHT UP AND RIGHT [1983] +0x84A5 U+251C # BOX DRAWINGS LIGHT VERTICAL AND RIGHT [1983] +0x84A6 U+252C # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL [1983] +0x84A7 U+2524 # BOX DRAWINGS LIGHT VERTICAL AND LEFT [1983] +0x84A8 U+2534 # BOX DRAWINGS LIGHT UP AND HORIZONTAL [1983] +0x84A9 U+253C # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL [1983] +0x84AA U+2501 # BOX DRAWINGS HEAVY HORIZONTAL [1983] +0x84AB U+2503 # BOX DRAWINGS HEAVY VERTICAL [1983] +0x84AC U+250F # BOX DRAWINGS HEAVY DOWN AND RIGHT [1983] +0x84AD U+2513 # BOX DRAWINGS HEAVY DOWN AND LEFT [1983] +0x84AE U+251B # BOX DRAWINGS HEAVY UP AND LEFT [1983] +0x84AF U+2517 # BOX DRAWINGS HEAVY UP AND RIGHT [1983] +0x84B0 U+2523 # BOX DRAWINGS HEAVY VERTICAL AND RIGHT [1983] +0x84B1 U+2533 # BOX DRAWINGS HEAVY DOWN AND HORIZONTAL [1983] +0x84B2 U+252B # BOX DRAWINGS HEAVY VERTICAL AND LEFT [1983] +0x84B3 U+253B # BOX DRAWINGS HEAVY UP AND HORIZONTAL [1983] +0x84B4 U+254B # BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL [1983] +0x84B5 U+2520 # BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT [1983] +0x84B6 U+252F # BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY [1983] +0x84B7 U+2528 # BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT [1983] +0x84B8 U+2537 # BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY [1983] +0x84B9 U+253F # BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY [1983] +0x84BA U+251D # BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY [1983] +0x84BB U+2530 # BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT [1983] +0x84BC U+2525 # BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY [1983] +0x84BD U+2538 # BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT [1983] +0x84BE U+2542 # BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT [1983] +0x84BF U+3251 # CIRCLED NUMBER TWENTY ONE [2000] [Unicode3.2] +0x84C0 U+3252 # CIRCLED NUMBER TWENTY TWO [2000] [Unicode3.2] +0x84C1 U+3253 # CIRCLED NUMBER TWENTY THREE [2000] [Unicode3.2] +0x84C2 U+3254 # CIRCLED NUMBER TWENTY FOUR [2000] [Unicode3.2] +0x84C3 U+3255 # CIRCLED NUMBER TWENTY FIVE [2000] [Unicode3.2] +0x84C4 U+3256 # CIRCLED NUMBER TWENTY SIX [2000] [Unicode3.2] +0x84C5 U+3257 # CIRCLED NUMBER TWENTY SEVEN [2000] [Unicode3.2] +0x84C6 U+3258 # CIRCLED NUMBER TWENTY EIGHT [2000] [Unicode3.2] +0x84C7 U+3259 # CIRCLED NUMBER TWENTY NINE [2000] [Unicode3.2] +0x84C8 U+325A # CIRCLED NUMBER THIRTY [2000] [Unicode3.2] +0x84C9 U+325B # CIRCLED NUMBER THIRTY ONE [2000] [Unicode3.2] +0x84CA U+325C # CIRCLED NUMBER THIRTY TWO [2000] [Unicode3.2] +0x84CB U+325D # CIRCLED NUMBER THIRTY THREE [2000] [Unicode3.2] +0x84CC U+325E # CIRCLED NUMBER THIRTY FOUR [2000] [Unicode3.2] +0x84CD U+325F # CIRCLED NUMBER THIRTY FIVE [2000] [Unicode3.2] +0x84CE U+32B1 # CIRCLED NUMBER THIRTY SIX [2000] [Unicode3.2] +0x84CF U+32B2 # CIRCLED NUMBER THIRTY SEVEN [2000] [Unicode3.2] +0x84D0 U+32B3 # CIRCLED NUMBER THIRTY EIGHT [2000] [Unicode3.2] +0x84D1 U+32B4 # CIRCLED NUMBER THIRTY NINE [2000] [Unicode3.2] +0x84D2 U+32B5 # CIRCLED NUMBER FORTY [2000] [Unicode3.2] +0x84D3 U+32B6 # CIRCLED NUMBER FORTY ONE [2000] [Unicode3.2] +0x84D4 U+32B7 # CIRCLED NUMBER FORTY TWO [2000] [Unicode3.2] +0x84D5 U+32B8 # CIRCLED NUMBER FORTY THREE [2000] [Unicode3.2] +0x84D6 U+32B9 # CIRCLED NUMBER FORTY FOUR [2000] [Unicode3.2] +0x84D7 U+32BA # CIRCLED NUMBER FORTY FIVE [2000] [Unicode3.2] +0x84D8 U+32BB # CIRCLED NUMBER FORTY SIX [2000] [Unicode3.2] +0x84D9 U+32BC # CIRCLED NUMBER FORTY SEVEN [2000] [Unicode3.2] +0x84DA U+32BD # CIRCLED NUMBER FORTY EIGHT [2000] [Unicode3.2] +0x84DB U+32BE # CIRCLED NUMBER FORTY NINE [2000] [Unicode3.2] +0x84DC U+32BF # CIRCLED NUMBER FIFTY [2000] [Unicode3.2] +0x84DD # +0x84DE # +0x84DF # +0x84E0 # +0x84E1 # +0x84E2 # +0x84E3 # +0x84E4 # +0x84E5 U+25D0 # CIRCLE WITH LEFT HALF BLACK [2000] +0x84E6 U+25D1 # CIRCLE WITH RIGHT HALF BLACK [2000] +0x84E7 U+25D2 # CIRCLE WITH LOWER HALF BLACK [2000] +0x84E8 U+25D3 # CIRCLE WITH UPPER HALF BLACK [2000] +0x84E9 U+203C # DOUBLE EXCLAMATION MARK [2000] +0x84EA U+2047 # DOUBLE QUESTION MARK [2000] [Unicode3.2] +0x84EB U+2048 # QUESTION EXCLAMATION MARK [2000] +0x84EC U+2049 # EXCLAMATION QUESTION MARK [2000] +0x84ED U+01CD # LATIN CAPITAL LETTER A WITH CARON [2000] +0x84EE U+01CE # LATIN SMALL LETTER A WITH CARON [2000] +0x84EF U+01D0 # LATIN SMALL LETTER I WITH CARON [2000] +0x84F0 U+1E3E # LATIN CAPITAL LETTER M WITH ACUTE [2000] +0x84F1 U+1E3F # LATIN SMALL LETTER M WITH ACUTE [2000] +0x84F2 U+01F8 # LATIN CAPITAL LETTER N WITH GRAVE [2000] +0x84F3 U+01F9 # LATIN SMALL LETTER N WITH GRAVE [2000] +0x84F4 U+01D1 # LATIN CAPITAL LETTER O WITH CARON [2000] +0x84F5 U+01D2 # LATIN SMALL LETTER O WITH CARON [2000] +0x84F6 U+01D4 # LATIN SMALL LETTER U WITH CARON [2000] +0x84F7 U+01D6 # LATIN SMALL LETTER U WITH DIAERESIS AND MACRON [2000] +0x84F8 U+01D8 # LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE [2000] +0x84F9 U+01DA # LATIN SMALL LETTER U WITH DIAERESIS AND CARON [2000] +0x84FA U+01DC # LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE [2000] +0x84FB # +0x84FC # +0x8540 U+20AC # EURO SIGN [2000] +0x8541 U+00A0 # NO-BREAK SPACE [2000] +0x8542 U+00A1 # INVERTED EXCLAMATION MARK [2000] +0x8543 U+00A4 # CURRENCY SIGN [2000] +0x8544 U+00A6 # BROKEN BAR [2000] +0x8545 U+00A9 # COPYRIGHT SIGN [2000] +0x8546 U+00AA # FEMININE ORDINAL INDICATOR [2000] +0x8547 U+00AB # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK [2000] +0x8548 U+00AD # SOFT HYPHEN [2000] +0x8549 U+00AE # REGISTERED SIGN [2000] +0x854A U+00AF # MACRON [2000] +0x854B U+00B2 # SUPERSCRIPT TWO [2000] +0x854C U+00B3 # SUPERSCRIPT THREE [2000] +0x854D U+00B7 # MIDDLE DOT [2000] +0x854E U+00B8 # CEDILLA [2000] +0x854F U+00B9 # SUPERSCRIPT ONE [2000] +0x8550 U+00BA # MASCULINE ORDINAL INDICATOR [2000] +0x8551 U+00BB # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK [2000] +0x8552 U+00BC # VULGAR FRACTION ONE QUARTER [2000] +0x8553 U+00BD # VULGAR FRACTION ONE HALF [2000] +0x8554 U+00BE # VULGAR FRACTION THREE QUARTERS [2000] +0x8555 U+00BF # INVERTED QUESTION MARK [2000] +0x8556 U+00C0 # LATIN CAPITAL LETTER A WITH GRAVE [2000] +0x8557 U+00C1 # LATIN CAPITAL LETTER A WITH ACUTE [2000] +0x8558 U+00C2 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX [2000] +0x8559 U+00C3 # LATIN CAPITAL LETTER A WITH TILDE [2000] +0x855A U+00C4 # LATIN CAPITAL LETTER A WITH DIAERESIS [2000] +0x855B U+00C5 # LATIN CAPITAL LETTER A WITH RING ABOVE [2000] +0x855C U+00C6 # LATIN CAPITAL LETTER AE [2000] +0x855D U+00C7 # LATIN CAPITAL LETTER C WITH CEDILLA [2000] +0x855E U+00C8 # LATIN CAPITAL LETTER E WITH GRAVE [2000] +0x855F U+00C9 # LATIN CAPITAL LETTER E WITH ACUTE [2000] +0x8560 U+00CA # LATIN CAPITAL LETTER E WITH CIRCUMFLEX [2000] +0x8561 U+00CB # LATIN CAPITAL LETTER E WITH DIAERESIS [2000] +0x8562 U+00CC # LATIN CAPITAL LETTER I WITH GRAVE [2000] +0x8563 U+00CD # LATIN CAPITAL LETTER I WITH ACUTE [2000] +0x8564 U+00CE # LATIN CAPITAL LETTER I WITH CIRCUMFLEX [2000] +0x8565 U+00CF # LATIN CAPITAL LETTER I WITH DIAERESIS [2000] +0x8566 U+00D0 # LATIN CAPITAL LETTER ETH [2000] +0x8567 U+00D1 # LATIN CAPITAL LETTER N WITH TILDE [2000] +0x8568 U+00D2 # LATIN CAPITAL LETTER O WITH GRAVE [2000] +0x8569 U+00D3 # LATIN CAPITAL LETTER O WITH ACUTE [2000] +0x856A U+00D4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX [2000] +0x856B U+00D5 # LATIN CAPITAL LETTER O WITH TILDE [2000] +0x856C U+00D6 # LATIN CAPITAL LETTER O WITH DIAERESIS [2000] +0x856D U+00D8 # LATIN CAPITAL LETTER O WITH STROKE [2000] +0x856E U+00D9 # LATIN CAPITAL LETTER U WITH GRAVE [2000] +0x856F U+00DA # LATIN CAPITAL LETTER U WITH ACUTE [2000] +0x8570 U+00DB # LATIN CAPITAL LETTER U WITH CIRCUMFLEX [2000] +0x8571 U+00DC # LATIN CAPITAL LETTER U WITH DIAERESIS [2000] +0x8572 U+00DD # LATIN CAPITAL LETTER Y WITH ACUTE [2000] +0x8573 U+00DE # LATIN CAPITAL LETTER THORN [2000] +0x8574 U+00DF # LATIN SMALL LETTER SHARP S [2000] +0x8575 U+00E0 # LATIN SMALL LETTER A WITH GRAVE [2000] +0x8576 U+00E1 # LATIN SMALL LETTER A WITH ACUTE [2000] +0x8577 U+00E2 # LATIN SMALL LETTER A WITH CIRCUMFLEX [2000] +0x8578 U+00E3 # LATIN SMALL LETTER A WITH TILDE [2000] +0x8579 U+00E4 # LATIN SMALL LETTER A WITH DIAERESIS [2000] +0x857A U+00E5 # LATIN SMALL LETTER A WITH RING ABOVE [2000] +0x857B U+00E6 # LATIN SMALL LETTER AE [2000] +0x857C U+00E7 # LATIN SMALL LETTER C WITH CEDILLA [2000] +0x857D U+00E8 # LATIN SMALL LETTER E WITH GRAVE [2000] +0x857E U+00E9 # LATIN SMALL LETTER E WITH ACUTE [2000] +0x8580 U+00EA # LATIN SMALL LETTER E WITH CIRCUMFLEX [2000] +0x8581 U+00EB # LATIN SMALL LETTER E WITH DIAERESIS [2000] +0x8582 U+00EC # LATIN SMALL LETTER I WITH GRAVE [2000] +0x8583 U+00ED # LATIN SMALL LETTER I WITH ACUTE [2000] +0x8584 U+00EE # LATIN SMALL LETTER I WITH CIRCUMFLEX [2000] +0x8585 U+00EF # LATIN SMALL LETTER I WITH DIAERESIS [2000] +0x8586 U+00F0 # LATIN SMALL LETTER ETH [2000] +0x8587 U+00F1 # LATIN SMALL LETTER N WITH TILDE [2000] +0x8588 U+00F2 # LATIN SMALL LETTER O WITH GRAVE [2000] +0x8589 U+00F3 # LATIN SMALL LETTER O WITH ACUTE [2000] +0x858A U+00F4 # LATIN SMALL LETTER O WITH CIRCUMFLEX [2000] +0x858B U+00F5 # LATIN SMALL LETTER O WITH TILDE [2000] +0x858C U+00F6 # LATIN SMALL LETTER O WITH DIAERESIS [2000] +0x858D U+00F8 # LATIN SMALL LETTER O WITH STROKE [2000] +0x858E U+00F9 # LATIN SMALL LETTER U WITH GRAVE [2000] +0x858F U+00FA # LATIN SMALL LETTER U WITH ACUTE [2000] +0x8590 U+00FB # LATIN SMALL LETTER U WITH CIRCUMFLEX [2000] +0x8591 U+00FC # LATIN SMALL LETTER U WITH DIAERESIS [2000] +0x8592 U+00FD # LATIN SMALL LETTER Y WITH ACUTE [2000] +0x8593 U+00FE # LATIN SMALL LETTER THORN [2000] +0x8594 U+00FF # LATIN SMALL LETTER Y WITH DIAERESIS [2000] +0x8595 U+0100 # LATIN CAPITAL LETTER A WITH MACRON [2000] +0x8596 U+012A # LATIN CAPITAL LETTER I WITH MACRON [2000] +0x8597 U+016A # LATIN CAPITAL LETTER U WITH MACRON [2000] +0x8598 U+0112 # LATIN CAPITAL LETTER E WITH MACRON [2000] +0x8599 U+014C # LATIN CAPITAL LETTER O WITH MACRON [2000] +0x859A U+0101 # LATIN SMALL LETTER A WITH MACRON [2000] +0x859B U+012B # LATIN SMALL LETTER I WITH MACRON [2000] +0x859C U+016B # LATIN SMALL LETTER U WITH MACRON [2000] +0x859D U+0113 # LATIN SMALL LETTER E WITH MACRON [2000] +0x859E U+014D # LATIN SMALL LETTER O WITH MACRON [2000] +0x859F U+0104 # LATIN CAPITAL LETTER A WITH OGONEK [2000] +0x85A0 U+02D8 # BREVE [2000] +0x85A1 U+0141 # LATIN CAPITAL LETTER L WITH STROKE [2000] +0x85A2 U+013D # LATIN CAPITAL LETTER L WITH CARON [2000] +0x85A3 U+015A # LATIN CAPITAL LETTER S WITH ACUTE [2000] +0x85A4 U+0160 # LATIN CAPITAL LETTER S WITH CARON [2000] +0x85A5 U+015E # LATIN CAPITAL LETTER S WITH CEDILLA [2000] +0x85A6 U+0164 # LATIN CAPITAL LETTER T WITH CARON [2000] +0x85A7 U+0179 # LATIN CAPITAL LETTER Z WITH ACUTE [2000] +0x85A8 U+017D # LATIN CAPITAL LETTER Z WITH CARON [2000] +0x85A9 U+017B # LATIN CAPITAL LETTER Z WITH DOT ABOVE [2000] +0x85AA U+0105 # LATIN SMALL LETTER A WITH OGONEK [2000] +0x85AB U+02DB # OGONEK [2000] +0x85AC U+0142 # LATIN SMALL LETTER L WITH STROKE [2000] +0x85AD U+013E # LATIN SMALL LETTER L WITH CARON [2000] +0x85AE U+015B # LATIN SMALL LETTER S WITH ACUTE [2000] +0x85AF U+02C7 # CARON [2000] +0x85B0 U+0161 # LATIN SMALL LETTER S WITH CARON [2000] +0x85B1 U+015F # LATIN SMALL LETTER S WITH CEDILLA [2000] +0x85B2 U+0165 # LATIN SMALL LETTER T WITH CARON [2000] +0x85B3 U+017A # LATIN SMALL LETTER Z WITH ACUTE [2000] +0x85B4 U+02DD # DOUBLE ACUTE ACCENT [2000] +0x85B5 U+017E # LATIN SMALL LETTER Z WITH CARON [2000] +0x85B6 U+017C # LATIN SMALL LETTER Z WITH DOT ABOVE [2000] +0x85B7 U+0154 # LATIN CAPITAL LETTER R WITH ACUTE [2000] +0x85B8 U+0102 # LATIN CAPITAL LETTER A WITH BREVE [2000] +0x85B9 U+0139 # LATIN CAPITAL LETTER L WITH ACUTE [2000] +0x85BA U+0106 # LATIN CAPITAL LETTER C WITH ACUTE [2000] +0x85BB U+010C # LATIN CAPITAL LETTER C WITH CARON [2000] +0x85BC U+0118 # LATIN CAPITAL LETTER E WITH OGONEK [2000] +0x85BD U+011A # LATIN CAPITAL LETTER E WITH CARON [2000] +0x85BE U+010E # LATIN CAPITAL LETTER D WITH CARON [2000] +0x85BF U+0143 # LATIN CAPITAL LETTER N WITH ACUTE [2000] +0x85C0 U+0147 # LATIN CAPITAL LETTER N WITH CARON [2000] +0x85C1 U+0150 # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE [2000] +0x85C2 U+0158 # LATIN CAPITAL LETTER R WITH CARON [2000] +0x85C3 U+016E # LATIN CAPITAL LETTER U WITH RING ABOVE [2000] +0x85C4 U+0170 # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE [2000] +0x85C5 U+0162 # LATIN CAPITAL LETTER T WITH CEDILLA [2000] +0x85C6 U+0155 # LATIN SMALL LETTER R WITH ACUTE [2000] +0x85C7 U+0103 # LATIN SMALL LETTER A WITH BREVE [2000] +0x85C8 U+013A # LATIN SMALL LETTER L WITH ACUTE [2000] +0x85C9 U+0107 # LATIN SMALL LETTER C WITH ACUTE [2000] +0x85CA U+010D # LATIN SMALL LETTER C WITH CARON [2000] +0x85CB U+0119 # LATIN SMALL LETTER E WITH OGONEK [2000] +0x85CC U+011B # LATIN SMALL LETTER E WITH CARON [2000] +0x85CD U+010F # LATIN SMALL LETTER D WITH CARON [2000] +0x85CE U+0111 # LATIN SMALL LETTER D WITH STROKE [2000] +0x85CF U+0144 # LATIN SMALL LETTER N WITH ACUTE [2000] +0x85D0 U+0148 # LATIN SMALL LETTER N WITH CARON [2000] +0x85D1 U+0151 # LATIN SMALL LETTER O WITH DOUBLE ACUTE [2000] +0x85D2 U+0159 # LATIN SMALL LETTER R WITH CARON [2000] +0x85D3 U+016F # LATIN SMALL LETTER U WITH RING ABOVE [2000] +0x85D4 U+0171 # LATIN SMALL LETTER U WITH DOUBLE ACUTE [2000] +0x85D5 U+0163 # LATIN SMALL LETTER T WITH CEDILLA [2000] +0x85D6 U+02D9 # DOT ABOVE [2000] +0x85D7 U+0108 # LATIN CAPITAL LETTER C WITH CIRCUMFLEX [2000] +0x85D8 U+011C # LATIN CAPITAL LETTER G WITH CIRCUMFLEX [2000] +0x85D9 U+0124 # LATIN CAPITAL LETTER H WITH CIRCUMFLEX [2000] +0x85DA U+0134 # LATIN CAPITAL LETTER J WITH CIRCUMFLEX [2000] +0x85DB U+015C # LATIN CAPITAL LETTER S WITH CIRCUMFLEX [2000] +0x85DC U+016C # LATIN CAPITAL LETTER U WITH BREVE [2000] +0x85DD U+0109 # LATIN SMALL LETTER C WITH CIRCUMFLEX [2000] +0x85DE U+011D # LATIN SMALL LETTER G WITH CIRCUMFLEX [2000] +0x85DF U+0125 # LATIN SMALL LETTER H WITH CIRCUMFLEX [2000] +0x85E0 U+0135 # LATIN SMALL LETTER J WITH CIRCUMFLEX [2000] +0x85E1 U+015D # LATIN SMALL LETTER S WITH CIRCUMFLEX [2000] +0x85E2 U+016D # LATIN SMALL LETTER U WITH BREVE [2000] +0x85E3 U+0271 # LATIN SMALL LETTER M WITH HOOK [2000] +0x85E4 U+028B # LATIN SMALL LETTER V WITH HOOK [2000] +0x85E5 U+027E # LATIN SMALL LETTER R WITH FISHHOOK [2000] +0x85E6 U+0283 # LATIN SMALL LETTER ESH [2000] +0x85E7 U+0292 # LATIN SMALL LETTER EZH [2000] +0x85E8 U+026C # LATIN SMALL LETTER L WITH BELT [2000] +0x85E9 U+026E # LATIN SMALL LETTER LEZH [2000] +0x85EA U+0279 # LATIN SMALL LETTER TURNED R [2000] +0x85EB U+0288 # LATIN SMALL LETTER T WITH RETROFLEX HOOK [2000] +0x85EC U+0256 # LATIN SMALL LETTER D WITH TAIL [2000] +0x85ED U+0273 # LATIN SMALL LETTER N WITH RETROFLEX HOOK [2000] +0x85EE U+027D # LATIN SMALL LETTER R WITH TAIL [2000] +0x85EF U+0282 # LATIN SMALL LETTER S WITH HOOK [2000] +0x85F0 U+0290 # LATIN SMALL LETTER Z WITH RETROFLEX HOOK [2000] +0x85F1 U+027B # LATIN SMALL LETTER TURNED R WITH HOOK [2000] +0x85F2 U+026D # LATIN SMALL LETTER L WITH RETROFLEX HOOK [2000] +0x85F3 U+025F # LATIN SMALL LETTER DOTLESS J WITH STROKE [2000] +0x85F4 U+0272 # LATIN SMALL LETTER N WITH LEFT HOOK [2000] +0x85F5 U+029D # LATIN SMALL LETTER J WITH CROSSED-TAIL [2000] +0x85F6 U+028E # LATIN SMALL LETTER TURNED Y [2000] +0x85F7 U+0261 # LATIN SMALL LETTER SCRIPT G [2000] +0x85F8 U+014B # LATIN SMALL LETTER ENG [2000] +0x85F9 U+0270 # LATIN SMALL LETTER TURNED M WITH LONG LEG [2000] +0x85FA U+0281 # LATIN LETTER SMALL CAPITAL INVERTED R [2000] +0x85FB U+0127 # LATIN SMALL LETTER H WITH STROKE [2000] +0x85FC U+0295 # LATIN LETTER PHARYNGEAL VOICED FRICATIVE [2000] +0x8640 U+0294 # LATIN LETTER GLOTTAL STOP [2000] +0x8641 U+0266 # LATIN SMALL LETTER H WITH HOOK [2000] +0x8642 U+0298 # LATIN LETTER BILABIAL CLICK [2000] +0x8643 U+01C2 # LATIN LETTER ALVEOLAR CLICK [2000] +0x8644 U+0253 # LATIN SMALL LETTER B WITH HOOK [2000] +0x8645 U+0257 # LATIN SMALL LETTER D WITH HOOK [2000] +0x8646 U+0284 # LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK [2000] +0x8647 U+0260 # LATIN SMALL LETTER G WITH HOOK [2000] +0x8648 U+0193 # LATIN CAPITAL LETTER G WITH HOOK [2000] +0x8649 U+0153 # LATIN SMALL LIGATURE OE [2000] +0x864A U+0152 # LATIN CAPITAL LIGATURE OE [2000] +0x864B U+0268 # LATIN SMALL LETTER I WITH STROKE [2000] +0x864C U+0289 # LATIN SMALL LETTER U BAR [2000] +0x864D U+0258 # LATIN SMALL LETTER REVERSED E [2000] +0x864E U+0275 # LATIN SMALL LETTER BARRED O [2000] +0x864F U+0259 # LATIN SMALL LETTER SCHWA [2000] +0x8650 U+025C # LATIN SMALL LETTER REVERSED OPEN E [2000] +0x8651 U+025E # LATIN SMALL LETTER CLOSED REVERSED OPEN E [2000] +0x8652 U+0250 # LATIN SMALL LETTER TURNED A [2000] +0x8653 U+026F # LATIN SMALL LETTER TURNED M [2000] +0x8654 U+028A # LATIN SMALL LETTER UPSILON [2000] +0x8655 U+0264 # LATIN SMALL LETTER RAMS HORN [2000] +0x8656 U+028C # LATIN SMALL LETTER TURNED V [2000] +0x8657 U+0254 # LATIN SMALL LETTER OPEN O [2000] +0x8658 U+0251 # LATIN SMALL LETTER ALPHA [2000] +0x8659 U+0252 # LATIN SMALL LETTER TURNED ALPHA [2000] +0x865A U+028D # LATIN SMALL LETTER TURNED W [2000] +0x865B U+0265 # LATIN SMALL LETTER TURNED H [2000] +0x865C U+02A2 # LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE [2000] +0x865D U+02A1 # LATIN LETTER GLOTTAL STOP WITH STROKE [2000] +0x865E U+0255 # LATIN SMALL LETTER C WITH CURL [2000] +0x865F U+0291 # LATIN SMALL LETTER Z WITH CURL [2000] +0x8660 U+027A # LATIN SMALL LETTER TURNED R WITH LONG LEG [2000] +0x8661 U+0267 # LATIN SMALL LETTER HENG WITH HOOK [2000] +0x8662 U+025A # LATIN SMALL LETTER SCHWA WITH HOOK [2000] +0x8663 U+00E6+0300 # [2000] +0x8664 U+01FD # LATIN SMALL LETTER AE WITH ACUTE [2000] +0x8665 U+1F70 # GREEK SMALL LETTER ALPHA WITH VARIA [2000] +0x8666 U+1F71 # GREEK SMALL LETTER ALPHA WITH OXIA [2000] +0x8667 U+0254+0300 # [2000] +0x8668 U+0254+0301 # [2000] +0x8669 U+028C+0300 # [2000] +0x866A U+028C+0301 # [2000] +0x866B U+0259+0300 # [2000] +0x866C U+0259+0301 # [2000] +0x866D U+025A+0300 # [2000] +0x866E U+025A+0301 # [2000] +0x866F U+1F72 # GREEK SMALL LETTER EPSILON WITH VARIA [2000] +0x8670 U+1F73 # GREEK SMALL LETTER EPSILON WITH OXIA [2000] +0x8671 U+0361 # COMBINING DOUBLE INVERTED BREVE [2000] +0x8672 U+02C8 # MODIFIER LETTER VERTICAL LINE [2000] +0x8673 U+02CC # MODIFIER LETTER LOW VERTICAL LINE [2000] +0x8674 U+02D0 # MODIFIER LETTER TRIANGULAR COLON [2000] +0x8675 U+02D1 # MODIFIER LETTER HALF TRIANGULAR COLON [2000] +0x8676 U+0306 # COMBINING BREVE [2000] +0x8677 U+203F # UNDERTIE [2000] +0x8678 U+030B # COMBINING DOUBLE ACUTE ACCENT [2000] +0x8679 U+0301 # COMBINING ACUTE ACCENT [2000] +0x867A U+0304 # COMBINING MACRON [2000] +0x867B U+0300 # COMBINING GRAVE ACCENT [2000] +0x867C U+030F # COMBINING DOUBLE GRAVE ACCENT [2000] +0x867D U+030C # COMBINING CARON [2000] +0x867E U+0302 # COMBINING CIRCUMFLEX ACCENT [2000] +0x8680 U+02E5 # MODIFIER LETTER EXTRA-HIGH TONE BAR [2000] +0x8681 U+02E6 # MODIFIER LETTER HIGH TONE BAR [2000] +0x8682 U+02E7 # MODIFIER LETTER MID TONE BAR [2000] +0x8683 U+02E8 # MODIFIER LETTER LOW TONE BAR [2000] +0x8684 U+02E9 # MODIFIER LETTER EXTRA-LOW TONE BAR [2000] +0x8685 U+02E9+02E5 # [2000] +0x8686 U+02E5+02E9 # [2000] +0x8687 U+0325 # COMBINING RING BELOW [2000] +0x8688 U+032C # COMBINING CARON BELOW [2000] +0x8689 U+0339 # COMBINING RIGHT HALF RING BELOW [2000] +0x868A U+031C # COMBINING LEFT HALF RING BELOW [2000] +0x868B U+031F # COMBINING PLUS SIGN BELOW [2000] +0x868C U+0320 # COMBINING MINUS SIGN BELOW [2000] +0x868D U+0308 # COMBINING DIAERESIS [2000] +0x868E U+033D # COMBINING X ABOVE [2000] +0x868F U+0329 # COMBINING VERTICAL LINE BELOW [2000] +0x8690 U+032F # COMBINING INVERTED BREVE BELOW [2000] +0x8691 U+02DE # MODIFIER LETTER RHOTIC HOOK [2000] +0x8692 U+0324 # COMBINING DIAERESIS BELOW [2000] +0x8693 U+0330 # COMBINING TILDE BELOW [2000] +0x8694 U+033C # COMBINING SEAGULL BELOW [2000] +0x8695 U+0334 # COMBINING TILDE OVERLAY [2000] +0x8696 U+031D # COMBINING UP TACK BELOW [2000] +0x8697 U+031E # COMBINING DOWN TACK BELOW [2000] +0x8698 U+0318 # COMBINING LEFT TACK BELOW [2000] +0x8699 U+0319 # COMBINING RIGHT TACK BELOW [2000] +0x869A U+032A # COMBINING BRIDGE BELOW [2000] +0x869B U+033A # COMBINING INVERTED BRIDGE BELOW [2000] +0x869C U+033B # COMBINING SQUARE BELOW [2000] +0x869D U+0303 # COMBINING TILDE [2000] +0x869E U+031A # COMBINING LEFT ANGLE ABOVE [2000] +0x869F U+2776 # DINGBAT NEGATIVE CIRCLED DIGIT ONE [2000] +0x86A0 U+2777 # DINGBAT NEGATIVE CIRCLED DIGIT TWO [2000] +0x86A1 U+2778 # DINGBAT NEGATIVE CIRCLED DIGIT THREE [2000] +0x86A2 U+2779 # DINGBAT NEGATIVE CIRCLED DIGIT FOUR [2000] +0x86A3 U+277A # DINGBAT NEGATIVE CIRCLED DIGIT FIVE [2000] +0x86A4 U+277B # DINGBAT NEGATIVE CIRCLED DIGIT SIX [2000] +0x86A5 U+277C # DINGBAT NEGATIVE CIRCLED DIGIT SEVEN [2000] +0x86A6 U+277D # DINGBAT NEGATIVE CIRCLED DIGIT EIGHT [2000] +0x86A7 U+277E # DINGBAT NEGATIVE CIRCLED DIGIT NINE [2000] +0x86A8 U+277F # DINGBAT NEGATIVE CIRCLED NUMBER TEN [2000] +0x86A9 U+24EB # NEGATIVE CIRCLED NUMBER ELEVEN [2000] [Unicode3.2] +0x86AA U+24EC # NEGATIVE CIRCLED NUMBER TWELVE [2000] [Unicode3.2] +0x86AB U+24ED # NEGATIVE CIRCLED NUMBER THIRTEEN [2000] [Unicode3.2] +0x86AC U+24EE # NEGATIVE CIRCLED NUMBER FOURTEEN [2000] [Unicode3.2] +0x86AD U+24EF # NEGATIVE CIRCLED NUMBER FIFTEEN [2000] [Unicode3.2] +0x86AE U+24F0 # NEGATIVE CIRCLED NUMBER SIXTEEN [2000] [Unicode3.2] +0x86AF U+24F1 # NEGATIVE CIRCLED NUMBER SEVENTEEN [2000] [Unicode3.2] +0x86B0 U+24F2 # NEGATIVE CIRCLED NUMBER EIGHTEEN [2000] [Unicode3.2] +0x86B1 U+24F3 # NEGATIVE CIRCLED NUMBER NINETEEN [2000] [Unicode3.2] +0x86B2 U+24F4 # NEGATIVE CIRCLED NUMBER TWENTY [2000] [Unicode3.2] +0x86B3 U+2170 # SMALL ROMAN NUMERAL ONE [2000] +0x86B4 U+2171 # SMALL ROMAN NUMERAL TWO [2000] +0x86B5 U+2172 # SMALL ROMAN NUMERAL THREE [2000] +0x86B6 U+2173 # SMALL ROMAN NUMERAL FOUR [2000] +0x86B7 U+2174 # SMALL ROMAN NUMERAL FIVE [2000] +0x86B8 U+2175 # SMALL ROMAN NUMERAL SIX [2000] +0x86B9 U+2176 # SMALL ROMAN NUMERAL SEVEN [2000] +0x86BA U+2177 # SMALL ROMAN NUMERAL EIGHT [2000] +0x86BB U+2178 # SMALL ROMAN NUMERAL NINE [2000] +0x86BC U+2179 # SMALL ROMAN NUMERAL TEN [2000] +0x86BD U+217A # SMALL ROMAN NUMERAL ELEVEN [2000] +0x86BE U+217B # SMALL ROMAN NUMERAL TWELVE [2000] +0x86BF U+24D0 # CIRCLED LATIN SMALL LETTER A [2000] +0x86C0 U+24D1 # CIRCLED LATIN SMALL LETTER B [2000] +0x86C1 U+24D2 # CIRCLED LATIN SMALL LETTER C [2000] +0x86C2 U+24D3 # CIRCLED LATIN SMALL LETTER D [2000] +0x86C3 U+24D4 # CIRCLED LATIN SMALL LETTER E [2000] +0x86C4 U+24D5 # CIRCLED LATIN SMALL LETTER F [2000] +0x86C5 U+24D6 # CIRCLED LATIN SMALL LETTER G [2000] +0x86C6 U+24D7 # CIRCLED LATIN SMALL LETTER H [2000] +0x86C7 U+24D8 # CIRCLED LATIN SMALL LETTER I [2000] +0x86C8 U+24D9 # CIRCLED LATIN SMALL LETTER J [2000] +0x86C9 U+24DA # CIRCLED LATIN SMALL LETTER K [2000] +0x86CA U+24DB # CIRCLED LATIN SMALL LETTER L [2000] +0x86CB U+24DC # CIRCLED LATIN SMALL LETTER M [2000] +0x86CC U+24DD # CIRCLED LATIN SMALL LETTER N [2000] +0x86CD U+24DE # CIRCLED LATIN SMALL LETTER O [2000] +0x86CE U+24DF # CIRCLED LATIN SMALL LETTER P [2000] +0x86CF U+24E0 # CIRCLED LATIN SMALL LETTER Q [2000] +0x86D0 U+24E1 # CIRCLED LATIN SMALL LETTER R [2000] +0x86D1 U+24E2 # CIRCLED LATIN SMALL LETTER S [2000] +0x86D2 U+24E3 # CIRCLED LATIN SMALL LETTER T [2000] +0x86D3 U+24E4 # CIRCLED LATIN SMALL LETTER U [2000] +0x86D4 U+24E5 # CIRCLED LATIN SMALL LETTER V [2000] +0x86D5 U+24E6 # CIRCLED LATIN SMALL LETTER W [2000] +0x86D6 U+24E7 # CIRCLED LATIN SMALL LETTER X [2000] +0x86D7 U+24E8 # CIRCLED LATIN SMALL LETTER Y [2000] +0x86D8 U+24E9 # CIRCLED LATIN SMALL LETTER Z [2000] +0x86D9 U+32D0 # CIRCLED KATAKANA A [2000] +0x86DA U+32D1 # CIRCLED KATAKANA I [2000] +0x86DB U+32D2 # CIRCLED KATAKANA U [2000] +0x86DC U+32D3 # CIRCLED KATAKANA E [2000] +0x86DD U+32D4 # CIRCLED KATAKANA O [2000] +0x86DE U+32D5 # CIRCLED KATAKANA KA [2000] +0x86DF U+32D6 # CIRCLED KATAKANA KI [2000] +0x86E0 U+32D7 # CIRCLED KATAKANA KU [2000] +0x86E1 U+32D8 # CIRCLED KATAKANA KE [2000] +0x86E2 U+32D9 # CIRCLED KATAKANA KO [2000] +0x86E3 U+32DA # CIRCLED KATAKANA SA [2000] +0x86E4 U+32DB # CIRCLED KATAKANA SI [2000] +0x86E5 U+32DC # CIRCLED KATAKANA SU [2000] +0x86E6 U+32DD # CIRCLED KATAKANA SE [2000] +0x86E7 U+32DE # CIRCLED KATAKANA SO [2000] +0x86E8 U+32DF # CIRCLED KATAKANA TA [2000] +0x86E9 U+32E0 # CIRCLED KATAKANA TI [2000] +0x86EA U+32E1 # CIRCLED KATAKANA TU [2000] +0x86EB U+32E2 # CIRCLED KATAKANA TE [2000] +0x86EC U+32E3 # CIRCLED KATAKANA TO [2000] +0x86ED U+32FA # CIRCLED KATAKANA RO [2000] +0x86EE U+32E9 # CIRCLED KATAKANA HA [2000] +0x86EF U+32E5 # CIRCLED KATAKANA NI [2000] +0x86F0 U+32ED # CIRCLED KATAKANA HO [2000] +0x86F1 U+32EC # CIRCLED KATAKANA HE [2000] +0x86F2 # +0x86F3 # +0x86F4 # +0x86F5 # +0x86F6 # +0x86F7 # +0x86F8 # +0x86F9 # +0x86FA # +0x86FB U+2051 # TWO ASTERISKS ALIGNED VERTICALLY [2000] [Unicode3.2] +0x86FC U+2042 # ASTERISM [2000] +0x8740 U+2460 # CIRCLED DIGIT ONE [2000] +0x8741 U+2461 # CIRCLED DIGIT TWO [2000] +0x8742 U+2462 # CIRCLED DIGIT THREE [2000] +0x8743 U+2463 # CIRCLED DIGIT FOUR [2000] +0x8744 U+2464 # CIRCLED DIGIT FIVE [2000] +0x8745 U+2465 # CIRCLED DIGIT SIX [2000] +0x8746 U+2466 # CIRCLED DIGIT SEVEN [2000] +0x8747 U+2467 # CIRCLED DIGIT EIGHT [2000] +0x8748 U+2468 # CIRCLED DIGIT NINE [2000] +0x8749 U+2469 # CIRCLED NUMBER TEN [2000] +0x874A U+246A # CIRCLED NUMBER ELEVEN [2000] +0x874B U+246B # CIRCLED NUMBER TWELVE [2000] +0x874C U+246C # CIRCLED NUMBER THIRTEEN [2000] +0x874D U+246D # CIRCLED NUMBER FOURTEEN [2000] +0x874E U+246E # CIRCLED NUMBER FIFTEEN [2000] +0x874F U+246F # CIRCLED NUMBER SIXTEEN [2000] +0x8750 U+2470 # CIRCLED NUMBER SEVENTEEN [2000] +0x8751 U+2471 # CIRCLED NUMBER EIGHTEEN [2000] +0x8752 U+2472 # CIRCLED NUMBER NINETEEN [2000] +0x8753 U+2473 # CIRCLED NUMBER TWENTY [2000] +0x8754 U+2160 # ROMAN NUMERAL ONE [2000] +0x8755 U+2161 # ROMAN NUMERAL TWO [2000] +0x8756 U+2162 # ROMAN NUMERAL THREE [2000] +0x8757 U+2163 # ROMAN NUMERAL FOUR [2000] +0x8758 U+2164 # ROMAN NUMERAL FIVE [2000] +0x8759 U+2165 # ROMAN NUMERAL SIX [2000] +0x875A U+2166 # ROMAN NUMERAL SEVEN [2000] +0x875B U+2167 # ROMAN NUMERAL EIGHT [2000] +0x875C U+2168 # ROMAN NUMERAL NINE [2000] +0x875D U+2169 # ROMAN NUMERAL TEN [2000] +0x875E U+216A # ROMAN NUMERAL ELEVEN [2000] +0x875F U+3349 # SQUARE MIRI [2000] +0x8760 U+3314 # SQUARE KIRO [2000] +0x8761 U+3322 # SQUARE SENTI [2000] +0x8762 U+334D # SQUARE MEETORU [2000] +0x8763 U+3318 # SQUARE GURAMU [2000] +0x8764 U+3327 # SQUARE TON [2000] +0x8765 U+3303 # SQUARE AARU [2000] +0x8766 U+3336 # SQUARE HEKUTAARU [2000] +0x8767 U+3351 # SQUARE RITTORU [2000] +0x8768 U+3357 # SQUARE WATTO [2000] +0x8769 U+330D # SQUARE KARORII [2000] +0x876A U+3326 # SQUARE DORU [2000] +0x876B U+3323 # SQUARE SENTO [2000] +0x876C U+332B # SQUARE PAASENTO [2000] +0x876D U+334A # SQUARE MIRIBAARU [2000] +0x876E U+333B # SQUARE PEEZI [2000] +0x876F U+339C # SQUARE MM [2000] +0x8770 U+339D # SQUARE CM [2000] +0x8771 U+339E # SQUARE KM [2000] +0x8772 U+338E # SQUARE MG [2000] +0x8773 U+338F # SQUARE KG [2000] +0x8774 U+33C4 # SQUARE CC [2000] +0x8775 U+33A1 # SQUARE M SQUARED [2000] +0x8776 U+216B # ROMAN NUMERAL TWELVE [2000] +0x8777 # +0x8778 # +0x8779 # +0x877A # +0x877B # +0x877C # +0x877D # +0x877E U+337B # SQUARE ERA NAME HEISEI [2000] +0x8780 U+301D # REVERSED DOUBLE PRIME QUOTATION MARK [2000] +0x8781 U+301F # LOW DOUBLE PRIME QUOTATION MARK [2000] +0x8782 U+2116 # NUMERO SIGN [2000] +0x8783 U+33CD # SQUARE KK [2000] +0x8784 U+2121 # TELEPHONE SIGN [2000] +0x8785 U+32A4 # CIRCLED IDEOGRAPH HIGH [2000] +0x8786 U+32A5 # CIRCLED IDEOGRAPH CENTRE [2000] +0x8787 U+32A6 # CIRCLED IDEOGRAPH LOW [2000] +0x8788 U+32A7 # CIRCLED IDEOGRAPH LEFT [2000] +0x8789 U+32A8 # CIRCLED IDEOGRAPH RIGHT [2000] +0x878A U+3231 # PARENTHESIZED IDEOGRAPH STOCK [2000] +0x878B U+3232 # PARENTHESIZED IDEOGRAPH HAVE [2000] +0x878C U+3239 # PARENTHESIZED IDEOGRAPH REPRESENT [2000] +0x878D U+337E # SQUARE ERA NAME MEIZI [2000] +0x878E U+337D # SQUARE ERA NAME TAISYOU [2000] +0x878F U+337C # SQUARE ERA NAME SYOUWA [2000] +0x8790 # Windows: U+2252 +0x8791 # Windows: U+2261 +0x8792 # Windows: U+222B +0x8793 U+222E # CONTOUR INTEGRAL [2000] +0x8794 # Windows: U+2211 +0x8795 # Windows: U+221A +0x8796 # Windows: U+22A5 +0x8797 # Windows: U+2220 +0x8798 U+221F # RIGHT ANGLE [2000] +0x8799 U+22BF # RIGHT TRIANGLE [2000] +0x879A # Windows: U+2235 +0x879B # Windows: U+2229 +0x879C # Windows: U+222A +0x879D U+2756 # BLACK DIAMOND MINUS WHITE X [2000] +0x879E U+261E # WHITE RIGHT POINTING INDEX [2000] +0x879F U+4FF1 # [2004] +0x87A0 U+2000B # [2000] [Unicode3.1] +0x87A1 U+3402 # [2000] +0x87A2 U+4E28 # [2000] +0x87A3 U+4E2F # [2000] +0x87A4 U+4E30 # [2000] +0x87A5 U+4E8D # [2000] +0x87A6 U+4EE1 # [2000] +0x87A7 U+4EFD # [2000] +0x87A8 U+4EFF # [2000] +0x87A9 U+4F03 # [2000] +0x87AA U+4F0B # [2000] +0x87AB U+4F60 # [2000] +0x87AC U+4F48 # [2000] +0x87AD U+4F49 # [2000] +0x87AE U+4F56 # [2000] +0x87AF U+4F5F # [2000] +0x87B0 U+4F6A # [2000] +0x87B1 U+4F6C # [2000] +0x87B2 U+4F7E # [2000] +0x87B3 U+4F8A # [2000] +0x87B4 U+4F94 # [2000] +0x87B5 U+4F97 # [2000] +0x87B6 U+FA30 # CJK COMPATIBILITY IDEOGRAPH-FA30 [2000] [Unicode3.2] +0x87B7 U+4FC9 # [2000] +0x87B8 U+4FE0 # [2000] +0x87B9 U+5001 # [2000] +0x87BA U+5002 # [2000] +0x87BB U+500E # [2000] +0x87BC U+5018 # [2000] +0x87BD U+5027 # [2000] +0x87BE U+502E # [2000] +0x87BF U+5040 # [2000] +0x87C0 U+503B # [2000] +0x87C1 U+5041 # [2000] +0x87C2 U+5094 # [2000] +0x87C3 U+50CC # [2000] +0x87C4 U+50F2 # [2000] +0x87C5 U+50D0 # [2000] +0x87C6 U+50E6 # [2000] +0x87C7 U+FA31 # CJK COMPATIBILITY IDEOGRAPH-FA31 [2000] [Unicode3.2] +0x87C8 U+5106 # [2000] +0x87C9 U+5103 # [2000] +0x87CA U+510B # [2000] +0x87CB U+511E # [2000] +0x87CC U+5135 # [2000] +0x87CD U+514A # [2000] +0x87CE U+FA32 # CJK COMPATIBILITY IDEOGRAPH-FA32 [2000] [Unicode3.2] +0x87CF U+5155 # [2000] +0x87D0 U+5157 # [2000] +0x87D1 U+34B5 # [2000] +0x87D2 U+519D # [2000] +0x87D3 U+51C3 # [2000] +0x87D4 U+51CA # [2000] +0x87D5 U+51DE # [2000] +0x87D6 U+51E2 # [2000] +0x87D7 U+51EE # [2000] +0x87D8 U+5201 # [2000] +0x87D9 U+34DB # [2000] +0x87DA U+5213 # [2000] +0x87DB U+5215 # [2000] +0x87DC U+5249 # [2000] +0x87DD U+5257 # [2000] +0x87DE U+5261 # [2000] +0x87DF U+5293 # [2000] +0x87E0 U+52C8 # [2000] +0x87E1 U+FA33 # CJK COMPATIBILITY IDEOGRAPH-FA33 [2000] [Unicode3.2] +0x87E2 U+52CC # [2000] +0x87E3 U+52D0 # [2000] +0x87E4 U+52D6 # [2000] +0x87E5 U+52DB # [2000] +0x87E6 U+FA34 # CJK COMPATIBILITY IDEOGRAPH-FA34 [2000] [Unicode3.2] +0x87E7 U+52F0 # [2000] +0x87E8 U+52FB # [2000] +0x87E9 U+5300 # [2000] +0x87EA U+5307 # [2000] +0x87EB U+531C # [2000] +0x87EC U+FA35 # CJK COMPATIBILITY IDEOGRAPH-FA35 [2000] [Unicode3.2] +0x87ED U+5361 # [2000] +0x87EE U+5363 # [2000] +0x87EF U+537D # [2000] +0x87F0 U+5393 # [2000] +0x87F1 U+539D # [2000] +0x87F2 U+53B2 # [2000] +0x87F3 U+5412 # [2000] +0x87F4 U+5427 # [2000] +0x87F5 U+544D # [2000] +0x87F6 U+549C # [2000] +0x87F7 U+546B # [2000] +0x87F8 U+5474 # [2000] +0x87F9 U+547F # [2000] +0x87FA U+5488 # [2000] +0x87FB U+5496 # [2000] +0x87FC U+54A1 # [2000] +0x8840 U+54A9 # [2000] +0x8841 U+54C6 # [2000] +0x8842 U+54FF # [2000] +0x8843 U+550E # [2000] +0x8844 U+552B # [2000] +0x8845 U+5535 # [2000] +0x8846 U+5550 # [2000] +0x8847 U+555E # [2000] +0x8848 U+5581 # [2000] +0x8849 U+5586 # [2000] +0x884A U+558E # [2000] +0x884B U+FA36 # CJK COMPATIBILITY IDEOGRAPH-FA36 [2000] [Unicode3.2] +0x884C U+55AD # [2000] +0x884D U+55CE # [2000] +0x884E U+FA37 # CJK COMPATIBILITY IDEOGRAPH-FA37 [2000] [Unicode3.2] +0x884F U+5608 # [2000] +0x8850 U+560E # [2000] +0x8851 U+563B # [2000] +0x8852 U+5649 # [2000] +0x8853 U+5676 # [2000] +0x8854 U+5666 # [2000] +0x8855 U+FA38 # CJK COMPATIBILITY IDEOGRAPH-FA38 [2000] [Unicode3.2] +0x8856 U+566F # [2000] +0x8857 U+5671 # [2000] +0x8858 U+5672 # [2000] +0x8859 U+5699 # [2000] +0x885A U+569E # [2000] +0x885B U+56A9 # [2000] +0x885C U+56AC # [2000] +0x885D U+56B3 # [2000] +0x885E U+56C9 # [2000] +0x885F U+56CA # [2000] +0x8860 U+570A # [2000] +0x8861 U+2123D # [2000] [Unicode3.1] +0x8862 U+5721 # [2000] +0x8863 U+572F # [2000] +0x8864 U+5733 # [2000] +0x8865 U+5734 # [2000] +0x8866 U+5770 # [2000] +0x8867 U+5777 # [2000] +0x8868 U+577C # [2000] +0x8869 U+579C # [2000] +0x886A U+FA0F # CJK COMPATIBILITY IDEOGRAPH-FA0F [2000] +0x886B U+2131B # [2000] [Unicode3.1] +0x886C U+57B8 # [2000] +0x886D U+57C7 # [2000] +0x886E U+57C8 # [2000] +0x886F U+57CF # [2000] +0x8870 U+57E4 # [2000] +0x8871 U+57ED # [2000] +0x8872 U+57F5 # [2000] +0x8873 U+57F6 # [2000] +0x8874 U+57FF # [2000] +0x8875 U+5809 # [2000] +0x8876 U+FA10 # CJK COMPATIBILITY IDEOGRAPH-FA10 [2000] +0x8877 U+5861 # [2000] +0x8878 U+5864 # [2000] +0x8879 U+FA39 # CJK COMPATIBILITY IDEOGRAPH-FA39 [2000] [Unicode3.2] +0x887A U+587C # [2000] +0x887B U+5889 # [2000] +0x887C U+589E # [2000] +0x887D U+FA3A # CJK COMPATIBILITY IDEOGRAPH-FA3A [2000] [Unicode3.2] +0x887E U+58A9 # [2000] +0x8880 U+2146E # [2000] [Unicode3.1] +0x8881 U+58D2 # [2000] +0x8882 U+58CE # [2000] +0x8883 U+58D4 # [2000] +0x8884 U+58DA # [2000] +0x8885 U+58E0 # [2000] +0x8886 U+58E9 # [2000] +0x8887 U+590C # [2000] +0x8888 U+8641 # [2000] +0x8889 U+595D # [2000] +0x888A U+596D # [2000] +0x888B U+598B # [2000] +0x888C U+5992 # [2000] +0x888D U+59A4 # [2000] +0x888E U+59C3 # [2000] +0x888F U+59D2 # [2000] +0x8890 U+59DD # [2000] +0x8891 U+5A13 # [2000] +0x8892 U+5A23 # [2000] +0x8893 U+5A67 # [2000] +0x8894 U+5A6D # [2000] +0x8895 U+5A77 # [2000] +0x8896 U+5A7E # [2000] +0x8897 U+5A84 # [2000] +0x8898 U+5A9E # [2000] +0x8899 U+5AA7 # [2000] +0x889A U+5AC4 # [2000] +0x889B U+218BD # [2000] [Unicode3.1] +0x889C U+5B19 # [2000] +0x889D U+5B25 # [2000] +0x889E U+525D # [2004] +0x889F U+4E9C # +0x88A0 U+5516 # +0x88A1 U+5A03 # +0x88A2 U+963F # +0x88A3 U+54C0 # +0x88A4 U+611B # +0x88A5 U+6328 # +0x88A6 U+59F6 # +0x88A7 U+9022 # +0x88A8 U+8475 # +0x88A9 U+831C # +0x88AA U+7A50 # +0x88AB U+60AA # +0x88AC U+63E1 # +0x88AD U+6E25 # +0x88AE U+65ED # +0x88AF U+8466 # +0x88B0 U+82A6 # +0x88B1 U+9BF5 # +0x88B2 U+6893 # +0x88B3 U+5727 # +0x88B4 U+65A1 # +0x88B5 U+6271 # +0x88B6 U+5B9B # +0x88B7 U+59D0 # +0x88B8 U+867B # +0x88B9 U+98F4 # +0x88BA U+7D62 # +0x88BB U+7DBE # +0x88BC U+9B8E # +0x88BD U+6216 # +0x88BE U+7C9F # +0x88BF U+88B7 # +0x88C0 U+5B89 # +0x88C1 U+5EB5 # +0x88C2 U+6309 # +0x88C3 U+6697 # +0x88C4 U+6848 # +0x88C5 U+95C7 # +0x88C6 U+978D # +0x88C7 U+674F # +0x88C8 U+4EE5 # +0x88C9 U+4F0A # +0x88CA U+4F4D # +0x88CB U+4F9D # +0x88CC U+5049 # +0x88CD U+56F2 # +0x88CE U+5937 # +0x88CF U+59D4 # +0x88D0 U+5A01 # +0x88D1 U+5C09 # +0x88D2 U+60DF # +0x88D3 U+610F # +0x88D4 U+6170 # +0x88D5 U+6613 # +0x88D6 U+6905 # +0x88D7 U+70BA # +0x88D8 U+754F # +0x88D9 U+7570 # +0x88DA U+79FB # +0x88DB U+7DAD # +0x88DC U+7DEF # +0x88DD U+80C3 # +0x88DE U+840E # +0x88DF U+8863 # +0x88E0 U+8B02 # +0x88E1 U+9055 # +0x88E2 U+907A # +0x88E3 U+533B # +0x88E4 U+4E95 # +0x88E5 U+4EA5 # +0x88E6 U+57DF # +0x88E7 U+80B2 # +0x88E8 U+90C1 # +0x88E9 U+78EF # +0x88EA U+4E00 # +0x88EB U+58F1 # +0x88EC U+6EA2 # +0x88ED U+9038 # +0x88EE U+7A32 # +0x88EF U+8328 # +0x88F0 U+828B # +0x88F1 U+9C2F # +0x88F2 U+5141 # +0x88F3 U+5370 # +0x88F4 U+54BD # +0x88F5 U+54E1 # +0x88F6 U+56E0 # +0x88F7 U+59FB # +0x88F8 U+5F15 # +0x88F9 U+98F2 # +0x88FA U+6DEB # +0x88FB U+80E4 # +0x88FC U+852D # +0x8940 U+9662 # +0x8941 U+9670 # +0x8942 U+96A0 # +0x8943 U+97FB # +0x8944 U+540B # +0x8945 U+53F3 # +0x8946 U+5B87 # +0x8947 U+70CF # +0x8948 U+7FBD # +0x8949 U+8FC2 # +0x894A U+96E8 # +0x894B U+536F # +0x894C U+9D5C # +0x894D U+7ABA # +0x894E U+4E11 # +0x894F U+7893 # +0x8950 U+81FC # +0x8951 U+6E26 # +0x8952 U+5618 # +0x8953 U+5504 # +0x8954 U+6B1D # +0x8955 U+851A # +0x8956 U+9C3B # +0x8957 U+59E5 # +0x8958 U+53A9 # +0x8959 U+6D66 # +0x895A U+74DC # +0x895B U+958F # +0x895C U+5642 # +0x895D U+4E91 # +0x895E U+904B # +0x895F U+96F2 # +0x8960 U+834F # +0x8961 U+990C # +0x8962 U+53E1 # +0x8963 U+55B6 # +0x8964 U+5B30 # +0x8965 U+5F71 # +0x8966 U+6620 # +0x8967 U+66F3 # +0x8968 U+6804 # +0x8969 U+6C38 # +0x896A U+6CF3 # +0x896B U+6D29 # +0x896C U+745B # +0x896D U+76C8 # +0x896E U+7A4E # +0x896F U+9834 # +0x8970 U+82F1 # +0x8971 U+885B # +0x8972 U+8A60 # +0x8973 U+92ED # +0x8974 U+6DB2 # +0x8975 U+75AB # +0x8976 U+76CA # +0x8977 U+99C5 # +0x8978 U+60A6 # +0x8979 U+8B01 # +0x897A U+8D8A # +0x897B U+95B2 # +0x897C U+698E # +0x897D U+53AD # +0x897E U+5186 # +0x8980 U+5712 # +0x8981 U+5830 # +0x8982 U+5944 # +0x8983 U+5BB4 # +0x8984 U+5EF6 # +0x8985 U+6028 # +0x8986 U+63A9 # +0x8987 U+63F4 # +0x8988 U+6CBF # +0x8989 U+6F14 # +0x898A U+708E # +0x898B U+7114 # +0x898C U+7159 # +0x898D U+71D5 # +0x898E U+733F # +0x898F U+7E01 # +0x8990 U+8276 # +0x8991 U+82D1 # +0x8992 U+8597 # +0x8993 U+9060 # +0x8994 U+925B # +0x8995 U+9D1B # +0x8996 U+5869 # +0x8997 U+65BC # +0x8998 U+6C5A # +0x8999 U+7525 # +0x899A U+51F9 # +0x899B U+592E # +0x899C U+5965 # +0x899D U+5F80 # +0x899E U+5FDC # +0x899F U+62BC # +0x89A0 U+65FA # +0x89A1 U+6A2A # +0x89A2 U+6B27 # +0x89A3 U+6BB4 # +0x89A4 U+738B # +0x89A5 U+7FC1 # +0x89A6 U+8956 # +0x89A7 U+9D2C # +0x89A8 U+9D0E # +0x89A9 U+9EC4 # +0x89AA U+5CA1 # +0x89AB U+6C96 # +0x89AC U+837B # +0x89AD U+5104 # +0x89AE U+5C4B # +0x89AF U+61B6 # +0x89B0 U+81C6 # +0x89B1 U+6876 # +0x89B2 U+7261 # +0x89B3 U+4E59 # +0x89B4 U+4FFA # +0x89B5 U+5378 # +0x89B6 U+6069 # +0x89B7 U+6E29 # +0x89B8 U+7A4F # +0x89B9 U+97F3 # +0x89BA U+4E0B # +0x89BB U+5316 # +0x89BC U+4EEE # +0x89BD U+4F55 # +0x89BE U+4F3D # +0x89BF U+4FA1 # +0x89C0 U+4F73 # +0x89C1 U+52A0 # +0x89C2 U+53EF # +0x89C3 U+5609 # +0x89C4 U+590F # +0x89C5 U+5AC1 # +0x89C6 U+5BB6 # +0x89C7 U+5BE1 # +0x89C8 U+79D1 # +0x89C9 U+6687 # +0x89CA U+679C # +0x89CB U+67B6 # +0x89CC U+6B4C # +0x89CD U+6CB3 # +0x89CE U+706B # +0x89CF U+73C2 # +0x89D0 U+798D # +0x89D1 U+79BE # +0x89D2 U+7A3C # +0x89D3 U+7B87 # +0x89D4 U+82B1 # +0x89D5 U+82DB # +0x89D6 U+8304 # +0x89D7 U+8377 # +0x89D8 U+83EF # +0x89D9 U+83D3 # +0x89DA U+8766 # +0x89DB U+8AB2 # +0x89DC U+5629 # +0x89DD U+8CA8 # +0x89DE U+8FE6 # +0x89DF U+904E # +0x89E0 U+971E # +0x89E1 U+868A # +0x89E2 U+4FC4 # +0x89E3 U+5CE8 # +0x89E4 U+6211 # +0x89E5 U+7259 # +0x89E6 U+753B # +0x89E7 U+81E5 # +0x89E8 U+82BD # +0x89E9 U+86FE # +0x89EA U+8CC0 # +0x89EB U+96C5 # +0x89EC U+9913 # +0x89ED U+99D5 # +0x89EE U+4ECB # +0x89EF U+4F1A # +0x89F0 U+89E3 # +0x89F1 U+56DE # +0x89F2 U+584A # +0x89F3 U+58CA # +0x89F4 U+5EFB # +0x89F5 U+5FEB # +0x89F6 U+602A # +0x89F7 U+6094 # +0x89F8 U+6062 # +0x89F9 U+61D0 # +0x89FA U+6212 # +0x89FB U+62D0 # +0x89FC U+6539 # +0x8A40 U+9B41 # +0x8A41 U+6666 # +0x8A42 U+68B0 # +0x8A43 U+6D77 # +0x8A44 U+7070 # +0x8A45 U+754C # +0x8A46 U+7686 # +0x8A47 U+7D75 # +0x8A48 U+82A5 # +0x8A49 U+87F9 # +0x8A4A U+958B # +0x8A4B U+968E # +0x8A4C U+8C9D # +0x8A4D U+51F1 # +0x8A4E U+52BE # +0x8A4F U+5916 # +0x8A50 U+54B3 # +0x8A51 U+5BB3 # +0x8A52 U+5D16 # +0x8A53 U+6168 # +0x8A54 U+6982 # +0x8A55 U+6DAF # +0x8A56 U+788D # +0x8A57 U+84CB # +0x8A58 U+8857 # +0x8A59 U+8A72 # +0x8A5A U+93A7 # +0x8A5B U+9AB8 # +0x8A5C U+6D6C # +0x8A5D U+99A8 # +0x8A5E U+86D9 # +0x8A5F U+57A3 # +0x8A60 U+67FF # +0x8A61 U+86CE # +0x8A62 U+920E # +0x8A63 U+5283 # +0x8A64 U+5687 # +0x8A65 U+5404 # +0x8A66 U+5ED3 # +0x8A67 U+62E1 # +0x8A68 U+64B9 # +0x8A69 U+683C # +0x8A6A U+6838 # +0x8A6B U+6BBB # +0x8A6C U+7372 # +0x8A6D U+78BA # +0x8A6E U+7A6B # +0x8A6F U+899A # +0x8A70 U+89D2 # +0x8A71 U+8D6B # +0x8A72 U+8F03 # +0x8A73 U+90ED # +0x8A74 U+95A3 # +0x8A75 U+9694 # +0x8A76 U+9769 # +0x8A77 U+5B66 # +0x8A78 U+5CB3 # +0x8A79 U+697D # +0x8A7A U+984D # +0x8A7B U+984E # +0x8A7C U+639B # +0x8A7D U+7B20 # +0x8A7E U+6A2B # +0x8A80 U+6A7F # +0x8A81 U+68B6 # +0x8A82 U+9C0D # +0x8A83 U+6F5F # +0x8A84 U+5272 # +0x8A85 U+559D # +0x8A86 U+6070 # +0x8A87 U+62EC # +0x8A88 U+6D3B # +0x8A89 U+6E07 # +0x8A8A U+6ED1 # +0x8A8B U+845B # +0x8A8C U+8910 # +0x8A8D U+8F44 # +0x8A8E U+4E14 # +0x8A8F U+9C39 # +0x8A90 U+53F6 # +0x8A91 U+691B # +0x8A92 U+6A3A # +0x8A93 U+9784 # +0x8A94 U+682A # +0x8A95 U+515C # +0x8A96 U+7AC3 # +0x8A97 U+84B2 # +0x8A98 U+91DC # +0x8A99 U+938C # +0x8A9A U+565B # +0x8A9B U+9D28 # +0x8A9C U+6822 # +0x8A9D U+8305 # +0x8A9E U+8431 # +0x8A9F U+7CA5 # +0x8AA0 U+5208 # +0x8AA1 U+82C5 # +0x8AA2 U+74E6 # +0x8AA3 U+4E7E # +0x8AA4 U+4F83 # +0x8AA5 U+51A0 # +0x8AA6 U+5BD2 # +0x8AA7 U+520A # +0x8AA8 U+52D8 # +0x8AA9 U+52E7 # +0x8AAA U+5DFB # +0x8AAB U+559A # +0x8AAC U+582A # +0x8AAD U+59E6 # +0x8AAE U+5B8C # +0x8AAF U+5B98 # +0x8AB0 U+5BDB # +0x8AB1 U+5E72 # +0x8AB2 U+5E79 # +0x8AB3 U+60A3 # +0x8AB4 U+611F # +0x8AB5 U+6163 # +0x8AB6 U+61BE # +0x8AB7 U+63DB # +0x8AB8 U+6562 # +0x8AB9 U+67D1 # +0x8ABA U+6853 # +0x8ABB U+68FA # +0x8ABC U+6B3E # +0x8ABD U+6B53 # +0x8ABE U+6C57 # +0x8ABF U+6F22 # +0x8AC0 U+6F97 # +0x8AC1 U+6F45 # +0x8AC2 U+74B0 # +0x8AC3 U+7518 # +0x8AC4 U+76E3 # +0x8AC5 U+770B # +0x8AC6 U+7AFF # +0x8AC7 U+7BA1 # +0x8AC8 U+7C21 # +0x8AC9 U+7DE9 # +0x8ACA U+7F36 # +0x8ACB U+7FF0 # +0x8ACC U+809D # +0x8ACD U+8266 # +0x8ACE U+839E # +0x8ACF U+89B3 # +0x8AD0 U+8ACC # +0x8AD1 U+8CAB # +0x8AD2 U+9084 # +0x8AD3 U+9451 # +0x8AD4 U+9593 # +0x8AD5 U+9591 # +0x8AD6 U+95A2 # +0x8AD7 U+9665 # +0x8AD8 U+97D3 # +0x8AD9 U+9928 # +0x8ADA U+8218 # +0x8ADB U+4E38 # +0x8ADC U+542B # +0x8ADD U+5CB8 # +0x8ADE U+5DCC # +0x8ADF U+73A9 # +0x8AE0 U+764C # +0x8AE1 U+773C # +0x8AE2 U+5CA9 # +0x8AE3 U+7FEB # +0x8AE4 U+8D0B # +0x8AE5 U+96C1 # +0x8AE6 U+9811 # +0x8AE7 U+9854 # +0x8AE8 U+9858 # +0x8AE9 U+4F01 # +0x8AEA U+4F0E # +0x8AEB U+5371 # +0x8AEC U+559C # +0x8AED U+5668 # +0x8AEE U+57FA # +0x8AEF U+5947 # +0x8AF0 U+5B09 # +0x8AF1 U+5BC4 # +0x8AF2 U+5C90 # +0x8AF3 U+5E0C # +0x8AF4 U+5E7E # +0x8AF5 U+5FCC # +0x8AF6 U+63EE # +0x8AF7 U+673A # +0x8AF8 U+65D7 # +0x8AF9 U+65E2 # +0x8AFA U+671F # +0x8AFB U+68CB # +0x8AFC U+68C4 # +0x8B40 U+6A5F # +0x8B41 U+5E30 # +0x8B42 U+6BC5 # +0x8B43 U+6C17 # +0x8B44 U+6C7D # +0x8B45 U+757F # +0x8B46 U+7948 # +0x8B47 U+5B63 # +0x8B48 U+7A00 # +0x8B49 U+7D00 # +0x8B4A U+5FBD # +0x8B4B U+898F # +0x8B4C U+8A18 # +0x8B4D U+8CB4 # +0x8B4E U+8D77 # +0x8B4F U+8ECC # +0x8B50 U+8F1D # +0x8B51 U+98E2 # +0x8B52 U+9A0E # +0x8B53 U+9B3C # +0x8B54 U+4E80 # +0x8B55 U+507D # +0x8B56 U+5100 # +0x8B57 U+5993 # +0x8B58 U+5B9C # +0x8B59 U+622F # +0x8B5A U+6280 # +0x8B5B U+64EC # +0x8B5C U+6B3A # +0x8B5D U+72A0 # +0x8B5E U+7591 # +0x8B5F U+7947 # +0x8B60 U+7FA9 # +0x8B61 U+87FB # +0x8B62 U+8ABC # +0x8B63 U+8B70 # +0x8B64 U+63AC # +0x8B65 U+83CA # +0x8B66 U+97A0 # +0x8B67 U+5409 # +0x8B68 U+5403 # +0x8B69 U+55AB # +0x8B6A U+6854 # +0x8B6B U+6A58 # +0x8B6C U+8A70 # +0x8B6D U+7827 # +0x8B6E U+6775 # +0x8B6F U+9ECD # +0x8B70 U+5374 # +0x8B71 U+5BA2 # +0x8B72 U+811A # +0x8B73 U+8650 # +0x8B74 U+9006 # +0x8B75 U+4E18 # +0x8B76 U+4E45 # +0x8B77 U+4EC7 # +0x8B78 U+4F11 # +0x8B79 U+53CA # +0x8B7A U+5438 # +0x8B7B U+5BAE # +0x8B7C U+5F13 # +0x8B7D U+6025 # +0x8B7E U+6551 # +0x8B80 U+673D # +0x8B81 U+6C42 # +0x8B82 U+6C72 # +0x8B83 U+6CE3 # +0x8B84 U+7078 # +0x8B85 U+7403 # +0x8B86 U+7A76 # +0x8B87 U+7AAE # +0x8B88 U+7B08 # +0x8B89 U+7D1A # +0x8B8A U+7CFE # +0x8B8B U+7D66 # +0x8B8C U+65E7 # +0x8B8D U+725B # +0x8B8E U+53BB # +0x8B8F U+5C45 # +0x8B90 U+5DE8 # +0x8B91 U+62D2 # +0x8B92 U+62E0 # +0x8B93 U+6319 # +0x8B94 U+6E20 # +0x8B95 U+865A # +0x8B96 U+8A31 # +0x8B97 U+8DDD # +0x8B98 U+92F8 # +0x8B99 U+6F01 # +0x8B9A U+79A6 # +0x8B9B U+9B5A # +0x8B9C U+4EA8 # +0x8B9D U+4EAB # +0x8B9E U+4EAC # +0x8B9F U+4F9B # +0x8BA0 U+4FA0 # +0x8BA1 U+50D1 # +0x8BA2 U+5147 # +0x8BA3 U+7AF6 # +0x8BA4 U+5171 # +0x8BA5 U+51F6 # +0x8BA6 U+5354 # +0x8BA7 U+5321 # +0x8BA8 U+537F # +0x8BA9 U+53EB # +0x8BAA U+55AC # +0x8BAB U+5883 # +0x8BAC U+5CE1 # +0x8BAD U+5F37 # +0x8BAE U+5F4A # +0x8BAF U+602F # +0x8BB0 U+6050 # +0x8BB1 U+606D # +0x8BB2 U+631F # +0x8BB3 U+6559 # +0x8BB4 U+6A4B # +0x8BB5 U+6CC1 # +0x8BB6 U+72C2 # +0x8BB7 U+72ED # +0x8BB8 U+77EF # +0x8BB9 U+80F8 # +0x8BBA U+8105 # +0x8BBB U+8208 # +0x8BBC U+854E # +0x8BBD U+90F7 # +0x8BBE U+93E1 # +0x8BBF U+97FF # +0x8BC0 U+9957 # +0x8BC1 U+9A5A # +0x8BC2 U+4EF0 # +0x8BC3 U+51DD # +0x8BC4 U+5C2D # +0x8BC5 U+6681 # +0x8BC6 U+696D # +0x8BC7 U+5C40 # +0x8BC8 U+66F2 # +0x8BC9 U+6975 # +0x8BCA U+7389 # +0x8BCB U+6850 # +0x8BCC U+7C81 # +0x8BCD U+50C5 # +0x8BCE U+52E4 # +0x8BCF U+5747 # +0x8BD0 U+5DFE # +0x8BD1 U+9326 # +0x8BD2 U+65A4 # +0x8BD3 U+6B23 # +0x8BD4 U+6B3D # +0x8BD5 U+7434 # +0x8BD6 U+7981 # +0x8BD7 U+79BD # +0x8BD8 U+7B4B # +0x8BD9 U+7DCA # +0x8BDA U+82B9 # +0x8BDB U+83CC # +0x8BDC U+887F # +0x8BDD U+895F # +0x8BDE U+8B39 # +0x8BDF U+8FD1 # +0x8BE0 U+91D1 # +0x8BE1 U+541F # +0x8BE2 U+9280 # +0x8BE3 U+4E5D # +0x8BE4 U+5036 # +0x8BE5 U+53E5 # +0x8BE6 U+533A # +0x8BE7 U+72D7 # +0x8BE8 U+7396 # +0x8BE9 U+77E9 # +0x8BEA U+82E6 # +0x8BEB U+8EAF # +0x8BEC U+99C6 # +0x8BED U+99C8 # +0x8BEE U+99D2 # +0x8BEF U+5177 # +0x8BF0 U+611A # +0x8BF1 U+865E # +0x8BF2 U+55B0 # +0x8BF3 U+7A7A # +0x8BF4 U+5076 # +0x8BF5 U+5BD3 # +0x8BF6 U+9047 # +0x8BF7 U+9685 # +0x8BF8 U+4E32 # +0x8BF9 U+6ADB # +0x8BFA U+91E7 # +0x8BFB U+5C51 # +0x8BFC U+5C48 # +0x8C40 U+6398 # +0x8C41 U+7A9F # +0x8C42 U+6C93 # +0x8C43 U+9774 # +0x8C44 U+8F61 # +0x8C45 U+7AAA # +0x8C46 U+718A # +0x8C47 U+9688 # +0x8C48 U+7C82 # +0x8C49 U+6817 # +0x8C4A U+7E70 # +0x8C4B U+6851 # +0x8C4C U+936C # +0x8C4D U+52F2 # +0x8C4E U+541B # +0x8C4F U+85AB # +0x8C50 U+8A13 # +0x8C51 U+7FA4 # +0x8C52 U+8ECD # +0x8C53 U+90E1 # +0x8C54 U+5366 # +0x8C55 U+8888 # +0x8C56 U+7941 # +0x8C57 U+4FC2 # +0x8C58 U+50BE # +0x8C59 U+5211 # +0x8C5A U+5144 # +0x8C5B U+5553 # +0x8C5C U+572D # +0x8C5D U+73EA # +0x8C5E U+578B # +0x8C5F U+5951 # +0x8C60 U+5F62 # +0x8C61 U+5F84 # +0x8C62 U+6075 # +0x8C63 U+6176 # +0x8C64 U+6167 # +0x8C65 U+61A9 # +0x8C66 U+63B2 # +0x8C67 U+643A # +0x8C68 U+656C # +0x8C69 U+666F # +0x8C6A U+6842 # +0x8C6B U+6E13 # +0x8C6C U+7566 # +0x8C6D U+7A3D # +0x8C6E U+7CFB # +0x8C6F U+7D4C # +0x8C70 U+7D99 # +0x8C71 U+7E4B # +0x8C72 U+7F6B # +0x8C73 U+830E # +0x8C74 U+834A # +0x8C75 U+86CD # +0x8C76 U+8A08 # +0x8C77 U+8A63 # +0x8C78 U+8B66 # +0x8C79 U+8EFD # +0x8C7A U+981A # +0x8C7B U+9D8F # +0x8C7C U+82B8 # +0x8C7D U+8FCE # +0x8C7E U+9BE8 # +0x8C80 U+5287 # +0x8C81 U+621F # +0x8C82 U+6483 # +0x8C83 U+6FC0 # +0x8C84 U+9699 # +0x8C85 U+6841 # +0x8C86 U+5091 # +0x8C87 U+6B20 # +0x8C88 U+6C7A # +0x8C89 U+6F54 # +0x8C8A U+7A74 # +0x8C8B U+7D50 # +0x8C8C U+8840 # +0x8C8D U+8A23 # +0x8C8E U+6708 # +0x8C8F U+4EF6 # +0x8C90 U+5039 # +0x8C91 U+5026 # +0x8C92 U+5065 # +0x8C93 U+517C # +0x8C94 U+5238 # +0x8C95 U+5263 # +0x8C96 U+55A7 # +0x8C97 U+570F # +0x8C98 U+5805 # +0x8C99 U+5ACC # +0x8C9A U+5EFA # +0x8C9B U+61B2 # +0x8C9C U+61F8 # +0x8C9D U+62F3 # +0x8C9E U+6372 # +0x8C9F U+691C # +0x8CA0 U+6A29 # +0x8CA1 U+727D # +0x8CA2 U+72AC # +0x8CA3 U+732E # +0x8CA4 U+7814 # +0x8CA5 U+786F # +0x8CA6 U+7D79 # +0x8CA7 U+770C # +0x8CA8 U+80A9 # +0x8CA9 U+898B # +0x8CAA U+8B19 # +0x8CAB U+8CE2 # +0x8CAC U+8ED2 # +0x8CAD U+9063 # +0x8CAE U+9375 # +0x8CAF U+967A # +0x8CB0 U+9855 # +0x8CB1 U+9A13 # +0x8CB2 U+9E78 # +0x8CB3 U+5143 # +0x8CB4 U+539F # +0x8CB5 U+53B3 # +0x8CB6 U+5E7B # +0x8CB7 U+5F26 # +0x8CB8 U+6E1B # +0x8CB9 U+6E90 # +0x8CBA U+7384 # +0x8CBB U+73FE # +0x8CBC U+7D43 # +0x8CBD U+8237 # +0x8CBE U+8A00 # +0x8CBF U+8AFA # +0x8CC0 U+9650 # +0x8CC1 U+4E4E # +0x8CC2 U+500B # +0x8CC3 U+53E4 # +0x8CC4 U+547C # +0x8CC5 U+56FA # +0x8CC6 U+59D1 # +0x8CC7 U+5B64 # +0x8CC8 U+5DF1 # +0x8CC9 U+5EAB # +0x8CCA U+5F27 # +0x8CCB U+6238 # +0x8CCC U+6545 # +0x8CCD U+67AF # +0x8CCE U+6E56 # +0x8CCF U+72D0 # +0x8CD0 U+7CCA # +0x8CD1 U+88B4 # +0x8CD2 U+80A1 # +0x8CD3 U+80E1 # +0x8CD4 U+83F0 # +0x8CD5 U+864E # +0x8CD6 U+8A87 # +0x8CD7 U+8DE8 # +0x8CD8 U+9237 # +0x8CD9 U+96C7 # +0x8CDA U+9867 # +0x8CDB U+9F13 # +0x8CDC U+4E94 # +0x8CDD U+4E92 # +0x8CDE U+4F0D # +0x8CDF U+5348 # +0x8CE0 U+5449 # +0x8CE1 U+543E # +0x8CE2 U+5A2F # +0x8CE3 U+5F8C # +0x8CE4 U+5FA1 # +0x8CE5 U+609F # +0x8CE6 U+68A7 # +0x8CE7 U+6A8E # +0x8CE8 U+745A # +0x8CE9 U+7881 # +0x8CEA U+8A9E # +0x8CEB U+8AA4 # +0x8CEC U+8B77 # +0x8CED U+9190 # +0x8CEE U+4E5E # +0x8CEF U+9BC9 # +0x8CF0 U+4EA4 # +0x8CF1 U+4F7C # +0x8CF2 U+4FAF # +0x8CF3 U+5019 # +0x8CF4 U+5016 # +0x8CF5 U+5149 # +0x8CF6 U+516C # +0x8CF7 U+529F # +0x8CF8 U+52B9 # +0x8CF9 U+52FE # +0x8CFA U+539A # +0x8CFB U+53E3 # +0x8CFC U+5411 # +0x8D40 U+540E # +0x8D41 U+5589 # +0x8D42 U+5751 # +0x8D43 U+57A2 # +0x8D44 U+597D # +0x8D45 U+5B54 # +0x8D46 U+5B5D # +0x8D47 U+5B8F # +0x8D48 U+5DE5 # +0x8D49 U+5DE7 # +0x8D4A U+5DF7 # +0x8D4B U+5E78 # +0x8D4C U+5E83 # +0x8D4D U+5E9A # +0x8D4E U+5EB7 # +0x8D4F U+5F18 # +0x8D50 U+6052 # +0x8D51 U+614C # +0x8D52 U+6297 # +0x8D53 U+62D8 # +0x8D54 U+63A7 # +0x8D55 U+653B # +0x8D56 U+6602 # +0x8D57 U+6643 # +0x8D58 U+66F4 # +0x8D59 U+676D # +0x8D5A U+6821 # +0x8D5B U+6897 # +0x8D5C U+69CB # +0x8D5D U+6C5F # +0x8D5E U+6D2A # +0x8D5F U+6D69 # +0x8D60 U+6E2F # +0x8D61 U+6E9D # +0x8D62 U+7532 # +0x8D63 U+7687 # +0x8D64 U+786C # +0x8D65 U+7A3F # +0x8D66 U+7CE0 # +0x8D67 U+7D05 # +0x8D68 U+7D18 # +0x8D69 U+7D5E # +0x8D6A U+7DB1 # +0x8D6B U+8015 # +0x8D6C U+8003 # +0x8D6D U+80AF # +0x8D6E U+80B1 # +0x8D6F U+8154 # +0x8D70 U+818F # +0x8D71 U+822A # +0x8D72 U+8352 # +0x8D73 U+884C # +0x8D74 U+8861 # +0x8D75 U+8B1B # +0x8D76 U+8CA2 # +0x8D77 U+8CFC # +0x8D78 U+90CA # +0x8D79 U+9175 # +0x8D7A U+9271 # +0x8D7B U+783F # +0x8D7C U+92FC # +0x8D7D U+95A4 # +0x8D7E U+964D # +0x8D80 U+9805 # +0x8D81 U+9999 # +0x8D82 U+9AD8 # +0x8D83 U+9D3B # +0x8D84 U+525B # +0x8D85 U+52AB # +0x8D86 U+53F7 # +0x8D87 U+5408 # +0x8D88 U+58D5 # +0x8D89 U+62F7 # +0x8D8A U+6FE0 # +0x8D8B U+8C6A # +0x8D8C U+8F5F # +0x8D8D U+9EB9 # +0x8D8E U+514B # +0x8D8F U+523B # +0x8D90 U+544A # +0x8D91 U+56FD # +0x8D92 U+7A40 # +0x8D93 U+9177 # +0x8D94 U+9D60 # +0x8D95 U+9ED2 # +0x8D96 U+7344 # +0x8D97 U+6F09 # +0x8D98 U+8170 # +0x8D99 U+7511 # +0x8D9A U+5FFD # +0x8D9B U+60DA # +0x8D9C U+9AA8 # +0x8D9D U+72DB # +0x8D9E U+8FBC # +0x8D9F U+6B64 # +0x8DA0 U+9803 # +0x8DA1 U+4ECA # +0x8DA2 U+56F0 # +0x8DA3 U+5764 # +0x8DA4 U+58BE # +0x8DA5 U+5A5A # +0x8DA6 U+6068 # +0x8DA7 U+61C7 # +0x8DA8 U+660F # +0x8DA9 U+6606 # +0x8DAA U+6839 # +0x8DAB U+68B1 # +0x8DAC U+6DF7 # +0x8DAD U+75D5 # +0x8DAE U+7D3A # +0x8DAF U+826E # +0x8DB0 U+9B42 # +0x8DB1 U+4E9B # +0x8DB2 U+4F50 # +0x8DB3 U+53C9 # +0x8DB4 U+5506 # +0x8DB5 U+5D6F # +0x8DB6 U+5DE6 # +0x8DB7 U+5DEE # +0x8DB8 U+67FB # +0x8DB9 U+6C99 # +0x8DBA U+7473 # +0x8DBB U+7802 # +0x8DBC U+8A50 # +0x8DBD U+9396 # +0x8DBE U+88DF # +0x8DBF U+5750 # +0x8DC0 U+5EA7 # +0x8DC1 U+632B # +0x8DC2 U+50B5 # +0x8DC3 U+50AC # +0x8DC4 U+518D # +0x8DC5 U+6700 # +0x8DC6 U+54C9 # +0x8DC7 U+585E # +0x8DC8 U+59BB # +0x8DC9 U+5BB0 # +0x8DCA U+5F69 # +0x8DCB U+624D # +0x8DCC U+63A1 # +0x8DCD U+683D # +0x8DCE U+6B73 # +0x8DCF U+6E08 # +0x8DD0 U+707D # +0x8DD1 U+91C7 # +0x8DD2 U+7280 # +0x8DD3 U+7815 # +0x8DD4 U+7826 # +0x8DD5 U+796D # +0x8DD6 U+658E # +0x8DD7 U+7D30 # +0x8DD8 U+83DC # +0x8DD9 U+88C1 # +0x8DDA U+8F09 # +0x8DDB U+969B # +0x8DDC U+5264 # +0x8DDD U+5728 # +0x8DDE U+6750 # +0x8DDF U+7F6A # +0x8DE0 U+8CA1 # +0x8DE1 U+51B4 # +0x8DE2 U+5742 # +0x8DE3 U+962A # +0x8DE4 U+583A # +0x8DE5 U+698A # +0x8DE6 U+80B4 # +0x8DE7 U+54B2 # +0x8DE8 U+5D0E # +0x8DE9 U+57FC # +0x8DEA U+7895 # +0x8DEB U+9DFA # +0x8DEC U+4F5C # +0x8DED U+524A # +0x8DEE U+548B # +0x8DEF U+643E # +0x8DF0 U+6628 # +0x8DF1 U+6714 # +0x8DF2 U+67F5 # +0x8DF3 U+7A84 # +0x8DF4 U+7B56 # +0x8DF5 U+7D22 # +0x8DF6 U+932F # +0x8DF7 U+685C # +0x8DF8 U+9BAD # +0x8DF9 U+7B39 # +0x8DFA U+5319 # +0x8DFB U+518A # +0x8DFC U+5237 # +0x8E40 U+5BDF # +0x8E41 U+62F6 # +0x8E42 U+64AE # +0x8E43 U+64E6 # +0x8E44 U+672D # +0x8E45 U+6BBA # +0x8E46 U+85A9 # +0x8E47 U+96D1 # +0x8E48 U+7690 # +0x8E49 U+9BD6 # +0x8E4A U+634C # +0x8E4B U+9306 # +0x8E4C U+9BAB # +0x8E4D U+76BF # +0x8E4E U+6652 # +0x8E4F U+4E09 # +0x8E50 U+5098 # +0x8E51 U+53C2 # +0x8E52 U+5C71 # +0x8E53 U+60E8 # +0x8E54 U+6492 # +0x8E55 U+6563 # +0x8E56 U+685F # +0x8E57 U+71E6 # +0x8E58 U+73CA # +0x8E59 U+7523 # +0x8E5A U+7B97 # +0x8E5B U+7E82 # +0x8E5C U+8695 # +0x8E5D U+8B83 # +0x8E5E U+8CDB # +0x8E5F U+9178 # +0x8E60 U+9910 # +0x8E61 U+65AC # +0x8E62 U+66AB # +0x8E63 U+6B8B # +0x8E64 U+4ED5 # +0x8E65 U+4ED4 # +0x8E66 U+4F3A # +0x8E67 U+4F7F # +0x8E68 U+523A # +0x8E69 U+53F8 # +0x8E6A U+53F2 # +0x8E6B U+55E3 # +0x8E6C U+56DB # +0x8E6D U+58EB # +0x8E6E U+59CB # +0x8E6F U+59C9 # +0x8E70 U+59FF # +0x8E71 U+5B50 # +0x8E72 U+5C4D # +0x8E73 U+5E02 # +0x8E74 U+5E2B # +0x8E75 U+5FD7 # +0x8E76 U+601D # +0x8E77 U+6307 # +0x8E78 U+652F # +0x8E79 U+5B5C # +0x8E7A U+65AF # +0x8E7B U+65BD # +0x8E7C U+65E8 # +0x8E7D U+679D # +0x8E7E U+6B62 # +0x8E80 U+6B7B # +0x8E81 U+6C0F # +0x8E82 U+7345 # +0x8E83 U+7949 # +0x8E84 U+79C1 # +0x8E85 U+7CF8 # +0x8E86 U+7D19 # +0x8E87 U+7D2B # +0x8E88 U+80A2 # +0x8E89 U+8102 # +0x8E8A U+81F3 # +0x8E8B U+8996 # +0x8E8C U+8A5E # +0x8E8D U+8A69 # +0x8E8E U+8A66 # +0x8E8F U+8A8C # +0x8E90 U+8AEE # +0x8E91 U+8CC7 # +0x8E92 U+8CDC # +0x8E93 U+96CC # +0x8E94 U+98FC # +0x8E95 U+6B6F # +0x8E96 U+4E8B # +0x8E97 U+4F3C # +0x8E98 U+4F8D # +0x8E99 U+5150 # +0x8E9A U+5B57 # +0x8E9B U+5BFA # +0x8E9C U+6148 # +0x8E9D U+6301 # +0x8E9E U+6642 # +0x8E9F U+6B21 # +0x8EA0 U+6ECB # +0x8EA1 U+6CBB # +0x8EA2 U+723E # +0x8EA3 U+74BD # +0x8EA4 U+75D4 # +0x8EA5 U+78C1 # +0x8EA6 U+793A # +0x8EA7 U+800C # +0x8EA8 U+8033 # +0x8EA9 U+81EA # +0x8EAA U+8494 # +0x8EAB U+8F9E # +0x8EAC U+6C50 # +0x8EAD U+9E7F # +0x8EAE U+5F0F # +0x8EAF U+8B58 # +0x8EB0 U+9D2B # +0x8EB1 U+7AFA # +0x8EB2 U+8EF8 # +0x8EB3 U+5B8D # +0x8EB4 U+96EB # +0x8EB5 U+4E03 # +0x8EB6 U+53F1 # +0x8EB7 U+57F7 # +0x8EB8 U+5931 # +0x8EB9 U+5AC9 # +0x8EBA U+5BA4 # +0x8EBB U+6089 # +0x8EBC U+6E7F # +0x8EBD U+6F06 # +0x8EBE U+75BE # +0x8EBF U+8CEA # +0x8EC0 U+5B9F # +0x8EC1 U+8500 # +0x8EC2 U+7BE0 # +0x8EC3 U+5072 # +0x8EC4 U+67F4 # +0x8EC5 U+829D # +0x8EC6 U+5C61 # +0x8EC7 U+854A # +0x8EC8 U+7E1E # +0x8EC9 U+820E # +0x8ECA U+5199 # +0x8ECB U+5C04 # +0x8ECC U+6368 # +0x8ECD U+8D66 # +0x8ECE U+659C # +0x8ECF U+716E # +0x8ED0 U+793E # +0x8ED1 U+7D17 # +0x8ED2 U+8005 # +0x8ED3 U+8B1D # +0x8ED4 U+8ECA # +0x8ED5 U+906E # +0x8ED6 U+86C7 # +0x8ED7 U+90AA # +0x8ED8 U+501F # +0x8ED9 U+52FA # +0x8EDA U+5C3A # +0x8EDB U+6753 # +0x8EDC U+707C # +0x8EDD U+7235 # +0x8EDE U+914C # +0x8EDF U+91C8 # +0x8EE0 U+932B # +0x8EE1 U+82E5 # +0x8EE2 U+5BC2 # +0x8EE3 U+5F31 # +0x8EE4 U+60F9 # +0x8EE5 U+4E3B # +0x8EE6 U+53D6 # +0x8EE7 U+5B88 # +0x8EE8 U+624B # +0x8EE9 U+6731 # +0x8EEA U+6B8A # +0x8EEB U+72E9 # +0x8EEC U+73E0 # +0x8EED U+7A2E # +0x8EEE U+816B # +0x8EEF U+8DA3 # +0x8EF0 U+9152 # +0x8EF1 U+9996 # +0x8EF2 U+5112 # +0x8EF3 U+53D7 # +0x8EF4 U+546A # +0x8EF5 U+5BFF # +0x8EF6 U+6388 # +0x8EF7 U+6A39 # +0x8EF8 U+7DAC # +0x8EF9 U+9700 # +0x8EFA U+56DA # +0x8EFB U+53CE # +0x8EFC U+5468 # +0x8F40 U+5B97 # +0x8F41 U+5C31 # +0x8F42 U+5DDE # +0x8F43 U+4FEE # +0x8F44 U+6101 # +0x8F45 U+62FE # +0x8F46 U+6D32 # +0x8F47 U+79C0 # +0x8F48 U+79CB # +0x8F49 U+7D42 # +0x8F4A U+7E4D # +0x8F4B U+7FD2 # +0x8F4C U+81ED # +0x8F4D U+821F # +0x8F4E U+8490 # +0x8F4F U+8846 # +0x8F50 U+8972 # +0x8F51 U+8B90 # +0x8F52 U+8E74 # +0x8F53 U+8F2F # +0x8F54 U+9031 # +0x8F55 U+914B # +0x8F56 U+916C # +0x8F57 U+96C6 # +0x8F58 U+919C # +0x8F59 U+4EC0 # +0x8F5A U+4F4F # +0x8F5B U+5145 # +0x8F5C U+5341 # +0x8F5D U+5F93 # +0x8F5E U+620E # +0x8F5F U+67D4 # +0x8F60 U+6C41 # +0x8F61 U+6E0B # +0x8F62 U+7363 # +0x8F63 U+7E26 # +0x8F64 U+91CD # +0x8F65 U+9283 # +0x8F66 U+53D4 # +0x8F67 U+5919 # +0x8F68 U+5BBF # +0x8F69 U+6DD1 # +0x8F6A U+795D # +0x8F6B U+7E2E # +0x8F6C U+7C9B # +0x8F6D U+587E # +0x8F6E U+719F # +0x8F6F U+51FA # +0x8F70 U+8853 # +0x8F71 U+8FF0 # +0x8F72 U+4FCA # +0x8F73 U+5CFB # +0x8F74 U+6625 # +0x8F75 U+77AC # +0x8F76 U+7AE3 # +0x8F77 U+821C # +0x8F78 U+99FF # +0x8F79 U+51C6 # +0x8F7A U+5FAA # +0x8F7B U+65EC # +0x8F7C U+696F # +0x8F7D U+6B89 # +0x8F7E U+6DF3 # +0x8F80 U+6E96 # +0x8F81 U+6F64 # +0x8F82 U+76FE # +0x8F83 U+7D14 # +0x8F84 U+5DE1 # +0x8F85 U+9075 # +0x8F86 U+9187 # +0x8F87 U+9806 # +0x8F88 U+51E6 # +0x8F89 U+521D # +0x8F8A U+6240 # +0x8F8B U+6691 # +0x8F8C U+66D9 # +0x8F8D U+6E1A # +0x8F8E U+5EB6 # +0x8F8F U+7DD2 # +0x8F90 U+7F72 # +0x8F91 U+66F8 # +0x8F92 U+85AF # +0x8F93 U+85F7 # +0x8F94 U+8AF8 # +0x8F95 U+52A9 # +0x8F96 U+53D9 # +0x8F97 U+5973 # +0x8F98 U+5E8F # +0x8F99 U+5F90 # +0x8F9A U+6055 # +0x8F9B U+92E4 # +0x8F9C U+9664 # +0x8F9D U+50B7 # +0x8F9E U+511F # +0x8F9F U+52DD # +0x8FA0 U+5320 # +0x8FA1 U+5347 # +0x8FA2 U+53EC # +0x8FA3 U+54E8 # +0x8FA4 U+5546 # +0x8FA5 U+5531 # +0x8FA6 U+5617 # +0x8FA7 U+5968 # +0x8FA8 U+59BE # +0x8FA9 U+5A3C # +0x8FAA U+5BB5 # +0x8FAB U+5C06 # +0x8FAC U+5C0F # +0x8FAD U+5C11 # +0x8FAE U+5C1A # +0x8FAF U+5E84 # +0x8FB0 U+5E8A # +0x8FB1 U+5EE0 # +0x8FB2 U+5F70 # +0x8FB3 U+627F # +0x8FB4 U+6284 # +0x8FB5 U+62DB # +0x8FB6 U+638C # +0x8FB7 U+6377 # +0x8FB8 U+6607 # +0x8FB9 U+660C # +0x8FBA U+662D # +0x8FBB U+6676 # +0x8FBC U+677E # +0x8FBD U+68A2 # +0x8FBE U+6A1F # +0x8FBF U+6A35 # +0x8FC0 U+6CBC # +0x8FC1 U+6D88 # +0x8FC2 U+6E09 # +0x8FC3 U+6E58 # +0x8FC4 U+713C # +0x8FC5 U+7126 # +0x8FC6 U+7167 # +0x8FC7 U+75C7 # +0x8FC8 U+7701 # +0x8FC9 U+785D # +0x8FCA U+7901 # +0x8FCB U+7965 # +0x8FCC U+79F0 # +0x8FCD U+7AE0 # +0x8FCE U+7B11 # +0x8FCF U+7CA7 # +0x8FD0 U+7D39 # +0x8FD1 U+8096 # +0x8FD2 U+83D6 # +0x8FD3 U+848B # +0x8FD4 U+8549 # +0x8FD5 U+885D # +0x8FD6 U+88F3 # +0x8FD7 U+8A1F # +0x8FD8 U+8A3C # +0x8FD9 U+8A54 # +0x8FDA U+8A73 # +0x8FDB U+8C61 # +0x8FDC U+8CDE # +0x8FDD U+91A4 # +0x8FDE U+9266 # +0x8FDF U+937E # +0x8FE0 U+9418 # +0x8FE1 U+969C # +0x8FE2 U+9798 # +0x8FE3 U+4E0A # +0x8FE4 U+4E08 # +0x8FE5 U+4E1E # +0x8FE6 U+4E57 # +0x8FE7 U+5197 # +0x8FE8 U+5270 # +0x8FE9 U+57CE # +0x8FEA U+5834 # +0x8FEB U+58CC # +0x8FEC U+5B22 # +0x8FED U+5E38 # +0x8FEE U+60C5 # +0x8FEF U+64FE # +0x8FF0 U+6761 # +0x8FF1 U+6756 # +0x8FF2 U+6D44 # +0x8FF3 U+72B6 # +0x8FF4 U+7573 # +0x8FF5 U+7A63 # +0x8FF6 U+84B8 # +0x8FF7 U+8B72 # +0x8FF8 U+91B8 # +0x8FF9 U+9320 # +0x8FFA U+5631 # +0x8FFB U+57F4 # +0x8FFC U+98FE # +0x9040 U+62ED # +0x9041 U+690D # +0x9042 U+6B96 # +0x9043 U+71ED # +0x9044 U+7E54 # +0x9045 U+8077 # +0x9046 U+8272 # +0x9047 U+89E6 # +0x9048 U+98DF # +0x9049 U+8755 # +0x904A U+8FB1 # +0x904B U+5C3B # +0x904C U+4F38 # +0x904D U+4FE1 # +0x904E U+4FB5 # +0x904F U+5507 # +0x9050 U+5A20 # +0x9051 U+5BDD # +0x9052 U+5BE9 # +0x9053 U+5FC3 # +0x9054 U+614E # +0x9055 U+632F # +0x9056 U+65B0 # +0x9057 U+664B # +0x9058 U+68EE # +0x9059 U+699B # +0x905A U+6D78 # +0x905B U+6DF1 # +0x905C U+7533 # +0x905D U+75B9 # +0x905E U+771F # +0x905F U+795E # +0x9060 U+79E6 # +0x9061 U+7D33 # +0x9062 U+81E3 # +0x9063 U+82AF # +0x9064 U+85AA # +0x9065 U+89AA # +0x9066 U+8A3A # +0x9067 U+8EAB # +0x9068 U+8F9B # +0x9069 U+9032 # +0x906A U+91DD # +0x906B U+9707 # +0x906C U+4EBA # +0x906D U+4EC1 # +0x906E U+5203 # +0x906F U+5875 # +0x9070 U+58EC # +0x9071 U+5C0B # +0x9072 U+751A # +0x9073 U+5C3D # +0x9074 U+814E # +0x9075 U+8A0A # +0x9076 U+8FC5 # +0x9077 U+9663 # +0x9078 U+976D # +0x9079 U+7B25 # +0x907A U+8ACF # +0x907B U+9808 # +0x907C U+9162 # +0x907D U+56F3 # +0x907E U+53A8 # +0x9080 U+9017 # +0x9081 U+5439 # +0x9082 U+5782 # +0x9083 U+5E25 # +0x9084 U+63A8 # +0x9085 U+6C34 # +0x9086 U+708A # +0x9087 U+7761 # +0x9088 U+7C8B # +0x9089 U+7FE0 # +0x908A U+8870 # +0x908B U+9042 # +0x908C U+9154 # +0x908D U+9310 # +0x908E U+9318 # +0x908F U+968F # +0x9090 U+745E # +0x9091 U+9AC4 # +0x9092 U+5D07 # +0x9093 U+5D69 # +0x9094 U+6570 # +0x9095 U+67A2 # +0x9096 U+8DA8 # +0x9097 U+96DB # +0x9098 U+636E # +0x9099 U+6749 # +0x909A U+6919 # +0x909B U+83C5 # +0x909C U+9817 # +0x909D U+96C0 # +0x909E U+88FE # +0x909F U+6F84 # +0x90A0 U+647A # +0x90A1 U+5BF8 # +0x90A2 U+4E16 # +0x90A3 U+702C # +0x90A4 U+755D # +0x90A5 U+662F # +0x90A6 U+51C4 # +0x90A7 U+5236 # +0x90A8 U+52E2 # +0x90A9 U+59D3 # +0x90AA U+5F81 # +0x90AB U+6027 # +0x90AC U+6210 # +0x90AD U+653F # +0x90AE U+6574 # +0x90AF U+661F # +0x90B0 U+6674 # +0x90B1 U+68F2 # +0x90B2 U+6816 # +0x90B3 U+6B63 # +0x90B4 U+6E05 # +0x90B5 U+7272 # +0x90B6 U+751F # +0x90B7 U+76DB # +0x90B8 U+7CBE # +0x90B9 U+8056 # +0x90BA U+58F0 # +0x90BB U+88FD # +0x90BC U+897F # +0x90BD U+8AA0 # +0x90BE U+8A93 # +0x90BF U+8ACB # +0x90C0 U+901D # +0x90C1 U+9192 # +0x90C2 U+9752 # +0x90C3 U+9759 # +0x90C4 U+6589 # +0x90C5 U+7A0E # +0x90C6 U+8106 # +0x90C7 U+96BB # +0x90C8 U+5E2D # +0x90C9 U+60DC # +0x90CA U+621A # +0x90CB U+65A5 # +0x90CC U+6614 # +0x90CD U+6790 # +0x90CE U+77F3 # +0x90CF U+7A4D # +0x90D0 U+7C4D # +0x90D1 U+7E3E # +0x90D2 U+810A # +0x90D3 U+8CAC # +0x90D4 U+8D64 # +0x90D5 U+8DE1 # +0x90D6 U+8E5F # +0x90D7 U+78A9 # +0x90D8 U+5207 # +0x90D9 U+62D9 # +0x90DA U+63A5 # +0x90DB U+6442 # +0x90DC U+6298 # +0x90DD U+8A2D # +0x90DE U+7A83 # +0x90DF U+7BC0 # +0x90E0 U+8AAC # +0x90E1 U+96EA # +0x90E2 U+7D76 # +0x90E3 U+820C # +0x90E4 U+8749 # +0x90E5 U+4ED9 # +0x90E6 U+5148 # +0x90E7 U+5343 # +0x90E8 U+5360 # +0x90E9 U+5BA3 # +0x90EA U+5C02 # +0x90EB U+5C16 # +0x90EC U+5DDD # +0x90ED U+6226 # +0x90EE U+6247 # +0x90EF U+64B0 # +0x90F0 U+6813 # +0x90F1 U+6834 # +0x90F2 U+6CC9 # +0x90F3 U+6D45 # +0x90F4 U+6D17 # +0x90F5 U+67D3 # +0x90F6 U+6F5C # +0x90F7 U+714E # +0x90F8 U+717D # +0x90F9 U+65CB # +0x90FA U+7A7F # +0x90FB U+7BAD # +0x90FC U+7DDA # +0x9140 U+7E4A # +0x9141 U+7FA8 # +0x9142 U+817A # +0x9143 U+821B # +0x9144 U+8239 # +0x9145 U+85A6 # +0x9146 U+8A6E # +0x9147 U+8CCE # +0x9148 U+8DF5 # +0x9149 U+9078 # +0x914A U+9077 # +0x914B U+92AD # +0x914C U+9291 # +0x914D U+9583 # +0x914E U+9BAE # +0x914F U+524D # +0x9150 U+5584 # +0x9151 U+6F38 # +0x9152 U+7136 # +0x9153 U+5168 # +0x9154 U+7985 # +0x9155 U+7E55 # +0x9156 U+81B3 # +0x9157 U+7CCE # +0x9158 U+564C # +0x9159 U+5851 # +0x915A U+5CA8 # +0x915B U+63AA # +0x915C U+66FE # +0x915D U+66FD # +0x915E U+695A # +0x915F U+72D9 # +0x9160 U+758F # +0x9161 U+758E # +0x9162 U+790E # +0x9163 U+7956 # +0x9164 U+79DF # +0x9165 U+7C97 # +0x9166 U+7D20 # +0x9167 U+7D44 # +0x9168 U+8607 # +0x9169 U+8A34 # +0x916A U+963B # +0x916B U+9061 # +0x916C U+9F20 # +0x916D U+50E7 # +0x916E U+5275 # +0x916F U+53CC # +0x9170 U+53E2 # +0x9171 U+5009 # +0x9172 U+55AA # +0x9173 U+58EE # +0x9174 U+594F # +0x9175 U+723D # +0x9176 U+5B8B # +0x9177 U+5C64 # +0x9178 U+531D # +0x9179 U+60E3 # +0x917A U+60F3 # +0x917B U+635C # +0x917C U+6383 # +0x917D U+633F # +0x917E U+63BB # +0x9180 U+64CD # +0x9181 U+65E9 # +0x9182 U+66F9 # +0x9183 U+5DE3 # +0x9184 U+69CD # +0x9185 U+69FD # +0x9186 U+6F15 # +0x9187 U+71E5 # +0x9188 U+4E89 # +0x9189 U+75E9 # +0x918A U+76F8 # +0x918B U+7A93 # +0x918C U+7CDF # +0x918D U+7DCF # +0x918E U+7D9C # +0x918F U+8061 # +0x9190 U+8349 # +0x9191 U+8358 # +0x9192 U+846C # +0x9193 U+84BC # +0x9194 U+85FB # +0x9195 U+88C5 # +0x9196 U+8D70 # +0x9197 U+9001 # +0x9198 U+906D # +0x9199 U+9397 # +0x919A U+971C # +0x919B U+9A12 # +0x919C U+50CF # +0x919D U+5897 # +0x919E U+618E # +0x919F U+81D3 # +0x91A0 U+8535 # +0x91A1 U+8D08 # +0x91A2 U+9020 # +0x91A3 U+4FC3 # +0x91A4 U+5074 # +0x91A5 U+5247 # +0x91A6 U+5373 # +0x91A7 U+606F # +0x91A8 U+6349 # +0x91A9 U+675F # +0x91AA U+6E2C # +0x91AB U+8DB3 # +0x91AC U+901F # +0x91AD U+4FD7 # +0x91AE U+5C5E # +0x91AF U+8CCA # +0x91B0 U+65CF # +0x91B1 U+7D9A # +0x91B2 U+5352 # +0x91B3 U+8896 # +0x91B4 U+5176 # +0x91B5 U+63C3 # +0x91B6 U+5B58 # +0x91B7 U+5B6B # +0x91B8 U+5C0A # +0x91B9 U+640D # +0x91BA U+6751 # +0x91BB U+905C # +0x91BC U+4ED6 # +0x91BD U+591A # +0x91BE U+592A # +0x91BF U+6C70 # +0x91C0 U+8A51 # +0x91C1 U+553E # +0x91C2 U+5815 # +0x91C3 U+59A5 # +0x91C4 U+60F0 # +0x91C5 U+6253 # +0x91C6 U+67C1 # +0x91C7 U+8235 # +0x91C8 U+6955 # +0x91C9 U+9640 # +0x91CA U+99C4 # +0x91CB U+9A28 # +0x91CC U+4F53 # +0x91CD U+5806 # +0x91CE U+5BFE # +0x91CF U+8010 # +0x91D0 U+5CB1 # +0x91D1 U+5E2F # +0x91D2 U+5F85 # +0x91D3 U+6020 # +0x91D4 U+614B # +0x91D5 U+6234 # +0x91D6 U+66FF # +0x91D7 U+6CF0 # +0x91D8 U+6EDE # +0x91D9 U+80CE # +0x91DA U+817F # +0x91DB U+82D4 # +0x91DC U+888B # +0x91DD U+8CB8 # +0x91DE U+9000 # +0x91DF U+902E # +0x91E0 U+968A # +0x91E1 U+9EDB # +0x91E2 U+9BDB # +0x91E3 U+4EE3 # +0x91E4 U+53F0 # +0x91E5 U+5927 # +0x91E6 U+7B2C # +0x91E7 U+918D # +0x91E8 U+984C # +0x91E9 U+9DF9 # +0x91EA U+6EDD # +0x91EB U+7027 # +0x91EC U+5353 # +0x91ED U+5544 # +0x91EE U+5B85 # +0x91EF U+6258 # +0x91F0 U+629E # +0x91F1 U+62D3 # +0x91F2 U+6CA2 # +0x91F3 U+6FEF # +0x91F4 U+7422 # +0x91F5 U+8A17 # +0x91F6 U+9438 # +0x91F7 U+6FC1 # +0x91F8 U+8AFE # +0x91F9 U+8338 # +0x91FA U+51E7 # +0x91FB U+86F8 # +0x91FC U+53EA # +0x9240 U+53E9 # +0x9241 U+4F46 # +0x9242 U+9054 # +0x9243 U+8FB0 # +0x9244 U+596A # +0x9245 U+8131 # +0x9246 U+5DFD # +0x9247 U+7AEA # +0x9248 U+8FBF # +0x9249 U+68DA # +0x924A U+8C37 # +0x924B U+72F8 # +0x924C U+9C48 # +0x924D U+6A3D # +0x924E U+8AB0 # +0x924F U+4E39 # +0x9250 U+5358 # +0x9251 U+5606 # +0x9252 U+5766 # +0x9253 U+62C5 # +0x9254 U+63A2 # +0x9255 U+65E6 # +0x9256 U+6B4E # +0x9257 U+6DE1 # +0x9258 U+6E5B # +0x9259 U+70AD # +0x925A U+77ED # +0x925B U+7AEF # +0x925C U+7BAA # +0x925D U+7DBB # +0x925E U+803D # +0x925F U+80C6 # +0x9260 U+86CB # +0x9261 U+8A95 # +0x9262 U+935B # +0x9263 U+56E3 # +0x9264 U+58C7 # +0x9265 U+5F3E # +0x9266 U+65AD # +0x9267 U+6696 # +0x9268 U+6A80 # +0x9269 U+6BB5 # +0x926A U+7537 # +0x926B U+8AC7 # +0x926C U+5024 # +0x926D U+77E5 # +0x926E U+5730 # +0x926F U+5F1B # +0x9270 U+6065 # +0x9271 U+667A # +0x9272 U+6C60 # +0x9273 U+75F4 # +0x9274 U+7A1A # +0x9275 U+7F6E # +0x9276 U+81F4 # +0x9277 U+8718 # +0x9278 U+9045 # +0x9279 U+99B3 # +0x927A U+7BC9 # +0x927B U+755C # +0x927C U+7AF9 # +0x927D U+7B51 # +0x927E U+84C4 # +0x9280 U+9010 # +0x9281 U+79E9 # +0x9282 U+7A92 # +0x9283 U+8336 # +0x9284 U+5AE1 # +0x9285 U+7740 # +0x9286 U+4E2D # +0x9287 U+4EF2 # +0x9288 U+5B99 # +0x9289 U+5FE0 # +0x928A U+62BD # +0x928B U+663C # +0x928C U+67F1 # +0x928D U+6CE8 # +0x928E U+866B # +0x928F U+8877 # +0x9290 U+8A3B # +0x9291 U+914E # +0x9292 U+92F3 # +0x9293 U+99D0 # +0x9294 U+6A17 # +0x9295 U+7026 # +0x9296 U+732A # +0x9297 U+82E7 # +0x9298 U+8457 # +0x9299 U+8CAF # +0x929A U+4E01 # +0x929B U+5146 # +0x929C U+51CB # +0x929D U+558B # +0x929E U+5BF5 # +0x929F U+5E16 # +0x92A0 U+5E33 # +0x92A1 U+5E81 # +0x92A2 U+5F14 # +0x92A3 U+5F35 # +0x92A4 U+5F6B # +0x92A5 U+5FB4 # +0x92A6 U+61F2 # +0x92A7 U+6311 # +0x92A8 U+66A2 # +0x92A9 U+671D # +0x92AA U+6F6E # +0x92AB U+7252 # +0x92AC U+753A # +0x92AD U+773A # +0x92AE U+8074 # +0x92AF U+8139 # +0x92B0 U+8178 # +0x92B1 U+8776 # +0x92B2 U+8ABF # +0x92B3 U+8ADC # +0x92B4 U+8D85 # +0x92B5 U+8DF3 # +0x92B6 U+929A # +0x92B7 U+9577 # +0x92B8 U+9802 # +0x92B9 U+9CE5 # +0x92BA U+52C5 # +0x92BB U+6357 # +0x92BC U+76F4 # +0x92BD U+6715 # +0x92BE U+6C88 # +0x92BF U+73CD # +0x92C0 U+8CC3 # +0x92C1 U+93AE # +0x92C2 U+9673 # +0x92C3 U+6D25 # +0x92C4 U+589C # +0x92C5 U+690E # +0x92C6 U+69CC # +0x92C7 U+8FFD # +0x92C8 U+939A # +0x92C9 U+75DB # +0x92CA U+901A # +0x92CB U+585A # +0x92CC U+6802 # +0x92CD U+63B4 # +0x92CE U+69FB # +0x92CF U+4F43 # +0x92D0 U+6F2C # +0x92D1 U+67D8 # +0x92D2 U+8FBB # +0x92D3 U+8526 # +0x92D4 U+7DB4 # +0x92D5 U+9354 # +0x92D6 U+693F # +0x92D7 U+6F70 # +0x92D8 U+576A # +0x92D9 U+58F7 # +0x92DA U+5B2C # +0x92DB U+7D2C # +0x92DC U+722A # +0x92DD U+540A # +0x92DE U+91E3 # +0x92DF U+9DB4 # +0x92E0 U+4EAD # +0x92E1 U+4F4E # +0x92E2 U+505C # +0x92E3 U+5075 # +0x92E4 U+5243 # +0x92E5 U+8C9E # +0x92E6 U+5448 # +0x92E7 U+5824 # +0x92E8 U+5B9A # +0x92E9 U+5E1D # +0x92EA U+5E95 # +0x92EB U+5EAD # +0x92EC U+5EF7 # +0x92ED U+5F1F # +0x92EE U+608C # +0x92EF U+62B5 # +0x92F0 U+633A # +0x92F1 U+63D0 # +0x92F2 U+68AF # +0x92F3 U+6C40 # +0x92F4 U+7887 # +0x92F5 U+798E # +0x92F6 U+7A0B # +0x92F7 U+7DE0 # +0x92F8 U+8247 # +0x92F9 U+8A02 # +0x92FA U+8AE6 # +0x92FB U+8E44 # +0x92FC U+9013 # +0x9340 U+90B8 # +0x9341 U+912D # +0x9342 U+91D8 # +0x9343 U+9F0E # +0x9344 U+6CE5 # +0x9345 U+6458 # +0x9346 U+64E2 # +0x9347 U+6575 # +0x9348 U+6EF4 # +0x9349 U+7684 # +0x934A U+7B1B # +0x934B U+9069 # +0x934C U+93D1 # +0x934D U+6EBA # +0x934E U+54F2 # +0x934F U+5FB9 # +0x9350 U+64A4 # +0x9351 U+8F4D # +0x9352 U+8FED # +0x9353 U+9244 # +0x9354 U+5178 # +0x9355 U+586B # +0x9356 U+5929 # +0x9357 U+5C55 # +0x9358 U+5E97 # +0x9359 U+6DFB # +0x935A U+7E8F # +0x935B U+751C # +0x935C U+8CBC # +0x935D U+8EE2 # +0x935E U+985B # +0x935F U+70B9 # +0x9360 U+4F1D # +0x9361 U+6BBF # +0x9362 U+6FB1 # +0x9363 U+7530 # +0x9364 U+96FB # +0x9365 U+514E # +0x9366 U+5410 # +0x9367 U+5835 # +0x9368 U+5857 # +0x9369 U+59AC # +0x936A U+5C60 # +0x936B U+5F92 # +0x936C U+6597 # +0x936D U+675C # +0x936E U+6E21 # +0x936F U+767B # +0x9370 U+83DF # +0x9371 U+8CED # +0x9372 U+9014 # +0x9373 U+90FD # +0x9374 U+934D # +0x9375 U+7825 # +0x9376 U+783A # +0x9377 U+52AA # +0x9378 U+5EA6 # +0x9379 U+571F # +0x937A U+5974 # +0x937B U+6012 # +0x937C U+5012 # +0x937D U+515A # +0x937E U+51AC # +0x9380 U+51CD # +0x9381 U+5200 # +0x9382 U+5510 # +0x9383 U+5854 # +0x9384 U+5858 # +0x9385 U+5957 # +0x9386 U+5B95 # +0x9387 U+5CF6 # +0x9388 U+5D8B # +0x9389 U+60BC # +0x938A U+6295 # +0x938B U+642D # +0x938C U+6771 # +0x938D U+6843 # +0x938E U+68BC # +0x938F U+68DF # +0x9390 U+76D7 # +0x9391 U+6DD8 # +0x9392 U+6E6F # +0x9393 U+6D9B # +0x9394 U+706F # +0x9395 U+71C8 # +0x9396 U+5F53 # +0x9397 U+75D8 # +0x9398 U+7977 # +0x9399 U+7B49 # +0x939A U+7B54 # +0x939B U+7B52 # +0x939C U+7CD6 # +0x939D U+7D71 # +0x939E U+5230 # +0x939F U+8463 # +0x93A0 U+8569 # +0x93A1 U+85E4 # +0x93A2 U+8A0E # +0x93A3 U+8B04 # +0x93A4 U+8C46 # +0x93A5 U+8E0F # +0x93A6 U+9003 # +0x93A7 U+900F # +0x93A8 U+9419 # +0x93A9 U+9676 # +0x93AA U+982D # +0x93AB U+9A30 # +0x93AC U+95D8 # +0x93AD U+50CD # +0x93AE U+52D5 # +0x93AF U+540C # +0x93B0 U+5802 # +0x93B1 U+5C0E # +0x93B2 U+61A7 # +0x93B3 U+649E # +0x93B4 U+6D1E # +0x93B5 U+77B3 # +0x93B6 U+7AE5 # +0x93B7 U+80F4 # +0x93B8 U+8404 # +0x93B9 U+9053 # +0x93BA U+9285 # +0x93BB U+5CE0 # +0x93BC U+9D07 # +0x93BD U+533F # +0x93BE U+5F97 # +0x93BF U+5FB3 # +0x93C0 U+6D9C # +0x93C1 U+7279 # +0x93C2 U+7763 # +0x93C3 U+79BF # +0x93C4 U+7BE4 # +0x93C5 U+6BD2 # +0x93C6 U+72EC # +0x93C7 U+8AAD # +0x93C8 U+6803 # +0x93C9 U+6A61 # +0x93CA U+51F8 # +0x93CB U+7A81 # +0x93CC U+6934 # +0x93CD U+5C4A # +0x93CE U+9CF6 # +0x93CF U+82EB # +0x93D0 U+5BC5 # +0x93D1 U+9149 # +0x93D2 U+701E # +0x93D3 U+5678 # +0x93D4 U+5C6F # +0x93D5 U+60C7 # +0x93D6 U+6566 # +0x93D7 U+6C8C # +0x93D8 U+8C5A # +0x93D9 U+9041 # +0x93DA U+9813 # +0x93DB U+5451 # +0x93DC U+66C7 # +0x93DD U+920D # +0x93DE U+5948 # +0x93DF U+90A3 # +0x93E0 U+5185 # +0x93E1 U+4E4D # +0x93E2 U+51EA # +0x93E3 U+8599 # +0x93E4 U+8B0E # +0x93E5 U+7058 # +0x93E6 U+637A # +0x93E7 U+934B # +0x93E8 U+6962 # +0x93E9 U+99B4 # +0x93EA U+7E04 # +0x93EB U+7577 # +0x93EC U+5357 # +0x93ED U+6960 # +0x93EE U+8EDF # +0x93EF U+96E3 # +0x93F0 U+6C5D # +0x93F1 U+4E8C # +0x93F2 U+5C3C # +0x93F3 U+5F10 # +0x93F4 U+8FE9 # +0x93F5 U+5302 # +0x93F6 U+8CD1 # +0x93F7 U+8089 # +0x93F8 U+8679 # +0x93F9 U+5EFF # +0x93FA U+65E5 # +0x93FB U+4E73 # +0x93FC U+5165 # +0x9440 U+5982 # +0x9441 U+5C3F # +0x9442 U+97EE # +0x9443 U+4EFB # +0x9444 U+598A # +0x9445 U+5FCD # +0x9446 U+8A8D # +0x9447 U+6FE1 # +0x9448 U+79B0 # +0x9449 U+7962 # +0x944A U+5BE7 # +0x944B U+8471 # +0x944C U+732B # +0x944D U+71B1 # +0x944E U+5E74 # +0x944F U+5FF5 # +0x9450 U+637B # +0x9451 U+649A # +0x9452 U+71C3 # +0x9453 U+7C98 # +0x9454 U+4E43 # +0x9455 U+5EFC # +0x9456 U+4E4B # +0x9457 U+57DC # +0x9458 U+56A2 # +0x9459 U+60A9 # +0x945A U+6FC3 # +0x945B U+7D0D # +0x945C U+80FD # +0x945D U+8133 # +0x945E U+81BF # +0x945F U+8FB2 # +0x9460 U+8997 # +0x9461 U+86A4 # +0x9462 U+5DF4 # +0x9463 U+628A # +0x9464 U+64AD # +0x9465 U+8987 # +0x9466 U+6777 # +0x9467 U+6CE2 # +0x9468 U+6D3E # +0x9469 U+7436 # +0x946A U+7834 # +0x946B U+5A46 # +0x946C U+7F75 # +0x946D U+82AD # +0x946E U+99AC # +0x946F U+4FF3 # +0x9470 U+5EC3 # +0x9471 U+62DD # +0x9472 U+6392 # +0x9473 U+6557 # +0x9474 U+676F # +0x9475 U+76C3 # +0x9476 U+724C # +0x9477 U+80CC # +0x9478 U+80BA # +0x9479 U+8F29 # +0x947A U+914D # +0x947B U+500D # +0x947C U+57F9 # +0x947D U+5A92 # +0x947E U+6885 # +0x9480 U+6973 # +0x9481 U+7164 # +0x9482 U+72FD # +0x9483 U+8CB7 # +0x9484 U+58F2 # +0x9485 U+8CE0 # +0x9486 U+966A # +0x9487 U+9019 # +0x9488 U+877F # +0x9489 U+79E4 # +0x948A U+77E7 # +0x948B U+8429 # +0x948C U+4F2F # +0x948D U+5265 # +0x948E U+535A # +0x948F U+62CD # +0x9490 U+67CF # +0x9491 U+6CCA # +0x9492 U+767D # +0x9493 U+7B94 # +0x9494 U+7C95 # +0x9495 U+8236 # +0x9496 U+8584 # +0x9497 U+8FEB # +0x9498 U+66DD # +0x9499 U+6F20 # +0x949A U+7206 # +0x949B U+7E1B # +0x949C U+83AB # +0x949D U+99C1 # +0x949E U+9EA6 # +0x949F U+51FD # +0x94A0 U+7BB1 # +0x94A1 U+7872 # +0x94A2 U+7BB8 # +0x94A3 U+8087 # +0x94A4 U+7B48 # +0x94A5 U+6AE8 # +0x94A6 U+5E61 # +0x94A7 U+808C # +0x94A8 U+7551 # +0x94A9 U+7560 # +0x94AA U+516B # +0x94AB U+9262 # +0x94AC U+6E8C # +0x94AD U+767A # +0x94AE U+9197 # +0x94AF U+9AEA # +0x94B0 U+4F10 # +0x94B1 U+7F70 # +0x94B2 U+629C # +0x94B3 U+7B4F # +0x94B4 U+95A5 # +0x94B5 U+9CE9 # +0x94B6 U+567A # +0x94B7 U+5859 # +0x94B8 U+86E4 # +0x94B9 U+96BC # +0x94BA U+4F34 # +0x94BB U+5224 # +0x94BC U+534A # +0x94BD U+53CD # +0x94BE U+53DB # +0x94BF U+5E06 # +0x94C0 U+642C # +0x94C1 U+6591 # +0x94C2 U+677F # +0x94C3 U+6C3E # +0x94C4 U+6C4E # +0x94C5 U+7248 # +0x94C6 U+72AF # +0x94C7 U+73ED # +0x94C8 U+7554 # +0x94C9 U+7E41 # +0x94CA U+822C # +0x94CB U+85E9 # +0x94CC U+8CA9 # +0x94CD U+7BC4 # +0x94CE U+91C6 # +0x94CF U+7169 # +0x94D0 U+9812 # +0x94D1 U+98EF # +0x94D2 U+633D # +0x94D3 U+6669 # +0x94D4 U+756A # +0x94D5 U+76E4 # +0x94D6 U+78D0 # +0x94D7 U+8543 # +0x94D8 U+86EE # +0x94D9 U+532A # +0x94DA U+5351 # +0x94DB U+5426 # +0x94DC U+5983 # +0x94DD U+5E87 # +0x94DE U+5F7C # +0x94DF U+60B2 # +0x94E0 U+6249 # +0x94E1 U+6279 # +0x94E2 U+62AB # +0x94E3 U+6590 # +0x94E4 U+6BD4 # +0x94E5 U+6CCC # +0x94E6 U+75B2 # +0x94E7 U+76AE # +0x94E8 U+7891 # +0x94E9 U+79D8 # +0x94EA U+7DCB # +0x94EB U+7F77 # +0x94EC U+80A5 # +0x94ED U+88AB # +0x94EE U+8AB9 # +0x94EF U+8CBB # +0x94F0 U+907F # +0x94F1 U+975E # +0x94F2 U+98DB # +0x94F3 U+6A0B # +0x94F4 U+7C38 # +0x94F5 U+5099 # +0x94F6 U+5C3E # +0x94F7 U+5FAE # +0x94F8 U+6787 # +0x94F9 U+6BD8 # +0x94FA U+7435 # +0x94FB U+7709 # +0x94FC U+7F8E # +0x9540 U+9F3B # +0x9541 U+67CA # +0x9542 U+7A17 # +0x9543 U+5339 # +0x9544 U+758B # +0x9545 U+9AED # +0x9546 U+5F66 # +0x9547 U+819D # +0x9548 U+83F1 # +0x9549 U+8098 # +0x954A U+5F3C # +0x954B U+5FC5 # +0x954C U+7562 # +0x954D U+7B46 # +0x954E U+903C # +0x954F U+6867 # +0x9550 U+59EB # +0x9551 U+5A9B # +0x9552 U+7D10 # +0x9553 U+767E # +0x9554 U+8B2C # +0x9555 U+4FF5 # +0x9556 U+5F6A # +0x9557 U+6A19 # +0x9558 U+6C37 # +0x9559 U+6F02 # +0x955A U+74E2 # +0x955B U+7968 # +0x955C U+8868 # +0x955D U+8A55 # +0x955E U+8C79 # +0x955F U+5EDF # +0x9560 U+63CF # +0x9561 U+75C5 # +0x9562 U+79D2 # +0x9563 U+82D7 # +0x9564 U+9328 # +0x9565 U+92F2 # +0x9566 U+849C # +0x9567 U+86ED # +0x9568 U+9C2D # +0x9569 U+54C1 # +0x956A U+5F6C # +0x956B U+658C # +0x956C U+6D5C # +0x956D U+7015 # +0x956E U+8CA7 # +0x956F U+8CD3 # +0x9570 U+983B # +0x9571 U+654F # +0x9572 U+74F6 # +0x9573 U+4E0D # +0x9574 U+4ED8 # +0x9575 U+57E0 # +0x9576 U+592B # +0x9577 U+5A66 # +0x9578 U+5BCC # +0x9579 U+51A8 # +0x957A U+5E03 # +0x957B U+5E9C # +0x957C U+6016 # +0x957D U+6276 # +0x957E U+6577 # +0x9580 U+65A7 # +0x9581 U+666E # +0x9582 U+6D6E # +0x9583 U+7236 # +0x9584 U+7B26 # +0x9585 U+8150 # +0x9586 U+819A # +0x9587 U+8299 # +0x9588 U+8B5C # +0x9589 U+8CA0 # +0x958A U+8CE6 # +0x958B U+8D74 # +0x958C U+961C # +0x958D U+9644 # +0x958E U+4FAE # +0x958F U+64AB # +0x9590 U+6B66 # +0x9591 U+821E # +0x9592 U+8461 # +0x9593 U+856A # +0x9594 U+90E8 # +0x9595 U+5C01 # +0x9596 U+6953 # +0x9597 U+98A8 # +0x9598 U+847A # +0x9599 U+8557 # +0x959A U+4F0F # +0x959B U+526F # +0x959C U+5FA9 # +0x959D U+5E45 # +0x959E U+670D # +0x959F U+798F # +0x95A0 U+8179 # +0x95A1 U+8907 # +0x95A2 U+8986 # +0x95A3 U+6DF5 # +0x95A4 U+5F17 # +0x95A5 U+6255 # +0x95A6 U+6CB8 # +0x95A7 U+4ECF # +0x95A8 U+7269 # +0x95A9 U+9B92 # +0x95AA U+5206 # +0x95AB U+543B # +0x95AC U+5674 # +0x95AD U+58B3 # +0x95AE U+61A4 # +0x95AF U+626E # +0x95B0 U+711A # +0x95B1 U+596E # +0x95B2 U+7C89 # +0x95B3 U+7CDE # +0x95B4 U+7D1B # +0x95B5 U+96F0 # +0x95B6 U+6587 # +0x95B7 U+805E # +0x95B8 U+4E19 # +0x95B9 U+4F75 # +0x95BA U+5175 # +0x95BB U+5840 # +0x95BC U+5E63 # +0x95BD U+5E73 # +0x95BE U+5F0A # +0x95BF U+67C4 # +0x95C0 U+4E26 # +0x95C1 U+853D # +0x95C2 U+9589 # +0x95C3 U+965B # +0x95C4 U+7C73 # +0x95C5 U+9801 # +0x95C6 U+50FB # +0x95C7 U+58C1 # +0x95C8 U+7656 # +0x95C9 U+78A7 # +0x95CA U+5225 # +0x95CB U+77A5 # +0x95CC U+8511 # +0x95CD U+7B86 # +0x95CE U+504F # +0x95CF U+5909 # +0x95D0 U+7247 # +0x95D1 U+7BC7 # +0x95D2 U+7DE8 # +0x95D3 U+8FBA # +0x95D4 U+8FD4 # +0x95D5 U+904D # +0x95D6 U+4FBF # +0x95D7 U+52C9 # +0x95D8 U+5A29 # +0x95D9 U+5F01 # +0x95DA U+97AD # +0x95DB U+4FDD # +0x95DC U+8217 # +0x95DD U+92EA # +0x95DE U+5703 # +0x95DF U+6355 # +0x95E0 U+6B69 # +0x95E1 U+752B # +0x95E2 U+88DC # +0x95E3 U+8F14 # +0x95E4 U+7A42 # +0x95E5 U+52DF # +0x95E6 U+5893 # +0x95E7 U+6155 # +0x95E8 U+620A # +0x95E9 U+66AE # +0x95EA U+6BCD # +0x95EB U+7C3F # +0x95EC U+83E9 # +0x95ED U+5023 # +0x95EE U+4FF8 # +0x95EF U+5305 # +0x95F0 U+5446 # +0x95F1 U+5831 # +0x95F2 U+5949 # +0x95F3 U+5B9D # +0x95F4 U+5CF0 # +0x95F5 U+5CEF # +0x95F6 U+5D29 # +0x95F7 U+5E96 # +0x95F8 U+62B1 # +0x95F9 U+6367 # +0x95FA U+653E # +0x95FB U+65B9 # +0x95FC U+670B # +0x9640 U+6CD5 # +0x9641 U+6CE1 # +0x9642 U+70F9 # +0x9643 U+7832 # +0x9644 U+7E2B # +0x9645 U+80DE # +0x9646 U+82B3 # +0x9647 U+840C # +0x9648 U+84EC # +0x9649 U+8702 # +0x964A U+8912 # +0x964B U+8A2A # +0x964C U+8C4A # +0x964D U+90A6 # +0x964E U+92D2 # +0x964F U+98FD # +0x9650 U+9CF3 # +0x9651 U+9D6C # +0x9652 U+4E4F # +0x9653 U+4EA1 # +0x9654 U+508D # +0x9655 U+5256 # +0x9656 U+574A # +0x9657 U+59A8 # +0x9658 U+5E3D # +0x9659 U+5FD8 # +0x965A U+5FD9 # +0x965B U+623F # +0x965C U+66B4 # +0x965D U+671B # +0x965E U+67D0 # +0x965F U+68D2 # +0x9660 U+5192 # +0x9661 U+7D21 # +0x9662 U+80AA # +0x9663 U+81A8 # +0x9664 U+8B00 # +0x9665 U+8C8C # +0x9666 U+8CBF # +0x9667 U+927E # +0x9668 U+9632 # +0x9669 U+5420 # +0x966A U+982C # +0x966B U+5317 # +0x966C U+50D5 # +0x966D U+535C # +0x966E U+58A8 # +0x966F U+64B2 # +0x9670 U+6734 # +0x9671 U+7267 # +0x9672 U+7766 # +0x9673 U+7A46 # +0x9674 U+91E6 # +0x9675 U+52C3 # +0x9676 U+6CA1 # +0x9677 U+6B86 # +0x9678 U+5800 # +0x9679 U+5E4C # +0x967A U+5954 # +0x967B U+672C # +0x967C U+7FFB # +0x967D U+51E1 # +0x967E U+76C6 # +0x9680 U+6469 # +0x9681 U+78E8 # +0x9682 U+9B54 # +0x9683 U+9EBB # +0x9684 U+57CB # +0x9685 U+59B9 # +0x9686 U+6627 # +0x9687 U+679A # +0x9688 U+6BCE # +0x9689 U+54E9 # +0x968A U+69D9 # +0x968B U+5E55 # +0x968C U+819C # +0x968D U+6795 # +0x968E U+9BAA # +0x968F U+67FE # +0x9690 U+9C52 # +0x9691 U+685D # +0x9692 U+4EA6 # +0x9693 U+4FE3 # +0x9694 U+53C8 # +0x9695 U+62B9 # +0x9696 U+672B # +0x9697 U+6CAB # +0x9698 U+8FC4 # +0x9699 U+4FAD # +0x969A U+7E6D # +0x969B U+9EBF # +0x969C U+4E07 # +0x969D U+6162 # +0x969E U+6E80 # +0x969F U+6F2B # +0x96A0 U+8513 # +0x96A1 U+5473 # +0x96A2 U+672A # +0x96A3 U+9B45 # +0x96A4 U+5DF3 # +0x96A5 U+7B95 # +0x96A6 U+5CAC # +0x96A7 U+5BC6 # +0x96A8 U+871C # +0x96A9 U+6E4A # +0x96AA U+84D1 # +0x96AB U+7A14 # +0x96AC U+8108 # +0x96AD U+5999 # +0x96AE U+7C8D # +0x96AF U+6C11 # +0x96B0 U+7720 # +0x96B1 U+52D9 # +0x96B2 U+5922 # +0x96B3 U+7121 # +0x96B4 U+725F # +0x96B5 U+77DB # +0x96B6 U+9727 # +0x96B7 U+9D61 # +0x96B8 U+690B # +0x96B9 U+5A7F # +0x96BA U+5A18 # +0x96BB U+51A5 # +0x96BC U+540D # +0x96BD U+547D # +0x96BE U+660E # +0x96BF U+76DF # +0x96C0 U+8FF7 # +0x96C1 U+9298 # +0x96C2 U+9CF4 # +0x96C3 U+59EA # +0x96C4 U+725D # +0x96C5 U+6EC5 # +0x96C6 U+514D # +0x96C7 U+68C9 # +0x96C8 U+7DBF # +0x96C9 U+7DEC # +0x96CA U+9762 # +0x96CB U+9EBA # +0x96CC U+6478 # +0x96CD U+6A21 # +0x96CE U+8302 # +0x96CF U+5984 # +0x96D0 U+5B5F # +0x96D1 U+6BDB # +0x96D2 U+731B # +0x96D3 U+76F2 # +0x96D4 U+7DB2 # +0x96D5 U+8017 # +0x96D6 U+8499 # +0x96D7 U+5132 # +0x96D8 U+6728 # +0x96D9 U+9ED9 # +0x96DA U+76EE # +0x96DB U+6762 # +0x96DC U+52FF # +0x96DD U+9905 # +0x96DE U+5C24 # +0x96DF U+623B # +0x96E0 U+7C7E # +0x96E1 U+8CB0 # +0x96E2 U+554F # +0x96E3 U+60B6 # +0x96E4 U+7D0B # +0x96E5 U+9580 # +0x96E6 U+5301 # +0x96E7 U+4E5F # +0x96E8 U+51B6 # +0x96E9 U+591C # +0x96EA U+723A # +0x96EB U+8036 # +0x96EC U+91CE # +0x96ED U+5F25 # +0x96EE U+77E2 # +0x96EF U+5384 # +0x96F0 U+5F79 # +0x96F1 U+7D04 # +0x96F2 U+85AC # +0x96F3 U+8A33 # +0x96F4 U+8E8D # +0x96F5 U+9756 # +0x96F6 U+67F3 # +0x96F7 U+85AE # +0x96F8 U+9453 # +0x96F9 U+6109 # +0x96FA U+6108 # +0x96FB U+6CB9 # +0x96FC U+7652 # +0x9740 U+8AED # +0x9741 U+8F38 # +0x9742 U+552F # +0x9743 U+4F51 # +0x9744 U+512A # +0x9745 U+52C7 # +0x9746 U+53CB # +0x9747 U+5BA5 # +0x9748 U+5E7D # +0x9749 U+60A0 # +0x974A U+6182 # +0x974B U+63D6 # +0x974C U+6709 # +0x974D U+67DA # +0x974E U+6E67 # +0x974F U+6D8C # +0x9750 U+7336 # +0x9751 U+7337 # +0x9752 U+7531 # +0x9753 U+7950 # +0x9754 U+88D5 # +0x9755 U+8A98 # +0x9756 U+904A # +0x9757 U+9091 # +0x9758 U+90F5 # +0x9759 U+96C4 # +0x975A U+878D # +0x975B U+5915 # +0x975C U+4E88 # +0x975D U+4F59 # +0x975E U+4E0E # +0x975F U+8A89 # +0x9760 U+8F3F # +0x9761 U+9810 # +0x9762 U+50AD # +0x9763 U+5E7C # +0x9764 U+5996 # +0x9765 U+5BB9 # +0x9766 U+5EB8 # +0x9767 U+63DA # +0x9768 U+63FA # +0x9769 U+64C1 # +0x976A U+66DC # +0x976B U+694A # +0x976C U+69D8 # +0x976D U+6D0B # +0x976E U+6EB6 # +0x976F U+7194 # +0x9770 U+7528 # +0x9771 U+7AAF # +0x9772 U+7F8A # +0x9773 U+8000 # +0x9774 U+8449 # +0x9775 U+84C9 # +0x9776 U+8981 # +0x9777 U+8B21 # +0x9778 U+8E0A # +0x9779 U+9065 # +0x977A U+967D # +0x977B U+990A # +0x977C U+617E # +0x977D U+6291 # +0x977E U+6B32 # +0x9780 U+6C83 # +0x9781 U+6D74 # +0x9782 U+7FCC # +0x9783 U+7FFC # +0x9784 U+6DC0 # +0x9785 U+7F85 # +0x9786 U+87BA # +0x9787 U+88F8 # +0x9788 U+6765 # +0x9789 U+83B1 # +0x978A U+983C # +0x978B U+96F7 # +0x978C U+6D1B # +0x978D U+7D61 # +0x978E U+843D # +0x978F U+916A # +0x9790 U+4E71 # +0x9791 U+5375 # +0x9792 U+5D50 # +0x9793 U+6B04 # +0x9794 U+6FEB # +0x9795 U+85CD # +0x9796 U+862D # +0x9797 U+89A7 # +0x9798 U+5229 # +0x9799 U+540F # +0x979A U+5C65 # +0x979B U+674E # +0x979C U+68A8 # +0x979D U+7406 # +0x979E U+7483 # +0x979F U+75E2 # +0x97A0 U+88CF # +0x97A1 U+88E1 # +0x97A2 U+91CC # +0x97A3 U+96E2 # +0x97A4 U+9678 # +0x97A5 U+5F8B # +0x97A6 U+7387 # +0x97A7 U+7ACB # +0x97A8 U+844E # +0x97A9 U+63A0 # +0x97AA U+7565 # +0x97AB U+5289 # +0x97AC U+6D41 # +0x97AD U+6E9C # +0x97AE U+7409 # +0x97AF U+7559 # +0x97B0 U+786B # +0x97B1 U+7C92 # +0x97B2 U+9686 # +0x97B3 U+7ADC # +0x97B4 U+9F8D # +0x97B5 U+4FB6 # +0x97B6 U+616E # +0x97B7 U+65C5 # +0x97B8 U+865C # +0x97B9 U+4E86 # +0x97BA U+4EAE # +0x97BB U+50DA # +0x97BC U+4E21 # +0x97BD U+51CC # +0x97BE U+5BEE # +0x97BF U+6599 # +0x97C0 U+6881 # +0x97C1 U+6DBC # +0x97C2 U+731F # +0x97C3 U+7642 # +0x97C4 U+77AD # +0x97C5 U+7A1C # +0x97C6 U+7CE7 # +0x97C7 U+826F # +0x97C8 U+8AD2 # +0x97C9 U+907C # +0x97CA U+91CF # +0x97CB U+9675 # +0x97CC U+9818 # +0x97CD U+529B # +0x97CE U+7DD1 # +0x97CF U+502B # +0x97D0 U+5398 # +0x97D1 U+6797 # +0x97D2 U+6DCB # +0x97D3 U+71D0 # +0x97D4 U+7433 # +0x97D5 U+81E8 # +0x97D6 U+8F2A # +0x97D7 U+96A3 # +0x97D8 U+9C57 # +0x97D9 U+9E9F # +0x97DA U+7460 # +0x97DB U+5841 # +0x97DC U+6D99 # +0x97DD U+7D2F # +0x97DE U+985E # +0x97DF U+4EE4 # +0x97E0 U+4F36 # +0x97E1 U+4F8B # +0x97E2 U+51B7 # +0x97E3 U+52B1 # +0x97E4 U+5DBA # +0x97E5 U+601C # +0x97E6 U+73B2 # +0x97E7 U+793C # +0x97E8 U+82D3 # +0x97E9 U+9234 # +0x97EA U+96B7 # +0x97EB U+96F6 # +0x97EC U+970A # +0x97ED U+9E97 # +0x97EE U+9F62 # +0x97EF U+66A6 # +0x97F0 U+6B74 # +0x97F1 U+5217 # +0x97F2 U+52A3 # +0x97F3 U+70C8 # +0x97F4 U+88C2 # +0x97F5 U+5EC9 # +0x97F6 U+604B # +0x97F7 U+6190 # +0x97F8 U+6F23 # +0x97F9 U+7149 # +0x97FA U+7C3E # +0x97FB U+7DF4 # +0x97FC U+806F # +0x9840 U+84EE # +0x9841 U+9023 # +0x9842 U+932C # +0x9843 U+5442 # +0x9844 U+9B6F # +0x9845 U+6AD3 # +0x9846 U+7089 # +0x9847 U+8CC2 # +0x9848 U+8DEF # +0x9849 U+9732 # +0x984A U+52B4 # +0x984B U+5A41 # +0x984C U+5ECA # +0x984D U+5F04 # +0x984E U+6717 # +0x984F U+697C # +0x9850 U+6994 # +0x9851 U+6D6A # +0x9852 U+6F0F # +0x9853 U+7262 # +0x9854 U+72FC # +0x9855 U+7BED # +0x9856 U+8001 # +0x9857 U+807E # +0x9858 U+874B # +0x9859 U+90CE # +0x985A U+516D # +0x985B U+9E93 # +0x985C U+7984 # +0x985D U+808B # +0x985E U+9332 # +0x985F U+8AD6 # +0x9860 U+502D # +0x9861 U+548C # +0x9862 U+8A71 # +0x9863 U+6B6A # +0x9864 U+8CC4 # +0x9865 U+8107 # +0x9866 U+60D1 # +0x9867 U+67A0 # +0x9868 U+9DF2 # +0x9869 U+4E99 # +0x986A U+4E98 # +0x986B U+9C10 # +0x986C U+8A6B # +0x986D U+85C1 # +0x986E U+8568 # +0x986F U+6900 # +0x9870 U+6E7E # +0x9871 U+7897 # +0x9872 U+8155 # +0x9873 U+20B9F # [2004] [Unicode3.1] +0x9874 U+5B41 # [2000] +0x9875 U+5B56 # [2000] +0x9876 U+5B7D # [2000] +0x9877 U+5B93 # [2000] +0x9878 U+5BD8 # [2000] +0x9879 U+5BEC # [2000] +0x987A U+5C12 # [2000] +0x987B U+5C1E # [2000] +0x987C U+5C23 # [2000] +0x987D U+5C2B # [2000] +0x987E U+378D # [2000] +0x9880 U+5C62 # [2000] +0x9881 U+FA3B # CJK COMPATIBILITY IDEOGRAPH-FA3B [2000] [Unicode3.2] +0x9882 U+FA3C # CJK COMPATIBILITY IDEOGRAPH-FA3C [2000] [Unicode3.2] +0x9883 U+216B4 # [2000] [Unicode3.1] +0x9884 U+5C7A # [2000] +0x9885 U+5C8F # [2000] +0x9886 U+5C9F # [2000] +0x9887 U+5CA3 # [2000] +0x9888 U+5CAA # [2000] +0x9889 U+5CBA # [2000] +0x988A U+5CCB # [2000] +0x988B U+5CD0 # [2000] +0x988C U+5CD2 # [2000] +0x988D U+5CF4 # [2000] +0x988E U+21E34 # [2000] [Unicode3.1] +0x988F U+37E2 # [2000] +0x9890 U+5D0D # [2000] +0x9891 U+5D27 # [2000] +0x9892 U+FA11 # CJK COMPATIBILITY IDEOGRAPH-FA11 [2000] +0x9893 U+5D46 # [2000] +0x9894 U+5D47 # [2000] +0x9895 U+5D53 # [2000] +0x9896 U+5D4A # [2000] +0x9897 U+5D6D # [2000] +0x9898 U+5D81 # [2000] +0x9899 U+5DA0 # [2000] +0x989A U+5DA4 # [2000] +0x989B U+5DA7 # [2000] +0x989C U+5DB8 # [2000] +0x989D U+5DCB # [2000] +0x989E U+541E # [2004] +0x989F U+5F0C # +0x98A0 U+4E10 # +0x98A1 U+4E15 # +0x98A2 U+4E2A # +0x98A3 U+4E31 # +0x98A4 U+4E36 # +0x98A5 U+4E3C # +0x98A6 U+4E3F # +0x98A7 U+4E42 # +0x98A8 U+4E56 # +0x98A9 U+4E58 # +0x98AA U+4E82 # +0x98AB U+4E85 # +0x98AC U+8C6B # +0x98AD U+4E8A # +0x98AE U+8212 # +0x98AF U+5F0D # +0x98B0 U+4E8E # +0x98B1 U+4E9E # +0x98B2 U+4E9F # +0x98B3 U+4EA0 # +0x98B4 U+4EA2 # +0x98B5 U+4EB0 # +0x98B6 U+4EB3 # +0x98B7 U+4EB6 # +0x98B8 U+4ECE # +0x98B9 U+4ECD # +0x98BA U+4EC4 # +0x98BB U+4EC6 # +0x98BC U+4EC2 # +0x98BD U+4ED7 # +0x98BE U+4EDE # +0x98BF U+4EED # +0x98C0 U+4EDF # +0x98C1 U+4EF7 # +0x98C2 U+4F09 # +0x98C3 U+4F5A # +0x98C4 U+4F30 # +0x98C5 U+4F5B # +0x98C6 U+4F5D # +0x98C7 U+4F57 # +0x98C8 U+4F47 # +0x98C9 U+4F76 # +0x98CA U+4F88 # +0x98CB U+4F8F # +0x98CC U+4F98 # +0x98CD U+4F7B # +0x98CE U+4F69 # +0x98CF U+4F70 # +0x98D0 U+4F91 # +0x98D1 U+4F6F # +0x98D2 U+4F86 # +0x98D3 U+4F96 # +0x98D4 U+5118 # +0x98D5 U+4FD4 # +0x98D6 U+4FDF # +0x98D7 U+4FCE # +0x98D8 U+4FD8 # +0x98D9 U+4FDB # +0x98DA U+4FD1 # +0x98DB U+4FDA # +0x98DC U+4FD0 # +0x98DD U+4FE4 # +0x98DE U+4FE5 # +0x98DF U+501A # +0x98E0 U+5028 # +0x98E1 U+5014 # +0x98E2 U+502A # +0x98E3 U+5025 # +0x98E4 U+5005 # +0x98E5 U+4F1C # +0x98E6 U+4FF6 # +0x98E7 U+5021 # +0x98E8 U+5029 # +0x98E9 U+502C # +0x98EA U+4FFE # +0x98EB U+4FEF # +0x98EC U+5011 # +0x98ED U+5006 # +0x98EE U+5043 # +0x98EF U+5047 # +0x98F0 U+6703 # +0x98F1 U+5055 # +0x98F2 U+5050 # +0x98F3 U+5048 # +0x98F4 U+505A # +0x98F5 U+5056 # +0x98F6 U+506C # +0x98F7 U+5078 # +0x98F8 U+5080 # +0x98F9 U+509A # +0x98FA U+5085 # +0x98FB U+50B4 # +0x98FC U+50B2 # +0x9940 U+50C9 # +0x9941 U+50CA # +0x9942 U+50B3 # +0x9943 U+50C2 # +0x9944 U+50D6 # +0x9945 U+50DE # +0x9946 U+50E5 # +0x9947 U+50ED # +0x9948 U+50E3 # +0x9949 U+50EE # +0x994A U+50F9 # +0x994B U+50F5 # +0x994C U+5109 # +0x994D U+5101 # +0x994E U+5102 # +0x994F U+5116 # +0x9950 U+5115 # +0x9951 U+5114 # +0x9952 U+511A # +0x9953 U+5121 # +0x9954 U+513A # +0x9955 U+5137 # +0x9956 U+513C # +0x9957 U+513B # +0x9958 U+513F # +0x9959 U+5140 # +0x995A U+5152 # +0x995B U+514C # +0x995C U+5154 # +0x995D U+5162 # +0x995E U+7AF8 # +0x995F U+5169 # +0x9960 U+516A # +0x9961 U+516E # +0x9962 U+5180 # +0x9963 U+5182 # +0x9964 U+56D8 # +0x9965 U+518C # +0x9966 U+5189 # +0x9967 U+518F # +0x9968 U+5191 # +0x9969 U+5193 # +0x996A U+5195 # +0x996B U+5196 # +0x996C U+51A4 # +0x996D U+51A6 # +0x996E U+51A2 # +0x996F U+51A9 # +0x9970 U+51AA # +0x9971 U+51AB # +0x9972 U+51B3 # +0x9973 U+51B1 # +0x9974 U+51B2 # +0x9975 U+51B0 # +0x9976 U+51B5 # +0x9977 U+51BD # +0x9978 U+51C5 # +0x9979 U+51C9 # +0x997A U+51DB # +0x997B U+51E0 # +0x997C U+8655 # +0x997D U+51E9 # +0x997E U+51ED # +0x9980 U+51F0 # +0x9981 U+51F5 # +0x9982 U+51FE # +0x9983 U+5204 # +0x9984 U+520B # +0x9985 U+5214 # +0x9986 U+520E # +0x9987 U+5227 # +0x9988 U+522A # +0x9989 U+522E # +0x998A U+5233 # +0x998B U+5239 # +0x998C U+524F # +0x998D U+5244 # +0x998E U+524B # +0x998F U+524C # +0x9990 U+525E # +0x9991 U+5254 # +0x9992 U+526A # +0x9993 U+5274 # +0x9994 U+5269 # +0x9995 U+5273 # +0x9996 U+527F # +0x9997 U+527D # +0x9998 U+528D # +0x9999 U+5294 # +0x999A U+5292 # +0x999B U+5271 # +0x999C U+5288 # +0x999D U+5291 # +0x999E U+8FA8 # +0x999F U+8FA7 # +0x99A0 U+52AC # +0x99A1 U+52AD # +0x99A2 U+52BC # +0x99A3 U+52B5 # +0x99A4 U+52C1 # +0x99A5 U+52CD # +0x99A6 U+52D7 # +0x99A7 U+52DE # +0x99A8 U+52E3 # +0x99A9 U+52E6 # +0x99AA U+98ED # +0x99AB U+52E0 # +0x99AC U+52F3 # +0x99AD U+52F5 # +0x99AE U+52F8 # +0x99AF U+52F9 # +0x99B0 U+5306 # +0x99B1 U+5308 # +0x99B2 U+7538 # +0x99B3 U+530D # +0x99B4 U+5310 # +0x99B5 U+530F # +0x99B6 U+5315 # +0x99B7 U+531A # +0x99B8 U+5323 # +0x99B9 U+532F # +0x99BA U+5331 # +0x99BB U+5333 # +0x99BC U+5338 # +0x99BD U+5340 # +0x99BE U+5346 # +0x99BF U+5345 # +0x99C0 U+4E17 # +0x99C1 U+5349 # +0x99C2 U+534D # +0x99C3 U+51D6 # +0x99C4 U+535E # +0x99C5 U+5369 # +0x99C6 U+536E # +0x99C7 U+5918 # +0x99C8 U+537B # +0x99C9 U+5377 # +0x99CA U+5382 # +0x99CB U+5396 # +0x99CC U+53A0 # +0x99CD U+53A6 # +0x99CE U+53A5 # +0x99CF U+53AE # +0x99D0 U+53B0 # +0x99D1 U+53B6 # +0x99D2 U+53C3 # +0x99D3 U+7C12 # +0x99D4 U+96D9 # +0x99D5 U+53DF # +0x99D6 U+66FC # +0x99D7 U+71EE # +0x99D8 U+53EE # +0x99D9 U+53E8 # +0x99DA U+53ED # +0x99DB U+53FA # +0x99DC U+5401 # +0x99DD U+543D # +0x99DE U+5440 # +0x99DF U+542C # +0x99E0 U+542D # +0x99E1 U+543C # +0x99E2 U+542E # +0x99E3 U+5436 # +0x99E4 U+5429 # +0x99E5 U+541D # +0x99E6 U+544E # +0x99E7 U+548F # +0x99E8 U+5475 # +0x99E9 U+548E # +0x99EA U+545F # +0x99EB U+5471 # +0x99EC U+5477 # +0x99ED U+5470 # +0x99EE U+5492 # +0x99EF U+547B # +0x99F0 U+5480 # +0x99F1 U+5476 # +0x99F2 U+5484 # +0x99F3 U+5490 # +0x99F4 U+5486 # +0x99F5 U+54C7 # +0x99F6 U+54A2 # +0x99F7 U+54B8 # +0x99F8 U+54A5 # +0x99F9 U+54AC # +0x99FA U+54C4 # +0x99FB U+54C8 # +0x99FC U+54A8 # +0x9A40 U+54AB # +0x9A41 U+54C2 # +0x9A42 U+54A4 # +0x9A43 U+54BE # +0x9A44 U+54BC # +0x9A45 U+54D8 # +0x9A46 U+54E5 # +0x9A47 U+54E6 # +0x9A48 U+550F # +0x9A49 U+5514 # +0x9A4A U+54FD # +0x9A4B U+54EE # +0x9A4C U+54ED # +0x9A4D U+54FA # +0x9A4E U+54E2 # +0x9A4F U+5539 # +0x9A50 U+5540 # +0x9A51 U+5563 # +0x9A52 U+554C # +0x9A53 U+552E # +0x9A54 U+555C # +0x9A55 U+5545 # +0x9A56 U+5556 # +0x9A57 U+5557 # +0x9A58 U+5538 # +0x9A59 U+5533 # +0x9A5A U+555D # +0x9A5B U+5599 # +0x9A5C U+5580 # +0x9A5D U+54AF # +0x9A5E U+558A # +0x9A5F U+559F # +0x9A60 U+557B # +0x9A61 U+557E # +0x9A62 U+5598 # +0x9A63 U+559E # +0x9A64 U+55AE # +0x9A65 U+557C # +0x9A66 U+5583 # +0x9A67 U+55A9 # +0x9A68 U+5587 # +0x9A69 U+55A8 # +0x9A6A U+55DA # +0x9A6B U+55C5 # +0x9A6C U+55DF # +0x9A6D U+55C4 # +0x9A6E U+55DC # +0x9A6F U+55E4 # +0x9A70 U+55D4 # +0x9A71 U+5614 # +0x9A72 U+55F7 # +0x9A73 U+5616 # +0x9A74 U+55FE # +0x9A75 U+55FD # +0x9A76 U+561B # +0x9A77 U+55F9 # +0x9A78 U+564E # +0x9A79 U+5650 # +0x9A7A U+71DF # +0x9A7B U+5634 # +0x9A7C U+5636 # +0x9A7D U+5632 # +0x9A7E U+5638 # +0x9A80 U+566B # +0x9A81 U+5664 # +0x9A82 U+562F # +0x9A83 U+566C # +0x9A84 U+566A # +0x9A85 U+5686 # +0x9A86 U+5680 # +0x9A87 U+568A # +0x9A88 U+56A0 # +0x9A89 U+5694 # +0x9A8A U+568F # +0x9A8B U+56A5 # +0x9A8C U+56AE # +0x9A8D U+56B6 # +0x9A8E U+56B4 # +0x9A8F U+56C2 # +0x9A90 U+56BC # +0x9A91 U+56C1 # +0x9A92 U+56C3 # +0x9A93 U+56C0 # +0x9A94 U+56C8 # +0x9A95 U+56CE # +0x9A96 U+56D1 # +0x9A97 U+56D3 # +0x9A98 U+56D7 # +0x9A99 U+56EE # +0x9A9A U+56F9 # +0x9A9B U+5700 # +0x9A9C U+56FF # +0x9A9D U+5704 # +0x9A9E U+5709 # +0x9A9F U+5708 # +0x9AA0 U+570B # +0x9AA1 U+570D # +0x9AA2 U+5713 # +0x9AA3 U+5718 # +0x9AA4 U+5716 # +0x9AA5 U+55C7 # +0x9AA6 U+571C # +0x9AA7 U+5726 # +0x9AA8 U+5737 # +0x9AA9 U+5738 # +0x9AAA U+574E # +0x9AAB U+573B # +0x9AAC U+5740 # +0x9AAD U+574F # +0x9AAE U+5769 # +0x9AAF U+57C0 # +0x9AB0 U+5788 # +0x9AB1 U+5761 # +0x9AB2 U+577F # +0x9AB3 U+5789 # +0x9AB4 U+5793 # +0x9AB5 U+57A0 # +0x9AB6 U+57B3 # +0x9AB7 U+57A4 # +0x9AB8 U+57AA # +0x9AB9 U+57B0 # +0x9ABA U+57C3 # +0x9ABB U+57C6 # +0x9ABC U+57D4 # +0x9ABD U+57D2 # +0x9ABE U+57D3 # +0x9ABF U+580A # +0x9AC0 U+57D6 # +0x9AC1 U+57E3 # +0x9AC2 U+580B # +0x9AC3 U+5819 # +0x9AC4 U+581D # +0x9AC5 U+5872 # +0x9AC6 U+5821 # +0x9AC7 U+5862 # +0x9AC8 U+584B # +0x9AC9 U+5870 # +0x9ACA U+6BC0 # +0x9ACB U+5852 # +0x9ACC U+583D # +0x9ACD U+5879 # +0x9ACE U+5885 # +0x9ACF U+58B9 # +0x9AD0 U+589F # +0x9AD1 U+58AB # +0x9AD2 U+58BA # +0x9AD3 U+58DE # +0x9AD4 U+58BB # +0x9AD5 U+58B8 # +0x9AD6 U+58AE # +0x9AD7 U+58C5 # +0x9AD8 U+58D3 # +0x9AD9 U+58D1 # +0x9ADA U+58D7 # +0x9ADB U+58D9 # +0x9ADC U+58D8 # +0x9ADD U+58E5 # +0x9ADE U+58DC # +0x9ADF U+58E4 # +0x9AE0 U+58DF # +0x9AE1 U+58EF # +0x9AE2 U+58FA # +0x9AE3 U+58F9 # +0x9AE4 U+58FB # +0x9AE5 U+58FC # +0x9AE6 U+58FD # +0x9AE7 U+5902 # +0x9AE8 U+590A # +0x9AE9 U+5910 # +0x9AEA U+591B # +0x9AEB U+68A6 # +0x9AEC U+5925 # +0x9AED U+592C # +0x9AEE U+592D # +0x9AEF U+5932 # +0x9AF0 U+5938 # +0x9AF1 U+593E # +0x9AF2 U+7AD2 # +0x9AF3 U+5955 # +0x9AF4 U+5950 # +0x9AF5 U+594E # +0x9AF6 U+595A # +0x9AF7 U+5958 # +0x9AF8 U+5962 # +0x9AF9 U+5960 # +0x9AFA U+5967 # +0x9AFB U+596C # +0x9AFC U+5969 # +0x9B40 U+5978 # +0x9B41 U+5981 # +0x9B42 U+599D # +0x9B43 U+4F5E # +0x9B44 U+4FAB # +0x9B45 U+59A3 # +0x9B46 U+59B2 # +0x9B47 U+59C6 # +0x9B48 U+59E8 # +0x9B49 U+59DC # +0x9B4A U+598D # +0x9B4B U+59D9 # +0x9B4C U+59DA # +0x9B4D U+5A25 # +0x9B4E U+5A1F # +0x9B4F U+5A11 # +0x9B50 U+5A1C # +0x9B51 U+5A09 # +0x9B52 U+5A1A # +0x9B53 U+5A40 # +0x9B54 U+5A6C # +0x9B55 U+5A49 # +0x9B56 U+5A35 # +0x9B57 U+5A36 # +0x9B58 U+5A62 # +0x9B59 U+5A6A # +0x9B5A U+5A9A # +0x9B5B U+5ABC # +0x9B5C U+5ABE # +0x9B5D U+5ACB # +0x9B5E U+5AC2 # +0x9B5F U+5ABD # +0x9B60 U+5AE3 # +0x9B61 U+5AD7 # +0x9B62 U+5AE6 # +0x9B63 U+5AE9 # +0x9B64 U+5AD6 # +0x9B65 U+5AFA # +0x9B66 U+5AFB # +0x9B67 U+5B0C # +0x9B68 U+5B0B # +0x9B69 U+5B16 # +0x9B6A U+5B32 # +0x9B6B U+5AD0 # +0x9B6C U+5B2A # +0x9B6D U+5B36 # +0x9B6E U+5B3E # +0x9B6F U+5B43 # +0x9B70 U+5B45 # +0x9B71 U+5B40 # +0x9B72 U+5B51 # +0x9B73 U+5B55 # +0x9B74 U+5B5A # +0x9B75 U+5B5B # +0x9B76 U+5B65 # +0x9B77 U+5B69 # +0x9B78 U+5B70 # +0x9B79 U+5B73 # +0x9B7A U+5B75 # +0x9B7B U+5B78 # +0x9B7C U+6588 # +0x9B7D U+5B7A # +0x9B7E U+5B80 # +0x9B80 U+5B83 # +0x9B81 U+5BA6 # +0x9B82 U+5BB8 # +0x9B83 U+5BC3 # +0x9B84 U+5BC7 # +0x9B85 U+5BC9 # +0x9B86 U+5BD4 # +0x9B87 U+5BD0 # +0x9B88 U+5BE4 # +0x9B89 U+5BE6 # +0x9B8A U+5BE2 # +0x9B8B U+5BDE # +0x9B8C U+5BE5 # +0x9B8D U+5BEB # +0x9B8E U+5BF0 # +0x9B8F U+5BF6 # +0x9B90 U+5BF3 # +0x9B91 U+5C05 # +0x9B92 U+5C07 # +0x9B93 U+5C08 # +0x9B94 U+5C0D # +0x9B95 U+5C13 # +0x9B96 U+5C20 # +0x9B97 U+5C22 # +0x9B98 U+5C28 # +0x9B99 U+5C38 # +0x9B9A U+5C39 # +0x9B9B U+5C41 # +0x9B9C U+5C46 # +0x9B9D U+5C4E # +0x9B9E U+5C53 # +0x9B9F U+5C50 # +0x9BA0 U+5C4F # +0x9BA1 U+5B71 # +0x9BA2 U+5C6C # +0x9BA3 U+5C6E # +0x9BA4 U+4E62 # +0x9BA5 U+5C76 # +0x9BA6 U+5C79 # +0x9BA7 U+5C8C # +0x9BA8 U+5C91 # +0x9BA9 U+5C94 # +0x9BAA U+599B # +0x9BAB U+5CAB # +0x9BAC U+5CBB # +0x9BAD U+5CB6 # +0x9BAE U+5CBC # +0x9BAF U+5CB7 # +0x9BB0 U+5CC5 # +0x9BB1 U+5CBE # +0x9BB2 U+5CC7 # +0x9BB3 U+5CD9 # +0x9BB4 U+5CE9 # +0x9BB5 U+5CFD # +0x9BB6 U+5CFA # +0x9BB7 U+5CED # +0x9BB8 U+5D8C # +0x9BB9 U+5CEA # +0x9BBA U+5D0B # +0x9BBB U+5D15 # +0x9BBC U+5D17 # +0x9BBD U+5D5C # +0x9BBE U+5D1F # +0x9BBF U+5D1B # +0x9BC0 U+5D11 # +0x9BC1 U+5D14 # +0x9BC2 U+5D22 # +0x9BC3 U+5D1A # +0x9BC4 U+5D19 # +0x9BC5 U+5D18 # +0x9BC6 U+5D4C # +0x9BC7 U+5D52 # +0x9BC8 U+5D4E # +0x9BC9 U+5D4B # +0x9BCA U+5D6C # +0x9BCB U+5D73 # +0x9BCC U+5D76 # +0x9BCD U+5D87 # +0x9BCE U+5D84 # +0x9BCF U+5D82 # +0x9BD0 U+5DA2 # +0x9BD1 U+5D9D # +0x9BD2 U+5DAC # +0x9BD3 U+5DAE # +0x9BD4 U+5DBD # +0x9BD5 U+5D90 # +0x9BD6 U+5DB7 # +0x9BD7 U+5DBC # +0x9BD8 U+5DC9 # +0x9BD9 U+5DCD # +0x9BDA U+5DD3 # +0x9BDB U+5DD2 # +0x9BDC U+5DD6 # +0x9BDD U+5DDB # +0x9BDE U+5DEB # +0x9BDF U+5DF2 # +0x9BE0 U+5DF5 # +0x9BE1 U+5E0B # +0x9BE2 U+5E1A # +0x9BE3 U+5E19 # +0x9BE4 U+5E11 # +0x9BE5 U+5E1B # +0x9BE6 U+5E36 # +0x9BE7 U+5E37 # +0x9BE8 U+5E44 # +0x9BE9 U+5E43 # +0x9BEA U+5E40 # +0x9BEB U+5E4E # +0x9BEC U+5E57 # +0x9BED U+5E54 # +0x9BEE U+5E5F # +0x9BEF U+5E62 # +0x9BF0 U+5E64 # +0x9BF1 U+5E47 # +0x9BF2 U+5E75 # +0x9BF3 U+5E76 # +0x9BF4 U+5E7A # +0x9BF5 U+9EBC # +0x9BF6 U+5E7F # +0x9BF7 U+5EA0 # +0x9BF8 U+5EC1 # +0x9BF9 U+5EC2 # +0x9BFA U+5EC8 # +0x9BFB U+5ED0 # +0x9BFC U+5ECF # +0x9C40 U+5ED6 # +0x9C41 U+5EE3 # +0x9C42 U+5EDD # +0x9C43 U+5EDA # +0x9C44 U+5EDB # +0x9C45 U+5EE2 # +0x9C46 U+5EE1 # +0x9C47 U+5EE8 # +0x9C48 U+5EE9 # +0x9C49 U+5EEC # +0x9C4A U+5EF1 # +0x9C4B U+5EF3 # +0x9C4C U+5EF0 # +0x9C4D U+5EF4 # +0x9C4E U+5EF8 # +0x9C4F U+5EFE # +0x9C50 U+5F03 # +0x9C51 U+5F09 # +0x9C52 U+5F5D # +0x9C53 U+5F5C # +0x9C54 U+5F0B # +0x9C55 U+5F11 # +0x9C56 U+5F16 # +0x9C57 U+5F29 # +0x9C58 U+5F2D # +0x9C59 U+5F38 # +0x9C5A U+5F41 # +0x9C5B U+5F48 # +0x9C5C U+5F4C # +0x9C5D U+5F4E # +0x9C5E U+5F2F # +0x9C5F U+5F51 # +0x9C60 U+5F56 # +0x9C61 U+5F57 # +0x9C62 U+5F59 # +0x9C63 U+5F61 # +0x9C64 U+5F6D # +0x9C65 U+5F73 # +0x9C66 U+5F77 # +0x9C67 U+5F83 # +0x9C68 U+5F82 # +0x9C69 U+5F7F # +0x9C6A U+5F8A # +0x9C6B U+5F88 # +0x9C6C U+5F91 # +0x9C6D U+5F87 # +0x9C6E U+5F9E # +0x9C6F U+5F99 # +0x9C70 U+5F98 # +0x9C71 U+5FA0 # +0x9C72 U+5FA8 # +0x9C73 U+5FAD # +0x9C74 U+5FBC # +0x9C75 U+5FD6 # +0x9C76 U+5FFB # +0x9C77 U+5FE4 # +0x9C78 U+5FF8 # +0x9C79 U+5FF1 # +0x9C7A U+5FDD # +0x9C7B U+60B3 # +0x9C7C U+5FFF # +0x9C7D U+6021 # +0x9C7E U+6060 # +0x9C80 U+6019 # +0x9C81 U+6010 # +0x9C82 U+6029 # +0x9C83 U+600E # +0x9C84 U+6031 # +0x9C85 U+601B # +0x9C86 U+6015 # +0x9C87 U+602B # +0x9C88 U+6026 # +0x9C89 U+600F # +0x9C8A U+603A # +0x9C8B U+605A # +0x9C8C U+6041 # +0x9C8D U+606A # +0x9C8E U+6077 # +0x9C8F U+605F # +0x9C90 U+604A # +0x9C91 U+6046 # +0x9C92 U+604D # +0x9C93 U+6063 # +0x9C94 U+6043 # +0x9C95 U+6064 # +0x9C96 U+6042 # +0x9C97 U+606C # +0x9C98 U+606B # +0x9C99 U+6059 # +0x9C9A U+6081 # +0x9C9B U+608D # +0x9C9C U+60E7 # +0x9C9D U+6083 # +0x9C9E U+609A # +0x9C9F U+6084 # +0x9CA0 U+609B # +0x9CA1 U+6096 # +0x9CA2 U+6097 # +0x9CA3 U+6092 # +0x9CA4 U+60A7 # +0x9CA5 U+608B # +0x9CA6 U+60E1 # +0x9CA7 U+60B8 # +0x9CA8 U+60E0 # +0x9CA9 U+60D3 # +0x9CAA U+60B4 # +0x9CAB U+5FF0 # +0x9CAC U+60BD # +0x9CAD U+60C6 # +0x9CAE U+60B5 # +0x9CAF U+60D8 # +0x9CB0 U+614D # +0x9CB1 U+6115 # +0x9CB2 U+6106 # +0x9CB3 U+60F6 # +0x9CB4 U+60F7 # +0x9CB5 U+6100 # +0x9CB6 U+60F4 # +0x9CB7 U+60FA # +0x9CB8 U+6103 # +0x9CB9 U+6121 # +0x9CBA U+60FB # +0x9CBB U+60F1 # +0x9CBC U+610D # +0x9CBD U+610E # +0x9CBE U+6147 # +0x9CBF U+613E # +0x9CC0 U+6128 # +0x9CC1 U+6127 # +0x9CC2 U+614A # +0x9CC3 U+613F # +0x9CC4 U+613C # +0x9CC5 U+612C # +0x9CC6 U+6134 # +0x9CC7 U+613D # +0x9CC8 U+6142 # +0x9CC9 U+6144 # +0x9CCA U+6173 # +0x9CCB U+6177 # +0x9CCC U+6158 # +0x9CCD U+6159 # +0x9CCE U+615A # +0x9CCF U+616B # +0x9CD0 U+6174 # +0x9CD1 U+616F # +0x9CD2 U+6165 # +0x9CD3 U+6171 # +0x9CD4 U+615F # +0x9CD5 U+615D # +0x9CD6 U+6153 # +0x9CD7 U+6175 # +0x9CD8 U+6199 # +0x9CD9 U+6196 # +0x9CDA U+6187 # +0x9CDB U+61AC # +0x9CDC U+6194 # +0x9CDD U+619A # +0x9CDE U+618A # +0x9CDF U+6191 # +0x9CE0 U+61AB # +0x9CE1 U+61AE # +0x9CE2 U+61CC # +0x9CE3 U+61CA # +0x9CE4 U+61C9 # +0x9CE5 U+61F7 # +0x9CE6 U+61C8 # +0x9CE7 U+61C3 # +0x9CE8 U+61C6 # +0x9CE9 U+61BA # +0x9CEA U+61CB # +0x9CEB U+7F79 # +0x9CEC U+61CD # +0x9CED U+61E6 # +0x9CEE U+61E3 # +0x9CEF U+61F6 # +0x9CF0 U+61FA # +0x9CF1 U+61F4 # +0x9CF2 U+61FF # +0x9CF3 U+61FD # +0x9CF4 U+61FC # +0x9CF5 U+61FE # +0x9CF6 U+6200 # +0x9CF7 U+6208 # +0x9CF8 U+6209 # +0x9CF9 U+620D # +0x9CFA U+620C # +0x9CFB U+6214 # +0x9CFC U+621B # +0x9D40 U+621E # +0x9D41 U+6221 # +0x9D42 U+622A # +0x9D43 U+622E # +0x9D44 U+6230 # +0x9D45 U+6232 # +0x9D46 U+6233 # +0x9D47 U+6241 # +0x9D48 U+624E # +0x9D49 U+625E # +0x9D4A U+6263 # +0x9D4B U+625B # +0x9D4C U+6260 # +0x9D4D U+6268 # +0x9D4E U+627C # +0x9D4F U+6282 # +0x9D50 U+6289 # +0x9D51 U+627E # +0x9D52 U+6292 # +0x9D53 U+6293 # +0x9D54 U+6296 # +0x9D55 U+62D4 # +0x9D56 U+6283 # +0x9D57 U+6294 # +0x9D58 U+62D7 # +0x9D59 U+62D1 # +0x9D5A U+62BB # +0x9D5B U+62CF # +0x9D5C U+62FF # +0x9D5D U+62C6 # +0x9D5E U+64D4 # +0x9D5F U+62C8 # +0x9D60 U+62DC # +0x9D61 U+62CC # +0x9D62 U+62CA # +0x9D63 U+62C2 # +0x9D64 U+62C7 # +0x9D65 U+629B # +0x9D66 U+62C9 # +0x9D67 U+630C # +0x9D68 U+62EE # +0x9D69 U+62F1 # +0x9D6A U+6327 # +0x9D6B U+6302 # +0x9D6C U+6308 # +0x9D6D U+62EF # +0x9D6E U+62F5 # +0x9D6F U+6350 # +0x9D70 U+633E # +0x9D71 U+634D # +0x9D72 U+641C # +0x9D73 U+634F # +0x9D74 U+6396 # +0x9D75 U+638E # +0x9D76 U+6380 # +0x9D77 U+63AB # +0x9D78 U+6376 # +0x9D79 U+63A3 # +0x9D7A U+638F # +0x9D7B U+6389 # +0x9D7C U+639F # +0x9D7D U+63B5 # +0x9D7E U+636B # +0x9D80 U+6369 # +0x9D81 U+63BE # +0x9D82 U+63E9 # +0x9D83 U+63C0 # +0x9D84 U+63C6 # +0x9D85 U+63E3 # +0x9D86 U+63C9 # +0x9D87 U+63D2 # +0x9D88 U+63F6 # +0x9D89 U+63C4 # +0x9D8A U+6416 # +0x9D8B U+6434 # +0x9D8C U+6406 # +0x9D8D U+6413 # +0x9D8E U+6426 # +0x9D8F U+6436 # +0x9D90 U+651D # +0x9D91 U+6417 # +0x9D92 U+6428 # +0x9D93 U+640F # +0x9D94 U+6467 # +0x9D95 U+646F # +0x9D96 U+6476 # +0x9D97 U+644E # +0x9D98 U+652A # +0x9D99 U+6495 # +0x9D9A U+6493 # +0x9D9B U+64A5 # +0x9D9C U+64A9 # +0x9D9D U+6488 # +0x9D9E U+64BC # +0x9D9F U+64DA # +0x9DA0 U+64D2 # +0x9DA1 U+64C5 # +0x9DA2 U+64C7 # +0x9DA3 U+64BB # +0x9DA4 U+64D8 # +0x9DA5 U+64C2 # +0x9DA6 U+64F1 # +0x9DA7 U+64E7 # +0x9DA8 U+8209 # +0x9DA9 U+64E0 # +0x9DAA U+64E1 # +0x9DAB U+62AC # +0x9DAC U+64E3 # +0x9DAD U+64EF # +0x9DAE U+652C # +0x9DAF U+64F6 # +0x9DB0 U+64F4 # +0x9DB1 U+64F2 # +0x9DB2 U+64FA # +0x9DB3 U+6500 # +0x9DB4 U+64FD # +0x9DB5 U+6518 # +0x9DB6 U+651C # +0x9DB7 U+6505 # +0x9DB8 U+6524 # +0x9DB9 U+6523 # +0x9DBA U+652B # +0x9DBB U+6534 # +0x9DBC U+6535 # +0x9DBD U+6537 # +0x9DBE U+6536 # +0x9DBF U+6538 # +0x9DC0 U+754B # +0x9DC1 U+6548 # +0x9DC2 U+6556 # +0x9DC3 U+6555 # +0x9DC4 U+654D # +0x9DC5 U+6558 # +0x9DC6 U+655E # +0x9DC7 U+655D # +0x9DC8 U+6572 # +0x9DC9 U+6578 # +0x9DCA U+6582 # +0x9DCB U+6583 # +0x9DCC U+8B8A # +0x9DCD U+659B # +0x9DCE U+659F # +0x9DCF U+65AB # +0x9DD0 U+65B7 # +0x9DD1 U+65C3 # +0x9DD2 U+65C6 # +0x9DD3 U+65C1 # +0x9DD4 U+65C4 # +0x9DD5 U+65CC # +0x9DD6 U+65D2 # +0x9DD7 U+65DB # +0x9DD8 U+65D9 # +0x9DD9 U+65E0 # +0x9DDA U+65E1 # +0x9DDB U+65F1 # +0x9DDC U+6772 # +0x9DDD U+660A # +0x9DDE U+6603 # +0x9DDF U+65FB # +0x9DE0 U+6773 # +0x9DE1 U+6635 # +0x9DE2 U+6636 # +0x9DE3 U+6634 # +0x9DE4 U+661C # +0x9DE5 U+664F # +0x9DE6 U+6644 # +0x9DE7 U+6649 # +0x9DE8 U+6641 # +0x9DE9 U+665E # +0x9DEA U+665D # +0x9DEB U+6664 # +0x9DEC U+6667 # +0x9DED U+6668 # +0x9DEE U+665F # +0x9DEF U+6662 # +0x9DF0 U+6670 # +0x9DF1 U+6683 # +0x9DF2 U+6688 # +0x9DF3 U+668E # +0x9DF4 U+6689 # +0x9DF5 U+6684 # +0x9DF6 U+6698 # +0x9DF7 U+669D # +0x9DF8 U+66C1 # +0x9DF9 U+66B9 # +0x9DFA U+66C9 # +0x9DFB U+66BE # +0x9DFC U+66BC # +0x9E40 U+66C4 # +0x9E41 U+66B8 # +0x9E42 U+66D6 # +0x9E43 U+66DA # +0x9E44 U+66E0 # +0x9E45 U+663F # +0x9E46 U+66E6 # +0x9E47 U+66E9 # +0x9E48 U+66F0 # +0x9E49 U+66F5 # +0x9E4A U+66F7 # +0x9E4B U+670F # +0x9E4C U+6716 # +0x9E4D U+671E # +0x9E4E U+6726 # +0x9E4F U+6727 # +0x9E50 U+9738 # +0x9E51 U+672E # +0x9E52 U+673F # +0x9E53 U+6736 # +0x9E54 U+6741 # +0x9E55 U+6738 # +0x9E56 U+6737 # +0x9E57 U+6746 # +0x9E58 U+675E # +0x9E59 U+6760 # +0x9E5A U+6759 # +0x9E5B U+6763 # +0x9E5C U+6764 # +0x9E5D U+6789 # +0x9E5E U+6770 # +0x9E5F U+67A9 # +0x9E60 U+677C # +0x9E61 U+676A # +0x9E62 U+678C # +0x9E63 U+678B # +0x9E64 U+67A6 # +0x9E65 U+67A1 # +0x9E66 U+6785 # +0x9E67 U+67B7 # +0x9E68 U+67EF # +0x9E69 U+67B4 # +0x9E6A U+67EC # +0x9E6B U+67B3 # +0x9E6C U+67E9 # +0x9E6D U+67B8 # +0x9E6E U+67E4 # +0x9E6F U+67DE # +0x9E70 U+67DD # +0x9E71 U+67E2 # +0x9E72 U+67EE # +0x9E73 U+67B9 # +0x9E74 U+67CE # +0x9E75 U+67C6 # +0x9E76 U+67E7 # +0x9E77 U+6A9C # +0x9E78 U+681E # +0x9E79 U+6846 # +0x9E7A U+6829 # +0x9E7B U+6840 # +0x9E7C U+684D # +0x9E7D U+6832 # +0x9E7E U+684E # +0x9E80 U+68B3 # +0x9E81 U+682B # +0x9E82 U+6859 # +0x9E83 U+6863 # +0x9E84 U+6877 # +0x9E85 U+687F # +0x9E86 U+689F # +0x9E87 U+688F # +0x9E88 U+68AD # +0x9E89 U+6894 # +0x9E8A U+689D # +0x9E8B U+689B # +0x9E8C U+6883 # +0x9E8D U+6AAE # +0x9E8E U+68B9 # +0x9E8F U+6874 # +0x9E90 U+68B5 # +0x9E91 U+68A0 # +0x9E92 U+68BA # +0x9E93 U+690F # +0x9E94 U+688D # +0x9E95 U+687E # +0x9E96 U+6901 # +0x9E97 U+68CA # +0x9E98 U+6908 # +0x9E99 U+68D8 # +0x9E9A U+6922 # +0x9E9B U+6926 # +0x9E9C U+68E1 # +0x9E9D U+690C # +0x9E9E U+68CD # +0x9E9F U+68D4 # +0x9EA0 U+68E7 # +0x9EA1 U+68D5 # +0x9EA2 U+6936 # +0x9EA3 U+6912 # +0x9EA4 U+6904 # +0x9EA5 U+68D7 # +0x9EA6 U+68E3 # +0x9EA7 U+6925 # +0x9EA8 U+68F9 # +0x9EA9 U+68E0 # +0x9EAA U+68EF # +0x9EAB U+6928 # +0x9EAC U+692A # +0x9EAD U+691A # +0x9EAE U+6923 # +0x9EAF U+6921 # +0x9EB0 U+68C6 # +0x9EB1 U+6979 # +0x9EB2 U+6977 # +0x9EB3 U+695C # +0x9EB4 U+6978 # +0x9EB5 U+696B # +0x9EB6 U+6954 # +0x9EB7 U+697E # +0x9EB8 U+696E # +0x9EB9 U+6939 # +0x9EBA U+6974 # +0x9EBB U+693D # +0x9EBC U+6959 # +0x9EBD U+6930 # +0x9EBE U+6961 # +0x9EBF U+695E # +0x9EC0 U+695D # +0x9EC1 U+6981 # +0x9EC2 U+696A # +0x9EC3 U+69B2 # +0x9EC4 U+69AE # +0x9EC5 U+69D0 # +0x9EC6 U+69BF # +0x9EC7 U+69C1 # +0x9EC8 U+69D3 # +0x9EC9 U+69BE # +0x9ECA U+69CE # +0x9ECB U+5BE8 # +0x9ECC U+69CA # +0x9ECD U+69DD # +0x9ECE U+69BB # +0x9ECF U+69C3 # +0x9ED0 U+69A7 # +0x9ED1 U+6A2E # +0x9ED2 U+6991 # +0x9ED3 U+69A0 # +0x9ED4 U+699C # +0x9ED5 U+6995 # +0x9ED6 U+69B4 # +0x9ED7 U+69DE # +0x9ED8 U+69E8 # +0x9ED9 U+6A02 # +0x9EDA U+6A1B # +0x9EDB U+69FF # +0x9EDC U+6B0A # +0x9EDD U+69F9 # +0x9EDE U+69F2 # +0x9EDF U+69E7 # +0x9EE0 U+6A05 # +0x9EE1 U+69B1 # +0x9EE2 U+6A1E # +0x9EE3 U+69ED # +0x9EE4 U+6A14 # +0x9EE5 U+69EB # +0x9EE6 U+6A0A # +0x9EE7 U+6A12 # +0x9EE8 U+6AC1 # +0x9EE9 U+6A23 # +0x9EEA U+6A13 # +0x9EEB U+6A44 # +0x9EEC U+6A0C # +0x9EED U+6A72 # +0x9EEE U+6A36 # +0x9EEF U+6A78 # +0x9EF0 U+6A47 # +0x9EF1 U+6A62 # +0x9EF2 U+6A59 # +0x9EF3 U+6A66 # +0x9EF4 U+6A48 # +0x9EF5 U+6A38 # +0x9EF6 U+6A22 # +0x9EF7 U+6A90 # +0x9EF8 U+6A8D # +0x9EF9 U+6AA0 # +0x9EFA U+6A84 # +0x9EFB U+6AA2 # +0x9EFC U+6AA3 # +0x9F40 U+6A97 # +0x9F41 U+8617 # +0x9F42 U+6ABB # +0x9F43 U+6AC3 # +0x9F44 U+6AC2 # +0x9F45 U+6AB8 # +0x9F46 U+6AB3 # +0x9F47 U+6AAC # +0x9F48 U+6ADE # +0x9F49 U+6AD1 # +0x9F4A U+6ADF # +0x9F4B U+6AAA # +0x9F4C U+6ADA # +0x9F4D U+6AEA # +0x9F4E U+6AFB # +0x9F4F U+6B05 # +0x9F50 U+8616 # +0x9F51 U+6AFA # +0x9F52 U+6B12 # +0x9F53 U+6B16 # +0x9F54 U+9B31 # +0x9F55 U+6B1F # +0x9F56 U+6B38 # +0x9F57 U+6B37 # +0x9F58 U+76DC # +0x9F59 U+6B39 # +0x9F5A U+98EE # +0x9F5B U+6B47 # +0x9F5C U+6B43 # +0x9F5D U+6B49 # +0x9F5E U+6B50 # +0x9F5F U+6B59 # +0x9F60 U+6B54 # +0x9F61 U+6B5B # +0x9F62 U+6B5F # +0x9F63 U+6B61 # +0x9F64 U+6B78 # +0x9F65 U+6B79 # +0x9F66 U+6B7F # +0x9F67 U+6B80 # +0x9F68 U+6B84 # +0x9F69 U+6B83 # +0x9F6A U+6B8D # +0x9F6B U+6B98 # +0x9F6C U+6B95 # +0x9F6D U+6B9E # +0x9F6E U+6BA4 # +0x9F6F U+6BAA # +0x9F70 U+6BAB # +0x9F71 U+6BAF # +0x9F72 U+6BB2 # +0x9F73 U+6BB1 # +0x9F74 U+6BB3 # +0x9F75 U+6BB7 # +0x9F76 U+6BBC # +0x9F77 U+6BC6 # +0x9F78 U+6BCB # +0x9F79 U+6BD3 # +0x9F7A U+6BDF # +0x9F7B U+6BEC # +0x9F7C U+6BEB # +0x9F7D U+6BF3 # +0x9F7E U+6BEF # +0x9F80 U+9EBE # +0x9F81 U+6C08 # +0x9F82 U+6C13 # +0x9F83 U+6C14 # +0x9F84 U+6C1B # +0x9F85 U+6C24 # +0x9F86 U+6C23 # +0x9F87 U+6C5E # +0x9F88 U+6C55 # +0x9F89 U+6C62 # +0x9F8A U+6C6A # +0x9F8B U+6C82 # +0x9F8C U+6C8D # +0x9F8D U+6C9A # +0x9F8E U+6C81 # +0x9F8F U+6C9B # +0x9F90 U+6C7E # +0x9F91 U+6C68 # +0x9F92 U+6C73 # +0x9F93 U+6C92 # +0x9F94 U+6C90 # +0x9F95 U+6CC4 # +0x9F96 U+6CF1 # +0x9F97 U+6CD3 # +0x9F98 U+6CBD # +0x9F99 U+6CD7 # +0x9F9A U+6CC5 # +0x9F9B U+6CDD # +0x9F9C U+6CAE # +0x9F9D U+6CB1 # +0x9F9E U+6CBE # +0x9F9F U+6CBA # +0x9FA0 U+6CDB # +0x9FA1 U+6CEF # +0x9FA2 U+6CD9 # +0x9FA3 U+6CEA # +0x9FA4 U+6D1F # +0x9FA5 U+884D # +0x9FA6 U+6D36 # +0x9FA7 U+6D2B # +0x9FA8 U+6D3D # +0x9FA9 U+6D38 # +0x9FAA U+6D19 # +0x9FAB U+6D35 # +0x9FAC U+6D33 # +0x9FAD U+6D12 # +0x9FAE U+6D0C # +0x9FAF U+6D63 # +0x9FB0 U+6D93 # +0x9FB1 U+6D64 # +0x9FB2 U+6D5A # +0x9FB3 U+6D79 # +0x9FB4 U+6D59 # +0x9FB5 U+6D8E # +0x9FB6 U+6D95 # +0x9FB7 U+6FE4 # +0x9FB8 U+6D85 # +0x9FB9 U+6DF9 # +0x9FBA U+6E15 # +0x9FBB U+6E0A # +0x9FBC U+6DB5 # +0x9FBD U+6DC7 # +0x9FBE U+6DE6 # +0x9FBF U+6DB8 # +0x9FC0 U+6DC6 # +0x9FC1 U+6DEC # +0x9FC2 U+6DDE # +0x9FC3 U+6DCC # +0x9FC4 U+6DE8 # +0x9FC5 U+6DD2 # +0x9FC6 U+6DC5 # +0x9FC7 U+6DFA # +0x9FC8 U+6DD9 # +0x9FC9 U+6DE4 # +0x9FCA U+6DD5 # +0x9FCB U+6DEA # +0x9FCC U+6DEE # +0x9FCD U+6E2D # +0x9FCE U+6E6E # +0x9FCF U+6E2E # +0x9FD0 U+6E19 # +0x9FD1 U+6E72 # +0x9FD2 U+6E5F # +0x9FD3 U+6E3E # +0x9FD4 U+6E23 # +0x9FD5 U+6E6B # +0x9FD6 U+6E2B # +0x9FD7 U+6E76 # +0x9FD8 U+6E4D # +0x9FD9 U+6E1F # +0x9FDA U+6E43 # +0x9FDB U+6E3A # +0x9FDC U+6E4E # +0x9FDD U+6E24 # +0x9FDE U+6EFF # +0x9FDF U+6E1D # +0x9FE0 U+6E38 # +0x9FE1 U+6E82 # +0x9FE2 U+6EAA # +0x9FE3 U+6E98 # +0x9FE4 U+6EC9 # +0x9FE5 U+6EB7 # +0x9FE6 U+6ED3 # +0x9FE7 U+6EBD # +0x9FE8 U+6EAF # +0x9FE9 U+6EC4 # +0x9FEA U+6EB2 # +0x9FEB U+6ED4 # +0x9FEC U+6ED5 # +0x9FED U+6E8F # +0x9FEE U+6EA5 # +0x9FEF U+6EC2 # +0x9FF0 U+6E9F # +0x9FF1 U+6F41 # +0x9FF2 U+6F11 # +0x9FF3 U+704C # +0x9FF4 U+6EEC # +0x9FF5 U+6EF8 # +0x9FF6 U+6EFE # +0x9FF7 U+6F3F # +0x9FF8 U+6EF2 # +0x9FF9 U+6F31 # +0x9FFA U+6EEF # +0x9FFB U+6F32 # +0x9FFC U+6ECC # +0xE040 U+6F3E # +0xE041 U+6F13 # +0xE042 U+6EF7 # +0xE043 U+6F86 # +0xE044 U+6F7A # +0xE045 U+6F78 # +0xE046 U+6F81 # +0xE047 U+6F80 # +0xE048 U+6F6F # +0xE049 U+6F5B # +0xE04A U+6FF3 # +0xE04B U+6F6D # +0xE04C U+6F82 # +0xE04D U+6F7C # +0xE04E U+6F58 # +0xE04F U+6F8E # +0xE050 U+6F91 # +0xE051 U+6FC2 # +0xE052 U+6F66 # +0xE053 U+6FB3 # +0xE054 U+6FA3 # +0xE055 U+6FA1 # +0xE056 U+6FA4 # +0xE057 U+6FB9 # +0xE058 U+6FC6 # +0xE059 U+6FAA # +0xE05A U+6FDF # +0xE05B U+6FD5 # +0xE05C U+6FEC # +0xE05D U+6FD4 # +0xE05E U+6FD8 # +0xE05F U+6FF1 # +0xE060 U+6FEE # +0xE061 U+6FDB # +0xE062 U+7009 # +0xE063 U+700B # +0xE064 U+6FFA # +0xE065 U+7011 # +0xE066 U+7001 # +0xE067 U+700F # +0xE068 U+6FFE # +0xE069 U+701B # +0xE06A U+701A # +0xE06B U+6F74 # +0xE06C U+701D # +0xE06D U+7018 # +0xE06E U+701F # +0xE06F U+7030 # +0xE070 U+703E # +0xE071 U+7032 # +0xE072 U+7051 # +0xE073 U+7063 # +0xE074 U+7099 # +0xE075 U+7092 # +0xE076 U+70AF # +0xE077 U+70F1 # +0xE078 U+70AC # +0xE079 U+70B8 # +0xE07A U+70B3 # +0xE07B U+70AE # +0xE07C U+70DF # +0xE07D U+70CB # +0xE07E U+70DD # +0xE080 U+70D9 # +0xE081 U+7109 # +0xE082 U+70FD # +0xE083 U+711C # +0xE084 U+7119 # +0xE085 U+7165 # +0xE086 U+7155 # +0xE087 U+7188 # +0xE088 U+7166 # +0xE089 U+7162 # +0xE08A U+714C # +0xE08B U+7156 # +0xE08C U+716C # +0xE08D U+718F # +0xE08E U+71FB # +0xE08F U+7184 # +0xE090 U+7195 # +0xE091 U+71A8 # +0xE092 U+71AC # +0xE093 U+71D7 # +0xE094 U+71B9 # +0xE095 U+71BE # +0xE096 U+71D2 # +0xE097 U+71C9 # +0xE098 U+71D4 # +0xE099 U+71CE # +0xE09A U+71E0 # +0xE09B U+71EC # +0xE09C U+71E7 # +0xE09D U+71F5 # +0xE09E U+71FC # +0xE09F U+71F9 # +0xE0A0 U+71FF # +0xE0A1 U+720D # +0xE0A2 U+7210 # +0xE0A3 U+721B # +0xE0A4 U+7228 # +0xE0A5 U+722D # +0xE0A6 U+722C # +0xE0A7 U+7230 # +0xE0A8 U+7232 # +0xE0A9 U+723B # +0xE0AA U+723C # +0xE0AB U+723F # +0xE0AC U+7240 # +0xE0AD U+7246 # +0xE0AE U+724B # +0xE0AF U+7258 # +0xE0B0 U+7274 # +0xE0B1 U+727E # +0xE0B2 U+7282 # +0xE0B3 U+7281 # +0xE0B4 U+7287 # +0xE0B5 U+7292 # +0xE0B6 U+7296 # +0xE0B7 U+72A2 # +0xE0B8 U+72A7 # +0xE0B9 U+72B9 # +0xE0BA U+72B2 # +0xE0BB U+72C3 # +0xE0BC U+72C6 # +0xE0BD U+72C4 # +0xE0BE U+72CE # +0xE0BF U+72D2 # +0xE0C0 U+72E2 # +0xE0C1 U+72E0 # +0xE0C2 U+72E1 # +0xE0C3 U+72F9 # +0xE0C4 U+72F7 # +0xE0C5 U+500F # +0xE0C6 U+7317 # +0xE0C7 U+730A # +0xE0C8 U+731C # +0xE0C9 U+7316 # +0xE0CA U+731D # +0xE0CB U+7334 # +0xE0CC U+732F # +0xE0CD U+7329 # +0xE0CE U+7325 # +0xE0CF U+733E # +0xE0D0 U+734E # +0xE0D1 U+734F # +0xE0D2 U+9ED8 # +0xE0D3 U+7357 # +0xE0D4 U+736A # +0xE0D5 U+7368 # +0xE0D6 U+7370 # +0xE0D7 U+7378 # +0xE0D8 U+7375 # +0xE0D9 U+737B # +0xE0DA U+737A # +0xE0DB U+73C8 # +0xE0DC U+73B3 # +0xE0DD U+73CE # +0xE0DE U+73BB # +0xE0DF U+73C0 # +0xE0E0 U+73E5 # +0xE0E1 U+73EE # +0xE0E2 U+73DE # +0xE0E3 U+74A2 # +0xE0E4 U+7405 # +0xE0E5 U+746F # +0xE0E6 U+7425 # +0xE0E7 U+73F8 # +0xE0E8 U+7432 # +0xE0E9 U+743A # +0xE0EA U+7455 # +0xE0EB U+743F # +0xE0EC U+745F # +0xE0ED U+7459 # +0xE0EE U+7441 # +0xE0EF U+745C # +0xE0F0 U+7469 # +0xE0F1 U+7470 # +0xE0F2 U+7463 # +0xE0F3 U+746A # +0xE0F4 U+7476 # +0xE0F5 U+747E # +0xE0F6 U+748B # +0xE0F7 U+749E # +0xE0F8 U+74A7 # +0xE0F9 U+74CA # +0xE0FA U+74CF # +0xE0FB U+74D4 # +0xE0FC U+73F1 # +0xE140 U+74E0 # +0xE141 U+74E3 # +0xE142 U+74E7 # +0xE143 U+74E9 # +0xE144 U+74EE # +0xE145 U+74F2 # +0xE146 U+74F0 # +0xE147 U+74F1 # +0xE148 U+74F8 # +0xE149 U+74F7 # +0xE14A U+7504 # +0xE14B U+7503 # +0xE14C U+7505 # +0xE14D U+750C # +0xE14E U+750E # +0xE14F U+750D # +0xE150 U+7515 # +0xE151 U+7513 # +0xE152 U+751E # +0xE153 U+7526 # +0xE154 U+752C # +0xE155 U+753C # +0xE156 U+7544 # +0xE157 U+754D # +0xE158 U+754A # +0xE159 U+7549 # +0xE15A U+755B # +0xE15B U+7546 # +0xE15C U+755A # +0xE15D U+7569 # +0xE15E U+7564 # +0xE15F U+7567 # +0xE160 U+756B # +0xE161 U+756D # +0xE162 U+7578 # +0xE163 U+7576 # +0xE164 U+7586 # +0xE165 U+7587 # +0xE166 U+7574 # +0xE167 U+758A # +0xE168 U+7589 # +0xE169 U+7582 # +0xE16A U+7594 # +0xE16B U+759A # +0xE16C U+759D # +0xE16D U+75A5 # +0xE16E U+75A3 # +0xE16F U+75C2 # +0xE170 U+75B3 # +0xE171 U+75C3 # +0xE172 U+75B5 # +0xE173 U+75BD # +0xE174 U+75B8 # +0xE175 U+75BC # +0xE176 U+75B1 # +0xE177 U+75CD # +0xE178 U+75CA # +0xE179 U+75D2 # +0xE17A U+75D9 # +0xE17B U+75E3 # +0xE17C U+75DE # +0xE17D U+75FE # +0xE17E U+75FF # +0xE180 U+75FC # +0xE181 U+7601 # +0xE182 U+75F0 # +0xE183 U+75FA # +0xE184 U+75F2 # +0xE185 U+75F3 # +0xE186 U+760B # +0xE187 U+760D # +0xE188 U+7609 # +0xE189 U+761F # +0xE18A U+7627 # +0xE18B U+7620 # +0xE18C U+7621 # +0xE18D U+7622 # +0xE18E U+7624 # +0xE18F U+7634 # +0xE190 U+7630 # +0xE191 U+763B # +0xE192 U+7647 # +0xE193 U+7648 # +0xE194 U+7646 # +0xE195 U+765C # +0xE196 U+7658 # +0xE197 U+7661 # +0xE198 U+7662 # +0xE199 U+7668 # +0xE19A U+7669 # +0xE19B U+766A # +0xE19C U+7667 # +0xE19D U+766C # +0xE19E U+7670 # +0xE19F U+7672 # +0xE1A0 U+7676 # +0xE1A1 U+7678 # +0xE1A2 U+767C # +0xE1A3 U+7680 # +0xE1A4 U+7683 # +0xE1A5 U+7688 # +0xE1A6 U+768B # +0xE1A7 U+768E # +0xE1A8 U+7696 # +0xE1A9 U+7693 # +0xE1AA U+7699 # +0xE1AB U+769A # +0xE1AC U+76B0 # +0xE1AD U+76B4 # +0xE1AE U+76B8 # +0xE1AF U+76B9 # +0xE1B0 U+76BA # +0xE1B1 U+76C2 # +0xE1B2 U+76CD # +0xE1B3 U+76D6 # +0xE1B4 U+76D2 # +0xE1B5 U+76DE # +0xE1B6 U+76E1 # +0xE1B7 U+76E5 # +0xE1B8 U+76E7 # +0xE1B9 U+76EA # +0xE1BA U+862F # +0xE1BB U+76FB # +0xE1BC U+7708 # +0xE1BD U+7707 # +0xE1BE U+7704 # +0xE1BF U+7729 # +0xE1C0 U+7724 # +0xE1C1 U+771E # +0xE1C2 U+7725 # +0xE1C3 U+7726 # +0xE1C4 U+771B # +0xE1C5 U+7737 # +0xE1C6 U+7738 # +0xE1C7 U+7747 # +0xE1C8 U+775A # +0xE1C9 U+7768 # +0xE1CA U+776B # +0xE1CB U+775B # +0xE1CC U+7765 # +0xE1CD U+777F # +0xE1CE U+777E # +0xE1CF U+7779 # +0xE1D0 U+778E # +0xE1D1 U+778B # +0xE1D2 U+7791 # +0xE1D3 U+77A0 # +0xE1D4 U+779E # +0xE1D5 U+77B0 # +0xE1D6 U+77B6 # +0xE1D7 U+77B9 # +0xE1D8 U+77BF # +0xE1D9 U+77BC # +0xE1DA U+77BD # +0xE1DB U+77BB # +0xE1DC U+77C7 # +0xE1DD U+77CD # +0xE1DE U+77D7 # +0xE1DF U+77DA # +0xE1E0 U+77DC # +0xE1E1 U+77E3 # +0xE1E2 U+77EE # +0xE1E3 U+77FC # +0xE1E4 U+780C # +0xE1E5 U+7812 # +0xE1E6 U+7926 # +0xE1E7 U+7820 # +0xE1E8 U+792A # +0xE1E9 U+7845 # +0xE1EA U+788E # +0xE1EB U+7874 # +0xE1EC U+7886 # +0xE1ED U+787C # +0xE1EE U+789A # +0xE1EF U+788C # +0xE1F0 U+78A3 # +0xE1F1 U+78B5 # +0xE1F2 U+78AA # +0xE1F3 U+78AF # +0xE1F4 U+78D1 # +0xE1F5 U+78C6 # +0xE1F6 U+78CB # +0xE1F7 U+78D4 # +0xE1F8 U+78BE # +0xE1F9 U+78BC # +0xE1FA U+78C5 # +0xE1FB U+78CA # +0xE1FC U+78EC # +0xE240 U+78E7 # +0xE241 U+78DA # +0xE242 U+78FD # +0xE243 U+78F4 # +0xE244 U+7907 # +0xE245 U+7912 # +0xE246 U+7911 # +0xE247 U+7919 # +0xE248 U+792C # +0xE249 U+792B # +0xE24A U+7940 # +0xE24B U+7960 # +0xE24C U+7957 # +0xE24D U+795F # +0xE24E U+795A # +0xE24F U+7955 # +0xE250 U+7953 # +0xE251 U+797A # +0xE252 U+797F # +0xE253 U+798A # +0xE254 U+799D # +0xE255 U+79A7 # +0xE256 U+9F4B # +0xE257 U+79AA # +0xE258 U+79AE # +0xE259 U+79B3 # +0xE25A U+79B9 # +0xE25B U+79BA # +0xE25C U+79C9 # +0xE25D U+79D5 # +0xE25E U+79E7 # +0xE25F U+79EC # +0xE260 U+79E1 # +0xE261 U+79E3 # +0xE262 U+7A08 # +0xE263 U+7A0D # +0xE264 U+7A18 # +0xE265 U+7A19 # +0xE266 U+7A20 # +0xE267 U+7A1F # +0xE268 U+7980 # +0xE269 U+7A31 # +0xE26A U+7A3B # +0xE26B U+7A3E # +0xE26C U+7A37 # +0xE26D U+7A43 # +0xE26E U+7A57 # +0xE26F U+7A49 # +0xE270 U+7A61 # +0xE271 U+7A62 # +0xE272 U+7A69 # +0xE273 U+9F9D # +0xE274 U+7A70 # +0xE275 U+7A79 # +0xE276 U+7A7D # +0xE277 U+7A88 # +0xE278 U+7A97 # +0xE279 U+7A95 # +0xE27A U+7A98 # +0xE27B U+7A96 # +0xE27C U+7AA9 # +0xE27D U+7AC8 # +0xE27E U+7AB0 # +0xE280 U+7AB6 # +0xE281 U+7AC5 # +0xE282 U+7AC4 # +0xE283 U+7ABF # +0xE284 U+9083 # +0xE285 U+7AC7 # +0xE286 U+7ACA # +0xE287 U+7ACD # +0xE288 U+7ACF # +0xE289 U+7AD5 # +0xE28A U+7AD3 # +0xE28B U+7AD9 # +0xE28C U+7ADA # +0xE28D U+7ADD # +0xE28E U+7AE1 # +0xE28F U+7AE2 # +0xE290 U+7AE6 # +0xE291 U+7AED # +0xE292 U+7AF0 # +0xE293 U+7B02 # +0xE294 U+7B0F # +0xE295 U+7B0A # +0xE296 U+7B06 # +0xE297 U+7B33 # +0xE298 U+7B18 # +0xE299 U+7B19 # +0xE29A U+7B1E # +0xE29B U+7B35 # +0xE29C U+7B28 # +0xE29D U+7B36 # +0xE29E U+7B50 # +0xE29F U+7B7A # +0xE2A0 U+7B04 # +0xE2A1 U+7B4D # +0xE2A2 U+7B0B # +0xE2A3 U+7B4C # +0xE2A4 U+7B45 # +0xE2A5 U+7B75 # +0xE2A6 U+7B65 # +0xE2A7 U+7B74 # +0xE2A8 U+7B67 # +0xE2A9 U+7B70 # +0xE2AA U+7B71 # +0xE2AB U+7B6C # +0xE2AC U+7B6E # +0xE2AD U+7B9D # +0xE2AE U+7B98 # +0xE2AF U+7B9F # +0xE2B0 U+7B8D # +0xE2B1 U+7B9C # +0xE2B2 U+7B9A # +0xE2B3 U+7B8B # +0xE2B4 U+7B92 # +0xE2B5 U+7B8F # +0xE2B6 U+7B5D # +0xE2B7 U+7B99 # +0xE2B8 U+7BCB # +0xE2B9 U+7BC1 # +0xE2BA U+7BCC # +0xE2BB U+7BCF # +0xE2BC U+7BB4 # +0xE2BD U+7BC6 # +0xE2BE U+7BDD # +0xE2BF U+7BE9 # +0xE2C0 U+7C11 # +0xE2C1 U+7C14 # +0xE2C2 U+7BE6 # +0xE2C3 U+7BE5 # +0xE2C4 U+7C60 # +0xE2C5 U+7C00 # +0xE2C6 U+7C07 # +0xE2C7 U+7C13 # +0xE2C8 U+7BF3 # +0xE2C9 U+7BF7 # +0xE2CA U+7C17 # +0xE2CB U+7C0D # +0xE2CC U+7BF6 # +0xE2CD U+7C23 # +0xE2CE U+7C27 # +0xE2CF U+7C2A # +0xE2D0 U+7C1F # +0xE2D1 U+7C37 # +0xE2D2 U+7C2B # +0xE2D3 U+7C3D # +0xE2D4 U+7C4C # +0xE2D5 U+7C43 # +0xE2D6 U+7C54 # +0xE2D7 U+7C4F # +0xE2D8 U+7C40 # +0xE2D9 U+7C50 # +0xE2DA U+7C58 # +0xE2DB U+7C5F # +0xE2DC U+7C64 # +0xE2DD U+7C56 # +0xE2DE U+7C65 # +0xE2DF U+7C6C # +0xE2E0 U+7C75 # +0xE2E1 U+7C83 # +0xE2E2 U+7C90 # +0xE2E3 U+7CA4 # +0xE2E4 U+7CAD # +0xE2E5 U+7CA2 # +0xE2E6 U+7CAB # +0xE2E7 U+7CA1 # +0xE2E8 U+7CA8 # +0xE2E9 U+7CB3 # +0xE2EA U+7CB2 # +0xE2EB U+7CB1 # +0xE2EC U+7CAE # +0xE2ED U+7CB9 # +0xE2EE U+7CBD # +0xE2EF U+7CC0 # +0xE2F0 U+7CC5 # +0xE2F1 U+7CC2 # +0xE2F2 U+7CD8 # +0xE2F3 U+7CD2 # +0xE2F4 U+7CDC # +0xE2F5 U+7CE2 # +0xE2F6 U+9B3B # +0xE2F7 U+7CEF # +0xE2F8 U+7CF2 # +0xE2F9 U+7CF4 # +0xE2FA U+7CF6 # +0xE2FB U+7CFA # +0xE2FC U+7D06 # +0xE340 U+7D02 # +0xE341 U+7D1C # +0xE342 U+7D15 # +0xE343 U+7D0A # +0xE344 U+7D45 # +0xE345 U+7D4B # +0xE346 U+7D2E # +0xE347 U+7D32 # +0xE348 U+7D3F # +0xE349 U+7D35 # +0xE34A U+7D46 # +0xE34B U+7D73 # +0xE34C U+7D56 # +0xE34D U+7D4E # +0xE34E U+7D72 # +0xE34F U+7D68 # +0xE350 U+7D6E # +0xE351 U+7D4F # +0xE352 U+7D63 # +0xE353 U+7D93 # +0xE354 U+7D89 # +0xE355 U+7D5B # +0xE356 U+7D8F # +0xE357 U+7D7D # +0xE358 U+7D9B # +0xE359 U+7DBA # +0xE35A U+7DAE # +0xE35B U+7DA3 # +0xE35C U+7DB5 # +0xE35D U+7DC7 # +0xE35E U+7DBD # +0xE35F U+7DAB # +0xE360 U+7E3D # +0xE361 U+7DA2 # +0xE362 U+7DAF # +0xE363 U+7DDC # +0xE364 U+7DB8 # +0xE365 U+7D9F # +0xE366 U+7DB0 # +0xE367 U+7DD8 # +0xE368 U+7DDD # +0xE369 U+7DE4 # +0xE36A U+7DDE # +0xE36B U+7DFB # +0xE36C U+7DF2 # +0xE36D U+7DE1 # +0xE36E U+7E05 # +0xE36F U+7E0A # +0xE370 U+7E23 # +0xE371 U+7E21 # +0xE372 U+7E12 # +0xE373 U+7E31 # +0xE374 U+7E1F # +0xE375 U+7E09 # +0xE376 U+7E0B # +0xE377 U+7E22 # +0xE378 U+7E46 # +0xE379 U+7E66 # +0xE37A U+7E3B # +0xE37B U+7E35 # +0xE37C U+7E39 # +0xE37D U+7E43 # +0xE37E U+7E37 # +0xE380 U+7E32 # +0xE381 U+7E3A # +0xE382 U+7E67 # +0xE383 U+7E5D # +0xE384 U+7E56 # +0xE385 U+7E5E # +0xE386 U+7E59 # +0xE387 U+7E5A # +0xE388 U+7E79 # +0xE389 U+7E6A # +0xE38A U+7E69 # +0xE38B U+7E7C # +0xE38C U+7E7B # +0xE38D U+7E83 # +0xE38E U+7DD5 # +0xE38F U+7E7D # +0xE390 U+8FAE # +0xE391 U+7E7F # +0xE392 U+7E88 # +0xE393 U+7E89 # +0xE394 U+7E8C # +0xE395 U+7E92 # +0xE396 U+7E90 # +0xE397 U+7E93 # +0xE398 U+7E94 # +0xE399 U+7E96 # +0xE39A U+7E8E # +0xE39B U+7E9B # +0xE39C U+7E9C # +0xE39D U+7F38 # +0xE39E U+7F3A # +0xE39F U+7F45 # +0xE3A0 U+7F4C # +0xE3A1 U+7F4D # +0xE3A2 U+7F4E # +0xE3A3 U+7F50 # +0xE3A4 U+7F51 # +0xE3A5 U+7F55 # +0xE3A6 U+7F54 # +0xE3A7 U+7F58 # +0xE3A8 U+7F5F # +0xE3A9 U+7F60 # +0xE3AA U+7F68 # +0xE3AB U+7F69 # +0xE3AC U+7F67 # +0xE3AD U+7F78 # +0xE3AE U+7F82 # +0xE3AF U+7F86 # +0xE3B0 U+7F83 # +0xE3B1 U+7F88 # +0xE3B2 U+7F87 # +0xE3B3 U+7F8C # +0xE3B4 U+7F94 # +0xE3B5 U+7F9E # +0xE3B6 U+7F9D # +0xE3B7 U+7F9A # +0xE3B8 U+7FA3 # +0xE3B9 U+7FAF # +0xE3BA U+7FB2 # +0xE3BB U+7FB9 # +0xE3BC U+7FAE # +0xE3BD U+7FB6 # +0xE3BE U+7FB8 # +0xE3BF U+8B71 # +0xE3C0 U+7FC5 # +0xE3C1 U+7FC6 # +0xE3C2 U+7FCA # +0xE3C3 U+7FD5 # +0xE3C4 U+7FD4 # +0xE3C5 U+7FE1 # +0xE3C6 U+7FE6 # +0xE3C7 U+7FE9 # +0xE3C8 U+7FF3 # +0xE3C9 U+7FF9 # +0xE3CA U+98DC # +0xE3CB U+8006 # +0xE3CC U+8004 # +0xE3CD U+800B # +0xE3CE U+8012 # +0xE3CF U+8018 # +0xE3D0 U+8019 # +0xE3D1 U+801C # +0xE3D2 U+8021 # +0xE3D3 U+8028 # +0xE3D4 U+803F # +0xE3D5 U+803B # +0xE3D6 U+804A # +0xE3D7 U+8046 # +0xE3D8 U+8052 # +0xE3D9 U+8058 # +0xE3DA U+805A # +0xE3DB U+805F # +0xE3DC U+8062 # +0xE3DD U+8068 # +0xE3DE U+8073 # +0xE3DF U+8072 # +0xE3E0 U+8070 # +0xE3E1 U+8076 # +0xE3E2 U+8079 # +0xE3E3 U+807D # +0xE3E4 U+807F # +0xE3E5 U+8084 # +0xE3E6 U+8086 # +0xE3E7 U+8085 # +0xE3E8 U+809B # +0xE3E9 U+8093 # +0xE3EA U+809A # +0xE3EB U+80AD # +0xE3EC U+5190 # +0xE3ED U+80AC # +0xE3EE U+80DB # +0xE3EF U+80E5 # +0xE3F0 U+80D9 # +0xE3F1 U+80DD # +0xE3F2 U+80C4 # +0xE3F3 U+80DA # +0xE3F4 U+80D6 # +0xE3F5 U+8109 # +0xE3F6 U+80EF # +0xE3F7 U+80F1 # +0xE3F8 U+811B # +0xE3F9 U+8129 # +0xE3FA U+8123 # +0xE3FB U+812F # +0xE3FC U+814B # +0xE440 U+968B # +0xE441 U+8146 # +0xE442 U+813E # +0xE443 U+8153 # +0xE444 U+8151 # +0xE445 U+80FC # +0xE446 U+8171 # +0xE447 U+816E # +0xE448 U+8165 # +0xE449 U+8166 # +0xE44A U+8174 # +0xE44B U+8183 # +0xE44C U+8188 # +0xE44D U+818A # +0xE44E U+8180 # +0xE44F U+8182 # +0xE450 U+81A0 # +0xE451 U+8195 # +0xE452 U+81A4 # +0xE453 U+81A3 # +0xE454 U+815F # +0xE455 U+8193 # +0xE456 U+81A9 # +0xE457 U+81B0 # +0xE458 U+81B5 # +0xE459 U+81BE # +0xE45A U+81B8 # +0xE45B U+81BD # +0xE45C U+81C0 # +0xE45D U+81C2 # +0xE45E U+81BA # +0xE45F U+81C9 # +0xE460 U+81CD # +0xE461 U+81D1 # +0xE462 U+81D9 # +0xE463 U+81D8 # +0xE464 U+81C8 # +0xE465 U+81DA # +0xE466 U+81DF # +0xE467 U+81E0 # +0xE468 U+81E7 # +0xE469 U+81FA # +0xE46A U+81FB # +0xE46B U+81FE # +0xE46C U+8201 # +0xE46D U+8202 # +0xE46E U+8205 # +0xE46F U+8207 # +0xE470 U+820A # +0xE471 U+820D # +0xE472 U+8210 # +0xE473 U+8216 # +0xE474 U+8229 # +0xE475 U+822B # +0xE476 U+8238 # +0xE477 U+8233 # +0xE478 U+8240 # +0xE479 U+8259 # +0xE47A U+8258 # +0xE47B U+825D # +0xE47C U+825A # +0xE47D U+825F # +0xE47E U+8264 # +0xE480 U+8262 # +0xE481 U+8268 # +0xE482 U+826A # +0xE483 U+826B # +0xE484 U+822E # +0xE485 U+8271 # +0xE486 U+8277 # +0xE487 U+8278 # +0xE488 U+827E # +0xE489 U+828D # +0xE48A U+8292 # +0xE48B U+82AB # +0xE48C U+829F # +0xE48D U+82BB # +0xE48E U+82AC # +0xE48F U+82E1 # +0xE490 U+82E3 # +0xE491 U+82DF # +0xE492 U+82D2 # +0xE493 U+82F4 # +0xE494 U+82F3 # +0xE495 U+82FA # +0xE496 U+8393 # +0xE497 U+8303 # +0xE498 U+82FB # +0xE499 U+82F9 # +0xE49A U+82DE # +0xE49B U+8306 # +0xE49C U+82DC # +0xE49D U+8309 # +0xE49E U+82D9 # +0xE49F U+8335 # +0xE4A0 U+8334 # +0xE4A1 U+8316 # +0xE4A2 U+8332 # +0xE4A3 U+8331 # +0xE4A4 U+8340 # +0xE4A5 U+8339 # +0xE4A6 U+8350 # +0xE4A7 U+8345 # +0xE4A8 U+832F # +0xE4A9 U+832B # +0xE4AA U+8317 # +0xE4AB U+8318 # +0xE4AC U+8385 # +0xE4AD U+839A # +0xE4AE U+83AA # +0xE4AF U+839F # +0xE4B0 U+83A2 # +0xE4B1 U+8396 # +0xE4B2 U+8323 # +0xE4B3 U+838E # +0xE4B4 U+8387 # +0xE4B5 U+838A # +0xE4B6 U+837C # +0xE4B7 U+83B5 # +0xE4B8 U+8373 # +0xE4B9 U+8375 # +0xE4BA U+83A0 # +0xE4BB U+8389 # +0xE4BC U+83A8 # +0xE4BD U+83F4 # +0xE4BE U+8413 # +0xE4BF U+83EB # +0xE4C0 U+83CE # +0xE4C1 U+83FD # +0xE4C2 U+8403 # +0xE4C3 U+83D8 # +0xE4C4 U+840B # +0xE4C5 U+83C1 # +0xE4C6 U+83F7 # +0xE4C7 U+8407 # +0xE4C8 U+83E0 # +0xE4C9 U+83F2 # +0xE4CA U+840D # +0xE4CB U+8422 # +0xE4CC U+8420 # +0xE4CD U+83BD # +0xE4CE U+8438 # +0xE4CF U+8506 # +0xE4D0 U+83FB # +0xE4D1 U+846D # +0xE4D2 U+842A # +0xE4D3 U+843C # +0xE4D4 U+855A # +0xE4D5 U+8484 # +0xE4D6 U+8477 # +0xE4D7 U+846B # +0xE4D8 U+84AD # +0xE4D9 U+846E # +0xE4DA U+8482 # +0xE4DB U+8469 # +0xE4DC U+8446 # +0xE4DD U+842C # +0xE4DE U+846F # +0xE4DF U+8479 # +0xE4E0 U+8435 # +0xE4E1 U+84CA # +0xE4E2 U+8462 # +0xE4E3 U+84B9 # +0xE4E4 U+84BF # +0xE4E5 U+849F # +0xE4E6 U+84D9 # +0xE4E7 U+84CD # +0xE4E8 U+84BB # +0xE4E9 U+84DA # +0xE4EA U+84D0 # +0xE4EB U+84C1 # +0xE4EC U+84C6 # +0xE4ED U+84D6 # +0xE4EE U+84A1 # +0xE4EF U+8521 # +0xE4F0 U+84FF # +0xE4F1 U+84F4 # +0xE4F2 U+8517 # +0xE4F3 U+8518 # +0xE4F4 U+852C # +0xE4F5 U+851F # +0xE4F6 U+8515 # +0xE4F7 U+8514 # +0xE4F8 U+84FC # +0xE4F9 U+8540 # +0xE4FA U+8563 # +0xE4FB U+8558 # +0xE4FC U+8548 # +0xE540 U+8541 # +0xE541 U+8602 # +0xE542 U+854B # +0xE543 U+8555 # +0xE544 U+8580 # +0xE545 U+85A4 # +0xE546 U+8588 # +0xE547 U+8591 # +0xE548 U+858A # +0xE549 U+85A8 # +0xE54A U+856D # +0xE54B U+8594 # +0xE54C U+859B # +0xE54D U+85EA # +0xE54E U+8587 # +0xE54F U+859C # +0xE550 U+8577 # +0xE551 U+857E # +0xE552 U+8590 # +0xE553 U+85C9 # +0xE554 U+85BA # +0xE555 U+85CF # +0xE556 U+85B9 # +0xE557 U+85D0 # +0xE558 U+85D5 # +0xE559 U+85DD # +0xE55A U+85E5 # +0xE55B U+85DC # +0xE55C U+85F9 # +0xE55D U+860A # +0xE55E U+8613 # +0xE55F U+860B # +0xE560 U+85FE # +0xE561 U+85FA # +0xE562 U+8606 # +0xE563 U+8622 # +0xE564 U+861A # +0xE565 U+8630 # +0xE566 U+863F # +0xE567 U+864D # +0xE568 U+4E55 # +0xE569 U+8654 # +0xE56A U+865F # +0xE56B U+8667 # +0xE56C U+8671 # +0xE56D U+8693 # +0xE56E U+86A3 # +0xE56F U+86A9 # +0xE570 U+86AA # +0xE571 U+868B # +0xE572 U+868C # +0xE573 U+86B6 # +0xE574 U+86AF # +0xE575 U+86C4 # +0xE576 U+86C6 # +0xE577 U+86B0 # +0xE578 U+86C9 # +0xE579 U+8823 # +0xE57A U+86AB # +0xE57B U+86D4 # +0xE57C U+86DE # +0xE57D U+86E9 # +0xE57E U+86EC # +0xE580 U+86DF # +0xE581 U+86DB # +0xE582 U+86EF # +0xE583 U+8712 # +0xE584 U+8706 # +0xE585 U+8708 # +0xE586 U+8700 # +0xE587 U+8703 # +0xE588 U+86FB # +0xE589 U+8711 # +0xE58A U+8709 # +0xE58B U+870D # +0xE58C U+86F9 # +0xE58D U+870A # +0xE58E U+8734 # +0xE58F U+873F # +0xE590 U+8737 # +0xE591 U+873B # +0xE592 U+8725 # +0xE593 U+8729 # +0xE594 U+871A # +0xE595 U+8760 # +0xE596 U+875F # +0xE597 U+8778 # +0xE598 U+874C # +0xE599 U+874E # +0xE59A U+8774 # +0xE59B U+8757 # +0xE59C U+8768 # +0xE59D U+876E # +0xE59E U+8759 # +0xE59F U+8753 # +0xE5A0 U+8763 # +0xE5A1 U+876A # +0xE5A2 U+8805 # +0xE5A3 U+87A2 # +0xE5A4 U+879F # +0xE5A5 U+8782 # +0xE5A6 U+87AF # +0xE5A7 U+87CB # +0xE5A8 U+87BD # +0xE5A9 U+87C0 # +0xE5AA U+87D0 # +0xE5AB U+96D6 # +0xE5AC U+87AB # +0xE5AD U+87C4 # +0xE5AE U+87B3 # +0xE5AF U+87C7 # +0xE5B0 U+87C6 # +0xE5B1 U+87BB # +0xE5B2 U+87EF # +0xE5B3 U+87F2 # +0xE5B4 U+87E0 # +0xE5B5 U+880F # +0xE5B6 U+880D # +0xE5B7 U+87FE # +0xE5B8 U+87F6 # +0xE5B9 U+87F7 # +0xE5BA U+880E # +0xE5BB U+87D2 # +0xE5BC U+8811 # +0xE5BD U+8816 # +0xE5BE U+8815 # +0xE5BF U+8822 # +0xE5C0 U+8821 # +0xE5C1 U+8831 # +0xE5C2 U+8836 # +0xE5C3 U+8839 # +0xE5C4 U+8827 # +0xE5C5 U+883B # +0xE5C6 U+8844 # +0xE5C7 U+8842 # +0xE5C8 U+8852 # +0xE5C9 U+8859 # +0xE5CA U+885E # +0xE5CB U+8862 # +0xE5CC U+886B # +0xE5CD U+8881 # +0xE5CE U+887E # +0xE5CF U+889E # +0xE5D0 U+8875 # +0xE5D1 U+887D # +0xE5D2 U+88B5 # +0xE5D3 U+8872 # +0xE5D4 U+8882 # +0xE5D5 U+8897 # +0xE5D6 U+8892 # +0xE5D7 U+88AE # +0xE5D8 U+8899 # +0xE5D9 U+88A2 # +0xE5DA U+888D # +0xE5DB U+88A4 # +0xE5DC U+88B0 # +0xE5DD U+88BF # +0xE5DE U+88B1 # +0xE5DF U+88C3 # +0xE5E0 U+88C4 # +0xE5E1 U+88D4 # +0xE5E2 U+88D8 # +0xE5E3 U+88D9 # +0xE5E4 U+88DD # +0xE5E5 U+88F9 # +0xE5E6 U+8902 # +0xE5E7 U+88FC # +0xE5E8 U+88F4 # +0xE5E9 U+88E8 # +0xE5EA U+88F2 # +0xE5EB U+8904 # +0xE5EC U+890C # +0xE5ED U+890A # +0xE5EE U+8913 # +0xE5EF U+8943 # +0xE5F0 U+891E # +0xE5F1 U+8925 # +0xE5F2 U+892A # +0xE5F3 U+892B # +0xE5F4 U+8941 # +0xE5F5 U+8944 # +0xE5F6 U+893B # +0xE5F7 U+8936 # +0xE5F8 U+8938 # +0xE5F9 U+894C # +0xE5FA U+891D # +0xE5FB U+8960 # +0xE5FC U+895E # +0xE640 U+8966 # +0xE641 U+8964 # +0xE642 U+896D # +0xE643 U+896A # +0xE644 U+896F # +0xE645 U+8974 # +0xE646 U+8977 # +0xE647 U+897E # +0xE648 U+8983 # +0xE649 U+8988 # +0xE64A U+898A # +0xE64B U+8993 # +0xE64C U+8998 # +0xE64D U+89A1 # +0xE64E U+89A9 # +0xE64F U+89A6 # +0xE650 U+89AC # +0xE651 U+89AF # +0xE652 U+89B2 # +0xE653 U+89BA # +0xE654 U+89BD # +0xE655 U+89BF # +0xE656 U+89C0 # +0xE657 U+89DA # +0xE658 U+89DC # +0xE659 U+89DD # +0xE65A U+89E7 # +0xE65B U+89F4 # +0xE65C U+89F8 # +0xE65D U+8A03 # +0xE65E U+8A16 # +0xE65F U+8A10 # +0xE660 U+8A0C # +0xE661 U+8A1B # +0xE662 U+8A1D # +0xE663 U+8A25 # +0xE664 U+8A36 # +0xE665 U+8A41 # +0xE666 U+8A5B # +0xE667 U+8A52 # +0xE668 U+8A46 # +0xE669 U+8A48 # +0xE66A U+8A7C # +0xE66B U+8A6D # +0xE66C U+8A6C # +0xE66D U+8A62 # +0xE66E U+8A85 # +0xE66F U+8A82 # +0xE670 U+8A84 # +0xE671 U+8AA8 # +0xE672 U+8AA1 # +0xE673 U+8A91 # +0xE674 U+8AA5 # +0xE675 U+8AA6 # +0xE676 U+8A9A # +0xE677 U+8AA3 # +0xE678 U+8AC4 # +0xE679 U+8ACD # +0xE67A U+8AC2 # +0xE67B U+8ADA # +0xE67C U+8AEB # +0xE67D U+8AF3 # +0xE67E U+8AE7 # +0xE680 U+8AE4 # +0xE681 U+8AF1 # +0xE682 U+8B14 # +0xE683 U+8AE0 # +0xE684 U+8AE2 # +0xE685 U+8AF7 # +0xE686 U+8ADE # +0xE687 U+8ADB # +0xE688 U+8B0C # +0xE689 U+8B07 # +0xE68A U+8B1A # +0xE68B U+8AE1 # +0xE68C U+8B16 # +0xE68D U+8B10 # +0xE68E U+8B17 # +0xE68F U+8B20 # +0xE690 U+8B33 # +0xE691 U+97AB # +0xE692 U+8B26 # +0xE693 U+8B2B # +0xE694 U+8B3E # +0xE695 U+8B28 # +0xE696 U+8B41 # +0xE697 U+8B4C # +0xE698 U+8B4F # +0xE699 U+8B4E # +0xE69A U+8B49 # +0xE69B U+8B56 # +0xE69C U+8B5B # +0xE69D U+8B5A # +0xE69E U+8B6B # +0xE69F U+8B5F # +0xE6A0 U+8B6C # +0xE6A1 U+8B6F # +0xE6A2 U+8B74 # +0xE6A3 U+8B7D # +0xE6A4 U+8B80 # +0xE6A5 U+8B8C # +0xE6A6 U+8B8E # +0xE6A7 U+8B92 # +0xE6A8 U+8B93 # +0xE6A9 U+8B96 # +0xE6AA U+8B99 # +0xE6AB U+8B9A # +0xE6AC U+8C3A # +0xE6AD U+8C41 # +0xE6AE U+8C3F # +0xE6AF U+8C48 # +0xE6B0 U+8C4C # +0xE6B1 U+8C4E # +0xE6B2 U+8C50 # +0xE6B3 U+8C55 # +0xE6B4 U+8C62 # +0xE6B5 U+8C6C # +0xE6B6 U+8C78 # +0xE6B7 U+8C7A # +0xE6B8 U+8C82 # +0xE6B9 U+8C89 # +0xE6BA U+8C85 # +0xE6BB U+8C8A # +0xE6BC U+8C8D # +0xE6BD U+8C8E # +0xE6BE U+8C94 # +0xE6BF U+8C7C # +0xE6C0 U+8C98 # +0xE6C1 U+621D # +0xE6C2 U+8CAD # +0xE6C3 U+8CAA # +0xE6C4 U+8CBD # +0xE6C5 U+8CB2 # +0xE6C6 U+8CB3 # +0xE6C7 U+8CAE # +0xE6C8 U+8CB6 # +0xE6C9 U+8CC8 # +0xE6CA U+8CC1 # +0xE6CB U+8CE4 # +0xE6CC U+8CE3 # +0xE6CD U+8CDA # +0xE6CE U+8CFD # +0xE6CF U+8CFA # +0xE6D0 U+8CFB # +0xE6D1 U+8D04 # +0xE6D2 U+8D05 # +0xE6D3 U+8D0A # +0xE6D4 U+8D07 # +0xE6D5 U+8D0F # +0xE6D6 U+8D0D # +0xE6D7 U+8D10 # +0xE6D8 U+9F4E # +0xE6D9 U+8D13 # +0xE6DA U+8CCD # +0xE6DB U+8D14 # +0xE6DC U+8D16 # +0xE6DD U+8D67 # +0xE6DE U+8D6D # +0xE6DF U+8D71 # +0xE6E0 U+8D73 # +0xE6E1 U+8D81 # +0xE6E2 U+8D99 # +0xE6E3 U+8DC2 # +0xE6E4 U+8DBE # +0xE6E5 U+8DBA # +0xE6E6 U+8DCF # +0xE6E7 U+8DDA # +0xE6E8 U+8DD6 # +0xE6E9 U+8DCC # +0xE6EA U+8DDB # +0xE6EB U+8DCB # +0xE6EC U+8DEA # +0xE6ED U+8DEB # +0xE6EE U+8DDF # +0xE6EF U+8DE3 # +0xE6F0 U+8DFC # +0xE6F1 U+8E08 # +0xE6F2 U+8E09 # +0xE6F3 U+8DFF # +0xE6F4 U+8E1D # +0xE6F5 U+8E1E # +0xE6F6 U+8E10 # +0xE6F7 U+8E1F # +0xE6F8 U+8E42 # +0xE6F9 U+8E35 # +0xE6FA U+8E30 # +0xE6FB U+8E34 # +0xE6FC U+8E4A # +0xE740 U+8E47 # +0xE741 U+8E49 # +0xE742 U+8E4C # +0xE743 U+8E50 # +0xE744 U+8E48 # +0xE745 U+8E59 # +0xE746 U+8E64 # +0xE747 U+8E60 # +0xE748 U+8E2A # +0xE749 U+8E63 # +0xE74A U+8E55 # +0xE74B U+8E76 # +0xE74C U+8E72 # +0xE74D U+8E7C # +0xE74E U+8E81 # +0xE74F U+8E87 # +0xE750 U+8E85 # +0xE751 U+8E84 # +0xE752 U+8E8B # +0xE753 U+8E8A # +0xE754 U+8E93 # +0xE755 U+8E91 # +0xE756 U+8E94 # +0xE757 U+8E99 # +0xE758 U+8EAA # +0xE759 U+8EA1 # +0xE75A U+8EAC # +0xE75B U+8EB0 # +0xE75C U+8EC6 # +0xE75D U+8EB1 # +0xE75E U+8EBE # +0xE75F U+8EC5 # +0xE760 U+8EC8 # +0xE761 U+8ECB # +0xE762 U+8EDB # +0xE763 U+8EE3 # +0xE764 U+8EFC # +0xE765 U+8EFB # +0xE766 U+8EEB # +0xE767 U+8EFE # +0xE768 U+8F0A # +0xE769 U+8F05 # +0xE76A U+8F15 # +0xE76B U+8F12 # +0xE76C U+8F19 # +0xE76D U+8F13 # +0xE76E U+8F1C # +0xE76F U+8F1F # +0xE770 U+8F1B # +0xE771 U+8F0C # +0xE772 U+8F26 # +0xE773 U+8F33 # +0xE774 U+8F3B # +0xE775 U+8F39 # +0xE776 U+8F45 # +0xE777 U+8F42 # +0xE778 U+8F3E # +0xE779 U+8F4C # +0xE77A U+8F49 # +0xE77B U+8F46 # +0xE77C U+8F4E # +0xE77D U+8F57 # +0xE77E U+8F5C # +0xE780 U+8F62 # +0xE781 U+8F63 # +0xE782 U+8F64 # +0xE783 U+8F9C # +0xE784 U+8F9F # +0xE785 U+8FA3 # +0xE786 U+8FAD # +0xE787 U+8FAF # +0xE788 U+8FB7 # +0xE789 U+8FDA # +0xE78A U+8FE5 # +0xE78B U+8FE2 # +0xE78C U+8FEA # +0xE78D U+8FEF # +0xE78E U+9087 # +0xE78F U+8FF4 # +0xE790 U+9005 # +0xE791 U+8FF9 # +0xE792 U+8FFA # +0xE793 U+9011 # +0xE794 U+9015 # +0xE795 U+9021 # +0xE796 U+900D # +0xE797 U+901E # +0xE798 U+9016 # +0xE799 U+900B # +0xE79A U+9027 # +0xE79B U+9036 # +0xE79C U+9035 # +0xE79D U+9039 # +0xE79E U+8FF8 # +0xE79F U+904F # +0xE7A0 U+9050 # +0xE7A1 U+9051 # +0xE7A2 U+9052 # +0xE7A3 U+900E # +0xE7A4 U+9049 # +0xE7A5 U+903E # +0xE7A6 U+9056 # +0xE7A7 U+9058 # +0xE7A8 U+905E # +0xE7A9 U+9068 # +0xE7AA U+906F # +0xE7AB U+9076 # +0xE7AC U+96A8 # +0xE7AD U+9072 # +0xE7AE U+9082 # +0xE7AF U+907D # +0xE7B0 U+9081 # +0xE7B1 U+9080 # +0xE7B2 U+908A # +0xE7B3 U+9089 # +0xE7B4 U+908F # +0xE7B5 U+90A8 # +0xE7B6 U+90AF # +0xE7B7 U+90B1 # +0xE7B8 U+90B5 # +0xE7B9 U+90E2 # +0xE7BA U+90E4 # +0xE7BB U+6248 # +0xE7BC U+90DB # +0xE7BD U+9102 # +0xE7BE U+9112 # +0xE7BF U+9119 # +0xE7C0 U+9132 # +0xE7C1 U+9130 # +0xE7C2 U+914A # +0xE7C3 U+9156 # +0xE7C4 U+9158 # +0xE7C5 U+9163 # +0xE7C6 U+9165 # +0xE7C7 U+9169 # +0xE7C8 U+9173 # +0xE7C9 U+9172 # +0xE7CA U+918B # +0xE7CB U+9189 # +0xE7CC U+9182 # +0xE7CD U+91A2 # +0xE7CE U+91AB # +0xE7CF U+91AF # +0xE7D0 U+91AA # +0xE7D1 U+91B5 # +0xE7D2 U+91B4 # +0xE7D3 U+91BA # +0xE7D4 U+91C0 # +0xE7D5 U+91C1 # +0xE7D6 U+91C9 # +0xE7D7 U+91CB # +0xE7D8 U+91D0 # +0xE7D9 U+91D6 # +0xE7DA U+91DF # +0xE7DB U+91E1 # +0xE7DC U+91DB # +0xE7DD U+91FC # +0xE7DE U+91F5 # +0xE7DF U+91F6 # +0xE7E0 U+921E # +0xE7E1 U+91FF # +0xE7E2 U+9214 # +0xE7E3 U+922C # +0xE7E4 U+9215 # +0xE7E5 U+9211 # +0xE7E6 U+925E # +0xE7E7 U+9257 # +0xE7E8 U+9245 # +0xE7E9 U+9249 # +0xE7EA U+9264 # +0xE7EB U+9248 # +0xE7EC U+9295 # +0xE7ED U+923F # +0xE7EE U+924B # +0xE7EF U+9250 # +0xE7F0 U+929C # +0xE7F1 U+9296 # +0xE7F2 U+9293 # +0xE7F3 U+929B # +0xE7F4 U+925A # +0xE7F5 U+92CF # +0xE7F6 U+92B9 # +0xE7F7 U+92B7 # +0xE7F8 U+92E9 # +0xE7F9 U+930F # +0xE7FA U+92FA # +0xE7FB U+9344 # +0xE7FC U+932E # +0xE840 U+9319 # +0xE841 U+9322 # +0xE842 U+931A # +0xE843 U+9323 # +0xE844 U+933A # +0xE845 U+9335 # +0xE846 U+933B # +0xE847 U+935C # +0xE848 U+9360 # +0xE849 U+937C # +0xE84A U+936E # +0xE84B U+9356 # +0xE84C U+93B0 # +0xE84D U+93AC # +0xE84E U+93AD # +0xE84F U+9394 # +0xE850 U+93B9 # +0xE851 U+93D6 # +0xE852 U+93D7 # +0xE853 U+93E8 # +0xE854 U+93E5 # +0xE855 U+93D8 # +0xE856 U+93C3 # +0xE857 U+93DD # +0xE858 U+93D0 # +0xE859 U+93C8 # +0xE85A U+93E4 # +0xE85B U+941A # +0xE85C U+9414 # +0xE85D U+9413 # +0xE85E U+9403 # +0xE85F U+9407 # +0xE860 U+9410 # +0xE861 U+9436 # +0xE862 U+942B # +0xE863 U+9435 # +0xE864 U+9421 # +0xE865 U+943A # +0xE866 U+9441 # +0xE867 U+9452 # +0xE868 U+9444 # +0xE869 U+945B # +0xE86A U+9460 # +0xE86B U+9462 # +0xE86C U+945E # +0xE86D U+946A # +0xE86E U+9229 # +0xE86F U+9470 # +0xE870 U+9475 # +0xE871 U+9477 # +0xE872 U+947D # +0xE873 U+945A # +0xE874 U+947C # +0xE875 U+947E # +0xE876 U+9481 # +0xE877 U+947F # +0xE878 U+9582 # +0xE879 U+9587 # +0xE87A U+958A # +0xE87B U+9594 # +0xE87C U+9596 # +0xE87D U+9598 # +0xE87E U+9599 # +0xE880 U+95A0 # +0xE881 U+95A8 # +0xE882 U+95A7 # +0xE883 U+95AD # +0xE884 U+95BC # +0xE885 U+95BB # +0xE886 U+95B9 # +0xE887 U+95BE # +0xE888 U+95CA # +0xE889 U+6FF6 # +0xE88A U+95C3 # +0xE88B U+95CD # +0xE88C U+95CC # +0xE88D U+95D5 # +0xE88E U+95D4 # +0xE88F U+95D6 # +0xE890 U+95DC # +0xE891 U+95E1 # +0xE892 U+95E5 # +0xE893 U+95E2 # +0xE894 U+9621 # +0xE895 U+9628 # +0xE896 U+962E # +0xE897 U+962F # +0xE898 U+9642 # +0xE899 U+964C # +0xE89A U+964F # +0xE89B U+964B # +0xE89C U+9677 # +0xE89D U+965C # +0xE89E U+965E # +0xE89F U+965D # +0xE8A0 U+965F # +0xE8A1 U+9666 # +0xE8A2 U+9672 # +0xE8A3 U+966C # +0xE8A4 U+968D # +0xE8A5 U+9698 # +0xE8A6 U+9695 # +0xE8A7 U+9697 # +0xE8A8 U+96AA # +0xE8A9 U+96A7 # +0xE8AA U+96B1 # +0xE8AB U+96B2 # +0xE8AC U+96B0 # +0xE8AD U+96B4 # +0xE8AE U+96B6 # +0xE8AF U+96B8 # +0xE8B0 U+96B9 # +0xE8B1 U+96CE # +0xE8B2 U+96CB # +0xE8B3 U+96C9 # +0xE8B4 U+96CD # +0xE8B5 U+894D # +0xE8B6 U+96DC # +0xE8B7 U+970D # +0xE8B8 U+96D5 # +0xE8B9 U+96F9 # +0xE8BA U+9704 # +0xE8BB U+9706 # +0xE8BC U+9708 # +0xE8BD U+9713 # +0xE8BE U+970E # +0xE8BF U+9711 # +0xE8C0 U+970F # +0xE8C1 U+9716 # +0xE8C2 U+9719 # +0xE8C3 U+9724 # +0xE8C4 U+972A # +0xE8C5 U+9730 # +0xE8C6 U+9739 # +0xE8C7 U+973D # +0xE8C8 U+973E # +0xE8C9 U+9744 # +0xE8CA U+9746 # +0xE8CB U+9748 # +0xE8CC U+9742 # +0xE8CD U+9749 # +0xE8CE U+975C # +0xE8CF U+9760 # +0xE8D0 U+9764 # +0xE8D1 U+9766 # +0xE8D2 U+9768 # +0xE8D3 U+52D2 # +0xE8D4 U+976B # +0xE8D5 U+9771 # +0xE8D6 U+9779 # +0xE8D7 U+9785 # +0xE8D8 U+977C # +0xE8D9 U+9781 # +0xE8DA U+977A # +0xE8DB U+9786 # +0xE8DC U+978B # +0xE8DD U+978F # +0xE8DE U+9790 # +0xE8DF U+979C # +0xE8E0 U+97A8 # +0xE8E1 U+97A6 # +0xE8E2 U+97A3 # +0xE8E3 U+97B3 # +0xE8E4 U+97B4 # +0xE8E5 U+97C3 # +0xE8E6 U+97C6 # +0xE8E7 U+97C8 # +0xE8E8 U+97CB # +0xE8E9 U+97DC # +0xE8EA U+97ED # +0xE8EB U+9F4F # +0xE8EC U+97F2 # +0xE8ED U+7ADF # +0xE8EE U+97F6 # +0xE8EF U+97F5 # +0xE8F0 U+980F # +0xE8F1 U+980C # +0xE8F2 U+9838 # +0xE8F3 U+9824 # +0xE8F4 U+9821 # +0xE8F5 U+9837 # +0xE8F6 U+983D # +0xE8F7 U+9846 # +0xE8F8 U+984F # +0xE8F9 U+984B # +0xE8FA U+986B # +0xE8FB U+986F # +0xE8FC U+9870 # +0xE940 U+9871 # +0xE941 U+9874 # +0xE942 U+9873 # +0xE943 U+98AA # +0xE944 U+98AF # +0xE945 U+98B1 # +0xE946 U+98B6 # +0xE947 U+98C4 # +0xE948 U+98C3 # +0xE949 U+98C6 # +0xE94A U+98E9 # +0xE94B U+98EB # +0xE94C U+9903 # +0xE94D U+9909 # +0xE94E U+9912 # +0xE94F U+9914 # +0xE950 U+9918 # +0xE951 U+9921 # +0xE952 U+991D # +0xE953 U+991E # +0xE954 U+9924 # +0xE955 U+9920 # +0xE956 U+992C # +0xE957 U+992E # +0xE958 U+993D # +0xE959 U+993E # +0xE95A U+9942 # +0xE95B U+9949 # +0xE95C U+9945 # +0xE95D U+9950 # +0xE95E U+994B # +0xE95F U+9951 # +0xE960 U+9952 # +0xE961 U+994C # +0xE962 U+9955 # +0xE963 U+9997 # +0xE964 U+9998 # +0xE965 U+99A5 # +0xE966 U+99AD # +0xE967 U+99AE # +0xE968 U+99BC # +0xE969 U+99DF # +0xE96A U+99DB # +0xE96B U+99DD # +0xE96C U+99D8 # +0xE96D U+99D1 # +0xE96E U+99ED # +0xE96F U+99EE # +0xE970 U+99F1 # +0xE971 U+99F2 # +0xE972 U+99FB # +0xE973 U+99F8 # +0xE974 U+9A01 # +0xE975 U+9A0F # +0xE976 U+9A05 # +0xE977 U+99E2 # +0xE978 U+9A19 # +0xE979 U+9A2B # +0xE97A U+9A37 # +0xE97B U+9A45 # +0xE97C U+9A42 # +0xE97D U+9A40 # +0xE97E U+9A43 # +0xE980 U+9A3E # +0xE981 U+9A55 # +0xE982 U+9A4D # +0xE983 U+9A5B # +0xE984 U+9A57 # +0xE985 U+9A5F # +0xE986 U+9A62 # +0xE987 U+9A65 # +0xE988 U+9A64 # +0xE989 U+9A69 # +0xE98A U+9A6B # +0xE98B U+9A6A # +0xE98C U+9AAD # +0xE98D U+9AB0 # +0xE98E U+9ABC # +0xE98F U+9AC0 # +0xE990 U+9ACF # +0xE991 U+9AD1 # +0xE992 U+9AD3 # +0xE993 U+9AD4 # +0xE994 U+9ADE # +0xE995 U+9ADF # +0xE996 U+9AE2 # +0xE997 U+9AE3 # +0xE998 U+9AE6 # +0xE999 U+9AEF # +0xE99A U+9AEB # +0xE99B U+9AEE # +0xE99C U+9AF4 # +0xE99D U+9AF1 # +0xE99E U+9AF7 # +0xE99F U+9AFB # +0xE9A0 U+9B06 # +0xE9A1 U+9B18 # +0xE9A2 U+9B1A # +0xE9A3 U+9B1F # +0xE9A4 U+9B22 # +0xE9A5 U+9B23 # +0xE9A6 U+9B25 # +0xE9A7 U+9B27 # +0xE9A8 U+9B28 # +0xE9A9 U+9B29 # +0xE9AA U+9B2A # +0xE9AB U+9B2E # +0xE9AC U+9B2F # +0xE9AD U+9B32 # +0xE9AE U+9B44 # +0xE9AF U+9B43 # +0xE9B0 U+9B4F # +0xE9B1 U+9B4D # +0xE9B2 U+9B4E # +0xE9B3 U+9B51 # +0xE9B4 U+9B58 # +0xE9B5 U+9B74 # +0xE9B6 U+9B93 # +0xE9B7 U+9B83 # +0xE9B8 U+9B91 # +0xE9B9 U+9B96 # +0xE9BA U+9B97 # +0xE9BB U+9B9F # +0xE9BC U+9BA0 # +0xE9BD U+9BA8 # +0xE9BE U+9BB4 # +0xE9BF U+9BC0 # +0xE9C0 U+9BCA # +0xE9C1 U+9BB9 # +0xE9C2 U+9BC6 # +0xE9C3 U+9BCF # +0xE9C4 U+9BD1 # +0xE9C5 U+9BD2 # +0xE9C6 U+9BE3 # +0xE9C7 U+9BE2 # +0xE9C8 U+9BE4 # +0xE9C9 U+9BD4 # +0xE9CA U+9BE1 # +0xE9CB U+9C3A # +0xE9CC U+9BF2 # +0xE9CD U+9BF1 # +0xE9CE U+9BF0 # +0xE9CF U+9C15 # +0xE9D0 U+9C14 # +0xE9D1 U+9C09 # +0xE9D2 U+9C13 # +0xE9D3 U+9C0C # +0xE9D4 U+9C06 # +0xE9D5 U+9C08 # +0xE9D6 U+9C12 # +0xE9D7 U+9C0A # +0xE9D8 U+9C04 # +0xE9D9 U+9C2E # +0xE9DA U+9C1B # +0xE9DB U+9C25 # +0xE9DC U+9C24 # +0xE9DD U+9C21 # +0xE9DE U+9C30 # +0xE9DF U+9C47 # +0xE9E0 U+9C32 # +0xE9E1 U+9C46 # +0xE9E2 U+9C3E # +0xE9E3 U+9C5A # +0xE9E4 U+9C60 # +0xE9E5 U+9C67 # +0xE9E6 U+9C76 # +0xE9E7 U+9C78 # +0xE9E8 U+9CE7 # +0xE9E9 U+9CEC # +0xE9EA U+9CF0 # +0xE9EB U+9D09 # +0xE9EC U+9D08 # +0xE9ED U+9CEB # +0xE9EE U+9D03 # +0xE9EF U+9D06 # +0xE9F0 U+9D2A # +0xE9F1 U+9D26 # +0xE9F2 U+9DAF # +0xE9F3 U+9D23 # +0xE9F4 U+9D1F # +0xE9F5 U+9D44 # +0xE9F6 U+9D15 # +0xE9F7 U+9D12 # +0xE9F8 U+9D41 # +0xE9F9 U+9D3F # +0xE9FA U+9D3E # +0xE9FB U+9D46 # +0xE9FC U+9D48 # +0xEA40 U+9D5D # +0xEA41 U+9D5E # +0xEA42 U+9D64 # +0xEA43 U+9D51 # +0xEA44 U+9D50 # +0xEA45 U+9D59 # +0xEA46 U+9D72 # +0xEA47 U+9D89 # +0xEA48 U+9D87 # +0xEA49 U+9DAB # +0xEA4A U+9D6F # +0xEA4B U+9D7A # +0xEA4C U+9D9A # +0xEA4D U+9DA4 # +0xEA4E U+9DA9 # +0xEA4F U+9DB2 # +0xEA50 U+9DC4 # +0xEA51 U+9DC1 # +0xEA52 U+9DBB # +0xEA53 U+9DB8 # +0xEA54 U+9DBA # +0xEA55 U+9DC6 # +0xEA56 U+9DCF # +0xEA57 U+9DC2 # +0xEA58 U+9DD9 # +0xEA59 U+9DD3 # +0xEA5A U+9DF8 # +0xEA5B U+9DE6 # +0xEA5C U+9DED # +0xEA5D U+9DEF # +0xEA5E U+9DFD # +0xEA5F U+9E1A # +0xEA60 U+9E1B # +0xEA61 U+9E1E # +0xEA62 U+9E75 # +0xEA63 U+9E79 # +0xEA64 U+9E7D # +0xEA65 U+9E81 # +0xEA66 U+9E88 # +0xEA67 U+9E8B # +0xEA68 U+9E8C # +0xEA69 U+9E92 # +0xEA6A U+9E95 # +0xEA6B U+9E91 # +0xEA6C U+9E9D # +0xEA6D U+9EA5 # +0xEA6E U+9EA9 # +0xEA6F U+9EB8 # +0xEA70 U+9EAA # +0xEA71 U+9EAD # +0xEA72 U+9761 # +0xEA73 U+9ECC # +0xEA74 U+9ECE # +0xEA75 U+9ECF # +0xEA76 U+9ED0 # +0xEA77 U+9ED4 # +0xEA78 U+9EDC # +0xEA79 U+9EDE # +0xEA7A U+9EDD # +0xEA7B U+9EE0 # +0xEA7C U+9EE5 # +0xEA7D U+9EE8 # +0xEA7E U+9EEF # +0xEA80 U+9EF4 # +0xEA81 U+9EF6 # +0xEA82 U+9EF7 # +0xEA83 U+9EF9 # +0xEA84 U+9EFB # +0xEA85 U+9EFC # +0xEA86 U+9EFD # +0xEA87 U+9F07 # +0xEA88 U+9F08 # +0xEA89 U+76B7 # +0xEA8A U+9F15 # +0xEA8B U+9F21 # +0xEA8C U+9F2C # +0xEA8D U+9F3E # +0xEA8E U+9F4A # +0xEA8F U+9F52 # +0xEA90 U+9F54 # +0xEA91 U+9F63 # +0xEA92 U+9F5F # +0xEA93 U+9F60 # +0xEA94 U+9F61 # +0xEA95 U+9F66 # +0xEA96 U+9F67 # +0xEA97 U+9F6C # +0xEA98 U+9F6A # +0xEA99 U+9F77 # +0xEA9A U+9F72 # +0xEA9B U+9F76 # +0xEA9C U+9F95 # +0xEA9D U+9F9C # +0xEA9E U+9FA0 # +0xEA9F U+582F # [1983] +0xEAA0 U+69C7 # [1983] +0xEAA1 U+9059 # [1983] +0xEAA2 U+7464 # [1983] +0xEAA3 U+51DC # [1990] +0xEAA4 U+7199 # [1990] +0xEAA5 U+5653 # [2004] +0xEAA6 U+5DE2 # [2000] +0xEAA7 U+5E14 # [2000] +0xEAA8 U+5E18 # [2000] +0xEAA9 U+5E58 # [2000] +0xEAAA U+5E5E # [2000] +0xEAAB U+5EBE # [2000] +0xEAAC U+F928 # CJK COMPATIBILITY IDEOGRAPH-F928 [2000] +0xEAAD U+5ECB # [2000] +0xEAAE U+5EF9 # [2000] +0xEAAF U+5F00 # [2000] +0xEAB0 U+5F02 # [2000] +0xEAB1 U+5F07 # [2000] +0xEAB2 U+5F1D # [2000] +0xEAB3 U+5F23 # [2000] +0xEAB4 U+5F34 # [2000] +0xEAB5 U+5F36 # [2000] +0xEAB6 U+5F3D # [2000] +0xEAB7 U+5F40 # [2000] +0xEAB8 U+5F45 # [2000] +0xEAB9 U+5F54 # [2000] +0xEABA U+5F58 # [2000] +0xEABB U+5F64 # [2000] +0xEABC U+5F67 # [2000] +0xEABD U+5F7D # [2000] +0xEABE U+5F89 # [2000] +0xEABF U+5F9C # [2000] +0xEAC0 U+5FA7 # [2000] +0xEAC1 U+5FAF # [2000] +0xEAC2 U+5FB5 # [2000] +0xEAC3 U+5FB7 # [2000] +0xEAC4 U+5FC9 # [2000] +0xEAC5 U+5FDE # [2000] +0xEAC6 U+5FE1 # [2000] +0xEAC7 U+5FE9 # [2000] +0xEAC8 U+600D # [2000] +0xEAC9 U+6014 # [2000] +0xEACA U+6018 # [2000] +0xEACB U+6033 # [2000] +0xEACC U+6035 # [2000] +0xEACD U+6047 # [2000] +0xEACE U+FA3D # CJK COMPATIBILITY IDEOGRAPH-FA3D [2000] [Unicode3.2] +0xEACF U+609D # [2000] +0xEAD0 U+609E # [2000] +0xEAD1 U+60CB # [2000] +0xEAD2 U+60D4 # [2000] +0xEAD3 U+60D5 # [2000] +0xEAD4 U+60DD # [2000] +0xEAD5 U+60F8 # [2000] +0xEAD6 U+611C # [2000] +0xEAD7 U+612B # [2000] +0xEAD8 U+6130 # [2000] +0xEAD9 U+6137 # [2000] +0xEADA U+FA3E # CJK COMPATIBILITY IDEOGRAPH-FA3E [2000] [Unicode3.2] +0xEADB U+618D # [2000] +0xEADC U+FA3F # CJK COMPATIBILITY IDEOGRAPH-FA3F [2000] [Unicode3.2] +0xEADD U+61BC # [2000] +0xEADE U+61B9 # [2000] +0xEADF U+FA40 # CJK COMPATIBILITY IDEOGRAPH-FA40 [2000] [Unicode3.2] +0xEAE0 U+6222 # [2000] +0xEAE1 U+623E # [2000] +0xEAE2 U+6243 # [2000] +0xEAE3 U+6256 # [2000] +0xEAE4 U+625A # [2000] +0xEAE5 U+626F # [2000] +0xEAE6 U+6285 # [2000] +0xEAE7 U+62C4 # [2000] +0xEAE8 U+62D6 # [2000] +0xEAE9 U+62FC # [2000] +0xEAEA U+630A # [2000] +0xEAEB U+6318 # [2000] +0xEAEC U+6339 # [2000] +0xEAED U+6343 # [2000] +0xEAEE U+6365 # [2000] +0xEAEF U+637C # [2000] +0xEAF0 U+63E5 # [2000] +0xEAF1 U+63ED # [2000] +0xEAF2 U+63F5 # [2000] +0xEAF3 U+6410 # [2000] +0xEAF4 U+6414 # [2000] +0xEAF5 U+6422 # [2000] +0xEAF6 U+6479 # [2000] +0xEAF7 U+6451 # [2000] +0xEAF8 U+6460 # [2000] +0xEAF9 U+646D # [2000] +0xEAFA U+64CE # [2000] +0xEAFB U+64BE # [2000] +0xEAFC U+64BF # [2000] +0xEB40 U+64C4 # [2000] +0xEB41 U+64CA # [2000] +0xEB42 U+64D0 # [2000] +0xEB43 U+64F7 # [2000] +0xEB44 U+64FB # [2000] +0xEB45 U+6522 # [2000] +0xEB46 U+6529 # [2000] +0xEB47 U+FA41 # CJK COMPATIBILITY IDEOGRAPH-FA41 [2000] [Unicode3.2] +0xEB48 U+6567 # [2000] +0xEB49 U+659D # [2000] +0xEB4A U+FA42 # CJK COMPATIBILITY IDEOGRAPH-FA42 [2000] [Unicode3.2] +0xEB4B U+6600 # [2000] +0xEB4C U+6609 # [2000] +0xEB4D U+6615 # [2000] +0xEB4E U+661E # [2000] +0xEB4F U+663A # [2000] +0xEB50 U+6622 # [2000] +0xEB51 U+6624 # [2000] +0xEB52 U+662B # [2000] +0xEB53 U+6630 # [2000] +0xEB54 U+6631 # [2000] +0xEB55 U+6633 # [2000] +0xEB56 U+66FB # [2000] +0xEB57 U+6648 # [2000] +0xEB58 U+664C # [2000] +0xEB59 U+231C4 # [2000] [Unicode3.1] +0xEB5A U+6659 # [2000] +0xEB5B U+665A # [2000] +0xEB5C U+6661 # [2000] +0xEB5D U+6665 # [2000] +0xEB5E U+6673 # [2000] +0xEB5F U+6677 # [2000] +0xEB60 U+6678 # [2000] +0xEB61 U+668D # [2000] +0xEB62 U+FA43 # CJK COMPATIBILITY IDEOGRAPH-FA43 [2000] [Unicode3.2] +0xEB63 U+66A0 # [2000] +0xEB64 U+66B2 # [2000] +0xEB65 U+66BB # [2000] +0xEB66 U+66C6 # [2000] +0xEB67 U+66C8 # [2000] +0xEB68 U+3B22 # [2000] +0xEB69 U+66DB # [2000] +0xEB6A U+66E8 # [2000] +0xEB6B U+66FA # [2000] +0xEB6C U+6713 # [2000] +0xEB6D U+F929 # CJK COMPATIBILITY IDEOGRAPH-F929 [2000] +0xEB6E U+6733 # [2000] +0xEB6F U+6766 # [2000] +0xEB70 U+6747 # [2000] +0xEB71 U+6748 # [2000] +0xEB72 U+677B # [2000] +0xEB73 U+6781 # [2000] +0xEB74 U+6793 # [2000] +0xEB75 U+6798 # [2000] +0xEB76 U+679B # [2000] +0xEB77 U+67BB # [2000] +0xEB78 U+67F9 # [2000] +0xEB79 U+67C0 # [2000] +0xEB7A U+67D7 # [2000] +0xEB7B U+67FC # [2000] +0xEB7C U+6801 # [2000] +0xEB7D U+6852 # [2000] +0xEB7E U+681D # [2000] +0xEB80 U+682C # [2000] +0xEB81 U+6831 # [2000] +0xEB82 U+685B # [2000] +0xEB83 U+6872 # [2000] +0xEB84 U+6875 # [2000] +0xEB85 U+FA44 # CJK COMPATIBILITY IDEOGRAPH-FA44 [2000] [Unicode3.2] +0xEB86 U+68A3 # [2000] +0xEB87 U+68A5 # [2000] +0xEB88 U+68B2 # [2000] +0xEB89 U+68C8 # [2000] +0xEB8A U+68D0 # [2000] +0xEB8B U+68E8 # [2000] +0xEB8C U+68ED # [2000] +0xEB8D U+68F0 # [2000] +0xEB8E U+68F1 # [2000] +0xEB8F U+68FC # [2000] +0xEB90 U+690A # [2000] +0xEB91 U+6949 # [2000] +0xEB92 U+235C4 # [2000] [Unicode3.1] +0xEB93 U+6935 # [2000] +0xEB94 U+6942 # [2000] +0xEB95 U+6957 # [2000] +0xEB96 U+6963 # [2000] +0xEB97 U+6964 # [2000] +0xEB98 U+6968 # [2000] +0xEB99 U+6980 # [2000] +0xEB9A U+FA14 # CJK COMPATIBILITY IDEOGRAPH-FA14 [2000] +0xEB9B U+69A5 # [2000] +0xEB9C U+69AD # [2000] +0xEB9D U+69CF # [2000] +0xEB9E U+3BB6 # [2000] +0xEB9F U+3BC3 # [2000] +0xEBA0 U+69E2 # [2000] +0xEBA1 U+69E9 # [2000] +0xEBA2 U+69EA # [2000] +0xEBA3 U+69F5 # [2000] +0xEBA4 U+69F6 # [2000] +0xEBA5 U+6A0F # [2000] +0xEBA6 U+6A15 # [2000] +0xEBA7 U+2373F # [2000] [Unicode3.1] +0xEBA8 U+6A3B # [2000] +0xEBA9 U+6A3E # [2000] +0xEBAA U+6A45 # [2000] +0xEBAB U+6A50 # [2000] +0xEBAC U+6A56 # [2000] +0xEBAD U+6A5B # [2000] +0xEBAE U+6A6B # [2000] +0xEBAF U+6A73 # [2000] +0xEBB0 U+23763 # [2000] [Unicode3.1] +0xEBB1 U+6A89 # [2000] +0xEBB2 U+6A94 # [2000] +0xEBB3 U+6A9D # [2000] +0xEBB4 U+6A9E # [2000] +0xEBB5 U+6AA5 # [2000] +0xEBB6 U+6AE4 # [2000] +0xEBB7 U+6AE7 # [2000] +0xEBB8 U+3C0F # [2000] +0xEBB9 U+F91D # CJK COMPATIBILITY IDEOGRAPH-F91D [2000] +0xEBBA U+6B1B # [2000] +0xEBBB U+6B1E # [2000] +0xEBBC U+6B2C # [2000] +0xEBBD U+6B35 # [2000] +0xEBBE U+6B46 # [2000] +0xEBBF U+6B56 # [2000] +0xEBC0 U+6B60 # [2000] +0xEBC1 U+6B65 # [2000] +0xEBC2 U+6B67 # [2000] +0xEBC3 U+6B77 # [2000] +0xEBC4 U+6B82 # [2000] +0xEBC5 U+6BA9 # [2000] +0xEBC6 U+6BAD # [2000] +0xEBC7 U+F970 # CJK COMPATIBILITY IDEOGRAPH-F970 [2000] +0xEBC8 U+6BCF # [2000] +0xEBC9 U+6BD6 # [2000] +0xEBCA U+6BD7 # [2000] +0xEBCB U+6BFF # [2000] +0xEBCC U+6C05 # [2000] +0xEBCD U+6C10 # [2000] +0xEBCE U+6C33 # [2000] +0xEBCF U+6C59 # [2000] +0xEBD0 U+6C5C # [2000] +0xEBD1 U+6CAA # [2000] +0xEBD2 U+6C74 # [2000] +0xEBD3 U+6C76 # [2000] +0xEBD4 U+6C85 # [2000] +0xEBD5 U+6C86 # [2000] +0xEBD6 U+6C98 # [2000] +0xEBD7 U+6C9C # [2000] +0xEBD8 U+6CFB # [2000] +0xEBD9 U+6CC6 # [2000] +0xEBDA U+6CD4 # [2000] +0xEBDB U+6CE0 # [2000] +0xEBDC U+6CEB # [2000] +0xEBDD U+6CEE # [2000] +0xEBDE U+23CFE # [2000] [Unicode3.1] +0xEBDF U+6D04 # [2000] +0xEBE0 U+6D0E # [2000] +0xEBE1 U+6D2E # [2000] +0xEBE2 U+6D31 # [2000] +0xEBE3 U+6D39 # [2000] +0xEBE4 U+6D3F # [2000] +0xEBE5 U+6D58 # [2000] +0xEBE6 U+6D65 # [2000] +0xEBE7 U+FA45 # CJK COMPATIBILITY IDEOGRAPH-FA45 [2000] [Unicode3.2] +0xEBE8 U+6D82 # [2000] +0xEBE9 U+6D87 # [2000] +0xEBEA U+6D89 # [2000] +0xEBEB U+6D94 # [2000] +0xEBEC U+6DAA # [2000] +0xEBED U+6DAC # [2000] +0xEBEE U+6DBF # [2000] +0xEBEF U+6DC4 # [2000] +0xEBF0 U+6DD6 # [2000] +0xEBF1 U+6DDA # [2000] +0xEBF2 U+6DDB # [2000] +0xEBF3 U+6DDD # [2000] +0xEBF4 U+6DFC # [2000] +0xEBF5 U+FA46 # CJK COMPATIBILITY IDEOGRAPH-FA46 [2000] [Unicode3.2] +0xEBF6 U+6E34 # [2000] +0xEBF7 U+6E44 # [2000] +0xEBF8 U+6E5C # [2000] +0xEBF9 U+6E5E # [2000] +0xEBFA U+6EAB # [2000] +0xEBFB U+6EB1 # [2000] +0xEBFC U+6EC1 # [2000] +0xEC40 U+6EC7 # [2000] +0xEC41 U+6ECE # [2000] +0xEC42 U+6F10 # [2000] +0xEC43 U+6F1A # [2000] +0xEC44 U+FA47 # CJK COMPATIBILITY IDEOGRAPH-FA47 [2000] [Unicode3.2] +0xEC45 U+6F2A # [2000] +0xEC46 U+6F2F # [2000] +0xEC47 U+6F33 # [2000] +0xEC48 U+6F51 # [2000] +0xEC49 U+6F59 # [2000] +0xEC4A U+6F5E # [2000] +0xEC4B U+6F61 # [2000] +0xEC4C U+6F62 # [2000] +0xEC4D U+6F7E # [2000] +0xEC4E U+6F88 # [2000] +0xEC4F U+6F8C # [2000] +0xEC50 U+6F8D # [2000] +0xEC51 U+6F94 # [2000] +0xEC52 U+6FA0 # [2000] +0xEC53 U+6FA7 # [2000] +0xEC54 U+6FB6 # [2000] +0xEC55 U+6FBC # [2000] +0xEC56 U+6FC7 # [2000] +0xEC57 U+6FCA # [2000] +0xEC58 U+6FF9 # [2000] +0xEC59 U+6FF0 # [2000] +0xEC5A U+6FF5 # [2000] +0xEC5B U+7005 # [2000] +0xEC5C U+7006 # [2000] +0xEC5D U+7028 # [2000] +0xEC5E U+704A # [2000] +0xEC5F U+705D # [2000] +0xEC60 U+705E # [2000] +0xEC61 U+704E # [2000] +0xEC62 U+7064 # [2000] +0xEC63 U+7075 # [2000] +0xEC64 U+7085 # [2000] +0xEC65 U+70A4 # [2000] +0xEC66 U+70AB # [2000] +0xEC67 U+70B7 # [2000] +0xEC68 U+70D4 # [2000] +0xEC69 U+70D8 # [2000] +0xEC6A U+70E4 # [2000] +0xEC6B U+710F # [2000] +0xEC6C U+712B # [2000] +0xEC6D U+711E # [2000] +0xEC6E U+7120 # [2000] +0xEC6F U+712E # [2000] +0xEC70 U+7130 # [2000] +0xEC71 U+7146 # [2000] +0xEC72 U+7147 # [2000] +0xEC73 U+7151 # [2000] +0xEC74 U+FA48 # CJK COMPATIBILITY IDEOGRAPH-FA48 [2000] [Unicode3.2] +0xEC75 U+7152 # [2000] +0xEC76 U+715C # [2000] +0xEC77 U+7160 # [2000] +0xEC78 U+7168 # [2000] +0xEC79 U+FA15 # CJK COMPATIBILITY IDEOGRAPH-FA15 [2000] +0xEC7A U+7185 # [2000] +0xEC7B U+7187 # [2000] +0xEC7C U+7192 # [2000] +0xEC7D U+71C1 # [2000] +0xEC7E U+71BA # [2000] +0xEC80 U+71C4 # [2000] +0xEC81 U+71FE # [2000] +0xEC82 U+7200 # [2000] +0xEC83 U+7215 # [2000] +0xEC84 U+7255 # [2000] +0xEC85 U+7256 # [2000] +0xEC86 U+3E3F # [2000] +0xEC87 U+728D # [2000] +0xEC88 U+729B # [2000] +0xEC89 U+72BE # [2000] +0xEC8A U+72C0 # [2000] +0xEC8B U+72FB # [2000] +0xEC8C U+247F1 # [2000] [Unicode3.1] +0xEC8D U+7327 # [2000] +0xEC8E U+7328 # [2000] +0xEC8F U+FA16 # CJK COMPATIBILITY IDEOGRAPH-FA16 [2000] +0xEC90 U+7350 # [2000] +0xEC91 U+7366 # [2000] +0xEC92 U+737C # [2000] +0xEC93 U+7395 # [2000] +0xEC94 U+739F # [2000] +0xEC95 U+73A0 # [2000] +0xEC96 U+73A2 # [2000] +0xEC97 U+73A6 # [2000] +0xEC98 U+73AB # [2000] +0xEC99 U+73C9 # [2000] +0xEC9A U+73CF # [2000] +0xEC9B U+73D6 # [2000] +0xEC9C U+73D9 # [2000] +0xEC9D U+73E3 # [2000] +0xEC9E U+73E9 # [2000] +0xEC9F U+7407 # [2000] +0xECA0 U+740A # [2000] +0xECA1 U+741A # [2000] +0xECA2 U+741B # [2000] +0xECA3 U+FA4A # CJK COMPATIBILITY IDEOGRAPH-FA4A [2000] [Unicode3.2] +0xECA4 U+7426 # [2000] +0xECA5 U+7428 # [2000] +0xECA6 U+742A # [2000] +0xECA7 U+742B # [2000] +0xECA8 U+742C # [2000] +0xECA9 U+742E # [2000] +0xECAA U+742F # [2000] +0xECAB U+7430 # [2000] +0xECAC U+7444 # [2000] +0xECAD U+7446 # [2000] +0xECAE U+7447 # [2000] +0xECAF U+744B # [2000] +0xECB0 U+7457 # [2000] +0xECB1 U+7462 # [2000] +0xECB2 U+746B # [2000] +0xECB3 U+746D # [2000] +0xECB4 U+7486 # [2000] +0xECB5 U+7487 # [2000] +0xECB6 U+7489 # [2000] +0xECB7 U+7498 # [2000] +0xECB8 U+749C # [2000] +0xECB9 U+749F # [2000] +0xECBA U+74A3 # [2000] +0xECBB U+7490 # [2000] +0xECBC U+74A6 # [2000] +0xECBD U+74A8 # [2000] +0xECBE U+74A9 # [2000] +0xECBF U+74B5 # [2000] +0xECC0 U+74BF # [2000] +0xECC1 U+74C8 # [2000] +0xECC2 U+74C9 # [2000] +0xECC3 U+74DA # [2000] +0xECC4 U+74FF # [2000] +0xECC5 U+7501 # [2000] +0xECC6 U+7517 # [2000] +0xECC7 U+752F # [2000] +0xECC8 U+756F # [2000] +0xECC9 U+7579 # [2000] +0xECCA U+7592 # [2000] +0xECCB U+3F72 # [2000] +0xECCC U+75CE # [2000] +0xECCD U+75E4 # [2000] +0xECCE U+7600 # [2000] +0xECCF U+7602 # [2000] +0xECD0 U+7608 # [2000] +0xECD1 U+7615 # [2000] +0xECD2 U+7616 # [2000] +0xECD3 U+7619 # [2000] +0xECD4 U+761E # [2000] +0xECD5 U+762D # [2000] +0xECD6 U+7635 # [2000] +0xECD7 U+7643 # [2000] +0xECD8 U+764B # [2000] +0xECD9 U+7664 # [2000] +0xECDA U+7665 # [2000] +0xECDB U+766D # [2000] +0xECDC U+766F # [2000] +0xECDD U+7671 # [2000] +0xECDE U+7681 # [2000] +0xECDF U+769B # [2000] +0xECE0 U+769D # [2000] +0xECE1 U+769E # [2000] +0xECE2 U+76A6 # [2000] +0xECE3 U+76AA # [2000] +0xECE4 U+76B6 # [2000] +0xECE5 U+76C5 # [2000] +0xECE6 U+76CC # [2000] +0xECE7 U+76CE # [2000] +0xECE8 U+76D4 # [2000] +0xECE9 U+76E6 # [2000] +0xECEA U+76F1 # [2000] +0xECEB U+76FC # [2000] +0xECEC U+770A # [2000] +0xECED U+7719 # [2000] +0xECEE U+7734 # [2000] +0xECEF U+7736 # [2000] +0xECF0 U+7746 # [2000] +0xECF1 U+774D # [2000] +0xECF2 U+774E # [2000] +0xECF3 U+775C # [2000] +0xECF4 U+775F # [2000] +0xECF5 U+7762 # [2000] +0xECF6 U+777A # [2000] +0xECF7 U+7780 # [2000] +0xECF8 U+7794 # [2000] +0xECF9 U+77AA # [2000] +0xECFA U+77E0 # [2000] +0xECFB U+782D # [2000] +0xECFC U+2548E # [2000] [Unicode3.1] +0xED40 U+7843 # [2000] +0xED41 U+784E # [2000] +0xED42 U+784F # [2000] +0xED43 U+7851 # [2000] +0xED44 U+7868 # [2000] +0xED45 U+786E # [2000] +0xED46 U+FA4B # CJK COMPATIBILITY IDEOGRAPH-FA4B [2000] [Unicode3.2] +0xED47 U+78B0 # [2000] +0xED48 U+2550E # [2000] [Unicode3.1] +0xED49 U+78AD # [2000] +0xED4A U+78E4 # [2000] +0xED4B U+78F2 # [2000] +0xED4C U+7900 # [2000] +0xED4D U+78F7 # [2000] +0xED4E U+791C # [2000] +0xED4F U+792E # [2000] +0xED50 U+7931 # [2000] +0xED51 U+7934 # [2000] +0xED52 U+FA4C # CJK COMPATIBILITY IDEOGRAPH-FA4C [2000] [Unicode3.2] +0xED53 U+FA4D # CJK COMPATIBILITY IDEOGRAPH-FA4D [2000] [Unicode3.2] +0xED54 U+7945 # [2000] +0xED55 U+7946 # [2000] +0xED56 U+FA4E # CJK COMPATIBILITY IDEOGRAPH-FA4E [2000] [Unicode3.2] +0xED57 U+FA4F # CJK COMPATIBILITY IDEOGRAPH-FA4F [2000] [Unicode3.2] +0xED58 U+FA50 # CJK COMPATIBILITY IDEOGRAPH-FA50 [2000] [Unicode3.2] +0xED59 U+795C # [2000] +0xED5A U+FA51 # CJK COMPATIBILITY IDEOGRAPH-FA51 [2000] [Unicode3.2] +0xED5B U+FA19 # CJK COMPATIBILITY IDEOGRAPH-FA19 [2000] +0xED5C U+FA1A # CJK COMPATIBILITY IDEOGRAPH-FA1A [2000] +0xED5D U+7979 # [2000] +0xED5E U+FA52 # CJK COMPATIBILITY IDEOGRAPH-FA52 [2000] [Unicode3.2] +0xED5F U+FA53 # CJK COMPATIBILITY IDEOGRAPH-FA53 [2000] [Unicode3.2] +0xED60 U+FA1B # CJK COMPATIBILITY IDEOGRAPH-FA1B [2000] +0xED61 U+7998 # [2000] +0xED62 U+79B1 # [2000] +0xED63 U+79B8 # [2000] +0xED64 U+79C8 # [2000] +0xED65 U+79CA # [2000] +0xED66 U+25771 # [2000] [Unicode3.1] +0xED67 U+79D4 # [2000] +0xED68 U+79DE # [2000] +0xED69 U+79EB # [2000] +0xED6A U+79ED # [2000] +0xED6B U+7A03 # [2000] +0xED6C U+FA54 # CJK COMPATIBILITY IDEOGRAPH-FA54 [2000] [Unicode3.2] +0xED6D U+7A39 # [2000] +0xED6E U+7A5D # [2000] +0xED6F U+7A6D # [2000] +0xED70 U+FA55 # CJK COMPATIBILITY IDEOGRAPH-FA55 [2000] [Unicode3.2] +0xED71 U+7A85 # [2000] +0xED72 U+7AA0 # [2000] +0xED73 U+259C4 # [2000] [Unicode3.1] +0xED74 U+7AB3 # [2000] +0xED75 U+7ABB # [2000] +0xED76 U+7ACE # [2000] +0xED77 U+7AEB # [2000] +0xED78 U+7AFD # [2000] +0xED79 U+7B12 # [2000] +0xED7A U+7B2D # [2000] +0xED7B U+7B3B # [2000] +0xED7C U+7B47 # [2000] +0xED7D U+7B4E # [2000] +0xED7E U+7B60 # [2000] +0xED80 U+7B6D # [2000] +0xED81 U+7B6F # [2000] +0xED82 U+7B72 # [2000] +0xED83 U+7B9E # [2000] +0xED84 U+FA56 # CJK COMPATIBILITY IDEOGRAPH-FA56 [2000] [Unicode3.2] +0xED85 U+7BD7 # [2000] +0xED86 U+7BD9 # [2000] +0xED87 U+7C01 # [2000] +0xED88 U+7C31 # [2000] +0xED89 U+7C1E # [2000] +0xED8A U+7C20 # [2000] +0xED8B U+7C33 # [2000] +0xED8C U+7C36 # [2000] +0xED8D U+4264 # [2000] +0xED8E U+25DA1 # [2000] [Unicode3.1] +0xED8F U+7C59 # [2000] +0xED90 U+7C6D # [2000] +0xED91 U+7C79 # [2000] +0xED92 U+7C8F # [2000] +0xED93 U+7C94 # [2000] +0xED94 U+7CA0 # [2000] +0xED95 U+7CBC # [2000] +0xED96 U+7CD5 # [2000] +0xED97 U+7CD9 # [2000] +0xED98 U+7CDD # [2000] +0xED99 U+7D07 # [2000] +0xED9A U+7D08 # [2000] +0xED9B U+7D13 # [2000] +0xED9C U+7D1D # [2000] +0xED9D U+7D23 # [2000] +0xED9E U+7D31 # [2000] +0xED9F U+7D41 # [2000] +0xEDA0 U+7D48 # [2000] +0xEDA1 U+7D53 # [2000] +0xEDA2 U+7D5C # [2000] +0xEDA3 U+7D7A # [2000] +0xEDA4 U+7D83 # [2000] +0xEDA5 U+7D8B # [2000] +0xEDA6 U+7DA0 # [2000] +0xEDA7 U+7DA6 # [2000] +0xEDA8 U+7DC2 # [2000] +0xEDA9 U+7DCC # [2000] +0xEDAA U+7DD6 # [2000] +0xEDAB U+7DE3 # [2000] +0xEDAC U+FA57 # CJK COMPATIBILITY IDEOGRAPH-FA57 [2000] [Unicode3.2] +0xEDAD U+7E28 # [2000] +0xEDAE U+7E08 # [2000] +0xEDAF U+7E11 # [2000] +0xEDB0 U+7E15 # [2000] +0xEDB1 U+FA59 # CJK COMPATIBILITY IDEOGRAPH-FA59 [2000] [Unicode3.2] +0xEDB2 U+7E47 # [2000] +0xEDB3 U+7E52 # [2000] +0xEDB4 U+7E61 # [2000] +0xEDB5 U+7E8A # [2000] +0xEDB6 U+7E8D # [2000] +0xEDB7 U+7F47 # [2000] +0xEDB8 U+FA5A # CJK COMPATIBILITY IDEOGRAPH-FA5A [2000] [Unicode3.2] +0xEDB9 U+7F91 # [2000] +0xEDBA U+7F97 # [2000] +0xEDBB U+7FBF # [2000] +0xEDBC U+7FCE # [2000] +0xEDBD U+7FDB # [2000] +0xEDBE U+7FDF # [2000] +0xEDBF U+7FEC # [2000] +0xEDC0 U+7FEE # [2000] +0xEDC1 U+7FFA # [2000] +0xEDC2 U+FA5B # CJK COMPATIBILITY IDEOGRAPH-FA5B [2000] [Unicode3.2] +0xEDC3 U+8014 # [2000] +0xEDC4 U+8026 # [2000] +0xEDC5 U+8035 # [2000] +0xEDC6 U+8037 # [2000] +0xEDC7 U+803C # [2000] +0xEDC8 U+80CA # [2000] +0xEDC9 U+80D7 # [2000] +0xEDCA U+80E0 # [2000] +0xEDCB U+80F3 # [2000] +0xEDCC U+8118 # [2000] +0xEDCD U+814A # [2000] +0xEDCE U+8160 # [2000] +0xEDCF U+8167 # [2000] +0xEDD0 U+8168 # [2000] +0xEDD1 U+816D # [2000] +0xEDD2 U+81BB # [2000] +0xEDD3 U+81CA # [2000] +0xEDD4 U+81CF # [2000] +0xEDD5 U+81D7 # [2000] +0xEDD6 U+FA5C # CJK COMPATIBILITY IDEOGRAPH-FA5C [2000] [Unicode3.2] +0xEDD7 U+4453 # [2000] +0xEDD8 U+445B # [2000] +0xEDD9 U+8260 # [2000] +0xEDDA U+8274 # [2000] +0xEDDB U+26AFF # [2000] [Unicode3.1] +0xEDDC U+828E # [2000] +0xEDDD U+82A1 # [2000] +0xEDDE U+82A3 # [2000] +0xEDDF U+82A4 # [2000] +0xEDE0 U+82A9 # [2000] +0xEDE1 U+82AE # [2000] +0xEDE2 U+82B7 # [2000] +0xEDE3 U+82BE # [2000] +0xEDE4 U+82BF # [2000] +0xEDE5 U+82C6 # [2000] +0xEDE6 U+82D5 # [2000] +0xEDE7 U+82FD # [2000] +0xEDE8 U+82FE # [2000] +0xEDE9 U+8300 # [2000] +0xEDEA U+8301 # [2000] +0xEDEB U+8362 # [2000] +0xEDEC U+8322 # [2000] +0xEDED U+832D # [2000] +0xEDEE U+833A # [2000] +0xEDEF U+8343 # [2000] +0xEDF0 U+8347 # [2000] +0xEDF1 U+8351 # [2000] +0xEDF2 U+8355 # [2000] +0xEDF3 U+837D # [2000] +0xEDF4 U+8386 # [2000] +0xEDF5 U+8392 # [2000] +0xEDF6 U+8398 # [2000] +0xEDF7 U+83A7 # [2000] +0xEDF8 U+83A9 # [2000] +0xEDF9 U+83BF # [2000] +0xEDFA U+83C0 # [2000] +0xEDFB U+83C7 # [2000] +0xEDFC U+83CF # [2000] +0xEE40 U+83D1 # [2000] +0xEE41 U+83E1 # [2000] +0xEE42 U+83EA # [2000] +0xEE43 U+8401 # [2000] +0xEE44 U+8406 # [2000] +0xEE45 U+840A # [2000] +0xEE46 U+FA5F # CJK COMPATIBILITY IDEOGRAPH-FA5F [2000] [Unicode3.2] +0xEE47 U+8448 # [2000] +0xEE48 U+845F # [2000] +0xEE49 U+8470 # [2000] +0xEE4A U+8473 # [2000] +0xEE4B U+8485 # [2000] +0xEE4C U+849E # [2000] +0xEE4D U+84AF # [2000] +0xEE4E U+84B4 # [2000] +0xEE4F U+84BA # [2000] +0xEE50 U+84C0 # [2000] +0xEE51 U+84C2 # [2000] +0xEE52 U+26E40 # [2000] [Unicode3.1] +0xEE53 U+8532 # [2000] +0xEE54 U+851E # [2000] +0xEE55 U+8523 # [2000] +0xEE56 U+852F # [2000] +0xEE57 U+8559 # [2000] +0xEE58 U+8564 # [2000] +0xEE59 U+FA1F # CJK COMPATIBILITY IDEOGRAPH-FA1F [2000] +0xEE5A U+85AD # [2000] +0xEE5B U+857A # [2000] +0xEE5C U+858C # [2000] +0xEE5D U+858F # [2000] +0xEE5E U+85A2 # [2000] +0xEE5F U+85B0 # [2000] +0xEE60 U+85CB # [2000] +0xEE61 U+85CE # [2000] +0xEE62 U+85ED # [2000] +0xEE63 U+8612 # [2000] +0xEE64 U+85FF # [2000] +0xEE65 U+8604 # [2000] +0xEE66 U+8605 # [2000] +0xEE67 U+8610 # [2000] +0xEE68 U+270F4 # [2000] [Unicode3.1] +0xEE69 U+8618 # [2000] +0xEE6A U+8629 # [2000] +0xEE6B U+8638 # [2000] +0xEE6C U+8657 # [2000] +0xEE6D U+865B # [2000] +0xEE6E U+F936 # CJK COMPATIBILITY IDEOGRAPH-F936 [2000] +0xEE6F U+8662 # [2000] +0xEE70 U+459D # [2000] +0xEE71 U+866C # [2000] +0xEE72 U+8675 # [2000] +0xEE73 U+8698 # [2000] +0xEE74 U+86B8 # [2000] +0xEE75 U+86FA # [2000] +0xEE76 U+86FC # [2000] +0xEE77 U+86FD # [2000] +0xEE78 U+870B # [2000] +0xEE79 U+8771 # [2000] +0xEE7A U+8787 # [2000] +0xEE7B U+8788 # [2000] +0xEE7C U+87AC # [2000] +0xEE7D U+87AD # [2000] +0xEE7E U+87B5 # [2000] +0xEE80 U+45EA # [2000] +0xEE81 U+87D6 # [2000] +0xEE82 U+87EC # [2000] +0xEE83 U+8806 # [2000] +0xEE84 U+880A # [2000] +0xEE85 U+8810 # [2000] +0xEE86 U+8814 # [2000] +0xEE87 U+881F # [2000] +0xEE88 U+8898 # [2000] +0xEE89 U+88AA # [2000] +0xEE8A U+88CA # [2000] +0xEE8B U+88CE # [2000] +0xEE8C U+27684 # [2000] [Unicode3.1] +0xEE8D U+88F5 # [2000] +0xEE8E U+891C # [2000] +0xEE8F U+FA60 # CJK COMPATIBILITY IDEOGRAPH-FA60 [2000] [Unicode3.2] +0xEE90 U+8918 # [2000] +0xEE91 U+8919 # [2000] +0xEE92 U+891A # [2000] +0xEE93 U+8927 # [2000] +0xEE94 U+8930 # [2000] +0xEE95 U+8932 # [2000] +0xEE96 U+8939 # [2000] +0xEE97 U+8940 # [2000] +0xEE98 U+8994 # [2000] +0xEE99 U+FA61 # CJK COMPATIBILITY IDEOGRAPH-FA61 [2000] [Unicode3.2] +0xEE9A U+89D4 # [2000] +0xEE9B U+89E5 # [2000] +0xEE9C U+89F6 # [2000] +0xEE9D U+8A12 # [2000] +0xEE9E U+8A15 # [2000] +0xEE9F U+8A22 # [2000] +0xEEA0 U+8A37 # [2000] +0xEEA1 U+8A47 # [2000] +0xEEA2 U+8A4E # [2000] +0xEEA3 U+8A5D # [2000] +0xEEA4 U+8A61 # [2000] +0xEEA5 U+8A75 # [2000] +0xEEA6 U+8A79 # [2000] +0xEEA7 U+8AA7 # [2000] +0xEEA8 U+8AD0 # [2000] +0xEEA9 U+8ADF # [2000] +0xEEAA U+8AF4 # [2000] +0xEEAB U+8AF6 # [2000] +0xEEAC U+FA22 # CJK COMPATIBILITY IDEOGRAPH-FA22 [2000] +0xEEAD U+FA62 # CJK COMPATIBILITY IDEOGRAPH-FA62 [2000] [Unicode3.2] +0xEEAE U+FA63 # CJK COMPATIBILITY IDEOGRAPH-FA63 [2000] [Unicode3.2] +0xEEAF U+8B46 # [2000] +0xEEB0 U+8B54 # [2000] +0xEEB1 U+8B59 # [2000] +0xEEB2 U+8B69 # [2000] +0xEEB3 U+8B9D # [2000] +0xEEB4 U+8C49 # [2000] +0xEEB5 U+8C68 # [2000] +0xEEB6 U+FA64 # CJK COMPATIBILITY IDEOGRAPH-FA64 [2000] [Unicode3.2] +0xEEB7 U+8CE1 # [2000] +0xEEB8 U+8CF4 # [2000] +0xEEB9 U+8CF8 # [2000] +0xEEBA U+8CFE # [2000] +0xEEBB U+FA65 # CJK COMPATIBILITY IDEOGRAPH-FA65 [2000] [Unicode3.2] +0xEEBC U+8D12 # [2000] +0xEEBD U+8D1B # [2000] +0xEEBE U+8DAF # [2000] +0xEEBF U+8DCE # [2000] +0xEEC0 U+8DD1 # [2000] +0xEEC1 U+8DD7 # [2000] +0xEEC2 U+8E20 # [2000] +0xEEC3 U+8E23 # [2000] +0xEEC4 U+8E3D # [2000] +0xEEC5 U+8E70 # [2000] +0xEEC6 U+8E7B # [2000] +0xEEC7 U+28277 # [2000] [Unicode3.1] +0xEEC8 U+8EC0 # [2000] +0xEEC9 U+4844 # [2000] +0xEECA U+8EFA # [2000] +0xEECB U+8F1E # [2000] +0xEECC U+8F2D # [2000] +0xEECD U+8F36 # [2000] +0xEECE U+8F54 # [2000] +0xEECF U+283CD # [2000] [Unicode3.1] +0xEED0 U+8FA6 # [2000] +0xEED1 U+8FB5 # [2000] +0xEED2 U+8FE4 # [2000] +0xEED3 U+8FE8 # [2000] +0xEED4 U+8FEE # [2000] +0xEED5 U+9008 # [2000] +0xEED6 U+902D # [2000] +0xEED7 U+FA67 # CJK COMPATIBILITY IDEOGRAPH-FA67 [2000] [Unicode3.2] +0xEED8 U+9088 # [2000] +0xEED9 U+9095 # [2000] +0xEEDA U+9097 # [2000] +0xEEDB U+9099 # [2000] +0xEEDC U+909B # [2000] +0xEEDD U+90A2 # [2000] +0xEEDE U+90B3 # [2000] +0xEEDF U+90BE # [2000] +0xEEE0 U+90C4 # [2000] +0xEEE1 U+90C5 # [2000] +0xEEE2 U+90C7 # [2000] +0xEEE3 U+90D7 # [2000] +0xEEE4 U+90DD # [2000] +0xEEE5 U+90DE # [2000] +0xEEE6 U+90EF # [2000] +0xEEE7 U+90F4 # [2000] +0xEEE8 U+FA26 # CJK COMPATIBILITY IDEOGRAPH-FA26 [2000] +0xEEE9 U+9114 # [2000] +0xEEEA U+9115 # [2000] +0xEEEB U+9116 # [2000] +0xEEEC U+9122 # [2000] +0xEEED U+9123 # [2000] +0xEEEE U+9127 # [2000] +0xEEEF U+912F # [2000] +0xEEF0 U+9131 # [2000] +0xEEF1 U+9134 # [2000] +0xEEF2 U+913D # [2000] +0xEEF3 U+9148 # [2000] +0xEEF4 U+915B # [2000] +0xEEF5 U+9183 # [2000] +0xEEF6 U+919E # [2000] +0xEEF7 U+91AC # [2000] +0xEEF8 U+91B1 # [2000] +0xEEF9 U+91BC # [2000] +0xEEFA U+91D7 # [2000] +0xEEFB U+91FB # [2000] +0xEEFC U+91E4 # [2000] +0xEF40 U+91E5 # [2000] +0xEF41 U+91ED # [2000] +0xEF42 U+91F1 # [2000] +0xEF43 U+9207 # [2000] +0xEF44 U+9210 # [2000] +0xEF45 U+9238 # [2000] +0xEF46 U+9239 # [2000] +0xEF47 U+923A # [2000] +0xEF48 U+923C # [2000] +0xEF49 U+9240 # [2000] +0xEF4A U+9243 # [2000] +0xEF4B U+924F # [2000] +0xEF4C U+9278 # [2000] +0xEF4D U+9288 # [2000] +0xEF4E U+92C2 # [2000] +0xEF4F U+92CB # [2000] +0xEF50 U+92CC # [2000] +0xEF51 U+92D3 # [2000] +0xEF52 U+92E0 # [2000] +0xEF53 U+92FF # [2000] +0xEF54 U+9304 # [2000] +0xEF55 U+931F # [2000] +0xEF56 U+9321 # [2000] +0xEF57 U+9325 # [2000] +0xEF58 U+9348 # [2000] +0xEF59 U+9349 # [2000] +0xEF5A U+934A # [2000] +0xEF5B U+9364 # [2000] +0xEF5C U+9365 # [2000] +0xEF5D U+936A # [2000] +0xEF5E U+9370 # [2000] +0xEF5F U+939B # [2000] +0xEF60 U+93A3 # [2000] +0xEF61 U+93BA # [2000] +0xEF62 U+93C6 # [2000] +0xEF63 U+93DE # [2000] +0xEF64 U+93DF # [2000] +0xEF65 U+9404 # [2000] +0xEF66 U+93FD # [2000] +0xEF67 U+9433 # [2000] +0xEF68 U+944A # [2000] +0xEF69 U+9463 # [2000] +0xEF6A U+946B # [2000] +0xEF6B U+9471 # [2000] +0xEF6C U+9472 # [2000] +0xEF6D U+958E # [2000] +0xEF6E U+959F # [2000] +0xEF6F U+95A6 # [2000] +0xEF70 U+95A9 # [2000] +0xEF71 U+95AC # [2000] +0xEF72 U+95B6 # [2000] +0xEF73 U+95BD # [2000] +0xEF74 U+95CB # [2000] +0xEF75 U+95D0 # [2000] +0xEF76 U+95D3 # [2000] +0xEF77 U+49B0 # [2000] +0xEF78 U+95DA # [2000] +0xEF79 U+95DE # [2000] +0xEF7A U+9658 # [2000] +0xEF7B U+9684 # [2000] +0xEF7C U+F9DC # CJK COMPATIBILITY IDEOGRAPH-F9DC [2000] +0xEF7D U+969D # [2000] +0xEF7E U+96A4 # [2000] +0xEF80 U+96A5 # [2000] +0xEF81 U+96D2 # [2000] +0xEF82 U+96DE # [2000] +0xEF83 U+FA68 # CJK COMPATIBILITY IDEOGRAPH-FA68 [2000] [Unicode3.2] +0xEF84 U+96E9 # [2000] +0xEF85 U+96EF # [2000] +0xEF86 U+9733 # [2000] +0xEF87 U+973B # [2000] +0xEF88 U+974D # [2000] +0xEF89 U+974E # [2000] +0xEF8A U+974F # [2000] +0xEF8B U+975A # [2000] +0xEF8C U+976E # [2000] +0xEF8D U+9773 # [2000] +0xEF8E U+9795 # [2000] +0xEF8F U+97AE # [2000] +0xEF90 U+97BA # [2000] +0xEF91 U+97C1 # [2000] +0xEF92 U+97C9 # [2000] +0xEF93 U+97DE # [2000] +0xEF94 U+97DB # [2000] +0xEF95 U+97F4 # [2000] +0xEF96 U+FA69 # CJK COMPATIBILITY IDEOGRAPH-FA69 [2000] [Unicode3.2] +0xEF97 U+980A # [2000] +0xEF98 U+981E # [2000] +0xEF99 U+982B # [2000] +0xEF9A U+9830 # [2000] +0xEF9B U+FA6A # CJK COMPATIBILITY IDEOGRAPH-FA6A [2000] [Unicode3.2] +0xEF9C U+9852 # [2000] +0xEF9D U+9853 # [2000] +0xEF9E U+9856 # [2000] +0xEF9F U+9857 # [2000] +0xEFA0 U+9859 # [2000] +0xEFA1 U+985A # [2000] +0xEFA2 U+F9D0 # CJK COMPATIBILITY IDEOGRAPH-F9D0 [2000] +0xEFA3 U+9865 # [2000] +0xEFA4 U+986C # [2000] +0xEFA5 U+98BA # [2000] +0xEFA6 U+98C8 # [2000] +0xEFA7 U+98E7 # [2000] +0xEFA8 U+9958 # [2000] +0xEFA9 U+999E # [2000] +0xEFAA U+9A02 # [2000] +0xEFAB U+9A03 # [2000] +0xEFAC U+9A24 # [2000] +0xEFAD U+9A2D # [2000] +0xEFAE U+9A2E # [2000] +0xEFAF U+9A38 # [2000] +0xEFB0 U+9A4A # [2000] +0xEFB1 U+9A4E # [2000] +0xEFB2 U+9A52 # [2000] +0xEFB3 U+9AB6 # [2000] +0xEFB4 U+9AC1 # [2000] +0xEFB5 U+9AC3 # [2000] +0xEFB6 U+9ACE # [2000] +0xEFB7 U+9AD6 # [2000] +0xEFB8 U+9AF9 # [2000] +0xEFB9 U+9B02 # [2000] +0xEFBA U+9B08 # [2000] +0xEFBB U+9B20 # [2000] +0xEFBC U+4C17 # [2000] +0xEFBD U+9B2D # [2000] +0xEFBE U+9B5E # [2000] +0xEFBF U+9B79 # [2000] +0xEFC0 U+9B66 # [2000] +0xEFC1 U+9B72 # [2000] +0xEFC2 U+9B75 # [2000] +0xEFC3 U+9B84 # [2000] +0xEFC4 U+9B8A # [2000] +0xEFC5 U+9B8F # [2000] +0xEFC6 U+9B9E # [2000] +0xEFC7 U+9BA7 # [2000] +0xEFC8 U+9BC1 # [2000] +0xEFC9 U+9BCE # [2000] +0xEFCA U+9BE5 # [2000] +0xEFCB U+9BF8 # [2000] +0xEFCC U+9BFD # [2000] +0xEFCD U+9C00 # [2000] +0xEFCE U+9C23 # [2000] +0xEFCF U+9C41 # [2000] +0xEFD0 U+9C4F # [2000] +0xEFD1 U+9C50 # [2000] +0xEFD2 U+9C53 # [2000] +0xEFD3 U+9C63 # [2000] +0xEFD4 U+9C65 # [2000] +0xEFD5 U+9C77 # [2000] +0xEFD6 U+9D1D # [2000] +0xEFD7 U+9D1E # [2000] +0xEFD8 U+9D43 # [2000] +0xEFD9 U+9D47 # [2000] +0xEFDA U+9D52 # [2000] +0xEFDB U+9D63 # [2000] +0xEFDC U+9D70 # [2000] +0xEFDD U+9D7C # [2000] +0xEFDE U+9D8A # [2000] +0xEFDF U+9D96 # [2000] +0xEFE0 U+9DC0 # [2000] +0xEFE1 U+9DAC # [2000] +0xEFE2 U+9DBC # [2000] +0xEFE3 U+9DD7 # [2000] +0xEFE4 U+2A190 # [2000] [Unicode3.1] +0xEFE5 U+9DE7 # [2000] +0xEFE6 U+9E07 # [2000] +0xEFE7 U+9E15 # [2000] +0xEFE8 U+9E7C # [2000] +0xEFE9 U+9E9E # [2000] +0xEFEA U+9EA4 # [2000] +0xEFEB U+9EAC # [2000] +0xEFEC U+9EAF # [2000] +0xEFED U+9EB4 # [2000] +0xEFEE U+9EB5 # [2000] +0xEFEF U+9EC3 # [2000] +0xEFF0 U+9ED1 # [2000] +0xEFF1 U+9F10 # [2000] +0xEFF2 U+9F39 # [2000] +0xEFF3 U+9F57 # [2000] +0xEFF4 U+9F90 # [2000] +0xEFF5 U+9F94 # [2000] +0xEFF6 U+9F97 # [2000] +0xEFF7 U+9FA2 # [2000] +0xEFF8 U+59F8 # [2004] +0xEFF9 U+5C5B # [2004] +0xEFFA U+5E77 # [2004] +0xEFFB U+7626 # [2004] +0xEFFC U+7E6B # [2004] +0xF040 U+20089 # [2000] [Unicode3.1] +0xF041 U+4E02 # [2000] +0xF042 U+4E0F # [2000] +0xF043 U+4E12 # [2000] +0xF044 U+4E29 # [2000] +0xF045 U+4E2B # [2000] +0xF046 U+4E2E # [2000] +0xF047 U+4E40 # [2000] +0xF048 U+4E47 # [2000] +0xF049 U+4E48 # [2000] +0xF04A U+200A2 # [2000] [Unicode3.1] +0xF04B U+4E51 # [2000] +0xF04C U+3406 # [2000] +0xF04D U+200A4 # [2000] [Unicode3.1] +0xF04E U+4E5A # [2000] +0xF04F U+4E69 # [2000] +0xF050 U+4E9D # [2000] +0xF051 U+342C # [2000] +0xF052 U+342E # [2000] +0xF053 U+4EB9 # [2000] +0xF054 U+4EBB # [2000] +0xF055 U+201A2 # [2000] [Unicode3.1] +0xF056 U+4EBC # [2000] +0xF057 U+4EC3 # [2000] +0xF058 U+4EC8 # [2000] +0xF059 U+4ED0 # [2000] +0xF05A U+4EEB # [2000] +0xF05B U+4EDA # [2000] +0xF05C U+4EF1 # [2000] +0xF05D U+4EF5 # [2000] +0xF05E U+4F00 # [2000] +0xF05F U+4F16 # [2000] +0xF060 U+4F64 # [2000] +0xF061 U+4F37 # [2000] +0xF062 U+4F3E # [2000] +0xF063 U+4F54 # [2000] +0xF064 U+4F58 # [2000] +0xF065 U+20213 # [2000] [Unicode3.1] +0xF066 U+4F77 # [2000] +0xF067 U+4F78 # [2000] +0xF068 U+4F7A # [2000] +0xF069 U+4F7D # [2000] +0xF06A U+4F82 # [2000] +0xF06B U+4F85 # [2000] +0xF06C U+4F92 # [2000] +0xF06D U+4F9A # [2000] +0xF06E U+4FE6 # [2000] +0xF06F U+4FB2 # [2000] +0xF070 U+4FBE # [2000] +0xF071 U+4FC5 # [2000] +0xF072 U+4FCB # [2000] +0xF073 U+4FCF # [2000] +0xF074 U+4FD2 # [2000] +0xF075 U+346A # [2000] +0xF076 U+4FF2 # [2000] +0xF077 U+5000 # [2000] +0xF078 U+5010 # [2000] +0xF079 U+5013 # [2000] +0xF07A U+501C # [2000] +0xF07B U+501E # [2000] +0xF07C U+5022 # [2000] +0xF07D U+3468 # [2000] +0xF07E U+5042 # [2000] +0xF080 U+5046 # [2000] +0xF081 U+504E # [2000] +0xF082 U+5053 # [2000] +0xF083 U+5057 # [2000] +0xF084 U+5063 # [2000] +0xF085 U+5066 # [2000] +0xF086 U+506A # [2000] +0xF087 U+5070 # [2000] +0xF088 U+50A3 # [2000] +0xF089 U+5088 # [2000] +0xF08A U+5092 # [2000] +0xF08B U+5093 # [2000] +0xF08C U+5095 # [2000] +0xF08D U+5096 # [2000] +0xF08E U+509C # [2000] +0xF08F U+50AA # [2000] +0xF090 U+2032B # [2000] [Unicode3.1] +0xF091 U+50B1 # [2000] +0xF092 U+50BA # [2000] +0xF093 U+50BB # [2000] +0xF094 U+50C4 # [2000] +0xF095 U+50C7 # [2000] +0xF096 U+50F3 # [2000] +0xF097 U+20381 # [2000] [Unicode3.1] +0xF098 U+50CE # [2000] +0xF099 U+20371 # [2000] [Unicode3.1] +0xF09A U+50D4 # [2000] +0xF09B U+50D9 # [2000] +0xF09C U+50E1 # [2000] +0xF09D U+50E9 # [2000] +0xF09E U+3492 # [2000] +0xF09F U+5B96 # [2000] +0xF0A0 U+5BAC # [2000] +0xF0A1 U+3761 # [2000] +0xF0A2 U+5BC0 # [2000] +0xF0A3 U+3762 # [2000] +0xF0A4 U+5BCE # [2000] +0xF0A5 U+5BD6 # [2000] +0xF0A6 U+376C # [2000] +0xF0A7 U+376B # [2000] +0xF0A8 U+5BF1 # [2000] +0xF0A9 U+5BFD # [2000] +0xF0AA U+3775 # [2000] +0xF0AB U+5C03 # [2000] +0xF0AC U+5C29 # [2000] +0xF0AD U+5C30 # [2000] +0xF0AE U+21C56 # [2000] [Unicode3.1] +0xF0AF U+5C5F # [2000] +0xF0B0 U+5C63 # [2000] +0xF0B1 U+5C67 # [2000] +0xF0B2 U+5C68 # [2000] +0xF0B3 U+5C69 # [2000] +0xF0B4 U+5C70 # [2000] +0xF0B5 U+21D2D # [2000] [Unicode3.1] +0xF0B6 U+21D45 # [2000] [Unicode3.1] +0xF0B7 U+5C7C # [2000] +0xF0B8 U+21D78 # [2000] [Unicode3.1] +0xF0B9 U+21D62 # [2000] [Unicode3.1] +0xF0BA U+5C88 # [2000] +0xF0BB U+5C8A # [2000] +0xF0BC U+37C1 # [2000] +0xF0BD U+21DA1 # [2000] [Unicode3.1] +0xF0BE U+21D9C # [2000] [Unicode3.1] +0xF0BF U+5CA0 # [2000] +0xF0C0 U+5CA2 # [2000] +0xF0C1 U+5CA6 # [2000] +0xF0C2 U+5CA7 # [2000] +0xF0C3 U+21D92 # [2000] [Unicode3.1] +0xF0C4 U+5CAD # [2000] +0xF0C5 U+5CB5 # [2000] +0xF0C6 U+21DB7 # [2000] [Unicode3.1] +0xF0C7 U+5CC9 # [2000] +0xF0C8 U+21DE0 # [2000] [Unicode3.1] +0xF0C9 U+21E33 # [2000] [Unicode3.1] +0xF0CA U+5D06 # [2000] +0xF0CB U+5D10 # [2000] +0xF0CC U+5D2B # [2000] +0xF0CD U+5D1D # [2000] +0xF0CE U+5D20 # [2000] +0xF0CF U+5D24 # [2000] +0xF0D0 U+5D26 # [2000] +0xF0D1 U+5D31 # [2000] +0xF0D2 U+5D39 # [2000] +0xF0D3 U+5D42 # [2000] +0xF0D4 U+37E8 # [2000] +0xF0D5 U+5D61 # [2000] +0xF0D6 U+5D6A # [2000] +0xF0D7 U+37F4 # [2000] +0xF0D8 U+5D70 # [2000] +0xF0D9 U+21F1E # [2000] [Unicode3.1] +0xF0DA U+37FD # [2000] +0xF0DB U+5D88 # [2000] +0xF0DC U+3800 # [2000] +0xF0DD U+5D92 # [2000] +0xF0DE U+5D94 # [2000] +0xF0DF U+5D97 # [2000] +0xF0E0 U+5D99 # [2000] +0xF0E1 U+5DB0 # [2000] +0xF0E2 U+5DB2 # [2000] +0xF0E3 U+5DB4 # [2000] +0xF0E4 U+21F76 # [2000] [Unicode3.1] +0xF0E5 U+5DB9 # [2000] +0xF0E6 U+5DD1 # [2000] +0xF0E7 U+5DD7 # [2000] +0xF0E8 U+5DD8 # [2000] +0xF0E9 U+5DE0 # [2000] +0xF0EA U+21FFA # [2000] [Unicode3.1] +0xF0EB U+5DE4 # [2000] +0xF0EC U+5DE9 # [2000] +0xF0ED U+382F # [2000] +0xF0EE U+5E00 # [2000] +0xF0EF U+3836 # [2000] +0xF0F0 U+5E12 # [2000] +0xF0F1 U+5E15 # [2000] +0xF0F2 U+3840 # [2000] +0xF0F3 U+5E1F # [2000] +0xF0F4 U+5E2E # [2000] +0xF0F5 U+5E3E # [2000] +0xF0F6 U+5E49 # [2000] +0xF0F7 U+385C # [2000] +0xF0F8 U+5E56 # [2000] +0xF0F9 U+3861 # [2000] +0xF0FA U+5E6B # [2000] +0xF0FB U+5E6C # [2000] +0xF0FC U+5E6D # [2000] +0xF140 U+5108 # [2000] +0xF141 U+203F9 # [2000] [Unicode3.1] +0xF142 U+5117 # [2000] +0xF143 U+511B # [2000] +0xF144 U+2044A # [2000] [Unicode3.1] +0xF145 U+5160 # [2000] +0xF146 U+20509 # [2000] [Unicode3.1] +0xF147 U+5173 # [2000] +0xF148 U+5183 # [2000] +0xF149 U+518B # [2000] +0xF14A U+34BC # [2000] +0xF14B U+5198 # [2000] +0xF14C U+51A3 # [2000] +0xF14D U+51AD # [2000] +0xF14E U+34C7 # [2000] +0xF14F U+51BC # [2000] +0xF150 U+205D6 # [2000] [Unicode3.1] +0xF151 U+20628 # [2000] [Unicode3.1] +0xF152 U+51F3 # [2000] +0xF153 U+51F4 # [2000] +0xF154 U+5202 # [2000] +0xF155 U+5212 # [2000] +0xF156 U+5216 # [2000] +0xF157 U+2074F # [2000] [Unicode3.1] +0xF158 U+5255 # [2000] +0xF159 U+525C # [2000] +0xF15A U+526C # [2000] +0xF15B U+5277 # [2000] +0xF15C U+5284 # [2000] +0xF15D U+5282 # [2000] +0xF15E U+20807 # [2000] [Unicode3.1] +0xF15F U+5298 # [2000] +0xF160 U+2083A # [2000] [Unicode3.1] +0xF161 U+52A4 # [2000] +0xF162 U+52A6 # [2000] +0xF163 U+52AF # [2000] +0xF164 U+52BA # [2000] +0xF165 U+52BB # [2000] +0xF166 U+52CA # [2000] +0xF167 U+351F # [2000] +0xF168 U+52D1 # [2000] +0xF169 U+208B9 # [2000] [Unicode3.1] +0xF16A U+52F7 # [2000] +0xF16B U+530A # [2000] +0xF16C U+530B # [2000] +0xF16D U+5324 # [2000] +0xF16E U+5335 # [2000] +0xF16F U+533E # [2000] +0xF170 U+5342 # [2000] +0xF171 U+2097C # [2000] [Unicode3.1] +0xF172 U+2099D # [2000] [Unicode3.1] +0xF173 U+5367 # [2000] +0xF174 U+536C # [2000] +0xF175 U+537A # [2000] +0xF176 U+53A4 # [2000] +0xF177 U+53B4 # [2000] +0xF178 U+20AD3 # [2000] [Unicode3.1] +0xF179 U+53B7 # [2000] +0xF17A U+53C0 # [2000] +0xF17B U+20B1D # [2000] [Unicode3.1] +0xF17C U+355D # [2000] +0xF17D U+355E # [2000] +0xF17E U+53D5 # [2000] +0xF180 U+53DA # [2000] +0xF181 U+3563 # [2000] +0xF182 U+53F4 # [2000] +0xF183 U+53F5 # [2000] +0xF184 U+5455 # [2000] +0xF185 U+5424 # [2000] +0xF186 U+5428 # [2000] +0xF187 U+356E # [2000] +0xF188 U+5443 # [2000] +0xF189 U+5462 # [2000] +0xF18A U+5466 # [2000] +0xF18B U+546C # [2000] +0xF18C U+548A # [2000] +0xF18D U+548D # [2000] +0xF18E U+5495 # [2000] +0xF18F U+54A0 # [2000] +0xF190 U+54A6 # [2000] +0xF191 U+54AD # [2000] +0xF192 U+54AE # [2000] +0xF193 U+54B7 # [2000] +0xF194 U+54BA # [2000] +0xF195 U+54BF # [2000] +0xF196 U+54C3 # [2000] +0xF197 U+20D45 # [2000] [Unicode3.1] +0xF198 U+54EC # [2000] +0xF199 U+54EF # [2000] +0xF19A U+54F1 # [2000] +0xF19B U+54F3 # [2000] +0xF19C U+5500 # [2000] +0xF19D U+5501 # [2000] +0xF19E U+5509 # [2000] +0xF19F U+553C # [2000] +0xF1A0 U+5541 # [2000] +0xF1A1 U+35A6 # [2000] +0xF1A2 U+5547 # [2000] +0xF1A3 U+554A # [2000] +0xF1A4 U+35A8 # [2000] +0xF1A5 U+5560 # [2000] +0xF1A6 U+5561 # [2000] +0xF1A7 U+5564 # [2000] +0xF1A8 U+20DE1 # [2000] [Unicode3.1] +0xF1A9 U+557D # [2000] +0xF1AA U+5582 # [2000] +0xF1AB U+5588 # [2000] +0xF1AC U+5591 # [2000] +0xF1AD U+35C5 # [2000] +0xF1AE U+55D2 # [2000] +0xF1AF U+20E95 # [2000] [Unicode3.1] +0xF1B0 U+20E6D # [2000] [Unicode3.1] +0xF1B1 U+55BF # [2000] +0xF1B2 U+55C9 # [2000] +0xF1B3 U+55CC # [2000] +0xF1B4 U+55D1 # [2000] +0xF1B5 U+55DD # [2000] +0xF1B6 U+35DA # [2000] +0xF1B7 U+55E2 # [2000] +0xF1B8 U+20E64 # [2000] [Unicode3.1] +0xF1B9 U+55E9 # [2000] +0xF1BA U+5628 # [2000] +0xF1BB U+20F5F # [2000] [Unicode3.1] +0xF1BC U+5607 # [2000] +0xF1BD U+5610 # [2000] +0xF1BE U+5630 # [2000] +0xF1BF U+5637 # [2000] +0xF1C0 U+35F4 # [2000] +0xF1C1 U+563D # [2000] +0xF1C2 U+563F # [2000] +0xF1C3 U+5640 # [2000] +0xF1C4 U+5647 # [2000] +0xF1C5 U+565E # [2000] +0xF1C6 U+5660 # [2000] +0xF1C7 U+566D # [2000] +0xF1C8 U+3605 # [2000] +0xF1C9 U+5688 # [2000] +0xF1CA U+568C # [2000] +0xF1CB U+5695 # [2000] +0xF1CC U+569A # [2000] +0xF1CD U+569D # [2000] +0xF1CE U+56A8 # [2000] +0xF1CF U+56AD # [2000] +0xF1D0 U+56B2 # [2000] +0xF1D1 U+56C5 # [2000] +0xF1D2 U+56CD # [2000] +0xF1D3 U+56DF # [2000] +0xF1D4 U+56E8 # [2000] +0xF1D5 U+56F6 # [2000] +0xF1D6 U+56F7 # [2000] +0xF1D7 U+21201 # [2000] [Unicode3.1] +0xF1D8 U+5715 # [2000] +0xF1D9 U+5723 # [2000] +0xF1DA U+21255 # [2000] [Unicode3.1] +0xF1DB U+5729 # [2000] +0xF1DC U+2127B # [2000] [Unicode3.1] +0xF1DD U+5745 # [2000] +0xF1DE U+5746 # [2000] +0xF1DF U+574C # [2000] +0xF1E0 U+574D # [2000] +0xF1E1 U+21274 # [2000] [Unicode3.1] +0xF1E2 U+5768 # [2000] +0xF1E3 U+576F # [2000] +0xF1E4 U+5773 # [2000] +0xF1E5 U+5774 # [2000] +0xF1E6 U+5775 # [2000] +0xF1E7 U+577B # [2000] +0xF1E8 U+212E4 # [2000] [Unicode3.1] +0xF1E9 U+212D7 # [2000] [Unicode3.1] +0xF1EA U+57AC # [2000] +0xF1EB U+579A # [2000] +0xF1EC U+579D # [2000] +0xF1ED U+579E # [2000] +0xF1EE U+57A8 # [2000] +0xF1EF U+57D7 # [2000] +0xF1F0 U+212FD # [2000] [Unicode3.1] +0xF1F1 U+57CC # [2000] +0xF1F2 U+21336 # [2000] [Unicode3.1] +0xF1F3 U+21344 # [2000] [Unicode3.1] +0xF1F4 U+57DE # [2000] +0xF1F5 U+57E6 # [2000] +0xF1F6 U+57F0 # [2000] +0xF1F7 U+364A # [2000] +0xF1F8 U+57F8 # [2000] +0xF1F9 U+57FB # [2000] +0xF1FA U+57FD # [2000] +0xF1FB U+5804 # [2000] +0xF1FC U+581E # [2000] +0xF240 U+5820 # [2000] +0xF241 U+5827 # [2000] +0xF242 U+5832 # [2000] +0xF243 U+5839 # [2000] +0xF244 U+213C4 # [2000] [Unicode3.1] +0xF245 U+5849 # [2000] +0xF246 U+584C # [2000] +0xF247 U+5867 # [2000] +0xF248 U+588A # [2000] +0xF249 U+588B # [2000] +0xF24A U+588D # [2000] +0xF24B U+588F # [2000] +0xF24C U+5890 # [2000] +0xF24D U+5894 # [2000] +0xF24E U+589D # [2000] +0xF24F U+58AA # [2000] +0xF250 U+58B1 # [2000] +0xF251 U+2146D # [2000] [Unicode3.1] +0xF252 U+58C3 # [2000] +0xF253 U+58CD # [2000] +0xF254 U+58E2 # [2000] +0xF255 U+58F3 # [2000] +0xF256 U+58F4 # [2000] +0xF257 U+5905 # [2000] +0xF258 U+5906 # [2000] +0xF259 U+590B # [2000] +0xF25A U+590D # [2000] +0xF25B U+5914 # [2000] +0xF25C U+5924 # [2000] +0xF25D U+215D7 # [2000] [Unicode3.1] +0xF25E U+3691 # [2000] +0xF25F U+593D # [2000] +0xF260 U+3699 # [2000] +0xF261 U+5946 # [2000] +0xF262 U+3696 # [2000] +0xF263 U+26C29 # [2000] [Unicode3.1] +0xF264 U+595B # [2000] +0xF265 U+595F # [2000] +0xF266 U+21647 # [2000] [Unicode3.1] +0xF267 U+5975 # [2000] +0xF268 U+5976 # [2000] +0xF269 U+597C # [2000] +0xF26A U+599F # [2000] +0xF26B U+59AE # [2000] +0xF26C U+59BC # [2000] +0xF26D U+59C8 # [2000] +0xF26E U+59CD # [2000] +0xF26F U+59DE # [2000] +0xF270 U+59E3 # [2000] +0xF271 U+59E4 # [2000] +0xF272 U+59E7 # [2000] +0xF273 U+59EE # [2000] +0xF274 U+21706 # [2000] [Unicode3.1] +0xF275 U+21742 # [2000] [Unicode3.1] +0xF276 U+36CF # [2000] +0xF277 U+5A0C # [2000] +0xF278 U+5A0D # [2000] +0xF279 U+5A17 # [2000] +0xF27A U+5A27 # [2000] +0xF27B U+5A2D # [2000] +0xF27C U+5A55 # [2000] +0xF27D U+5A65 # [2000] +0xF27E U+5A7A # [2000] +0xF280 U+5A8B # [2000] +0xF281 U+5A9C # [2000] +0xF282 U+5A9F # [2000] +0xF283 U+5AA0 # [2000] +0xF284 U+5AA2 # [2000] +0xF285 U+5AB1 # [2000] +0xF286 U+5AB3 # [2000] +0xF287 U+5AB5 # [2000] +0xF288 U+5ABA # [2000] +0xF289 U+5ABF # [2000] +0xF28A U+5ADA # [2000] +0xF28B U+5ADC # [2000] +0xF28C U+5AE0 # [2000] +0xF28D U+5AE5 # [2000] +0xF28E U+5AF0 # [2000] +0xF28F U+5AEE # [2000] +0xF290 U+5AF5 # [2000] +0xF291 U+5B00 # [2000] +0xF292 U+5B08 # [2000] +0xF293 U+5B17 # [2000] +0xF294 U+5B34 # [2000] +0xF295 U+5B2D # [2000] +0xF296 U+5B4C # [2000] +0xF297 U+5B52 # [2000] +0xF298 U+5B68 # [2000] +0xF299 U+5B6F # [2000] +0xF29A U+5B7C # [2000] +0xF29B U+5B7F # [2000] +0xF29C U+5B81 # [2000] +0xF29D U+5B84 # [2000] +0xF29E U+219C3 # [2000] [Unicode3.1] +0xF29F U+5E6E # [2000] +0xF2A0 U+2217B # [2000] [Unicode3.1] +0xF2A1 U+5EA5 # [2000] +0xF2A2 U+5EAA # [2000] +0xF2A3 U+5EAC # [2000] +0xF2A4 U+5EB9 # [2000] +0xF2A5 U+5EBF # [2000] +0xF2A6 U+5EC6 # [2000] +0xF2A7 U+5ED2 # [2000] +0xF2A8 U+5ED9 # [2000] +0xF2A9 U+2231E # [2000] [Unicode3.1] +0xF2AA U+5EFD # [2000] +0xF2AB U+5F08 # [2000] +0xF2AC U+5F0E # [2000] +0xF2AD U+5F1C # [2000] +0xF2AE U+223AD # [2000] [Unicode3.1] +0xF2AF U+5F1E # [2000] +0xF2B0 U+5F47 # [2000] +0xF2B1 U+5F63 # [2000] +0xF2B2 U+5F72 # [2000] +0xF2B3 U+5F7E # [2000] +0xF2B4 U+5F8F # [2000] +0xF2B5 U+5FA2 # [2000] +0xF2B6 U+5FA4 # [2000] +0xF2B7 U+5FB8 # [2000] +0xF2B8 U+5FC4 # [2000] +0xF2B9 U+38FA # [2000] +0xF2BA U+5FC7 # [2000] +0xF2BB U+5FCB # [2000] +0xF2BC U+5FD2 # [2000] +0xF2BD U+5FD3 # [2000] +0xF2BE U+5FD4 # [2000] +0xF2BF U+5FE2 # [2000] +0xF2C0 U+5FEE # [2000] +0xF2C1 U+5FEF # [2000] +0xF2C2 U+5FF3 # [2000] +0xF2C3 U+5FFC # [2000] +0xF2C4 U+3917 # [2000] +0xF2C5 U+6017 # [2000] +0xF2C6 U+6022 # [2000] +0xF2C7 U+6024 # [2000] +0xF2C8 U+391A # [2000] +0xF2C9 U+604C # [2000] +0xF2CA U+607F # [2000] +0xF2CB U+608A # [2000] +0xF2CC U+6095 # [2000] +0xF2CD U+60A8 # [2000] +0xF2CE U+226F3 # [2000] [Unicode3.1] +0xF2CF U+60B0 # [2000] +0xF2D0 U+60B1 # [2000] +0xF2D1 U+60BE # [2000] +0xF2D2 U+60C8 # [2000] +0xF2D3 U+60D9 # [2000] +0xF2D4 U+60DB # [2000] +0xF2D5 U+60EE # [2000] +0xF2D6 U+60F2 # [2000] +0xF2D7 U+60F5 # [2000] +0xF2D8 U+6110 # [2000] +0xF2D9 U+6112 # [2000] +0xF2DA U+6113 # [2000] +0xF2DB U+6119 # [2000] +0xF2DC U+611E # [2000] +0xF2DD U+613A # [2000] +0xF2DE U+396F # [2000] +0xF2DF U+6141 # [2000] +0xF2E0 U+6146 # [2000] +0xF2E1 U+6160 # [2000] +0xF2E2 U+617C # [2000] +0xF2E3 U+2285B # [2000] [Unicode3.1] +0xF2E4 U+6192 # [2000] +0xF2E5 U+6193 # [2000] +0xF2E6 U+6197 # [2000] +0xF2E7 U+6198 # [2000] +0xF2E8 U+61A5 # [2000] +0xF2E9 U+61A8 # [2000] +0xF2EA U+61AD # [2000] +0xF2EB U+228AB # [2000] [Unicode3.1] +0xF2EC U+61D5 # [2000] +0xF2ED U+61DD # [2000] +0xF2EE U+61DF # [2000] +0xF2EF U+61F5 # [2000] +0xF2F0 U+2298F # [2000] [Unicode3.1] +0xF2F1 U+6215 # [2000] +0xF2F2 U+6223 # [2000] +0xF2F3 U+6229 # [2000] +0xF2F4 U+6246 # [2000] +0xF2F5 U+624C # [2000] +0xF2F6 U+6251 # [2000] +0xF2F7 U+6252 # [2000] +0xF2F8 U+6261 # [2000] +0xF2F9 U+6264 # [2000] +0xF2FA U+627B # [2000] +0xF2FB U+626D # [2000] +0xF2FC U+6273 # [2000] +0xF340 U+6299 # [2000] +0xF341 U+62A6 # [2000] +0xF342 U+62D5 # [2000] +0xF343 U+22AB8 # [2000] [Unicode3.1] +0xF344 U+62FD # [2000] +0xF345 U+6303 # [2000] +0xF346 U+630D # [2000] +0xF347 U+6310 # [2000] +0xF348 U+22B4F # [2000] [Unicode3.1] +0xF349 U+22B50 # [2000] [Unicode3.1] +0xF34A U+6332 # [2000] +0xF34B U+6335 # [2000] +0xF34C U+633B # [2000] +0xF34D U+633C # [2000] +0xF34E U+6341 # [2000] +0xF34F U+6344 # [2000] +0xF350 U+634E # [2000] +0xF351 U+22B46 # [2000] [Unicode3.1] +0xF352 U+6359 # [2000] +0xF353 U+22C1D # [2000] [Unicode3.1] +0xF354 U+22BA6 # [2000] [Unicode3.1] +0xF355 U+636C # [2000] +0xF356 U+6384 # [2000] +0xF357 U+6399 # [2000] +0xF358 U+22C24 # [2000] [Unicode3.1] +0xF359 U+6394 # [2000] +0xF35A U+63BD # [2000] +0xF35B U+63F7 # [2000] +0xF35C U+63D4 # [2000] +0xF35D U+63D5 # [2000] +0xF35E U+63DC # [2000] +0xF35F U+63E0 # [2000] +0xF360 U+63EB # [2000] +0xF361 U+63EC # [2000] +0xF362 U+63F2 # [2000] +0xF363 U+6409 # [2000] +0xF364 U+641E # [2000] +0xF365 U+6425 # [2000] +0xF366 U+6429 # [2000] +0xF367 U+642F # [2000] +0xF368 U+645A # [2000] +0xF369 U+645B # [2000] +0xF36A U+645D # [2000] +0xF36B U+6473 # [2000] +0xF36C U+647D # [2000] +0xF36D U+6487 # [2000] +0xF36E U+6491 # [2000] +0xF36F U+649D # [2000] +0xF370 U+649F # [2000] +0xF371 U+64CB # [2000] +0xF372 U+64CC # [2000] +0xF373 U+64D5 # [2000] +0xF374 U+64D7 # [2000] +0xF375 U+22DE1 # [2000] [Unicode3.1] +0xF376 U+64E4 # [2000] +0xF377 U+64E5 # [2000] +0xF378 U+64FF # [2000] +0xF379 U+6504 # [2000] +0xF37A U+3A6E # [2000] +0xF37B U+650F # [2000] +0xF37C U+6514 # [2000] +0xF37D U+6516 # [2000] +0xF37E U+3A73 # [2000] +0xF380 U+651E # [2000] +0xF381 U+6532 # [2000] +0xF382 U+6544 # [2000] +0xF383 U+6554 # [2000] +0xF384 U+656B # [2000] +0xF385 U+657A # [2000] +0xF386 U+6581 # [2000] +0xF387 U+6584 # [2000] +0xF388 U+6585 # [2000] +0xF389 U+658A # [2000] +0xF38A U+65B2 # [2000] +0xF38B U+65B5 # [2000] +0xF38C U+65B8 # [2000] +0xF38D U+65BF # [2000] +0xF38E U+65C2 # [2000] +0xF38F U+65C9 # [2000] +0xF390 U+65D4 # [2000] +0xF391 U+3AD6 # [2000] +0xF392 U+65F2 # [2000] +0xF393 U+65F9 # [2000] +0xF394 U+65FC # [2000] +0xF395 U+6604 # [2000] +0xF396 U+6608 # [2000] +0xF397 U+6621 # [2000] +0xF398 U+662A # [2000] +0xF399 U+6645 # [2000] +0xF39A U+6651 # [2000] +0xF39B U+664E # [2000] +0xF39C U+3AEA # [2000] +0xF39D U+231C3 # [2000] [Unicode3.1] +0xF39E U+6657 # [2000] +0xF39F U+665B # [2000] +0xF3A0 U+6663 # [2000] +0xF3A1 U+231F5 # [2000] [Unicode3.1] +0xF3A2 U+231B6 # [2000] [Unicode3.1] +0xF3A3 U+666A # [2000] +0xF3A4 U+666B # [2000] +0xF3A5 U+666C # [2000] +0xF3A6 U+666D # [2000] +0xF3A7 U+667B # [2000] +0xF3A8 U+6680 # [2000] +0xF3A9 U+6690 # [2000] +0xF3AA U+6692 # [2000] +0xF3AB U+6699 # [2000] +0xF3AC U+3B0E # [2000] +0xF3AD U+66AD # [2000] +0xF3AE U+66B1 # [2000] +0xF3AF U+66B5 # [2000] +0xF3B0 U+3B1A # [2000] +0xF3B1 U+66BF # [2000] +0xF3B2 U+3B1C # [2000] +0xF3B3 U+66EC # [2000] +0xF3B4 U+3AD7 # [2000] +0xF3B5 U+6701 # [2000] +0xF3B6 U+6705 # [2000] +0xF3B7 U+6712 # [2000] +0xF3B8 U+23372 # [2000] [Unicode3.1] +0xF3B9 U+6719 # [2000] +0xF3BA U+233D3 # [2000] [Unicode3.1] +0xF3BB U+233D2 # [2000] [Unicode3.1] +0xF3BC U+674C # [2000] +0xF3BD U+674D # [2000] +0xF3BE U+6754 # [2000] +0xF3BF U+675D # [2000] +0xF3C0 U+233D0 # [2000] [Unicode3.1] +0xF3C1 U+233E4 # [2000] [Unicode3.1] +0xF3C2 U+233D5 # [2000] [Unicode3.1] +0xF3C3 U+6774 # [2000] +0xF3C4 U+6776 # [2000] +0xF3C5 U+233DA # [2000] [Unicode3.1] +0xF3C6 U+6792 # [2000] +0xF3C7 U+233DF # [2000] [Unicode3.1] +0xF3C8 U+8363 # [2000] +0xF3C9 U+6810 # [2000] +0xF3CA U+67B0 # [2000] +0xF3CB U+67B2 # [2000] +0xF3CC U+67C3 # [2000] +0xF3CD U+67C8 # [2000] +0xF3CE U+67D2 # [2000] +0xF3CF U+67D9 # [2000] +0xF3D0 U+67DB # [2000] +0xF3D1 U+67F0 # [2000] +0xF3D2 U+67F7 # [2000] +0xF3D3 U+2344A # [2000] [Unicode3.1] +0xF3D4 U+23451 # [2000] [Unicode3.1] +0xF3D5 U+2344B # [2000] [Unicode3.1] +0xF3D6 U+6818 # [2000] +0xF3D7 U+681F # [2000] +0xF3D8 U+682D # [2000] +0xF3D9 U+23465 # [2000] [Unicode3.1] +0xF3DA U+6833 # [2000] +0xF3DB U+683B # [2000] +0xF3DC U+683E # [2000] +0xF3DD U+6844 # [2000] +0xF3DE U+6845 # [2000] +0xF3DF U+6849 # [2000] +0xF3E0 U+684C # [2000] +0xF3E1 U+6855 # [2000] +0xF3E2 U+6857 # [2000] +0xF3E3 U+3B77 # [2000] +0xF3E4 U+686B # [2000] +0xF3E5 U+686E # [2000] +0xF3E6 U+687A # [2000] +0xF3E7 U+687C # [2000] +0xF3E8 U+6882 # [2000] +0xF3E9 U+6890 # [2000] +0xF3EA U+6896 # [2000] +0xF3EB U+3B6D # [2000] +0xF3EC U+6898 # [2000] +0xF3ED U+6899 # [2000] +0xF3EE U+689A # [2000] +0xF3EF U+689C # [2000] +0xF3F0 U+68AA # [2000] +0xF3F1 U+68AB # [2000] +0xF3F2 U+68B4 # [2000] +0xF3F3 U+68BB # [2000] +0xF3F4 U+68FB # [2000] +0xF3F5 U+234E4 # [2000] [Unicode3.1] +0xF3F6 U+2355A # [2000] [Unicode3.1] +0xF3F7 U+FA13 # CJK COMPATIBILITY IDEOGRAPH-FA13 [2000] +0xF3F8 U+68C3 # [2000] +0xF3F9 U+68C5 # [2000] +0xF3FA U+68CC # [2000] +0xF3FB U+68CF # [2000] +0xF3FC U+68D6 # [2000] +0xF440 U+68D9 # [2000] +0xF441 U+68E4 # [2000] +0xF442 U+68E5 # [2000] +0xF443 U+68EC # [2000] +0xF444 U+68F7 # [2000] +0xF445 U+6903 # [2000] +0xF446 U+6907 # [2000] +0xF447 U+3B87 # [2000] +0xF448 U+3B88 # [2000] +0xF449 U+23594 # [2000] [Unicode3.1] +0xF44A U+693B # [2000] +0xF44B U+3B8D # [2000] +0xF44C U+6946 # [2000] +0xF44D U+6969 # [2000] +0xF44E U+696C # [2000] +0xF44F U+6972 # [2000] +0xF450 U+697A # [2000] +0xF451 U+697F # [2000] +0xF452 U+6992 # [2000] +0xF453 U+3BA4 # [2000] +0xF454 U+6996 # [2000] +0xF455 U+6998 # [2000] +0xF456 U+69A6 # [2000] +0xF457 U+69B0 # [2000] +0xF458 U+69B7 # [2000] +0xF459 U+69BA # [2000] +0xF45A U+69BC # [2000] +0xF45B U+69C0 # [2000] +0xF45C U+69D1 # [2000] +0xF45D U+69D6 # [2000] +0xF45E U+23639 # [2000] [Unicode3.1] +0xF45F U+23647 # [2000] [Unicode3.1] +0xF460 U+6A30 # [2000] +0xF461 U+23638 # [2000] [Unicode3.1] +0xF462 U+2363A # [2000] [Unicode3.1] +0xF463 U+69E3 # [2000] +0xF464 U+69EE # [2000] +0xF465 U+69EF # [2000] +0xF466 U+69F3 # [2000] +0xF467 U+3BCD # [2000] +0xF468 U+69F4 # [2000] +0xF469 U+69FE # [2000] +0xF46A U+6A11 # [2000] +0xF46B U+6A1A # [2000] +0xF46C U+6A1D # [2000] +0xF46D U+2371C # [2000] [Unicode3.1] +0xF46E U+6A32 # [2000] +0xF46F U+6A33 # [2000] +0xF470 U+6A34 # [2000] +0xF471 U+6A3F # [2000] +0xF472 U+6A46 # [2000] +0xF473 U+6A49 # [2000] +0xF474 U+6A7A # [2000] +0xF475 U+6A4E # [2000] +0xF476 U+6A52 # [2000] +0xF477 U+6A64 # [2000] +0xF478 U+2370C # [2000] [Unicode3.1] +0xF479 U+6A7E # [2000] +0xF47A U+6A83 # [2000] +0xF47B U+6A8B # [2000] +0xF47C U+3BF0 # [2000] +0xF47D U+6A91 # [2000] +0xF47E U+6A9F # [2000] +0xF480 U+6AA1 # [2000] +0xF481 U+23764 # [2000] [Unicode3.1] +0xF482 U+6AAB # [2000] +0xF483 U+6ABD # [2000] +0xF484 U+6AC6 # [2000] +0xF485 U+6AD4 # [2000] +0xF486 U+6AD0 # [2000] +0xF487 U+6ADC # [2000] +0xF488 U+6ADD # [2000] +0xF489 U+237FF # [2000] [Unicode3.1] +0xF48A U+237E7 # [2000] [Unicode3.1] +0xF48B U+6AEC # [2000] +0xF48C U+6AF1 # [2000] +0xF48D U+6AF2 # [2000] +0xF48E U+6AF3 # [2000] +0xF48F U+6AFD # [2000] +0xF490 U+23824 # [2000] [Unicode3.1] +0xF491 U+6B0B # [2000] +0xF492 U+6B0F # [2000] +0xF493 U+6B10 # [2000] +0xF494 U+6B11 # [2000] +0xF495 U+2383D # [2000] [Unicode3.1] +0xF496 U+6B17 # [2000] +0xF497 U+3C26 # [2000] +0xF498 U+6B2F # [2000] +0xF499 U+6B4A # [2000] +0xF49A U+6B58 # [2000] +0xF49B U+6B6C # [2000] +0xF49C U+6B75 # [2000] +0xF49D U+6B7A # [2000] +0xF49E U+6B81 # [2000] +0xF49F U+6B9B # [2000] +0xF4A0 U+6BAE # [2000] +0xF4A1 U+23A98 # [2000] [Unicode3.1] +0xF4A2 U+6BBD # [2000] +0xF4A3 U+6BBE # [2000] +0xF4A4 U+6BC7 # [2000] +0xF4A5 U+6BC8 # [2000] +0xF4A6 U+6BC9 # [2000] +0xF4A7 U+6BDA # [2000] +0xF4A8 U+6BE6 # [2000] +0xF4A9 U+6BE7 # [2000] +0xF4AA U+6BEE # [2000] +0xF4AB U+6BF1 # [2000] +0xF4AC U+6C02 # [2000] +0xF4AD U+6C0A # [2000] +0xF4AE U+6C0E # [2000] +0xF4AF U+6C35 # [2000] +0xF4B0 U+6C36 # [2000] +0xF4B1 U+6C3A # [2000] +0xF4B2 U+23C7F # [2000] [Unicode3.1] +0xF4B3 U+6C3F # [2000] +0xF4B4 U+6C4D # [2000] +0xF4B5 U+6C5B # [2000] +0xF4B6 U+6C6D # [2000] +0xF4B7 U+6C84 # [2000] +0xF4B8 U+6C89 # [2000] +0xF4B9 U+3CC3 # [2000] +0xF4BA U+6C94 # [2000] +0xF4BB U+6C95 # [2000] +0xF4BC U+6C97 # [2000] +0xF4BD U+6CAD # [2000] +0xF4BE U+6CC2 # [2000] +0xF4BF U+6CD0 # [2000] +0xF4C0 U+3CD2 # [2000] +0xF4C1 U+6CD6 # [2000] +0xF4C2 U+6CDA # [2000] +0xF4C3 U+6CDC # [2000] +0xF4C4 U+6CE9 # [2000] +0xF4C5 U+6CEC # [2000] +0xF4C6 U+6CED # [2000] +0xF4C7 U+23D00 # [2000] [Unicode3.1] +0xF4C8 U+6D00 # [2000] +0xF4C9 U+6D0A # [2000] +0xF4CA U+6D24 # [2000] +0xF4CB U+6D26 # [2000] +0xF4CC U+6D27 # [2000] +0xF4CD U+6C67 # [2000] +0xF4CE U+6D2F # [2000] +0xF4CF U+6D3C # [2000] +0xF4D0 U+6D5B # [2000] +0xF4D1 U+6D5E # [2000] +0xF4D2 U+6D60 # [2000] +0xF4D3 U+6D70 # [2000] +0xF4D4 U+6D80 # [2000] +0xF4D5 U+6D81 # [2000] +0xF4D6 U+6D8A # [2000] +0xF4D7 U+6D8D # [2000] +0xF4D8 U+6D91 # [2000] +0xF4D9 U+6D98 # [2000] +0xF4DA U+23D40 # [2000] [Unicode3.1] +0xF4DB U+6E17 # [2000] +0xF4DC U+23DFA # [2000] [Unicode3.1] +0xF4DD U+23DF9 # [2000] [Unicode3.1] +0xF4DE U+23DD3 # [2000] [Unicode3.1] +0xF4DF U+6DAB # [2000] +0xF4E0 U+6DAE # [2000] +0xF4E1 U+6DB4 # [2000] +0xF4E2 U+6DC2 # [2000] +0xF4E3 U+6D34 # [2000] +0xF4E4 U+6DC8 # [2000] +0xF4E5 U+6DCE # [2000] +0xF4E6 U+6DCF # [2000] +0xF4E7 U+6DD0 # [2000] +0xF4E8 U+6DDF # [2000] +0xF4E9 U+6DE9 # [2000] +0xF4EA U+6DF6 # [2000] +0xF4EB U+6E36 # [2000] +0xF4EC U+6E1E # [2000] +0xF4ED U+6E22 # [2000] +0xF4EE U+6E27 # [2000] +0xF4EF U+3D11 # [2000] +0xF4F0 U+6E32 # [2000] +0xF4F1 U+6E3C # [2000] +0xF4F2 U+6E48 # [2000] +0xF4F3 U+6E49 # [2000] +0xF4F4 U+6E4B # [2000] +0xF4F5 U+6E4C # [2000] +0xF4F6 U+6E4F # [2000] +0xF4F7 U+6E51 # [2000] +0xF4F8 U+6E53 # [2000] +0xF4F9 U+6E54 # [2000] +0xF4FA U+6E57 # [2000] +0xF4FB U+6E63 # [2000] +0xF4FC U+3D1E # [2000] +0xF540 U+6E93 # [2000] +0xF541 U+6EA7 # [2000] +0xF542 U+6EB4 # [2000] +0xF543 U+6EBF # [2000] +0xF544 U+6EC3 # [2000] +0xF545 U+6ECA # [2000] +0xF546 U+6ED9 # [2000] +0xF547 U+6F35 # [2000] +0xF548 U+6EEB # [2000] +0xF549 U+6EF9 # [2000] +0xF54A U+6EFB # [2000] +0xF54B U+6F0A # [2000] +0xF54C U+6F0C # [2000] +0xF54D U+6F18 # [2000] +0xF54E U+6F25 # [2000] +0xF54F U+6F36 # [2000] +0xF550 U+6F3C # [2000] +0xF551 U+23F7E # [2000] [Unicode3.1] +0xF552 U+6F52 # [2000] +0xF553 U+6F57 # [2000] +0xF554 U+6F5A # [2000] +0xF555 U+6F60 # [2000] +0xF556 U+6F68 # [2000] +0xF557 U+6F98 # [2000] +0xF558 U+6F7D # [2000] +0xF559 U+6F90 # [2000] +0xF55A U+6F96 # [2000] +0xF55B U+6FBE # [2000] +0xF55C U+6F9F # [2000] +0xF55D U+6FA5 # [2000] +0xF55E U+6FAF # [2000] +0xF55F U+3D64 # [2000] +0xF560 U+6FB5 # [2000] +0xF561 U+6FC8 # [2000] +0xF562 U+6FC9 # [2000] +0xF563 U+6FDA # [2000] +0xF564 U+6FDE # [2000] +0xF565 U+6FE9 # [2000] +0xF566 U+24096 # [2000] [Unicode3.1] +0xF567 U+6FFC # [2000] +0xF568 U+7000 # [2000] +0xF569 U+7007 # [2000] +0xF56A U+700A # [2000] +0xF56B U+7023 # [2000] +0xF56C U+24103 # [2000] [Unicode3.1] +0xF56D U+7039 # [2000] +0xF56E U+703A # [2000] +0xF56F U+703C # [2000] +0xF570 U+7043 # [2000] +0xF571 U+7047 # [2000] +0xF572 U+704B # [2000] +0xF573 U+3D9A # [2000] +0xF574 U+7054 # [2000] +0xF575 U+7065 # [2000] +0xF576 U+7069 # [2000] +0xF577 U+706C # [2000] +0xF578 U+706E # [2000] +0xF579 U+7076 # [2000] +0xF57A U+707E # [2000] +0xF57B U+7081 # [2000] +0xF57C U+7086 # [2000] +0xF57D U+7095 # [2000] +0xF57E U+7097 # [2000] +0xF580 U+70BB # [2000] +0xF581 U+241C6 # [2000] [Unicode3.1] +0xF582 U+709F # [2000] +0xF583 U+70B1 # [2000] +0xF584 U+241FE # [2000] [Unicode3.1] +0xF585 U+70EC # [2000] +0xF586 U+70CA # [2000] +0xF587 U+70D1 # [2000] +0xF588 U+70D3 # [2000] +0xF589 U+70DC # [2000] +0xF58A U+7103 # [2000] +0xF58B U+7104 # [2000] +0xF58C U+7106 # [2000] +0xF58D U+7107 # [2000] +0xF58E U+7108 # [2000] +0xF58F U+710C # [2000] +0xF590 U+3DC0 # [2000] +0xF591 U+712F # [2000] +0xF592 U+7131 # [2000] +0xF593 U+7150 # [2000] +0xF594 U+714A # [2000] +0xF595 U+7153 # [2000] +0xF596 U+715E # [2000] +0xF597 U+3DD4 # [2000] +0xF598 U+7196 # [2000] +0xF599 U+7180 # [2000] +0xF59A U+719B # [2000] +0xF59B U+71A0 # [2000] +0xF59C U+71A2 # [2000] +0xF59D U+71AE # [2000] +0xF59E U+71AF # [2000] +0xF59F U+71B3 # [2000] +0xF5A0 U+243BC # [2000] [Unicode3.1] +0xF5A1 U+71CB # [2000] +0xF5A2 U+71D3 # [2000] +0xF5A3 U+71D9 # [2000] +0xF5A4 U+71DC # [2000] +0xF5A5 U+7207 # [2000] +0xF5A6 U+3E05 # [2000] +0xF5A7 U+FA49 # CJK COMPATIBILITY IDEOGRAPH-FA49 [2000] [Unicode3.2] +0xF5A8 U+722B # [2000] +0xF5A9 U+7234 # [2000] +0xF5AA U+7238 # [2000] +0xF5AB U+7239 # [2000] +0xF5AC U+4E2C # [2000] +0xF5AD U+7242 # [2000] +0xF5AE U+7253 # [2000] +0xF5AF U+7257 # [2000] +0xF5B0 U+7263 # [2000] +0xF5B1 U+24629 # [2000] [Unicode3.1] +0xF5B2 U+726E # [2000] +0xF5B3 U+726F # [2000] +0xF5B4 U+7278 # [2000] +0xF5B5 U+727F # [2000] +0xF5B6 U+728E # [2000] +0xF5B7 U+246A5 # [2000] [Unicode3.1] +0xF5B8 U+72AD # [2000] +0xF5B9 U+72AE # [2000] +0xF5BA U+72B0 # [2000] +0xF5BB U+72B1 # [2000] +0xF5BC U+72C1 # [2000] +0xF5BD U+3E60 # [2000] +0xF5BE U+72CC # [2000] +0xF5BF U+3E66 # [2000] +0xF5C0 U+3E68 # [2000] +0xF5C1 U+72F3 # [2000] +0xF5C2 U+72FA # [2000] +0xF5C3 U+7307 # [2000] +0xF5C4 U+7312 # [2000] +0xF5C5 U+7318 # [2000] +0xF5C6 U+7319 # [2000] +0xF5C7 U+3E83 # [2000] +0xF5C8 U+7339 # [2000] +0xF5C9 U+732C # [2000] +0xF5CA U+7331 # [2000] +0xF5CB U+7333 # [2000] +0xF5CC U+733D # [2000] +0xF5CD U+7352 # [2000] +0xF5CE U+3E94 # [2000] +0xF5CF U+736B # [2000] +0xF5D0 U+736C # [2000] +0xF5D1 U+24896 # [2000] [Unicode3.1] +0xF5D2 U+736E # [2000] +0xF5D3 U+736F # [2000] +0xF5D4 U+7371 # [2000] +0xF5D5 U+7377 # [2000] +0xF5D6 U+7381 # [2000] +0xF5D7 U+7385 # [2000] +0xF5D8 U+738A # [2000] +0xF5D9 U+7394 # [2000] +0xF5DA U+7398 # [2000] +0xF5DB U+739C # [2000] +0xF5DC U+739E # [2000] +0xF5DD U+73A5 # [2000] +0xF5DE U+73A8 # [2000] +0xF5DF U+73B5 # [2000] +0xF5E0 U+73B7 # [2000] +0xF5E1 U+73B9 # [2000] +0xF5E2 U+73BC # [2000] +0xF5E3 U+73BF # [2000] +0xF5E4 U+73C5 # [2000] +0xF5E5 U+73CB # [2000] +0xF5E6 U+73E1 # [2000] +0xF5E7 U+73E7 # [2000] +0xF5E8 U+73F9 # [2000] +0xF5E9 U+7413 # [2000] +0xF5EA U+73FA # [2000] +0xF5EB U+7401 # [2000] +0xF5EC U+7424 # [2000] +0xF5ED U+7431 # [2000] +0xF5EE U+7439 # [2000] +0xF5EF U+7453 # [2000] +0xF5F0 U+7440 # [2000] +0xF5F1 U+7443 # [2000] +0xF5F2 U+744D # [2000] +0xF5F3 U+7452 # [2000] +0xF5F4 U+745D # [2000] +0xF5F5 U+7471 # [2000] +0xF5F6 U+7481 # [2000] +0xF5F7 U+7485 # [2000] +0xF5F8 U+7488 # [2000] +0xF5F9 U+24A4D # [2000] [Unicode3.1] +0xF5FA U+7492 # [2000] +0xF5FB U+7497 # [2000] +0xF5FC U+7499 # [2000] +0xF640 U+74A0 # [2000] +0xF641 U+74A1 # [2000] +0xF642 U+74A5 # [2000] +0xF643 U+74AA # [2000] +0xF644 U+74AB # [2000] +0xF645 U+74B9 # [2000] +0xF646 U+74BB # [2000] +0xF647 U+74BA # [2000] +0xF648 U+74D6 # [2000] +0xF649 U+74D8 # [2000] +0xF64A U+74DE # [2000] +0xF64B U+74EF # [2000] +0xF64C U+74EB # [2000] +0xF64D U+24B56 # [2000] [Unicode3.1] +0xF64E U+74FA # [2000] +0xF64F U+24B6F # [2000] [Unicode3.1] +0xF650 U+7520 # [2000] +0xF651 U+7524 # [2000] +0xF652 U+752A # [2000] +0xF653 U+3F57 # [2000] +0xF654 U+24C16 # [2000] [Unicode3.1] +0xF655 U+753D # [2000] +0xF656 U+753E # [2000] +0xF657 U+7540 # [2000] +0xF658 U+7548 # [2000] +0xF659 U+754E # [2000] +0xF65A U+7550 # [2000] +0xF65B U+7552 # [2000] +0xF65C U+756C # [2000] +0xF65D U+7572 # [2000] +0xF65E U+7571 # [2000] +0xF65F U+757A # [2000] +0xF660 U+757D # [2000] +0xF661 U+757E # [2000] +0xF662 U+7581 # [2000] +0xF663 U+24D14 # [2000] [Unicode3.1] +0xF664 U+758C # [2000] +0xF665 U+3F75 # [2000] +0xF666 U+75A2 # [2000] +0xF667 U+3F77 # [2000] +0xF668 U+75B0 # [2000] +0xF669 U+75B7 # [2000] +0xF66A U+75BF # [2000] +0xF66B U+75C0 # [2000] +0xF66C U+75C6 # [2000] +0xF66D U+75CF # [2000] +0xF66E U+75D3 # [2000] +0xF66F U+75DD # [2000] +0xF670 U+75DF # [2000] +0xF671 U+75E0 # [2000] +0xF672 U+75E7 # [2000] +0xF673 U+75EC # [2000] +0xF674 U+75EE # [2000] +0xF675 U+75F1 # [2000] +0xF676 U+75F9 # [2000] +0xF677 U+7603 # [2000] +0xF678 U+7618 # [2000] +0xF679 U+7607 # [2000] +0xF67A U+760F # [2000] +0xF67B U+3FAE # [2000] +0xF67C U+24E0E # [2000] [Unicode3.1] +0xF67D U+7613 # [2000] +0xF67E U+761B # [2000] +0xF680 U+761C # [2000] +0xF681 U+24E37 # [2000] [Unicode3.1] +0xF682 U+7625 # [2000] +0xF683 U+7628 # [2000] +0xF684 U+763C # [2000] +0xF685 U+7633 # [2000] +0xF686 U+24E6A # [2000] [Unicode3.1] +0xF687 U+3FC9 # [2000] +0xF688 U+7641 # [2000] +0xF689 U+24E8B # [2000] [Unicode3.1] +0xF68A U+7649 # [2000] +0xF68B U+7655 # [2000] +0xF68C U+3FD7 # [2000] +0xF68D U+766E # [2000] +0xF68E U+7695 # [2000] +0xF68F U+769C # [2000] +0xF690 U+76A1 # [2000] +0xF691 U+76A0 # [2000] +0xF692 U+76A7 # [2000] +0xF693 U+76A8 # [2000] +0xF694 U+76AF # [2000] +0xF695 U+2504A # [2000] [Unicode3.1] +0xF696 U+76C9 # [2000] +0xF697 U+25055 # [2000] [Unicode3.1] +0xF698 U+76E8 # [2000] +0xF699 U+76EC # [2000] +0xF69A U+25122 # [2000] [Unicode3.1] +0xF69B U+7717 # [2000] +0xF69C U+771A # [2000] +0xF69D U+772D # [2000] +0xF69E U+7735 # [2000] +0xF69F U+251A9 # [2000] [Unicode3.1] +0xF6A0 U+4039 # [2000] +0xF6A1 U+251E5 # [2000] [Unicode3.1] +0xF6A2 U+251CD # [2000] [Unicode3.1] +0xF6A3 U+7758 # [2000] +0xF6A4 U+7760 # [2000] +0xF6A5 U+776A # [2000] +0xF6A6 U+2521E # [2000] [Unicode3.1] +0xF6A7 U+7772 # [2000] +0xF6A8 U+777C # [2000] +0xF6A9 U+777D # [2000] +0xF6AA U+2524C # [2000] [Unicode3.1] +0xF6AB U+4058 # [2000] +0xF6AC U+779A # [2000] +0xF6AD U+779F # [2000] +0xF6AE U+77A2 # [2000] +0xF6AF U+77A4 # [2000] +0xF6B0 U+77A9 # [2000] +0xF6B1 U+77DE # [2000] +0xF6B2 U+77DF # [2000] +0xF6B3 U+77E4 # [2000] +0xF6B4 U+77E6 # [2000] +0xF6B5 U+77EA # [2000] +0xF6B6 U+77EC # [2000] +0xF6B7 U+4093 # [2000] +0xF6B8 U+77F0 # [2000] +0xF6B9 U+77F4 # [2000] +0xF6BA U+77FB # [2000] +0xF6BB U+2542E # [2000] [Unicode3.1] +0xF6BC U+7805 # [2000] +0xF6BD U+7806 # [2000] +0xF6BE U+7809 # [2000] +0xF6BF U+780D # [2000] +0xF6C0 U+7819 # [2000] +0xF6C1 U+7821 # [2000] +0xF6C2 U+782C # [2000] +0xF6C3 U+7847 # [2000] +0xF6C4 U+7864 # [2000] +0xF6C5 U+786A # [2000] +0xF6C6 U+254D9 # [2000] [Unicode3.1] +0xF6C7 U+788A # [2000] +0xF6C8 U+7894 # [2000] +0xF6C9 U+78A4 # [2000] +0xF6CA U+789D # [2000] +0xF6CB U+789E # [2000] +0xF6CC U+789F # [2000] +0xF6CD U+78BB # [2000] +0xF6CE U+78C8 # [2000] +0xF6CF U+78CC # [2000] +0xF6D0 U+78CE # [2000] +0xF6D1 U+78D5 # [2000] +0xF6D2 U+78E0 # [2000] +0xF6D3 U+78E1 # [2000] +0xF6D4 U+78E6 # [2000] +0xF6D5 U+78F9 # [2000] +0xF6D6 U+78FA # [2000] +0xF6D7 U+78FB # [2000] +0xF6D8 U+78FE # [2000] +0xF6D9 U+255A7 # [2000] [Unicode3.1] +0xF6DA U+7910 # [2000] +0xF6DB U+791B # [2000] +0xF6DC U+7930 # [2000] +0xF6DD U+7925 # [2000] +0xF6DE U+793B # [2000] +0xF6DF U+794A # [2000] +0xF6E0 U+7958 # [2000] +0xF6E1 U+795B # [2000] +0xF6E2 U+4105 # [2000] +0xF6E3 U+7967 # [2000] +0xF6E4 U+7972 # [2000] +0xF6E5 U+7994 # [2000] +0xF6E6 U+7995 # [2000] +0xF6E7 U+7996 # [2000] +0xF6E8 U+799B # [2000] +0xF6E9 U+79A1 # [2000] +0xF6EA U+79A9 # [2000] +0xF6EB U+79B4 # [2000] +0xF6EC U+79BB # [2000] +0xF6ED U+79C2 # [2000] +0xF6EE U+79C7 # [2000] +0xF6EF U+79CC # [2000] +0xF6F0 U+79CD # [2000] +0xF6F1 U+79D6 # [2000] +0xF6F2 U+4148 # [2000] +0xF6F3 U+257A9 # [2000] [Unicode3.1] +0xF6F4 U+257B4 # [2000] [Unicode3.1] +0xF6F5 U+414F # [2000] +0xF6F6 U+7A0A # [2000] +0xF6F7 U+7A11 # [2000] +0xF6F8 U+7A15 # [2000] +0xF6F9 U+7A1B # [2000] +0xF6FA U+7A1E # [2000] +0xF6FB U+4163 # [2000] +0xF6FC U+7A2D # [2000] +0xF740 U+7A38 # [2000] +0xF741 U+7A47 # [2000] +0xF742 U+7A4C # [2000] +0xF743 U+7A56 # [2000] +0xF744 U+7A59 # [2000] +0xF745 U+7A5C # [2000] +0xF746 U+7A5F # [2000] +0xF747 U+7A60 # [2000] +0xF748 U+7A67 # [2000] +0xF749 U+7A6A # [2000] +0xF74A U+7A75 # [2000] +0xF74B U+7A78 # [2000] +0xF74C U+7A82 # [2000] +0xF74D U+7A8A # [2000] +0xF74E U+7A90 # [2000] +0xF74F U+7AA3 # [2000] +0xF750 U+7AAC # [2000] +0xF751 U+259D4 # [2000] [Unicode3.1] +0xF752 U+41B4 # [2000] +0xF753 U+7AB9 # [2000] +0xF754 U+7ABC # [2000] +0xF755 U+7ABE # [2000] +0xF756 U+41BF # [2000] +0xF757 U+7ACC # [2000] +0xF758 U+7AD1 # [2000] +0xF759 U+7AE7 # [2000] +0xF75A U+7AE8 # [2000] +0xF75B U+7AF4 # [2000] +0xF75C U+25AE4 # [2000] [Unicode3.1] +0xF75D U+25AE3 # [2000] [Unicode3.1] +0xF75E U+7B07 # [2000] +0xF75F U+25AF1 # [2000] [Unicode3.1] +0xF760 U+7B3D # [2000] +0xF761 U+7B27 # [2000] +0xF762 U+7B2A # [2000] +0xF763 U+7B2E # [2000] +0xF764 U+7B2F # [2000] +0xF765 U+7B31 # [2000] +0xF766 U+41E6 # [2000] +0xF767 U+41F3 # [2000] +0xF768 U+7B7F # [2000] +0xF769 U+7B41 # [2000] +0xF76A U+41EE # [2000] +0xF76B U+7B55 # [2000] +0xF76C U+7B79 # [2000] +0xF76D U+7B64 # [2000] +0xF76E U+7B66 # [2000] +0xF76F U+7B69 # [2000] +0xF770 U+7B73 # [2000] +0xF771 U+25BB2 # [2000] [Unicode3.1] +0xF772 U+4207 # [2000] +0xF773 U+7B90 # [2000] +0xF774 U+7B91 # [2000] +0xF775 U+7B9B # [2000] +0xF776 U+420E # [2000] +0xF777 U+7BAF # [2000] +0xF778 U+7BB5 # [2000] +0xF779 U+7BBC # [2000] +0xF77A U+7BC5 # [2000] +0xF77B U+7BCA # [2000] +0xF77C U+25C4B # [2000] [Unicode3.1] +0xF77D U+25C64 # [2000] [Unicode3.1] +0xF77E U+7BD4 # [2000] +0xF780 U+7BD6 # [2000] +0xF781 U+7BDA # [2000] +0xF782 U+7BEA # [2000] +0xF783 U+7BF0 # [2000] +0xF784 U+7C03 # [2000] +0xF785 U+7C0B # [2000] +0xF786 U+7C0E # [2000] +0xF787 U+7C0F # [2000] +0xF788 U+7C26 # [2000] +0xF789 U+7C45 # [2000] +0xF78A U+7C4A # [2000] +0xF78B U+7C51 # [2000] +0xF78C U+7C57 # [2000] +0xF78D U+7C5E # [2000] +0xF78E U+7C61 # [2000] +0xF78F U+7C69 # [2000] +0xF790 U+7C6E # [2000] +0xF791 U+7C6F # [2000] +0xF792 U+7C70 # [2000] +0xF793 U+25E2E # [2000] [Unicode3.1] +0xF794 U+25E56 # [2000] [Unicode3.1] +0xF795 U+25E65 # [2000] [Unicode3.1] +0xF796 U+7CA6 # [2000] +0xF797 U+25E62 # [2000] [Unicode3.1] +0xF798 U+7CB6 # [2000] +0xF799 U+7CB7 # [2000] +0xF79A U+7CBF # [2000] +0xF79B U+25ED8 # [2000] [Unicode3.1] +0xF79C U+7CC4 # [2000] +0xF79D U+25EC2 # [2000] [Unicode3.1] +0xF79E U+7CC8 # [2000] +0xF79F U+7CCD # [2000] +0xF7A0 U+25EE8 # [2000] [Unicode3.1] +0xF7A1 U+7CD7 # [2000] +0xF7A2 U+25F23 # [2000] [Unicode3.1] +0xF7A3 U+7CE6 # [2000] +0xF7A4 U+7CEB # [2000] +0xF7A5 U+25F5C # [2000] [Unicode3.1] +0xF7A6 U+7CF5 # [2000] +0xF7A7 U+7D03 # [2000] +0xF7A8 U+7D09 # [2000] +0xF7A9 U+42C6 # [2000] +0xF7AA U+7D12 # [2000] +0xF7AB U+7D1E # [2000] +0xF7AC U+25FE0 # [2000] [Unicode3.1] +0xF7AD U+25FD4 # [2000] [Unicode3.1] +0xF7AE U+7D3D # [2000] +0xF7AF U+7D3E # [2000] +0xF7B0 U+7D40 # [2000] +0xF7B1 U+7D47 # [2000] +0xF7B2 U+2600C # [2000] [Unicode3.1] +0xF7B3 U+25FFB # [2000] [Unicode3.1] +0xF7B4 U+42D6 # [2000] +0xF7B5 U+7D59 # [2000] +0xF7B6 U+7D5A # [2000] +0xF7B7 U+7D6A # [2000] +0xF7B8 U+7D70 # [2000] +0xF7B9 U+42DD # [2000] +0xF7BA U+7D7F # [2000] +0xF7BB U+26017 # [2000] [Unicode3.1] +0xF7BC U+7D86 # [2000] +0xF7BD U+7D88 # [2000] +0xF7BE U+7D8C # [2000] +0xF7BF U+7D97 # [2000] +0xF7C0 U+26060 # [2000] [Unicode3.1] +0xF7C1 U+7D9D # [2000] +0xF7C2 U+7DA7 # [2000] +0xF7C3 U+7DAA # [2000] +0xF7C4 U+7DB6 # [2000] +0xF7C5 U+7DB7 # [2000] +0xF7C6 U+7DC0 # [2000] +0xF7C7 U+7DD7 # [2000] +0xF7C8 U+7DD9 # [2000] +0xF7C9 U+7DE6 # [2000] +0xF7CA U+7DF1 # [2000] +0xF7CB U+7DF9 # [2000] +0xF7CC U+4302 # [2000] +0xF7CD U+260ED # [2000] [Unicode3.1] +0xF7CE U+FA58 # CJK COMPATIBILITY IDEOGRAPH-FA58 [2000] [Unicode3.2] +0xF7CF U+7E10 # [2000] +0xF7D0 U+7E17 # [2000] +0xF7D1 U+7E1D # [2000] +0xF7D2 U+7E20 # [2000] +0xF7D3 U+7E27 # [2000] +0xF7D4 U+7E2C # [2000] +0xF7D5 U+7E45 # [2000] +0xF7D6 U+7E73 # [2000] +0xF7D7 U+7E75 # [2000] +0xF7D8 U+7E7E # [2000] +0xF7D9 U+7E86 # [2000] +0xF7DA U+7E87 # [2000] +0xF7DB U+432B # [2000] +0xF7DC U+7E91 # [2000] +0xF7DD U+7E98 # [2000] +0xF7DE U+7E9A # [2000] +0xF7DF U+4343 # [2000] +0xF7E0 U+7F3C # [2000] +0xF7E1 U+7F3B # [2000] +0xF7E2 U+7F3E # [2000] +0xF7E3 U+7F43 # [2000] +0xF7E4 U+7F44 # [2000] +0xF7E5 U+7F4F # [2000] +0xF7E6 U+34C1 # [2000] +0xF7E7 U+26270 # [2000] [Unicode3.1] +0xF7E8 U+7F52 # [2000] +0xF7E9 U+26286 # [2000] [Unicode3.1] +0xF7EA U+7F61 # [2000] +0xF7EB U+7F63 # [2000] +0xF7EC U+7F64 # [2000] +0xF7ED U+7F6D # [2000] +0xF7EE U+7F7D # [2000] +0xF7EF U+7F7E # [2000] +0xF7F0 U+2634C # [2000] [Unicode3.1] +0xF7F1 U+7F90 # [2000] +0xF7F2 U+517B # [2000] +0xF7F3 U+23D0E # [2000] [Unicode3.1] +0xF7F4 U+7F96 # [2000] +0xF7F5 U+7F9C # [2000] +0xF7F6 U+7FAD # [2000] +0xF7F7 U+26402 # [2000] [Unicode3.1] +0xF7F8 U+7FC3 # [2000] +0xF7F9 U+7FCF # [2000] +0xF7FA U+7FE3 # [2000] +0xF7FB U+7FE5 # [2000] +0xF7FC U+7FEF # [2000] +0xF840 U+7FF2 # [2000] +0xF841 U+8002 # [2000] +0xF842 U+800A # [2000] +0xF843 U+8008 # [2000] +0xF844 U+800E # [2000] +0xF845 U+8011 # [2000] +0xF846 U+8016 # [2000] +0xF847 U+8024 # [2000] +0xF848 U+802C # [2000] +0xF849 U+8030 # [2000] +0xF84A U+8043 # [2000] +0xF84B U+8066 # [2000] +0xF84C U+8071 # [2000] +0xF84D U+8075 # [2000] +0xF84E U+807B # [2000] +0xF84F U+8099 # [2000] +0xF850 U+809C # [2000] +0xF851 U+80A4 # [2000] +0xF852 U+80A7 # [2000] +0xF853 U+80B8 # [2000] +0xF854 U+2667E # [2000] [Unicode3.1] +0xF855 U+80C5 # [2000] +0xF856 U+80D5 # [2000] +0xF857 U+80D8 # [2000] +0xF858 U+80E6 # [2000] +0xF859 U+266B0 # [2000] [Unicode3.1] +0xF85A U+810D # [2000] +0xF85B U+80F5 # [2000] +0xF85C U+80FB # [2000] +0xF85D U+43EE # [2000] +0xF85E U+8135 # [2000] +0xF85F U+8116 # [2000] +0xF860 U+811E # [2000] +0xF861 U+43F0 # [2000] +0xF862 U+8124 # [2000] +0xF863 U+8127 # [2000] +0xF864 U+812C # [2000] +0xF865 U+2671D # [2000] [Unicode3.1] +0xF866 U+813D # [2000] +0xF867 U+4408 # [2000] +0xF868 U+8169 # [2000] +0xF869 U+4417 # [2000] +0xF86A U+8181 # [2000] +0xF86B U+441C # [2000] +0xF86C U+8184 # [2000] +0xF86D U+8185 # [2000] +0xF86E U+4422 # [2000] +0xF86F U+8198 # [2000] +0xF870 U+81B2 # [2000] +0xF871 U+81C1 # [2000] +0xF872 U+81C3 # [2000] +0xF873 U+81D6 # [2000] +0xF874 U+81DB # [2000] +0xF875 U+268DD # [2000] [Unicode3.1] +0xF876 U+81E4 # [2000] +0xF877 U+268EA # [2000] [Unicode3.1] +0xF878 U+81EC # [2000] +0xF879 U+26951 # [2000] [Unicode3.1] +0xF87A U+81FD # [2000] +0xF87B U+81FF # [2000] +0xF87C U+2696F # [2000] [Unicode3.1] +0xF87D U+8204 # [2000] +0xF87E U+269DD # [2000] [Unicode3.1] +0xF880 U+8219 # [2000] +0xF881 U+8221 # [2000] +0xF882 U+8222 # [2000] +0xF883 U+26A1E # [2000] [Unicode3.1] +0xF884 U+8232 # [2000] +0xF885 U+8234 # [2000] +0xF886 U+823C # [2000] +0xF887 U+8246 # [2000] +0xF888 U+8249 # [2000] +0xF889 U+8245 # [2000] +0xF88A U+26A58 # [2000] [Unicode3.1] +0xF88B U+824B # [2000] +0xF88C U+4476 # [2000] +0xF88D U+824F # [2000] +0xF88E U+447A # [2000] +0xF88F U+8257 # [2000] +0xF890 U+26A8C # [2000] [Unicode3.1] +0xF891 U+825C # [2000] +0xF892 U+8263 # [2000] +0xF893 U+26AB7 # [2000] [Unicode3.1] +0xF894 U+FA5D # CJK COMPATIBILITY IDEOGRAPH-FA5D [2000] [Unicode3.2] +0xF895 U+FA5E # CJK COMPATIBILITY IDEOGRAPH-FA5E [2000] [Unicode3.2] +0xF896 U+8279 # [2000] +0xF897 U+4491 # [2000] +0xF898 U+827D # [2000] +0xF899 U+827F # [2000] +0xF89A U+8283 # [2000] +0xF89B U+828A # [2000] +0xF89C U+8293 # [2000] +0xF89D U+82A7 # [2000] +0xF89E U+82A8 # [2000] +0xF89F U+82B2 # [2000] +0xF8A0 U+82B4 # [2000] +0xF8A1 U+82BA # [2000] +0xF8A2 U+82BC # [2000] +0xF8A3 U+82E2 # [2000] +0xF8A4 U+82E8 # [2000] +0xF8A5 U+82F7 # [2000] +0xF8A6 U+8307 # [2000] +0xF8A7 U+8308 # [2000] +0xF8A8 U+830C # [2000] +0xF8A9 U+8354 # [2000] +0xF8AA U+831B # [2000] +0xF8AB U+831D # [2000] +0xF8AC U+8330 # [2000] +0xF8AD U+833C # [2000] +0xF8AE U+8344 # [2000] +0xF8AF U+8357 # [2000] +0xF8B0 U+44BE # [2000] +0xF8B1 U+837F # [2000] +0xF8B2 U+44D4 # [2000] +0xF8B3 U+44B3 # [2000] +0xF8B4 U+838D # [2000] +0xF8B5 U+8394 # [2000] +0xF8B6 U+8395 # [2000] +0xF8B7 U+839B # [2000] +0xF8B8 U+839D # [2000] +0xF8B9 U+83C9 # [2000] +0xF8BA U+83D0 # [2000] +0xF8BB U+83D4 # [2000] +0xF8BC U+83DD # [2000] +0xF8BD U+83E5 # [2000] +0xF8BE U+83F9 # [2000] +0xF8BF U+840F # [2000] +0xF8C0 U+8411 # [2000] +0xF8C1 U+8415 # [2000] +0xF8C2 U+26C73 # [2000] [Unicode3.1] +0xF8C3 U+8417 # [2000] +0xF8C4 U+8439 # [2000] +0xF8C5 U+844A # [2000] +0xF8C6 U+844F # [2000] +0xF8C7 U+8451 # [2000] +0xF8C8 U+8452 # [2000] +0xF8C9 U+8459 # [2000] +0xF8CA U+845A # [2000] +0xF8CB U+845C # [2000] +0xF8CC U+26CDD # [2000] [Unicode3.1] +0xF8CD U+8465 # [2000] +0xF8CE U+8476 # [2000] +0xF8CF U+8478 # [2000] +0xF8D0 U+847C # [2000] +0xF8D1 U+8481 # [2000] +0xF8D2 U+450D # [2000] +0xF8D3 U+84DC # [2000] +0xF8D4 U+8497 # [2000] +0xF8D5 U+84A6 # [2000] +0xF8D6 U+84BE # [2000] +0xF8D7 U+4508 # [2000] +0xF8D8 U+84CE # [2000] +0xF8D9 U+84CF # [2000] +0xF8DA U+84D3 # [2000] +0xF8DB U+26E65 # [2000] [Unicode3.1] +0xF8DC U+84E7 # [2000] +0xF8DD U+84EA # [2000] +0xF8DE U+84EF # [2000] +0xF8DF U+84F0 # [2000] +0xF8E0 U+84F1 # [2000] +0xF8E1 U+84FA # [2000] +0xF8E2 U+84FD # [2000] +0xF8E3 U+850C # [2000] +0xF8E4 U+851B # [2000] +0xF8E5 U+8524 # [2000] +0xF8E6 U+8525 # [2000] +0xF8E7 U+852B # [2000] +0xF8E8 U+8534 # [2000] +0xF8E9 U+854F # [2000] +0xF8EA U+856F # [2000] +0xF8EB U+4525 # [2000] +0xF8EC U+4543 # [2000] +0xF8ED U+853E # [2000] +0xF8EE U+8551 # [2000] +0xF8EF U+8553 # [2000] +0xF8F0 U+855E # [2000] +0xF8F1 U+8561 # [2000] +0xF8F2 U+8562 # [2000] +0xF8F3 U+26F94 # [2000] [Unicode3.1] +0xF8F4 U+857B # [2000] +0xF8F5 U+857D # [2000] +0xF8F6 U+857F # [2000] +0xF8F7 U+8581 # [2000] +0xF8F8 U+8586 # [2000] +0xF8F9 U+8593 # [2000] +0xF8FA U+859D # [2000] +0xF8FB U+859F # [2000] +0xF8FC U+26FF8 # [2000] [Unicode3.1] +0xF940 U+26FF6 # [2000] [Unicode3.1] +0xF941 U+26FF7 # [2000] [Unicode3.1] +0xF942 U+85B7 # [2000] +0xF943 U+85BC # [2000] +0xF944 U+85C7 # [2000] +0xF945 U+85CA # [2000] +0xF946 U+85D8 # [2000] +0xF947 U+85D9 # [2000] +0xF948 U+85DF # [2000] +0xF949 U+85E1 # [2000] +0xF94A U+85E6 # [2000] +0xF94B U+85F6 # [2000] +0xF94C U+8600 # [2000] +0xF94D U+8611 # [2000] +0xF94E U+861E # [2000] +0xF94F U+8621 # [2000] +0xF950 U+8624 # [2000] +0xF951 U+8627 # [2000] +0xF952 U+2710D # [2000] [Unicode3.1] +0xF953 U+8639 # [2000] +0xF954 U+863C # [2000] +0xF955 U+27139 # [2000] [Unicode3.1] +0xF956 U+8640 # [2000] +0xF957 U+FA20 # CJK COMPATIBILITY IDEOGRAPH-FA20 [2000] +0xF958 U+8653 # [2000] +0xF959 U+8656 # [2000] +0xF95A U+866F # [2000] +0xF95B U+8677 # [2000] +0xF95C U+867A # [2000] +0xF95D U+8687 # [2000] +0xF95E U+8689 # [2000] +0xF95F U+868D # [2000] +0xF960 U+8691 # [2000] +0xF961 U+869C # [2000] +0xF962 U+869D # [2000] +0xF963 U+86A8 # [2000] +0xF964 U+FA21 # CJK COMPATIBILITY IDEOGRAPH-FA21 [2000] +0xF965 U+86B1 # [2000] +0xF966 U+86B3 # [2000] +0xF967 U+86C1 # [2000] +0xF968 U+86C3 # [2000] +0xF969 U+86D1 # [2000] +0xF96A U+86D5 # [2000] +0xF96B U+86D7 # [2000] +0xF96C U+86E3 # [2000] +0xF96D U+86E6 # [2000] +0xF96E U+45B8 # [2000] +0xF96F U+8705 # [2000] +0xF970 U+8707 # [2000] +0xF971 U+870E # [2000] +0xF972 U+8710 # [2000] +0xF973 U+8713 # [2000] +0xF974 U+8719 # [2000] +0xF975 U+871F # [2000] +0xF976 U+8721 # [2000] +0xF977 U+8723 # [2000] +0xF978 U+8731 # [2000] +0xF979 U+873A # [2000] +0xF97A U+873E # [2000] +0xF97B U+8740 # [2000] +0xF97C U+8743 # [2000] +0xF97D U+8751 # [2000] +0xF97E U+8758 # [2000] +0xF980 U+8764 # [2000] +0xF981 U+8765 # [2000] +0xF982 U+8772 # [2000] +0xF983 U+877C # [2000] +0xF984 U+273DB # [2000] [Unicode3.1] +0xF985 U+273DA # [2000] [Unicode3.1] +0xF986 U+87A7 # [2000] +0xF987 U+8789 # [2000] +0xF988 U+878B # [2000] +0xF989 U+8793 # [2000] +0xF98A U+87A0 # [2000] +0xF98B U+273FE # [2000] [Unicode3.1] +0xF98C U+45E5 # [2000] +0xF98D U+87BE # [2000] +0xF98E U+27410 # [2000] [Unicode3.1] +0xF98F U+87C1 # [2000] +0xF990 U+87CE # [2000] +0xF991 U+87F5 # [2000] +0xF992 U+87DF # [2000] +0xF993 U+27449 # [2000] [Unicode3.1] +0xF994 U+87E3 # [2000] +0xF995 U+87E5 # [2000] +0xF996 U+87E6 # [2000] +0xF997 U+87EA # [2000] +0xF998 U+87EB # [2000] +0xF999 U+87ED # [2000] +0xF99A U+8801 # [2000] +0xF99B U+8803 # [2000] +0xF99C U+880B # [2000] +0xF99D U+8813 # [2000] +0xF99E U+8828 # [2000] +0xF99F U+882E # [2000] +0xF9A0 U+8832 # [2000] +0xF9A1 U+883C # [2000] +0xF9A2 U+460F # [2000] +0xF9A3 U+884A # [2000] +0xF9A4 U+8858 # [2000] +0xF9A5 U+885F # [2000] +0xF9A6 U+8864 # [2000] +0xF9A7 U+27615 # [2000] [Unicode3.1] +0xF9A8 U+27614 # [2000] [Unicode3.1] +0xF9A9 U+8869 # [2000] +0xF9AA U+27631 # [2000] [Unicode3.1] +0xF9AB U+886F # [2000] +0xF9AC U+88A0 # [2000] +0xF9AD U+88BC # [2000] +0xF9AE U+88BD # [2000] +0xF9AF U+88BE # [2000] +0xF9B0 U+88C0 # [2000] +0xF9B1 U+88D2 # [2000] +0xF9B2 U+27693 # [2000] [Unicode3.1] +0xF9B3 U+88D1 # [2000] +0xF9B4 U+88D3 # [2000] +0xF9B5 U+88DB # [2000] +0xF9B6 U+88F0 # [2000] +0xF9B7 U+88F1 # [2000] +0xF9B8 U+4641 # [2000] +0xF9B9 U+8901 # [2000] +0xF9BA U+2770E # [2000] [Unicode3.1] +0xF9BB U+8937 # [2000] +0xF9BC U+27723 # [2000] [Unicode3.1] +0xF9BD U+8942 # [2000] +0xF9BE U+8945 # [2000] +0xF9BF U+8949 # [2000] +0xF9C0 U+27752 # [2000] [Unicode3.1] +0xF9C1 U+4665 # [2000] +0xF9C2 U+8962 # [2000] +0xF9C3 U+8980 # [2000] +0xF9C4 U+8989 # [2000] +0xF9C5 U+8990 # [2000] +0xF9C6 U+899F # [2000] +0xF9C7 U+89B0 # [2000] +0xF9C8 U+89B7 # [2000] +0xF9C9 U+89D6 # [2000] +0xF9CA U+89D8 # [2000] +0xF9CB U+89EB # [2000] +0xF9CC U+46A1 # [2000] +0xF9CD U+89F1 # [2000] +0xF9CE U+89F3 # [2000] +0xF9CF U+89FD # [2000] +0xF9D0 U+89FF # [2000] +0xF9D1 U+46AF # [2000] +0xF9D2 U+8A11 # [2000] +0xF9D3 U+8A14 # [2000] +0xF9D4 U+27985 # [2000] [Unicode3.1] +0xF9D5 U+8A21 # [2000] +0xF9D6 U+8A35 # [2000] +0xF9D7 U+8A3E # [2000] +0xF9D8 U+8A45 # [2000] +0xF9D9 U+8A4D # [2000] +0xF9DA U+8A58 # [2000] +0xF9DB U+8AAE # [2000] +0xF9DC U+8A90 # [2000] +0xF9DD U+8AB7 # [2000] +0xF9DE U+8ABE # [2000] +0xF9DF U+8AD7 # [2000] +0xF9E0 U+8AFC # [2000] +0xF9E1 U+27A84 # [2000] [Unicode3.1] +0xF9E2 U+8B0A # [2000] +0xF9E3 U+8B05 # [2000] +0xF9E4 U+8B0D # [2000] +0xF9E5 U+8B1C # [2000] +0xF9E6 U+8B1F # [2000] +0xF9E7 U+8B2D # [2000] +0xF9E8 U+8B43 # [2000] +0xF9E9 U+470C # [2000] +0xF9EA U+8B51 # [2000] +0xF9EB U+8B5E # [2000] +0xF9EC U+8B76 # [2000] +0xF9ED U+8B7F # [2000] +0xF9EE U+8B81 # [2000] +0xF9EF U+8B8B # [2000] +0xF9F0 U+8B94 # [2000] +0xF9F1 U+8B95 # [2000] +0xF9F2 U+8B9C # [2000] +0xF9F3 U+8B9E # [2000] +0xF9F4 U+8C39 # [2000] +0xF9F5 U+27BB3 # [2000] [Unicode3.1] +0xF9F6 U+8C3D # [2000] +0xF9F7 U+27BBE # [2000] [Unicode3.1] +0xF9F8 U+27BC7 # [2000] [Unicode3.1] +0xF9F9 U+8C45 # [2000] +0xF9FA U+8C47 # [2000] +0xF9FB U+8C4F # [2000] +0xF9FC U+8C54 # [2000] +0xFA40 U+8C57 # [2000] +0xFA41 U+8C69 # [2000] +0xFA42 U+8C6D # [2000] +0xFA43 U+8C73 # [2000] +0xFA44 U+27CB8 # [2000] [Unicode3.1] +0xFA45 U+8C93 # [2000] +0xFA46 U+8C92 # [2000] +0xFA47 U+8C99 # [2000] +0xFA48 U+4764 # [2000] +0xFA49 U+8C9B # [2000] +0xFA4A U+8CA4 # [2000] +0xFA4B U+8CD6 # [2000] +0xFA4C U+8CD5 # [2000] +0xFA4D U+8CD9 # [2000] +0xFA4E U+27DA0 # [2000] [Unicode3.1] +0xFA4F U+8CF0 # [2000] +0xFA50 U+8CF1 # [2000] +0xFA51 U+27E10 # [2000] [Unicode3.1] +0xFA52 U+8D09 # [2000] +0xFA53 U+8D0E # [2000] +0xFA54 U+8D6C # [2000] +0xFA55 U+8D84 # [2000] +0xFA56 U+8D95 # [2000] +0xFA57 U+8DA6 # [2000] +0xFA58 U+27FB7 # [2000] [Unicode3.1] +0xFA59 U+8DC6 # [2000] +0xFA5A U+8DC8 # [2000] +0xFA5B U+8DD9 # [2000] +0xFA5C U+8DEC # [2000] +0xFA5D U+8E0C # [2000] +0xFA5E U+47FD # [2000] +0xFA5F U+8DFD # [2000] +0xFA60 U+8E06 # [2000] +0xFA61 U+2808A # [2000] [Unicode3.1] +0xFA62 U+8E14 # [2000] +0xFA63 U+8E16 # [2000] +0xFA64 U+8E21 # [2000] +0xFA65 U+8E22 # [2000] +0xFA66 U+8E27 # [2000] +0xFA67 U+280BB # [2000] [Unicode3.1] +0xFA68 U+4816 # [2000] +0xFA69 U+8E36 # [2000] +0xFA6A U+8E39 # [2000] +0xFA6B U+8E4B # [2000] +0xFA6C U+8E54 # [2000] +0xFA6D U+8E62 # [2000] +0xFA6E U+8E6C # [2000] +0xFA6F U+8E6D # [2000] +0xFA70 U+8E6F # [2000] +0xFA71 U+8E98 # [2000] +0xFA72 U+8E9E # [2000] +0xFA73 U+8EAE # [2000] +0xFA74 U+8EB3 # [2000] +0xFA75 U+8EB5 # [2000] +0xFA76 U+8EB6 # [2000] +0xFA77 U+8EBB # [2000] +0xFA78 U+28282 # [2000] [Unicode3.1] +0xFA79 U+8ED1 # [2000] +0xFA7A U+8ED4 # [2000] +0xFA7B U+484E # [2000] +0xFA7C U+8EF9 # [2000] +0xFA7D U+282F3 # [2000] [Unicode3.1] +0xFA7E U+8F00 # [2000] +0xFA80 U+8F08 # [2000] +0xFA81 U+8F17 # [2000] +0xFA82 U+8F2B # [2000] +0xFA83 U+8F40 # [2000] +0xFA84 U+8F4A # [2000] +0xFA85 U+8F58 # [2000] +0xFA86 U+2840C # [2000] [Unicode3.1] +0xFA87 U+8FA4 # [2000] +0xFA88 U+8FB4 # [2000] +0xFA89 U+FA66 # CJK COMPATIBILITY IDEOGRAPH-FA66 [2000] [Unicode3.2] +0xFA8A U+8FB6 # [2000] +0xFA8B U+28455 # [2000] [Unicode3.1] +0xFA8C U+8FC1 # [2000] +0xFA8D U+8FC6 # [2000] +0xFA8E U+FA24 # CJK COMPATIBILITY IDEOGRAPH-FA24 [2000] +0xFA8F U+8FCA # [2000] +0xFA90 U+8FCD # [2000] +0xFA91 U+8FD3 # [2000] +0xFA92 U+8FD5 # [2000] +0xFA93 U+8FE0 # [2000] +0xFA94 U+8FF1 # [2000] +0xFA95 U+8FF5 # [2000] +0xFA96 U+8FFB # [2000] +0xFA97 U+9002 # [2000] +0xFA98 U+900C # [2000] +0xFA99 U+9037 # [2000] +0xFA9A U+2856B # [2000] [Unicode3.1] +0xFA9B U+9043 # [2000] +0xFA9C U+9044 # [2000] +0xFA9D U+905D # [2000] +0xFA9E U+285C8 # [2000] [Unicode3.1] +0xFA9F U+285C9 # [2000] [Unicode3.1] +0xFAA0 U+9085 # [2000] +0xFAA1 U+908C # [2000] +0xFAA2 U+9090 # [2000] +0xFAA3 U+961D # [2000] +0xFAA4 U+90A1 # [2000] +0xFAA5 U+48B5 # [2000] +0xFAA6 U+90B0 # [2000] +0xFAA7 U+90B6 # [2000] +0xFAA8 U+90C3 # [2000] +0xFAA9 U+90C8 # [2000] +0xFAAA U+286D7 # [2000] [Unicode3.1] +0xFAAB U+90DC # [2000] +0xFAAC U+90DF # [2000] +0xFAAD U+286FA # [2000] [Unicode3.1] +0xFAAE U+90F6 # [2000] +0xFAAF U+90F2 # [2000] +0xFAB0 U+9100 # [2000] +0xFAB1 U+90EB # [2000] +0xFAB2 U+90FE # [2000] +0xFAB3 U+90FF # [2000] +0xFAB4 U+9104 # [2000] +0xFAB5 U+9106 # [2000] +0xFAB6 U+9118 # [2000] +0xFAB7 U+911C # [2000] +0xFAB8 U+911E # [2000] +0xFAB9 U+9137 # [2000] +0xFABA U+9139 # [2000] +0xFABB U+913A # [2000] +0xFABC U+9146 # [2000] +0xFABD U+9147 # [2000] +0xFABE U+9157 # [2000] +0xFABF U+9159 # [2000] +0xFAC0 U+9161 # [2000] +0xFAC1 U+9164 # [2000] +0xFAC2 U+9174 # [2000] +0xFAC3 U+9179 # [2000] +0xFAC4 U+9185 # [2000] +0xFAC5 U+918E # [2000] +0xFAC6 U+91A8 # [2000] +0xFAC7 U+91AE # [2000] +0xFAC8 U+91B3 # [2000] +0xFAC9 U+91B6 # [2000] +0xFACA U+91C3 # [2000] +0xFACB U+91C4 # [2000] +0xFACC U+91DA # [2000] +0xFACD U+28949 # [2000] [Unicode3.1] +0xFACE U+28946 # [2000] [Unicode3.1] +0xFACF U+91EC # [2000] +0xFAD0 U+91EE # [2000] +0xFAD1 U+9201 # [2000] +0xFAD2 U+920A # [2000] +0xFAD3 U+9216 # [2000] +0xFAD4 U+9217 # [2000] +0xFAD5 U+2896B # [2000] [Unicode3.1] +0xFAD6 U+9233 # [2000] +0xFAD7 U+9242 # [2000] +0xFAD8 U+9247 # [2000] +0xFAD9 U+924A # [2000] +0xFADA U+924E # [2000] +0xFADB U+9251 # [2000] +0xFADC U+9256 # [2000] +0xFADD U+9259 # [2000] +0xFADE U+9260 # [2000] +0xFADF U+9261 # [2000] +0xFAE0 U+9265 # [2000] +0xFAE1 U+9267 # [2000] +0xFAE2 U+9268 # [2000] +0xFAE3 U+28987 # [2000] [Unicode3.1] +0xFAE4 U+28988 # [2000] [Unicode3.1] +0xFAE5 U+927C # [2000] +0xFAE6 U+927D # [2000] +0xFAE7 U+927F # [2000] +0xFAE8 U+9289 # [2000] +0xFAE9 U+928D # [2000] +0xFAEA U+9297 # [2000] +0xFAEB U+9299 # [2000] +0xFAEC U+929F # [2000] +0xFAED U+92A7 # [2000] +0xFAEE U+92AB # [2000] +0xFAEF U+289BA # [2000] [Unicode3.1] +0xFAF0 U+289BB # [2000] [Unicode3.1] +0xFAF1 U+92B2 # [2000] +0xFAF2 U+92BF # [2000] +0xFAF3 U+92C0 # [2000] +0xFAF4 U+92C6 # [2000] +0xFAF5 U+92CE # [2000] +0xFAF6 U+92D0 # [2000] +0xFAF7 U+92D7 # [2000] +0xFAF8 U+92D9 # [2000] +0xFAF9 U+92E5 # [2000] +0xFAFA U+92E7 # [2000] +0xFAFB U+9311 # [2000] +0xFAFC U+28A1E # [2000] [Unicode3.1] +0xFB40 U+28A29 # [2000] [Unicode3.1] +0xFB41 U+92F7 # [2000] +0xFB42 U+92F9 # [2000] +0xFB43 U+92FB # [2000] +0xFB44 U+9302 # [2000] +0xFB45 U+930D # [2000] +0xFB46 U+9315 # [2000] +0xFB47 U+931D # [2000] +0xFB48 U+931E # [2000] +0xFB49 U+9327 # [2000] +0xFB4A U+9329 # [2000] +0xFB4B U+28A71 # [2000] [Unicode3.1] +0xFB4C U+28A43 # [2000] [Unicode3.1] +0xFB4D U+9347 # [2000] +0xFB4E U+9351 # [2000] +0xFB4F U+9357 # [2000] +0xFB50 U+935A # [2000] +0xFB51 U+936B # [2000] +0xFB52 U+9371 # [2000] +0xFB53 U+9373 # [2000] +0xFB54 U+93A1 # [2000] +0xFB55 U+28A99 # [2000] [Unicode3.1] +0xFB56 U+28ACD # [2000] [Unicode3.1] +0xFB57 U+9388 # [2000] +0xFB58 U+938B # [2000] +0xFB59 U+938F # [2000] +0xFB5A U+939E # [2000] +0xFB5B U+93F5 # [2000] +0xFB5C U+28AE4 # [2000] [Unicode3.1] +0xFB5D U+28ADD # [2000] [Unicode3.1] +0xFB5E U+93F1 # [2000] +0xFB5F U+93C1 # [2000] +0xFB60 U+93C7 # [2000] +0xFB61 U+93DC # [2000] +0xFB62 U+93E2 # [2000] +0xFB63 U+93E7 # [2000] +0xFB64 U+9409 # [2000] +0xFB65 U+940F # [2000] +0xFB66 U+9416 # [2000] +0xFB67 U+9417 # [2000] +0xFB68 U+93FB # [2000] +0xFB69 U+9432 # [2000] +0xFB6A U+9434 # [2000] +0xFB6B U+943B # [2000] +0xFB6C U+9445 # [2000] +0xFB6D U+28BC1 # [2000] [Unicode3.1] +0xFB6E U+28BEF # [2000] [Unicode3.1] +0xFB6F U+946D # [2000] +0xFB70 U+946F # [2000] +0xFB71 U+9578 # [2000] +0xFB72 U+9579 # [2000] +0xFB73 U+9586 # [2000] +0xFB74 U+958C # [2000] +0xFB75 U+958D # [2000] +0xFB76 U+28D10 # [2000] [Unicode3.1] +0xFB77 U+95AB # [2000] +0xFB78 U+95B4 # [2000] +0xFB79 U+28D71 # [2000] [Unicode3.1] +0xFB7A U+95C8 # [2000] +0xFB7B U+28DFB # [2000] [Unicode3.1] +0xFB7C U+28E1F # [2000] [Unicode3.1] +0xFB7D U+962C # [2000] +0xFB7E U+9633 # [2000] +0xFB80 U+9634 # [2000] +0xFB81 U+28E36 # [2000] [Unicode3.1] +0xFB82 U+963C # [2000] +0xFB83 U+9641 # [2000] +0xFB84 U+9661 # [2000] +0xFB85 U+28E89 # [2000] [Unicode3.1] +0xFB86 U+9682 # [2000] +0xFB87 U+28EEB # [2000] [Unicode3.1] +0xFB88 U+969A # [2000] +0xFB89 U+28F32 # [2000] [Unicode3.1] +0xFB8A U+49E7 # [2000] +0xFB8B U+96A9 # [2000] +0xFB8C U+96AF # [2000] +0xFB8D U+96B3 # [2000] +0xFB8E U+96BA # [2000] +0xFB8F U+96BD # [2000] +0xFB90 U+49FA # [2000] +0xFB91 U+28FF8 # [2000] [Unicode3.1] +0xFB92 U+96D8 # [2000] +0xFB93 U+96DA # [2000] +0xFB94 U+96DD # [2000] +0xFB95 U+4A04 # [2000] +0xFB96 U+9714 # [2000] +0xFB97 U+9723 # [2000] +0xFB98 U+4A29 # [2000] +0xFB99 U+9736 # [2000] +0xFB9A U+9741 # [2000] +0xFB9B U+9747 # [2000] +0xFB9C U+9755 # [2000] +0xFB9D U+9757 # [2000] +0xFB9E U+975B # [2000] +0xFB9F U+976A # [2000] +0xFBA0 U+292A0 # [2000] [Unicode3.1] +0xFBA1 U+292B1 # [2000] [Unicode3.1] +0xFBA2 U+9796 # [2000] +0xFBA3 U+979A # [2000] +0xFBA4 U+979E # [2000] +0xFBA5 U+97A2 # [2000] +0xFBA6 U+97B1 # [2000] +0xFBA7 U+97B2 # [2000] +0xFBA8 U+97BE # [2000] +0xFBA9 U+97CC # [2000] +0xFBAA U+97D1 # [2000] +0xFBAB U+97D4 # [2000] +0xFBAC U+97D8 # [2000] +0xFBAD U+97D9 # [2000] +0xFBAE U+97E1 # [2000] +0xFBAF U+97F1 # [2000] +0xFBB0 U+9804 # [2000] +0xFBB1 U+980D # [2000] +0xFBB2 U+980E # [2000] +0xFBB3 U+9814 # [2000] +0xFBB4 U+9816 # [2000] +0xFBB5 U+4ABC # [2000] +0xFBB6 U+29490 # [2000] [Unicode3.1] +0xFBB7 U+9823 # [2000] +0xFBB8 U+9832 # [2000] +0xFBB9 U+9833 # [2000] +0xFBBA U+9825 # [2000] +0xFBBB U+9847 # [2000] +0xFBBC U+9866 # [2000] +0xFBBD U+98AB # [2000] +0xFBBE U+98AD # [2000] +0xFBBF U+98B0 # [2000] +0xFBC0 U+295CF # [2000] [Unicode3.1] +0xFBC1 U+98B7 # [2000] +0xFBC2 U+98B8 # [2000] +0xFBC3 U+98BB # [2000] +0xFBC4 U+98BC # [2000] +0xFBC5 U+98BF # [2000] +0xFBC6 U+98C2 # [2000] +0xFBC7 U+98C7 # [2000] +0xFBC8 U+98CB # [2000] +0xFBC9 U+98E0 # [2000] +0xFBCA U+2967F # [2000] [Unicode3.1] +0xFBCB U+98E1 # [2000] +0xFBCC U+98E3 # [2000] +0xFBCD U+98E5 # [2000] +0xFBCE U+98EA # [2000] +0xFBCF U+98F0 # [2000] +0xFBD0 U+98F1 # [2000] +0xFBD1 U+98F3 # [2000] +0xFBD2 U+9908 # [2000] +0xFBD3 U+4B3B # [2000] +0xFBD4 U+296F0 # [2000] [Unicode3.1] +0xFBD5 U+9916 # [2000] +0xFBD6 U+9917 # [2000] +0xFBD7 U+29719 # [2000] [Unicode3.1] +0xFBD8 U+991A # [2000] +0xFBD9 U+991B # [2000] +0xFBDA U+991C # [2000] +0xFBDB U+29750 # [2000] [Unicode3.1] +0xFBDC U+9931 # [2000] +0xFBDD U+9932 # [2000] +0xFBDE U+9933 # [2000] +0xFBDF U+993A # [2000] +0xFBE0 U+993B # [2000] +0xFBE1 U+993C # [2000] +0xFBE2 U+9940 # [2000] +0xFBE3 U+9941 # [2000] +0xFBE4 U+9946 # [2000] +0xFBE5 U+994D # [2000] +0xFBE6 U+994E # [2000] +0xFBE7 U+995C # [2000] +0xFBE8 U+995F # [2000] +0xFBE9 U+9960 # [2000] +0xFBEA U+99A3 # [2000] +0xFBEB U+99A6 # [2000] +0xFBEC U+99B9 # [2000] +0xFBED U+99BD # [2000] +0xFBEE U+99BF # [2000] +0xFBEF U+99C3 # [2000] +0xFBF0 U+99C9 # [2000] +0xFBF1 U+99D4 # [2000] +0xFBF2 U+99D9 # [2000] +0xFBF3 U+99DE # [2000] +0xFBF4 U+298C6 # [2000] [Unicode3.1] +0xFBF5 U+99F0 # [2000] +0xFBF6 U+99F9 # [2000] +0xFBF7 U+99FC # [2000] +0xFBF8 U+9A0A # [2000] +0xFBF9 U+9A11 # [2000] +0xFBFA U+9A16 # [2000] +0xFBFB U+9A1A # [2000] +0xFBFC U+9A20 # [2000] +0xFC40 U+9A31 # [2000] +0xFC41 U+9A36 # [2000] +0xFC42 U+9A44 # [2000] +0xFC43 U+9A4C # [2000] +0xFC44 U+9A58 # [2000] +0xFC45 U+4BC2 # [2000] +0xFC46 U+9AAF # [2000] +0xFC47 U+4BCA # [2000] +0xFC48 U+9AB7 # [2000] +0xFC49 U+4BD2 # [2000] +0xFC4A U+9AB9 # [2000] +0xFC4B U+29A72 # [2000] [Unicode3.1] +0xFC4C U+9AC6 # [2000] +0xFC4D U+9AD0 # [2000] +0xFC4E U+9AD2 # [2000] +0xFC4F U+9AD5 # [2000] +0xFC50 U+4BE8 # [2000] +0xFC51 U+9ADC # [2000] +0xFC52 U+9AE0 # [2000] +0xFC53 U+9AE5 # [2000] +0xFC54 U+9AE9 # [2000] +0xFC55 U+9B03 # [2000] +0xFC56 U+9B0C # [2000] +0xFC57 U+9B10 # [2000] +0xFC58 U+9B12 # [2000] +0xFC59 U+9B16 # [2000] +0xFC5A U+9B1C # [2000] +0xFC5B U+9B2B # [2000] +0xFC5C U+9B33 # [2000] +0xFC5D U+9B3D # [2000] +0xFC5E U+4C20 # [2000] +0xFC5F U+9B4B # [2000] +0xFC60 U+9B63 # [2000] +0xFC61 U+9B65 # [2000] +0xFC62 U+9B6B # [2000] +0xFC63 U+9B6C # [2000] +0xFC64 U+9B73 # [2000] +0xFC65 U+9B76 # [2000] +0xFC66 U+9B77 # [2000] +0xFC67 U+9BA6 # [2000] +0xFC68 U+9BAC # [2000] +0xFC69 U+9BB1 # [2000] +0xFC6A U+29DDB # [2000] [Unicode3.1] +0xFC6B U+29E3D # [2000] [Unicode3.1] +0xFC6C U+9BB2 # [2000] +0xFC6D U+9BB8 # [2000] +0xFC6E U+9BBE # [2000] +0xFC6F U+9BC7 # [2000] +0xFC70 U+9BF3 # [2000] +0xFC71 U+9BD8 # [2000] +0xFC72 U+9BDD # [2000] +0xFC73 U+9BE7 # [2000] +0xFC74 U+9BEA # [2000] +0xFC75 U+9BEB # [2000] +0xFC76 U+9BEF # [2000] +0xFC77 U+9BEE # [2000] +0xFC78 U+29E15 # [2000] [Unicode3.1] +0xFC79 U+9BFA # [2000] +0xFC7A U+29E8A # [2000] [Unicode3.1] +0xFC7B U+9BF7 # [2000] +0xFC7C U+29E49 # [2000] [Unicode3.1] +0xFC7D U+9C16 # [2000] +0xFC7E U+9C18 # [2000] +0xFC80 U+9C19 # [2000] +0xFC81 U+9C1A # [2000] +0xFC82 U+9C1D # [2000] +0xFC83 U+9C22 # [2000] +0xFC84 U+9C27 # [2000] +0xFC85 U+9C29 # [2000] +0xFC86 U+9C2A # [2000] +0xFC87 U+29EC4 # [2000] [Unicode3.1] +0xFC88 U+9C31 # [2000] +0xFC89 U+9C36 # [2000] +0xFC8A U+9C37 # [2000] +0xFC8B U+9C45 # [2000] +0xFC8C U+9C5C # [2000] +0xFC8D U+29EE9 # [2000] [Unicode3.1] +0xFC8E U+9C49 # [2000] +0xFC8F U+9C4A # [2000] +0xFC90 U+29EDB # [2000] [Unicode3.1] +0xFC91 U+9C54 # [2000] +0xFC92 U+9C58 # [2000] +0xFC93 U+9C5B # [2000] +0xFC94 U+9C5D # [2000] +0xFC95 U+9C5F # [2000] +0xFC96 U+9C69 # [2000] +0xFC97 U+9C6A # [2000] +0xFC98 U+9C6B # [2000] +0xFC99 U+9C6D # [2000] +0xFC9A U+9C6E # [2000] +0xFC9B U+9C70 # [2000] +0xFC9C U+9C72 # [2000] +0xFC9D U+9C75 # [2000] +0xFC9E U+9C7A # [2000] +0xFC9F U+9CE6 # [2000] +0xFCA0 U+9CF2 # [2000] +0xFCA1 U+9D0B # [2000] +0xFCA2 U+9D02 # [2000] +0xFCA3 U+29FCE # [2000] [Unicode3.1] +0xFCA4 U+9D11 # [2000] +0xFCA5 U+9D17 # [2000] +0xFCA6 U+9D18 # [2000] +0xFCA7 U+2A02F # [2000] [Unicode3.1] +0xFCA8 U+4CC4 # [2000] +0xFCA9 U+2A01A # [2000] [Unicode3.1] +0xFCAA U+9D32 # [2000] +0xFCAB U+4CD1 # [2000] +0xFCAC U+9D42 # [2000] +0xFCAD U+9D4A # [2000] +0xFCAE U+9D5F # [2000] +0xFCAF U+9D62 # [2000] +0xFCB0 U+2A0F9 # [2000] [Unicode3.1] +0xFCB1 U+9D69 # [2000] +0xFCB2 U+9D6B # [2000] +0xFCB3 U+2A082 # [2000] [Unicode3.1] +0xFCB4 U+9D73 # [2000] +0xFCB5 U+9D76 # [2000] +0xFCB6 U+9D77 # [2000] +0xFCB7 U+9D7E # [2000] +0xFCB8 U+9D84 # [2000] +0xFCB9 U+9D8D # [2000] +0xFCBA U+9D99 # [2000] +0xFCBB U+9DA1 # [2000] +0xFCBC U+9DBF # [2000] +0xFCBD U+9DB5 # [2000] +0xFCBE U+9DB9 # [2000] +0xFCBF U+9DBD # [2000] +0xFCC0 U+9DC3 # [2000] +0xFCC1 U+9DC7 # [2000] +0xFCC2 U+9DC9 # [2000] +0xFCC3 U+9DD6 # [2000] +0xFCC4 U+9DDA # [2000] +0xFCC5 U+9DDF # [2000] +0xFCC6 U+9DE0 # [2000] +0xFCC7 U+9DE3 # [2000] +0xFCC8 U+9DF4 # [2000] +0xFCC9 U+4D07 # [2000] +0xFCCA U+9E0A # [2000] +0xFCCB U+9E02 # [2000] +0xFCCC U+9E0D # [2000] +0xFCCD U+9E19 # [2000] +0xFCCE U+9E1C # [2000] +0xFCCF U+9E1D # [2000] +0xFCD0 U+9E7B # [2000] +0xFCD1 U+22218 # [2000] [Unicode3.1] +0xFCD2 U+9E80 # [2000] +0xFCD3 U+9E85 # [2000] +0xFCD4 U+9E9B # [2000] +0xFCD5 U+9EA8 # [2000] +0xFCD6 U+2A38C # [2000] [Unicode3.1] +0xFCD7 U+9EBD # [2000] +0xFCD8 U+2A437 # [2000] [Unicode3.1] +0xFCD9 U+9EDF # [2000] +0xFCDA U+9EE7 # [2000] +0xFCDB U+9EEE # [2000] +0xFCDC U+9EFF # [2000] +0xFCDD U+9F02 # [2000] +0xFCDE U+4D77 # [2000] +0xFCDF U+9F03 # [2000] +0xFCE0 U+9F17 # [2000] +0xFCE1 U+9F19 # [2000] +0xFCE2 U+9F2F # [2000] +0xFCE3 U+9F37 # [2000] +0xFCE4 U+9F3A # [2000] +0xFCE5 U+9F3D # [2000] +0xFCE6 U+9F41 # [2000] +0xFCE7 U+9F45 # [2000] +0xFCE8 U+9F46 # [2000] +0xFCE9 U+9F53 # [2000] +0xFCEA U+9F55 # [2000] +0xFCEB U+9F58 # [2000] +0xFCEC U+2A5F1 # [2000] [Unicode3.1] +0xFCED U+9F5D # [2000] +0xFCEE U+2A602 # [2000] [Unicode3.1] +0xFCEF U+9F69 # [2000] +0xFCF0 U+2A61A # [2000] [Unicode3.1] +0xFCF1 U+9F6D # [2000] +0xFCF2 U+9F70 # [2000] +0xFCF3 U+9F75 # [2000] +0xFCF4 U+2A6B2 # [2000] [Unicode3.1] diff --git a/jdk/make/tools/Makefile b/jdk/make/tools/Makefile index 3bc1cacd0ff..be1c59a7cfa 100644 --- a/jdk/make/tools/Makefile +++ b/jdk/make/tools/Makefile @@ -51,7 +51,8 @@ SUBDIRS = \ jdwpgen \ makeclasslist \ strip_properties \ - winver + winver \ + CharsetMapping all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/tools/src/build/tools/charsetmapping/CharsetMapping.java b/jdk/make/tools/src/build/tools/charsetmapping/CharsetMapping.java new file mode 100644 index 00000000000..9637449e09a --- /dev/null +++ b/jdk/make/tools/src/build/tools/charsetmapping/CharsetMapping.java @@ -0,0 +1,271 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package build.tools.charsetmapping; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.BufferedReader; +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.*; + +public class CharsetMapping { + public final static char UNMAPPABLE_DECODING = '\uFFFD'; + public final static int UNMAPPABLE_ENCODING = -1; + + public static class Entry { + public int bs; //byte sequence reps + public int cp; //Unicode codepoint + public int cp2; //CC of composite + + public Entry () {} + public Entry (int bytes, int cp, int cp2) { + this.bs = bytes; + this.cp = cp; + this.cp2 = cp2; + } + } + + static Comparator comparatorCP = + new Comparator() { + public int compare(Entry m1, Entry m2) { + return m1.cp - m2.cp; + } + public boolean equals(Object obj) { + return this == obj; + } + }; + + public static class Parser { + static final Pattern basic = Pattern.compile("(?:0x)?(\\p{XDigit}++)\\s++(?:0x)?(\\p{XDigit}++)?\\s*+.*"); + static final int gBS = 1; + static final int gCP = 2; + static final int gCP2 = 3; + + BufferedReader reader; + boolean closed; + Matcher matcher; + int gbs, gcp, gcp2; + + public Parser (InputStream in, Pattern p, int gbs, int gcp, int gcp2) + throws IOException + { + this.reader = new BufferedReader(new InputStreamReader(in)); + this.closed = false; + this.matcher = p.matcher(""); + this.gbs = gbs; + this.gcp = gcp; + this.gcp2 = gcp2; + } + + public Parser (InputStream in, Pattern p) throws IOException { + this(in, p, gBS, gCP, gCP2); + } + + public Parser (InputStream in) throws IOException { + this(in, basic, gBS, gCP, gCP2); + } + + protected boolean isDirective(String line) { + return line.startsWith("#"); + } + + protected Entry parse(Matcher matcher, Entry mapping) { + mapping.bs = Integer.parseInt(matcher.group(gbs), 16); + mapping.cp = Integer.parseInt(matcher.group(gcp), 16); + if (gcp2 <= matcher.groupCount() && + matcher.group(gcp2) != null) + mapping.cp2 = Integer.parseInt(matcher.group(gcp2), 16); + else + mapping.cp2 = 0; + return mapping; + } + + public Entry next() throws Exception { + return next(new Entry()); + } + + // returns null and closes the input stream if the eof has beenreached. + public Entry next(Entry mapping) throws Exception { + if (closed) + return null; + String line; + while ((line = reader.readLine()) != null) { + if (isDirective(line)) + continue; + matcher.reset(line); + if (!matcher.lookingAt()) { + //System.out.println("Missed: " + line); + continue; + } + return parse(matcher, mapping); + } + reader.close(); + closed = true; + return null; + } + } + + // tags of different charset mapping tables + private final static int MAP_SINGLEBYTE = 0x1; // 0..256 : c + private final static int MAP_DOUBLEBYTE1 = 0x2; // min..max: c + private final static int MAP_DOUBLEBYTE2 = 0x3; // min..max: c [DB2] + private final static int MAP_SUPPLEMENT = 0x5; // db,c + private final static int MAP_SUPPLEMENT_C2B = 0x6; // c,db + private final static int MAP_COMPOSITE = 0x7; // db,base,cc + private final static int MAP_INDEXC2B = 0x8; // index table of c->bb + + private static final void writeShort(OutputStream out, int data) + throws IOException + { + out.write((data >>> 8) & 0xFF); + out.write((data ) & 0xFF); + } + + private static final void writeShortArray(OutputStream out, + int type, + int[] array, + int off, + int size) // exclusive + throws IOException + { + writeShort(out, type); + writeShort(out, size); + for (int i = off; i < size; i++) { + writeShort(out, array[off+i]); + } + } + + public static final void writeSIZE(OutputStream out, int data) + throws IOException + { + out.write((data >>> 24) & 0xFF); + out.write((data >>> 16) & 0xFF); + out.write((data >>> 8) & 0xFF); + out.write((data ) & 0xFF); + } + + public static void writeINDEXC2B(OutputStream out, int[] indexC2B) + throws IOException + { + writeShort(out, MAP_INDEXC2B); + writeShort(out, indexC2B.length); + int off = 0; + for (int i = 0; i < indexC2B.length; i++) { + if (indexC2B[i] != 0) { + writeShort(out, off); + off += 256; + } else { + writeShort(out, -1); + } + } + } + + public static void writeSINGLEBYTE(OutputStream out, int[] sb) + throws IOException + { + writeShortArray(out, MAP_SINGLEBYTE, sb, 0, 256); + } + + private static void writeDOUBLEBYTE(OutputStream out, + int type, + int[] db, + int b1Min, int b1Max, + int b2Min, int b2Max) + throws IOException + { + writeShort(out, type); + writeShort(out, b1Min); + writeShort(out, b1Max); + writeShort(out, b2Min); + writeShort(out, b2Max); + writeShort(out, (b1Max - b1Min + 1) * (b2Max - b2Min + 1)); + + for (int b1 = b1Min; b1 <= b1Max; b1++) { + for (int b2 = b2Min; b2 <= b2Max; b2++) { + writeShort(out, db[b1 * 256 + b2]); + } + } + } + public static void writeDOUBLEBYTE1(OutputStream out, + int[] db, + int b1Min, int b1Max, + int b2Min, int b2Max) + throws IOException + { + writeDOUBLEBYTE(out, MAP_DOUBLEBYTE1, db, b1Min, b1Max, b2Min, b2Max); + } + + public static void writeDOUBLEBYTE2(OutputStream out, + int[] db, + int b1Min, int b1Max, + int b2Min, int b2Max) + throws IOException + { + writeDOUBLEBYTE(out, MAP_DOUBLEBYTE2, db, b1Min, b1Max, b2Min, b2Max); + } + + // the c2b table is output as well + public static void writeSUPPLEMENT(OutputStream out, Entry[] supp, int size) + throws IOException + { + writeShort(out, MAP_SUPPLEMENT); + writeShort(out, size * 2); + // db at first half, cc at the low half + for (int i = 0; i < size; i++) { + writeShort(out, supp[i].bs); + } + for (int i = 0; i < size; i++) { + writeShort(out, supp[i].cp); + } + + //c2b + writeShort(out, MAP_SUPPLEMENT_C2B); + writeShort(out, size*2); + Arrays.sort(supp, 0, size, comparatorCP); + for (int i = 0; i < size; i++) { + writeShort(out, supp[i].cp); + } + for (int i = 0; i < size; i++) { + writeShort(out, supp[i].bs); + } + } + + public static void writeCOMPOSITE(OutputStream out, Entry[] comp, int size) + throws IOException + { + writeShort(out, MAP_COMPOSITE); + writeShort(out, size*3); + // comp is sorted already + for (int i = 0; i < size; i++) { + writeShort(out, (char)comp[i].bs); + writeShort(out, (char)comp[i].cp); + writeShort(out, (char)comp[i].cp2); + } + } +} diff --git a/jdk/make/tools/src/build/tools/charsetmapping/GenerateMapping.java b/jdk/make/tools/src/build/tools/charsetmapping/GenerateMapping.java new file mode 100644 index 00000000000..e1f1d86ab79 --- /dev/null +++ b/jdk/make/tools/src/build/tools/charsetmapping/GenerateMapping.java @@ -0,0 +1,98 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package build.tools.charsetmapping; + +import java.io.*; +import java.util.regex.*; +import static build.tools.charsetmapping.CharsetMapping.*; + +public class GenerateMapping { + public static void main(String argv[]) throws IOException { + if (argv.length < 2) { + System.out.println("Usage: java GenCSData fMap fDat"); + System.exit(1); + } + genDataJIS0213(new FileInputStream(argv[0]), + new FileOutputStream(argv[1])); + } + + // regex pattern to parse the "jis0213.map" file + static Pattern sjis0213 = Pattern.compile("0x(\\p{XDigit}++)\\s++U\\+(\\p{XDigit}++)(?:\\+(\\p{XDigit}++))?\\s++#.*"); + private static void genDataJIS0213(InputStream in, OutputStream out) + { + int[] sb = new int[0x100]; // singlebyte + int[] db = new int[0x10000]; // doublebyte + int[] indexC2B = new int[256]; + Entry[] supp = new Entry[0x10000]; + Entry[] comp = new Entry[0x100]; + int suppTotal = 0; + int compTotal = 0; + + int b1Min1 = 0x81; + int b1Max1 = 0x9f; + int b1Min2 = 0xe0; + int b1Max2 = 0xfc; + int b2Min = 0x40; + int b2Max = 0xfe; + + //init + for (int i = 0; i < 0x80; i++) sb[i] = i; + for (int i = 0x80; i < 0x100; i++) sb[i] = UNMAPPABLE_DECODING; + for (int i = 0; i < 0x10000; i++) db[i] = UNMAPPABLE_DECODING; + try { + Parser p = new Parser(in, sjis0213); + Entry e = null; + while ((e = p.next()) != null) { + if (e.cp2 != 0) { + comp[compTotal++] = e; + } else { + if (e.cp <= 0xffff) { + if (e.bs <= 0xff) + sb[e.bs] = e.cp; + else + db[e.bs] = e.cp; + indexC2B[e.cp>>8] = 1; + } else { + supp[suppTotal++] = e; + } + } + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + // c2b Index Table, always the first one + writeINDEXC2B(baos, indexC2B); + writeSINGLEBYTE(baos, sb); + writeDOUBLEBYTE1(baos, db, b1Min1, b1Max1, b2Min, b2Max); + writeDOUBLEBYTE2(baos, db, b1Min2, b1Max2, b2Min, b2Max); + writeSUPPLEMENT(baos, supp, suppTotal); + writeCOMPOSITE(baos, comp, compTotal); + writeSIZE(out, baos.size()); + baos.writeTo(out); + out.close(); + } catch (Exception x) { + x.printStackTrace(); + } + } +} diff --git a/jdk/src/share/bin/emessages.h b/jdk/src/share/bin/emessages.h index f11c396ad60..03824bba5d1 100644 --- a/jdk/src/share/bin/emessages.h +++ b/jdk/src/share/bin/emessages.h @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ #define JAR_ERROR2 "Error: Unable to access jarfile %s" #define JAR_ERROR3 "Error: Invalid or corrupt jarfile %s" -#define CLS_ERROR1 "Error: Could not find the main class.\n" JNI_ERROR +#define CLS_ERROR1 "Error: Could not find the main class %s.\n" JNI_ERROR #define CLS_ERROR2 "Error: Failed to load Main Class: %s\n%s" #define CLS_ERROR3 "Error: No main method found in specified class.\n" GEN_ERROR #define CLS_ERROR4 "Error: Main method not public\n" GEN_ERROR diff --git a/jdk/src/share/bin/java.c b/jdk/src/share/bin/java.c index 47c2fc17cd0..f7cbcdc95bc 100644 --- a/jdk/src/share/bin/java.c +++ b/jdk/src/share/bin/java.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -414,7 +414,7 @@ JavaMain(void * _args) mainClass = LoadClass(env, classname); if(mainClass == NULL) { /* exception occured */ ReportExceptionDescription(env); - ReportErrorMessage(CLS_ERROR1); + ReportErrorMessage(CLS_ERROR1, classname); goto leave; } (*env)->ReleaseStringUTFChars(env, mainClassName, classname); @@ -433,7 +433,7 @@ JavaMain(void * _args) mainClass = LoadClass(env, classname); if(mainClass == NULL) { /* exception occured */ ReportExceptionDescription(env); - ReportErrorMessage(CLS_ERROR1); + ReportErrorMessage(CLS_ERROR1, classname); goto leave; } (*env)->ReleaseStringUTFChars(env, mainClassName, classname); diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java index b41450257a0..ae2bcb56a20 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReader.java @@ -504,7 +504,7 @@ public class GIFImageReader extends ImageReader { } // Found position of metadata for image 0 - imageStartPosition.add(new Long(stream.getStreamPosition())); + imageStartPosition.add(Long.valueOf(stream.getStreamPosition())); } catch (IOException e) { throw new IIOException("I/O error reading header!", e); } diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java index 66d647f6856..58d819f11ea 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFWritableImageMetadata.java @@ -98,7 +98,7 @@ class GIFWritableImageMetadata extends GIFImageMetadata { try { return data.getBytes("ISO-8859-1"); } catch (UnsupportedEncodingException e) { - return (new String("")).getBytes(); + return "".getBytes(); } } diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKColorChooserPanel.java b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKColorChooserPanel.java index f5b671e7cd4..ba1c8da7958 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKColorChooserPanel.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKColorChooserPanel.java @@ -328,7 +328,7 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements setHSB(hue, saturation, brightness); if (update) { settingColor = true; - hueSpinner.setValue(new Integer((int)(hue * 360))); + hueSpinner.setValue(Integer.valueOf((int)(hue * 360))); settingColor = false; } } @@ -376,8 +376,8 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements setHSB(hue, s, b); if (update) { settingColor = true; - saturationSpinner.setValue(new Integer((int)(s * 255))); - valueSpinner.setValue(new Integer((int)(b * 255))); + saturationSpinner.setValue(Integer.valueOf((int)(s * 255))); + valueSpinner.setValue(Integer.valueOf((int)(b * 255))); settingColor = false; } } @@ -391,9 +391,9 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements setColor(color, false, true, true); settingColor = true; - hueSpinner.setValue(new Integer((int)(hue * 360))); - saturationSpinner.setValue(new Integer((int)(saturation * 255))); - valueSpinner.setValue(new Integer((int)(brightness * 255))); + hueSpinner.setValue(Integer.valueOf((int)(hue * 360))); + saturationSpinner.setValue(Integer.valueOf((int)(saturation * 255))); + valueSpinner.setValue(Integer.valueOf((int)(brightness * 255))); settingColor = false; } @@ -409,9 +409,9 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements setColor(color, false, false, true); settingColor = true; - redSpinner.setValue(new Integer(color.getRed())); - greenSpinner.setValue(new Integer(color.getGreen())); - blueSpinner.setValue(new Integer(color.getBlue())); + redSpinner.setValue(Integer.valueOf(color.getRed())); + greenSpinner.setValue(Integer.valueOf(color.getGreen())); + blueSpinner.setValue(Integer.valueOf(color.getBlue())); settingColor = false; } @@ -454,13 +454,13 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements colorNameTF.setText("#" + hexString.substring(1)); if (updateSpinners) { - redSpinner.setValue(new Integer(color.getRed())); - greenSpinner.setValue(new Integer(color.getGreen())); - blueSpinner.setValue(new Integer(color.getBlue())); + redSpinner.setValue(Integer.valueOf(color.getRed())); + greenSpinner.setValue(Integer.valueOf(color.getGreen())); + blueSpinner.setValue(Integer.valueOf(color.getBlue())); - hueSpinner.setValue(new Integer((int)(hue * 360))); - saturationSpinner.setValue(new Integer((int)(saturation * 255))); - valueSpinner.setValue(new Integer((int)(brightness * 255))); + hueSpinner.setValue(Integer.valueOf((int)(hue * 360))); + saturationSpinner.setValue(Integer.valueOf((int)(saturation * 255))); + valueSpinner.setValue(Integer.valueOf((int)(brightness * 255))); } settingColor = false; } diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java index d338c08d6fd..a640862c50c 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java @@ -97,14 +97,11 @@ class GTKFileChooserUI extends SynthFileChooserUI { private static final Dimension hstrut3 = new Dimension(3, 1); private static final Dimension vstrut10 = new Dimension(1, 10); - private static final Insets insets = new Insets(10, 10, 10, 10); - private static Dimension prefListSize = new Dimension(75, 150); private static Dimension PREF_SIZE = new Dimension(435, 360); private static Dimension MIN_SIZE = new Dimension(200, 300); - private static Dimension PREF_ACC_SIZE = new Dimension(10, 10); private static Dimension ZERO_ACC_SIZE = new Dimension(1, 1); private static Dimension MAX_SIZE = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); @@ -125,7 +122,6 @@ class GTKFileChooserUI extends SynthFileChooserUI { private JPanel bottomButtonPanel; private GTKDirectoryModel model = null; private Action newFolderAction; - private JPanel interior; private boolean readOnly; private boolean showDirectoryIcons; private boolean showFileIcons; @@ -710,15 +706,19 @@ class GTKFileChooserUI extends SynthFileChooserUI { bottomButtonPanel.setName("GTKFileChooser.bottomButtonPanel"); align(bottomButtonPanel); + JPanel pnButtons = new JPanel(new GridLayout(1, 2, 5, 0)); + JButton cancelButton = getCancelButton(fc); align(cancelButton); cancelButton.setMargin(buttonMargin); - bottomButtonPanel.add(cancelButton); + pnButtons.add(cancelButton); - JButton approveButton = getApproveButton(fc);; + JButton approveButton = getApproveButton(fc); align(approveButton); approveButton.setMargin(buttonMargin); - bottomButtonPanel.add(approveButton); + pnButtons.add(approveButton); + + bottomButtonPanel.add(pnButtons); if (fc.getControlButtonsAreShown()) { fc.add(bottomButtonPanel, BorderLayout.SOUTH); @@ -1108,7 +1108,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { // Get the canonical (full) path. This has the side // benefit of removing extraneous chars from the path, // for example /foo/bar/ becomes /foo/bar - File canonical = null; + File canonical; try { canonical = fsv.createFileObject(ShellFolder.getNormalizedFile(directory).getPath()); } catch (IOException e) { diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java index b4f435798a1..7fd7bde45a6 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java @@ -336,7 +336,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { // populate the table with the values from basic. super.initComponentDefaults(table); - Integer zero = new Integer(0); + Integer zero = Integer.valueOf(0); Object zeroBorder = new sun.swing.SwingLazyValue( "javax.swing.plaf.BorderUIResource$EmptyBorderUIResource", new Object[] {zero, zero, zero, zero}); @@ -371,7 +371,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { int vProgWidth = 22 - (progXThickness * 2); int vProgHeight = 80 - (progYThickness * 2); - Integer caretBlinkRate = new Integer(500); + Integer caretBlinkRate = Integer.valueOf(500); Insets zeroInsets = new InsetsUIResource(0, 0, 0, 0); Double defaultCaretAspectRatio = new Double(0.025); @@ -540,7 +540,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { } Object[] defaults = new Object[] { - "ArrowButton.size", new Integer(13), + "ArrowButton.size", Integer.valueOf(13), "Button.defaultButtonFollowsFocus", Boolean.FALSE, @@ -893,8 +893,8 @@ public class GTKLookAndFeel extends SynthLookAndFeel { "ScrollBar.squareButtons", Boolean.FALSE, - "ScrollBar.thumbHeight", new Integer(14), - "ScrollBar.width", new Integer(16), + "ScrollBar.thumbHeight", Integer.valueOf(14), + "ScrollBar.width", Integer.valueOf(16), "ScrollBar.minimumThumbSize", new Dimension(8, 8), "ScrollBar.maximumThumbSize", new Dimension(4096, 4096), "ScrollBar.allowsAbsolutePositioning", Boolean.TRUE, @@ -954,12 +954,12 @@ public class GTKLookAndFeel extends SynthLookAndFeel { "Separator.insets", zeroInsets, - "Separator.thickness", new Integer(2), + "Separator.thickness", Integer.valueOf(2), "Slider.paintValue", Boolean.TRUE, - "Slider.thumbWidth", new Integer(30), - "Slider.thumbHeight", new Integer(14), + "Slider.thumbWidth", Integer.valueOf(30), + "Slider.thumbHeight", Integer.valueOf(14), "Slider.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { "RIGHT", "positiveUnitIncrement", @@ -982,7 +982,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { "LEFT", "positiveUnitIncrement", "KP_LEFT", "positiveUnitIncrement", }), - + "Slider.onlyLeftMouseButtonDrag", Boolean.FALSE, "Spinner.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { @@ -1013,9 +1013,9 @@ public class GTKLookAndFeel extends SynthLookAndFeel { }), - "SplitPane.size", new Integer(7), - "SplitPane.oneTouchOffset", new Integer(2), - "SplitPane.oneTouchButtonSize", new Integer(5), + "SplitPane.size", Integer.valueOf(7), + "SplitPane.oneTouchOffset", Integer.valueOf(2), + "SplitPane.oneTouchButtonSize", Integer.valueOf(5), "SplitPane.supportsOneTouchButtons", Boolean.FALSE, @@ -1223,13 +1223,13 @@ public class GTKLookAndFeel extends SynthLookAndFeel { "ToolTip.font", new FontLazyValue(Region.TOOL_TIP), - "Tree.padding", new Integer(4), + "Tree.padding", Integer.valueOf(4), "Tree.background", tableBg, "Tree.drawHorizontalLines", Boolean.FALSE, "Tree.drawVerticalLines", Boolean.FALSE, - "Tree.rowHeight", new Integer(-1), + "Tree.rowHeight", Integer.valueOf(-1), "Tree.scrollsOnExpand", Boolean.FALSE, - "Tree.expanderSize", new Integer(10), + "Tree.expanderSize", Integer.valueOf(10), "Tree.repaintWholeRow", Boolean.TRUE, "Tree.closedIcon", null, "Tree.leafIcon", null, @@ -1240,8 +1240,8 @@ public class GTKLookAndFeel extends SynthLookAndFeel { "Tree.collapsedIcon", new GTKStyle.GTKLazyValue( "com.sun.java.swing.plaf.gtk.GTKIconFactory", "getTreeCollapsedIcon"), - "Tree.leftChildIndent", new Integer(2), - "Tree.rightChildIndent", new Integer(12), + "Tree.leftChildIndent", Integer.valueOf(2), + "Tree.rightChildIndent", Integer.valueOf(12), "Tree.scrollsHorizontallyAndVertically", Boolean.FALSE, "Tree.drawsFocusBorder", Boolean.TRUE, "Tree.focusInputMap", diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java index 0d008907248..4f6e42c784c 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java @@ -851,7 +851,7 @@ class GTKStyle extends SynthStyle implements GTKConstants { int focusLineWidth = getClassSpecificIntValue(context, "focus-line-width", 0); if (value == null && focusLineWidth > 0) { - value = new Integer(16 + 2 * focusLineWidth); + value = Integer.valueOf(16 + 2 * focusLineWidth); } } return value; @@ -975,12 +975,12 @@ class GTKStyle extends SynthStyle implements GTKConstants { private static void initIconTypeMap() { ICON_TYPE_MAP = new HashMap(); - ICON_TYPE_MAP.put("gtk-menu", new Integer(1)); - ICON_TYPE_MAP.put("gtk-small-toolbar", new Integer(2)); - ICON_TYPE_MAP.put("gtk-large-toolbar", new Integer(3)); - ICON_TYPE_MAP.put("gtk-button", new Integer(4)); - ICON_TYPE_MAP.put("gtk-dnd", new Integer(5)); - ICON_TYPE_MAP.put("gtk-dialog", new Integer(6)); + ICON_TYPE_MAP.put("gtk-menu", Integer.valueOf(1)); + ICON_TYPE_MAP.put("gtk-small-toolbar", Integer.valueOf(2)); + ICON_TYPE_MAP.put("gtk-large-toolbar", Integer.valueOf(3)); + ICON_TYPE_MAP.put("gtk-button", Integer.valueOf(4)); + ICON_TYPE_MAP.put("gtk-dnd", Integer.valueOf(5)); + ICON_TYPE_MAP.put("gtk-dialog", Integer.valueOf(6)); } } diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java index 274ac510c0b..e6117989134 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java @@ -178,7 +178,7 @@ class Metacity implements SynthConstants { name = child.getNodeName(); Object value = null; if ("distance".equals(name)) { - value = new Integer(getIntAttr(child, "value", 0)); + value = Integer.valueOf(getIntAttr(child, "value", 0)); } else if ("border".equals(name)) { value = new Insets(getIntAttr(child, "top", 0), getIntAttr(child, "left", 0), @@ -808,7 +808,7 @@ class Metacity implements SynthConstants { protected void setFrameGeometry(JComponent titlePane, Map gm) { this.frameGeometry = gm; if (getInt("top_height") == 0 && titlePane != null) { - gm.put("top_height", new Integer(titlePane.getHeight())); + gm.put("top_height", Integer.valueOf(titlePane.getHeight())); } } diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifGraphicsUtils.java b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifGraphicsUtils.java index d6783e7375d..31425407792 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifGraphicsUtils.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifGraphicsUtils.java @@ -225,15 +225,15 @@ public class MotifGraphicsUtils implements SwingConstants if(b.getIcon() != null) { Icon icon; if(!model.isEnabled()) { - icon = (Icon) b.getDisabledIcon(); + icon = b.getDisabledIcon(); } else if(model.isPressed() && model.isArmed()) { - icon = (Icon) b.getPressedIcon(); + icon = b.getPressedIcon(); if(icon == null) { // Use default icon - icon = (Icon) b.getIcon(); + icon = b.getIcon(); } } else { - icon = (Icon) b.getIcon(); + icon = b.getIcon(); } if (icon!=null) { diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameTitlePane.java b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameTitlePane.java index 251555a592f..737a36d2eb5 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameTitlePane.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameTitlePane.java @@ -86,18 +86,18 @@ public class MotifInternalFrameTitlePane protected void assembleSystemMenu() { systemMenu = new JPopupMenu(); - JMenuItem mi = (JMenuItem)systemMenu.add(new JMenuItem(restoreAction)); + JMenuItem mi = systemMenu.add(new JMenuItem(restoreAction)); mi.setMnemonic('R'); - mi = (JMenuItem) systemMenu.add(new JMenuItem(moveAction)); + mi = systemMenu.add(new JMenuItem(moveAction)); mi.setMnemonic('M'); - mi = (JMenuItem) systemMenu.add(new JMenuItem(sizeAction)); + mi = systemMenu.add(new JMenuItem(sizeAction)); mi.setMnemonic('S'); - mi = (JMenuItem) systemMenu.add(new JMenuItem(iconifyAction)); + mi = systemMenu.add(new JMenuItem(iconifyAction)); mi.setMnemonic('n'); - mi = (JMenuItem) systemMenu.add(new JMenuItem(maximizeAction)); + mi = systemMenu.add(new JMenuItem(maximizeAction)); mi.setMnemonic('x'); systemMenu.add(new JSeparator()); - mi = (JMenuItem) systemMenu.add(new JMenuItem(closeAction)); + mi = systemMenu.add(new JMenuItem(closeAction)); mi.setMnemonic('C'); systemButton = new SystemButton(); @@ -157,7 +157,7 @@ public class MotifInternalFrameTitlePane } public void propertyChange(PropertyChangeEvent evt) { - String prop = (String)evt.getPropertyName(); + String prop = evt.getPropertyName(); JInternalFrame f = (JInternalFrame)evt.getSource(); boolean value = false; if (JInternalFrame.IS_SELECTED_PROPERTY.equals(prop)) { diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java index 63994ff6732..e91dbb9e718 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifLookAndFeel.java @@ -290,7 +290,7 @@ public class MotifLookAndFeel extends BasicLookAndFeel Object unselectedTabBackground = new UIDefaults.LazyValue() { public Object createValue(UIDefaults table) { - Color c = (Color)table.getColor("control"); + Color c = table.getColor("control"); return new ColorUIResource(Math.max((int)(c.getRed()*.85),0), Math.max((int)(c.getGreen()*.85),0), Math.max((int)(c.getBlue()*.85),0)); @@ -299,7 +299,7 @@ public class MotifLookAndFeel extends BasicLookAndFeel Object unselectedTabForeground = new UIDefaults.LazyValue() { public Object createValue(UIDefaults table) { - Color c = (Color)table.getColor("controlText"); + Color c = table.getColor("controlText"); return new ColorUIResource(Math.max((int)(c.getRed()*.85),0), Math.max((int)(c.getGreen()*.85),0), Math.max((int)(c.getBlue()*.85),0)); @@ -308,7 +308,7 @@ public class MotifLookAndFeel extends BasicLookAndFeel Object unselectedTabShadow = new UIDefaults.LazyValue() { public Object createValue(UIDefaults table) { - Color c = (Color)table.getColor("control"); + Color c = table.getColor("control"); Color base = new Color(Math.max((int)(c.getRed()*.85),0), Math.max((int)(c.getGreen()*.85),0), Math.max((int)(c.getBlue()*.85),0)); @@ -318,7 +318,7 @@ public class MotifLookAndFeel extends BasicLookAndFeel Object unselectedTabHighlight = new UIDefaults.LazyValue() { public Object createValue(UIDefaults table) { - Color c = (Color)table.getColor("control"); + Color c = table.getColor("control"); Color base = new Color(Math.max((int)(c.getRed()*.85),0), Math.max((int)(c.getGreen()*.85),0), Math.max((int)(c.getBlue()*.85),0)); @@ -567,7 +567,7 @@ public class MotifLookAndFeel extends BasicLookAndFeel "ProgressBar.selectionBackground", table.get("controlText"), "ProgressBar.border", loweredBevelBorder, "ProgressBar.cellLength", new Integer(6), - "ProgressBar.cellSpacing", new Integer(0), + "ProgressBar.cellSpacing", Integer.valueOf(0), // Buttons "Button.margin", new InsetsUIResource(2, 4, 2, 4), @@ -859,7 +859,7 @@ public class MotifLookAndFeel extends BasicLookAndFeel "SplitPane.background", table.get("control"), "SplitPane.highlight", table.get("controlHighlight"), "SplitPane.shadow", table.get("controlShadow"), - "SplitPane.dividerSize", new Integer(20), + "SplitPane.dividerSize", Integer.valueOf(20), "SplitPane.activeThumb", table.get("activeCaptionBorder"), "SplitPane.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { @@ -1160,7 +1160,7 @@ public class MotifLookAndFeel extends BasicLookAndFeel }), "TextField.caretForeground", black, - "TextField.caretBlinkRate", new Integer(500), + "TextField.caretBlinkRate", Integer.valueOf(500), "TextField.inactiveForeground", table.get("textInactiveText"), "TextField.selectionBackground", table.get("textHighlight"), "TextField.selectionForeground", table.get("textHighlightText"), @@ -1171,7 +1171,7 @@ public class MotifLookAndFeel extends BasicLookAndFeel "TextField.focusInputMap", fieldInputMap, "PasswordField.caretForeground", black, - "PasswordField.caretBlinkRate", new Integer(500), + "PasswordField.caretBlinkRate", Integer.valueOf(500), "PasswordField.inactiveForeground", table.get("textInactiveText"), "PasswordField.selectionBackground", table.get("textHighlight"), "PasswordField.selectionForeground", table.get("textHighlightText"), @@ -1182,7 +1182,7 @@ public class MotifLookAndFeel extends BasicLookAndFeel "PasswordField.focusInputMap", passwordInputMap, "TextArea.caretForeground", black, - "TextArea.caretBlinkRate", new Integer(500), + "TextArea.caretBlinkRate", Integer.valueOf(500), "TextArea.inactiveForeground", table.get("textInactiveText"), "TextArea.selectionBackground", table.get("textHighlight"), "TextArea.selectionForeground", table.get("textHighlightText"), @@ -1193,7 +1193,7 @@ public class MotifLookAndFeel extends BasicLookAndFeel "TextArea.focusInputMap", multilineInputMap, "TextPane.caretForeground", black, - "TextPane.caretBlinkRate", new Integer(500), + "TextPane.caretBlinkRate", Integer.valueOf(500), "TextPane.inactiveForeground", table.get("textInactiveText"), "TextPane.selectionBackground", lightGray, "TextPane.selectionForeground", table.get("textHighlightText"), @@ -1204,7 +1204,7 @@ public class MotifLookAndFeel extends BasicLookAndFeel "TextPane.focusInputMap", multilineInputMap, "EditorPane.caretForeground", red, - "EditorPane.caretBlinkRate", new Integer(500), + "EditorPane.caretBlinkRate", Integer.valueOf(500), "EditorPane.inactiveForeground", table.get("textInactiveText"), "EditorPane.selectionBackground", lightGray, "EditorPane.selectionForeground", table.get("textHighlightText"), diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java index 3977b4d1de6..9af41fc39c8 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java @@ -299,9 +299,9 @@ public class WindowsLookAndFeel extends BasicLookAndFeel initResourceBundle(table); // *** Shared Fonts - Integer twelve = new Integer(12); - Integer fontPlain = new Integer(Font.PLAIN); - Integer fontBold = new Integer(Font.BOLD); + Integer twelve = Integer.valueOf(12); + Integer fontPlain = Integer.valueOf(Font.PLAIN); + Integer fontBold = Integer.valueOf(Font.BOLD); Object dialogPlain12 = new SwingLazyValue( "javax.swing.plaf.FontUIResource", @@ -522,19 +522,19 @@ public class WindowsLookAndFeel extends BasicLookAndFeel toolkit); Object WindowBorderWidth = new DesktopProperty( "win.frame.sizingBorderWidth", - new Integer(1), + Integer.valueOf(1), toolkit); Object TitlePaneHeight = new DesktopProperty( "win.frame.captionHeight", - new Integer(18), + Integer.valueOf(18), toolkit); Object TitleButtonWidth = new DesktopProperty( "win.frame.captionButtonWidth", - new Integer(16), + Integer.valueOf(16), toolkit); Object TitleButtonHeight = new DesktopProperty( "win.frame.captionButtonHeight", - new Integer(16), + Integer.valueOf(16), toolkit); Object InactiveTextColor = new DesktopProperty( "win.text.grayedTextColor", @@ -567,7 +567,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel Object IconFont = ControlFont; Object scrollBarWidth = new DesktopProperty("win.scrollbar.width", - new Integer(16), toolkit); + Integer.valueOf(16), toolkit); Object menuBarHeight = new DesktopProperty("win.menu.height", null, toolkit); @@ -673,12 +673,12 @@ public class WindowsLookAndFeel extends BasicLookAndFeel "Button.disabledForeground", InactiveTextColor, "Button.disabledShadow", ControlHighlightColor, "Button.focus", black, - "Button.dashedRectGapX", new XPValue(new Integer(3), new Integer(5)), - "Button.dashedRectGapY", new XPValue(new Integer(3), new Integer(4)), - "Button.dashedRectGapWidth", new XPValue(new Integer(6), new Integer(10)), - "Button.dashedRectGapHeight", new XPValue(new Integer(6), new Integer(8)), - "Button.textShiftOffset", new XPValue(new Integer(0), - new Integer(1)), + "Button.dashedRectGapX", new XPValue(Integer.valueOf(3), Integer.valueOf(5)), + "Button.dashedRectGapY", new XPValue(Integer.valueOf(3), Integer.valueOf(4)), + "Button.dashedRectGapWidth", new XPValue(Integer.valueOf(6), Integer.valueOf(10)), + "Button.dashedRectGapHeight", new XPValue(Integer.valueOf(6), Integer.valueOf(8)), + "Button.textShiftOffset", new XPValue(Integer.valueOf(0), + Integer.valueOf(1)), // W2K keyboard navigation hidding. "Button.showMnemonics", showMnemonics, "Button.focusInputMap", @@ -780,7 +780,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel }), // DesktopIcon - "DesktopIcon.width", new Integer(160), + "DesktopIcon.width", Integer.valueOf(160), "EditorPane.font", ControlFont, "EditorPane.background", WindowBackgroundColor, @@ -814,9 +814,9 @@ public class WindowsLookAndFeel extends BasicLookAndFeel "icons/NewFolder.gif"), "FileChooser.useSystemExtensionHiding", Boolean.TRUE, - "FileChooser.lookInLabelMnemonic", new Integer(KeyEvent.VK_I), - "FileChooser.fileNameLabelMnemonic", new Integer(KeyEvent.VK_N), - "FileChooser.filesOfTypeLabelMnemonic", new Integer(KeyEvent.VK_T), + "FileChooser.lookInLabelMnemonic", Integer.valueOf(KeyEvent.VK_I), + "FileChooser.fileNameLabelMnemonic", Integer.valueOf(KeyEvent.VK_N), + "FileChooser.filesOfTypeLabelMnemonic", Integer.valueOf(KeyEvent.VK_T), "FileChooser.usesSingleFilePane", Boolean.TRUE, "FileChooser.noPlacesBar", new DesktopProperty("win.comdlg.noPlacesBar", Boolean.FALSE, toolkit), @@ -1021,10 +1021,10 @@ public class WindowsLookAndFeel extends BasicLookAndFeel "Menu.selectionBackground", SelectionBackgroundColor, "Menu.acceleratorForeground", MenuTextColor, "Menu.acceleratorSelectionForeground", SelectionTextColor, - "Menu.menuPopupOffsetX", new Integer(0), - "Menu.menuPopupOffsetY", new Integer(0), - "Menu.submenuPopupOffsetX", new Integer(-4), - "Menu.submenuPopupOffsetY", new Integer(-3), + "Menu.menuPopupOffsetX", Integer.valueOf(0), + "Menu.menuPopupOffsetY", Integer.valueOf(0), + "Menu.submenuPopupOffsetX", Integer.valueOf(-4), + "Menu.submenuPopupOffsetY", Integer.valueOf(-3), "Menu.crossMenuMnemonic", Boolean.FALSE, "Menu.preserveTopLevelSelection", Boolean.TRUE, @@ -1184,8 +1184,8 @@ public class WindowsLookAndFeel extends BasicLookAndFeel "ProgressBar.highlight", ControlHighlightColor, "ProgressBar.selectionForeground", ControlBackgroundColor, "ProgressBar.selectionBackground", SelectionBackgroundColor, - "ProgressBar.cellLength", new Integer(7), - "ProgressBar.cellSpacing", new Integer(2), + "ProgressBar.cellLength", Integer.valueOf(7), + "ProgressBar.cellSpacing", Integer.valueOf(2), "ProgressBar.indeterminateInsets", new Insets(3, 3, 3, 3), // *** RootPane. @@ -1292,7 +1292,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel "SplitPane.highlight", ControlHighlightColor, "SplitPane.shadow", ControlShadowColor, "SplitPane.darkShadow", ControlDarkShadowColor, - "SplitPane.dividerSize", new Integer(5), + "SplitPane.dividerSize", Integer.valueOf(5), "SplitPane.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { "UP", "negativeIncrement", @@ -1496,7 +1496,7 @@ public class WindowsLookAndFeel extends BasicLookAndFeel "ToggleButton.light", ControlLightColor, "ToggleButton.highlight", ControlHighlightColor, "ToggleButton.focus", ControlTextColor, - "ToggleButton.textShiftOffset", new Integer(1), + "ToggleButton.textShiftOffset", Integer.valueOf(1), "ToggleButton.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { "SPACE", "pressed", @@ -1548,8 +1548,8 @@ public class WindowsLookAndFeel extends BasicLookAndFeel "Tree.background", WindowBackgroundColor, "Tree.foreground", WindowTextColor, "Tree.hash", gray, - "Tree.leftChildIndent", new Integer(8), - "Tree.rightChildIndent", new Integer(11), + "Tree.leftChildIndent", Integer.valueOf(8), + "Tree.rightChildIndent", Integer.valueOf(11), "Tree.textForeground", WindowTextColor, "Tree.textBackground", WindowBackgroundColor, "Tree.selectionForeground", SelectionTextColor, @@ -2488,18 +2488,18 @@ public class WindowsLookAndFeel extends BasicLookAndFeel private int direction; XPDLUValue(int xpdlu, int classicdlu, int direction) { - super(new Integer(xpdlu), new Integer(classicdlu)); + super(Integer.valueOf(xpdlu), Integer.valueOf(classicdlu)); this.direction = direction; } public Object getXPValue(UIDefaults table) { int px = dluToPixels(((Integer)xpValue).intValue(), direction); - return new Integer(px); + return Integer.valueOf(px); } public Object getClassicValue(UIDefaults table) { int px = dluToPixels(((Integer)classicValue).intValue(), direction); - return new Integer(px); + return Integer.valueOf(px); } } diff --git a/jdk/src/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java b/jdk/src/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java index 45c1b55a861..f736dc500bd 100644 --- a/jdk/src/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java +++ b/jdk/src/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java @@ -25,6 +25,8 @@ package com.sun.management; +import java.lang.management.PlatformManagedObject; + /** * Diagnostic management interface for the HotSpot Virtual Machine. * The diagnostic MBean is registered to the platform MBeanServer @@ -35,8 +37,13 @@ package com.sun.management; *
    * com.sun.management:type=HotSpotDiagnostic *
    +.* + * It can be obtained by calling the + * {@link PlatformManagedObject#getObjectName} method. + * + * @see ManagementFactory#getPlatformMXBeans(Class) */ -public interface HotSpotDiagnosticMXBean { +public interface HotSpotDiagnosticMXBean extends PlatformManagedObject { /** * Dumps the heap to the outputFile file in the same * format as the hprof heap dump. diff --git a/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java b/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java index 92163845283..014852ca6d0 100644 --- a/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java +++ b/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java @@ -620,9 +620,35 @@ public class ConfigFile extends javax.security.auth.login.Configuration { * start up time noticeably for the new launcher. -- DAC */ private InputStream getInputStream(URL url) throws IOException { - if ("file".equals(url.getProtocol())) { - String path = url.getFile().replace('/', File.separatorChar); - return new FileInputStream(path); + if ("file".equalsIgnoreCase(url.getProtocol())) { + // Compatibility notes: + // + // Code changed from + // String path = url.getFile().replace('/', File.separatorChar); + // return new FileInputStream(path); + // + // The original implementation would search for "/tmp/a%20b" + // when url is "file:///tmp/a%20b". This is incorrect. The + // current codes fix this bug and searches for "/tmp/a b". + // For compatibility reasons, when the file "/tmp/a b" does + // not exist, the file named "/tmp/a%20b" will be tried. + // + // This also means that if both file exists, the behavior of + // this method is changed, and the current codes choose the + // correct one. + try { + return url.openStream(); + } catch (Exception e) { + String file = url.getPath(); + if (url.getHost().length() > 0) { // For Windows UNC + file = "//" + url.getHost() + file; + } + if (debugConfig != null) { + debugConfig.println("cannot read " + url + + ", try " + file); + } + return new FileInputStream(file); + } } else { return url.openStream(); } diff --git a/jdk/src/share/classes/com/sun/tools/hat/Main.java b/jdk/src/share/classes/com/sun/tools/hat/Main.java index 4aebdbe0d70..d027904bdd4 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/Main.java +++ b/jdk/src/share/classes/com/sun/tools/hat/Main.java @@ -23,18 +23,10 @@ * have any questions. */ - /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. + * at JavaSoft/Sun. */ package com.sun.tools.hat; diff --git a/jdk/src/share/classes/com/sun/tools/hat/build.xml b/jdk/src/share/classes/com/sun/tools/hat/build.xml index 655034d3c81..401cb77ae02 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/build.xml +++ b/jdk/src/share/classes/com/sun/tools/hat/build.xml @@ -27,19 +27,9 @@ diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/AbstractJavaHeapObjectVisitor.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/AbstractJavaHeapObjectVisitor.java index d0e72c413e1..83a78cf9728 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/AbstractJavaHeapObjectVisitor.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/AbstractJavaHeapObjectVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/ArrayTypeCodes.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/ArrayTypeCodes.java index 2c3097474d3..fbcb72ffd17 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/ArrayTypeCodes.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/ArrayTypeCodes.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/HackJavaValue.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/HackJavaValue.java index 501cc128cca..fc807085218 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/HackJavaValue.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/HackJavaValue.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaBoolean.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaBoolean.java index 77eab286b15..f5de0d257c5 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaBoolean.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaBoolean.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaByte.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaByte.java index b19da339d0d..0b9ef2a1fae 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaByte.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaByte.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaChar.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaChar.java index dd7b8e35ec4..96cecbf4709 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaChar.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaChar.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaClass.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaClass.java index 6cdd45c6856..068de487982 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaClass.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaClass.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaDouble.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaDouble.java index 97985595541..414f6cab377 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaDouble.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaDouble.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaField.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaField.java index d92d12a6940..540309aec94 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaField.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaField.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaFloat.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaFloat.java index 4f8b589968c..cb0cb74cc7d 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaFloat.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaFloat.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaHeapObject.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaHeapObject.java index 35e0f151b97..0f3b7782815 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaHeapObject.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaHeapObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaHeapObjectVisitor.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaHeapObjectVisitor.java index 0091dd88119..ef82cb2bcd7 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaHeapObjectVisitor.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaHeapObjectVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaInt.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaInt.java index 076aa602e58..0e7f969cb6a 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaInt.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaInt.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaLazyReadObject.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaLazyReadObject.java index 7521723e9d6..0a9c6c25e27 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaLazyReadObject.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaLazyReadObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaLong.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaLong.java index 9c71c4312d9..3654e592ecf 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaLong.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaLong.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaObject.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaObject.java index 785945acad1..d78b794b00e 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaObject.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaObjectArray.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaObjectArray.java index 52c403102a9..e9a67d9eb92 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaObjectArray.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaObjectArray.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaObjectRef.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaObjectRef.java index 30c4eef3e1c..d7271698c74 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaObjectRef.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaObjectRef.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaShort.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaShort.java index 1d9bfa615fa..1d402eb3ab9 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaShort.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaShort.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaStatic.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaStatic.java index 8e6c1fe5a09..c84a43452b9 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaStatic.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaStatic.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaThing.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaThing.java index 9ac70c4136f..bfe7499af48 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaThing.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaThing.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaValue.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaValue.java index 8e694d24b65..2395660715d 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaValue.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaValue.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaValueArray.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaValueArray.java index 6da26096635..4f11161e95d 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaValueArray.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/JavaValueArray.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReachableExcludes.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReachableExcludes.java index d2d711896d1..5dd4d2bc6e0 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReachableExcludes.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReachableExcludes.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReachableExcludesImpl.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReachableExcludesImpl.java index 7bfbd9f8176..1f623243c7e 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReachableExcludesImpl.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReachableExcludesImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReachableObjects.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReachableObjects.java index d6fb869afba..d1749c56302 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReachableObjects.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReachableObjects.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReferenceChain.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReferenceChain.java index 9d8aeadcfcf..f682351d76d 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReferenceChain.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/ReferenceChain.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/Root.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/Root.java index c3197daa3db..1ec22b32ce0 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/Root.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/Root.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/Snapshot.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/Snapshot.java index f0097acc1a8..2000eee5bc5 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/Snapshot.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/Snapshot.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/StackFrame.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/StackFrame.java index 49ed6ea2f4d..1c7e8eacbab 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/StackFrame.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/StackFrame.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/model/StackTrace.java b/jdk/src/share/classes/com/sun/tools/hat/internal/model/StackTrace.java index 94776d11e63..bf64209d054 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/model/StackTrace.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/model/StackTrace.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.model; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/oql/OQLEngine.java b/jdk/src/share/classes/com/sun/tools/hat/internal/oql/OQLEngine.java index 3d98369e859..14a8ca8cf1d 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/oql/OQLEngine.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/oql/OQLEngine.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.oql; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/oql/OQLException.java b/jdk/src/share/classes/com/sun/tools/hat/internal/oql/OQLException.java index 7ab179a680f..00c1cdc0b34 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/oql/OQLException.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/oql/OQLException.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.oql; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/oql/OQLQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/oql/OQLQuery.java index e9fa71842e3..cd594c49133 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/oql/OQLQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/oql/OQLQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.oql; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/oql/ObjectVisitor.java b/jdk/src/share/classes/com/sun/tools/hat/internal/oql/ObjectVisitor.java index 21a795debc0..22a970ee722 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/oql/ObjectVisitor.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/oql/ObjectVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.oql; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/parser/FileReadBuffer.java b/jdk/src/share/classes/com/sun/tools/hat/internal/parser/FileReadBuffer.java index 654ad1eafbe..7d5f5f58cee 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/parser/FileReadBuffer.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/parser/FileReadBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.parser; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/parser/HprofReader.java b/jdk/src/share/classes/com/sun/tools/hat/internal/parser/HprofReader.java index eceac9fdc05..7c7a4376ff0 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/parser/HprofReader.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/parser/HprofReader.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,21 +23,11 @@ * have any questions. */ + /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.parser; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/parser/MappedReadBuffer.java b/jdk/src/share/classes/com/sun/tools/hat/internal/parser/MappedReadBuffer.java index 6540e55f687..a46a0bd5f5f 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/parser/MappedReadBuffer.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/parser/MappedReadBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,21 +23,11 @@ * have any questions. */ + /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.parser; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/parser/PositionDataInputStream.java b/jdk/src/share/classes/com/sun/tools/hat/internal/parser/PositionDataInputStream.java index a2310404d0e..fe68a529ddf 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/parser/PositionDataInputStream.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/parser/PositionDataInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.parser; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/parser/PositionInputStream.java b/jdk/src/share/classes/com/sun/tools/hat/internal/parser/PositionInputStream.java index 8554d237801..0c22fa0ece3 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/parser/PositionInputStream.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/parser/PositionInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.parser; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/parser/ReadBuffer.java b/jdk/src/share/classes/com/sun/tools/hat/internal/parser/ReadBuffer.java index 249c5360fc8..2980fbe4114 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/parser/ReadBuffer.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/parser/ReadBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.parser; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/parser/Reader.java b/jdk/src/share/classes/com/sun/tools/hat/internal/parser/Reader.java index ea39c9cde0b..33fca3a1c5c 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/parser/Reader.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/parser/Reader.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.parser; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllClassesQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllClassesQuery.java index 917194e3816..14209503e7c 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllClassesQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllClassesQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllRootsQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllRootsQuery.java index 25cb2b6a023..794e9c2c9a6 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllRootsQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllRootsQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/ClassQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/ClassQuery.java index 4fc235f7e2a..bb5e9ae8f3e 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/ClassQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/ClassQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/FinalizerObjectsQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/FinalizerObjectsQuery.java index 9bf9f29a75b..e4b4f1c7c3c 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/FinalizerObjectsQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/FinalizerObjectsQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/FinalizerSummaryQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/FinalizerSummaryQuery.java index cb1b11dc048..5fc4cc1e2e8 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/FinalizerSummaryQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/FinalizerSummaryQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/HistogramQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/HistogramQuery.java index a65a5740705..025850f8afb 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/HistogramQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/HistogramQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/HttpReader.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/HttpReader.java index 5b33cea6d0d..fb92b632a1f 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/HttpReader.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/HttpReader.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/InstancesCountQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/InstancesCountQuery.java index 066ee659d33..624a2c3d268 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/InstancesCountQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/InstancesCountQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,19 +24,10 @@ */ -/* The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * +/* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/InstancesQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/InstancesQuery.java index f30e153a439..6be2630b1eb 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/InstancesQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/InstancesQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,19 +24,10 @@ */ -/* The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * +/* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLHelp.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLHelp.java index 1a5ed041e6c..f0a6cf11657 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLHelp.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLHelp.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLQuery.java index 75bed2fdf49..e6c1dfbabd4 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/ObjectQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/ObjectQuery.java index 7748b0c97f7..30ab9c7cc94 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/ObjectQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/ObjectQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,19 +24,10 @@ */ -/* The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * +/* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/PlatformClasses.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/PlatformClasses.java index 24db65e2fe7..9ba31757c50 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/PlatformClasses.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/PlatformClasses.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,19 +24,10 @@ */ -/* The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * +/* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/QueryHandler.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/QueryHandler.java index 80d208318ac..49729018e7c 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/QueryHandler.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/QueryHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,20 +24,10 @@ */ - -/* The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * +/* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/QueryListener.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/QueryListener.java index d54b106f9e0..57233637416 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/QueryListener.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/QueryListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,19 +24,10 @@ */ -/* The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * +/* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/ReachableQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/ReachableQuery.java index 9a50739274c..8ee0f629792 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/ReachableQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/ReachableQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,20 +24,10 @@ */ - -/* The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * +/* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/RefsByTypeQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/RefsByTypeQuery.java index 0a2b73d2cd0..8256928f0b9 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/RefsByTypeQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/RefsByTypeQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/RootStackQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/RootStackQuery.java index 5b14ebe0fbf..45fd7d86ac1 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/RootStackQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/RootStackQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,19 +24,10 @@ */ -/* The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * +/* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/RootsQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/RootsQuery.java index b9d71d4d573..a9db43f6983 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/RootsQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/RootsQuery.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,19 +24,10 @@ */ -/* The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * +/* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.server; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/util/ArraySorter.java b/jdk/src/share/classes/com/sun/tools/hat/internal/util/ArraySorter.java index 84503e3057f..77b93290ffe 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/util/ArraySorter.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/util/ArraySorter.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,19 +24,10 @@ */ -/* The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * +/* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.util; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/util/Comparer.java b/jdk/src/share/classes/com/sun/tools/hat/internal/util/Comparer.java index 941f90f0e6c..aa1f147ee7b 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/util/Comparer.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/util/Comparer.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,19 +24,10 @@ */ -/* The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * +/* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.util; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/util/CompositeEnumeration.java b/jdk/src/share/classes/com/sun/tools/hat/internal/util/CompositeEnumeration.java index ec1804b6cbc..2042850141c 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/util/CompositeEnumeration.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/util/CompositeEnumeration.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,20 +25,9 @@ /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.util; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/util/Misc.java b/jdk/src/share/classes/com/sun/tools/hat/internal/util/Misc.java index 2a87657a05f..42b5bd1310d 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/util/Misc.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/util/Misc.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,19 +24,10 @@ */ -/* The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * +/* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.util; diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/util/VectorSorter.java b/jdk/src/share/classes/com/sun/tools/hat/internal/util/VectorSorter.java index cb963d6de43..776f9088f6a 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/util/VectorSorter.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/util/VectorSorter.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,19 +24,10 @@ */ -/* The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * +/* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. + * at JavaSoft/Sun. */ package com.sun.tools.hat.internal.util; diff --git a/jdk/src/share/classes/com/sun/tools/hat/resources/hat.js b/jdk/src/share/classes/com/sun/tools/hat/resources/hat.js index e81eae514d3..1b8cfdc935b 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/resources/hat.js +++ b/jdk/src/share/classes/com/sun/tools/hat/resources/hat.js @@ -23,22 +23,10 @@ * have any questions. */ - /* - * The contents of this file are subject to the Sun Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. A copy of the License is available at - * http://www.sun.com/, and in the file LICENSE.html in the - * doc directory. - * * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. Portions created by Bill Foote and others - * at Javasoft/Sun are Copyright (C) 1997-2004. All Rights Reserved. - * - * In addition to the formal license, I ask that you don't - * change the history or donations files without permission. - * + * at JavaSoft/Sun. */ var hatPkg = Packages.com.sun.tools.hat.internal; diff --git a/jdk/src/share/classes/com/sun/tracing/Probe.java b/jdk/src/share/classes/com/sun/tracing/Probe.java new file mode 100644 index 00000000000..9f735f77eb9 --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/Probe.java @@ -0,0 +1,71 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tracing; + +/** + * The {@code Probe} interface represents a tracepoint. + * + * A {@code Probe} instance is obtained by calling the + * {@code Provider.getProbe()} method of a provider instance created by + * {@code ProviderFactory.createProvider()}. A {@code Probe} can be used to + * trigger a probe manually (provided the correct arguments are passed to + * it), or to check a probe to see if anything is currently tracing it. + *

    + * A tracing check can be used to avoid lengthy work that might be + * needed to set up the probe's arguments. However, checking + * whether the probe is enabled generally takes the same amount of time + * as actually triggering the probe. So, you should only check a probe's status + * without triggering it if setting up the arguments is very expensive. + *

    + * Users do not need to implement this interface: instances are + * created automatically by the system when a {@code Provider)} instance is + * created. + *

    + * @since 1.7 + */ + +public interface Probe { + /** + * Checks whether there is an active trace of this probe. + * + * @return true if an active trace is detected. + */ + boolean isEnabled(); + + /** + * Determines whether a tracepoint is enabled. + * + * Typically, users do not need to use this method. It is called + * automatically when a Provider's instance method is called. Calls to + * this method expect the arguments to match the declared parameters for + * the method associated with the probe. + * + * @param args the parameters to pass to the method. + * @throws IllegalArgumentException if the provided parameters do not + * match the method declaration for this probe. + */ + void trigger(Object ... args); +} diff --git a/jdk/src/share/classes/com/sun/tracing/ProbeName.java b/jdk/src/share/classes/com/sun/tracing/ProbeName.java new file mode 100644 index 00000000000..7b3728857b1 --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/ProbeName.java @@ -0,0 +1,48 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tracing; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * An annotation used to override the name of a probe. + *

    + * This annotation can be added to a method in a user-defined {@code Provider} + * interface, to set the name that will be used for the generated probe + * associated with that method. Without this annotation, the name will be the + * name of the method. + *

    + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ProbeName { + String value(); +} + diff --git a/jdk/src/share/classes/com/sun/tracing/Provider.java b/jdk/src/share/classes/com/sun/tracing/Provider.java new file mode 100644 index 00000000000..3f05e516d75 --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/Provider.java @@ -0,0 +1,76 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tracing; + +/** + * {@code Provider} is a superinterface for user-defined tracing providers. + *

    + * To define tracepoints, users must extend this interface + * and then use a {@code ProviderFactory} to create an instance of the + * newly-defined interface. Each method in the defined interface represents a + * tracepoint (or probe), which can be triggered by calling the associated + * method on the returned instance. + *

    + * This interface also contains a {@code getProbe()} method, which can be + * used to get direct handles to the {@code Probe} objects themselves. + * {@code Probe} objects can be triggered manually, or they can be queried to + * check their state. + *

    + * When an application has finished triggering probes, it should call + * {@code dispose()} to free up any system resources associated with the + * Provider. + *

    + * All methods declared in a subclass of this interface should have a + * {@code void} return type. Methods can have parameters, and when called the + * values of the arguments will be passed to the tracing implementation. + * If any methods do not have a {@code void} return type, an + * {@code java.lang.IllegalArgumentException} will be thrown when the + * provider is registered. + * @since 1.7 + */ + +public interface Provider { + /** + * Retrieves a reference to a Probe object, which is used to check status + * or to trigger the probe manually. + * + * If the provided method parameter is not a method of the provider + * interface, or if the provider interface has been disposed, then + * this returns null + * + * @param method a method declared in the provider. + * @return the specified probe represented by that method, or null. + */ + Probe getProbe(java.lang.reflect.Method method); + + /** + * Disposes system resources associated with this provider. + * + * After calling this method, triggering the probes will have no effect. + * Additional calls to this method after the first call are ignored. + */ + void dispose(); +} diff --git a/jdk/src/share/classes/com/sun/tracing/ProviderFactory.java b/jdk/src/share/classes/com/sun/tracing/ProviderFactory.java new file mode 100644 index 00000000000..768a6bebb8d --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/ProviderFactory.java @@ -0,0 +1,110 @@ + +package com.sun.tracing; + +import java.util.HashSet; +import java.io.PrintStream; +import java.lang.reflect.Field; +import java.util.logging.Logger; + +import sun.tracing.NullProviderFactory; +import sun.tracing.PrintStreamProviderFactory; +import sun.tracing.MultiplexProviderFactory; +import sun.tracing.dtrace.DTraceProviderFactory; + +/** + * {@code ProviderFactory} is a factory class used to create instances of + * providers. + * + * To enable tracing in an application, this class must be used to create + * instances of the provider interfaces defined by users. + * The system-defined factory is obtained by using the + * {@code getDefaultFactory()} static method. The resulting instance can be + * used to create any number of providers. + * + * @since 1.7 + */ +public abstract class ProviderFactory { + + protected ProviderFactory() {} + + /** + * Creates an implementation of a Provider interface. + * + * @param cls the provider interface to be defined. + * @return an implementation of {@code cls}, whose methods, when called, + * will trigger tracepoints in the application. + * @throws NullPointerException if cls is null + * @throws IllegalArgumentException if the class definition contains + * non-void methods + */ + public abstract T createProvider(Class cls); + + /** + * Returns an implementation of a {@code ProviderFactory} which + * creates instances of Providers. + * + * The created Provider instances will be linked to all appropriate + * and enabled system-defined tracing mechanisms in the JDK. + * + * @return a {@code ProviderFactory} that is used to create Providers. + */ + public static ProviderFactory getDefaultFactory() { + HashSet factories = new HashSet(); + + // Try to instantiate a DTraceProviderFactory + String prop = null; + try { prop = System.getProperty("com.sun.tracing.dtrace"); } + catch (java.security.AccessControlException e) { + Logger.getAnonymousLogger().fine( + "Cannot access property com.sun.tracing.dtrace"); + } + if ( (prop == null || !prop.equals("disable")) && + DTraceProviderFactory.isSupported() ) { + factories.add(new DTraceProviderFactory()); + } + + // Try to instantiate an output stream factory + try { prop = System.getProperty("sun.tracing.stream"); } + catch (java.security.AccessControlException e) { + Logger.getAnonymousLogger().fine( + "Cannot access property sun.tracing.stream"); + } + if (prop != null) { + for (String spec : prop.split(",")) { + PrintStream ps = getPrintStreamFromSpec(spec); + if (ps != null) { + factories.add(new PrintStreamProviderFactory(ps)); + } + } + } + + // See how many factories we instantiated, and return an appropriate + // factory that encapsulates that. + if (factories.size() == 0) { + return new NullProviderFactory(); + } else if (factories.size() == 1) { + return factories.toArray(new ProviderFactory[1])[0]; + } else { + return new MultiplexProviderFactory(factories); + } + } + + private static PrintStream getPrintStreamFromSpec(String spec) { + try { + // spec is in the form of ., where is + // a fully specified class name, and is a static member + // in that class. The must be a 'PrintStream' or subtype + // in order to be used. + int fieldpos = spec.lastIndexOf('.'); + Class cls = Class.forName(spec.substring(0, fieldpos)); + Field f = cls.getField(spec.substring(fieldpos + 1)); + Class fieldType = f.getType(); + return (PrintStream)f.get(null); + } catch (Exception e) { + Logger.getAnonymousLogger().warning( + "Could not parse sun.tracing.stream property: " + e); + } + return null; + } +} + diff --git a/jdk/src/share/classes/com/sun/tracing/ProviderName.java b/jdk/src/share/classes/com/sun/tracing/ProviderName.java new file mode 100644 index 00000000000..d34e2970dee --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/ProviderName.java @@ -0,0 +1,48 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tracing; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * An annotation used to specify the name of a provider. + *

    + * This annotation can be added to a user-defined {@code Provider} + * interface, to set the name that will be used + * for the provider in the generated probes. Without this annotation, + * the simple class name of the provider interface is used. + *

    + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface ProviderName { + String value(); +} + diff --git a/jdk/src/share/classes/com/sun/tracing/dtrace/ArgsAttributes.java b/jdk/src/share/classes/com/sun/tracing/dtrace/ArgsAttributes.java new file mode 100644 index 00000000000..de88931ab46 --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/ArgsAttributes.java @@ -0,0 +1,53 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + + +/** + * This annotation describes the interface attributes of the probe arguments in + * a single provider. + * + * This annotation can be added to a user-defined {@code Provider} specification + * interface to set the stability attributes of the probe arguments, for + * all the probes specified in that provider. + *

    + * If this annotation is not present, the interface attributes for the + * arguments are Private/Private/Unknown. + *

    + * @see Solaris Dynamic Tracing Guide, Chapter 39: Stability + * @since 1.7 + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +public @interface ArgsAttributes { + Attributes value(); +} diff --git a/jdk/src/share/classes/com/sun/tracing/dtrace/Attributes.java b/jdk/src/share/classes/com/sun/tracing/dtrace/Attributes.java new file mode 100644 index 00000000000..8f8810520f8 --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/Attributes.java @@ -0,0 +1,66 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + + +/** + * This annotation describes the interface's field attributes + * for the probes in a provider. + * + * This annotation provides the contents of field-specific annotations + * that specify the stability attributes and dependency class of a + * particular field, for the probes in a provider. + *

    + * The default interface attributes for unspecified fields is + * Private/Private/Unknown. + *

    + * @see Solaris Dynamic Tracing Guide, Chapter 39: Stability + * @since 1.7 + */ + +@Retention(RetentionPolicy.RUNTIME) +@Target({}) +public @interface Attributes { + /** + * The stability level of the name. + */ + StabilityLevel name() default StabilityLevel.PRIVATE; + + /** + * The stability level of the data. + */ + StabilityLevel data() default StabilityLevel.PRIVATE; + + /** + * The interface attribute's dependency class. + */ + DependencyClass dependency() default DependencyClass.UNKNOWN; +} diff --git a/jdk/src/share/classes/com/sun/tracing/dtrace/DependencyClass.java b/jdk/src/share/classes/com/sun/tracing/dtrace/DependencyClass.java new file mode 100644 index 00000000000..8f4b4870980 --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/DependencyClass.java @@ -0,0 +1,77 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tracing.dtrace; + +/** + * Enumeration for the DTrace dependency classes. + * + * @see Solaris Dynamic Tracing Guide for details, Chapter 39: Stability + * @since 1.7 + */ +public enum DependencyClass { + /** + * The interface has an unknown set of architectural dependencies. + */ + UNKNOWN (0), + /** + * The interface is specific to the CPU model of the current system. + */ + CPU (1), + /** + * The interface is specific to the hardware platform of the current + * system. + */ + PLATFORM (2), + /** + * The interface is specific to the hardware platform group of the + * current system. + */ + GROUP (3), + /** + * The interface is specific to the instruction set architecture (ISA) + * supported by the microprocessors on this system. + */ + ISA (4), + /** + * The interface is common to all Solaris systems regardless of the + * underlying hardware. + */ + COMMON (5); + + public String toDisplayString() { + return toString().substring(0,1) + + toString().substring(1).toLowerCase(); + } + + public int getEncoding() { return encoding; } + + private int encoding; + + private DependencyClass(int encoding) { + this.encoding = encoding; + } +} + diff --git a/jdk/src/share/classes/com/sun/tracing/dtrace/FunctionAttributes.java b/jdk/src/share/classes/com/sun/tracing/dtrace/FunctionAttributes.java new file mode 100644 index 00000000000..1458cadff78 --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/FunctionAttributes.java @@ -0,0 +1,51 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * This annotation describes the interface attributes of the + * {@code function} field for a single provider. + * + * This annotation can be added to a user-defined {@code Provider} specification + * interface to set the stability attributes of the {@code function} field for + * all probes specified in that provider. + *

    + * If this annotation is not present, the interface attributes for the + * {@code function} field are Private/Private/Unknown. + *

    + * @see Solaris Dynamic Tracing Guide, Chapter 39: Stability + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +public @interface FunctionAttributes { + Attributes value(); +} diff --git a/jdk/src/share/classes/com/sun/tracing/dtrace/FunctionName.java b/jdk/src/share/classes/com/sun/tracing/dtrace/FunctionName.java new file mode 100644 index 00000000000..7e7407c4f4c --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/FunctionName.java @@ -0,0 +1,47 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * An annotation used to specify the {@code function} field for a DTrace probe. + * + * This annotation can be added to a method in a user-defined Provider + * specification interface to set the {@code function} field that is used + * for the generated DTrace probe associated with that method. + *

    + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface FunctionName { + String value(); +} + diff --git a/jdk/src/share/classes/com/sun/tracing/dtrace/ModuleAttributes.java b/jdk/src/share/classes/com/sun/tracing/dtrace/ModuleAttributes.java new file mode 100644 index 00000000000..78c7412447e --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/ModuleAttributes.java @@ -0,0 +1,51 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * This annotation is used to describe the interface attributes of the + * {@code module} field for a single provider. + * + * This annotation can be added to a user-defined Provider specification + * interface to set the stability attributes of the {@code module} field for + * all probes specified in that provider. + *

    + * If this annotation is not present, the interface attributes for the + * {@code module} field is Private/Private/Unknown. + *

    + * @see Solaris Dynamic Tracing Guide, Chapter 39: Stability + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +public @interface ModuleAttributes { + Attributes value(); +} diff --git a/jdk/src/share/classes/com/sun/tracing/dtrace/ModuleName.java b/jdk/src/share/classes/com/sun/tracing/dtrace/ModuleName.java new file mode 100644 index 00000000000..fb53a0498ca --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/ModuleName.java @@ -0,0 +1,47 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * An annotation used to specify the {@code module} field for a DTrace probe. + * + * This annotation can be added to a method in a user-defined Provider + * specification interface to set the {@code module} field that will be used + * for the generated DTrace probe associated with that method. + *

    + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface ModuleName { + String value(); +} + diff --git a/jdk/src/share/classes/com/sun/tracing/dtrace/NameAttributes.java b/jdk/src/share/classes/com/sun/tracing/dtrace/NameAttributes.java new file mode 100644 index 00000000000..6a2ae7c927b --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/NameAttributes.java @@ -0,0 +1,51 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * This annotation describes the interface attributes of the + * {@code name} field for a single provider. + * + * This annotation can be added to a user-defined Provider specification + * interface to set the stability attributes of the {@code name} field for + * all probes specified in that provider. + *

    + * If this annotation is not present, the interface attributes for the + * {@code name} field will be Private/Private/Unknown. + *

    + * @see Solaris Dynamic Tracing Guide, Chapter 39: Stability + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +public @interface NameAttributes { + Attributes value(); +} diff --git a/jdk/src/share/classes/com/sun/tracing/dtrace/ProviderAttributes.java b/jdk/src/share/classes/com/sun/tracing/dtrace/ProviderAttributes.java new file mode 100644 index 00000000000..a793829a395 --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/ProviderAttributes.java @@ -0,0 +1,51 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tracing.dtrace; + +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.ElementType; + +/** + * This annotation is used to describe the interface attributes of the + * {@code provider} field for a single provider. + * + * This annotation can be added to a user-defined Provider specification + * interface to set the stability attributes of the {@code provider} field for + * all probes specified in that provider. + *

    + * If this annotation is not present, the interface attributes for the + * {@code provider} field will be Private/Private/Unknown. + *

    + * @see Solaris Dynamic Tracing Guide, Chapter 39: Stability + * @since 1.7 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE }) +public @interface ProviderAttributes { + Attributes value(); +} diff --git a/jdk/src/share/classes/com/sun/tracing/dtrace/StabilityLevel.java b/jdk/src/share/classes/com/sun/tracing/dtrace/StabilityLevel.java new file mode 100644 index 00000000000..dafd1796157 --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/StabilityLevel.java @@ -0,0 +1,88 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tracing.dtrace; + +/** + * Enumeration for the DTrace stability levels. + * + * @see Solaris Dynamic Tracing Guide, Chapter 39: Stability + * @since 1.7 + */ +public enum StabilityLevel { + /** + * The interface is private to DTrace and represents an implementation + * detail of DTrace. + */ + INTERNAL (0), + /** + * The interface is private to Sun for use by other Sun products. It is + * not yet publicly documented for use by customers and ISVs. + */ + PRIVATE (1), + /** + * The interface is supported in the current release but is scheduled + * to be removed, most likely in a future minor release. + */ + OBSOLETE (2), + /** + * The interface is controlled by an entity other than Sun. + */ + EXTERNAL (3), + /** + * The interface gives developers early access to new or + * rapidly changing technology or to an implementation artifact that is + * essential for observing or debugging system behavior. A more + * stable solution is anticipated in the future. + */ + UNSTABLE (4), + /** + * The interface might eventually become Standard or Stable but is + * still in transition. + */ + EVOLVING (5), + /** + * The interface is a mature interface under Sun's control. + */ + STABLE (6), + /** + * The interface complies with an industry standard. + */ + STANDARD (7); + + String toDisplayString() { + return toString().substring(0,1) + + toString().substring(1).toLowerCase(); + } + + public int getEncoding() { return encoding; } + + private int encoding; + + private StabilityLevel(int encoding) { + this.encoding = encoding; + } +} + diff --git a/jdk/src/share/classes/com/sun/tracing/dtrace/package-info.java b/jdk/src/share/classes/com/sun/tracing/dtrace/package-info.java new file mode 100644 index 00000000000..7ccdaefab78 --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/dtrace/package-info.java @@ -0,0 +1,82 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * This package contains annotations and enumerations that are used to + * add DTrace-specific information to a tracing provider. + *

    + * The DTrace-specific annotations modify the attributes of a DTrace provider + * implementation when it is used by the tracing subsystem. The annotations are + * added to a {@code com.sun.tracing} provider specification to control + * specific attributes of the provider as it relates to DTrace. + *

    + * Any other tracing subsystems supported by the system will ignore these + * annotations. + *

    + * DTrace probes have additional fields and stability attributes that are + * not accounted for in the generic tracing package. If unspecified, the + * default values are used for the stability and dependency attributes of + * probes, as well as for the module and field names of the generated probes. + * The values can be specified by adding the appropriate annotations to the + * provider specification. + *

    + * The {@code FunctionName} annotation is used to annotate the tracepoint + * methods defined in the provider specification. The value of this annotation + * is used as the {@code function} field in the generated DTrace probes. It + * is typically set to the name of the enclosing function where the + * tracepoint is triggered. + *

    + * The {@code ModuleName} annotation is used to annotate the provider + * specification itself and applies to all the probes in the provider. It + * sets the value of the {@code module} field in the generated DTrace probes. + *

    + * The remaining annotations, are also applied to the provider itself, and + * are used to set the stability and dependency attributes of all probes in + * that provider. Each probe field and the probe arguments can be + * independently assigned interface attributes to control the stability + * ratings of the probes. + *

    + * Here is an example of how to declare a provider, specifying additional DTrace + * data: +

    +    @ProviderName("my_app_provider")
    +    @ModuleName("app.jar")
    +    @ProviderAttributes(@Attributes={
    +        name=StabilityLevel.STABLE,data=StabilityLevel.STABLE,
    +        dependency=DependencyClass.COMMON})
    +    @ProbeAttributes(@Attributes={
    +        name=StabilityLevel.STABLE,data=StabilityLevel.STABLE,
    +        dependency=DependencyClass.COMMON})
    +    @ModuleAttributes(@Attributes={name=StabilityLevel.UNSTABLE})
    +    public class MyProvider {
    +        @FunctionName("main") void startProbe();
    +    }
    +
    + *

    + * @see Solaris Dynamic Tracing Guide, Chapter 34: Statically Defined Tracing for User Applications + * @see Solaris Dynamic Tracing Guide, Chapter 39: Stability + */ + +package com.sun.tracing.dtrace; diff --git a/jdk/src/share/classes/com/sun/tracing/package-info.java b/jdk/src/share/classes/com/sun/tracing/package-info.java new file mode 100644 index 00000000000..e9e31b1bdc0 --- /dev/null +++ b/jdk/src/share/classes/com/sun/tracing/package-info.java @@ -0,0 +1,183 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * This package provides a mechanism for defining and + * inserting tracepoints into Java-technology based applications, which + * can then be monitored by the tracing tools available on the system. + *

    + * To add tracepoints to a program, you must first decide where to place the + * tracepoints, what the logical names are for these points, what information + * will be available to the tracing mechanisms at each point, and decide upon + * any logical grouping. + *

    + * You add instrumentation to a program in three steps: + *

      + *
    • First, declare tracepoints by creating interfaces to define + * them, and include these interfaces in the program definition. + * The declared interfaces are standard Java technology-based + * interfaces and are compiled with the program.
    • + *
    • Second, add code in the application to create an instance of the + * interface at some point during the initialization of the application, + * using a factory class provided by the system. The reference to the + * instance can be stored as a global static, or passed as context to all + * the places where it is needed.
    • + *
    • Finally, add the actual tracepoints to the desired locations in the + * application by inserting a call to one of the methods defined in the + * interface, via the factory-created reference.
    • + *
    + *

    + * The method calls representing the tracepoints have no logical + * impact on the program. The side effect of the call is that any + * activated tracing mechanisms will be notified that the tracepoint has + * been hit, and will take whatever actions are appropriate (for example, + * logging the tracepoint, or triggering a DTrace probe, etc.). In most + * cases, the impact on performance of adding tracepoints to the application + * will be minimal. + *

    + * Each logical grouping of tracepoints should be defined in a common + * interface, called a provider. An application can have one or many + * providers. Each provider is independent and can be created whenever + * it is appropriate for that provider, for example, when a subsytem is + * initialized. Providers should be disposed of when they are no longer + * needed, to free up any associated system resources. Each tracepoint + * in a provider is represented by a method in that interface. These methods + * are referred to as probes. The method signature determines the probe + * parameters. A call to the method with the specified parameters triggers + * the probe and makes its parameter values visible to any associated tracing + * mechanism. + *

    + * User-defined interfaces which represent providers must extend the + * {@code Provider} interface. To activate the system-defined + * tracing mechanisms, you must obtain an instance of the + * {@code ProviderFactory} class, and pass the class of the provider to + * the {@code createProvider()} method. The returned instance is then used to + * trigger the probes later in the application. + *

    + * In addition to triggering the probes, the provider instance can be used + * to obtain direct references to the {@code Probe} objects, which can be used + * directly for triggering, or can be queried to determine whether the probe is + * currently being traced. The {@code Provider} interface also defines a + * {@code Provider.dispose()} method which is used to free up any resources + * that might be associated with that provider. + *

    + * When a probe is triggered, any activated tracing system will be given + * the provider name, the probe name, and the values of the probe arguments. + * The tracing system is free to consume this data is whatever way is + * appropriate. + * By default, the provider name is the same as the class name of the interface + * that defines the provider. Similarly, the probe name is + * the name of the method that defines the probe. These default values + * can be over-ridden by annotations. The provider definition can be + * annotated with the {@code @ProviderName} annotation, whose value will + * indicate the provider name that the tracing system will use. Similarly, + * the {@code @ProbeName} annotation annotates a declared method and + * indicates the probe name that should be used in the place of the + * method name. These annotations can be used to define providers and + * probes with the same name, in cases where the semantics of the Java language + * may prevent this. + *

    + * Here is a very small and simple usage example: + *

    + * +

    +   import com.sun.tracing.Provider;
    +   import com.sun.tracing.ProviderFactory;
    +
    +   interface MyProvider extends Provider {
    +       void startProbe();
    +       void finishProbe(int value);
    +   }
    +
    +   public class MyApplication {
    +       public static void main(String argv[]) {
    +           ProviderFactory factory = ProviderFactory.getDefaultFactory();
    +           MyProvider trace = factory.createProvider(MyProvider.class);
    +
    +           trace.startProbe();
    +           int result = foo();
    +           trace.finishProbe(result);
    +
    +           trace.dispose();
    +       }
    +   }
    +
    + *

    + * The Java Development Kit (JDK) currently only includes one system-defined + * tracing framework: DTrace. DTrace is enabled automatically whenever an + * application is run on a system and a JDK release that supports it. When + * DTrace is enabled, probes are made available for listing and matching by + * DTrace scripts as soon as the provider is created. At the tracepoint, an + * associated DTrace script is informed of the creation of the provider, and + * it takes whatever action it is designed to take. Tracepoints in the + * program have the following DTrace probe names:
    + * {@code :::} + * Where: + *

      + *
    • {@code } the provider name as specified by the application
    • + *
    • {@code } the operating system process ID
    • + *
    • {@code } undefined, unless specified by the application
    • + *
    • {@code } undefined, unless specified by the application
    • + *
    • {@code } the probe name as specified by the application
    • + *
    + *

    + * The {@code com.sun.tracing.dtrace} package contains additional + * annotations that can be used to control the names used for the + * module and function fields, as well as annotations + * that can be added to the provider to control probe stability and dependency + * attributes. + *

    + * Integer, float and string probe parameters are made available to DTrace + * using + * the built-in argument variables, {@code arg0 ... arg_n}. Integer-types + * are passed by value (boxed values are unboxed), floating-point types are + * passed as encoded integer + * arguments, and {@code java.lang.String} objects are converted + * to UTF8 strings, so they can be read into the DTrace script using the + * {@code copyinstr()} intrinsic. Non-string and non-boxed primitive + * reference arguments are only + * placeholders and have no value. + *

    + * Using the example above, with a theoretical process ID of 123, these are + * the probes that can be traced from DTrace: +

    +    MyProvider123:::startProbe
    +    MyProvider123:::finishProbe
    +
    + * When {@code finishProbe} executes, {@code arg0} will contain the + * value of {@code result}. + *

    + * The DTrace tracing mechanism is enabled for all providers, apart from in the + * following circumstances: + *

      + *
    • DTrace is not supported on the underlying system.
    • + *
    • The property {@code com.sun.tracing.dtrace} is set to "disable".
    • + *
    • The RuntimePermission {@code com.sun.tracing.dtrace.createProvider} + * is denied to the process.
    • + *
    + *

    + */ + +package com.sun.tracing; diff --git a/jdk/src/share/classes/java/awt/Button.java b/jdk/src/share/classes/java/awt/Button.java index 46d0d072424..fcb33ddecc2 100644 --- a/jdk/src/share/classes/java/awt/Button.java +++ b/jdk/src/share/classes/java/awt/Button.java @@ -597,7 +597,7 @@ public class Button extends Component implements Accessible { public String getAccessibleActionDescription(int i) { if (i == 0) { // [[[PENDING: WDW -- need to provide a localized string]]] - return new String("click"); + return "click"; } else { return null; } diff --git a/jdk/src/share/classes/java/awt/Color.java b/jdk/src/share/classes/java/awt/Color.java index c06b573d7ca..22a8455f2b5 100644 --- a/jdk/src/share/classes/java/awt/Color.java +++ b/jdk/src/share/classes/java/awt/Color.java @@ -51,6 +51,7 @@ import java.awt.color.ColorSpace; * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html * . *

    + * @version 10 Feb 1997 * @author Sami Shaio * @author Arthur van Hoff * @see ColorSpace @@ -1176,23 +1177,32 @@ public class Color implements Paint, java.io.Serializable { } /** - * Creates and returns a {@link PaintContext} used to generate a solid - * color pattern. This enables a Color object to be used - * as an argument to any method requiring an object implementing the - * {@link Paint} interface. - * The same PaintContext is returned, regardless of - * whether or not r, r2d, - * xform, or hints are null. - * @param cm the specified ColorModel - * @param r the specified {@link Rectangle} - * @param r2d the specified {@link Rectangle2D} - * @param xform the specified {@link AffineTransform} - * @param hints the specified {@link RenderingHints} - * @return a PaintContext that is used to generate a - * solid color pattern. + * Creates and returns a {@link PaintContext} used to + * generate a solid color field pattern. + * See the {@link Paint#createContext specification} of the + * method in the {@link Paint} interface for information + * on null parameter handling. + * + * @param cm the preferred {@link ColorModel} which represents the most convenient + * format for the caller to receive the pixel data, or {@code null} + * if there is no preference. + * @param r the device space bounding box + * of the graphics primitive being rendered. + * @param r2d the user space bounding box + * of the graphics primitive being rendered. + * @param xform the {@link AffineTransform} from user + * space into device space. + * @param hints the set of hints that the context object can use to + * choose between rendering alternatives. + * @return the {@code PaintContext} for + * generating color patterns. * @see Paint * @see PaintContext - * @see Graphics2D#setPaint + * @see ColorModel + * @see Rectangle + * @see Rectangle2D + * @see AffineTransform + * @see RenderingHints */ public synchronized PaintContext createContext(ColorModel cm, Rectangle r, Rectangle2D r2d, diff --git a/jdk/src/share/classes/java/awt/Component.java b/jdk/src/share/classes/java/awt/Component.java index b48b8c552fd..9c54250df6d 100644 --- a/jdk/src/share/classes/java/awt/Component.java +++ b/jdk/src/share/classes/java/awt/Component.java @@ -1,5 +1,5 @@ /* - * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,6 +49,7 @@ import java.io.ObjectInputStream; import java.io.IOException; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; +import java.beans.Transient; import java.awt.event.InputMethodListener; import java.awt.event.InputMethodEvent; import java.awt.im.InputContext; @@ -634,7 +635,9 @@ public abstract class Component implements ImageObserver, MenuContainer, */ private PropertyChangeSupport changeSupport; - private transient final Object changeSupportLock = new Object(); + // Note: this field is considered final, though readObject() prohibits + // initializing final fields. + private transient Object changeSupportLock = new Object(); private Object getChangeSupportLock() { return changeSupportLock; } @@ -1003,7 +1006,7 @@ public abstract class Component implements ImageObserver, MenuContainer, /** * Gets this component's locking object (the object that owns the thread - * sychronization monitor) for AWT component-tree and layout + * synchronization monitor) for AWT component-tree and layout * operations. * @return this component's locking object */ @@ -1100,6 +1103,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @see #setVisible * @since JDK1.0 */ + @Transient public boolean isVisible() { return isVisible_NoClientCode(); } @@ -1325,12 +1329,15 @@ public abstract class Component implements ImageObserver, MenuContainer, KeyboardFocusManager.clearMostRecentFocusOwner(this); synchronized (getTreeLock()) { enabled = false; - if (isFocusOwner()) { + // A disabled lw container is allowed to contain a focus owner. + if ((isFocusOwner() || (containsFocus() && !isLightweight())) && + KeyboardFocusManager.isAutoFocusTransferEnabled()) + { // Don't clear the global focus owner. If transferFocus // fails, we want the focus to stay on the disabled // Component so that keyboard traversal, et. al. still // makes sense to the user. - autoTransferFocus(false); + transferFocus(false); } ComponentPeer peer = this.peer; if (peer != null) { @@ -1491,8 +1498,8 @@ public abstract class Component implements ImageObserver, MenuContainer, synchronized (getTreeLock()) { visible = false; mixOnHiding(isLightweight()); - if (containsFocus()) { - autoTransferFocus(true); + if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabled()) { + transferFocus(true); } ComponentPeer peer = this.peer; if (peer != null) { @@ -1531,6 +1538,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @beaninfo * bound: true */ + @Transient public Color getForeground() { Color foreground = this.foreground; if (foreground != null) { @@ -1585,6 +1593,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @see #setBackground * @since JDK1.0 */ + @Transient public Color getBackground() { Color background = this.background; if (background != null) { @@ -1644,6 +1653,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @see #setFont * @since JDK1.0 */ + @Transient public Font getFont() { return getFont_NoClientCode(); } @@ -6576,12 +6586,8 @@ public abstract class Component implements ImageObserver, MenuContainer, } synchronized (getTreeLock()) { - if (isFocusOwner() - && KeyboardFocusManager.isAutoFocusTransferEnabled() - && !nextFocusHelper()) - { - KeyboardFocusManager.getCurrentKeyboardFocusManager(). - clearGlobalFocusOwner(); + if (isFocusOwner() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) { + transferFocus(true); } if (getContainer() != null && isAddNotifyComplete) { @@ -6716,8 +6722,8 @@ public abstract class Component implements ImageObserver, MenuContainer, firePropertyChange("focusable", oldFocusable, focusable); if (oldFocusable && !focusable) { - if (isFocusOwner()) { - autoTransferFocus(true); + if (isFocusOwner() && KeyboardFocusManager.isAutoFocusTransferEnabled()) { + transferFocus(true); } KeyboardFocusManager.clearMostRecentFocusOwner(this); } @@ -7371,69 +7377,6 @@ public abstract class Component implements ImageObserver, MenuContainer, } } - private void autoTransferFocus(boolean clearOnFailure) { - Component toTest = KeyboardFocusManager. - getCurrentKeyboardFocusManager().getFocusOwner(); - if (toTest != this) { - if (toTest != null) { - toTest.autoTransferFocus(clearOnFailure); - } - return; - } - - // Check if there are pending focus requests. We shouldn't do - // auto-transfer if user has already took care of this - // component becoming ineligible to hold focus. - if (!KeyboardFocusManager.isAutoFocusTransferEnabled()) { - return; - } - - // the following code will execute only if this Component is the focus - // owner - - if (!(isDisplayable() && isVisible() && isEnabled() && isFocusable())) { - doAutoTransfer(clearOnFailure); - return; - } - - toTest = getParent(); - - while (toTest != null && !(toTest instanceof Window)) { - if (!(toTest.isDisplayable() && toTest.isVisible() && - (toTest.isEnabled() || toTest.isLightweight()))) { - doAutoTransfer(clearOnFailure); - return; - } - toTest = toTest.getParent(); - } - } - private void doAutoTransfer(boolean clearOnFailure) { - if (focusLog.isLoggable(Level.FINER)) { - focusLog.log(Level.FINER, "this = " + this + ", clearOnFailure = " + clearOnFailure); - } - if (clearOnFailure) { - if (!nextFocusHelper()) { - if (focusLog.isLoggable(Level.FINER)) { - focusLog.log(Level.FINER, "clear global focus owner"); - } - KeyboardFocusManager.getCurrentKeyboardFocusManager(). - clearGlobalFocusOwner(); - } - } else { - transferFocus(); - } - } - - /** - * Transfers the focus to the next component, as though this Component were - * the focus owner. - * @see #requestFocus() - * @since JDK1.1 - */ - public void transferFocus() { - nextFocus(); - } - /** * Returns the Container which is the focus cycle root of this Component's * focus traversal cycle. Each focus traversal cycle has only a single @@ -7473,31 +7416,51 @@ public abstract class Component implements ImageObserver, MenuContainer, return (rootAncestor == container); } + Container getTraversalRoot() { + return getFocusCycleRootAncestor(); + } + + /** + * Transfers the focus to the next component, as though this Component were + * the focus owner. + * @see #requestFocus() + * @since JDK1.1 + */ + public void transferFocus() { + nextFocus(); + } + /** * @deprecated As of JDK version 1.1, * replaced by transferFocus(). */ @Deprecated public void nextFocus() { - nextFocusHelper(); + transferFocus(false); } - private boolean nextFocusHelper() { - Component toFocus = preNextFocusHelper(); + boolean transferFocus(boolean clearOnFailure) { if (focusLog.isLoggable(Level.FINER)) { - focusLog.log(Level.FINER, "toFocus = " + toFocus); + focusLog.finer("clearOnFailure = " + clearOnFailure); } - if (isFocusOwner() && toFocus == this) { - return false; + Component toFocus = getNextFocusCandidate(); + boolean res = false; + if (toFocus != null && !toFocus.isFocusOwner() && toFocus != this) { + res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_FORWARD); } - return postNextFocusHelper(toFocus, CausedFocusEvent.Cause.TRAVERSAL_FORWARD); + if (clearOnFailure && !res) { + if (focusLog.isLoggable(Level.FINER)) { + focusLog.finer("clear global focus owner"); + } + KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + } + if (focusLog.isLoggable(Level.FINER)) { + focusLog.finer("returning result: " + res); + } + return res; } - Container getTraversalRoot() { - return getFocusCycleRootAncestor(); - } - - final Component preNextFocusHelper() { + final Component getNextFocusCandidate() { Container rootAncestor = getTraversalRoot(); Component comp = this; while (rootAncestor != null && @@ -7509,18 +7472,19 @@ public abstract class Component implements ImageObserver, MenuContainer, rootAncestor = comp.getFocusCycleRootAncestor(); } if (focusLog.isLoggable(Level.FINER)) { - focusLog.log(Level.FINER, "comp = " + comp + ", root = " + rootAncestor); + focusLog.finer("comp = " + comp + ", root = " + rootAncestor); } + Component candidate = null; if (rootAncestor != null) { FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy(); Component toFocus = policy.getComponentAfter(rootAncestor, comp); if (focusLog.isLoggable(Level.FINER)) { - focusLog.log(Level.FINER, "component after is " + toFocus); + focusLog.finer("component after is " + toFocus); } if (toFocus == null) { toFocus = policy.getDefaultComponent(rootAncestor); if (focusLog.isLoggable(Level.FINER)) { - focusLog.log(Level.FINER, "default component is " + toFocus); + focusLog.finer("default component is " + toFocus); } } if (toFocus == null) { @@ -7529,23 +7493,12 @@ public abstract class Component implements ImageObserver, MenuContainer, toFocus = applet; } } - return toFocus; + candidate = toFocus; } - return null; - } - - static boolean postNextFocusHelper(Component toFocus, CausedFocusEvent.Cause cause) { - if (toFocus != null) { - if (focusLog.isLoggable(Level.FINER)) { - focusLog.log(Level.FINER, "Next component " + toFocus); - } - boolean res = toFocus.requestFocusInWindow(cause); - if (focusLog.isLoggable(Level.FINER)) { - focusLog.log(Level.FINER, "Request focus returned " + res); - } - return res; + if (focusLog.isLoggable(Level.FINER)) { + focusLog.finer("Focus transfer candidate: " + candidate); } - return false; + return candidate; } /** @@ -7555,6 +7508,10 @@ public abstract class Component implements ImageObserver, MenuContainer, * @since 1.4 */ public void transferFocusBackward() { + transferFocusBackward(false); + } + + boolean transferFocusBackward(boolean clearOnFailure) { Container rootAncestor = getTraversalRoot(); Component comp = this; while (rootAncestor != null && @@ -7565,6 +7522,7 @@ public abstract class Component implements ImageObserver, MenuContainer, comp = rootAncestor; rootAncestor = comp.getFocusCycleRootAncestor(); } + boolean res = false; if (rootAncestor != null) { FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy(); Component toFocus = policy.getComponentBefore(rootAncestor, comp); @@ -7572,9 +7530,19 @@ public abstract class Component implements ImageObserver, MenuContainer, toFocus = policy.getDefaultComponent(rootAncestor); } if (toFocus != null) { - toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_BACKWARD); + res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_BACKWARD); } } + if (!res) { + if (focusLog.isLoggable(Level.FINER)) { + focusLog.finer("clear global focus owner"); + } + KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + } + if (focusLog.isLoggable(Level.FINER)) { + focusLog.finer("returning result: " + res); + } + return res; } /** @@ -7649,6 +7617,20 @@ public abstract class Component implements ImageObserver, MenuContainer, return hasFocus(); } + /* + * Used to disallow auto-focus-transfer on disposal of the focus owner + * in the process of disposing its parent container. + */ + private boolean autoFocusTransferOnDisposal = true; + + void setAutoFocusTransferOnDisposal(boolean value) { + autoFocusTransferOnDisposal = value; + } + + boolean isAutoFocusTransferOnDisposal() { + return autoFocusTransferOnDisposal; + } + /** * Adds the specified popup menu to the component. * @param popup the popup menu to be added to the component. @@ -8310,6 +8292,8 @@ public abstract class Component implements ImageObserver, MenuContainer, private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { + changeSupportLock = new Object(); + s.defaultReadObject(); appContext = AppContext.getAppContext(); diff --git a/jdk/src/share/classes/java/awt/Container.java b/jdk/src/share/classes/java/awt/Container.java index 7eba36a1168..d79bde285f3 100644 --- a/jdk/src/share/classes/java/awt/Container.java +++ b/jdk/src/share/classes/java/awt/Container.java @@ -2660,9 +2660,26 @@ public class Container extends Component { synchronized (getTreeLock()) { int ncomponents = this.ncomponents; Component component[] = this.component; - for (int i = ncomponents-1 ; i >= 0 ; i--) { - if( component[i] != null ) - component[i].removeNotify(); + for (int i = ncomponents - 1; i >= 0; i--) { + if( component[i] != null ) { + // Fix for 6607170. + // We want to suppress focus change on disposal + // of the focused component. But because of focus + // is asynchronous, we should suppress focus change + // on every component in case it receives native focus + // in the process of disposal. + component[i].setAutoFocusTransferOnDisposal(false); + component[i].removeNotify(); + component[i].setAutoFocusTransferOnDisposal(true); + } + } + // If some of the children had focus before disposal then it still has. + // Auto-transfer focus to the next (or previous) component if auto-transfer + // is enabled. + if (containsFocus() && KeyboardFocusManager.isAutoFocusTransferEnabledFor(this)) { + if (!transferFocus(false)) { + transferFocusBackward(true); + } } if ( dispatcher != null ) { dispatcher.dispose(); diff --git a/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java b/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java index 1874d8bb3e3..928379ec286 100644 --- a/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java +++ b/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java @@ -155,12 +155,13 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { boolean clearOnFailure) { if (toFocus != vetoedComponent && toFocus.isShowing() && toFocus.isFocusable() && - toFocus.requestFocus(false, CausedFocusEvent.Cause.ROLLBACK)) { + toFocus.requestFocus(false, CausedFocusEvent.Cause.ROLLBACK)) + { return true; } else { - Component nextFocus = toFocus.preNextFocusHelper(); - if (nextFocus != vetoedComponent - && Component.postNextFocusHelper(nextFocus, CausedFocusEvent.Cause.ROLLBACK)) + Component nextFocus = toFocus.getNextFocusCandidate(); + if (nextFocus != null && nextFocus != vetoedComponent && + nextFocus.requestFocusInWindow(CausedFocusEvent.Cause.ROLLBACK)) { return true; } else if (clearOnFailure) { @@ -504,9 +505,16 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { { // we should not accept focus on such component, so reject it. dequeueKeyEvents(-1, newFocusOwner); - if (KeyboardFocusManager.isAutoFocusTransferEnabled()) - { - restoreFocus(fe, newFocusedWindow); + if (KeyboardFocusManager.isAutoFocusTransferEnabled()) { + // If FOCUS_GAINED is for a disposed component (however + // it shouldn't happen) its toplevel parent is null. In this + // case we have to try to restore focus in the current focused + // window (for the details: 6607170). + if (newFocusedWindow == null) { + restoreFocus(fe, currentFocusedWindow); + } else { + restoreFocus(fe, newFocusedWindow); + } } break; } @@ -1078,6 +1086,9 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { focusNextComponent(focusedComponent); } return; + } else if (e.getID() == KeyEvent.KEY_PRESSED) { + // Fix for 6637607: consumeNextKeyTyped should be reset. + consumeNextKeyTyped = false; } toTest = focusedComponent.getFocusTraversalKeys( diff --git a/jdk/src/share/classes/java/awt/Dimension.java b/jdk/src/share/classes/java/awt/Dimension.java index b2bad361340..c0e2c75525d 100644 --- a/jdk/src/share/classes/java/awt/Dimension.java +++ b/jdk/src/share/classes/java/awt/Dimension.java @@ -1,5 +1,5 @@ /* - * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package java.awt; import java.awt.geom.Dimension2D; +import java.beans.Transient; /** * The Dimension class encapsulates the width and @@ -165,6 +166,7 @@ public class Dimension extends Dimension2D implements java.io.Serializable { * @see java.awt.Component#getSize * @since 1.1 */ + @Transient public Dimension getSize() { return new Dimension(width, height); } diff --git a/jdk/src/share/classes/java/awt/GradientPaint.java b/jdk/src/share/classes/java/awt/GradientPaint.java index 840e7aec826..105fcd1f607 100644 --- a/jdk/src/share/classes/java/awt/GradientPaint.java +++ b/jdk/src/share/classes/java/awt/GradientPaint.java @@ -53,6 +53,7 @@ import java.awt.image.ColorModel; * * @see Paint * @see Graphics2D#setPaint + * @version 10 Feb 1997 */ public class GradientPaint implements Paint { @@ -223,19 +224,32 @@ public class GradientPaint implements Paint { } /** - * Creates and returns a context used to generate the color pattern. - * @param cm {@link ColorModel} that receives - * the Paint data. This is used only as a hint. - * @param deviceBounds the device space bounding box of the - * graphics primitive being rendered - * @param userBounds the user space bounding box of the - * graphics primitive being rendered + * Creates and returns a {@link PaintContext} used to + * generate a linear color gradient pattern. + * See the {@link Paint#createContext specification} of the + * method in the {@link Paint} interface for information + * on null parameter handling. + * + * @param cm the preferred {@link ColorModel} which represents the most convenient + * format for the caller to receive the pixel data, or {@code null} + * if there is no preference. + * @param deviceBounds the device space bounding box + * of the graphics primitive being rendered. + * @param userBounds the user space bounding box + * of the graphics primitive being rendered. * @param xform the {@link AffineTransform} from user - * space into device space - * @param hints the hints that the context object uses to choose - * between rendering alternatives - * @return the {@link PaintContext} that generates color patterns. + * space into device space. + * @param hints the set of hints that the context object can use to + * choose between rendering alternatives. + * @return the {@code PaintContext} for + * generating color patterns. + * @see Paint * @see PaintContext + * @see ColorModel + * @see Rectangle + * @see Rectangle2D + * @see AffineTransform + * @see RenderingHints */ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, diff --git a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java index ae14e8311e8..d4a9e34f57d 100644 --- a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java +++ b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java @@ -2578,6 +2578,10 @@ public abstract class KeyboardFocusManager } } + static boolean isAutoFocusTransferEnabledFor(Component comp) { + return isAutoFocusTransferEnabled() && comp.isAutoFocusTransferOnDisposal(); + } + /* * Used to process exceptions in dispatching focus event (in focusLost/focusGained callbacks). * @param ex previously caught exception that may be processed right here, or null diff --git a/jdk/src/share/classes/java/awt/LinearGradientPaint.java b/jdk/src/share/classes/java/awt/LinearGradientPaint.java index ea5a7339d16..2cf21cbe86d 100644 --- a/jdk/src/share/classes/java/awt/LinearGradientPaint.java +++ b/jdk/src/share/classes/java/awt/LinearGradientPaint.java @@ -296,7 +296,32 @@ public final class LinearGradientPaint extends MultipleGradientPaint { } /** - * {@inheritDoc} + * Creates and returns a {@link PaintContext} used to + * generate a linear color gradient pattern. + * See the {@link Paint#createContext specification} of the + * method in the {@link Paint} interface for information + * on null parameter handling. + * + * @param cm the preferred {@link ColorModel} which represents the most convenient + * format for the caller to receive the pixel data, or {@code null} + * if there is no preference. + * @param deviceBounds the device space bounding box + * of the graphics primitive being rendered. + * @param userBounds the user space bounding box + * of the graphics primitive being rendered. + * @param transform the {@link AffineTransform} from user + * space into device space. + * @param hints the set of hints that the context object can use to + * choose between rendering alternatives. + * @return the {@code PaintContext} for + * generating color patterns. + * @see Paint + * @see PaintContext + * @see ColorModel + * @see Rectangle + * @see Rectangle2D + * @see AffineTransform + * @see RenderingHints */ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, diff --git a/jdk/src/share/classes/java/awt/MenuItem.java b/jdk/src/share/classes/java/awt/MenuItem.java index 899cab485ee..54756b8f488 100644 --- a/jdk/src/share/classes/java/awt/MenuItem.java +++ b/jdk/src/share/classes/java/awt/MenuItem.java @@ -847,7 +847,7 @@ public class MenuItem extends MenuComponent implements Accessible { public String getAccessibleActionDescription(int i) { if (i == 0) { // [[[PENDING: WDW -- need to provide a localized string]]] - return new String("click"); + return "click"; } else { return null; } diff --git a/jdk/src/share/classes/java/awt/Paint.java b/jdk/src/share/classes/java/awt/Paint.java index 07c4274a08f..8e572db7eab 100644 --- a/jdk/src/share/classes/java/awt/Paint.java +++ b/jdk/src/share/classes/java/awt/Paint.java @@ -46,42 +46,58 @@ import java.awt.geom.Rectangle2D; * @see GradientPaint * @see TexturePaint * @see Graphics2D#setPaint + * @version 1.36, 06/05/07 */ public interface Paint extends Transparency { /** * Creates and returns a {@link PaintContext} used to * generate the color pattern. - * Since the ColorModel argument to createContext is only a - * hint, implementations of Paint should accept a null argument - * for ColorModel. Note that if the application does not - * prefer a specific ColorModel, the null ColorModel argument - * will give the Paint implementation full leeway in using the - * most efficient ColorModel it prefers for its raster processing. - *

    - * Since the API documentation was not specific about this in - * releases before 1.4, there may be implementations of - * Paint that do not accept a null - * ColorModel argument. - * If a developer is writing code which passes a null - * ColorModel argument to the - * createContext method of Paint - * objects from arbitrary sources it would be wise to code defensively - * by manufacturing a non-null ColorModel for those - * objects which throw a NullPointerException. - * @param cm the {@link ColorModel} that receives the - * Paint data. This is used only as a hint. + * The arguments to this method convey additional information + * about the rendering operation that may be + * used or ignored on various implementations of the {@code Paint} interface. + * A caller must pass non-{@code null} values for all of the arguments + * except for the {@code ColorModel} argument which may be {@code null} to + * indicate that no specific {@code ColorModel} type is preferred. + * Implementations of the {@code Paint} interface are allowed to use or ignore + * any of the arguments as makes sense for their function, and are + * not constrained to use the specified {@code ColorModel} for the returned + * {@code PaintContext}, even if it is not {@code null}. + * Implementations are allowed to throw {@code NullPointerException} for + * any {@code null} argument other than the {@code ColorModel} argument, + * but are not required to do so. + * + * @param cm the preferred {@link ColorModel} which represents the most convenient + * format for the caller to receive the pixel data, or {@code null} + * if there is no preference. * @param deviceBounds the device space bounding box - * of the graphics primitive being rendered + * of the graphics primitive being rendered. + * Implementations of the {@code Paint} interface + * are allowed to throw {@code NullPointerException} + * for a {@code null} {@code deviceBounds}. * @param userBounds the user space bounding box - * of the graphics primitive being rendered + * of the graphics primitive being rendered. + * Implementations of the {@code Paint} interface + * are allowed to throw {@code NullPointerException} + * for a {@code null} {@code userBounds}. * @param xform the {@link AffineTransform} from user - * space into device space - * @param hints the hint that the context object uses to - * choose between rendering alternatives - * @return the PaintContext for - * generating color patterns + * space into device space. + * Implementations of the {@code Paint} interface + * are allowed to throw {@code NullPointerException} + * for a {@code null} {@code xform}. + * @param hints the set of hints that the context object can use to + * choose between rendering alternatives. + * Implementations of the {@code Paint} interface + * are allowed to throw {@code NullPointerException} + * for a {@code null} {@code hints}. + * @return the {@code PaintContext} for + * generating color patterns. * @see PaintContext + * @see ColorModel + * @see Rectangle + * @see Rectangle2D + * @see AffineTransform + * @see RenderingHints */ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, diff --git a/jdk/src/share/classes/java/awt/Point.java b/jdk/src/share/classes/java/awt/Point.java index 73c4aa3e79f..9bbe0346955 100644 --- a/jdk/src/share/classes/java/awt/Point.java +++ b/jdk/src/share/classes/java/awt/Point.java @@ -1,5 +1,5 @@ /* - * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package java.awt; import java.awt.geom.Point2D; +import java.beans.Transient; /** * A point representing a location in {@code (x,y)} coordinate space, @@ -119,6 +120,7 @@ public class Point extends Point2D implements java.io.Serializable { * @see java.awt.Point#setLocation(int, int) * @since 1.1 */ + @Transient public Point getLocation() { return new Point(x, y); } diff --git a/jdk/src/share/classes/java/awt/RadialGradientPaint.java b/jdk/src/share/classes/java/awt/RadialGradientPaint.java index 278906bb771..494daa57d1e 100644 --- a/jdk/src/share/classes/java/awt/RadialGradientPaint.java +++ b/jdk/src/share/classes/java/awt/RadialGradientPaint.java @@ -543,7 +543,31 @@ public final class RadialGradientPaint extends MultipleGradientPaint { } /** - * {@inheritDoc} + * Creates and returns a {@link PaintContext} used to + * generate a circular radial color gradient pattern. + * See the description of the {@link Paint#createContext createContext} method + * for information on null parameter handling. + * + * @param cm the preferred {@link ColorModel} which represents the most convenient + * format for the caller to receive the pixel data, or {@code null} + * if there is no preference. + * @param deviceBounds the device space bounding box + * of the graphics primitive being rendered. + * @param userBounds the user space bounding box + * of the graphics primitive being rendered. + * @param transform the {@link AffineTransform} from user + * space into device space. + * @param hints the set of hints that the context object can use to + * choose between rendering alternatives. + * @return the {@code PaintContext} for + * generating color patterns. + * @see Paint + * @see PaintContext + * @see ColorModel + * @see Rectangle + * @see Rectangle2D + * @see AffineTransform + * @see RenderingHints */ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, diff --git a/jdk/src/share/classes/java/awt/Rectangle.java b/jdk/src/share/classes/java/awt/Rectangle.java index 1457b4d07bc..bf51092ef1f 100644 --- a/jdk/src/share/classes/java/awt/Rectangle.java +++ b/jdk/src/share/classes/java/awt/Rectangle.java @@ -1,5 +1,5 @@ /* - * Copyright 1995-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package java.awt; import java.awt.geom.Rectangle2D; +import java.beans.Transient; /** * A Rectangle specifies an area in a coordinate space that is @@ -308,6 +309,7 @@ public class Rectangle extends Rectangle2D * @see #setBounds(int, int, int, int) * @since 1.1 */ + @Transient public Rectangle getBounds() { return new Rectangle(x, y, width, height); } diff --git a/jdk/src/share/classes/java/awt/ScrollPane.java b/jdk/src/share/classes/java/awt/ScrollPane.java index f4303c0aea4..b34c978474f 100644 --- a/jdk/src/share/classes/java/awt/ScrollPane.java +++ b/jdk/src/share/classes/java/awt/ScrollPane.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ import sun.awt.ScrollPaneWheelScroller; import sun.awt.SunToolkit; import java.beans.ConstructorProperties; +import java.beans.Transient; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.IOException; @@ -390,6 +391,7 @@ public class ScrollPane extends Container implements Accessible { * @throws NullPointerException if the scrollpane does not contain * a child */ + @Transient public Point getScrollPosition() { if (ncomponents <= 0) { throw new NullPointerException("child is null"); diff --git a/jdk/src/share/classes/java/awt/TexturePaint.java b/jdk/src/share/classes/java/awt/TexturePaint.java index 7c5dd5de01e..c4054e5783a 100644 --- a/jdk/src/share/classes/java/awt/TexturePaint.java +++ b/jdk/src/share/classes/java/awt/TexturePaint.java @@ -45,6 +45,7 @@ import java.awt.image.ColorModel; * replicated Rectangle2D. * @see Paint * @see Graphics2D#setPaint + * @version 1.48, 06/05/07 */ public class TexturePaint implements Paint { @@ -93,20 +94,32 @@ public class TexturePaint implements Paint { } /** - * Creates and returns a context used to generate the color pattern. - * @param cm the {@link ColorModel} that receives the - * Paint data. This is used only as a hint. - * @param deviceBounds the device space bounding box of the graphics - * primitive being rendered - * @param userBounds the user space bounding box of the graphics - * primitive being rendered - * @param xform the {@link AffineTransform} from user space - * into device space - * @param hints a {@link RenderingHints} object that can be used to - * specify how the pattern is ultimately rendered - * @return the {@link PaintContext} used for generating color - * patterns. + * Creates and returns a {@link PaintContext} used to + * generate a tiled image pattern. + * See the {@link Paint#createContext specification} of the + * method in the {@link Paint} interface for information + * on null parameter handling. + * + * @param cm the preferred {@link ColorModel} which represents the most convenient + * format for the caller to receive the pixel data, or {@code null} + * if there is no preference. + * @param deviceBounds the device space bounding box + * of the graphics primitive being rendered. + * @param userBounds the user space bounding box + * of the graphics primitive being rendered. + * @param xform the {@link AffineTransform} from user + * space into device space. + * @param hints the set of hints that the context object can use to + * choose between rendering alternatives. + * @return the {@code PaintContext} for + * generating color patterns. + * @see Paint * @see PaintContext + * @see ColorModel + * @see Rectangle + * @see Rectangle2D + * @see AffineTransform + * @see RenderingHints */ public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, diff --git a/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java b/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java index 77eb2bcec61..57936eb6045 100644 --- a/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java +++ b/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java @@ -298,7 +298,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { while (continueLine(line)) { String nextLine = in.readLine(); if (nextLine == null) { - nextLine = new String(""); + nextLine = ""; } String loppedLine = line.substring(0, line.length() - 1); @@ -313,7 +313,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } nextLine = nextLine.substring(startIndex, nextLine.length()); - line = new String(loppedLine+nextLine); + line = loppedLine+nextLine; } // Find start of key diff --git a/jdk/src/share/classes/java/awt/dnd/DragGestureEvent.java b/jdk/src/share/classes/java/awt/dnd/DragGestureEvent.java index 9996275225c..73885d436a1 100644 --- a/jdk/src/share/classes/java/awt/dnd/DragGestureEvent.java +++ b/jdk/src/share/classes/java/awt/dnd/DragGestureEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,9 +55,19 @@ import java.io.ObjectOutputStream; * platform dependent drag initiating gesture has occurred * on the Component that it is tracking. * + * The {@code action} field of any {@code DragGestureEvent} instance should take one of the following + * values: + *

      + *
    • {@code DnDConstants.ACTION_COPY} + *
    • {@code DnDConstants.ACTION_MOVE} + *
    • {@code DnDConstants.ACTION_LINK} + *
    + * Assigning the value different from listed above will cause an unspecified behavior. + * * @see java.awt.dnd.DragGestureRecognizer * @see java.awt.dnd.DragGestureListener * @see java.awt.dnd.DragSource + * @see java.awt.dnd.DnDConstants */ public class DragGestureEvent extends EventObject { @@ -65,19 +75,25 @@ public class DragGestureEvent extends EventObject { private static final long serialVersionUID = 9080172649166731306L; /** - * Constructs a DragGestureEvent given the - * DragGestureRecognizer firing this event, - * an int representing - * the user's preferred action, a Point - * indicating the origin of the drag, and a List - * of events that comprise the gesture. + * Constructs a DragGestureEvent object given by the + * DragGestureRecognizer instance firing this event, + * an {@code act} parameter representing + * the user's preferred action, an {@code ori} parameter + * indicating the origin of the drag, and a {@code List} of + * events that comprise the gesture({@code evs} parameter). *

    * @param dgr The DragGestureRecognizer firing this event - * @param act The the user's preferred action + * @param act The user's preferred action. + * For information on allowable values, see + * the class description for {@link DragGestureEvent} * @param ori The origin of the drag * @param evs The List of events that comprise the gesture *

    - * @throws IllegalArgumentException if input parameters are {@code null} + * @throws IllegalArgumentException if any parameter equals {@code null} + * @throws IllegalArgumentException if the act parameter does not comply with + * the values given in the class + * description for {@link DragGestureEvent} + * @see java.awt.dnd.DnDConstants */ public DragGestureEvent(DragGestureRecognizer dgr, int act, Point ori, diff --git a/jdk/src/share/classes/java/awt/dnd/DropTargetEvent.java b/jdk/src/share/classes/java/awt/dnd/DropTargetEvent.java index 64d0b44d170..42fd397c701 100644 --- a/jdk/src/share/classes/java/awt/dnd/DropTargetEvent.java +++ b/jdk/src/share/classes/java/awt/dnd/DropTargetEvent.java @@ -45,10 +45,13 @@ public class DropTargetEvent extends java.util.EventObject { private static final long serialVersionUID = 2821229066521922993L; /** - * Construct a DropTargetEvent with - * a specified DropTargetContext. + * Construct a DropTargetEvent object with + * the specified DropTargetContext. *

    - * @param dtc the DropTargetContext + * @param dtc The DropTargetContext + * @throws NullPointerException if {@code dtc} equals {@code null}. + * @see #getSource() + * @see #getDropTargetContext() */ public DropTargetEvent(DropTargetContext dtc) { diff --git a/jdk/src/share/classes/java/awt/event/ActionEvent.java b/jdk/src/share/classes/java/awt/event/ActionEvent.java index 41ed7d6488c..b81ab8a8f4f 100644 --- a/jdk/src/share/classes/java/awt/event/ActionEvent.java +++ b/jdk/src/share/classes/java/awt/event/ActionEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,10 @@ import java.awt.Event; * is therefore spared the details of processing individual mouse movements * and mouse clicks, and can instead process a "meaningful" (semantic) * event like "button pressed". + *

    + * An unspecified behavior will be caused if the {@code id} parameter + * of any particular {@code ActionEvent} instance is not + * in the range from {@code ACTION_FIRST} to {@code ACTION_LAST}. * * @see ActionListener * @see Tutorial: Java 1.1 Event Model @@ -134,18 +138,22 @@ public class ActionEvent extends AWTEvent { /** * Constructs an ActionEvent object. *

    - * Note that passing in an invalid id results in - * unspecified behavior. This method throws an + * This method throws an * IllegalArgumentException if source * is null. * A null command string is legal, * but not recommended. * - * @param source the object that originated the event - * @param id an integer that identifies the event - * @param command a string that may specify a command (possibly one + * @param source The object that originated the event + * @param id An integer that identifies the event. + * For information on allowable values, see + * the class description for {@link ActionEvent} + * @param command A string that may specify a command (possibly one * of several) associated with the event * @throws IllegalArgumentException if source is null + * @see #getSource() + * @see #getID() + * @see #getActionCommand() */ public ActionEvent(Object source, int id, String command) { this(source, id, command, 0); @@ -154,19 +162,27 @@ public class ActionEvent extends AWTEvent { /** * Constructs an ActionEvent object with modifier keys. *

    - * Note that passing in an invalid id results in - * unspecified behavior. This method throws an + * This method throws an * IllegalArgumentException if source * is null. * A null command string is legal, * but not recommended. * - * @param source the object that originated the event - * @param id an integer that identifies the event - * @param command a string that may specify a command (possibly one - * of several) associated with the event - * @param modifiers the modifier keys held down during this action + * @param source The object that originated the event + * @param id An integer that identifies the event. + * For information on allowable values, see + * the class description for {@link ActionEvent} + * @param command A string that may specify a command (possibly one + * of several) associated with the event + * @param modifiers The modifier keys down during event + * (shift, ctrl, alt, meta). + * Passing negative parameter is not recommended. + * Zero value means that no modifiers were passed * @throws IllegalArgumentException if source is null + * @see #getSource() + * @see #getID() + * @see #getActionCommand() + * @see #getModifiers() */ public ActionEvent(Object source, int id, String command, int modifiers) { this(source, id, command, 0, modifiers); @@ -176,20 +192,31 @@ public class ActionEvent extends AWTEvent { * Constructs an ActionEvent object with the specified * modifier keys and timestamp. *

    - * Note that passing in an invalid id results in - * unspecified behavior. This method throws an + * This method throws an * IllegalArgumentException if source * is null. * A null command string is legal, * but not recommended. * - * @param source the object that originated the event - * @param id an integer that identifies the event - * @param command a string that may specify a command (possibly one - * of several) associated with the event - * @param when the time the event occurred - * @param modifiers the modifier keys held down during this action + * @param source The object that originated the event + * @param id An integer that identifies the event. + * For information on allowable values, see + * the class description for {@link ActionEvent} + * @param command A string that may specify a command (possibly one + * of several) associated with the event + * @param modifiers The modifier keys down during event + * (shift, ctrl, alt, meta). + * Passing negative parameter is not recommended. + * Zero value means that no modifiers were passed + * @param when A long that gives the time the event occurred. + * Passing negative or zero value + * is not recommended * @throws IllegalArgumentException if source is null + * @see #getSource() + * @see #getID() + * @see #getActionCommand() + * @see #getModifiers() + * @see #getWhen() * * @since 1.4 */ diff --git a/jdk/src/share/classes/java/awt/event/AdjustmentEvent.java b/jdk/src/share/classes/java/awt/event/AdjustmentEvent.java index b928899b2ec..590dae60ffb 100644 --- a/jdk/src/share/classes/java/awt/event/AdjustmentEvent.java +++ b/jdk/src/share/classes/java/awt/event/AdjustmentEvent.java @@ -29,7 +29,25 @@ import java.awt.Adjustable; import java.awt.AWTEvent; /** - * The adjustment event emitted by Adjustable objects. + * The adjustment event emitted by Adjustable objects like + * {@link java.awt.Scrollbar} and {@link java.awt.ScrollPane}. + * When the user changes the value of the scrolling component, + * it receives an instance of {@code AdjustmentEvent}. + *

    + * An unspecified behavior will be caused if the {@code id} parameter + * of any particular {@code AdjustmentEvent} instance is not + * in the range from {@code ADJUSTMENT_FIRST} to {@code ADJUSTMENT_LAST}. + *

    + * The {@code type} of any {@code AdjustmentEvent} instance takes one of the following + * values: + *

      + *
    • {@code UNIT_INCREMENT} + *
    • {@code UNIT_DECREMENT} + *
    • {@code BLOCK_INCREMENT} + *
    • {@code BLOCK_DECREMENT} + *
    • {@code TRACK} + *
    + * Assigning the value different from listed above will cause an unspecified behavior. * @see java.awt.Adjustable * @see AdjustmentListener * @@ -130,17 +148,24 @@ public class AdjustmentEvent extends AWTEvent { * Constructs an AdjustmentEvent object with the * specified Adjustable source, event type, * adjustment type, and value. - *

    Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

    This method throws an * IllegalArgumentException if source * is null. * - * @param source the Adjustable object where the + * @param source The Adjustable object where the * event originated - * @param id the event type - * @param type the adjustment type - * @param value the current value of the adjustment + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link AdjustmentEvent} + * @param type An integer indicating the adjustment type. + * For information on allowable values, see + * the class description for {@link AdjustmentEvent} + * @param value The current value of the adjustment * @throws IllegalArgumentException if source is null + * @see #getSource() + * @see #getID() + * @see #getAdjustmentType() + * @see #getValue() */ public AdjustmentEvent(Adjustable source, int id, int type, int value) { this(source, id, type, value, false); @@ -149,22 +174,29 @@ public class AdjustmentEvent extends AWTEvent { /** * Constructs an AdjustmentEvent object with the * specified Adjustable source, event type, adjustment type, and value. - *

    Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

    This method throws an * IllegalArgumentException if source * is null. - * - * @param source the Adjustable object where the + * @param source The Adjustable object where the * event originated - * @param id the event type - * @param type the adjustment type - * @param value the current value of the adjustment - * @param isAdjusting true if the event is one + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link AdjustmentEvent} + * @param type An integer indicating the adjustment type. + * For information on allowable values, see + * the class description for {@link AdjustmentEvent} + * @param value The current value of the adjustment + * @param isAdjusting A boolean that equals true if the event is one * of a series of multiple adjusting events, * otherwise false * @throws IllegalArgumentException if source is null * @since 1.4 + * @see #getSource() + * @see #getID() + * @see #getAdjustmentType() + * @see #getValue() + * @see #getValueIsAdjusting() */ public AdjustmentEvent(Adjustable source, int id, int type, int value, boolean isAdjusting) { super(source, id); diff --git a/jdk/src/share/classes/java/awt/event/ComponentEvent.java b/jdk/src/share/classes/java/awt/event/ComponentEvent.java index a0264b81af0..bd51d262ef7 100644 --- a/jdk/src/share/classes/java/awt/event/ComponentEvent.java +++ b/jdk/src/share/classes/java/awt/event/ComponentEvent.java @@ -52,6 +52,10 @@ import java.awt.Rectangle; * (ComponentAdapter objects implement the * ComponentListener interface.) Each such listener object * gets this ComponentEvent when the event occurs. + *

    + * An unspecified behavior will be caused if the {@code id} parameter + * of any particular {@code ComponentEvent} instance is not + * in the range from {@code COMPONENT_FIRST} to {@code COMPONENT_LAST}. * * @see ComponentAdapter * @see ComponentListener @@ -99,14 +103,17 @@ public class ComponentEvent extends AWTEvent { /** * Constructs a ComponentEvent object. - *

    Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

    This method throws an * IllegalArgumentException if source * is null. * - * @param source the Component that originated the event - * @param id an integer indicating the type of event + * @param source The Component that originated the event + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link ComponentEvent} * @throws IllegalArgumentException if source is null + * @see #getComponent() + * @see #getID() */ public ComponentEvent(Component source, int id) { super(source, id); diff --git a/jdk/src/share/classes/java/awt/event/ContainerEvent.java b/jdk/src/share/classes/java/awt/event/ContainerEvent.java index f927312ba0b..16ef5b1c92f 100644 --- a/jdk/src/share/classes/java/awt/event/ContainerEvent.java +++ b/jdk/src/share/classes/java/awt/event/ContainerEvent.java @@ -45,6 +45,10 @@ import java.awt.Component; * (ContainerAdapter objects implement the * ContainerListener interface.) Each such listener object * gets this ContainerEvent when the event occurs. + *

    + * An unspecified behavior will be caused if the {@code id} parameter + * of any particular {@code ContainerEvent} instance is not + * in the range from {@code CONTAINER_FIRST} to {@code CONTAINER_LAST}. * * @see ContainerAdapter * @see ContainerListener @@ -92,16 +96,20 @@ public class ContainerEvent extends ComponentEvent { /** * Constructs a ContainerEvent object. - *

    Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

    This method throws an * IllegalArgumentException if source * is null. * - * @param source the Component object (container) + * @param source The Component object (container) * that originated the event - * @param id an integer indicating the type of event + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link ContainerEvent} * @param child the component that was added or removed * @throws IllegalArgumentException if source is null + * @see #getContainer() + * @see #getID() + * @see #getChild() */ public ContainerEvent(Component source, int id, Component child) { super(source, id); diff --git a/jdk/src/share/classes/java/awt/event/FocusEvent.java b/jdk/src/share/classes/java/awt/event/FocusEvent.java index 188ce44b720..ec018e0126e 100644 --- a/jdk/src/share/classes/java/awt/event/FocusEvent.java +++ b/jdk/src/share/classes/java/awt/event/FocusEvent.java @@ -50,6 +50,10 @@ import sun.awt.SunToolkit; * reactivated. Both permanent and temporary focus events are delivered using * the FOCUS_GAINED and FOCUS_LOST event ids; the level may be distinguished in * the event using the isTemporary() method. + *

    + * An unspecified behavior will be caused if the {@code id} parameter + * of any particular {@code FocusEvent} instance is not + * in the range from {@code FOCUS_FIRST} to {@code FOCUS_LAST}. * * @see FocusAdapter * @see FocusListener @@ -121,18 +125,23 @@ public class FocusEvent extends ComponentEvent { * application, with a Java application in a different VM, * or with no other Component, then the opposite * Component is null. - *

    Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

    This method throws an * IllegalArgumentException if source * is null. * - * @param source the Component that originated the event - * @param id FOCUS_GAINED or FOCUS_LOST - * @param temporary true if the focus change is temporary; + * @param source The Component that originated the event + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link FocusEvent} + * @param temporary Equals true if the focus change is temporary; * false otherwise - * @param opposite the other Component involved in the focus change, + * @param opposite The other Component involved in the focus change, * or null - * @throws IllegalArgumentException if source is null + * @throws IllegalArgumentException if source equals {@code null} + * @see #getSource() + * @see #getID() + * @see #isTemporary() + * @see #getOppositeComponent() * @since 1.4 */ public FocusEvent(Component source, int id, boolean temporary, @@ -145,16 +154,20 @@ public class FocusEvent extends ComponentEvent { /** * Constructs a FocusEvent object and identifies * whether or not the change is temporary. - *

    Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

    This method throws an * IllegalArgumentException if source * is null. * - * @param source the Component that originated the event - * @param id an integer indicating the type of event - * @param temporary true if the focus change is temporary; + * @param source The Component that originated the event + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link FocusEvent} + * @param temporary Equals true if the focus change is temporary; * false otherwise - * @throws IllegalArgumentException if source is null + * @throws IllegalArgumentException if source equals {@code null} + * @see #getSource() + * @see #getID() + * @see #isTemporary() */ public FocusEvent(Component source, int id, boolean temporary) { this(source, id, temporary, null); @@ -163,14 +176,17 @@ public class FocusEvent extends ComponentEvent { /** * Constructs a FocusEvent object and identifies it * as a permanent change in focus. - *

    Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

    This method throws an * IllegalArgumentException if source * is null. * - * @param source the Component that originated the event - * @param id an integer indicating the type of event - * @throws IllegalArgumentException if source is null + * @param source The Component that originated the event + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link FocusEvent} + * @throws IllegalArgumentException if source equals {@code null} + * @see #getSource() + * @see #getID() */ public FocusEvent(Component source, int id) { this(source, id, false); diff --git a/jdk/src/share/classes/java/awt/event/HierarchyEvent.java b/jdk/src/share/classes/java/awt/event/HierarchyEvent.java index d57256a45a2..6ed6ab18edb 100644 --- a/jdk/src/share/classes/java/awt/event/HierarchyEvent.java +++ b/jdk/src/share/classes/java/awt/event/HierarchyEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ import java.awt.Container; /** * An event which indicates a change to the Component - * hierarchy to which a Component belongs. + * hierarchy to which Component belongs. *

      *
    • Hierarchy Change Events (HierarchyListener) *
        @@ -58,16 +58,30 @@ import java.awt.Container; * Container is added, removed, moved, or resized, and passed down the * hierarchy. It is also generated by a Component object when that object's * addNotify, removeNotify, show, or - * hide method is called. ANCESTOR_MOVED and ANCESTOR_RESIZED + * hide method is called. The {@code ANCESTOR_MOVED} and + * {@code ANCESTOR_RESIZED} * events are dispatched to every HierarchyBoundsListener or * HierarchyBoundsAdapter object which registered to receive * such events using the Component's addHierarchyBoundsListener * method. (HierarchyBoundsAdapter objects implement the - * HierarchyBoundsListener interface.) HIERARCHY_CHANGED events are + * HierarchyBoundsListener interface.) The {@code HIERARCHY_CHANGED} events are * dispatched to every HierarchyListener object which registered * to receive such events using the Component's addHierarchyListener * method. Each such listener object gets this HierarchyEvent * when the event occurs. + *

        + * An unspecified behavior will be caused if the {@code id} parameter + * of any particular {@code HierarchyEvent} instance is not + * in the range from {@code HIERARCHY_FIRST} to {@code HIERARCHY_LAST}. + *
        + * The {@code changeFlags} parameter of any {@code HierarchyEvent} instance takes one of the following + * values: + *

          + *
        • {@code HierarchyEvent.PARENT_CHANGED} + *
        • {@code HierarchyEvent.DISPLAYABILITY_CHANGED} + *
        • {@code HierarchyEvent.SHOWING_CHANGED} + *
        + * Assigning the value different from listed above will cause unspecified behavior. * * @author David Mendenhall * @see HierarchyListener @@ -108,20 +122,20 @@ public class HierarchyEvent extends AWTEvent { public static final int HIERARCHY_LAST = ANCESTOR_RESIZED; /** - * Indicates that the HIERARCHY_CHANGED event + * A change flag indicates that the HIERARCHY_CHANGED event * was generated by a reparenting operation. */ public static final int PARENT_CHANGED = 0x1; /** - * Indicates that the HIERARCHY_CHANGED event - * was generated due to a change in the displayability - * of the hierarchy. To discern the - * current displayability of the hierarchy, call - * Component.isDisplayable. Displayability changes occur - * in response to explicit or implicit calls to + * A change flag indicates that the HIERARCHY_CHANGED event + * was generated due to the changing of the hierarchy displayability. + * To discern the + * current displayability of the hierarchy, call the + * Component.isDisplayable method. Displayability changes occur + * in response to explicit or implicit calls of the * Component.addNotify and - * Component.removeNotify. + * Component.removeNotify methods. * * @see java.awt.Component#isDisplayable() * @see java.awt.Component#addNotify() @@ -130,15 +144,15 @@ public class HierarchyEvent extends AWTEvent { public static final int DISPLAYABILITY_CHANGED = 0x2; /** - * Indicates that the HIERARCHY_CHANGED event - * was generated due to a change in the showing state - * of the hierarchy. To discern the - * current showing state of the hierarchy, call - * Component.isShowing. Showing state changes occur + * A change flag indicates that the HIERARCHY_CHANGED event + * was generated due to the changing of the hierarchy showing state. + * To discern the + * current showing state of the hierarchy, call the + * Component.isShowing method. Showing state changes occur * when either the displayability or visibility of the * hierarchy occurs. Visibility changes occur in response to explicit - * or implicit calls to Component.show and - * Component.hide. + * or implicit calls of the Component.show and + * Component.hide methods. * * @see java.awt.Component#isShowing() * @see java.awt.Component#addNotify() @@ -155,20 +169,26 @@ public class HierarchyEvent extends AWTEvent { /** * Constructs an HierarchyEvent object to identify a * change in the Component hierarchy. - *

        Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

        This method throws an * IllegalArgumentException if source * is null. * - * @param source the Component object that + * @param source The Component object that * originated the event - * @param id an integer indicating the type of event - * @param changed the Component at the top of + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link HierarchyEvent} + * @param changed The Component at the top of * the hierarchy which was changed - * @param changedParent the parent of changed; this + * @param changedParent The parent of the changed component. + * This * may be the parent before or after the * change, depending on the type of change - * @throws IllegalArgumentException if source is null + * @throws IllegalArgumentException if source is {@code null} + * @see #getSource() + * @see #getID() + * @see #getChanged() + * @see #getChangedParent() */ public HierarchyEvent(Component source, int id, Component changed, Container changedParent) { @@ -180,23 +200,32 @@ public class HierarchyEvent extends AWTEvent { /** * Constructs an HierarchyEvent object to identify * a change in the Component hierarchy. - *

        Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

        This method throws an * IllegalArgumentException if source * is null. * - * @param source the Component object that + * @param source The Component object that * originated the event - * @param id an integer indicating the type of event - * @param changed the Component at the top + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link HierarchyEvent} + * @param changed The Component at the top * of the hierarchy which was changed - * @param changedParent the parent of changed; this + * @param changedParent The parent of the changed component. + * This * may be the parent before or after the * change, depending on the type of change - * @param changeFlags a bitmask which indicates the type(s) of - * HIERARCHY_CHANGED events - * represented in this event object + * @param changeFlags A bitmask which indicates the type(s) of + * the HIERARCHY_CHANGED events + * represented in this event object. + * For information on allowable values, see + * the class description for {@link HierarchyEvent} * @throws IllegalArgumentException if source is null + * @see #getSource() + * @see #getID() + * @see #getChanged() + * @see #getChangedParent() + * @see #getChangeFlags() */ public HierarchyEvent(Component source, int id, Component changed, Container changedParent, long changeFlags) { diff --git a/jdk/src/share/classes/java/awt/event/InputEvent.java b/jdk/src/share/classes/java/awt/event/InputEvent.java index 45b1f87e40e..0c35c2be464 100644 --- a/jdk/src/share/classes/java/awt/event/InputEvent.java +++ b/jdk/src/share/classes/java/awt/event/InputEvent.java @@ -208,17 +208,32 @@ public abstract class InputEvent extends ComponentEvent { /** * Constructs an InputEvent object with the specified source component, * modifiers, and type. - *

        Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

        This method throws an * IllegalArgumentException if source * is null. * * @param source the object where the event originated - * @param id the event type - * @param when the time the event occurred - * @param modifiers represents the modifier keys and mouse buttons down - * while the event occurred + * @param id the integer that identifies the event type. + * It is allowed to pass as parameter any value that + * allowed for some subclass of {@code InputEvent} class. + * Passing in the value different from those values result + * in unspecified behavior + * @param when a long int that gives the time the event occurred. + * Passing negative or zero value + * is not recommended + * @param modifiers the modifier keys down during event (e.g. shift, ctrl, + * alt, meta) + * Passing negative parameter is not recommended. + * Zero value means no modifiers. + * Either extended _DOWN_MASK or old _MASK modifiers + * should be used, but both models should not be mixed + * in one event. Use of the extended modifiers is + * preferred * @throws IllegalArgumentException if source is null + * @see #getSource() + * @see #getID() + * @see #getWhen() + * @see #getModifiers() */ InputEvent(Component source, int id, long when, int modifiers) { super(source, id); @@ -285,7 +300,8 @@ public abstract class InputEvent extends ComponentEvent { } /** - * Returns the timestamp of when this event occurred. + * Returns the difference in milliseconds between the timestamp of when this event occurred and + * midnight, January 1, 1970 UTC. */ public long getWhen() { return when; @@ -358,7 +374,12 @@ public abstract class InputEvent extends ComponentEvent { * Returns a String describing the extended modifier keys and * mouse buttons, such as "Shift", "Button1", or "Ctrl+Shift". * These strings can be localized by changing the - * awt.properties file. + * awt.properties file. + *

        + * Note that passing negative parameter is incorrect, + * and will cause the returning an unspecified string. + * Zero parameter means that no modifiers were passed and will + * cause the returning an empty string. * * @param modifiers a modifier mask describing the extended * modifier keys and mouse buttons for the event diff --git a/jdk/src/share/classes/java/awt/event/InvocationEvent.java b/jdk/src/share/classes/java/awt/event/InvocationEvent.java index 705f87a12e4..0959a86cb35 100644 --- a/jdk/src/share/classes/java/awt/event/InvocationEvent.java +++ b/jdk/src/share/classes/java/awt/event/InvocationEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,10 @@ import java.awt.AWTEvent; * can use this fact to write replacement functions for invokeLater * and invokeAndWait without writing special-case code * in any AWTEventListener objects. + *

        + * An unspecified behavior will be caused if the {@code id} parameter + * of any particular {@code InvocationEvent} instance is not + * in the range from {@code INVOCATION_FIRST} to {@code INVOCATION_LAST}. * * @author Fred Ecks * @author David Mendenhall @@ -123,12 +127,13 @@ public class InvocationEvent extends AWTEvent implements ActiveEvent { *

        This method throws an IllegalArgumentException * if source is null. * - * @param source the Object that originated the event - * @param runnable the Runnable whose run + * @param source The Object that originated the event + * @param runnable The Runnable whose run * method will be executed * @throws IllegalArgumentException if source is null * - * @see #InvocationEvent(Object, Runnable, Object, boolean) + * @see #getSource() + * @see #InvocationEvent(Object, Runnable, Object, boolean) */ public InvocationEvent(Object source, Runnable runnable) { this(source, runnable, null, false); @@ -147,15 +152,15 @@ public class InvocationEvent extends AWTEvent implements ActiveEvent { *

        This method throws an IllegalArgumentException * if source is null. * - * @param source the Object that originated + * @param source The Object that originated * the event - * @param runnable the Runnable whose + * @param runnable The Runnable whose * run method will be * executed - * @param notifier the Object whose notifyAll + * @param notifier The {@code Object} whose notifyAll * method will be called after * Runnable.run has returned - * @param catchThrowables specifies whether dispatch + * @param catchThrowables Specifies whether dispatch * should catch Throwable when executing * the Runnable's run * method, or should instead propagate those @@ -163,6 +168,7 @@ public class InvocationEvent extends AWTEvent implements ActiveEvent { * dispatch loop * @throws IllegalArgumentException if source is null * + * @see #getSource() * @see #InvocationEvent(Object, int, Runnable, Object, boolean) */ public InvocationEvent(Object source, Runnable runnable, Object notifier, @@ -176,26 +182,29 @@ public class InvocationEvent extends AWTEvent implements ActiveEvent { * method when dispatched. If notifier is non-null, * notifyAll will be called on it * immediately after run returns. - *

        Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

        This method throws an * IllegalArgumentException if source * is null. * - * @param source the Object that originated + * @param source The Object that originated * the event - * @param id the ID for the event - * @param runnable the Runnable whose + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link InvocationEvent} + * @param runnable The Runnable whose * run method will be executed - * @param notifier the Object whose notifyAll + * @param notifier The Object whose notifyAll * method will be called after * Runnable.run has returned - * @param catchThrowables specifies whether dispatch + * @param catchThrowables Specifies whether dispatch * should catch Throwable when executing the * Runnable's run * method, or should instead propagate those * Throwables to the EventDispatchThread's * dispatch loop * @throws IllegalArgumentException if source is null + * @see #getSource() + * @see #getID() */ protected InvocationEvent(Object source, int id, Runnable runnable, Object notifier, boolean catchThrowables) { diff --git a/jdk/src/share/classes/java/awt/event/ItemEvent.java b/jdk/src/share/classes/java/awt/event/ItemEvent.java index 7b37f3ed0c4..156b0614618 100644 --- a/jdk/src/share/classes/java/awt/event/ItemEvent.java +++ b/jdk/src/share/classes/java/awt/event/ItemEvent.java @@ -41,6 +41,18 @@ import java.awt.ItemSelectable; * spared the details of processing individual mouse movements and mouse * clicks, and can instead process a "meaningful" (semantic) event like * "item selected" or "item deselected". + *

        + * An unspecified behavior will be caused if the {@code id} parameter + * of any particular {@code ItemEvent} instance is not + * in the range from {@code ITEM_FIRST} to {@code ITEM_LAST}. + *

        + * The {@code stateChange} of any {@code ItemEvent} instance takes one of the following + * values: + *

          + *
        • {@code ItemEvent.SELECTED} + *
        • {@code ItemEvent.DESELECTED} + *
        + * Assigning the value different from listed above will cause an unspecified behavior. * * @author Carl Quinn * @@ -101,19 +113,24 @@ public class ItemEvent extends AWTEvent { /** * Constructs an ItemEvent object. - *

        Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

        This method throws an * IllegalArgumentException if source * is null. * - * @param source the ItemSelectable object + * @param source The ItemSelectable object * that originated the event - * @param id an integer that identifies the event type - * @param item an object -- the item affected by the event - * @param stateChange - * an integer that indicates whether the item was - * selected or deselected + * @param id The integer that identifies the event type. + * For information on allowable values, see + * the class description for {@link ItemEvent} + * @param item An object -- the item affected by the event + * @param stateChange An integer that indicates whether the item was + * selected or deselected. + * For information on allowable values, see + * the class description for {@link ItemEvent} * @throws IllegalArgumentException if source is null + * @see #getItemSelectable() + * @see #getID() + * @see #getStateChange() */ public ItemEvent(ItemSelectable source, int id, Object item, int stateChange) { super(source, id); diff --git a/jdk/src/share/classes/java/awt/event/KeyEvent.java b/jdk/src/share/classes/java/awt/event/KeyEvent.java index 556ceb28b2b..03967570297 100644 --- a/jdk/src/share/classes/java/awt/event/KeyEvent.java +++ b/jdk/src/share/classes/java/awt/event/KeyEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,6 +128,10 @@ import java.io.ObjectInputStream; * (VK_ENTER, VK_BACK_SPACE, and VK_TAB), do not rely on the values of the VK_ * constants. Sun reserves the right to change these values as needed * to accomodate a wider range of keyboards in the future. + *

        + * An unspecified behavior will be caused if the {@code id} parameter + * of any particular {@code KeyEvent} instance is not + * in the range from {@code KEY_FIRST} to {@code KEY_LAST}. * * @author Carl Quinn * @author Amy Fowler @@ -914,27 +918,32 @@ public class KeyEvent extends InputEvent { /** * Constructs a KeyEvent object. - *

        Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

        This method throws an * IllegalArgumentException if source * is null. * - * @param source the Component that originated the event - * @param id an integer identifying the type of event - * @param when a long integer that specifies the time the event - * occurred - * @param modifiers the modifier keys down during event (shift, ctrl, - * alt, meta) - * Either extended _DOWN_MASK or old _MASK modifiers - * should be used, but both models should not be mixed - * in one event. Use of the extended modifiers is - * preferred. - * @param keyCode the integer code for an actual key, or VK_UNDEFINED + * @param source The Component that originated the event + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link KeyEvent} + * @param when A long integer that specifies the time the event + * occurred. + * Passing negative or zero value + * is not recommended + * @param modifiers The modifier keys down during event (shift, ctrl, + * alt, meta). + * Passing negative value + * is not recommended. + * Zero value means that no modifiers were passed. + * Use either an extended _DOWN_MASK or old _MASK modifiers, + * however do not mix models in the one event. + * The extended modifiers are preferred for using + * @param keyCode The integer code for an actual key, or VK_UNDEFINED * (for a key-typed event) - * @param keyChar the Unicode character generated by this event, or + * @param keyChar The Unicode character generated by this event, or * CHAR_UNDEFINED (for key-pressed and key-released * events which do not map to a valid Unicode character) - * @param keyLocation identifies the key location. The only legal + * @param keyLocation Identifies the key location. The only legal * values are KEY_LOCATION_UNKNOWN, * KEY_LOCATION_STANDARD, KEY_LOCATION_LEFT, * KEY_LOCATION_RIGHT, and KEY_LOCATION_NUMPAD. @@ -948,6 +957,13 @@ public class KeyEvent extends InputEvent { * or if keyLocation is not one of the legal * values enumerated above. * @throws IllegalArgumentException if source is null + * @see #getSource() + * @see #getID() + * @see #getWhen() + * @see #getModifiers() + * @see #getKeyCode() + * @see #getKeyChar() + * @see #getKeyLocation() * @since 1.4 */ public KeyEvent(Component source, int id, long when, int modifiers, @@ -982,24 +998,29 @@ public class KeyEvent extends InputEvent { /** * Constructs a KeyEvent object. - *

        Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

        This method throws an * IllegalArgumentException if source * is null. * - * @param source the Component that originated the event - * @param id an integer identifying the type of event - * @param when a long integer that specifies the time the event - * occurred - * @param modifiers the modifier keys down during event (shift, ctrl, - * alt, meta) - * Either extended _DOWN_MASK or old _MASK modifiers - * should be used, but both models should not be mixed - * in one event. Use of the extended modifiers is - * preferred. - * @param keyCode the integer code for an actual key, or VK_UNDEFINED + * @param source The Component that originated the event + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link KeyEvent} + * @param when A long integer that specifies the time the event + * occurred. + * Passing negative or zero value + * is not recommended + * @param modifiers The modifier keys down during event (shift, ctrl, + * alt, meta). + * Passing negative value + * is not recommended. + * Zero value means that no modifiers were passed. + * Use either an extended _DOWN_MASK or old _MASK modifiers, + * however do not mix models in the one event. + * The extended modifiers are preferred for using + * @param keyCode The integer code for an actual key, or VK_UNDEFINED * (for a key-typed event) - * @param keyChar the Unicode character generated by this event, or + * @param keyChar The Unicode character generated by this event, or * CHAR_UNDEFINED (for key-pressed and key-released * events which do not map to a valid Unicode character) * @throws IllegalArgumentException if id is @@ -1008,6 +1029,12 @@ public class KeyEvent extends InputEvent { * KEY_TYPED and keyCode is not * VK_UNDEFINED * @throws IllegalArgumentException if source is null + * @see #getSource() + * @see #getID() + * @see #getWhen() + * @see #getModifiers() + * @see #getKeyCode() + * @see #getKeyChar() */ public KeyEvent(Component source, int id, long when, int modifiers, int keyCode, char keyChar) { diff --git a/jdk/src/share/classes/java/awt/event/MouseEvent.java b/jdk/src/share/classes/java/awt/event/MouseEvent.java index d546be5ec8e..a9aed6add19 100644 --- a/jdk/src/share/classes/java/awt/event/MouseEvent.java +++ b/jdk/src/share/classes/java/awt/event/MouseEvent.java @@ -159,6 +159,11 @@ import java.awt.IllegalComponentStateException; * The reported coordinates for mouse drag events are clipped to fit within the * bounds of the virtual device associated with the Component. *

      + *

      + * An unspecified behavior will be caused if the {@code id} parameter + * of any particular {@code MouseEvent} instance is not + * in the range from {@code MOUSE_FIRST} to {@code MOUSE_LAST}-1 + * ({@code MOUSE_WHEEL} is not acceptable). * * @author Carl Quinn * @@ -418,8 +423,7 @@ public class MouseEvent extends InputEvent { * specified source component, * type, modifiers, coordinates, and click count. *

      - * Note that passing in an invalid id results in - * unspecified behavior. Creating an invalid event (such + * Creating an invalid event (such * as by using more than one of the old _MASKs, or modifier/button * values which don't match) results in unspecified behavior. * An invocation of the form @@ -435,28 +439,44 @@ public class MouseEvent extends InputEvent { * IllegalArgumentException if source * is null. * - * @param source the Component that originated the event - * @param id the integer that identifies the event - * @param when a long int that gives the time the event occurred - * @param modifiers the modifier keys down during event (e.g. shift, ctrl, + * @param source The Component that originated the event + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link MouseEvent} + * @param when A long integer that gives the time the event occurred. + * Passing negative or zero value + * is not recommended + * @param modifiers The modifier keys down during event (e.g. shift, ctrl, * alt, meta) - * Either extended _DOWN_MASK or old _MASK modifiers - * should be used, but both models should not be mixed - * in one event. Use of the extended modifiers is - * preferred. - * @param x the horizontal x coordinate for the mouse location - * @param y the vertical y coordinate for the mouse location - * @param clickCount the number of mouse clicks associated with event - * @param popupTrigger a boolean, true if this event is a trigger for a - * popup menu - * @param button which of the mouse buttons has changed state. - * NOBUTTON, - * BUTTON1, - * BUTTON2 or - * BUTTON3. + * Passing negative parameter + * is not recommended. + * Zero value means that no modifiers were passed. + * Use either an extended _DOWN_MASK or old _MASK modifiers, + * however do not mix models in the one event. + * The extended modifiers are preferred for using + * @param x The horizontal x coordinate for the mouse location. + * It is allowed to pass negative values + * @param y The vertical y coordinate for the mouse location. + * It is allowed to pass negative values + * @param clickCount The number of mouse clicks associated with event. + * Passing negative value + * is not recommended + * @param popupTrigger A boolean that equals {@code true} if this event + * is a trigger for a popup menu + * @param button An integer that indicates, which of the mouse buttons has + * changed its state * @throws IllegalArgumentException if an invalid button * value is passed in * @throws IllegalArgumentException if source is null + * @see #getSource() + * @see #getID() + * @see #getWhen() + * @see #getModifiers() + * @see #getX() + * @see #getY() + * @see #getClickCount() + * @see #isPopupTrigger() + * @see #getButton() * @since 1.4 */ public MouseEvent(Component source, int id, long when, int modifiers, @@ -479,8 +499,6 @@ public class MouseEvent extends InputEvent { * Constructs a MouseEvent object with the * specified source component, * type, modifiers, coordinates, and click count. - *

      Note that passing in an invalid id results in - * unspecified behavior. * An invocation of the form * MouseEvent(source, id, when, modifiers, x, y, clickCount, popupTrigger) * behaves in exactly the same way as the invocation @@ -493,21 +511,39 @@ public class MouseEvent extends InputEvent { * This method throws an IllegalArgumentException * if source is null. * - * @param source the Component that originated the event - * @param id the integer that identifies the event - * @param when a long int that gives the time the event occurred - * @param modifiers the modifier keys down during event (e.g. shift, ctrl, + * @param source The Component that originated the event + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link MouseEvent} + * @param when A long integer that gives the time the event occurred. + * Passing negative or zero value + * is not recommended + * @param modifiers The modifier keys down during event (e.g. shift, ctrl, * alt, meta) - * Either extended _DOWN_MASK or old _MASK modifiers - * should be used, but both models should not be mixed - * in one event. Use of the extended modifiers is - * preferred. - * @param x the horizontal x coordinate for the mouse location - * @param y the vertical y coordinate for the mouse location - * @param clickCount the number of mouse clicks associated with event - * @param popupTrigger a boolean, true if this event is a trigger for a - * popup menu + * Passing negative parameter + * is not recommended. + * Zero value means that no modifiers were passed. + * Use either an extended _DOWN_MASK or old _MASK modifiers, + * however do not mix models in the one event. + * The extended modifiers are preferred for using + * @param x The horizontal x coordinate for the mouse location. + * It is allowed to pass negative values + * @param y The vertical y coordinate for the mouse location. + * It is allowed to pass negative values + * @param clickCount The number of mouse clicks associated with event. + * Passing negative value + * is not recommended + * @param popupTrigger A boolean that equals {@code true} if this event + * is a trigger for a popup menu * @throws IllegalArgumentException if source is null + * @see #getSource() + * @see #getID() + * @see #getWhen() + * @see #getModifiers() + * @see #getX() + * @see #getY() + * @see #getClickCount() + * @see #isPopupTrigger() */ public MouseEvent(Component source, int id, long when, int modifiers, int x, int y, int clickCount, boolean popupTrigger) { @@ -520,8 +556,7 @@ public class MouseEvent extends InputEvent { * specified source component, * type, modifiers, coordinates, absolute coordinates, and click count. *

      - * Note that passing in an invalid id results in - * unspecified behavior. Creating an invalid event (such + * Creating an invalid event (such * as by using more than one of the old _MASKs, or modifier/button * values which don't match) results in unspecified behavior. * Even if inconsistent values for relative and absolute coordinates are @@ -531,30 +566,50 @@ public class MouseEvent extends InputEvent { * IllegalArgumentException if source * is null. * - * @param source the Component that originated the event - * @param id the integer that identifies the event - * @param when a long int that gives the time the event occurred - * @param modifiers the modifier keys down during event (e.g. shift, ctrl, + * @param source The Component that originated the event + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link MouseEvent} + * @param when A long integer that gives the time the event occurred. + * Passing negative or zero value + * is not recommended + * @param modifiers The modifier keys down during event (e.g. shift, ctrl, * alt, meta) - * Either extended _DOWN_MASK or old _MASK modifiers - * should be used, but both models should not be mixed - * in one event. Use of the extended modifiers is - * preferred. - * @param x the horizontal x coordinate for the mouse location - * @param y the vertical y coordinate for the mouse location - * @param xAbs the absolute horizontal x coordinate for the mouse location - * @param yAbs the absolute vertical y coordinate for the mouse location - * @param clickCount the number of mouse clicks associated with event - * @param popupTrigger a boolean, true if this event is a trigger for a - * popup menu - * @param button which of the mouse buttons has changed state. - * NOBUTTON, - * BUTTON1, - * BUTTON2 or - * BUTTON3. + * Passing negative parameter + * is not recommended. + * Zero value means that no modifiers were passed. + * Use either an extended _DOWN_MASK or old _MASK modifiers, + * however do not mix models in the one event. + * The extended modifiers are preferred for using + * @param x The horizontal x coordinate for the mouse location. + * It is allowed to pass negative values + * @param y The vertical y coordinate for the mouse location. + * It is allowed to pass negative values + * @param xAbs The absolute horizontal x coordinate for the mouse location + * It is allowed to pass negative values + * @param yAbs The absolute vertical y coordinate for the mouse location + * It is allowed to pass negative values + * @param clickCount The number of mouse clicks associated with event. + * Passing negative value + * is not recommended + * @param popupTrigger A boolean that equals {@code true} if this event + * is a trigger for a popup menu + * @param button An integer that indicates, which of the mouse buttons has + * changed its state * @throws IllegalArgumentException if an invalid button * value is passed in * @throws IllegalArgumentException if source is null + * @see #getSource() + * @see #getID() + * @see #getWhen() + * @see #getModifiers() + * @see #getX() + * @see #getY() + * @see #getXOnScreen() + * @see #getYOnScreen() + * @see #getClickCount() + * @see #isPopupTrigger() + * @see #getButton() * @since 1.6 */ public MouseEvent(Component source, int id, long when, int modifiers, @@ -675,21 +730,26 @@ public class MouseEvent extends InputEvent { } /** - * Returns a String describing the modifier keys and + * Returns a String instance describing the modifier keys and * mouse buttons that were down during the event, such as "Shift", * or "Ctrl+Shift". These strings can be localized by changing * the awt.properties file. *

      - * Note that InputEvent.ALT_MASK and - * InputEvent.BUTTON2_MASK have the same value, - * so the string "Alt" is returned for both modifiers. Likewise, - * InputEvent.META_MASK and - * InputEvent.BUTTON3_MASK have the same value, - * so the string "Meta" is returned for both modifiers. + * Note that the InputEvent.ALT_MASK and + * InputEvent.BUTTON2_MASK have equal values, + * so the "Alt" string is returned for both modifiers. Likewise, + * the InputEvent.META_MASK and + * InputEvent.BUTTON3_MASK have equal values, + * so the "Meta" string is returned for both modifiers. + *

      + * Note that passing negative parameter is incorrect, + * and will cause the returning an unspecified string. + * Zero parameter means that no modifiers were passed and will + * cause the returning an empty string. * - * @param modifiers a modifier mask describing the modifier keys and + * @param modifiers A modifier mask describing the modifier keys and * mouse buttons that were down during the event - * @return string a text description of the combination of modifier + * @return string string text description of the combination of modifier * keys and mouse buttons that were down during the event * @see InputEvent#getModifiersExText(int) * @since 1.4 diff --git a/jdk/src/share/classes/java/awt/event/MouseWheelEvent.java b/jdk/src/share/classes/java/awt/event/MouseWheelEvent.java index a1c5b2ebb91..19c46fe7f41 100644 --- a/jdk/src/share/classes/java/awt/event/MouseWheelEvent.java +++ b/jdk/src/share/classes/java/awt/event/MouseWheelEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/jdk/src/share/classes/java/awt/event/PaintEvent.java b/jdk/src/share/classes/java/awt/event/PaintEvent.java index beafed7f8eb..1826cce3578 100644 --- a/jdk/src/share/classes/java/awt/event/PaintEvent.java +++ b/jdk/src/share/classes/java/awt/event/PaintEvent.java @@ -36,6 +36,10 @@ import java.awt.Rectangle; * designed to be used with the Event Listener model; programs * should continue to override paint/update methods in order * render themselves properly. + *

      + * An unspecified behavior will be caused if the {@code id} parameter + * of any particular {@code PaintEvent} instance is not + * in the range from {@code PAINT_FIRST} to {@code PAINT_LAST}. * * @author Amy Fowler * @since 1.1 @@ -82,15 +86,19 @@ public class PaintEvent extends ComponentEvent { /** * Constructs a PaintEvent object with the specified * source component and type. - *

      Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

      This method throws an * IllegalArgumentException if source * is null. * - * @param source the object where the event originated - * @param id the event type - * @param updateRect the rectangle area which needs to be repainted + * @param source The object where the event originated + * @param id The integer that identifies the event type. + * For information on allowable values, see + * the class description for {@link PaintEvent} + * @param updateRect The rectangle area which needs to be repainted * @throws IllegalArgumentException if source is null + * @see #getSource() + * @see #getID() + * @see #getUpdateRect() */ public PaintEvent(Component source, int id, Rectangle updateRect) { super(source, id); diff --git a/jdk/src/share/classes/java/awt/event/TextEvent.java b/jdk/src/share/classes/java/awt/event/TextEvent.java index a8636dc0d78..36b62d40d01 100644 --- a/jdk/src/share/classes/java/awt/event/TextEvent.java +++ b/jdk/src/share/classes/java/awt/event/TextEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,12 +38,15 @@ import java.awt.AWTEvent; * this TextEvent when the event occurs. The listener is * spared the details of processing individual mouse movements and key strokes * Instead, it can process a "meaningful" (semantic) event like "text changed". + *

      + * An unspecified behavior will be caused if the {@code id} parameter + * of any particular {@code TextEvent} instance is not + * in the range from {@code TEXT_FIRST} to {@code TEXT_LAST}. * * @author Georges Saab * * @see java.awt.TextComponent * @see TextListener - * @see Tutorial: Writing a Text Listener * * @since 1.1 */ @@ -72,15 +75,18 @@ public class TextEvent extends AWTEvent { /** * Constructs a TextEvent object. - *

      Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

      This method throws an * IllegalArgumentException if source * is null. * - * @param source the (TextComponent) object that + * @param source The (TextComponent) object that * originated the event - * @param id an integer that identifies the event type + * @param id An integer that identifies the event type. + * For information on allowable values, see + * the class description for {@link TextEvent} * @throws IllegalArgumentException if source is null + * @see #getSource() + * @see #getID() */ public TextEvent(Object source, int id) { super(source, id); diff --git a/jdk/src/share/classes/java/awt/event/TextListener.java b/jdk/src/share/classes/java/awt/event/TextListener.java index cbb615a4606..99e52c2e4e1 100644 --- a/jdk/src/share/classes/java/awt/event/TextListener.java +++ b/jdk/src/share/classes/java/awt/event/TextListener.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,6 @@ import java.util.EventListener; * @author Georges Saab * * @see TextEvent - * @see Tutorial: Writing a Text Listener * * @since 1.1 */ diff --git a/jdk/src/share/classes/java/awt/event/WindowEvent.java b/jdk/src/share/classes/java/awt/event/WindowEvent.java index 090ba017f55..a662aab92e4 100644 --- a/jdk/src/share/classes/java/awt/event/WindowEvent.java +++ b/jdk/src/share/classes/java/awt/event/WindowEvent.java @@ -41,6 +41,10 @@ import sun.awt.SunToolkit; * (WindowAdapter objects implement the * WindowListener interface.) Each such listener object * gets this WindowEvent when the event occurs. + *

      + * An unspecified behavior will be caused if the {@code id} parameter + * of any particular {@code WindowEvent} instance is not + * in the range from {@code WINDOW_FIRST} to {@code WINDOW_LAST}. * * @author Carl Quinn * @author Amy Fowler @@ -170,20 +174,27 @@ public class WindowEvent extends ComponentEvent { /** * Constructs a WindowEvent object. - *

      Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

      This method throws an * IllegalArgumentException if source * is null. * - * @param source the Window object + * @param source The Window object * that originated the event - * @param id an integer indicating the type of event. - * @param opposite the other window involved in the focus or activation + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link WindowEvent} + * @param opposite The other window involved in the focus or activation * change, or null - * @param oldState previous state of the window for window state - * change event - * @param newState new state of the window for window state change event + * @param oldState Previous state of the window for window state change event. + * See {@code #getOldState()} for allowable values + * @param newState New state of the window for window state change event. + * See {@code #getNewState()} for allowable values * @throws IllegalArgumentException if source is null + * @see #getWindow() + * @see #getID() + * @see #getOppositeWindow() + * @see #getOldState() + * @see #getNewState() * @since 1.4 */ public WindowEvent(Window source, int id, Window opposite, @@ -209,24 +220,28 @@ public class WindowEvent extends ComponentEvent { * If this focus change occurs with a native application, with a * Java application in a different VM, or with no other * Window, then the opposite Window is null. - *

      Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

      This method throws an * IllegalArgumentException if source * is null. * - * @param source the Window object that + * @param source The Window object that * originated the event - * @param id WINDOW_ACTIVATED, - * WINDOW_DEACTIVATED, - * WINDOW_GAINED_FOCUS, - * or WINDOW_LOST_FOCUS. It is - * expected that this constructor will not be used for - * other WindowEvent types because the - * opposite Window of such events - * will always be null - * @param opposite the other Window involved in the + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link WindowEvent}. + * It is expected that this constructor will not + * be used for other then + * {@code WINDOW_ACTIVATED},{@code WINDOW_DEACTIVATED}, + * {@code WINDOW_GAINED_FOCUS}, or {@code WINDOW_LOST_FOCUS}. + * {@code WindowEvent} types, + * because the opposite Window of other event types + * will always be {@code null}. + * @param opposite The other Window involved in the * focus or activation change, or null * @throws IllegalArgumentException if source is null + * @see #getWindow() + * @see #getID() + * @see #getOppositeWindow() * @since 1.4 */ public WindowEvent(Window source, int id, Window opposite) { @@ -236,21 +251,30 @@ public class WindowEvent extends ComponentEvent { /** * Constructs a WindowEvent object with the specified * previous and new window states. - *

      Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

      This method throws an * IllegalArgumentException if source * is null. * - * @param source the Window object + * @param source The Window object * that originated the event - * @param id WINDOW_STATE_CHANGED event type. + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link WindowEvent}. * It is expected that this constructor will not - * be used for other WindowEvent + * be used for other then + * {@code WINDOW_STATE_CHANGED} + * {@code WindowEvent} * types, because the previous and new window * states are meaningless for other event types. - * @param oldState an integer representing the previous window state - * @param newState an integer representing the new window state + * @param oldState An integer representing the previous window state. + * See {@code #getOldState()} for allowable values + * @param newState An integer representing the new window state. + * See {@code #getNewState()} for allowable values * @throws IllegalArgumentException if source is null + * @see #getWindow() + * @see #getID() + * @see #getOldState() + * @see #getNewState() * @since 1.4 */ public WindowEvent(Window source, int id, int oldState, int newState) { @@ -259,14 +283,17 @@ public class WindowEvent extends ComponentEvent { /** * Constructs a WindowEvent object. - *

      Note that passing in an invalid id results in - * unspecified behavior. This method throws an + *

      This method throws an * IllegalArgumentException if source * is null. * - * @param source the Window object that originated the event - * @param id an integer indicating the type of event + * @param source The Window object that originated the event + * @param id An integer indicating the type of event. + * For information on allowable values, see + * the class description for {@link WindowEvent}. * @throws IllegalArgumentException if source is null + * @see #getWindow() + * @see #getID() */ public WindowEvent(Window source, int id) { this(source, id, null, 0, 0); diff --git a/jdk/src/share/classes/java/awt/geom/RectangularShape.java b/jdk/src/share/classes/java/awt/geom/RectangularShape.java index 9e733e90c2c..32cbbe678f2 100644 --- a/jdk/src/share/classes/java/awt/geom/RectangularShape.java +++ b/jdk/src/share/classes/java/awt/geom/RectangularShape.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package java.awt.geom; import java.awt.Shape; import java.awt.Rectangle; +import java.beans.Transient; /** * RectangularShape is the base class for a number of @@ -171,6 +172,7 @@ public abstract class RectangularShape implements Shape, Cloneable { * @see #setFrame(Rectangle2D) * @since 1.2 */ + @Transient public Rectangle2D getFrame() { return new Rectangle2D.Double(getX(), getY(), getWidth(), getHeight()); } diff --git a/jdk/src/share/classes/java/awt/im/InputContext.java b/jdk/src/share/classes/java/awt/im/InputContext.java index 9e5d7fa3623..0da7fcb42ff 100644 --- a/jdk/src/share/classes/java/awt/im/InputContext.java +++ b/jdk/src/share/classes/java/awt/im/InputContext.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ package java.awt.im; import java.awt.Component; import java.util.Locale; import java.awt.AWTEvent; +import java.beans.Transient; import java.lang.Character.Subset; import sun.awt.im.InputMethodContext; @@ -231,6 +232,7 @@ public class InputContext { * @see #setCompositionEnabled * @since 1.3 */ + @Transient public boolean isCompositionEnabled() { // real implementation is in sun.awt.im.InputContext return false; diff --git a/jdk/src/share/classes/java/awt/image/BufferedImage.java b/jdk/src/share/classes/java/awt/image/BufferedImage.java index 763fc31df69..e5b77bec510 100644 --- a/jdk/src/share/classes/java/awt/image/BufferedImage.java +++ b/jdk/src/share/classes/java/awt/image/BufferedImage.java @@ -1210,9 +1210,9 @@ public class BufferedImage extends java.awt.Image * BufferedImage. */ public String toString() { - return new String("BufferedImage@"+Integer.toHexString(hashCode()) - +": type = "+imageType - +" "+colorModel+" "+raster); + return "BufferedImage@"+Integer.toHexString(hashCode()) + +": type = "+imageType + +" "+colorModel+" "+raster; } /** diff --git a/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java b/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java index 9970d53dbba..6553a517200 100644 --- a/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java +++ b/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -164,53 +164,19 @@ public class DefaultPersistenceDelegate extends PersistenceDelegate { return new Expression(oldInstance, oldInstance.getClass(), "new", constructorArgs); } - private Method findMethod(Class type, String property) throws IntrospectionException { + private Method findMethod(Class type, String property) { if (property == null) { throw new IllegalArgumentException("Property name is null"); } - BeanInfo info = Introspector.getBeanInfo(type); - for (PropertyDescriptor pd : info.getPropertyDescriptors()) { - if (property.equals(pd.getName())) { - Method method = pd.getReadMethod(); - if (method != null) { - return method; - } - throw new IllegalStateException("Could not find getter for the property " + property); - } + PropertyDescriptor pd = getPropertyDescriptor(type, property); + if (pd == null) { + throw new IllegalStateException("Could not find property by the name " + property); } - throw new IllegalStateException("Could not find property by the name " + property); - } - - // This is a workaround for a bug in the introspector. - // PropertyDescriptors are not shared amongst subclasses. - private boolean isTransient(Class type, PropertyDescriptor pd) { - if (type == null) { - return false; + Method method = pd.getReadMethod(); + if (method == null) { + throw new IllegalStateException("Could not find getter for the property " + property); } - // This code was mistakenly deleted - it may be fine and - // is more efficient than the code below. This should - // all disappear anyway when property descriptors are shared - // by the introspector. - /* - Method getter = pd.getReadMethod(); - Class declaringClass = getter.getDeclaringClass(); - if (declaringClass == type) { - return Boolean.TRUE.equals(pd.getValue("transient")); - } - */ - String pName = pd.getName(); - BeanInfo info = MetaData.getBeanInfo(type); - PropertyDescriptor[] propertyDescriptors = info.getPropertyDescriptors(); - for (int i = 0; i < propertyDescriptors.length; ++i ) { - PropertyDescriptor pd2 = propertyDescriptors[i]; - if (pName.equals(pd2.getName())) { - Object value = pd2.getValue("transient"); - if (value != null) { - return Boolean.TRUE.equals(value); - } - } - } - return isTransient(type.getSuperclass(), pd); + return method; } private static boolean equals(Object o1, Object o2) { @@ -221,7 +187,7 @@ public class DefaultPersistenceDelegate extends PersistenceDelegate { Method getter = pd.getReadMethod(); Method setter = pd.getWriteMethod(); - if (getter != null && setter != null && !isTransient(type, pd)) { + if (getter != null && setter != null) { Expression oldGetExp = new Expression(oldInstance, getter.getName(), new Object[]{}); Expression newGetExp = new Expression(newInstance, getter.getName(), new Object[]{}); Object oldValue = oldGetExp.getValue(); @@ -254,14 +220,19 @@ public class DefaultPersistenceDelegate extends PersistenceDelegate { // Write out the properties of this instance. private void initBean(Class type, Object oldInstance, Object newInstance, Encoder out) { - // System.out.println("initBean: " + oldInstance); - BeanInfo info = MetaData.getBeanInfo(type); - + BeanInfo info; + try { + info = Introspector.getBeanInfo(type); + } catch (IntrospectionException exception) { + return; + } // Properties - PropertyDescriptor[] propertyDescriptors = info.getPropertyDescriptors(); - for (int i = 0; i < propertyDescriptors.length; ++i ) { + for (PropertyDescriptor d : info.getPropertyDescriptors()) { + if (d.isTransient()) { + continue; + } try { - doProperty(type, propertyDescriptors[i], oldInstance, newInstance, out); + doProperty(type, d, oldInstance, newInstance, out); } catch (Exception e) { out.getExceptionListener().exceptionThrown(e); @@ -295,9 +266,10 @@ public class DefaultPersistenceDelegate extends PersistenceDelegate { if (!java.awt.Component.class.isAssignableFrom(type)) { return; // Just handle the listeners of Components for now. } - EventSetDescriptor[] eventSetDescriptors = info.getEventSetDescriptors(); - for (int e = 0; e < eventSetDescriptors.length; e++) { - EventSetDescriptor d = eventSetDescriptors[e]; + for (EventSetDescriptor d : info.getEventSetDescriptors()) { + if (d.isTransient()) { + continue; + } Class listenerType = d.getListenerType(); @@ -408,4 +380,15 @@ public class DefaultPersistenceDelegate extends PersistenceDelegate { initBean(type, oldInstance, newInstance, out); } } + + private static PropertyDescriptor getPropertyDescriptor(Class type, String property) { + try { + for (PropertyDescriptor pd : Introspector.getBeanInfo(type).getPropertyDescriptors()) { + if (property.equals(pd.getName())) + return pd; + } + } catch (IntrospectionException exception) { + } + return null; + } } diff --git a/jdk/src/share/classes/java/beans/EventSetDescriptor.java b/jdk/src/share/classes/java/beans/EventSetDescriptor.java index 8c30657e0c3..05b62d8caf1 100644 --- a/jdk/src/share/classes/java/beans/EventSetDescriptor.java +++ b/jdk/src/share/classes/java/beans/EventSetDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -369,6 +369,7 @@ public class EventSetDescriptor extends FeatureDescriptor { setClass0(method.getDeclaringClass()); } addMethodDescriptor = new MethodDescriptor(method); + setTransient(method.getAnnotation(Transient.class)); } /** @@ -389,6 +390,7 @@ public class EventSetDescriptor extends FeatureDescriptor { setClass0(method.getDeclaringClass()); } removeMethodDescriptor = new MethodDescriptor(method); + setTransient(method.getAnnotation(Transient.class)); } /** @@ -411,6 +413,7 @@ public class EventSetDescriptor extends FeatureDescriptor { setClass0(method.getDeclaringClass()); } getMethodDescriptor = new MethodDescriptor(method); + setTransient(method.getAnnotation(Transient.class)); } /** diff --git a/jdk/src/share/classes/java/beans/FeatureDescriptor.java b/jdk/src/share/classes/java/beans/FeatureDescriptor.java index eea5a29d81c..36adbc044d6 100644 --- a/jdk/src/share/classes/java/beans/FeatureDescriptor.java +++ b/jdk/src/share/classes/java/beans/FeatureDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,9 @@ import java.lang.ref.WeakReference; import java.lang.ref.SoftReference; import java.lang.reflect.Method; -import java.lang.reflect.Type; + +import java.util.Enumeration; +import java.util.Hashtable; /** * The FeatureDescriptor class is the common baseclass for PropertyDescriptor, @@ -46,6 +48,7 @@ import java.lang.reflect.Type; */ public class FeatureDescriptor { + private static final String TRANSIENT = "transient"; private Reference classRef; @@ -187,10 +190,7 @@ public class FeatureDescriptor { * @param value The value. */ public void setValue(String attributeName, Object value) { - if (table == null) { - table = new java.util.Hashtable(); - } - table.put(attributeName, value); + getTable().put(attributeName, value); } /** @@ -201,10 +201,9 @@ public class FeatureDescriptor { * the attribute is unknown. */ public Object getValue(String attributeName) { - if (table == null) { - return null; - } - return table.get(attributeName); + return (this.table != null) + ? this.table.get(attributeName) + : null; } /** @@ -214,11 +213,8 @@ public class FeatureDescriptor { * @return An enumeration of the locale-independent names of any * attributes that have been registered with setValue. */ - public java.util.Enumeration attributeNames() { - if (table == null) { - table = new java.util.Hashtable(); - } - return table.keys(); + public Enumeration attributeNames() { + return getTable().keys(); } /** @@ -268,16 +264,54 @@ public class FeatureDescriptor { addTable(old.table); } - private void addTable(java.util.Hashtable t) { - if (t == null) { - return; + /** + * Copies all values from the specified attribute table. + * If some attribute is exist its value should be overridden. + * + * @param table the attribute table with new values + */ + private void addTable(Hashtable table) { + if ((table != null) && !table.isEmpty()) { + getTable().putAll(table); } - java.util.Enumeration keys = t.keys(); - while (keys.hasMoreElements()) { - String key = (String)keys.nextElement(); - Object value = t.get(key); - setValue(key, value); + } + + /** + * Returns the initialized attribute table. + * + * @return the initialized attribute table + */ + private Hashtable getTable() { + if (this.table == null) { + this.table = new Hashtable(); } + return this.table; + } + + /** + * Sets the "transient" attribute according to the annotation. + * If the "transient" attribute is already set + * it should not be changed. + * + * @param annotation the annotation of the element of the feature + */ + void setTransient(Transient annotation) { + if ((annotation != null) && (null == getValue(TRANSIENT))) { + setValue(TRANSIENT, annotation.value()); + } + } + + /** + * Indicates whether the feature is transient. + * + * @return {@code true} if the feature is transient, + * {@code false} otherwise + */ + boolean isTransient() { + Object value = getValue(TRANSIENT); + return (value instanceof Boolean) + ? (Boolean) value + : false; } // Package private methods for recreating the weak/soft referent @@ -292,39 +326,6 @@ public class FeatureDescriptor { : null; } - /** - * Create a Reference wrapper for the object. - * - * @param obj object that will be wrapped - * @param soft true if a SoftReference should be created; otherwise Soft - * @return a Reference or null if obj is null. - */ - static Reference createReference(Object obj, boolean soft) { - Reference ref = null; - if (obj != null) { - if (soft) { - ref = new SoftReference(obj); - } else { - ref = new WeakReference(obj); - } - } - return ref; - } - - // Convenience method which creates a WeakReference. - static Reference createReference(Object obj) { - return createReference(obj, false); - } - - /** - * Returns an object from a Reference wrapper. - * - * @return the Object in a wrapper or null. - */ - static Object getObject(Reference ref) { - return (ref == null) ? null : (Object)ref.get(); - } - /** * Creates a new soft reference that refers to the given object. * @@ -391,5 +392,5 @@ public class FeatureDescriptor { private String shortDescription; private String name; private String displayName; - private java.util.Hashtable table; + private Hashtable table; } diff --git a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java index 3b1a39e38a4..fa5b404c239 100644 --- a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -231,6 +231,7 @@ perty. indexedReadMethodName = readMethod.getName(); this.indexedReadMethodRef = getSoftReference(readMethod); + setTransient(readMethod.getAnnotation(Transient.class)); } @@ -303,6 +304,7 @@ perty. indexedWriteMethodName = writeMethod.getName(); this.indexedWriteMethodRef = getSoftReference(writeMethod); + setTransient(writeMethod.getAnnotation(Transient.class)); } /** diff --git a/jdk/src/share/classes/java/beans/MetaData.java b/jdk/src/share/classes/java/beans/MetaData.java index 7b9f6ced377..9bcd505c215 100644 --- a/jdk/src/share/classes/java/beans/MetaData.java +++ b/jdk/src/share/classes/java/beans/MetaData.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1352,7 +1352,6 @@ final class sun_swing_PrintColorUIResource_PersistenceDelegate extends Persisten class MetaData { private static Hashtable internalPersistenceDelegates = new Hashtable(); - private static Hashtable transientProperties = new Hashtable(); private static PersistenceDelegate nullPersistenceDelegate = new NullPersistenceDelegate(); private static PersistenceDelegate enumPersistenceDelegate = new EnumPersistenceDelegate(); @@ -1383,94 +1382,6 @@ class MetaData { internalPersistenceDelegates.put("java.util.JumboEnumSet", new java_util_EnumSet_PersistenceDelegate()); internalPersistenceDelegates.put("java.util.RegularEnumSet", new java_util_EnumSet_PersistenceDelegate()); - -// Transient properties - - // awt - - // Infinite graphs. - removeProperty("java.awt.geom.RectangularShape", "frame"); - // removeProperty("java.awt.Rectangle2D", "frame"); - // removeProperty("java.awt.Rectangle", "frame"); - - removeProperty("java.awt.Rectangle", "bounds"); - removeProperty("java.awt.Dimension", "size"); - removeProperty("java.awt.Point", "location"); - - // The color and font properties in Component need special treatment, see above. - removeProperty("java.awt.Component", "foreground"); - removeProperty("java.awt.Component", "background"); - removeProperty("java.awt.Component", "font"); - - // The visible property of Component needs special treatment because of Windows. - removeProperty("java.awt.Component", "visible"); - - // This property throws an exception if accessed when there is no child. - removeProperty("java.awt.ScrollPane", "scrollPosition"); - - // 4917458 this should be removed for XAWT since it may throw - // an unsupported exception if there isn't any input methods. - // This shouldn't be a problem since these are added behind - // the scenes automatically. - removeProperty("java.awt.im.InputContext", "compositionEnabled"); - - // swing - - // The size properties in JComponent need special treatment, see above. - removeProperty("javax.swing.JComponent", "minimumSize"); - removeProperty("javax.swing.JComponent", "preferredSize"); - removeProperty("javax.swing.JComponent", "maximumSize"); - - // These properties have platform specific implementations - // and should not appear in archives. - removeProperty("javax.swing.ImageIcon", "image"); - removeProperty("javax.swing.ImageIcon", "imageObserver"); - - // This property unconditionally throws a "not implemented" exception. - removeProperty("javax.swing.JMenuBar", "helpMenu"); - - // The scrollBars in a JScrollPane are dynamic and should not - // be archived. The row and columns headers are changed by - // components like JTable on "addNotify". - removeProperty("javax.swing.JScrollPane", "verticalScrollBar"); - removeProperty("javax.swing.JScrollPane", "horizontalScrollBar"); - removeProperty("javax.swing.JScrollPane", "rowHeader"); - removeProperty("javax.swing.JScrollPane", "columnHeader"); - - removeProperty("javax.swing.JViewport", "extentSize"); - - // Renderers need special treatment, since their properties - // change during rendering. - removeProperty("javax.swing.table.JTableHeader", "defaultRenderer"); - removeProperty("javax.swing.JList", "cellRenderer"); - - removeProperty("javax.swing.JList", "selectedIndices"); - - // The lead and anchor selection indexes are best ignored. - // Selection is rarely something that should persist from - // development to deployment. - removeProperty("javax.swing.DefaultListSelectionModel", "leadSelectionIndex"); - removeProperty("javax.swing.DefaultListSelectionModel", "anchorSelectionIndex"); - - // The selection must come after the text itself. - removeProperty("javax.swing.JComboBox", "selectedIndex"); - - // All selection information should come after the JTabbedPane is built - removeProperty("javax.swing.JTabbedPane", "selectedIndex"); - removeProperty("javax.swing.JTabbedPane", "selectedComponent"); - - // PENDING: The "disabledIcon" property is often computed from the icon property. - removeProperty("javax.swing.AbstractButton", "disabledIcon"); - removeProperty("javax.swing.JLabel", "disabledIcon"); - - // The caret property throws errors when it it set beyond - // the extent of the text. We could just set it after the - // text, but this is probably not something we want to archive anyway. - removeProperty("javax.swing.text.JTextComponent", "caret"); - removeProperty("javax.swing.text.JTextComponent", "caretPosition"); - // The selectionStart must come after the text itself. - removeProperty("javax.swing.text.JTextComponent", "selectionStart"); - removeProperty("javax.swing.text.JTextComponent", "selectionEnd"); } /*pp*/ static boolean equals(Object o1, Object o2) { @@ -1509,18 +1420,6 @@ class MetaData { // } String typeName = type.getName(); - - // Check to see if there are properties that have been lazily registered for removal. - if (getBeanAttribute(type, "transient_init") == null) { - Vector tp = (Vector)transientProperties.get(typeName); - if (tp != null) { - for(int i = 0; i < tp.size(); i++) { - setPropertyAttribute(type, (String)tp.get(i), "transient", Boolean.TRUE); - } - } - setBeanAttribute(type, "transient_init", Boolean.TRUE); - } - PersistenceDelegate pd = (PersistenceDelegate)getBeanAttribute(type, "persistenceDelegate"); if (pd == null) { pd = (PersistenceDelegate)internalPersistenceDelegates.get(typeName); @@ -1583,55 +1482,11 @@ class MetaData { return true; } - // Wrapper for Introspector.getBeanInfo to handle exception handling. - // Note: this relys on new 1.4 Introspector semantics which cache the BeanInfos - public static BeanInfo getBeanInfo(Class type) { - BeanInfo info = null; - try { - info = Introspector.getBeanInfo(type); - } catch (Throwable e) { - e.printStackTrace(); - } - - return info; - } - - private static PropertyDescriptor getPropertyDescriptor(Class type, String propertyName) { - BeanInfo info = getBeanInfo(type); - PropertyDescriptor[] propertyDescriptors = info.getPropertyDescriptors(); - // System.out.println("Searching for: " + propertyName + " in " + type); - for(int i = 0; i < propertyDescriptors.length; i++) { - PropertyDescriptor pd = propertyDescriptors[i]; - if (propertyName.equals(pd.getName())) { - return pd; - } - } - return null; - } - - private static void setPropertyAttribute(Class type, String property, String attribute, Object value) { - PropertyDescriptor pd = getPropertyDescriptor(type, property); - if (pd == null) { - System.err.println("Warning: property " + property + " is not defined on " + type); - return; - } - pd.setValue(attribute, value); - } - - private static void setBeanAttribute(Class type, String attribute, Object value) { - getBeanInfo(type).getBeanDescriptor().setValue(attribute, value); - } - private static Object getBeanAttribute(Class type, String attribute) { - return getBeanInfo(type).getBeanDescriptor().getValue(attribute); - } - - private static void removeProperty(String typeName, String property) { - Vector tp = (Vector)transientProperties.get(typeName); - if (tp == null) { - tp = new Vector(); - transientProperties.put(typeName, tp); + try { + return Introspector.getBeanInfo(type).getBeanDescriptor().getValue(attribute); + } catch (IntrospectionException exception) { + return null; } - tp.add(property); } } diff --git a/jdk/src/share/classes/java/beans/PropertyDescriptor.java b/jdk/src/share/classes/java/beans/PropertyDescriptor.java index 775b213c31d..08ae9a45f42 100644 --- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -256,6 +256,7 @@ public class PropertyDescriptor extends FeatureDescriptor { readMethodName = readMethod.getName(); this.readMethodRef = getSoftReference(readMethod); + setTransient(readMethod.getAnnotation(Transient.class)); } /** @@ -320,7 +321,7 @@ public class PropertyDescriptor extends FeatureDescriptor { writeMethodName = writeMethod.getName(); this.writeMethodRef = getSoftReference(writeMethod); - + setTransient(writeMethod.getAnnotation(Transient.class)); } private Method getReadMethod0() { diff --git a/jdk/src/share/classes/java/beans/Transient.java b/jdk/src/share/classes/java/beans/Transient.java new file mode 100644 index 00000000000..302152e7cb9 --- /dev/null +++ b/jdk/src/share/classes/java/beans/Transient.java @@ -0,0 +1,68 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.beans; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Indicates that an attribute called "transient" + * should be declared with the given {@code value} + * when the {@link Introspector} constructs + * a {@link PropertyDescriptor} or {@link EventSetDescriptor} + * classes associated with the annotated code element. + * A {@code true} value for the "transient" attribute + * indicates to encoders derived from {@link Encoder} + * that this feature should be ignored. + *

      + * The {@code Transient} annotation may be be used + * in any of the methods that are involved + * in a {@link FeatureDescriptor} subclass + * to identify the transient feature in the annotated class and its subclasses. + * Normally, the method that starts with "get" is the best place + * to put the annotation and it is this declaration + * that takes precedence in the case of multiple annotations + * being defined for the same feature. + *

      + * To declare a feature non-transient in a class + * whose superclass declares it transient, + * use {@code @Transient(false)}. + * In all cases, the {@link Introspector} decides + * if a feature is transient by referring to the annotation + * on the most specific superclass. + * If no {@code Transient} annotation is present + * in any superclass the feature is not transient. + * + * @since 1.7 + */ +@Target({METHOD}) +@Retention(RUNTIME) +public @interface Transient { + boolean value() default true; +} diff --git a/jdk/src/share/classes/java/lang/management/ClassLoadingMXBean.java b/jdk/src/share/classes/java/lang/management/ClassLoadingMXBean.java index 62f31e48769..762e14cb2f5 100644 --- a/jdk/src/share/classes/java/lang/management/ClassLoadingMXBean.java +++ b/jdk/src/share/classes/java/lang/management/ClassLoadingMXBean.java @@ -35,7 +35,7 @@ package java.lang.management; * that can be obtained by calling * the {@link ManagementFactory#getClassLoadingMXBean} method or * from the {@link ManagementFactory#getPlatformMBeanServer - * platform MBeanServer} method. + * platform MBeanServer}. * *

      The ObjectName for uniquely identifying the MXBean for * the class loading system within an MBeanServer is: @@ -44,6 +44,10 @@ package java.lang.management; * java.lang:type=ClassLoading} *

    * + * It can be obtained by calling the + * {@link PlatformManagedObject#getObjectName} method. + * + * @see ManagementFactory#getPlatformMXBeans(Class) * @see * JMX Specification. * @see @@ -52,7 +56,7 @@ package java.lang.management; * @author Mandy Chung * @since 1.5 */ -public interface ClassLoadingMXBean { +public interface ClassLoadingMXBean extends PlatformManagedObject { /** * Returns the total number of classes that have been loaded since diff --git a/jdk/src/share/classes/java/lang/management/CompilationMXBean.java b/jdk/src/share/classes/java/lang/management/CompilationMXBean.java index 94f97bb4507..ea93a2b0ccb 100644 --- a/jdk/src/share/classes/java/lang/management/CompilationMXBean.java +++ b/jdk/src/share/classes/java/lang/management/CompilationMXBean.java @@ -44,6 +44,10 @@ package java.lang.management; * java.lang:type=Compilation} * * + * It can be obtained by calling the + * {@link PlatformManagedObject#getObjectName} method. + * + * @see ManagementFactory#getPlatformMXBeans(Class) * @see * JMX Specification. * @see @@ -52,7 +56,7 @@ package java.lang.management; * @author Mandy Chung * @since 1.5 */ -public interface CompilationMXBean { +public interface CompilationMXBean extends PlatformManagedObject { /** * Returns the name of the Just-in-time (JIT) compiler. * diff --git a/jdk/src/share/classes/java/lang/management/GarbageCollectorMXBean.java b/jdk/src/share/classes/java/lang/management/GarbageCollectorMXBean.java index f737a9c2ec5..50ee93d8d79 100644 --- a/jdk/src/share/classes/java/lang/management/GarbageCollectorMXBean.java +++ b/jdk/src/share/classes/java/lang/management/GarbageCollectorMXBean.java @@ -48,9 +48,13 @@ package java.lang.management; * java.lang:type=GarbageCollector},name=collector's name * * + * It can be obtained by calling the + * {@link PlatformManagedObject#getObjectName} method. + * * A platform usually includes additional platform-dependent information * specific to a garbage collection algorithm for monitoring. * + * @see ManagementFactory#getPlatformMXBeans(Class) * @see MemoryMXBean * * @see diff --git a/jdk/src/share/classes/java/lang/management/ManagementFactory.java b/jdk/src/share/classes/java/lang/management/ManagementFactory.java index dff4f19a4e3..c9e12708ef8 100644 --- a/jdk/src/share/classes/java/lang/management/ManagementFactory.java +++ b/jdk/src/share/classes/java/lang/management/ManagementFactory.java @@ -24,17 +24,31 @@ */ package java.lang.management; +import javax.management.DynamicMBean; import javax.management.MBeanServer; import javax.management.MBeanServerConnection; +import javax.management.MBeanServerFactory; import javax.management.MBeanServerPermission; +import javax.management.NotificationEmitter; +import javax.management.ObjectInstance; import javax.management.ObjectName; +import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.MalformedObjectNameException; +import javax.management.MBeanRegistrationException; +import javax.management.NotCompliantMBeanException; +import javax.management.StandardEmitterMBean; +import javax.management.StandardMBean; +import java.util.Collections; +import java.util.ArrayList; import java.util.List; import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import javax.management.JMX; +import sun.management.ManagementFactoryHelper; /** * The ManagementFactory class is a factory class for getting @@ -49,13 +63,16 @@ import javax.management.JMX; *