This commit is contained in:
Albert Noll 2015-02-03 09:56:21 +00:00
commit 18ccddbb82
2182 changed files with 76161 additions and 22604 deletions

View File

@ -285,3 +285,9 @@ b409bc51bc23cfd51f2bd04ea919ec83535af9d0 jdk9-b37
82f4cb44b2d7af2352f48568a64b7b6a5ae960cd jdk9-b40
9fffb959eb4197ff806e4ac12244761815b4deee jdk9-b41
3107be2ba9c6e208a0b86bc7100a141abbc5b5fb jdk9-b42
6494b13f88a867026ee316b444d9a4fa589dd6bd jdk9-b43
abbfccd659b91a7bb815d5e36fed635dcdd40f31 jdk9-b44
bfc24ae2b900187585079bb11e66e459d1e525fe jdk9-b45
722378bc599e38d9a1dd484de30f10dfd7b21438 jdk9-b46
8327024a99559982b848e9c2191da9c0bf8838fd jdk9-b47
b2f9702efbe95527ea3a991474fda23987ff1c5c jdk9-b48

View File

@ -285,3 +285,9 @@ d42c0a90afc3c66ca87543076ec9aafd4b4680de jdk9-b38
cf136458ee747e151a27aa9ea0c1492ea55ef3e7 jdk9-b40
67395f7ca2db3b52e3a62a84888487de5cb9210a jdk9-b41
f7c11da0b0481d49cc7a65a453336c108191e821 jdk9-b42
02ee8c65622e8bd97496d584e22fc7dcf0edc4ae jdk9-b43
8994f5d87b3bb5e8d317d4e8ccb326da1a73684a jdk9-b44
3dd628fde2086218d548841022ee8436b6b88185 jdk9-b45
12f1e276447bcc81516e85367d53e4f08897049d jdk9-b46
b6cca3e6175a69f39e5799b7349ddb0176630291 jdk9-b47
0064e246d83f6f9fc245c19b6d05041ecaf4b6d4 jdk9-b48

View File

@ -54,8 +54,11 @@ ifneq ($(findstring qp,$(MAKEFLAGS)),)
# Duplication of global targets, needed before ParseConfAndSpec in case we have
# no configurations.
help:
# If CONF is not set, look for all available configurations
CONF?=
# If both CONF and SPEC are unset, look for all available configurations by
# setting CONF to the empty string.
ifeq ($(SPEC), )
CONF?=
endif
endif
# ... and then we can include our helper functions

View File

@ -987,3 +987,26 @@ AC_DEFUN_ONCE([BASIC_TEST_USABILITY_ISSUES],
IS_RECONFIGURE=no
fi
])
# Check for support for specific options in bash
AC_DEFUN_ONCE([BASIC_CHECK_BASH_OPTIONS],
[
# Test if bash supports pipefail.
AC_MSG_CHECKING([if bash supports pipefail])
if ${BASH} -c 'set -o pipefail'; then
BASH_ARGS="$BASH_ARGS -o pipefail"
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
AC_MSG_CHECKING([if bash supports errexit (-e)])
if ${BASH} -e -c 'true'; then
BASH_ARGS="$BASH_ARGS -e"
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
AC_SUBST(BASH_ARGS)
])

View File

@ -46,8 +46,12 @@ endif
BOOT_JDK := $(JDK_IMAGE_DIR)
# The bootcycle build has a different output directory
BUILD_OUTPUT:=@BUILD_OUTPUT@/bootcycle-build
SJAVAC_SERVER_DIR:=$(subst @BUILD_OUTPUT@,$(BUILD_OUTPUT),$(SJAVAC_SERVER_DIR))
OLD_BUILD_OUTPUT:=@BUILD_OUTPUT@
BUILD_OUTPUT:=$(OLD_BUILD_OUTPUT)/bootcycle-build
# The HOTSPOT_DIST dir is not defined relative to BUILD_OUTPUT in spec.gmk. Must not
# use space in this patsubst to avoid leading space in HOTSPOT_DIST.
HOTSPOT_DIST:=$(patsubst $(OLD_BUILD_OUTPUT)%,$(BUILD_OUTPUT)%,$(HOTSPOT_DIST))
SJAVAC_SERVER_DIR:=$(patsubst $(OLD_BUILD_OUTPUT)%, $(BUILD_OUTPUT)%, $(SJAVAC_SERVER_DIR))
JAVA_CMD:=$(BOOT_JDK)/bin/java
JAVAC_CMD:=$(BOOT_JDK)/bin/javac

View File

@ -36,6 +36,13 @@ else
shift
fi
if test "x$BASH" = x; then
echo "Error: This script must be run using bash." 1>&2
exit 1
fi
# Force autoconf to use bash
export CONFIG_SHELL=$BASH
conf_script_dir="$TOPDIR/common/autoconf"
if [ "$CUSTOM_CONFIG_DIR" = "" ]; then

View File

@ -113,6 +113,7 @@ HELP_SETUP_DEPENDENCY_HELP
# Setup tools that requires more complex handling, or that is not needed by the configure script.
BASIC_SETUP_COMPLEX_TOOLS
BASIC_CHECK_BASH_OPTIONS
# Check if pkg-config is available.
PKG_PROG_PKG_CONFIG

View File

@ -853,6 +853,7 @@ OS_VERSION_MICRO
OS_VERSION_MINOR
OS_VERSION_MAJOR
PKG_CONFIG
BASH_ARGS
CODESIGN
XATTR
DSYMUTIL
@ -3522,6 +3523,9 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
# Check for support for specific options in bash
#
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@ -4329,7 +4333,7 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++"
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
DATE_WHEN_GENERATED=1418036274
DATE_WHEN_GENERATED=1421247827
###############################################################################
#
@ -13965,7 +13969,8 @@ $as_echo "$COMPILE_TYPE" >&6; }
# ZERO_ARCHDEF is used to enable architecture-specific code
case "${OPENJDK_TARGET_CPU}" in
ppc*) ZERO_ARCHDEF=PPC ;;
ppc) ZERO_ARCHDEF=PPC32 ;;
ppc64) ZERO_ARCHDEF=PPC64 ;;
s390*) ZERO_ARCHDEF=S390 ;;
sparc*) ZERO_ARCHDEF=SPARC ;;
x86_64*) ZERO_ARCHDEF=AMD64 ;;
@ -19608,6 +19613,32 @@ $as_echo "yes" >&6; }
fi
# Test if bash supports pipefail.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if bash supports pipefail" >&5
$as_echo_n "checking if bash supports pipefail... " >&6; }
if ${BASH} -c 'set -o pipefail'; then
BASH_ARGS="$BASH_ARGS -o pipefail"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if bash supports errexit (-e)" >&5
$as_echo_n "checking if bash supports errexit (-e)... " >&6; }
if ${BASH} -e -c 'true'; then
BASH_ARGS="$BASH_ARGS -e"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Check if pkg-config is available.

View File

@ -367,7 +367,8 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS],
# ZERO_ARCHDEF is used to enable architecture-specific code
case "${OPENJDK_TARGET_CPU}" in
ppc*) ZERO_ARCHDEF=PPC ;;
ppc) ZERO_ARCHDEF=PPC32 ;;
ppc64) ZERO_ARCHDEF=PPC64 ;;
s390*) ZERO_ARCHDEF=S390 ;;
sparc*) ZERO_ARCHDEF=SPARC ;;
x86_64*) ZERO_ARCHDEF=AMD64 ;;

View File

@ -78,6 +78,11 @@ endif
OUTPUT_SYNC_SUPPORTED:=@OUTPUT_SYNC_SUPPORTED@
OUTPUT_SYNC:=@OUTPUT_SYNC@
# Override the shell with bash
BASH:=@BASH@
BASH_ARGS:=@BASH_ARGS@
SHELL:=$(BASH) $(BASH_ARGS)
# The "human readable" name of this configuration
CONF_NAME:=@CONF_NAME@
@ -243,7 +248,7 @@ MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/makesupport
HOTSPOT_OUTPUTDIR=$(BUILD_OUTPUT)/hotspot
JDK_OUTPUTDIR=$(BUILD_OUTPUT)/jdk
IMAGES_OUTPUTDIR=$(BUILD_OUTPUT)/images
TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/testmake
TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/test-make
MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/make-support
HOTSPOT_DIST=@HOTSPOT_DIST@
@ -495,7 +500,6 @@ endif
# Tools adhering to a minimal and common standard of posix compliance.
AWK:=@AWK@
BASENAME:=@BASENAME@
BASH:=@BASH@
CAT:=@CAT@
CCACHE:=@CCACHE@
# CD is going away, but remains to cater for legacy makefiles.
@ -690,10 +694,15 @@ OS_VERSION_MICRO:=@OS_VERSION_MICRO@
# Images directory definitions
JDK_IMAGE_SUBDIR:=jdk
JRE_IMAGE_SUBDIR:=jre
# Colon left out to be able to override output dir for bootcycle-images
JDK_IMAGE_DIR=$(IMAGES_OUTPUTDIR)/$(JDK_IMAGE_SUBDIR)
JRE_IMAGE_DIR=$(IMAGES_OUTPUTDIR)/$(JRE_IMAGE_SUBDIR)
# Test image, as above
TEST_IMAGE_SUBDIR:=test
TEST_IMAGE_DIR=$(IMAGES_OUTPUTDIR)/$(TEST_IMAGE_SUBDIR)
# Macosx bundles directory definitions
JDK_BUNDLE_SUBDIR=jdk-bundle/jdk$(JDK_VERSION).jdk/Contents
JRE_BUNDLE_SUBDIR=jre-bundle/jre$(JDK_VERSION).jre/Contents

View File

@ -173,8 +173,8 @@ AC_DEFUN([TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV],
# The trailing space for everyone except PATH is no typo, but is needed due
# to trailing \ in the Windows paths. These will be stripped later.
$ECHO "$WINPATH_BASH -c 'echo VS_PATH="'\"$PATH\" > set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
$ECHO "$WINPATH_BASH -c 'echo VS_INCLUDE="'\"$INCLUDE \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
$ECHO "$WINPATH_BASH -c 'echo VS_LIB="'\"$LIB \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
$ECHO "$WINPATH_BASH -c 'echo VS_INCLUDE="'\"$INCLUDE\;$include \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
$ECHO "$WINPATH_BASH -c 'echo VS_LIB="'\"$LIB\;$lib \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
$ECHO "$WINPATH_BASH -c 'echo VCINSTALLDIR="'\"$VCINSTALLDIR \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
$ECHO "$WINPATH_BASH -c 'echo WindowsSdkDir="'\"$WindowsSdkDir \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
$ECHO "$WINPATH_BASH -c 'echo WINDOWSSDKDIR="'\"$WINDOWSSDKDIR \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE

View File

@ -22,7 +22,7 @@
# questions.
#
# This script is processed by configure before it's usable. It is run from
# This script is processed by configure before it's usable. It is run from
# the root of the build directory.
@ -76,10 +76,13 @@ diff_text() {
TMP=1
if [[ "$THIS_FILE" = *"META-INF/MANIFEST.MF" ]]; then
# Filter out date string, ant version and java version differences.
TMP=$(LC_ALL=C $DIFF $OTHER_FILE $THIS_FILE | \
$GREP '^[<>]' | \
$SED -e '/[<>] Ant-Version: Apache Ant .*/d' \
-e '/[<>] Created-By: .* (Oracle Corporation).*/d')
-e '/[<>] Created-By: .* (Oracle [Corpatin)]*/d' \
-e '/[<>] [Corpatin]*)/d' \
-e '/[<>].*[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}.*/d')
fi
if test "x$SUFFIX" = "xjava"; then
TMP=$(LC_ALL=C $DIFF $OTHER_FILE $THIS_FILE | \
@ -92,7 +95,7 @@ diff_text() {
-e '/\/\/ java GenerateCharacter.*/d')
fi
# Ignore date strings in class files.
# On Macosx the system sources for generated java classes produce different output on
# On Macosx the system sources for generated java classes produce different output on
# consequtive invocations seemingly randomly.
# For example a method parameter randomly named "thePoint" or "aPoint". Ignore this.
# Anonymous lambda classes get randomly assigned counters in their names.
@ -100,18 +103,18 @@ diff_text() {
# To improve performance when large diffs are found, do a rough filtering of classes
# elibeble for these exceptions
if $GREP -R -e '[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}' \
-e '[0-9]\{2\}/[0-9]\{2\}/[0-9]\{4\}' \
-e thePoint -e aPoint -e setItemsPtr \
-e '[0-9]\{2\}/[0-9]\{2\}/[0-9]\{4\}' \
-e thePoint -e aPoint -e setItemsPtr \
-e 'lambda\$[a-zA-Z0-9]*\$[0-9]' ${THIS_FILE} > /dev/null; then
$JAVAP -c -constants -l -p "${OTHER_FILE}" > ${OTHER_FILE}.javap
$JAVAP -c -constants -l -p "${THIS_FILE}" > ${THIS_FILE}.javap
TMP=$($DIFF ${OTHER_FILE}.javap ${THIS_FILE}.javap | \
$GREP '^[<>]' | \
$SED -e '/[<>].*[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}.*/d' \
-e '/[0-9]\{2\}\/[0-9]\{2\}\/[0-9]\{4\}/d' \
-e '/[<>].*Point Lcom\/apple\/jobjc\/foundation\/NSPoint;/d' \
-e '/[<>].*public com\.apple\.jobjc\.Pointer<com\.apple\.jobjc\..*itemsPtr();/d' \
-e '/[<>].*public void setItemsPtr(com\.apple\.jobjc\.Pointer<com\.apple\.jobjc\..*);/d' \
-e '/[0-9]\{2\}\/[0-9]\{2\}\/[0-9]\{4\}/d' \
-e '/[<>].*Point Lcom\/apple\/jobjc\/foundation\/NSPoint;/d' \
-e '/[<>].*public com\.apple\.jobjc\.Pointer<com\.apple\.jobjc\..*itemsPtr();/d' \
-e '/[<>].*public void setItemsPtr(com\.apple\.jobjc\.Pointer<com\.apple\.jobjc\..*);/d' \
-e '/[<>].*lambda\$[a-zA-Z0-9]*\$[0-9]*/d')
fi
fi
@ -121,20 +124,19 @@ diff_text() {
# Disable this exception since we aren't changing the properties cleaning method yet.
# $CAT $OTHER_FILE | $SED -e 's/\([^\\]\):/\1\\:/g' -e 's/\([^\\]\)=/\1\\=/g' -e 's/#.*/#/g' \
# | $SED -f "$SRC_ROOT/common/makefiles/support/unicode2x.sed" \
# | $SED -e '/^#/d' -e '/^$/d' \
# | $SED -e '/^#/d' -e '/^$/d' \
# -e :a -e '/\\$/N; s/\\\n//; ta' \
# -e 's/^[ \t]*//;s/[ \t]*$//' \
# -e 's/\\=/=/' | LC_ALL=C $SORT > $OTHER_FILE.cleaned
# -e 's/^[ \t]*//;s/[ \t]*$//' \
# -e 's/\\=/=/' | LC_ALL=C $SORT > $OTHER_FILE.cleaned
# Filter out date string differences.
TMP=$(LC_ALL=C $DIFF $OTHER_FILE.cleaned $THIS_FILE | \
$GREP '^[<>]' | \
$SED -e '/[<>].*[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}.*/d')
fi
if test "x$SUFFIX" = "xMF"; then
# Filter out date string differences.
if test "x$SUFFIX" = "xhtml"; then
TMP=$(LC_ALL=C $DIFF $OTHER_FILE $THIS_FILE | \
$GREP '^[<>]' | \
$SED -e '/[<>].*[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}.*/d')
$SED -e '/[<>] <!-- Generated by javadoc .* on .* -->/d' )
fi
if test -n "$TMP"; then
echo Files $OTHER_FILE and $THIS_FILE differ
@ -158,7 +160,7 @@ compare_dirs() {
(cd $THIS_DIR && $FIND . -type d | $SORT > $WORK_DIR/dirs_this)
$DIFF $WORK_DIR/dirs_other $WORK_DIR/dirs_this > $WORK_DIR/dirs_diff
echo -n Directory structure...
if [ -s $WORK_DIR/dirs_diff ]; then
echo Differences found.
@ -192,7 +194,7 @@ compare_files() {
(cd $OTHER_DIR && $FIND . ! -type d | $SORT > $WORK_DIR/files_other)
(cd $THIS_DIR && $FIND . ! -type d | $SORT > $WORK_DIR/files_this)
$DIFF $WORK_DIR/files_other $WORK_DIR/files_this > $WORK_DIR/files_diff
echo -n File names...
@ -236,11 +238,11 @@ compare_permissions() {
TP=`ls -l ${THIS_DIR}/$f | awk '{printf("%.10s\n", $1);}'`
if [ "$OP" != "$TP" ]
then
if [ -z "$found" ]; then echo ; found="yes"; fi
$PRINTF "\told: ${OP} new: ${TP}\t$f\n"
if [ -z "$found" ]; then echo ; found="yes"; fi
$PRINTF "\tother: ${OP} this: ${TP}\t$f\n"
fi
done
if [ -z "$found" ]; then
if [ -z "$found" ]; then
echo "Identical!"
else
REGRESSIONS=true
@ -265,24 +267,22 @@ compare_file_types() {
if [ ! -f ${THIS_DIR}/$f ]; then continue; fi
OF=`cd ${OTHER_DIR} && $FILE -h $f | $SED 's/BuildID[^,]*//g'`
TF=`cd ${THIS_DIR} && $FILE -h $f | $SED 's/BuildID[^,]*//g'`
if [ "$f" = "./src.zip" ] || [[ "$f" = *"/Home/src.zip" ]] || [[ "$f" = *"/lib/JObjC.jar" ]]
then
if [ "`echo $OF | $GREP -ic zip`" -gt 0 -a "`echo $TF | $GREP -ic zip`" -gt 0 ]
then
# the way we produces zip-files make it so that directories are stored in old file
# but not in new (only files with full-path)
# this makes file-5.09 report them as different
continue;
fi
fi
if [ "$OF" != "$TF" ]
then
if [ -z "$found" ]; then echo ; found="yes"; fi
$PRINTF "\tother: ${OF}\n\tthis : ${TF}\n"
if [ "`echo $OF | $GREP -c 'Zip archive data'`" -gt 0 ] \
&& [ "`echo $TF | $GREP -c 'Zip archive data'`" -gt 0 ]
then
# the way we produce zip-files make it so that directories are stored in
# old file but not in new (only files with full-path) this makes file
# report them as different
continue
else
if [ -z "$found" ]; then echo ; found="yes"; fi
$PRINTF "\tother: ${OF}\n\tthis : ${TF}\n"
fi
fi
done
if [ -z "$found" ]; then
if [ -z "$found" ]; then
echo "Identical!"
else
REGRESSIONS=true
@ -296,12 +296,13 @@ compare_general_files() {
THIS_DIR=$1
OTHER_DIR=$2
WORK_DIR=$3
GENERAL_FILES=$(cd $THIS_DIR && $FIND . -type f ! -name "*.so" ! -name "*.jar" ! -name "*.zip" \
! -name "*.debuginfo" ! -name "*.dylib" ! -name "jexec" ! -name "*.jimage" \
! -name "ct.sym" ! -name "*.diz" ! -name "*.dll" \
! -name "ct.sym" ! -name "*.diz" ! -name "*.dll" ! -name "*.cpl" \
! -name "*.pdb" ! -name "*.exp" ! -name "*.ilk" \
! -name "*.lib" ! -name "*.war" ! -name "JavaControlPanel" \
! -name "*.obj" ! -name "*.o" ! -name "JavaControlPanelHelper" ! -name "JavaUpdater" \
| $GREP -v "./bin/" | $SORT | $FILTER)
echo General files...
@ -377,7 +378,7 @@ compare_zip_file() {
THIS_SUFFIX="${THIS_ZIP##*.}"
OTHER_SUFFIX="${OTHER_ZIP##*.}"
if [ "$THIS_SUFFIX" != "$OTHER_SUFFIX" ]; then
echo The files do not have the same suffix type!
echo "The files do not have the same suffix type! ($THIS_SUFFIX != $OTHER_SUFFIX)"
return 2
fi
@ -389,7 +390,7 @@ compare_zip_file() {
fi
# Not quite identical, the might still contain the same data.
# Unpack the jar/zip files in temp dirs
THIS_UNZIPDIR=$WORK_DIR/$ZIP_FILE.this
OTHER_UNZIPDIR=$WORK_DIR/$ZIP_FILE.other
$RM -rf $THIS_UNZIPDIR $OTHER_UNZIPDIR
@ -464,9 +465,9 @@ compare_zip_file() {
$RM -f $WORK_DIR/$ZIP_FILE.diffs
for file in $DIFFING_FILES; do
if [[ "$ACCEPTED_JARZIP_CONTENTS $EXCEPTIONS" != *"$file"* ]]; then
if [[ "$ACCEPTED_JARZIP_CONTENTS $EXCEPTIONS" != *"$file"* ]]; then
diff_text $OTHER_UNZIPDIR/$file $THIS_UNZIPDIR/$file >> $WORK_DIR/$ZIP_FILE.diffs
fi
fi
done
if [ -s "$WORK_DIR/$ZIP_FILE.diffs" ]; then
@ -573,6 +574,10 @@ compare_bin_file() {
$MKDIR -p $FILE_WORK_DIR
# Make soft links to original files from work dir to facilitate debugging
$LN -f -s $THIS_FILE $WORK_FILE_BASE.this
$LN -f -s $OTHER_FILE $WORK_FILE_BASE.other
ORIG_THIS_FILE="$THIS_FILE"
ORIG_OTHER_FILE="$OTHER_FILE"
@ -589,50 +594,51 @@ compare_bin_file() {
fi
if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
unset _NT_SYMBOL_PATH
# On windows we need to unzip the debug symbols, if present
OTHER_FILE_BASE=${OTHER_FILE/.dll/}
OTHER_FILE_BASE=${OTHER_FILE_BASE/.exe/}
DIZ_NAME=$(basename $OTHER_FILE_BASE).diz
unset _NT_SYMBOL_PATH
# On windows we need to unzip the debug symbols, if present
OTHER_FILE_BASE=${OTHER_FILE/.dll/}
OTHER_FILE_BASE=${OTHER_FILE_BASE/.exe/}
OTHER_FILE_BASE=${OTHER_FILE_BASE/.cpl/}
DIZ_NAME=$(basename $OTHER_FILE_BASE).diz
# java.exe and java.dll diz files will have the same name. Have to
# make sure java.exe gets the right one. This is only needed for
# OTHER since in the new build, all pdb files are left around.
if [ "$NAME" = "java.exe" ] && [ -f "$OTHER/tmp/java/java/obj64/java.diz" ]; then
OTHER_DIZ_FILE="$OTHER/tmp/java/java/obj64/java.diz"
elif [ -f "${OTHER_FILE_BASE}.diz" ]; then
OTHER_DIZ_FILE=${OTHER_FILE_BASE}.diz
else
# make sure java.exe gets the right one. This is only needed for
# OTHER since in the new build, all pdb files are left around.
if [ "$NAME" = "java.exe" ] && [ -f "$OTHER/tmp/java/java/obj64/java.diz" ]; then
OTHER_DIZ_FILE="$OTHER/tmp/java/java/obj64/java.diz"
elif [ -f "${OTHER_FILE_BASE}.diz" ]; then
OTHER_DIZ_FILE=${OTHER_FILE_BASE}.diz
else
# Some files, jli.dll, appears twice in the image but only one of
# thme has a diz file next to it.
OTHER_DIZ_FILE="$($FIND $OTHER_DIR -name $DIZ_NAME | $SED 1q)"
if [ ! -f "$OTHER_DIZ_FILE" ]; then
# As a last resort, look for diz file in the whole build output
# dir.
OTHER_DIZ_FILE="$($FIND $OTHER -name $DIZ_NAME | $SED 1q)"
fi
fi
if [ -n "$OTHER_DIZ_FILE" ]; then
$MKDIR -p $FILE_WORK_DIR/other
(cd $FILE_WORK_DIR/other ; $UNARCHIVE -o $OTHER_DIZ_FILE)
export _NT_SYMBOL_PATH="$FILE_WORK_DIR/other"
fi
THIS_FILE_BASE=${THIS_FILE/.dll/}
THIS_FILE_BASE=${THIS_FILE_BASE/.exe/}
if [ -f "${THIS_FILE/.dll/}.diz" ]; then
THIS_DIZ_FILE=${THIS_FILE/.dll/}.diz
else
THIS_DIZ_FILE="$($FIND $THIS_DIR -name $DIZ_NAME | $SED 1q)"
if [ ! -f "$THIS_DIZ_FILE" ]; then
# As a last resort, look for diz file in the whole build output
# dir.
THIS_DIZ_FILE="$($FIND $THIS -name $DIZ_NAME | $SED 1q)"
fi
fi
if [ -n "$THIS_DIZ_FILE" ]; then
$MKDIR -p $FILE_WORK_DIR/this
(cd $FILE_WORK_DIR/this ; $UNARCHIVE -o $THIS_DIZ_FILE)
export _NT_SYMBOL_PATH="$_NT_SYMBOL_PATH;$FILE_WORK_DIR/this"
fi
# thme has a diz file next to it.
OTHER_DIZ_FILE="$($FIND $OTHER_DIR -name $DIZ_NAME | $SED 1q)"
if [ ! -f "$OTHER_DIZ_FILE" ]; then
# As a last resort, look for diz file in the whole build output
# dir.
OTHER_DIZ_FILE="$($FIND $OTHER -name $DIZ_NAME | $SED 1q)"
fi
fi
if [ -n "$OTHER_DIZ_FILE" ]; then
$MKDIR -p $FILE_WORK_DIR/other
(cd $FILE_WORK_DIR/other ; $UNARCHIVE -o $OTHER_DIZ_FILE)
export _NT_SYMBOL_PATH="$FILE_WORK_DIR/other"
fi
THIS_FILE_BASE=${THIS_FILE/.dll/}
THIS_FILE_BASE=${THIS_FILE_BASE/.exe/}
if [ -f "${THIS_FILE/.dll/}.diz" ]; then
THIS_DIZ_FILE=${THIS_FILE/.dll/}.diz
else
THIS_DIZ_FILE="$($FIND $THIS_DIR -name $DIZ_NAME | $SED 1q)"
if [ ! -f "$THIS_DIZ_FILE" ]; then
# As a last resort, look for diz file in the whole build output
# dir.
THIS_DIZ_FILE="$($FIND $THIS -name $DIZ_NAME | $SED 1q)"
fi
fi
if [ -n "$THIS_DIZ_FILE" ]; then
$MKDIR -p $FILE_WORK_DIR/this
(cd $FILE_WORK_DIR/this ; $UNARCHIVE -o $THIS_DIZ_FILE)
export _NT_SYMBOL_PATH="$_NT_SYMBOL_PATH;$FILE_WORK_DIR/this"
fi
fi
if [ -z "$SKIP_BIN_DIFF" ]; then
@ -670,19 +676,19 @@ compare_bin_file() {
DIFF_SIZE_REL=$($EXPR $THIS_SIZE \* 100 / $OTHER_SIZE)
SIZE_MSG=$($PRINTF "%3d%% %4d" $DIFF_SIZE_REL $DIFF_SIZE_NUM)
if [[ "$ACCEPTED_SMALL_SIZE_DIFF" = *"$BIN_FILE"* ]] && [ "$DIFF_SIZE_REL" -gt 98 ] \
&& [ "$DIFF_SIZE_REL" -lt 102 ]; then
&& [ "$DIFF_SIZE_REL" -lt 102 ]; then
SIZE_MSG="($SIZE_MSG)"
DIFF_SIZE=
elif [ "$OPENJDK_TARGET_OS" = "windows" ] \
&& [[ "$ACCEPTED_SMALL_SIZE_DIFF" = *"$BIN_FILE"* ]] \
&& [ "$DIFF_SIZE_NUM" = 512 ]; then
# On windows, size of binaries increase in 512 increments.
&& [[ "$ACCEPTED_SMALL_SIZE_DIFF" = *"$BIN_FILE"* ]] \
&& [ "$DIFF_SIZE_NUM" = 512 ]; then
# On windows, size of binaries increase in 512 increments.
SIZE_MSG="($SIZE_MSG)"
DIFF_SIZE=
elif [ "$OPENJDK_TARGET_OS" = "windows" ] \
&& [[ "$ACCEPTED_SMALL_SIZE_DIFF" = *"$BIN_FILE"* ]] \
&& [ "$DIFF_SIZE_NUM" = -512 ]; then
# On windows, size of binaries increase in 512 increments.
&& [[ "$ACCEPTED_SMALL_SIZE_DIFF" = *"$BIN_FILE"* ]] \
&& [ "$DIFF_SIZE_NUM" = -512 ]; then
# On windows, size of binaries increase in 512 increments.
SIZE_MSG="($SIZE_MSG)"
DIFF_SIZE=
else
@ -717,18 +723,18 @@ compare_bin_file() {
if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
# The output from dumpbin on windows differs depending on if the debug symbol
# files are still around at the location the binary is pointing too. Need
# to filter out that extra information.
$DUMPBIN -exports $OTHER_FILE | $GREP -E '^ +[0-9A-F]+ +[0-9A-F]+ [0-9A-F]+' | sed 's/ = .*//g' | cut -c27- | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other
$DUMPBIN -exports $THIS_FILE | $GREP -E '^ +[0-9A-F]+ +[0-9A-F]+ [0-9A-F]+' | sed 's/ = .*//g' | cut -c27- | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this
# to filter out that extra information.
$DUMPBIN -exports $OTHER_FILE | $GREP -E '^ +[0-9A-F]+ +[0-9A-F]+ [0-9A-F]+' | sed 's/ = .*//g' | cut -c27- | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other
$DUMPBIN -exports $THIS_FILE | $GREP -E '^ +[0-9A-F]+ +[0-9A-F]+ [0-9A-F]+' | sed 's/ = .*//g' | cut -c27- | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this
elif [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
# Some symbols get seemingly random 15 character prefixes. Filter them out.
$NM -a $ORIG_OTHER_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SED 's/^\([a-zA-Z] [\.\$]\)[a-zA-Z0-9_\$]\{15,15\}\./\1./g' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other
$NM -a $ORIG_THIS_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SED 's/^\([a-zA-Z] [\.\$]\)[a-zA-Z0-9_\$]\{15,15\}\./\1./g' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this
$NM -a $ORIG_THIS_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SED 's/^\([a-zA-Z] [\.\$]\)[a-zA-Z0-9_\$]\{15,15\}\./\1./g' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this
else
$NM -a $ORIG_OTHER_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other
$NM -a $ORIG_THIS_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this
$NM -a $ORIG_OTHER_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other
$NM -a $ORIG_THIS_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this
fi
LC_ALL=C $DIFF $WORK_FILE_BASE.symbols.other $WORK_FILE_BASE.symbols.this > $WORK_FILE_BASE.symbols.diff
if [ -s $WORK_FILE_BASE.symbols.diff ]; then
SYM_MSG=" diff "
@ -741,7 +747,7 @@ compare_bin_file() {
SYM_MSG=" $SYM_MSG "
fi
else
SYM_MSG="($SYM_MSG)"
SYM_MSG="($SYM_MSG)"
DIFF_SYM=
fi
else
@ -754,48 +760,48 @@ compare_bin_file() {
# Check dependencies
if [ -n "$LDD_CMD" ]; then
(cd $FILE_WORK_DIR && $CP $OTHER_FILE . && $LDD_CMD $NAME 2>/dev/null | $AWK '{ print $1;}' | $SORT | $TEE $WORK_FILE_BASE.deps.other | $UNIQ > $WORK_FILE_BASE.deps.other.uniq)
(cd $FILE_WORK_DIR && $CP $THIS_FILE . && $LDD_CMD $NAME 2</dev/null | $AWK '{ print $1;}' | $SORT | $TEE $WORK_FILE_BASE.deps.this | $UNIQ > $WORK_FILE_BASE.deps.this.uniq)
(cd $FILE_WORK_DIR && $RM -f $NAME)
LC_ALL=C $DIFF $WORK_FILE_BASE.deps.other $WORK_FILE_BASE.deps.this > $WORK_FILE_BASE.deps.diff
LC_ALL=C $DIFF $WORK_FILE_BASE.deps.other.uniq $WORK_FILE_BASE.deps.this.uniq > $WORK_FILE_BASE.deps.diff.uniq
if [ -s $WORK_FILE_BASE.deps.diff ]; then
(cd $FILE_WORK_DIR && $CP $OTHER_FILE . && $LDD_CMD $NAME 2>/dev/null | $AWK '{ print $1;}' | $SORT | $TEE $WORK_FILE_BASE.deps.other | $UNIQ > $WORK_FILE_BASE.deps.other.uniq)
(cd $FILE_WORK_DIR && $CP $THIS_FILE . && $LDD_CMD $NAME 2</dev/null | $AWK '{ print $1;}' | $SORT | $TEE $WORK_FILE_BASE.deps.this | $UNIQ > $WORK_FILE_BASE.deps.this.uniq)
(cd $FILE_WORK_DIR && $RM -f $NAME)
LC_ALL=C $DIFF $WORK_FILE_BASE.deps.other $WORK_FILE_BASE.deps.this > $WORK_FILE_BASE.deps.diff
LC_ALL=C $DIFF $WORK_FILE_BASE.deps.other.uniq $WORK_FILE_BASE.deps.this.uniq > $WORK_FILE_BASE.deps.diff.uniq
if [ -s $WORK_FILE_BASE.deps.diff ]; then
if [ -s $WORK_FILE_BASE.deps.diff.uniq ]; then
DEP_MSG=" diff "
DEP_MSG=" diff "
else
DEP_MSG=" redun "
DEP_MSG=" redun "
fi
if [[ "$ACCEPTED_DEP_DIFF" != *"$BIN_FILE"* ]]; then
DIFF_DEP=true
if [[ "$KNOWN_DEP_DIFF" != *"$BIN_FILE"* ]]; then
DIFF_DEP=true
if [[ "$KNOWN_DEP_DIFF" != *"$BIN_FILE"* ]]; then
DEP_MSG="*$DEP_MSG*"
REGRESSIONS=true
else
else
DEP_MSG=" $DEP_MSG "
fi
fi
else
DEP_MSG="($DEP_MSG)"
DIFF_DEP=
DEP_MSG="($DEP_MSG)"
DIFF_DEP=
fi
else
DEP_MSG=" "
DIFF_DEP=
else
DEP_MSG=" "
DIFF_DEP=
if [[ "$KNOWN_DEP_DIFF $ACCEPTED_DEP_DIFF" = *"$BIN_FILE"* ]]; then
DEP_MSG=" ! "
fi
fi
fi
else
DEP_MSG=" - "
DEP_MSG=" - "
fi
# Compare fulldump output
if [ -n "$FULLDUMP_CMD" ] && [ -z "$SKIP_FULLDUMP_DIFF" ]; then
$FULLDUMP_CMD $OTHER_FILE > $WORK_FILE_BASE.fulldump.other 2>&1
$FULLDUMP_CMD $THIS_FILE > $WORK_FILE_BASE.fulldump.this 2>&1
LC_ALL=C $DIFF $WORK_FILE_BASE.fulldump.other $WORK_FILE_BASE.fulldump.this > $WORK_FILE_BASE.fulldump.diff
if [ -s $WORK_FILE_BASE.fulldump.diff ]; then
ELF_DIFF_SIZE=$(ls -n $WORK_FILE_BASE.fulldump.diff | awk '{print $5}')
ELF_MSG=$($PRINTF "%8d" $ELF_DIFF_SIZE)
@ -822,14 +828,17 @@ compare_bin_file() {
# Compare disassemble output
if [ -n "$DIS_CMD" ] && [ -z "$SKIP_DIS_DIFF" ]; then
if [ -z "$DIS_DIFF_FILTER" ]; then
DIS_DIFF_FILTER="$CAT"
fi
$DIS_CMD $OTHER_FILE | $GREP -v $NAME | $DIS_DIFF_FILTER > $WORK_FILE_BASE.dis.other 2>&1
$DIS_CMD $THIS_FILE | $GREP -v $NAME | $DIS_DIFF_FILTER > $WORK_FILE_BASE.dis.this 2>&1
# By default we filter out differences that include references to symbols.
# To get a raw diff with the complete disassembly, set
# DIS_DIFF_FILTER="$CAT"
if [ -z "$DIS_DIFF_FILTER" ]; then
DIS_DIFF_FILTER="$GREP -v ' # .* <.*>$'"
fi
$DIS_CMD $OTHER_FILE | $GREP -v $NAME | eval "$DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.other 2>&1
$DIS_CMD $THIS_FILE | $GREP -v $NAME | eval "$DIS_DIFF_FILTER" > $WORK_FILE_BASE.dis.this 2>&1
LC_ALL=C $DIFF $WORK_FILE_BASE.dis.other $WORK_FILE_BASE.dis.this > $WORK_FILE_BASE.dis.diff
if [ -s $WORK_FILE_BASE.dis.diff ]; then
DIS_DIFF_SIZE=$(ls -n $WORK_FILE_BASE.dis.diff | awk '{print $5}')
DIS_MSG=$($PRINTF "%8d" $DIS_DIFF_SIZE)
@ -907,7 +916,9 @@ compare_all_libs() {
OTHER_DIR=$2
WORK_DIR=$3
LIBS=$(cd $THIS_DIR && $FIND . -type f \( -name 'lib*.so' -o -name '*.dylib' -o -name '*.dll' -o -name 'JavaControlPanel' \) | $SORT | $FILTER)
LIBS=$(cd $THIS_DIR && $FIND . -type f \( -name 'lib*.so' -o -name '*.dylib' \
-o -name '*.dll' -o -name '*.obj' -o -name '*.o' \
-o -name '*.cpl' \) | $SORT | $FILTER)
if [ -n "$LIBS" ]; then
echo Libraries...
@ -967,7 +978,7 @@ COMPARE_ROOT=/tmp/cimages.$USER
$MKDIR -p $COMPARE_ROOT
if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
if [ "$(uname -o)" = "Cygwin" ]; then
COMPARE_ROOT=$(cygpath -msa $COMPARE_ROOT)
COMPARE_ROOT=$(cygpath -msa $COMPARE_ROOT)
fi
fi
@ -1091,7 +1102,7 @@ while [ -n "$1" ]; do
CMP_JARS=true
CMP_LIBS=true
CMP_EXECS=true
if [ -z "$FILTER" ]; then
FILTER="$GREP"
fi
@ -1177,8 +1188,8 @@ if [ "$SKIP_DEFAULT" != "true" ]; then
OTHER_J2RE="$OTHER/images/jre"
echo "Selecting jdk images for compare"
else
echo "No common images found."
exit 1
echo "No common images found."
exit 1
fi
if [ -d "$THIS/images/jdk-bundle" ] && [ -d "$OTHER/images/jdk-bundle" ]; then
@ -1189,6 +1200,17 @@ if [ "$SKIP_DEFAULT" != "true" ]; then
echo "Also comparing macosx bundles"
fi
if [ -d "$THIS/deploy" ] && [ -d "$OTHER/deploy" ]; then
THIS_DEPLOY_BUNDLE_DIR="$THIS/deploy/dist/installer/bundles"
OTHER_DEPLOY_BUNDLE_DIR="$OTHER/deploy/bundles"
echo "Also comparing deploy/bundles"
if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then
THIS_DEPLOY_APPLET_PLUGIN_DIR="$THIS/deploy/JavaAppletPlugin.plugin"
OTHER_DEPLOY_APPLET_PLUGIN_DIR="$OTHER/deploy/JavaAppletPlugin.plugin"
echo "Also comparing JavaAppletPlugin"
fi
fi
if [ -d "$OTHER/images" ]; then
OTHER_SEC_DIR="$OTHER/images"
else
@ -1212,7 +1234,7 @@ if [ "$SKIP_DEFAULT" != "true" ]; then
if [ -d "$THIS/docs" ] && [ -d "$OTHER/docs" ]; then
THIS_DOCS="$THIS/docs"
OTHER_DOCS="$OTHER/docs"
echo "Also comparing docs"
echo "Also comparing docs"
else
echo "WARNING! Docs haven't been built and won't be compared."
fi
@ -1227,7 +1249,7 @@ if [ "$CMP_NAMES" = "true" ]; then
compare_dirs $THIS_J2SDK $OTHER_J2SDK $COMPARE_ROOT/j2sdk
echo -n "J2RE "
compare_dirs $THIS_J2RE $OTHER_J2RE $COMPARE_ROOT/j2re
echo -n "J2SDK "
compare_files $THIS_J2SDK $OTHER_J2SDK $COMPARE_ROOT/j2sdk
echo -n "J2RE "
@ -1238,7 +1260,7 @@ if [ "$CMP_NAMES" = "true" ]; then
compare_dirs $THIS_J2SDK_BUNDLE $OTHER_J2SDK_BUNDLE $COMPARE_ROOT/jdk-bundle
echo -n "J2RE Bundle "
compare_dirs $THIS_J2RE_BUNDLE $OTHER_J2RE_BUNDLE $COMPARE_ROOT/jre-bundle
echo -n "J2SDK Bundle "
compare_files $THIS_J2SDK_BUNDLE $OTHER_J2SDK_BUNDLE $COMPARE_ROOT/jdk-bundle
echo -n "J2RE Bundle "
@ -1254,6 +1276,12 @@ if [ "$CMP_NAMES" = "true" ]; then
compare_dirs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
compare_files $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
echo -n "JavaAppletPlugin "
compare_dirs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
echo -n "JavaAppletPlugin "
compare_files $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
fi
if [ "$CMP_PERMS" = "true" ]; then
@ -1266,6 +1294,10 @@ if [ "$CMP_PERMS" = "true" ]; then
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
compare_permissions $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
echo -n "JavaAppletPlugin "
compare_permissions $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
fi
if [ "$CMP_TYPES" = "true" ]; then
@ -1284,6 +1316,10 @@ if [ "$CMP_TYPES" = "true" ]; then
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
compare_file_types $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
echo -n "JavaAppletPlugin "
compare_file_types $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
fi
if [ "$CMP_GENERAL" = "true" ]; then
@ -1306,6 +1342,10 @@ if [ "$CMP_GENERAL" = "true" ]; then
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
compare_general_files $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
echo -n "JavaAppletPlugin "
compare_general_files $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
fi
if [ "$CMP_ZIPS" = "true" ]; then
@ -1333,6 +1373,12 @@ if [ "$CMP_ZIPS" = "true" ]; then
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
compare_all_zip_files $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_BUNDLE_DIR" ] && [ -n "$OTHER_DEPLOY_BUNDLE_DIR" ]; then
compare_all_zip_files $THIS_DEPLOY_BUNDLE_DIR $OTHER_DEPLOY_BUNDLE_DIR $COMPARE_ROOT/deploy-bundle
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
compare_all_zip_files $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
fi
if [ "$CMP_JARS" = "true" ]; then
@ -1342,6 +1388,9 @@ if [ "$CMP_JARS" = "true" ]; then
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
compare_all_jar_files $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
compare_all_jar_files $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
fi
if [ "$CMP_LIBS" = "true" ]; then
@ -1356,15 +1405,27 @@ if [ "$CMP_LIBS" = "true" ]; then
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
compare_all_libs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
echo -n "JavaAppletPlugin "
compare_all_libs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
fi
if [ "$CMP_EXECS" = "true" ]; then
if [ -n "$THIS_J2SDK" ] && [ -n "$OTHER_J2SDK" ]; then
compare_all_execs $THIS_J2SDK $OTHER_J2SDK $COMPARE_ROOT/j2sdk
if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then
echo -n "J2RE "
compare_all_execs $THIS_J2RE $OTHER_J2RE $COMPARE_ROOT/j2re
fi
fi
if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
compare_all_execs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
fi
if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
echo -n "JavaAppletPlugin "
compare_all_execs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
fi
fi
echo

View File

@ -106,12 +106,15 @@ if [ ${vflag} = "true" ] ; then
echo "# Mercurial command: ${command}" > ${status_output}
fi
# capture command options and arguments (if any)
command_args="${@:-}"
# At this point all command options and args are in "$@".
# Always use "$@" (within double quotes) to avoid breaking
# args with spaces into separate args.
if [ ${vflag} = "true" ] ; then
echo "# Mercurial command arguments: ${command_args}" > ${status_output}
echo "# Mercurial command argument count: $#" > ${status_output}
for cmdarg in "$@" ; do
echo "# Mercurial command argument: ${cmdarg}" > ${status_output}
done
fi
# Clean out the temporary directory that stores the pid files.
@ -205,13 +208,14 @@ if [ "${command}" = "clone" -o "${command}" = "fclone" -o "${command}" = "tclone
pull_default_tail=`echo ${pull_default} | sed -e 's@^.*://[^/]*/\(.*\)@\1@'`
if [ -n "${command_args}" ] ; then
if [ $# -gt 0 ] ; then
# if there is an "extra sources" path then reparent "extra" repos to that path
if [ "x${pull_default}" = "x${pull_default_tail}" ] ; then
echo "ERROR: Need initial clone from non-local source" > ${status_output}
exit 1
fi
pull_extra="${command_args}/${pull_default_tail}"
# assume that "extra sources" path is the first arg
pull_extra="${1}/${pull_default_tail}"
# determine which extra subrepos need to be cloned.
for i in ${subrepos_extra} ; do
@ -356,8 +360,8 @@ else
(PYTHONUNBUFFERED=true hg${global_opts} clone ${clone_newrepo} ${i}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 &
else
# run the command.
echo "cd ${i} && hg${global_opts} ${command} ${command_args}" > ${status_output}
cd ${i} && (PYTHONUNBUFFERED=true hg${global_opts} ${command} ${command_args}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 &
echo "cd ${i} && hg${global_opts} ${command} ${@}" > ${status_output}
cd ${i} && (PYTHONUNBUFFERED=true hg${global_opts} ${command} "${@}"; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 &
fi
echo $! > ${tmp}/${repopidfile}.pid

View File

@ -26,10 +26,8 @@ corba/src/java.corba/share/classes/com/sun/org/omg : corba/src/share/classes/com
corba/src/java.corba/share/classes/com/sun/tools/corba/se/idl : corba/src/share/classes/com/sun/tools/corba/se/idl
corba/src/java.corba/share/classes/javax/activity : corba/src/share/classes/javax/activity
corba/src/java.corba/share/classes/javax/rmi : corba/src/share/classes/javax/rmi
corba/src/java.corba/share/classes/javax/transaction : corba/src/share/classes/javax/transaction
corba/src/java.corba/share/classes/org/omg : corba/src/share/classes/org/omg
corba/src/java.corba/share/classes/sun/corba : corba/src/share/classes/sun/corba
corba/src/java.sql/share/classes/javax/transaction/xa : corba/src/share/classes/javax/transaction/xa
corba/src/jdk.rmic/share/classes/sun/rmi/rmic/iiop : corba/src/share/classes/sun/rmi/rmic/iiop
jaxp/src/java.xml/share/classes/com/sun/java_cup/internal/runtime : jaxp/src/com/sun/java_cup/internal/runtime
jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal : jaxp/src/com/sun/org/apache/bcel/internal
@ -66,8 +64,8 @@ jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/fastinfoset : jaxws/s
jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/org : jaxws/src/share/jaxws_classes/com/sun/xml/internal/org
jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/txw2 : jaxws/src/share/jaxws_classes/com/sun/xml/internal/txw2
jaxws/src/java.xml.bind/share/classes/javax/xml/bind : jaxws/src/share/jaxws_classes/javax/xml/bind
jaxws/src/java.xml.soap/share/classes/com/sun/xml/internal/messaging : jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging
jaxws/src/java.xml.soap/share/classes/javax/xml/soap : jaxws/src/share/jaxws_classes/javax/xml/soap
jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging : jaxws/src/share/jaxws_classes/com/sun/xml/internal/messaging
jaxws/src/java.xml.ws/share/classes/javax/xml/soap : jaxws/src/share/jaxws_classes/javax/xml/soap
jaxws/src/java.xml.ws/share/classes/com/oracle/webservices/internal : jaxws/src/share/jaxws_classes/com/oracle/webservices/internal
jaxws/src/java.xml.ws/share/classes/com/oracle/xmlns/internal : jaxws/src/share/jaxws_classes/com/oracle/xmlns/internal
jaxws/src/java.xml.ws/share/classes/com/sun/org/glassfish : jaxws/src/share/jaxws_classes/com/sun/org/glassfish
@ -1245,6 +1243,8 @@ jdk/src/java.sql.rowset/share/classes/com/sun/rowset : jdk/src/share/classes/com
jdk/src/java.sql.rowset/share/classes/javax/sql/rowset : jdk/src/share/classes/javax/sql/rowset
jdk/src/java.sql/share/classes/java/sql : jdk/src/share/classes/java/sql
jdk/src/java.sql/share/classes/javax/sql : jdk/src/share/classes/javax/sql
jdk/src/java.sql/share/classes/javax/transaction/xa : corba/src/share/classes/javax/transaction/xa
jdk/src/java.transaction/share/classes/javax/transaction : corba/src/share/classes/javax/transaction
jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security : jdk/src/share/classes/com/sun/org/apache/xml/internal/security
jdk/src/java.xml.crypto/share/classes/javax/xml/crypto : jdk/src/share/classes/javax/xml/crypto
jdk/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal : jdk/src/share/classes/org/jcp/xml/dsig/internal

View File

@ -285,3 +285,9 @@ ffd90c81d4ef9d94d880fc852e2fc482ecd9b374 jdk9-b36
e27c725d6c9d155667b35255f442d4ceb8c3c084 jdk9-b40
1908b886ba1eda46fa725cf1160fe5d30fd1a7e5 jdk9-b41
078bb11af876fe528d4b516f33ad4dd9bb60549e jdk9-b42
9645e35616b60c5c07b4fdf11a132afc8081dfa8 jdk9-b43
1f57bd728c9e6865ccb9d43ccd80a1c11230a32f jdk9-b44
9e3f2bed80c0e5a84a256ce41f1d10c5ade48466 jdk9-b45
326f2068b4a4c05e2fa27d6acf93eba7b54b090d jdk9-b46
ee8447ca632e1d39180b4767c749db101bff7314 jdk9-b47
a13c49c5f2899b702652a460ed7aa73123e671e6 jdk9-b48

View File

@ -1,314 +0,0 @@
/*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.transaction.xa;
/** <p>The XAResource interface is a Java mapping of the industry standard
* XA interface based on the X/Open CAE Specification (Distributed
* Transaction Processing: The XA Specification).
*
* <p>The XA interface defines the contract between a Resource Manager
* and a Transaction Manager in a distributed transaction processing
* (DTP) environment. A JDBC driver or a JMS provider implements
* this interface to support the association between a global transaction
* and a database or message service connection.
*
* <p>The XAResource interface can be supported by any transactional
* resource that is intended to be used by application programs in an
* environment where transactions are controlled by an external
* transaction manager. An example of such a resource is a database
* management system. An application may access data through multiple
* database connections. Each database connection is enlisted with
* the transaction manager as a transactional resource. The transaction
* manager obtains an XAResource for each connection participating
* in a global transaction. The transaction manager uses the
* <code>start</code> method
* to associate the global transaction with the resource, and it uses the
* <code>end</code> method to disassociate the transaction from
* the resource. The resource
* manager is responsible for associating the global transaction to all
* work performed on its data between the start and end method invocations.
*
* <p>At transaction commit time, the resource managers are informed by
* the transaction manager to prepare, commit, or rollback a transaction
* according to the two-phase commit protocol.</p>
*
*/
public interface XAResource
{
/** Commits the global transaction specified by xid.
*
* @param xid A global transaction identifier
*
* @param onePhase If true, the resource manager should use a one-phase
* commit protocol to commit the work done on behalf of xid.
*
* @exception XAException An error has occurred. Possible XAExceptions
* are XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX, XAER_RMERR,
* XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or XAER_PROTO.
*
* <P>If the resource manager did not commit the transaction and the
* paramether onePhase is set to true, the resource manager may throw
* one of the XA_RB* exceptions. Upon return, the resource manager has
* rolled back the branch's work and has released all held resources.
*/
void commit(Xid xid, boolean onePhase) throws XAException;
/** Ends the work performed on behalf of a transaction branch.
* The resource manager disassociates the XA resource from the
* transaction branch specified and lets the transaction
* complete.
*
* <p>If TMSUSPEND is specified in the flags, the transaction branch
* is temporarily suspended in an incomplete state. The transaction
* context is in a suspended state and must be resumed via the
* <code>start</code> method with TMRESUME specified.</p>
*
* <p>If TMFAIL is specified, the portion of work has failed.
* The resource manager may mark the transaction as rollback-only</p>
*
* <p>If TMSUCCESS is specified, the portion of work has completed
* successfully.</p>
*
* @param xid A global transaction identifier that is the same as
* the identifier used previously in the <code>start</code> method.
*
* @param flags One of TMSUCCESS, TMFAIL, or TMSUSPEND.
*
* @exception XAException An error has occurred. Possible XAException
* values are XAER_RMERR, XAER_RMFAILED, XAER_NOTA, XAER_INVAL,
* XAER_PROTO, or XA_RB*.
*/
void end(Xid xid, int flags) throws XAException;
/** Tells the resource manager to forget about a heuristically
* completed transaction branch.
*
* @param xid A global transaction identifier.
*
* @exception XAException An error has occurred. Possible exception
* values are XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or
* XAER_PROTO.
*/
void forget(Xid xid) throws XAException;
/** Obtains the current transaction timeout value set for this
* XAResource instance. If <CODE>XAResource.setTransactionTimeout</CODE>
* was not used prior to invoking this method, the return value
* is the default timeout set for the resource manager; otherwise,
* the value used in the previous <CODE>setTransactionTimeout</CODE>
* call is returned.
*
* @return the transaction timeout value in seconds.
*
* @exception XAException An error has occurred. Possible exception
* values are XAER_RMERR and XAER_RMFAIL.
*/
int getTransactionTimeout() throws XAException;
/** This method is called to determine if the resource manager
* instance represented by the target object is the same as the
* resouce manager instance represented by the parameter <i>xares</i>.
*
* @param xares An XAResource object whose resource manager instance
* is to be compared with the resource manager instance of the
* target object.
*
* @return <i>true</i> if it's the same RM instance; otherwise
* <i>false</i>.
*
* @exception XAException An error has occurred. Possible exception
* values are XAER_RMERR and XAER_RMFAIL.
*
*/
boolean isSameRM(XAResource xares) throws XAException;
/** Ask the resource manager to prepare for a transaction commit
* of the transaction specified in xid.
*
* @param xid A global transaction identifier.
*
* @exception XAException An error has occurred. Possible exception
* values are: XA_RB*, XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL,
* or XAER_PROTO.
*
* @return A value indicating the resource manager's vote on the
* outcome of the transaction. The possible values are: XA_RDONLY
* or XA_OK. If the resource manager wants to roll back the
* transaction, it should do so by raising an appropriate XAException
* in the prepare method.
*/
int prepare(Xid xid) throws XAException;
/** Obtains a list of prepared transaction branches from a resource
* manager. The transaction manager calls this method during recovery
* to obtain the list of transaction branches that are currently in
* prepared or heuristically completed states.
*
* @param flag One of TMSTARTRSCAN, TMENDRSCAN, TMNOFLAGS. TMNOFLAGS
* must be used when no other flags are set in the parameter.
*
* @exception XAException An error has occurred. Possible values are
* XAER_RMERR, XAER_RMFAIL, XAER_INVAL, and XAER_PROTO.
*
* @return The resource manager returns zero or more XIDs of the
* transaction branches that are currently in a prepared or
* heuristically completed state. If an error occurs during the
* operation, the resource manager should throw the appropriate
* XAException.
*
*/
Xid[] recover(int flag) throws XAException;
/** Informs the resource manager to roll back work done on behalf
* of a transaction branch.
*
* @param xid A global transaction identifier.
*
* @exception XAException An error has occurred.
*/
void rollback(Xid xid) throws XAException;
/** <P>Sets the current transaction timeout value for this <CODE>XAResource</CODE>
* instance. Once set, this timeout value is effective until
* <code>setTransactionTimeout</code> is invoked again with a different
* value. To reset the timeout value to the default value used by the resource
* manager, set the value to zero.
*
* If the timeout operation is performed successfully, the method returns
* <i>true</i>; otherwise <i>false</i>. If a resource manager does not
* support explicitly setting the transaction timeout value, this method
* returns <i>false</i>.
*
* @param seconds The transaction timeout value in seconds.
*
* @return <i>true</i> if the transaction timeout value is set successfully;
* otherwise <i>false</i>.
*
* @exception XAException An error has occurred. Possible exception values
* are XAER_RMERR, XAER_RMFAIL, or XAER_INVAL.
*/
boolean setTransactionTimeout(int seconds) throws XAException;
/** Starts work on behalf of a transaction branch specified in
* <code>xid</code>.
*
* If TMJOIN is specified, the start applies to joining a transaction
* previously seen by the resource manager. If TMRESUME is specified,
* the start applies to resuming a suspended transaction specified in the
* parameter <code>xid</code>.
*
* If neither TMJOIN nor TMRESUME is specified and the transaction
* specified by <code>xid</code> has previously been seen by the resource
* manager, the resource manager throws the XAException exception with
* XAER_DUPID error code.
*
* @param xid A global transaction identifier to be associated
* with the resource.
*
* @param flags One of TMNOFLAGS, TMJOIN, or TMRESUME.
*
* @exception XAException An error has occurred. Possible exceptions
* are XA_RB*, XAER_RMERR, XAER_RMFAIL, XAER_DUPID, XAER_OUTSIDE,
* XAER_NOTA, XAER_INVAL, or XAER_PROTO.
*
*/
void start(Xid xid, int flags) throws XAException;
/**
* Ends a recovery scan.
*/
public final static int TMENDRSCAN = 0x00800000;
/**
* Disassociates the caller and marks the transaction branch
* rollback-only.
*/
public final static int TMFAIL = 0x20000000;
/**
* Caller is joining existing transaction branch.
*/
public final static int TMJOIN = 0x00200000;
/**
* Use TMNOFLAGS to indicate no flags value is selected.
*/
public final static int TMNOFLAGS = 0x00000000;
/**
* Caller is using one-phase optimization.
*/
public final static int TMONEPHASE = 0x40000000;
/**
* Caller is resuming association with a suspended
* transaction branch.
*/
public final static int TMRESUME = 0x08000000;
/**
* Starts a recovery scan.
*/
public final static int TMSTARTRSCAN = 0x01000000;
/**
* Disassociates caller from a transaction branch.
*/
public final static int TMSUCCESS = 0x04000000;
/**
* Caller is suspending (not ending) its association with
* a transaction branch.
*/
public final static int TMSUSPEND = 0x02000000;
/**
* The transaction branch has been read-only and has been committed.
*/
public final static int XA_RDONLY = 0x00000003;
/**
* The transaction work has been prepared normally.
*/
public final static int XA_OK = 0;
}

View File

@ -445,3 +445,9 @@ c363a8b87e477ee45d6d3cb2a36cb365141bc596 jdk9-b38
6b09b3193d731e3288e2a240c504a20d0a06c766 jdk9-b40
1d29b13e8a515a7ea3b882f140576d5d675bc11f jdk9-b41
38cb4fbd47e3472bd1b5ebac83bda96fe4869c4f jdk9-b42
65a9747147b8090037541040ba67156ec914db6a jdk9-b43
43a44b56dca61a4d766a20f0528fdd8b5ceff873 jdk9-b44
5dc8184af1e2bb30b0103113d1f1a58a21a80c37 jdk9-b45
a184ee1d717297bd35b7c3e35393e137921a3ed2 jdk9-b46
3b241fb72b8925b75941d612db762a6d5da66d02 jdk9-b47
cc775a4a24c7f5d9e624b4205e9fbd48a17331f6 jdk9-b48

View File

@ -58,15 +58,19 @@ sun.jvm.hotspot.debugger.cdbg.basic.x86 \
sun.jvm.hotspot.debugger.dummy \
sun.jvm.hotspot.debugger.linux \
sun.jvm.hotspot.debugger.linux.amd64 \
sun.jvm.hotspot.debugger.linux.ppc64 \
sun.jvm.hotspot.debugger.linux.x86 \
sun.jvm.hotspot.debugger.posix \
sun.jvm.hotspot.debugger.posix.elf \
sun.jvm.hotspot.debugger.ppc64 \
sun.jvm.hotspot.debugger.proc \
sun.jvm.hotspot.debugger.proc.amd64 \
sun.jvm.hotspot.debugger.proc.ppc64 \
sun.jvm.hotspot.debugger.proc.sparc \
sun.jvm.hotspot.debugger.proc.x86 \
sun.jvm.hotspot.debugger.remote \
sun.jvm.hotspot.debugger.remote.amd64 \
sun.jvm.hotspot.debugger.remote.ppc64 \
sun.jvm.hotspot.debugger.remote.sparc \
sun.jvm.hotspot.debugger.remote.x86 \
sun.jvm.hotspot.debugger.sparc \
@ -93,9 +97,11 @@ sun.jvm.hotspot.runtime.bsd_amd64 \
sun.jvm.hotspot.runtime.bsd_x86 \
sun.jvm.hotspot.runtime.linux \
sun.jvm.hotspot.runtime.linux_amd64 \
sun.jvm.hotspot.runtime.linux_ppc64 \
sun.jvm.hotspot.runtime.linux_sparc \
sun.jvm.hotspot.runtime.linux_x86 \
sun.jvm.hotspot.runtime.posix \
sun.jvm.hotspot.runtime.ppc64 \
sun.jvm.hotspot.runtime.solaris_amd64 \
sun.jvm.hotspot.runtime.solaris_sparc \
sun.jvm.hotspot.runtime.solaris_x86 \
@ -142,15 +148,19 @@ sun/jvm/hotspot/debugger/cdbg/basic/amd64/*.java \
sun/jvm/hotspot/debugger/cdbg/basic/x86/*.java \
sun/jvm/hotspot/debugger/dummy/*.java \
sun/jvm/hotspot/debugger/linux/*.java \
sun/jvm/hotspot/debugger/linux/ppc64/*.java \
sun/jvm/hotspot/debugger/linux/x86/*.java \
sun/jvm/hotspot/debugger/posix/*.java \
sun/jvm/hotspot/debugger/posix/elf/*.java \
sun/jvm/hotspot/debugger/ppc64/*.java \
sun/jvm/hotspot/debugger/proc/*.java \
sun/jvm/hotspot/debugger/proc/amd64/*.java \
sun/jvm/hotspot/debugger/proc/ppc64/*.java \
sun/jvm/hotspot/debugger/proc/sparc/*.java \
sun/jvm/hotspot/debugger/proc/x86/*.java \
sun/jvm/hotspot/debugger/remote/*.java \
sun/jvm/hotspot/debugger/remote/amd64/*.java \
sun/jvm/hotspot/debugger/remote/ppc64/*.java \
sun/jvm/hotspot/debugger/remote/sparc/*.java \
sun/jvm/hotspot/debugger/remote/x86/*.java \
sun/jvm/hotspot/debugger/sparc/*.java \
@ -174,9 +184,11 @@ sun/jvm/hotspot/runtime/bsd_amd64/*.java \
sun/jvm/hotspot/runtime/bsd_x86/*.java \
sun/jvm/hotspot/runtime/linux/*.java \
sun/jvm/hotspot/runtime/linux_amd64/*.java \
sun/jvm/hotspot/runtime/linux_ppc64/*.java \
sun/jvm/hotspot/runtime/linux_sparc/*.java \
sun/jvm/hotspot/runtime/linux_x86/*.java \
sun/jvm/hotspot/runtime/posix/*.java \
sun/jvm/hotspot/runtime/ppc64/*.java \
sun/jvm/hotspot/runtime/solaris_amd64/*.java \
sun/jvm/hotspot/runtime/solaris_sparc/*.java \
sun/jvm/hotspot/runtime/solaris_x86/*.java \

View File

@ -49,6 +49,10 @@
#include "sun_jvm_hotspot_debugger_sparc_SPARCThreadContext.h"
#endif
#ifdef ppc64
#include "sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext.h"
#endif
static jfieldID p_ps_prochandle_ID = 0;
static jfieldID threadList_ID = 0;
static jfieldID loadObjectList_ID = 0;
@ -341,7 +345,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo
return (err == PS_OK)? array : 0;
}
#if defined(i386) || defined(amd64) || defined(sparc) || defined(sparcv9)
#if defined(i386) || defined(amd64) || defined(sparc) || defined(sparcv9) | defined(ppc64)
JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0
(JNIEnv *env, jobject this_obj, jint lwp_id) {
@ -366,6 +370,10 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo
#if defined(sparc) || defined(sparcv9)
#define NPRGREG sun_jvm_hotspot_debugger_sparc_SPARCThreadContext_NPRGREG
#endif
#ifdef ppc64
#define NPRGREG sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_NPRGREG
#endif
array = (*env)->NewLongArray(env, NPRGREG);
CHECK_EXCEPTION_(0);
@ -458,6 +466,45 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo
regs[REG_INDEX(R_O7)] = gregs.u_regs[14];
#endif /* sparc */
#ifdef ppc64
#define REG_INDEX(reg) sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_##reg
regs[REG_INDEX(LR)] = gregs.link;
regs[REG_INDEX(NIP)] = gregs.nip;
regs[REG_INDEX(R0)] = gregs.gpr[0];
regs[REG_INDEX(R1)] = gregs.gpr[1];
regs[REG_INDEX(R2)] = gregs.gpr[2];
regs[REG_INDEX(R3)] = gregs.gpr[3];
regs[REG_INDEX(R4)] = gregs.gpr[4];
regs[REG_INDEX(R5)] = gregs.gpr[5];
regs[REG_INDEX(R6)] = gregs.gpr[6];
regs[REG_INDEX(R7)] = gregs.gpr[7];
regs[REG_INDEX(R8)] = gregs.gpr[8];
regs[REG_INDEX(R9)] = gregs.gpr[9];
regs[REG_INDEX(R10)] = gregs.gpr[10];
regs[REG_INDEX(R11)] = gregs.gpr[11];
regs[REG_INDEX(R12)] = gregs.gpr[12];
regs[REG_INDEX(R13)] = gregs.gpr[13];
regs[REG_INDEX(R14)] = gregs.gpr[14];
regs[REG_INDEX(R15)] = gregs.gpr[15];
regs[REG_INDEX(R16)] = gregs.gpr[16];
regs[REG_INDEX(R17)] = gregs.gpr[17];
regs[REG_INDEX(R18)] = gregs.gpr[18];
regs[REG_INDEX(R19)] = gregs.gpr[19];
regs[REG_INDEX(R20)] = gregs.gpr[20];
regs[REG_INDEX(R21)] = gregs.gpr[21];
regs[REG_INDEX(R22)] = gregs.gpr[22];
regs[REG_INDEX(R23)] = gregs.gpr[23];
regs[REG_INDEX(R24)] = gregs.gpr[24];
regs[REG_INDEX(R25)] = gregs.gpr[25];
regs[REG_INDEX(R26)] = gregs.gpr[26];
regs[REG_INDEX(R27)] = gregs.gpr[27];
regs[REG_INDEX(R28)] = gregs.gpr[28];
regs[REG_INDEX(R29)] = gregs.gpr[29];
regs[REG_INDEX(R30)] = gregs.gpr[30];
regs[REG_INDEX(R31)] = gregs.gpr[31];
#endif
(*env)->ReleaseLongArrayElements(env, array, regs, JNI_COMMIT);
return array;

View File

@ -27,9 +27,11 @@
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <elf.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/uio.h>
#include "libproc_impl.h"
#if defined(x86_64) && !defined(amd64)
@ -138,6 +140,15 @@ static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct use
return false;
}
return true;
#elif defined(PTRACE_GETREGSET)
struct iovec iov;
iov.iov_base = user;
iov.iov_len = sizeof(*user);
if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, (void*) &iov) < 0) {
print_debug("ptrace(PTRACE_GETREGSET, ...) failed for lwp %d\n", pid);
return false;
}
return true;
#else
print_debug("ptrace(PTRACE_GETREGS, ...) not supported\n");
return false;

View File

@ -325,6 +325,12 @@ static struct symtab* build_symtab_internal(int fd, const char *filename, bool t
// Reading of elf header
struct elf_section *scn_cache = NULL;
#if defined(ppc64) && !defined(ABI_ELFv2)
// Only big endian ppc64 (i.e. ABI_ELFv1) has 'official procedure descriptors' in ELF files
// see: http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Core-PPC64/LSB-Core-PPC64/specialsections.html
struct elf_section *opd_sect = NULL;
ELF_SHDR *opd = NULL;
#endif
int cnt = 0;
ELF_SHDR* shbuf = NULL;
ELF_SHDR* cursct = NULL;
@ -368,6 +374,14 @@ static struct symtab* build_symtab_internal(int fd, const char *filename, bool t
cursct++;
}
#if defined(ppc64) && !defined(ABI_ELFv2)
opd_sect = find_section_by_name(".opd", fd, &ehdr, scn_cache);
if (opd_sect != NULL && opd_sect->c_data != NULL && opd_sect->c_shdr != NULL) {
// plausibility check
opd = opd_sect->c_shdr;
}
#endif
for (cnt = 1; cnt < ehdr.e_shnum; cnt++) {
ELF_SHDR *shdr = scn_cache[cnt].c_shdr;
@ -412,6 +426,7 @@ static struct symtab* build_symtab_internal(int fd, const char *filename, bool t
// copy symbols info our symtab and enter them info the hash table
for (j = 0; j < n; j++, syms++) {
ENTRY item, *ret;
uintptr_t sym_value;
char *sym_name = symtab->strs + syms->st_name;
// skip non-object and non-function symbols
@ -422,9 +437,19 @@ static struct symtab* build_symtab_internal(int fd, const char *filename, bool t
if (*sym_name == '\0' || syms->st_shndx == SHN_UNDEF) continue;
symtab->symbols[j].name = sym_name;
symtab->symbols[j].offset = syms->st_value - baseaddr;
symtab->symbols[j].size = syms->st_size;
sym_value = syms->st_value;
#if defined(ppc64) && !defined(ABI_ELFv2)
// see hotspot/src/share/vm/utilities/elfFuncDescTable.hpp for a detailed description
// of why we have to go this extra way via the '.opd' section on big endian ppc64
if (opd != NULL && *sym_name != '.' &&
(opd->sh_addr <= sym_value && sym_value <= opd->sh_addr + opd->sh_size)) {
sym_value = ((ELF_ADDR*)opd_sect->c_data)[(sym_value - opd->sh_addr) / sizeof(ELF_ADDR*)];
}
#endif
symtab->symbols[j].offset = sym_value - baseaddr;
item.key = sym_name;
item.data = (void *)&(symtab->symbols[j]);
@ -433,9 +458,17 @@ static struct symtab* build_symtab_internal(int fd, const char *filename, bool t
}
}
#if defined(ppc64) && !defined(ABI_ELFv2)
// On Linux/PPC64 the debuginfo files contain an empty function descriptor
// section (i.e. '.opd' section) which makes the resolution of symbols
// with the above algorithm impossible (we would need the have both, the
// .opd section from the library and the symbol table from the debuginfo
// file which doesn't match with the current workflow.)
goto quit;
#endif
// Look for a separate debuginfo file.
if (try_debuginfo) {
// We prefer a debug symtab to an object's own symtab, so look in
// the debuginfo file. We stash a copy of the old symtab in case
// there is no debuginfo.

View File

@ -34,6 +34,6 @@ public class MachineDescriptionPPC64 extends MachineDescriptionTwosComplement im
}
public boolean isBigEndian() {
return true;
return "big".equals(System.getProperty("sun.cpu.endian"));
}
}

View File

@ -26,14 +26,17 @@ package sun.jvm.hotspot.debugger.linux;
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.x86.*;
import sun.jvm.hotspot.debugger.amd64.*;
import sun.jvm.hotspot.debugger.sparc.*;
import sun.jvm.hotspot.debugger.ppc64.*;
import sun.jvm.hotspot.debugger.linux.x86.*;
import sun.jvm.hotspot.debugger.linux.amd64.*;
import sun.jvm.hotspot.debugger.linux.sparc.*;
import sun.jvm.hotspot.debugger.linux.ppc64.*;
import sun.jvm.hotspot.utilities.*;
class LinuxCDebugger implements CDebugger {
@ -96,7 +99,14 @@ class LinuxCDebugger implements CDebugger {
Address pc = context.getRegisterAsAddress(SPARCThreadContext.R_O7);
if (pc == null) return null;
return new LinuxSPARCCFrame(dbg, sp, pc, LinuxDebuggerLocal.getAddressSize());
} else {
} else if (cpu.equals("ppc64")) {
PPC64ThreadContext context = (PPC64ThreadContext) thread.getContext();
Address sp = context.getRegisterAsAddress(PPC64ThreadContext.SP);
if (sp == null) return null;
Address pc = context.getRegisterAsAddress(PPC64ThreadContext.PC);
if (pc == null) return null;
return new LinuxPPC64CFrame(dbg, sp, pc, LinuxDebuggerLocal.getAddressSize());
} else {
// Runtime exception thrown by LinuxThreadContextFactory if unknown cpu
ThreadContext context = (ThreadContext) thread.getContext();
return context.getTopFrame(dbg);

View File

@ -29,6 +29,7 @@ import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.linux.amd64.*;
import sun.jvm.hotspot.debugger.linux.ia64.*;
import sun.jvm.hotspot.debugger.linux.x86.*;
import sun.jvm.hotspot.debugger.linux.ppc64.*;
import sun.jvm.hotspot.debugger.linux.sparc.*;
class LinuxThreadContextFactory {
@ -42,6 +43,8 @@ class LinuxThreadContextFactory {
return new LinuxIA64ThreadContext(dbg);
} else if (cpu.equals("sparc")) {
return new LinuxSPARCThreadContext(dbg);
} else if (cpu.equals("ppc64")) {
return new LinuxPPC64ThreadContext(dbg);
} else {
try {
Class tcc = Class.forName("sun.jvm.hotspot.debugger.linux." +

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.linux.ppc64;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.ppc64.*;
import sun.jvm.hotspot.debugger.linux.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.cdbg.basic.*;
final public class LinuxPPC64CFrame extends BasicCFrame {
// package/class internals only
public LinuxPPC64CFrame(LinuxDebugger dbg, Address sp, Address pc, int address_size) {
super(dbg.getCDebugger());
this.sp = sp;
this.pc = pc;
this.dbg = dbg;
this.address_size = address_size;
}
// override base class impl to avoid ELF parsing
public ClosestSymbol closestSymbolToPC() {
// try native lookup in debugger.
return dbg.lookup(dbg.getAddressValue(pc()));
}
public Address pc() {
return pc;
}
public Address localVariableBase() {
return sp;
}
public CFrame sender(ThreadProxy thread) {
if (sp == null) {
return null;
}
Address nextSP = sp.getAddressAt(0);
if (nextSP == null) {
return null;
}
Address nextPC = sp.getAddressAt(2 * address_size);
if (nextPC == null) {
return null;
}
return new LinuxPPC64CFrame(dbg, nextSP, nextPC, address_size);
}
public static int PPC64_STACK_BIAS = 0;
private static int address_size;
private Address pc;
private Address sp;
private LinuxDebugger dbg;
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.linux.ppc64;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.ppc64.*;
import sun.jvm.hotspot.debugger.linux.*;
public class LinuxPPC64ThreadContext extends PPC64ThreadContext {
private LinuxDebugger debugger;
public LinuxPPC64ThreadContext(LinuxDebugger debugger) {
super();
this.debugger = debugger;
}
public void setRegisterAsAddress(int index, Address value) {
setRegister(index, debugger.getAddressValue(value));
}
public Address getRegisterAsAddress(int index) {
return debugger.newAddress(getRegister(index));
}
}

View File

@ -0,0 +1,123 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.ppc64;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.cdbg.*;
/** Specifies the thread context on ppc64 platforms; only a sub-portion
* of the context is guaranteed to be present on all operating
* systems. */
public abstract class PPC64ThreadContext implements ThreadContext {
// NOTE: The indices for the various registers must be maintained as
// listed across various operating systems. However, only a small
// subset of the registers' values are guaranteed to be present (and
// must be present for the SA's stack walking to work).
public static final int R31 = 0;
public static final int R30 = 1;
public static final int R29 = 2;
public static final int R28 = 3;
public static final int R27 = 4;
public static final int R26 = 5;
public static final int R25 = 6;
public static final int R24 = 7;
public static final int R23 = 8;
public static final int R22 = 9;
public static final int R21 = 10;
public static final int R20 = 11;
public static final int R19 = 12;
public static final int R18 = 13;
public static final int R17 = 14;
public static final int R16 = 15;
public static final int R15 = 16;
public static final int R14 = 17;
public static final int R13 = 18;
public static final int R12 = 19;
public static final int R11 = 20;
public static final int R10 = 21;
public static final int R9 = 22;
public static final int R8 = 23;
public static final int R7 = 24;
public static final int R6 = 25;
public static final int R5 = 26;
public static final int R4 = 27;
public static final int R3 = 28;
public static final int R2 = 29;
public static final int R1 = 30;
public static final int R0 = 31;
public static final int NIP = 32;
public static final int LR = 33;
public static final int NPRGREG = 34;
private static final String[] regNames = {
"r31", "r30", "r29", "r28", "r27", "r26", "r25", "r24",
"r23", "r22", "r21", "r20", "r19", "r18", "r17", "r16",
"r15", "r14", "r13", "r12", "r11", "r10", "r9", "r8",
"r7", "r6", "r5", "r4", "r3", "r2", "r1", "r0",
"nip", "link"
};
public static final int PC = NIP;
public static final int SP = R1;
private long[] data;
public PPC64ThreadContext() {
data = new long[NPRGREG];
}
public int getNumRegisters() {
return NPRGREG;
}
public String getRegisterName(int index) {
return regNames[index];
}
public void setRegister(int index, long value) {
data[index] = value;
}
public long getRegister(int index) {
return data[index];
}
public CFrame getTopFrame(Debugger dbg) {
return null;
}
/** This can't be implemented in this class since we would have to
* tie the implementation to, for example, the debugging system */
public abstract void setRegisterAsAddress(int index, Address value);
/** This can't be implemented in this class since we would have to
* tie the implementation to, for example, the debugging system */
public abstract Address getRegisterAsAddress(int index);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,7 +32,9 @@ import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.proc.amd64.*;
import sun.jvm.hotspot.debugger.proc.sparc.*;
import sun.jvm.hotspot.debugger.proc.ppc64.*;
import sun.jvm.hotspot.debugger.proc.x86.*;
import sun.jvm.hotspot.debugger.ppc64.*;
import sun.jvm.hotspot.debugger.amd64.*;
import sun.jvm.hotspot.debugger.sparc.*;
import sun.jvm.hotspot.debugger.x86.*;
@ -86,6 +88,10 @@ public class ProcDebuggerLocal extends DebuggerBase implements ProcDebugger {
threadFactory = new ProcAMD64ThreadFactory(this);
pcRegIndex = AMD64ThreadContext.RIP;
fpRegIndex = AMD64ThreadContext.RBP;
} else if (cpu.equals("ppc64")) {
threadFactory = new ProcPPC64ThreadFactory(this);
pcRegIndex = PPC64ThreadContext.PC;
fpRegIndex = PPC64ThreadContext.SP;
} else {
try {
Class tfc = Class.forName("sun.jvm.hotspot.debugger.proc." +

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.proc.ppc64;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.ppc64.*;
import sun.jvm.hotspot.debugger.proc.*;
import sun.jvm.hotspot.utilities.*;
public class ProcPPC64Thread implements ThreadProxy {
private ProcDebugger debugger;
private int id;
public ProcPPC64Thread(ProcDebugger debugger, Address addr) {
this.debugger = debugger;
// FIXME: the size here should be configurable. However, making it
// so would produce a dependency on the "types" package from the
// debugger package, which is not desired.
this.id = (int) addr.getCIntegerAt(0, 4, true);
}
public ProcPPC64Thread(ProcDebugger debugger, long id) {
this.debugger = debugger;
this.id = (int) id;
}
public ThreadContext getContext() throws IllegalThreadStateException {
ProcPPC64ThreadContext context = new ProcPPC64ThreadContext(debugger);
long[] regs = debugger.getThreadIntegerRegisterSet(id);
if (Assert.ASSERTS_ENABLED) {
Assert.that(regs.length <= PPC64ThreadContext.NPRGREG, "size of register set is greater than " + PPC64ThreadContext.NPRGREG);
}
for (int i = 0; i < regs.length; i++) {
context.setRegister(i, regs[i]);
}
return context;
}
public boolean canSetContext() throws DebuggerException {
return false;
}
public void setContext(ThreadContext context)
throws IllegalThreadStateException, DebuggerException {
throw new DebuggerException("Unimplemented");
}
public String toString() {
return "t@" + id;
}
public boolean equals(Object obj) {
if ((obj == null) || !(obj instanceof ProcPPC64Thread)) {
return false;
}
return (((ProcPPC64Thread) obj).id == id);
}
public int hashCode() {
return id;
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.proc.ppc64;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.ppc64.*;
import sun.jvm.hotspot.debugger.proc.*;
public class ProcPPC64ThreadContext extends PPC64ThreadContext {
private ProcDebugger debugger;
public ProcPPC64ThreadContext(ProcDebugger debugger) {
super();
this.debugger = debugger;
}
public void setRegisterAsAddress(int index, Address value) {
setRegister(index, debugger.getAddressValue(value));
}
public Address getRegisterAsAddress(int index) {
return debugger.newAddress(getRegister(index));
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.proc.ppc64;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.proc.*;
public class ProcPPC64ThreadFactory implements ProcThreadFactory {
private ProcDebugger debugger;
public ProcPPC64ThreadFactory(ProcDebugger debugger) {
this.debugger = debugger;
}
public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) {
return new ProcPPC64Thread(debugger, threadIdentifierAddr);
}
public ThreadProxy createThreadWrapper(long id) {
return new ProcPPC64Thread(debugger, id);
}
}

View File

@ -33,6 +33,7 @@ import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.remote.sparc.*;
import sun.jvm.hotspot.debugger.remote.x86.*;
import sun.jvm.hotspot.debugger.remote.amd64.*;
import sun.jvm.hotspot.debugger.remote.ppc64.*;
/** An implementation of Debugger which wraps a
RemoteDebugger, providing remote debugging via RMI.
@ -70,6 +71,11 @@ public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger {
cachePageSize = 4096;
cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
unalignedAccessesOkay = true;
} else if (cpu.equals("ppc64")) {
threadFactory = new RemotePPC64ThreadFactory(this);
cachePageSize = 4096;
cacheNumPages = parseCacheNumPagesProperty(cacheSize / cachePageSize);
unalignedAccessesOkay = true;
} else {
try {
Class tf = Class.forName("sun.jvm.hotspot.debugger.remote." +

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.remote.ppc64;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.ppc64.*;
import sun.jvm.hotspot.debugger.remote.*;
import sun.jvm.hotspot.utilities.*;
public class RemotePPC64Thread extends RemoteThread {
public RemotePPC64Thread(RemoteDebuggerClient debugger, Address addr) {
super(debugger, addr);
}
public RemotePPC64Thread(RemoteDebuggerClient debugger, long id) {
super(debugger, id);
}
public ThreadContext getContext() throws IllegalThreadStateException {
RemotePPC64ThreadContext context = new RemotePPC64ThreadContext(debugger);
long[] regs = (addr != null)? debugger.getThreadIntegerRegisterSet(addr) :
debugger.getThreadIntegerRegisterSet(id);
if (Assert.ASSERTS_ENABLED) {
Assert.that(regs.length == PPC64ThreadContext.NPRGREG, "size of register set must match");
}
for (int i = 0; i < regs.length; i++) {
context.setRegister(i, regs[i]);
}
return context;
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.remote.ppc64;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.ppc64.*;
import sun.jvm.hotspot.debugger.remote.*;
public class RemotePPC64ThreadContext extends PPC64ThreadContext {
private RemoteDebuggerClient debugger;
public RemotePPC64ThreadContext(RemoteDebuggerClient debugger) {
super();
this.debugger = debugger;
}
/** This can't be implemented in this class since we would have to
tie the implementation to, for example, the debugging system */
public void setRegisterAsAddress(int index, Address value) {
setRegister(index, debugger.getAddressValue(value));
}
/** This can't be implemented in this class since we would have to
tie the implementation to, for example, the debugging system */
public Address getRegisterAsAddress(int index) {
return debugger.newAddress(getRegister(index));
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.debugger.remote.ppc64;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.remote.*;
public class RemotePPC64ThreadFactory implements RemoteThreadFactory {
private RemoteDebuggerClient debugger;
public RemotePPC64ThreadFactory(RemoteDebuggerClient debugger) {
this.debugger = debugger;
}
public ThreadProxy createThreadWrapper(Address threadIdentifierAddr) {
return new RemotePPC64Thread(debugger, threadIdentifierAddr);
}
public ThreadProxy createThreadWrapper(long id) {
return new RemotePPC64Thread(debugger, id);
}
}

View File

@ -25,6 +25,7 @@
package sun.jvm.hotspot.runtime;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.runtime.solaris_sparc.SolarisSPARCJavaThreadPDAccess;
@ -34,6 +35,7 @@ import sun.jvm.hotspot.runtime.win32_amd64.Win32AMD64JavaThreadPDAccess;
import sun.jvm.hotspot.runtime.win32_x86.Win32X86JavaThreadPDAccess;
import sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess;
import sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess;
import sun.jvm.hotspot.runtime.linux_ppc64.LinuxPPC64JavaThreadPDAccess;
import sun.jvm.hotspot.runtime.linux_sparc.LinuxSPARCJavaThreadPDAccess;
import sun.jvm.hotspot.runtime.bsd_x86.BsdX86JavaThreadPDAccess;
import sun.jvm.hotspot.runtime.bsd_amd64.BsdAMD64JavaThreadPDAccess;
@ -87,6 +89,8 @@ public class Threads {
access = new LinuxAMD64JavaThreadPDAccess();
} else if (cpu.equals("sparc")) {
access = new LinuxSPARCJavaThreadPDAccess();
} else if (cpu.equals("ppc64")) {
access = new LinuxPPC64JavaThreadPDAccess();
} else {
try {
access = (JavaThreadPDAccess)

View File

@ -78,7 +78,7 @@ public class VFrame {
}
if (f.isRuntimeFrame()) {
// This is a conversion frame. Skip this frame and try again.
// This is a conversion frame or a Stub routine. Skip this frame and try again.
RegisterMap tempMap = regMap.copy();
Frame s = f.sender(tempMap);
return newVFrame(s, tempMap, thread, unsafe, false);

View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.runtime.linux_ppc64;
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.ppc64.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.runtime.ppc64.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;
public class LinuxPPC64JavaThreadPDAccess implements JavaThreadPDAccess {
private static AddressField osThreadField;
// Field from OSThread
private static CIntegerField osThreadThreadIDField;
// This is currently unneeded but is being kept in case we change
// the currentFrameGuess algorithm
private static final long GUESS_SCAN_RANGE = 128 * 1024;
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("JavaThread");
osThreadField = type.getAddressField("_osthread");
Type osThreadType = db.lookupType("OSThread");
osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id");
}
public Address getLastJavaFP(Address addr) {
return null;
}
public Address getLastJavaPC(Address addr) {
return null;
}
public Address getBaseOfStackPointer(Address addr) {
return null;
}
public Frame getLastFramePD(JavaThread thread, Address addr) {
Address fp = thread.getLastJavaFP();
if (fp == null) {
return null; // no information
}
return new PPC64Frame(thread.getLastJavaSP(), fp);
}
public RegisterMap newRegisterMap(JavaThread thread, boolean updateMap) {
return new PPC64RegisterMap(thread, updateMap);
}
public Frame getCurrentFrameGuess(JavaThread thread, Address addr) {
ThreadProxy t = getThreadProxy(addr);
PPC64ThreadContext context = (PPC64ThreadContext) t.getContext();
PPC64CurrentFrameGuess guesser = new PPC64CurrentFrameGuess(context, thread);
if (!guesser.run(GUESS_SCAN_RANGE)) {
return null;
}
if (guesser.getPC() == null) {
return new PPC64Frame(guesser.getSP(), guesser.getFP());
} else {
return new PPC64Frame(guesser.getSP(), guesser.getFP(), guesser.getPC());
}
}
public void printThreadIDOn(Address addr, PrintStream tty) {
tty.print(getThreadProxy(addr));
}
public void printInfoOn(Address threadAddr, PrintStream tty) {
tty.print("Thread id: ");
printThreadIDOn(threadAddr, tty);
// tty.println("\nPostJavaState: " + getPostJavaState(threadAddr));
}
public Address getLastSP(Address addr) {
ThreadProxy t = getThreadProxy(addr);
PPC64ThreadContext context = (PPC64ThreadContext) t.getContext();
return context.getRegisterAsAddress(PPC64ThreadContext.SP);
}
public Address getLastFP(Address addr) {
return getLastSP(addr).getAddressAt(0);
}
public ThreadProxy getThreadProxy(Address addr) {
// Addr is the address of the JavaThread.
// Fetch the OSThread (for now and for simplicity, not making a
// separate "OSThread" class in this package)
Address osThreadAddr = osThreadField.getValue(addr);
// Get the address of the _thread_id from the OSThread
Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
JVMDebugger debugger = VM.getVM().getDebugger();
return debugger.getThreadForIdentifierAddress(threadIdAddr);
}
}

View File

@ -0,0 +1,179 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.runtime.ppc64;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.ppc64.*;
import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.interpreter.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.runtime.ppc64.*;
/** <P> Should be able to be used on all ppc64 platforms we support
(Linux/ppc64) to implement JavaThread's "currentFrameGuess()"
functionality. Input is a PPC64ThreadContext; output is SP, FP,
and PC for an PPC64Frame. Instantiation of the PPC64Frame is left
to the caller, since we may need to subclass PPC64Frame to support
signal handler frames on Unix platforms. </P>
*/
public class PPC64CurrentFrameGuess {
private PPC64ThreadContext context;
private JavaThread thread;
private Address spFound;
private Address fpFound;
private Address pcFound;
private static final boolean DEBUG;
static {
DEBUG = System.getProperty("sun.jvm.hotspot.runtime.ppc64.PPC64Frame.DEBUG") != null;
}
public PPC64CurrentFrameGuess(PPC64ThreadContext context,
JavaThread thread) {
this.context = context;
this.thread = thread;
}
/** Returns false if not able to find a frame within a reasonable range. */
public boolean run(long regionInBytesToSearch) {
Address sp = context.getRegisterAsAddress(PPC64ThreadContext.SP);
Address pc = context.getRegisterAsAddress(PPC64ThreadContext.PC);
if (sp == null) {
// Bail out if no last java frame either
if (thread.getLastJavaSP() != null) {
Address javaSP = thread.getLastJavaSP();
Address javaFP = javaSP.getAddressAt(0);
setValues(javaSP, javaFP, null);
return true;
}
return false;
}
/* There is no frame pointer per se for the ppc64 architecture. To mirror
* the behavior of the VM frame manager, we set fp to be the caller's (i.e., "sender's")
* stack pointer, which is the back chain value contained in our sp.
*/
Address fp = sp.getAddressAt(0);
setValues(null, null, null); // Assume we're not going to find anything
VM vm = VM.getVM();
if (vm.isJavaPCDbg(pc)) {
if (vm.isClientCompiler()) {
// Topmost frame is a Java frame.
if (DEBUG) {
System.out.println("CurrentFrameGuess: choosing compiler frame: sp = " +
sp + ", fp = " + fp + ", pc = " + pc);
}
setValues(sp, fp, pc);
return true;
} else {
if (vm.getInterpreter().contains(pc)) {
if (DEBUG) {
System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " +
sp + ", fp = " + fp + ", pc = " + pc);
}
setValues(sp, fp, pc);
return true;
}
// This algorithm takes the current PC as a given and tries to
// find the correct corresponding SP by walking up the stack
// and repeatedly performing stackwalks (very inefficient).
for (long offset = 0;
offset < regionInBytesToSearch;
offset += vm.getAddressSize()) {
try {
Address curSP = sp.addOffsetTo(offset);
fp = curSP.getAddressAt(0);
Frame frame = new PPC64Frame(curSP, fp, pc);
RegisterMap map = thread.newRegisterMap(false);
while (frame != null) {
if (frame.isEntryFrame() && frame.entryFrameIsFirst()) {
// We were able to traverse all the way to the
// bottommost Java frame.
// This sp looks good. Keep it.
if (DEBUG) {
System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc);
}
setValues(curSP, fp, pc);
return true;
}
frame = frame.sender(map);
}
} catch (Exception e) {
if (DEBUG) {
System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset);
}
// Bad SP. Try another.
}
}
// Were not able to find a plausible SP to go with this PC.
// Bail out.
return false;
}
} else {
// If the current program counter was not known to us as a Java
// PC, we currently assume that we are in the run-time system
// and attempt to look to thread-local storage for saved java SP.
// Note that if this is null (because we were, in fact,
// in Java code, i.e., vtable stubs or similar, and the SA
// didn't have enough insight into the target VM to understand
// that) then we are going to lose the entire stack trace for
// the thread, which is sub-optimal. FIXME.
if (thread.getLastJavaSP() == null) {
if (DEBUG) {
System.out.println("CurrentFrameGuess: last java sp is null");
}
return false; // No known Java frames on stack
}
Address javaSP = thread.getLastJavaSP();
Address javaFP = javaSP.getAddressAt(0);
Address javaPC = thread.getLastJavaPC();
if (DEBUG) {
System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " +
javaSP + ", fp = " + javaFP + ", pc = " + javaPC);
}
setValues(javaSP, javaFP, javaPC);
return true;
}
}
public Address getSP() { return spFound; }
public Address getFP() { return fpFound; }
/** May be null if getting values from thread-local storage; take
care to call the correct PPC64Frame constructor to recover this if
necessary */
public Address getPC() { return pcFound; }
private void setValues(Address sp, Address fp, Address pc) {
spFound = sp;
fpFound = fp;
pcFound = pc;
}
}

View File

@ -0,0 +1,513 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.runtime.ppc64;
import java.util.*;
import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.compiler.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;
/** Specialization of and implementation of abstract methods of the
Frame class for the ppc64 family of CPUs. */
public class PPC64Frame extends Frame {
private static final boolean DEBUG;
static {
DEBUG = System.getProperty("sun.jvm.hotspot.runtime.ppc64.PPC64Frame.DEBUG") != null;
}
// All frames
private static final int SENDER_SP_OFFSET = 0;
// Interpreter frames
private static final int INTERPRETER_FRAME_MIRROR_OFFSET = -3; // for native calls only
private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -4;
private static final int INTERPRETER_FRAME_LAST_SP_OFFSET = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1;
private static final int INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_LAST_SP_OFFSET -1;
private static final int INTERPRETER_FRAME_ESP_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1;
private static final int INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_ESP_OFFSET - 1;
private static final int INTERPRETER_FRAME_CACHE_OFFSET =INTERPRETER_FRAME_BCX_OFFSET - 1;
private static final int INTERPRETER_FRAME_MONITORS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1;
private static final int INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_MONITORS_OFFSET - 1;
private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
private static final int INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1; // FIXME: probably wrong, but unused anyway
private static final int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
private static final int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
// Entry frames
private static int ENTRY_FRAME_CALL_WRAPPER_OFFSET;
// Native frames
private static int NATIVE_FRAME_INITIAL_PARAM_OFFSET;
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) {
int abi_minframe_size = db.lookupIntConstant("frame::abi_minframe_size").intValue();
int entry_frame_locals_size = db.lookupIntConstant("frame::entry_frame_locals_size").intValue();
int wordLength = (int) VM.getVM().getAddressSize();
NATIVE_FRAME_INITIAL_PARAM_OFFSET = -abi_minframe_size/wordLength;
ENTRY_FRAME_CALL_WRAPPER_OFFSET = -entry_frame_locals_size/wordLength;
}
// an additional field beyond sp and pc:
Address raw_fp; // frame pointer
private Address raw_unextendedSP;
private PPC64Frame() {
}
private void adjustForDeopt() {
if ( pc != null) {
// Look for a deopt pc and if it is deopted convert to original pc
CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
if (cb != null && cb.isJavaMethod()) {
NMethod nm = (NMethod) cb;
if (pc.equals(nm.deoptHandlerBegin())) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
}
// adjust pc if frame is deoptimized.
pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
deoptimized = true;
}
}
}
}
public PPC64Frame(Address raw_sp, Address raw_fp, Address pc) {
this.raw_sp = raw_sp;
this.raw_unextendedSP = raw_sp;
if (raw_fp == null) {
this.raw_fp = raw_sp.getAddressAt(0);
} else {
this.raw_fp = raw_fp;
}
if (pc == null) {
this.pc = raw_sp.getAddressAt(2 * VM.getVM().getAddressSize());
} else {
this.pc = pc;
}
adjustUnextendedSP();
// Frame must be fully constructed before this call
adjustForDeopt();
if (DEBUG) {
System.out.println("PPC64Frame(sp, fp, pc): " + this);
dumpStack();
}
}
public PPC64Frame(Address raw_sp, Address raw_fp) {
this.raw_sp = raw_sp;
this.raw_unextendedSP = raw_sp;
if (raw_fp == null) {
this.raw_fp = raw_sp.getAddressAt(0);
} else {
this.raw_fp = raw_fp;
}
this.pc = raw_sp.getAddressAt(2 * VM.getVM().getAddressSize());
adjustUnextendedSP();
// Frame must be fully constructed before this call
adjustForDeopt();
if (DEBUG) {
System.out.println("PPC64Frame(sp, fp): " + this);
dumpStack();
}
}
public PPC64Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) {
this.raw_sp = raw_sp;
this.raw_unextendedSP = raw_unextendedSp;
if (raw_fp == null) {
this.raw_fp = raw_sp.getAddressAt(0);
} else {
this.raw_fp = raw_fp;
}
if (pc == null) {
this.pc = raw_sp.getAddressAt(2 * VM.getVM().getAddressSize());
} else {
this.pc = pc;
}
adjustUnextendedSP();
// Frame must be fully constructed before this call
adjustForDeopt();
if (DEBUG) {
System.out.println("PPC64Frame(sp, unextendedSP, fp, pc): " + this);
dumpStack();
}
}
public Object clone() {
PPC64Frame frame = new PPC64Frame();
frame.raw_sp = raw_sp;
frame.raw_unextendedSP = raw_unextendedSP;
frame.raw_fp = raw_fp;
frame.pc = pc;
frame.deoptimized = deoptimized;
return frame;
}
public boolean equals(Object arg) {
if (arg == null) {
return false;
}
if (!(arg instanceof PPC64Frame)) {
return false;
}
PPC64Frame other = (PPC64Frame) arg;
return (AddressOps.equal(getSP(), other.getSP()) &&
AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) &&
AddressOps.equal(getFP(), other.getFP()) &&
AddressOps.equal(getPC(), other.getPC()));
}
public int hashCode() {
if (raw_sp == null) {
return 0;
}
return raw_sp.hashCode();
}
public String toString() {
return "sp: " + (getSP() == null ? "null" : getSP().toString()) +
", unextendedSP: " + (getUnextendedSP() == null ? "null" : getUnextendedSP().toString()) +
", fp: " + (getFP() == null ? "null" : getFP().toString()) +
", pc: " + (pc == null ? "null" : pc.toString());
}
// accessors for the instance variables
public Address getFP() { return raw_fp; }
public Address getSP() { return raw_sp; }
public Address getID() { return raw_sp; }
// FIXME: not implemented yet (should be done for Solaris/PPC64)
public boolean isSignalHandlerFrameDbg() { return false; }
public int getSignalNumberDbg() { return 0; }
public String getSignalNameDbg() { return null; }
public boolean isInterpretedFrameValid() {
if (Assert.ASSERTS_ENABLED) {
Assert.that(isInterpretedFrame(), "Not an interpreted frame");
}
// These are reasonable sanity checks
if (getFP() == null || getFP().andWithMask(0x3) != null) {
return false;
}
if (getSP() == null || getSP().andWithMask(0x3) != null) {
return false;
}
// These are hacks to keep us out of trouble.
// The problem with these is that they mask other problems
if (getFP().lessThanOrEqual(getSP())) {
// this attempts to deal with unsigned comparison above
return false;
}
if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) {
// stack frames shouldn't be large.
return false;
}
return true;
}
// FIXME: not applicable in current system
// void patch_pc(Thread* thread, address pc);
public Frame sender(RegisterMap regMap, CodeBlob cb) {
PPC64RegisterMap map = (PPC64RegisterMap) regMap;
if (Assert.ASSERTS_ENABLED) {
Assert.that(map != null, "map must be set");
}
// Default is we done have to follow them. The sender_for_xxx will
// update it accordingly
map.setIncludeArgumentOops(false);
if (isEntryFrame()) return senderForEntryFrame(map);
if (isInterpretedFrame()) return senderForInterpreterFrame(map);
if(cb == null) {
cb = VM.getVM().getCodeCache().findBlob(getPC());
} else {
if (Assert.ASSERTS_ENABLED) {
Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
}
}
if (cb != null) {
return senderForCompiledFrame(map, cb);
}
// Must be native-compiled frame, i.e. the marshaling code for native
// methods that exists in the core system.
return new PPC64Frame(getSenderSP(), getLink(), getSenderPC());
}
private Frame senderForEntryFrame(PPC64RegisterMap map) {
if (DEBUG) {
System.out.println("senderForEntryFrame");
}
if (Assert.ASSERTS_ENABLED) {
Assert.that(map != null, "map must be set");
}
// Java frame called from C; skip all C frames and return top C
// frame of that chunk as the sender
PPC64JavaCallWrapper jcw = (PPC64JavaCallWrapper) getEntryFrameCallWrapper();
if (Assert.ASSERTS_ENABLED) {
Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero");
Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack");
}
PPC64Frame fr;
if (jcw.getLastJavaPC() != null) {
fr = new PPC64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC());
} else {
fr = new PPC64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP());
}
map.clear();
if (Assert.ASSERTS_ENABLED) {
Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
}
return fr;
}
//------------------------------------------------------------------------------
// frame::adjust_unextended_sp
private void adjustUnextendedSP() {
raw_unextendedSP = getFP();
}
private Frame senderForInterpreterFrame(PPC64RegisterMap map) {
if (DEBUG) {
System.out.println("senderForInterpreterFrame");
}
Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
Address sp = getSenderSP();
return new PPC64Frame(sp, unextendedSP, getLink(), getSenderPC());
}
private Frame senderForCompiledFrame(PPC64RegisterMap map, CodeBlob cb) {
if (DEBUG) {
System.out.println("senderForCompiledFrame");
}
//
// NOTE: some of this code is (unfortunately) duplicated in PPC64CurrentFrameGuess
//
if (Assert.ASSERTS_ENABLED) {
Assert.that(map != null, "map must be set");
}
// frame owned by optimizing compiler
if (Assert.ASSERTS_ENABLED) {
Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size");
}
Address senderSP = getSenderSP();
Address senderPC = getSenderPC();
if (map.getUpdateMap()) {
// Tell GC to use argument oopmaps for some runtime stubs that need it.
// For C1, the runtime stub might not have oop maps, so set this flag
// outside of update_register_map.
map.setIncludeArgumentOops(cb.callerMustGCArguments());
if (cb.getOopMaps() != null) {
OopMapSet.updateRegisterMap(this, cb, map, true);
}
}
return new PPC64Frame(senderSP, getLink(), senderPC);
}
protected boolean hasSenderPD() {
// FIXME
return true;
}
public long frameSize() {
return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize());
}
public Address getLink() {
return getSenderSP().getAddressAt(0);
}
public Address getUnextendedSP() { return raw_unextendedSP; }
// Return address:
public Address getSenderPC() { return getSenderSP().getAddressAt(2 * VM.getVM().getAddressSize()); }
// return address of param, zero origin index.
// MPJ note: Appears to be unused.
public Address getNativeParamAddr(int idx) {
return null;
// return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx);
}
public Address getSenderSP() { return getFP(); }
public Address addressOfInterpreterFrameLocals() {
return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET);
}
private Address addressOfInterpreterFrameBCX() {
return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET);
}
public int getInterpreterFrameBCI() {
// FIXME: this is not atomic with respect to GC and is unsuitable
// for use in a non-debugging, or reflective, system. Need to
// figure out how to express this.
Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0);
Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0);
Method method = (Method)Metadata.instantiateWrapperFor(methodHandle);
return bcpToBci(bcp, method);
}
public Address addressOfInterpreterFrameMDX() {
return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET);
}
// FIXME
//inline int frame::interpreter_frame_monitor_size() {
// return BasicObjectLock::size();
//}
// expression stack
// (the max_stack arguments are used by the GC; see class FrameClosure)
public Address addressOfInterpreterFrameExpressionStack() {
Address monitorEnd = interpreterFrameMonitorEnd().address();
return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize());
}
public int getInterpreterFrameExpressionStackDirection() { return -1; }
// top of expression stack
public Address addressOfInterpreterFrameTOS() {
return getSP();
}
/** Expression stack from top down */
public Address addressOfInterpreterFrameTOSAt(int slot) {
return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize());
}
public Address getInterpreterFrameSenderSP() {
if (Assert.ASSERTS_ENABLED) {
Assert.that(isInterpretedFrame(), "interpreted frame expected");
}
return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
}
// Monitors
public BasicObjectLock interpreterFrameMonitorBegin() {
return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET));
}
public BasicObjectLock interpreterFrameMonitorEnd() {
Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0);
if (Assert.ASSERTS_ENABLED) {
// make sure the pointer points inside the frame
Assert.that(AddressOps.gt(getFP(), result), "result must < than frame pointer");
Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer");
}
return new BasicObjectLock(result);
}
public int interpreterFrameMonitorSize() {
return BasicObjectLock.size();
}
// Method
public Address addressOfInterpreterFrameMethod() {
return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET);
}
// Constant pool cache
public Address addressOfInterpreterFrameCPCache() {
return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET);
}
// Entry frames
public JavaCallWrapper getEntryFrameCallWrapper() {
return new PPC64JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0));
}
protected Address addressOfSavedOopResult() {
// offset is 2 for compiler2 and 3 for compiler1
return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) *
VM.getVM().getAddressSize());
}
protected Address addressOfSavedReceiver() {
return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize());
}
private void dumpStack() {
if (getFP() != null) {
for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize()));
addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
System.out.println(addr + ": " + addr.getAddressAt(0));
}
} else {
for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize()));
addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
System.out.println(addr + ": " + addr.getAddressAt(0));
}
}
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.runtime.ppc64;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.runtime.*;
public class PPC64JavaCallWrapper extends JavaCallWrapper {
public PPC64JavaCallWrapper(Address addr) {
super(addr);
}
public Address getLastJavaFP() {
return null;
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 20014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.runtime.ppc64;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
public class PPC64RegisterMap extends RegisterMap {
/** This is the only public constructor */
public PPC64RegisterMap(JavaThread thread, boolean updateMap) {
super(thread, updateMap);
}
protected PPC64RegisterMap(RegisterMap map) {
super(map);
}
public Object clone() {
PPC64RegisterMap retval = new PPC64RegisterMap(this);
return retval;
}
// no PD state to clear or copy:
protected void clearPD() {}
protected void initializePD() {}
protected void initializeFromPD(RegisterMap map) {}
protected Address getLocationPD(VMReg reg) { return null; }
}

View File

@ -246,8 +246,7 @@ endif
XSLT_CHECK = $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory
# If not found then fail fast.
check_j2se_version:
$(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
if [ $$? -ne 0 ]; then \
$(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
$(REMOTE) $(RUN.JAVA) -version; \
echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
"to bootstrap this build" 1>&2; \

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -132,6 +132,7 @@ SUNWprivate_1.1 {
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameters;
JVM_GetMethodTypeAnnotations;
JVM_GetNanoTimeAdjustment;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetStackAccessControlContext;

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -130,6 +130,7 @@ SUNWprivate_1.1 {
JVM_GetMethodIxNameUTF;
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameters;
JVM_GetNanoTimeAdjustment;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetStackAccessControlContext;

View File

@ -46,7 +46,9 @@ CFLAGS += -qsuppress=1540-0198
# - 1540-1090 (I) The destructor of "..." might not be called.
# - 1500-010: (W) WARNING in ...: Infinite loop. Program may not stop.
# There are several infinite loops in the vm, suppress.
CFLAGS += -qsuppress=1540-1090 -qsuppress=1500-010
# - 1540-1639 (I) The behavior of long type bit fields has changed ...
# ... long type bit fields now default to long, not int.
CFLAGS += -qsuppress=1540-1090 -qsuppress=1500-010 -qsuppress=1540-1639
# Suppress
# - 540-1088 (W) The exception specification is being ignored.

View File

@ -74,6 +74,12 @@ CFLAGS += -D_REENTRANT
# no xlc counterpart for -fcheck-new
# CFLAGS += -fcheck-new
# We need to define this on the command line if we want to use the the
# predefined format specifiers from "inttypes.h". Otherwise system headrs
# can indirectly include inttypes.h before we define __STDC_FORMAT_MACROS
# in globalDefinitions.hpp
CFLAGS += -D__STDC_FORMAT_MACROS
ARCHFLAG = -q64
CFLAGS += $(ARCHFLAG)
@ -124,7 +130,7 @@ STATIC_STDCXX = -Wl,-lC_r
# MAPFLAG = -Xlinker --version-script=FILENAME
# Build shared library
SHARED_FLAG = -q64 -b64 -bexpall -G -bnoentry -qmkshrobj -brtl -bnolibpath
SHARED_FLAG = -q64 -b64 -bexpall -G -bnoentry -qmkshrobj -brtl -bnolibpath -bernotok
#------------------------------------------------------------------------
# Debug flags

View File

@ -240,8 +240,7 @@ endif
XSLT_CHECK = $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory
# If not found then fail fast.
check_j2se_version:
$(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
if [ $$? -ne 0 ]; then \
$(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
$(REMOTE) $(RUN.JAVA) -version; \
echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
"to bootstrap this build" 1>&2; \

View File

@ -179,23 +179,23 @@ $(GENOFFS): $(DTRACE_SRCDIR)/$(GENOFFS)Main.c lib$(GENOFFS).dylib
# $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs.
$(JVMOFFS).h: $(GENOFFS)
$(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -header > $@.tmp; touch $@; \
if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
then rm -f $@; mv $@.tmp $@; \
else rm -f $@.tmp; \
if diff $@.tmp $@ > /dev/null 2>&1 ; \
then rm -f $@.tmp; \
else rm -f $@; mv $@.tmp $@; \
fi
$(JVMOFFS)Index.h: $(GENOFFS)
$(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -index > $@.tmp; touch $@; \
if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
then rm -f $@; mv $@.tmp $@; \
else rm -f $@.tmp; \
if diff $@.tmp $@ > /dev/null 2>&1 ; \
then rm -f $@.tmp; \
else rm -f $@; mv $@.tmp $@; \
fi
$(JVMOFFS).cpp: $(GENOFFS) $(JVMOFFS).h $(JVMOFFS)Index.h
$(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -table > $@.tmp; touch $@; \
if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
then rm -f $@; mv $@.tmp $@; \
else rm -f $@.tmp; \
if diff $@.tmp $@ > /dev/null 2>&1; \
then rm -f $@.tmp; \
else rm -f $@; mv $@.tmp $@; \
fi
$(JVMOFFS.o): $(JVMOFFS).h $(JVMOFFS).cpp

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -130,6 +130,7 @@
_JVM_GetMethodIxSignatureUTF
_JVM_GetMethodParameters
_JVM_GetMethodTypeAnnotations
_JVM_GetNanoTimeAdjustment
_JVM_GetPrimitiveArrayElement
_JVM_GetProtectionDomain
_JVM_GetStackAccessControlContext

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -130,6 +130,7 @@
_JVM_GetMethodIxSignatureUTF
_JVM_GetMethodParameters
_JVM_GetMethodTypeAnnotations
_JVM_GetNanoTimeAdjustment
_JVM_GetPrimitiveArrayElement
_JVM_GetProtectionDomain
_JVM_GetStackAccessControlContext

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -132,6 +132,7 @@ SUNWprivate_1.1 {
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameters;
JVM_GetMethodTypeAnnotations;
JVM_GetNanoTimeAdjustment;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetStackAccessControlContext;

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -132,6 +132,7 @@ SUNWprivate_1.1 {
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameters;
JVM_GetMethodTypeAnnotations;
JVM_GetNanoTimeAdjustment;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetStackAccessControlContext;

View File

@ -59,7 +59,7 @@ universalize: $(UNIVERSAL_LIPO_LIST) $(UNIVERSAL_COPY_LIST)
# Package built libraries in a universal binary
$(UNIVERSAL_LIPO_LIST):
BUILT_LIPO_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) 2>/dev/null`"; \
BUILT_LIPO_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) 2>/dev/null`" || test $$? = "1"; \
if [ -n "$${BUILT_LIPO_FILES}" ]; then \
$(MKDIR) -p $(shell dirname $@); \
lipo -create -output $@ $${BUILT_LIPO_FILES}; \
@ -70,7 +70,7 @@ $(UNIVERSAL_LIPO_LIST):
# - copies directories; including empty dirs
# - copies files, symlinks, other non-directory files
$(UNIVERSAL_COPY_LIST):
BUILT_COPY_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) -prune 2>/dev/null`"; \
BUILT_COPY_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) -prune 2>/dev/null`" || test $$? = "1"; \
if [ -n "$${BUILT_COPY_FILES}" ]; then \
for i in $${BUILT_COPY_FILES}; do \
$(MKDIR) -p $(shell dirname $@); \

View File

@ -246,8 +246,7 @@ endif
XSLT_CHECK = $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory
# If not found then fail fast.
check_j2se_version:
$(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
if [ $$? -ne 0 ]; then \
$(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
$(REMOTE) $(RUN.JAVA) -version; \
echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
"to bootstrap this build" 1>&2; \

View File

@ -1,16 +0,0 @@
#!/bin/sh
# If we're cross compiling use that path for nm
if [ "$CROSS_COMPILE_ARCH" != "" ]; then
NM=$ALT_COMPILER_PATH/nm
else
NM=nm
fi
$NM --defined-only $* \
| awk '{
if ($3 ~ /^_ZTV/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";"
if ($3 ~ /^UseSharedSpaces$/) print "\t" $3 ";"
if ($3 ~ /^_ZN9Arguments17SharedArchivePathE$/) print "\t" $3 ";"
}' \
| sort -u

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -132,6 +132,7 @@ SUNWprivate_1.1 {
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameters;
JVM_GetMethodTypeAnnotations;
JVM_GetNanoTimeAdjustment;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetStackAccessControlContext;

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -132,6 +132,7 @@ SUNWprivate_1.1 {
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameters;
JVM_GetMethodTypeAnnotations;
JVM_GetNanoTimeAdjustment;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetStackAccessControlContext;

View File

@ -109,6 +109,7 @@ $(GENERATED)/sa-jdi.jar:: $(AGENT_FILES)
$(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.x86.X86ThreadContext
$(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.amd64.AMD64ThreadContext
$(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.sparc.SPARCThreadContext
$(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.debugger.ppc64.PPC64ThreadContext
$(QUIETLY) $(REMOTE) $(RUN.JAVAH) -classpath $(SA_CLASSDIR) -d $(GENERATED) -jni sun.jvm.hotspot.asm.Disassembler
clean:

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -239,8 +239,14 @@ mapfile_reorder : mapfile $(REORDERFILE)
rm -f $@
cat $^ > $@
VMDEF_PAT = ^_ZTV
VMDEF_PAT := ^gHotSpotVM|$(VMDEF_PAT)
VMDEF_PAT := ^UseSharedSpaces$$|$(VMDEF_PAT)
VMDEF_PAT := ^_ZN9Arguments17SharedArchivePathE$$|$(VMDEF_PAT)
vm.def: $(Res_Files) $(Obj_Files)
sh $(GAMMADIR)/make/linux/makefiles/build_vm_def.sh *.o > $@
$(QUIETLY) $(NM) --defined-only $(Obj_Files) | sort -k3 -u | \
awk '$$3 ~ /$(VMDEF_PAT)/ { print "\t" $$3 ";" }' > $@
mapfile_ext:
rm -f $@
@ -334,10 +340,8 @@ $(LIBJVM): $(LIBJVM.o) $(LIBJVM_MAPFILE) $(LD_SCRIPT)
rm -f $@.1; ln -s $@ $@.1; \
if [ \"$(CROSS_COMPILE_ARCH)\" = \"\" ] ; then \
if [ -x /usr/sbin/selinuxenabled ] ; then \
/usr/sbin/selinuxenabled; \
if [ $$? = 0 ] ; then \
/usr/bin/chcon -t textrel_shlib_t $@; \
if [ $$? != 0 ]; then \
if /usr/sbin/selinuxenabled; then \
if ! /usr/bin/chcon -t textrel_shlib_t $@; then \
echo "ERROR: Cannot chcon $@"; \
fi \
fi \

View File

@ -39,6 +39,7 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/c1/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/ci/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/classfile/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/code/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/compiler/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/*.java \
@ -49,24 +50,31 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/bsd/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/basic/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/dummy/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/ia64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/amd64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/ia64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/ppc64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/posix/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/posix/elf/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/ppc64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/amd64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/ppc64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/proc/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/amd64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/ppc64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/remote/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/win32/coff/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/amd64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/ia64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windows/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windows/amd64/*.java \
@ -90,12 +98,16 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_amd64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/linux_ppc64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/posix/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/solaris_amd64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/solaris_sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/solaris_x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/win32_amd64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/win32_x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/ppc64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/tools/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/tools/jcore/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/tools/soql/*.java \

View File

@ -190,8 +190,7 @@ endif
XSLT_CHECK = $(RUN.JAVAP) javax.xml.transform.TransformerFactory
# If not found then fail fast.
check_j2se_version:
$(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
if [ $$? -ne 0 ]; then \
$(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
$(RUN.JAVA) -version; \
echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
"to bootstrap this build" 1>&2; \

View File

@ -171,11 +171,11 @@ $(GENOFFS): $(DTRACE_SRCDIR)/$(GENOFFS)Main.c lib$(GENOFFS).so
./lib$(GENOFFS).so
CONDITIONALLY_UPDATE_JVMOFFS_TARGET = \
cmp -s $@ $@.tmp; \
case $$? in \
0) rm -f $@.tmp;; \
*) rm -f $@ && mv $@.tmp $@ && echo Updated $@;; \
esac
if cmp -s $@ $@.tmp; then \
rm -f $@.tmp; \
else \
rm -f $@ && mv $@.tmp $@ && echo Updated $@; \
fi
# $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs.
$(JVMOFFS).h: $(GENOFFS)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -132,6 +132,7 @@ SUNWprivate_1.1 {
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameters;
JVM_GetMethodTypeAnnotations;
JVM_GetNanoTimeAdjustment;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetStackAccessControlContext;

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved.
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2015 SAP AG. 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
@ -284,19 +284,20 @@ class Assembler : public AbstractAssembler {
MTCTR_OPCODE = (MTSPR_OPCODE | 9 << SPR_0_4_SHIFT),
MFCTR_OPCODE = (MFSPR_OPCODE | 9 << SPR_0_4_SHIFT),
MTTFHAR_OPCODE = (MTSPR_OPCODE | 128 << SPR_0_4_SHIFT),
MFTFHAR_OPCODE = (MFSPR_OPCODE | 128 << SPR_0_4_SHIFT),
MTTFIAR_OPCODE = (MTSPR_OPCODE | 129 << SPR_0_4_SHIFT),
MFTFIAR_OPCODE = (MFSPR_OPCODE | 129 << SPR_0_4_SHIFT),
MTTEXASR_OPCODE = (MTSPR_OPCODE | 130 << SPR_0_4_SHIFT),
MFTEXASR_OPCODE = (MFSPR_OPCODE | 130 << SPR_0_4_SHIFT),
MTTEXASRU_OPCODE = (MTSPR_OPCODE | 131 << SPR_0_4_SHIFT),
MFTEXASRU_OPCODE = (MFSPR_OPCODE | 131 << SPR_0_4_SHIFT),
// Attention: Higher and lower half are inserted in reversed order.
MTTFHAR_OPCODE = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
MFTFHAR_OPCODE = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
MTTFIAR_OPCODE = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 1 << SPR_0_4_SHIFT),
MFTFIAR_OPCODE = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 1 << SPR_0_4_SHIFT),
MTTEXASR_OPCODE = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 2 << SPR_0_4_SHIFT),
MFTEXASR_OPCODE = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 2 << SPR_0_4_SHIFT),
MTTEXASRU_OPCODE = (MTSPR_OPCODE | 4 << SPR_5_9_SHIFT | 3 << SPR_0_4_SHIFT),
MFTEXASRU_OPCODE = (MFSPR_OPCODE | 4 << SPR_5_9_SHIFT | 3 << SPR_0_4_SHIFT),
MTVRSAVE_OPCODE = (MTSPR_OPCODE | 256 << SPR_0_4_SHIFT),
MFVRSAVE_OPCODE = (MFSPR_OPCODE | 256 << SPR_0_4_SHIFT),
MTVRSAVE_OPCODE = (MTSPR_OPCODE | 8 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
MFVRSAVE_OPCODE = (MFSPR_OPCODE | 8 << SPR_5_9_SHIFT | 0 << SPR_0_4_SHIFT),
MFTB_OPCODE = (MFSPR_OPCODE | 268 << SPR_0_4_SHIFT),
MFTB_OPCODE = (MFSPR_OPCODE | 8 << SPR_5_9_SHIFT | 12 << SPR_0_4_SHIFT),
MTCRF_OPCODE = (31u << OPCODE_SHIFT | 144u << 1),
MFCR_OPCODE = (31u << OPCODE_SHIFT | 19u << 1),
@ -1494,6 +1495,26 @@ class Assembler : public AbstractAssembler {
inline void mftexasr(Register d);
inline void mftexasru(Register d);
// TEXASR bit description
enum transaction_failure_reason {
// Upper half (TEXASRU):
tm_failure_persistent = 7, // The failure is likely to recur on each execution.
tm_disallowed = 8, // The instruction is not permitted.
tm_nesting_of = 9, // The maximum transaction level was exceeded.
tm_footprint_of = 10, // The tracking limit for transactional storage accesses was exceeded.
tm_self_induced_cf = 11, // A self-induced conflict occurred in Suspended state.
tm_non_trans_cf = 12, // A conflict occurred with a non-transactional access by another processor.
tm_trans_cf = 13, // A conflict occurred with another transaction.
tm_translation_cf = 14, // A conflict occurred with a TLB invalidation.
tm_inst_fetch_cf = 16, // An instruction fetch was performed from a block that was previously written transactionally.
tm_tabort = 31, // Termination was caused by the execution of an abort instruction.
// Lower half:
tm_suspended = 32, // Failure was recorded in Suspended state.
tm_failure_summary = 36, // Failure has been detected and recorded.
tm_tfiar_exact = 37, // Value in the TFIAR is exact.
tm_rot = 38, // Rollback-only transaction.
};
// PPC 1, section 2.4.1 Branch Instructions
inline void b( address a, relocInfo::relocType rt = relocInfo::none);
inline void b( Label& L);
@ -1581,6 +1602,7 @@ class Assembler : public AbstractAssembler {
inline void bnectrl(ConditionRegister crx, relocInfo::relocType rt = relocInfo::none);
// condition register logic instructions
// NOTE: There's a preferred form: d and s2 should point into the same condition register.
inline void crand( int d, int s1, int s2);
inline void crnand(int d, int s1, int s2);
inline void cror( int d, int s1, int s2);
@ -1590,6 +1612,19 @@ class Assembler : public AbstractAssembler {
inline void crandc(int d, int s1, int s2);
inline void crorc( int d, int s1, int s2);
// More convenient version.
int condition_register_bit(ConditionRegister cr, Condition c) {
return 4 * (int)(intptr_t)cr + c;
}
void crand( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
void crnand(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
void cror( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
void crxor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
void crnor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
void creqv( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
void crandc(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
void crorc( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc);
// icache and dcache related instructions
inline void icbi( Register s1, Register s2);
//inline void dcba(Register s1, Register s2); // Instruction for embedded processor only.
@ -1673,6 +1708,10 @@ class Assembler : public AbstractAssembler {
inline void smt_prio_low();
inline void smt_prio_medium_low();
inline void smt_prio_medium();
// >= Power7
inline void smt_yield();
inline void smt_mdoio();
inline void smt_mdoom();
// trap instructions
inline void twi_0(Register a); // for load with acquire semantics use load+twi_0+isync (trap can't occur)
@ -1958,6 +1997,7 @@ class Assembler : public AbstractAssembler {
inline void tbeginrot_(); // R=1 Rollback-Only Transaction
inline void tend_(); // A=0
inline void tendall_(); // A=1
inline void tabort_();
inline void tabort_(Register a);
inline void tabortwc_(int t, Register a, Register b);
inline void tabortwci_(int t, Register a, int si);
@ -1967,6 +2007,10 @@ class Assembler : public AbstractAssembler {
inline void tresume_(); // tsr with L=1
inline void tcheck(int f);
static bool is_tbegin(int x) {
return TBEGIN_OPCODE == (x & (0x3f << OPCODE_SHIFT | 0x3ff << 1));
}
// The following encoders use r0 as second operand. These instructions
// read r0 as '0'.
inline void lwzx( Register d, Register s2);

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2014 SAP AG. All rights reserved.
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2015 SAP AG. 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
@ -453,6 +453,48 @@ inline void Assembler::creqv( int d, int s1, int s2) { emit_int32(CREQV_OPCODE
inline void Assembler::crandc(int d, int s1, int s2) { emit_int32(CRANDC_OPCODE | bt(d) | ba(s1) | bb(s2)); }
inline void Assembler::crorc( int d, int s1, int s2) { emit_int32(CRORC_OPCODE | bt(d) | ba(s1) | bb(s2)); }
// More convenient version.
inline void Assembler::crand( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
int dst_bit = condition_register_bit(crdst, cdst),
src_bit = condition_register_bit(crsrc, csrc);
crand(dst_bit, src_bit, dst_bit);
}
inline void Assembler::crnand(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
int dst_bit = condition_register_bit(crdst, cdst),
src_bit = condition_register_bit(crsrc, csrc);
crnand(dst_bit, src_bit, dst_bit);
}
inline void Assembler::cror( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
int dst_bit = condition_register_bit(crdst, cdst),
src_bit = condition_register_bit(crsrc, csrc);
cror(dst_bit, src_bit, dst_bit);
}
inline void Assembler::crxor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
int dst_bit = condition_register_bit(crdst, cdst),
src_bit = condition_register_bit(crsrc, csrc);
crxor(dst_bit, src_bit, dst_bit);
}
inline void Assembler::crnor( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
int dst_bit = condition_register_bit(crdst, cdst),
src_bit = condition_register_bit(crsrc, csrc);
crnor(dst_bit, src_bit, dst_bit);
}
inline void Assembler::creqv( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
int dst_bit = condition_register_bit(crdst, cdst),
src_bit = condition_register_bit(crsrc, csrc);
creqv(dst_bit, src_bit, dst_bit);
}
inline void Assembler::crandc(ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
int dst_bit = condition_register_bit(crdst, cdst),
src_bit = condition_register_bit(crsrc, csrc);
crandc(dst_bit, src_bit, dst_bit);
}
inline void Assembler::crorc( ConditionRegister crdst, Condition cdst, ConditionRegister crsrc, Condition csrc) {
int dst_bit = condition_register_bit(crdst, cdst),
src_bit = condition_register_bit(crsrc, csrc);
crorc(dst_bit, src_bit, dst_bit);
}
// Conditional move (>= Power7)
inline void Assembler::isel(Register d, ConditionRegister cr, Condition cc, bool inv, Register a, Register b) {
if (b == noreg) {
@ -516,6 +558,10 @@ inline void Assembler::smt_prio_medium_low() { Assembler::or_unchecked(R6, R6,
inline void Assembler::smt_prio_medium() { Assembler::or_unchecked(R2, R2, R2); }
inline void Assembler::smt_prio_medium_high() { Assembler::or_unchecked(R5, R5, R5); }
inline void Assembler::smt_prio_high() { Assembler::or_unchecked(R3, R3, R3); }
// >= Power7
inline void Assembler::smt_yield() { Assembler::or_unchecked(R27, R27, R27); }
inline void Assembler::smt_mdoio() { Assembler::or_unchecked(R29, R29, R29); }
inline void Assembler::smt_mdoom() { Assembler::or_unchecked(R30, R30, R30); }
inline void Assembler::twi_0(Register a) { twi_unchecked(0, a, 0);}
@ -778,7 +824,8 @@ inline void Assembler::tbegin_() { emit_int32( TB
inline void Assembler::tbeginrot_() { emit_int32( TBEGIN_OPCODE | /*R=1*/ 1u << (31-10) | rc(1)); }
inline void Assembler::tend_() { emit_int32( TEND_OPCODE | rc(1)); }
inline void Assembler::tendall_() { emit_int32( TEND_OPCODE | /*A=1*/ 1u << (31-6) | rc(1)); }
inline void Assembler::tabort_(Register a) { emit_int32( TABORT_OPCODE | ra(a) | rc(1)); }
inline void Assembler::tabort_() { emit_int32( TABORT_OPCODE | rc(1)); }
inline void Assembler::tabort_(Register a) { assert(a != R0, "r0 not allowed"); emit_int32( TABORT_OPCODE | ra(a) | rc(1)); }
inline void Assembler::tabortwc_(int t, Register a, Register b) { emit_int32( TABORTWC_OPCODE | to(t) | ra(a) | rb(b) | rc(1)); }
inline void Assembler::tabortwci_(int t, Register a, int si) { emit_int32( TABORTWCI_OPCODE | to(t) | ra(a) | sh1620(si) | rc(1)); }
inline void Assembler::tabortdc_(int t, Register a, Register b) { emit_int32( TABORTDC_OPCODE | to(t) | ra(a) | rb(b) | rc(1)); }

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2014 SAP AG. All rights reserved.
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2015 SAP AG. 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
@ -1712,7 +1712,7 @@ void InterpreterMacroAssembler::profile_obj_type(Register obj, Register mdo_addr
andi_(R0, klass, TypeEntries::type_unknown);
// Already unknown. Nothing to do anymore.
//bne(CCR0, do_nothing);
crorc(/*CCR0 eq*/2, /*CCR1 eq*/4+2, /*CCR0 eq*/2); // cr0 eq = cr1 eq or cr0 ne
crorc(CCR0, Assembler::equal, CCR1, Assembler::equal); // cr0 eq = cr1 eq or cr0 ne
beq(CCR0, do_nothing);
clrrdi_(R0, tmp, exact_log2(-TypeEntries::type_mask));
@ -1826,9 +1826,9 @@ void InterpreterMacroAssembler::profile_return_type(Register ret, Register tmp1,
lbz(tmp2, Method::intrinsic_id_offset_in_bytes(), R19_method);
cmpwi(CCR0, tmp1, Bytecodes::_invokedynamic);
cmpwi(CCR1, tmp1, Bytecodes::_invokehandle);
cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
cmpwi(CCR1, tmp2, vmIntrinsics::_compiledLambdaForm);
cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
bne(CCR0, profile_continue);
}

View File

@ -567,16 +567,21 @@ class MacroAssembler: public Assembler {
inline void load_with_trap_null_check(Register d, int si16, Register s1);
// Load heap oop and decompress. Loaded oop may not be null.
inline void load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1 = noreg);
// Specify tmp to save one cycle.
inline void load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1 = noreg,
Register tmp = noreg);
// Store heap oop and decompress. Decompressed oop may not be null.
// Specify tmp register if d should not be changed.
inline void store_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1,
/*specify if d must stay uncompressed*/ Register tmp = noreg);
Register tmp = noreg);
// Null allowed.
inline void load_heap_oop(Register d, RegisterOrConstant offs, Register s1 = noreg);
// Encode/decode heap oop. Oop may not be null, else en/decoding goes wrong.
// src == d allowed.
inline Register encode_heap_oop_not_null(Register d, Register src = noreg);
inline void decode_heap_oop_not_null(Register d);
inline Register decode_heap_oop_not_null(Register d, Register src = noreg);
// Null allowed.
inline void decode_heap_oop(Register d);

View File

@ -311,11 +311,14 @@ inline void MacroAssembler::load_with_trap_null_check(Register d, int si16, Regi
ld(d, si16, s1);
}
inline void MacroAssembler::load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1) {
inline void MacroAssembler::load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1, Register tmp) {
if (UseCompressedOops) {
lwz(d, offs, s1);
// In disjoint mode decoding can save a cycle if src != dst.
Register narrowOop = (tmp != noreg && Universe::narrow_oop_base_disjoint()) ? tmp : d;
lwz(narrowOop, offs, s1);
// Attention: no null check here!
decode_heap_oop_not_null(d);
Register res = decode_heap_oop_not_null(d, narrowOop);
assert(res == d, "caller will not consume loaded value");
} else {
ld(d, offs, s1);
}
@ -340,26 +343,36 @@ inline void MacroAssembler::load_heap_oop(Register d, RegisterOrConstant offs, R
}
inline Register MacroAssembler::encode_heap_oop_not_null(Register d, Register src) {
Register current = (src!=noreg) ? src : d; // Compressed oop is in d if no src provided.
if (Universe::narrow_oop_base() != NULL) {
Register current = (src != noreg) ? src : d; // Oop to be compressed is in d if no src provided.
if (Universe::narrow_oop_base_overlaps()) {
sub(d, current, R30);
current = d;
}
if (Universe::narrow_oop_shift() != 0) {
srdi(d, current, LogMinObjAlignmentInBytes);
rldicl(d, current, 64-Universe::narrow_oop_shift(), 32); // Clears the upper bits.
current = d;
}
return current; // Encoded oop is in this register.
}
inline void MacroAssembler::decode_heap_oop_not_null(Register d) {
inline Register MacroAssembler::decode_heap_oop_not_null(Register d, Register src) {
if (Universe::narrow_oop_base_disjoint() && src != noreg && src != d &&
Universe::narrow_oop_shift() != 0) {
mr(d, R30);
rldimi(d, src, Universe::narrow_oop_shift(), 32-Universe::narrow_oop_shift());
return d;
}
Register current = (src != noreg) ? src : d; // Compressed oop is in d if no src provided.
if (Universe::narrow_oop_shift() != 0) {
assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");
sldi(d, d, LogMinObjAlignmentInBytes);
sldi(d, current, Universe::narrow_oop_shift());
current = d;
}
if (Universe::narrow_oop_base() != NULL) {
add(d, d, R30);
add(d, current, R30);
current = d;
}
return current; // Decoded oop is in this register.
}
inline void MacroAssembler::decode_heap_oop(Register d) {
@ -368,13 +381,7 @@ inline void MacroAssembler::decode_heap_oop(Register d) {
cmpwi(CCR0, d, 0);
beq(CCR0, isNull);
}
if (Universe::narrow_oop_shift() != 0) {
assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");
sldi(d, d, LogMinObjAlignmentInBytes);
}
if (Universe::narrow_oop_base() != NULL) {
add(d, d, R30);
}
decode_heap_oop_not_null(d);
bind(isNull);
}

View File

@ -172,15 +172,15 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm,
// Load the invoker, as MH -> MH.form -> LF.vmentry
__ verify_oop(recv);
__ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), recv);
__ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), recv, temp2);
__ verify_oop(method_temp);
__ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp);
__ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp, temp2);
__ verify_oop(method_temp);
// the following assumes that a Method* is normally compressed in the vmtarget field:
// The following assumes that a Method* is normally compressed in the vmtarget field:
__ ld(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), method_temp);
if (VerifyMethodHandles && !for_compiler_entry) {
// make sure recv is already on stack
// Make sure recv is already on stack.
__ ld(temp2, in_bytes(Method::const_offset()), method_temp);
__ load_sized_value(temp2, in_bytes(ConstMethod::size_of_parameters_offset()), temp2,
sizeof(u2), /*is_signed*/ false);
@ -259,8 +259,9 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
}
if (TraceMethodHandles) {
if (tmp_mh != noreg)
if (tmp_mh != noreg) {
__ mr(R23_method_handle, tmp_mh); // make stub happy
}
trace_method_handle_interpreter_entry(_masm, iid);
}
@ -332,7 +333,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
if (VerifyMethodHandles && iid != vmIntrinsics::_linkToInterface) {
Label L_ok;
Register temp2_defc = temp2;
__ load_heap_oop_not_null(temp2_defc, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg);
__ load_heap_oop_not_null(temp2_defc, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg, temp3);
load_klass_from_Class(_masm, temp2_defc, temp3, temp4);
__ verify_klass_ptr(temp2_defc);
__ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, temp4, L_ok);
@ -407,7 +408,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
}
Register temp2_intf = temp2;
__ load_heap_oop_not_null(temp2_intf, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg);
__ load_heap_oop_not_null(temp2_intf, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg, temp3);
load_klass_from_Class(_masm, temp2_intf, temp3, temp4);
__ verify_klass_ptr(temp2_intf);
@ -464,7 +465,7 @@ void trace_method_handle_stub(const char* adaptername,
strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH
const char* mh_reg_name = has_mh ? "R23_method_handle" : "G23";
tty->print_cr("MH %s %s="INTPTR_FORMAT " sp=" INTPTR_FORMAT,
adaptername, mh_reg_name, (intptr_t) mh, (intptr_t) entry_sp);
adaptername, mh_reg_name, (intptr_t) mh, entry_sp);
if (Verbose) {
tty->print_cr("Registers:");
@ -535,23 +536,22 @@ void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adapt
BLOCK_COMMENT("trace_method_handle {");
int nbytes_save = 10 * 8; // 10 volatile gprs
__ save_LR_CR(R0);
__ mr(R0, R1_SP); // saved_sp
assert(Assembler::is_simm(-nbytes_save, 16), "Overwriting R0");
// Push_frame_reg_args only uses R0 if nbytes_save is wider than 16 bit.
__ push_frame_reg_args(nbytes_save, R0);
__ save_volatile_gprs(R1_SP, frame::abi_reg_args_size); // Except R0.
const Register tmp = R11; // Will be preserved.
const int nbytes_save = 11*8; // volatile gprs except R0
__ save_volatile_gprs(R1_SP, -nbytes_save); // except R0
__ save_LR_CR(tmp); // save in old frame
__ load_const(R3_ARG1, (address)adaptername);
__ mr(R5_ARG3, R1_SP); // saved_sp
__ push_frame_reg_args(nbytes_save, tmp);
__ load_const_optimized(R3_ARG1, (address)adaptername, tmp);
__ mr(R4_ARG2, R23_method_handle);
__ mr(R5_ARG3, R0); // saved_sp
__ mr(R6_ARG4, R1_SP);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub));
__ restore_volatile_gprs(R1_SP, 112); // Except R0.
__ pop_frame();
__ restore_LR_CR(R0);
__ restore_LR_CR(tmp);
__ restore_volatile_gprs(R1_SP, -nbytes_save); // except R0
BLOCK_COMMENT("} trace_method_handle");
}

View File

@ -1,6 +1,6 @@
//
// Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
// Copyright 2012, 2014 SAP AG. All rights reserved.
// Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
// Copyright 2012, 2015 SAP AG. 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
@ -2698,7 +2698,7 @@ encode %{
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
__ relocate(a.rspec());
} else if (constant_reloc == relocInfo::metadata_type) {
AddressLiteral a = __ allocate_metadata_address((Metadata *)val);
AddressLiteral a = __ constant_metadata_address((Metadata *)val);
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
__ relocate(a.rspec());
} else {
@ -2727,7 +2727,7 @@ encode %{
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
__ relocate(a.rspec());
} else if (constant_reloc == relocInfo::metadata_type) {
AddressLiteral a = __ allocate_metadata_address((Metadata *)val);
AddressLiteral a = __ constant_metadata_address((Metadata *)val);
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
__ relocate(a.rspec());
} else { // non-oop pointers, e.g. card mark base, heap top
@ -6029,6 +6029,20 @@ instruct clearMs32b(iRegNdst dst, iRegNsrc src) %{
ins_pipe(pipe_class_default);
%}
// Optimize DecodeN for disjoint base.
// Load base of compressed oops into a register
instruct loadBase(iRegLdst dst) %{
effect(DEF dst);
format %{ "MR $dst, r30_heapbase" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_or);
__ mr($dst$$Register, R30);
%}
ins_pipe(pipe_class_default);
%}
// Loading ConN must be postalloc expanded so that edges between
// the nodes are safe. They may not interfere with a safepoint.
// GL TODO: This needs three instructions: better put this into the constant pool.
@ -6724,13 +6738,12 @@ instruct cond_set_0_oop(iRegNdst dst, flagsReg crx, iRegPsrc src1) %{
ins_pipe(pipe_class_default);
%}
// base != 0
// 32G aligned narrow oop base.
instruct encodeP_32GAligned(iRegNdst dst, iRegPsrc src) %{
// Disjoint narrow oop base.
instruct encodeP_Disjoint(iRegNdst dst, iRegPsrc src) %{
match(Set dst (EncodeP src));
predicate(false /* TODO: PPC port Universe::narrow_oop_base_disjoint()*/);
predicate(Universe::narrow_oop_base_disjoint());
format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with 32G aligned base" %}
format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with disjoint base" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_rldicl);
@ -6745,7 +6758,7 @@ instruct encodeP_Ex(iRegNdst dst, flagsReg crx, iRegPsrc src) %{
effect(TEMP crx);
predicate(n->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull &&
Universe::narrow_oop_shift() != 0 &&
true /* TODO: PPC port Universe::narrow_oop_base_overlaps()*/);
Universe::narrow_oop_base_overlaps());
format %{ "EncodeP $dst, $crx, $src \t// postalloc expanded" %}
postalloc_expand( postalloc_expand_encode_oop(dst, src, crx));
@ -6756,7 +6769,7 @@ instruct encodeP_not_null_Ex(iRegNdst dst, iRegPsrc src) %{
match(Set dst (EncodeP src));
predicate(n->bottom_type()->make_ptr()->ptr() == TypePtr::NotNull &&
Universe::narrow_oop_shift() != 0 &&
true /* TODO: PPC port Universe::narrow_oop_base_overlaps()*/);
Universe::narrow_oop_base_overlaps());
format %{ "EncodeP $dst, $src\t// $src != Null, postalloc expanded" %}
postalloc_expand( postalloc_expand_encode_oop_not_null(dst, src) );
@ -6876,6 +6889,7 @@ instruct decodeN_Ex(iRegPdst dst, iRegNsrc src, flagsReg crx) %{
n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant) &&
Universe::narrow_oop_shift() != 0 &&
Universe::narrow_oop_base() != 0);
ins_cost(4 * DEFAULT_COST); // Should be more expensive than decodeN_Disjoint_isel_Ex.
effect(TEMP crx);
format %{ "DecodeN $dst, $src \t// Kills $crx, postalloc expanded" %}
@ -6897,6 +6911,106 @@ instruct decodeN_nullBase(iRegPdst dst, iRegNsrc src) %{
ins_pipe(pipe_class_default);
%}
// Optimize DecodeN for disjoint base.
// Shift narrow oop and or it into register that already contains the heap base.
// Base == dst must hold, and is assured by construction in postaloc_expand.
instruct decodeN_mergeDisjoint(iRegPdst dst, iRegNsrc src, iRegLsrc base) %{
match(Set dst (DecodeN src));
effect(TEMP base);
predicate(false);
format %{ "RLDIMI $dst, $src, shift, 32-shift \t// DecodeN (disjoint base)" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_rldimi);
__ rldimi($dst$$Register, $src$$Register, Universe::narrow_oop_shift(), 32-Universe::narrow_oop_shift());
%}
ins_pipe(pipe_class_default);
%}
// Optimize DecodeN for disjoint base.
// This node requires only one cycle on the critical path.
// We must postalloc_expand as we can not express use_def effects where
// the used register is L and the def'ed register P.
instruct decodeN_Disjoint_notNull_Ex(iRegPdst dst, iRegNsrc src) %{
match(Set dst (DecodeN src));
effect(TEMP_DEF dst);
predicate((n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull ||
n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant) &&
Universe::narrow_oop_base_disjoint());
ins_cost(DEFAULT_COST);
format %{ "MOV $dst, R30 \t\n"
"RLDIMI $dst, $src, shift, 32-shift \t// decode with disjoint base" %}
postalloc_expand %{
loadBaseNode *n1 = new loadBaseNode();
n1->add_req(NULL);
n1->_opnds[0] = op_dst;
decodeN_mergeDisjointNode *n2 = new decodeN_mergeDisjointNode();
n2->add_req(n_region, n_src, n1);
n2->_opnds[0] = op_dst;
n2->_opnds[1] = op_src;
n2->_opnds[2] = op_dst;
n2->_bottom_type = _bottom_type;
ra_->set_pair(n1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
ra_->set_pair(n2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
nodes->push(n1);
nodes->push(n2);
%}
%}
instruct decodeN_Disjoint_isel_Ex(iRegPdst dst, iRegNsrc src, flagsReg crx) %{
match(Set dst (DecodeN src));
effect(TEMP_DEF dst, TEMP crx);
predicate((n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull &&
n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant) &&
Universe::narrow_oop_base_disjoint() && VM_Version::has_isel());
ins_cost(3 * DEFAULT_COST);
format %{ "DecodeN $dst, $src \t// decode with disjoint base using isel" %}
postalloc_expand %{
loadBaseNode *n1 = new loadBaseNode();
n1->add_req(NULL);
n1->_opnds[0] = op_dst;
cmpN_reg_imm0Node *n_compare = new cmpN_reg_imm0Node();
n_compare->add_req(n_region, n_src);
n_compare->_opnds[0] = op_crx;
n_compare->_opnds[1] = op_src;
n_compare->_opnds[2] = new immN_0Oper(TypeNarrowOop::NULL_PTR);
decodeN_mergeDisjointNode *n2 = new decodeN_mergeDisjointNode();
n2->add_req(n_region, n_src, n1);
n2->_opnds[0] = op_dst;
n2->_opnds[1] = op_src;
n2->_opnds[2] = op_dst;
n2->_bottom_type = _bottom_type;
cond_set_0_ptrNode *n_cond_set = new cond_set_0_ptrNode();
n_cond_set->add_req(n_region, n_compare, n2);
n_cond_set->_opnds[0] = op_dst;
n_cond_set->_opnds[1] = op_crx;
n_cond_set->_opnds[2] = op_dst;
n_cond_set->_bottom_type = _bottom_type;
assert(ra_->is_oop(this) == true, "A decodeN node must produce an oop!");
ra_->set_oop(n_cond_set, true);
ra_->set_pair(n1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
ra_->set_pair(n_compare->_idx, ra_->get_reg_second(n_crx), ra_->get_reg_first(n_crx));
ra_->set_pair(n2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
ra_->set_pair(n_cond_set->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
nodes->push(n1);
nodes->push(n_compare);
nodes->push(n2);
nodes->push(n_cond_set);
%}
%}
// src != 0, shift != 0, base != 0
instruct decodeN_notNull_addBase_Ex(iRegPdst dst, iRegNsrc src) %{
match(Set dst (DecodeN src));
@ -6904,6 +7018,7 @@ instruct decodeN_notNull_addBase_Ex(iRegPdst dst, iRegNsrc src) %{
n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant) &&
Universe::narrow_oop_shift() != 0 &&
Universe::narrow_oop_base() != 0);
ins_cost(2 * DEFAULT_COST);
format %{ "DecodeN $dst, $src \t// $src != NULL, postalloc expanded" %}
postalloc_expand( postalloc_expand_decode_oop_not_null(dst, src));
@ -6973,13 +7088,12 @@ instruct encodePKlass_sub_base(iRegPdst dst, iRegLsrc base, iRegPdst src) %{
ins_pipe(pipe_class_default);
%}
// base != 0
// 32G aligned narrow oop base.
instruct encodePKlass_32GAligned(iRegNdst dst, iRegPsrc src) %{
// Disjoint narrow oop base.
instruct encodePKlass_Disjoint(iRegNdst dst, iRegPsrc src) %{
match(Set dst (EncodePKlass src));
predicate(false /* TODO: PPC port Universe::narrow_klass_base_disjoint()*/);
format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with 32G aligned base" %}
format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with disjoint base" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_rldicl);
@ -7486,7 +7600,7 @@ instruct storeLConditional_regP_regL_regL(flagsReg crx, indirect mem_ptr, iRegLs
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_compound);
__ cmpxchgd($crx$$CondRegister, R0, $oldVal$$Register, $newVal$$Register, $mem_ptr$$Register,
MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
MacroAssembler::MemBarAcq, MacroAssembler::cmpxchgx_hint_atomic_update(),
noreg, NULL, true);
%}
ins_pipe(pipe_class_default);
@ -10476,7 +10590,7 @@ instruct cmpN_reg_reg(flagsReg crx, iRegNsrc src1, iRegNsrc src2) %{
match(Set crx (CmpN src1 src2));
size(4);
ins_cost(DEFAULT_COST);
ins_cost(2);
format %{ "CMPLW $crx, $src1, $src2 \t// compressed ptr" %}
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_cmpl);
@ -10488,7 +10602,7 @@ instruct cmpN_reg_reg(flagsReg crx, iRegNsrc src1, iRegNsrc src2) %{
instruct cmpN_reg_imm0(flagsReg crx, iRegNsrc src1, immN_0 src2) %{
match(Set crx (CmpN src1 src2));
// Make this more expensive than zeroCheckN_iReg_imm0.
ins_cost(DEFAULT_COST);
ins_cost(2);
format %{ "CMPLWI $crx, $src1, $src2 \t// compressed ptr" %}
size(4);
@ -10508,6 +10622,7 @@ instruct zeroCheckP_reg_imm0(cmpOp cmp, iRegP_N2P value, immP_0 zero, label labl
_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne &&
_leaf->as_If()->_prob >= PROB_LIKELY_MAG(4) &&
Matcher::branches_to_uncommon_trap(_leaf));
ins_cost(1); // Should not be cheaper than zeroCheckN.
ins_is_TrapBasedCheckNode(true);
@ -10889,7 +11004,7 @@ instruct branchLoopEndSched(cmpOp cmp, flagsReg crx, label labl) %{
instruct partialSubtypeCheck(iRegPdst result, iRegP_N2P subklass, iRegP_N2P superklass,
iRegPdst tmp_klass, iRegPdst tmp_arrayptr) %{
match(Set result (PartialSubtypeCheck subklass superklass));
effect(TEMP result, TEMP tmp_klass, TEMP tmp_arrayptr);
effect(TEMP_DEF result, TEMP tmp_klass, TEMP tmp_arrayptr);
ins_cost(DEFAULT_COST*10);
format %{ "PartialSubtypeCheck $result = ($subklass instanceOf $superklass) tmp: $tmp_klass, $tmp_arrayptr" %}
@ -11000,7 +11115,7 @@ instruct string_indexOf_imm1_char(iRegIdst result, iRegPsrc haystack, iRegIsrc h
predicate(SpecialStringIndexOf); // type check implicit by parameter type, See Matcher::match_rule_supported
match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm)));
effect(TEMP result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1);
effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1);
ins_cost(150);
format %{ "String IndexOf CSCL1 $haystack[0..$haycnt], $needleImm+$offsetImm[0..$needlecntImm]"
@ -11037,7 +11152,7 @@ instruct string_indexOf_imm1(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt
iRegIdst tmp1, iRegIdst tmp2,
flagsRegCR0 cr0, flagsRegCR1 cr1) %{
match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
effect(USE_KILL needle, /* TDEF needle, */ TEMP result,
effect(USE_KILL needle, /* TDEF needle, */ TEMP_DEF result,
TEMP tmp1, TEMP tmp2);
// Required for EA: check if it is still a type_array.
predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
@ -11084,7 +11199,7 @@ instruct string_indexOf_imm(iRegIdst result, iRegPsrc haystack, rscratch1RegI ha
iRegIdst tmp1, iRegIdst tmp2, iRegIdst tmp3, iRegIdst tmp4, iRegIdst tmp5,
flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6) %{
match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP result,
effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result,
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6);
// Required for EA: check if it is still a type_array.
predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
@ -11118,7 +11233,7 @@ instruct string_indexOf(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt
flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6) %{
match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecnt)));
effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/
TEMP result,
TEMP_DEF result,
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6);
predicate(SpecialStringIndexOf); // See Matcher::match_rule_supported.
ins_cost(300);
@ -11142,7 +11257,7 @@ instruct string_equals_imm(iRegPsrc str1, iRegPsrc str2, uimmI15 cntImm, iRegIds
iRegPdst tmp1, iRegPdst tmp2,
flagsRegCR0 cr0, flagsRegCR6 cr6, regCTR ctr) %{
match(Set result (StrEquals (Binary str1 str2) cntImm));
effect(TEMP result, TEMP tmp1, TEMP tmp2,
effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2,
KILL cr0, KILL cr6, KILL ctr);
predicate(SpecialStringEquals); // See Matcher::match_rule_supported.
ins_cost(250);
@ -11165,7 +11280,7 @@ instruct string_equals(iRegPsrc str1, iRegPsrc str2, iRegIsrc cnt, iRegIdst resu
iRegPdst tmp1, iRegPdst tmp2, iRegPdst tmp3, iRegPdst tmp4, iRegPdst tmp5,
flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{
match(Set result (StrEquals (Binary str1 str2) cnt));
effect(TEMP result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5,
effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5,
KILL cr0, KILL cr1, KILL cr6, KILL ctr);
predicate(SpecialStringEquals); // See Matcher::match_rule_supported.
ins_cost(300);
@ -11188,7 +11303,7 @@ instruct string_equals(iRegPsrc str1, iRegPsrc str2, iRegIsrc cnt, iRegIdst resu
instruct string_compare(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result,
iRegPdst tmp, flagsRegCR0 cr0, regCTR ctr) %{
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
effect(USE_KILL cnt1, USE_KILL cnt2, USE_KILL str1, USE_KILL str2, TEMP result, TEMP tmp, KILL cr0, KILL ctr);
effect(USE_KILL cnt1, USE_KILL cnt2, USE_KILL str1, USE_KILL str2, TEMP_DEF result, TEMP tmp, KILL cr0, KILL ctr);
ins_cost(300);
ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2014 SAP AG. All rights reserved.
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2015 SAP AG. 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
@ -1079,7 +1079,7 @@ class StubGenerator: public StubCodeGenerator {
__ sldi(tmp2, R5_ARG3, log2_elem_size); // size in bytes
__ cmpld(CCR0, R3_ARG1, R4_ARG2); // Use unsigned comparison!
__ cmpld(CCR1, tmp1, tmp2);
__ crand(/*CCR0 lt*/0, /*CCR1 lt*/4+0, /*CCR0 lt*/0);
__ crand(CCR0, Assembler::less, CCR1, Assembler::less);
__ blt(CCR0, l_overlap); // Src before dst and distance smaller than size.
// need to copy forwards

View File

@ -264,11 +264,11 @@ void TemplateInterpreterGenerator::generate_counter_incr(Label* overflow, Label*
__ cmpdi(CCR0, Rmdo, 0);
__ beq(CCR0, no_mdo);
// Increment backedge counter in the MDO.
const int mdo_bc_offs = in_bytes(MethodData::backedge_counter_offset()) + in_bytes(InvocationCounter::counter_offset());
__ lwz(Rscratch2, mdo_bc_offs, Rmdo);
// Increment invocation counter in the MDO.
const int mdo_ic_offs = in_bytes(MethodData::invocation_counter_offset()) + in_bytes(InvocationCounter::counter_offset());
__ lwz(Rscratch2, mdo_ic_offs, Rmdo);
__ addi(Rscratch2, Rscratch2, increment);
__ stw(Rscratch2, mdo_bc_offs, Rmdo);
__ stw(Rscratch2, mdo_ic_offs, Rmdo);
__ load_const_optimized(Rscratch1, mask, R0);
__ and_(Rscratch1, Rscratch2, Rscratch1);
__ bne(CCR0, done);
@ -276,12 +276,12 @@ void TemplateInterpreterGenerator::generate_counter_incr(Label* overflow, Label*
}
// Increment counter in MethodCounters*.
const int mo_bc_offs = in_bytes(MethodCounters::backedge_counter_offset()) + in_bytes(InvocationCounter::counter_offset());
const int mo_ic_offs = in_bytes(MethodCounters::invocation_counter_offset()) + in_bytes(InvocationCounter::counter_offset());
__ bind(no_mdo);
__ get_method_counters(R19_method, R3_counters, done);
__ lwz(Rscratch2, mo_bc_offs, R3_counters);
__ lwz(Rscratch2, mo_ic_offs, R3_counters);
__ addi(Rscratch2, Rscratch2, increment);
__ stw(Rscratch2, mo_bc_offs, R3_counters);
__ stw(Rscratch2, mo_ic_offs, R3_counters);
__ load_const_optimized(Rscratch1, mask, R0);
__ and_(Rscratch1, Rscratch2, Rscratch1);
__ beq(CCR0, *overflow);

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013, 2014 SAP AG. All rights reserved.
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright 2013, 2015 SAP AG. 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
@ -335,11 +335,11 @@ void TemplateTable::ldc(bool wide) {
__ cmpwi(CCR0, Rscratch2, JVM_CONSTANT_UnresolvedClass); // Unresolved class?
__ cmpwi(CCR1, Rscratch2, JVM_CONSTANT_UnresolvedClassInError); // Unresolved class in error state?
__ cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
__ cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
// Resolved class - need to call vm to get java mirror of the class.
__ cmpwi(CCR1, Rscratch2, JVM_CONSTANT_Class);
__ crnor(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2); // Neither resolved class nor unresolved case from above?
__ crnor(CCR0, Assembler::equal, CCR1, Assembler::equal); // Neither resolved class nor unresolved case from above?
__ beq(CCR0, notClass);
__ li(R4, wide ? 1 : 0);
@ -2611,7 +2611,7 @@ void TemplateTable::jvmti_post_field_mod(Register Rcache, Register Rscratch, boo
__ cmpwi(CCR0, Rflags, ltos);
__ cmpwi(CCR1, Rflags, dtos);
__ addi(base, R15_esp, Interpreter::expr_offset_in_bytes(1));
__ crnor(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2);
__ crnor(CCR0, Assembler::equal, CCR1, Assembler::equal);
__ beq(CCR0, is_one_slot);
__ addi(base, R15_esp, Interpreter::expr_offset_in_bytes(2));
__ bind(is_one_slot);
@ -3563,7 +3563,7 @@ void TemplateTable::_new() {
// Make sure klass does not have has_finalizer, or is abstract, or interface or java/lang/Class.
__ andi_(R0, Rinstance_size, Klass::_lh_instance_slow_path_bit); // slow path bit equals 0?
__ crnand(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2); // slow path bit set or not fully initialized?
__ crnand(CCR0, Assembler::equal, CCR1, Assembler::equal); // slow path bit set or not fully initialized?
__ beq(CCR0, Lslow_case);
// --------------------------------------------------------------------------

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -483,15 +483,6 @@ void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
}
jbyte* G1PostBarrierStub::_byte_map_base = NULL;
jbyte* G1PostBarrierStub::byte_map_base_slow() {
BarrierSet* bs = Universe::heap()->barrier_set();
assert(bs->is_a(BarrierSet::G1SATBCTLogging),
"Must be if we're using this.");
return ((G1SATBCardTableModRefBS*)bs)->byte_map_base;
}
void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);

View File

@ -1374,6 +1374,7 @@ void InterpreterMacroAssembler::verify_method_data_pointer() {
}
void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocation_count,
Register method_counters,
Register Rtmp,
Label &profile_continue) {
assert(ProfileInterpreter, "must be profiling interpreter");
@ -1386,9 +1387,8 @@ void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocat
br_notnull_short(ImethodDataPtr, Assembler::pn, done);
// Test to see if we should create a method data oop
AddressLiteral profile_limit((address) &InvocationCounter::InterpreterProfileLimit);
sethi(profile_limit, Rtmp);
ld(Rtmp, profile_limit.low10(), Rtmp);
Address profile_limit(method_counters, MethodCounters::interpreter_profile_limit_offset());
ld(profile_limit, Rtmp);
cmp(invocation_count, Rtmp);
// Use long branches because call_VM() code and following code generated by
// test_backedge_count_for_osr() is large in debug VM.
@ -2375,6 +2375,7 @@ void InterpreterMacroAssembler::increment_backedge_counter( Register Rcounters,
#ifndef CC_INTERP
void InterpreterMacroAssembler::test_backedge_count_for_osr( Register backedge_count,
Register method_counters,
Register branch_bcp,
Register Rtmp ) {
Label did_not_overflow;
@ -2382,8 +2383,8 @@ void InterpreterMacroAssembler::test_backedge_count_for_osr( Register backedge_c
assert_different_registers(backedge_count, Rtmp, branch_bcp);
assert(UseOnStackReplacement,"Must UseOnStackReplacement to test_backedge_count_for_osr");
AddressLiteral limit(&InvocationCounter::InterpreterBackwardBranchLimit);
load_contents(limit, Rtmp);
Address limit(method_counters, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()));
ld(limit, Rtmp);
cmp_and_br_short(backedge_count, Rtmp, Assembler::lessUnsigned, Assembler::pt, did_not_overflow);
// When ProfileInterpreter is on, the backedge_count comes from the
@ -2500,17 +2501,13 @@ void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) {
// Jump if ((*counter_addr += increment) & mask) satisfies the condition.
void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
int increment, int mask,
int increment, Address mask_addr,
Register scratch1, Register scratch2,
Condition cond, Label *where) {
ld(counter_addr, scratch1);
add(scratch1, increment, scratch1);
if (is_simm13(mask)) {
andcc(scratch1, mask, G0);
} else {
set(mask, scratch2);
andcc(scratch1, scratch2, G0);
}
ld(mask_addr, scratch2);
andcc(scratch1, scratch2, G0);
br(cond, false, Assembler::pn, *where);
delayed()->st(scratch1, counter_addr);
}

View File

@ -267,7 +267,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
void increment_invocation_counter( Register Rcounters, Register Rtmp, Register Rtmp2 );
void increment_backedge_counter( Register Rcounters, Register Rtmp, Register Rtmp2 );
#ifndef CC_INTERP
void test_backedge_count_for_osr( Register backedge_count, Register branch_bcp, Register Rtmp );
void test_backedge_count_for_osr(Register backedge_count, Register method_counters, Register branch_bcp, Register Rtmp );
#endif /* CC_INTERP */
// Object locking
@ -280,7 +280,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
void set_method_data_pointer_for_bcp();
void test_method_data_pointer(Label& zero_continue);
void verify_method_data_pointer();
void test_invocation_counter_for_mdp(Register invocation_count, Register Rtmp, Label &profile_continue);
void test_invocation_counter_for_mdp(Register invocation_count, Register method_counters, Register Rtmp, Label &profile_continue);
void set_mdp_data_at(int constant, Register value);
void increment_mdp_data_at(Address counter, Register bumped_count,
@ -291,7 +291,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
Register bumped_count, Register scratch2,
bool decrement = false);
void increment_mask_and_jump(Address counter_addr,
int increment, int mask,
int increment, Address mask_addr,
Register scratch1, Register scratch2,
Condition cond, Label *where);
void set_mdp_flag_at(int flag_constant, Register scratch);

View File

@ -630,7 +630,12 @@ inline void MacroAssembler::ldf(FloatRegisterImpl::Width w, Register s1, Registe
inline void MacroAssembler::ldf(FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset) {
relocate(a.rspec(offset));
ldf(w, a.base(), a.disp() + offset, d);
if (a.has_index()) {
assert(offset == 0, "");
ldf(w, a.base(), a.index(), d);
} else {
ldf(w, a.base(), a.disp() + offset, d);
}
}
// returns if membar generates anything, obviously this code should mirror

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
@ -2996,7 +2996,7 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
%}
enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result) %{
Label Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone;
Label Lchar, Lchar_loop, Ldone;
MacroAssembler _masm(&cbuf);
Register str1_reg = reg_to_register_object($str1$$reg);

View File

@ -282,12 +282,11 @@ address TemplateInterpreterGenerator::generate_continuation_for(TosState state)
void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue) {
// Note: In tiered we increment either counters in MethodCounters* or in
// MDO depending if we're profiling or not.
const Register Rcounters = G3_scratch;
const Register G3_method_counters = G3_scratch;
Label done;
if (TieredCompilation) {
const int increment = InvocationCounter::count_increment;
const int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
Label no_mdo;
if (ProfileInterpreter) {
// If no method data exists, go to profile_continue.
@ -297,6 +296,7 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
Address mdo_invocation_counter(G4_scratch,
in_bytes(MethodData::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
Address mask(G4_scratch, in_bytes(MethodData::invoke_mask_offset()));
__ increment_mask_and_jump(mdo_invocation_counter, increment, mask,
G3_scratch, Lscratch,
Assembler::zero, overflow);
@ -305,20 +305,21 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
// Increment counter in MethodCounters*
__ bind(no_mdo);
Address invocation_counter(Rcounters,
Address invocation_counter(G3_method_counters,
in_bytes(MethodCounters::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
__ get_method_counters(Lmethod, Rcounters, done);
__ get_method_counters(Lmethod, G3_method_counters, done);
Address mask(G3_method_counters, in_bytes(MethodCounters::invoke_mask_offset()));
__ increment_mask_and_jump(invocation_counter, increment, mask,
G4_scratch, Lscratch,
Assembler::zero, overflow);
__ bind(done);
} else {
} else { // not TieredCompilation
// Update standard invocation counters
__ get_method_counters(Lmethod, Rcounters, done);
__ increment_invocation_counter(Rcounters, O0, G4_scratch);
__ get_method_counters(Lmethod, G3_method_counters, done);
__ increment_invocation_counter(G3_method_counters, O0, G4_scratch);
if (ProfileInterpreter) {
Address interpreter_invocation_counter(Rcounters,
Address interpreter_invocation_counter(G3_method_counters,
in_bytes(MethodCounters::interpreter_invocation_counter_offset()));
__ ld(interpreter_invocation_counter, G4_scratch);
__ inc(G4_scratch);
@ -327,16 +328,16 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
if (ProfileInterpreter && profile_method != NULL) {
// Test to see if we should create a method data oop
AddressLiteral profile_limit((address)&InvocationCounter::InterpreterProfileLimit);
__ load_contents(profile_limit, G3_scratch);
__ cmp_and_br_short(O0, G3_scratch, Assembler::lessUnsigned, Assembler::pn, *profile_method_continue);
Address profile_limit(G3_method_counters, in_bytes(MethodCounters::interpreter_profile_limit_offset()));
__ ld(profile_limit, G1_scratch);
__ cmp_and_br_short(O0, G1_scratch, Assembler::lessUnsigned, Assembler::pn, *profile_method_continue);
// if no method data exists, go to profile_method
__ test_method_data_pointer(*profile_method);
}
AddressLiteral invocation_limit((address)&InvocationCounter::InterpreterInvocationLimit);
__ load_contents(invocation_limit, G3_scratch);
Address invocation_limit(G3_method_counters, in_bytes(MethodCounters::interpreter_invocation_limit_offset()));
__ ld(invocation_limit, G3_scratch);
__ cmp(O0, G3_scratch);
__ br(Assembler::greaterEqualUnsigned, false, Assembler::pn, *overflow); // Far distance
__ delayed()->nop();

View File

@ -1599,13 +1599,12 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
// Bump bytecode pointer by displacement (take the branch)
__ delayed()->add( O1_disp, Lbcp, Lbcp ); // add to bc addr
const Register Rcounters = G3_scratch;
__ get_method_counters(Lmethod, Rcounters, Lforward);
const Register G3_method_counters = G3_scratch;
__ get_method_counters(Lmethod, G3_method_counters, Lforward);
if (TieredCompilation) {
Label Lno_mdo, Loverflow;
int increment = InvocationCounter::count_increment;
int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
if (ProfileInterpreter) {
// If no method data exists, go to profile_continue.
__ ld_ptr(Lmethod, Method::method_data_offset(), G4_scratch);
@ -1614,6 +1613,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
// Increment backedge counter in the MDO
Address mdo_backedge_counter(G4_scratch, in_bytes(MethodData::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
Address mask(G4_scratch, in_bytes(MethodData::backedge_mask_offset()));
__ increment_mask_and_jump(mdo_backedge_counter, increment, mask, G3_scratch, O0,
Assembler::notZero, &Lforward);
__ ba_short(Loverflow);
@ -1621,9 +1621,10 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
// If there's no MDO, increment counter in MethodCounters*
__ bind(Lno_mdo);
Address backedge_counter(Rcounters,
Address backedge_counter(G3_method_counters,
in_bytes(MethodCounters::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
Address mask(G3_method_counters, in_bytes(MethodCounters::backedge_mask_offset()));
__ increment_mask_and_jump(backedge_counter, increment, mask, G4_scratch, O0,
Assembler::notZero, &Lforward);
__ bind(Loverflow);
@ -1663,18 +1664,19 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ jmp(O2, G0);
__ delayed()->nop();
} else {
} else { // not TieredCompilation
// Update Backedge branch separately from invocations
const Register G4_invoke_ctr = G4;
__ increment_backedge_counter(Rcounters, G4_invoke_ctr, G1_scratch);
__ increment_backedge_counter(G3_method_counters, G4_invoke_ctr, G1_scratch);
if (ProfileInterpreter) {
__ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_scratch, Lforward);
__ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_method_counters, G1_scratch, Lforward);
if (UseOnStackReplacement) {
__ test_backedge_count_for_osr(O2_bumped_count, l_cur_bcp, G3_scratch);
__ test_backedge_count_for_osr(O2_bumped_count, G3_method_counters, l_cur_bcp, G1_scratch);
}
} else {
if (UseOnStackReplacement) {
__ test_backedge_count_for_osr(G4_invoke_ctr, l_cur_bcp, G3_scratch);
__ test_backedge_count_for_osr(G4_invoke_ctr, G3_method_counters, l_cur_bcp, G1_scratch);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -541,15 +541,6 @@ void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
}
jbyte* G1PostBarrierStub::_byte_map_base = NULL;
jbyte* G1PostBarrierStub::byte_map_base_slow() {
BarrierSet* bs = Universe::heap()->barrier_set();
assert(bs->is_a(BarrierSet::G1SATBCTLogging),
"Must be if we're using this.");
return ((G1SATBCardTableModRefBS*)bs)->byte_map_base;
}
void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);
assert(addr()->is_register(), "Precondition.");

View File

@ -1360,7 +1360,7 @@ void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) {
// Jump if ((*counter_addr += increment) & mask) satisfies the condition.
void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
int increment, int mask,
int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where) {
if (!preloaded) {

View File

@ -182,7 +182,7 @@
void increment_mdp_data_at(Register mdp_in, Register reg, int constant,
bool decrement = false);
void increment_mask_and_jump(Address counter_addr,
int increment, int mask,
int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where);
void set_mdp_flag_at(Register mdp_in, int flag_constant);

View File

@ -1426,7 +1426,7 @@ void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) {
// Jump if ((*counter_addr += increment) & mask) satisfies the condition.
void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
int increment, int mask,
int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where) {
if (!preloaded) {

View File

@ -191,7 +191,7 @@
void increment_mdp_data_at(Register mdp_in, Register reg, int constant,
bool decrement = false);
void increment_mask_and_jump(Address counter_addr,
int increment, int mask,
int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where);
void set_mdp_flag_at(Register mdp_in, int flag_constant);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -3184,7 +3184,24 @@ void MacroAssembler::pow_or_exp(bool is_exp, int num_fpu_regs_in_use) {
jmp(done);
} else {
// Stack: X Y
Label x_negative, y_odd;
Label x_negative, y_not_2;
static double two = 2.0;
ExternalAddress two_addr((address)&two);
// constant maybe too far on 64 bit
lea(tmp2, two_addr);
fld_d(Address(tmp2, 0)); // Stack: 2 X Y
fcmp(tmp, 2, true, false); // Stack: X Y
jcc(Assembler::parity, y_not_2);
jcc(Assembler::notEqual, y_not_2);
fxch(); fpop(); // Stack: X
fmul(0); // Stack: X*X
jmp(done);
bind(y_not_2);
fldz(); // Stack: 0 X Y
fcmp(tmp, 1, true, false); // Stack: X Y
@ -6177,7 +6194,7 @@ void MacroAssembler::string_indexofC8(Register str1, Register str2,
ShortBranchVerifier sbv(this);
assert(UseSSE42Intrinsics, "SSE4.2 is required");
// This method uses pcmpestri inxtruction with bound registers
// This method uses pcmpestri instruction with bound registers
// inputs:
// xmm - substring
// rax - substring length (elements count)
@ -6338,7 +6355,7 @@ void MacroAssembler::string_indexof(Register str1, Register str2,
//
assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < 8), "should be != 0");
// This method uses pcmpestri inxtruction with bound registers
// This method uses pcmpestri instruction with bound registers
// inputs:
// xmm - substring
// rax - substring length (elements count)
@ -6627,7 +6644,6 @@ void MacroAssembler::string_compare(Register str1, Register str2,
// start from first character again because it has aligned address.
int stride2 = 16;
int adr_stride = stride << scale;
int adr_stride2 = stride2 << scale;
assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri");
// rax and rdx are used by pcmpestri as elements counters
@ -6726,7 +6742,7 @@ void MacroAssembler::string_compare(Register str1, Register str2,
// inputs:
// vec1- substring
// rax - negative string length (elements count)
// mem - scaned string
// mem - scanned string
// rdx - string length (elements count)
// pcmpmask - cmp mode: 11000 (string compare with negated result)
// + 00 (unsigned bytes) or + 01 (unsigned shorts)

View File

@ -346,7 +346,6 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
// depending if we're profiling or not.
if (TieredCompilation) {
int increment = InvocationCounter::count_increment;
int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
Label no_mdo;
if (ProfileInterpreter) {
// Are we profiling?
@ -356,6 +355,7 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
// Increment counter in the MDO
const Address mdo_invocation_counter(rax, in_bytes(MethodData::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
const Address mask(rax, in_bytes(MethodData::invoke_mask_offset()));
__ increment_mask_and_jump(mdo_invocation_counter, increment, mask, rcx, false, Assembler::zero, overflow);
__ jmp(done);
}
@ -366,11 +366,12 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
InvocationCounter::counter_offset());
__ get_method_counters(rbx, rax, done);
const Address mask(rax, in_bytes(MethodCounters::invoke_mask_offset()));
__ increment_mask_and_jump(invocation_counter, increment, mask,
rcx, false, Assembler::zero, overflow);
__ bind(done);
} else {
const Address backedge_counter (rax,
} else { // not TieredCompilation
const Address backedge_counter(rax,
MethodCounters::backedge_counter_offset() +
InvocationCounter::counter_offset());
const Address invocation_counter(rax,
@ -400,16 +401,16 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
if (ProfileInterpreter && profile_method != NULL) {
// Test to see if we should create a method data oop
__ cmp32(rcx,
ExternalAddress((address)&InvocationCounter::InterpreterProfileLimit));
__ movptr(rax, Address(rbx, Method::method_counters_offset()));
__ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, *profile_method_continue);
// if no method data exists, go to profile_method
__ test_method_data_pointer(rax, *profile_method);
}
__ cmp32(rcx,
ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
__ movptr(rax, Address(rbx, Method::method_counters_offset()));
__ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_invocation_limit_offset())));
__ jcc(Assembler::aboveEqual, *overflow);
__ bind(done);
}

View File

@ -299,7 +299,6 @@ void InterpreterGenerator::generate_counter_incr(
// Note: In tiered we increment either counters in Method* or in MDO depending if we're profiling or not.
if (TieredCompilation) {
int increment = InvocationCounter::count_increment;
int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
Label no_mdo;
if (ProfileInterpreter) {
// Are we profiling?
@ -309,6 +308,7 @@ void InterpreterGenerator::generate_counter_incr(
// Increment counter in the MDO
const Address mdo_invocation_counter(rax, in_bytes(MethodData::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
const Address mask(rax, in_bytes(MethodData::invoke_mask_offset()));
__ increment_mask_and_jump(mdo_invocation_counter, increment, mask, rcx, false, Assembler::zero, overflow);
__ jmp(done);
}
@ -318,10 +318,11 @@ void InterpreterGenerator::generate_counter_incr(
MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset());
__ get_method_counters(rbx, rax, done);
const Address mask(rax, in_bytes(MethodCounters::invoke_mask_offset()));
__ increment_mask_and_jump(invocation_counter, increment, mask, rcx,
false, Assembler::zero, overflow);
__ bind(done);
} else {
} else { // not TieredCompilation
const Address backedge_counter(rax,
MethodCounters::backedge_counter_offset() +
InvocationCounter::counter_offset());
@ -350,14 +351,16 @@ void InterpreterGenerator::generate_counter_incr(
if (ProfileInterpreter && profile_method != NULL) {
// Test to see if we should create a method data oop
__ cmp32(rcx, ExternalAddress((address)&InvocationCounter::InterpreterProfileLimit));
__ movptr(rax, Address(rbx, Method::method_counters_offset()));
__ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, *profile_method_continue);
// if no method data exists, go to profile_method
__ test_method_data_pointer(rax, *profile_method);
}
__ cmp32(rcx, ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
__ movptr(rax, Address(rbx, Method::method_counters_offset()));
__ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_invocation_limit_offset())));
__ jcc(Assembler::aboveEqual, *overflow);
__ bind(done);
}

View File

@ -1621,7 +1621,6 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (TieredCompilation) {
Label no_mdo;
int increment = InvocationCounter::count_increment;
int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
if (ProfileInterpreter) {
// Are we profiling?
__ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset())));
@ -1630,6 +1629,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
// Increment the MDO backedge counter
const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset()));
__ increment_mask_and_jump(mdo_backedge_counter, increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
__ jmp(dispatch);
@ -1637,9 +1637,10 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ bind(no_mdo);
// Increment backedge counter in MethodCounters*
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset()));
__ increment_mask_and_jump(Address(rcx, be_offset), increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
} else {
} else { // not TieredCompilation
// increment counter
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
__ movl(rax, Address(rcx, be_offset)); // load backedge counter
@ -1653,8 +1654,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (ProfileInterpreter) {
// Test to see if we should create a method data oop
__ cmp32(rax,
ExternalAddress((address) &InvocationCounter::InterpreterProfileLimit));
__ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, dispatch);
// if no method data exists, go to profile method
@ -1662,8 +1662,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (UseOnStackReplacement) {
// check for overflow against rbx, which is the MDO taken count
__ cmp32(rbx,
ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
__ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::below, dispatch);
// When ProfileInterpreter is on, the backedge_count comes from the
@ -1678,8 +1677,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
} else {
if (UseOnStackReplacement) {
// check for overflow against rax, which is the sum of the counters
__ cmp32(rax,
ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
__ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::aboveEqual, backedge_counter_overflow);
}

View File

@ -1642,7 +1642,6 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (TieredCompilation) {
Label no_mdo;
int increment = InvocationCounter::count_increment;
int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
if (ProfileInterpreter) {
// Are we profiling?
__ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset())));
@ -1651,6 +1650,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
// Increment the MDO backedge counter
const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset()));
__ increment_mask_and_jump(mdo_backedge_counter, increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
__ jmp(dispatch);
@ -1658,9 +1658,10 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
__ bind(no_mdo);
// Increment backedge counter in MethodCounters*
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset()));
__ increment_mask_and_jump(Address(rcx, be_offset), increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
} else {
} else { // not TieredCompilation
// increment counter
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
__ movl(rax, Address(rcx, be_offset)); // load backedge counter
@ -1674,8 +1675,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (ProfileInterpreter) {
// Test to see if we should create a method data oop
__ cmp32(rax,
ExternalAddress((address) &InvocationCounter::InterpreterProfileLimit));
__ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, dispatch);
// if no method data exists, go to profile method
@ -1683,8 +1683,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (UseOnStackReplacement) {
// check for overflow against ebx which is the MDO taken count
__ cmp32(rbx,
ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
__ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::below, dispatch);
// When ProfileInterpreter is on, the backedge_count comes
@ -1702,8 +1701,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
if (UseOnStackReplacement) {
// check for overflow against eax, which is the sum of the
// counters
__ cmp32(rax,
ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
__ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::aboveEqual, backedge_counter_overflow);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2014 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -1115,6 +1115,15 @@ jlong os::javaTimeMillis() {
return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000);
}
void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) {
timeval time;
int status = gettimeofday(&time, NULL);
assert(status != -1, "aix error at gettimeofday()");
seconds = jlong(time.tv_sec);
nanos = jlong(time.tv_usec) * 1000;
}
// We need to manually declare mread_real_time,
// because IBM didn't provide a prototype in time.h.
// (they probably only ever tested in C, not C++)

View File

@ -31,6 +31,7 @@
#include "os_aix.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/perfMemory.hpp"
#include "services/memTracker.hpp"
#include "utilities/exceptions.hpp"
// put OS-includes here
@ -196,12 +197,37 @@ static pid_t filename_to_pid(const char* filename) {
return pid;
}
// Check if the given statbuf is considered a secure directory for
// the backing store files. Returns true if the directory is considered
// a secure location. Returns false if the statbuf is a symbolic link or
// if an error occurred.
static bool is_statbuf_secure(struct stat *statp) {
if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
// The path represents a link or some non-directory file type,
// which is not what we expected. Declare it insecure.
//
return false;
}
// We have an existing directory, check if the permissions are safe.
if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
// The directory is open for writing and could be subjected
// to a symlink or a hard link attack. Declare it insecure.
return false;
}
// See if the uid of the directory matches the effective uid of the process.
//
if (statp->st_uid != geteuid()) {
// The directory was not created by this user, declare it insecure.
return false;
}
return true;
}
// check if the given path is considered a secure directory for
// Check if the given path is considered a secure directory for
// the backing store files. Returns true if the directory exists
// and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
//
static bool is_directory_secure(const char* path) {
struct stat statbuf;
int result = 0;
@ -211,38 +237,276 @@ static bool is_directory_secure(const char* path) {
return false;
}
// the path exists, now check it's mode
if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
// the path represents a link or some non-directory file type,
// which is not what we expected. declare it insecure.
//
// The path exists, see if it is secure.
return is_statbuf_secure(&statbuf);
}
// (Taken over from Solaris to support the O_NOFOLLOW case on AIX.)
// Check if the given directory file descriptor is considered a secure
// directory for the backing store files. Returns true if the directory
// exists and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
static bool is_dirfd_secure(int dir_fd) {
struct stat statbuf;
int result = 0;
RESTARTABLE(::fstat(dir_fd, &statbuf), result);
if (result == OS_ERR) {
return false;
}
else {
// we have an existing directory, check if the permissions are safe.
//
if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
// the directory is open for writing and could be subjected
// to a symlnk attack. declare it insecure.
//
return false;
// The path exists, now check its mode.
return is_statbuf_secure(&statbuf);
}
// Check to make sure fd1 and fd2 are referencing the same file system object.
static bool is_same_fsobject(int fd1, int fd2) {
struct stat statbuf1;
struct stat statbuf2;
int result = 0;
RESTARTABLE(::fstat(fd1, &statbuf1), result);
if (result == OS_ERR) {
return false;
}
RESTARTABLE(::fstat(fd2, &statbuf2), result);
if (result == OS_ERR) {
return false;
}
if ((statbuf1.st_ino == statbuf2.st_ino) &&
(statbuf1.st_dev == statbuf2.st_dev)) {
return true;
} else {
return false;
}
}
// Helper functions for open without O_NOFOLLOW which is not present on AIX 5.3/6.1.
// We use the jdk6 implementation here.
#ifndef O_NOFOLLOW
// The O_NOFOLLOW oflag doesn't exist before solaris 5.10, this is to simulate that behaviour
// was done in jdk 5/6 hotspot by Oracle this way
static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool use_mode) {
struct stat orig_st;
struct stat new_st;
bool create;
int error;
int fd;
create = false;
if (lstat(path, &orig_st) != 0) {
if (errno == ENOENT && (oflag & O_CREAT) != 0) {
// File doesn't exist, but_we want to create it, add O_EXCL flag
// to make sure no-one creates it (or a symlink) before us
// This works as we expect with symlinks, from posix man page:
// 'If O_EXCL and O_CREAT are set, and path names a symbolic
// link, open() shall fail and set errno to [EEXIST]'.
oflag |= O_EXCL;
create = true;
} else {
// File doesn't exist, and we are not creating it.
return OS_ERR;
}
} else {
// Lstat success, check if existing file is a link.
if ((orig_st.st_mode & S_IFMT) == S_IFLNK) {
// File is a symlink.
errno = ELOOP;
return OS_ERR;
}
}
if (use_mode == true) {
fd = open(path, oflag, mode);
} else {
fd = open(path, oflag);
}
if (fd == OS_ERR) {
return fd;
}
// Can't do inode checks on before/after if we created the file.
if (create == false) {
if (fstat(fd, &new_st) != 0) {
// Keep errno from fstat, in case close also fails.
error = errno;
::close(fd);
errno = error;
return OS_ERR;
}
if (orig_st.st_dev != new_st.st_dev || orig_st.st_ino != new_st.st_ino) {
// File was tampered with during race window.
::close(fd);
errno = EEXIST;
if (PrintMiscellaneous && Verbose) {
warning("possible file tampering attempt detected when opening %s", path);
}
return OS_ERR;
}
}
return fd;
}
static int open_o_nofollow(const char* path, int oflag, mode_t mode) {
return open_o_nofollow_impl(path, oflag, mode, true);
}
static int open_o_nofollow(const char* path, int oflag) {
return open_o_nofollow_impl(path, oflag, 0, false);
}
#endif
// Open the directory of the given path and validate it.
// Return a DIR * of the open directory.
static DIR *open_directory_secure(const char* dirname) {
// Open the directory using open() so that it can be verified
// to be secure by calling is_dirfd_secure(), opendir() and then check
// to see if they are the same file system object. This method does not
// introduce a window of opportunity for the directory to be attacked that
// calling opendir() and is_directory_secure() does.
int result;
DIR *dirp = NULL;
// No O_NOFOLLOW defined at buildtime, and it is not documented for open;
// so provide a workaround in this case.
#ifdef O_NOFOLLOW
RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
#else
// workaround (jdk6 coding)
RESTARTABLE(::open_o_nofollow(dirname, O_RDONLY), result);
#endif
if (result == OS_ERR) {
// Directory doesn't exist or is a symlink, so there is nothing to cleanup.
if (PrintMiscellaneous && Verbose) {
if (errno == ELOOP) {
warning("directory %s is a symlink and is not secure\n", dirname);
} else {
warning("could not open directory %s: %s\n", dirname, strerror(errno));
}
}
return dirp;
}
int fd = result;
// Determine if the open directory is secure.
if (!is_dirfd_secure(fd)) {
// The directory is not a secure directory.
os::close(fd);
return dirp;
}
// Open the directory.
dirp = ::opendir(dirname);
if (dirp == NULL) {
// The directory doesn't exist, close fd and return.
os::close(fd);
return dirp;
}
// Check to make sure fd and dirp are referencing the same file system object.
if (!is_same_fsobject(fd, dirp->dd_fd)) {
// The directory is not secure.
os::close(fd);
os::closedir(dirp);
dirp = NULL;
return dirp;
}
// Close initial open now that we know directory is secure
os::close(fd);
return dirp;
}
// NOTE: The code below uses fchdir(), open() and unlink() because
// fdopendir(), openat() and unlinkat() are not supported on all
// versions. Once the support for fdopendir(), openat() and unlinkat()
// is available on all supported versions the code can be changed
// to use these functions.
// Open the directory of the given path, validate it and set the
// current working directory to it.
// Return a DIR * of the open directory and the saved cwd fd.
//
static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
// Open the directory.
DIR* dirp = open_directory_secure(dirname);
if (dirp == NULL) {
// Directory doesn't exist or is insecure, so there is nothing to cleanup.
return dirp;
}
int fd = dirp->dd_fd;
// Open a fd to the cwd and save it off.
int result;
RESTARTABLE(::open(".", O_RDONLY), result);
if (result == OS_ERR) {
*saved_cwd_fd = -1;
} else {
*saved_cwd_fd = result;
}
// Set the current directory to dirname by using the fd of the directory.
result = fchdir(fd);
return dirp;
}
// Close the directory and restore the current working directory.
static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
int result;
// If we have a saved cwd change back to it and close the fd.
if (saved_cwd_fd != -1) {
result = fchdir(saved_cwd_fd);
::close(saved_cwd_fd);
}
// Close the directory.
os::closedir(dirp);
}
// Check if the given file descriptor is considered a secure.
static bool is_file_secure(int fd, const char *filename) {
int result;
struct stat statbuf;
// Determine if the file is secure.
RESTARTABLE(::fstat(fd, &statbuf), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("fstat failed on %s: %s\n", filename, strerror(errno));
}
return false;
}
if (statbuf.st_nlink > 1) {
// A file with multiple links is not expected.
if (PrintMiscellaneous && Verbose) {
warning("file %s has multiple links\n", filename);
}
return false;
}
return true;
}
// return the user name for the given user id
//
// the caller is expected to free the allocated memory.
// Return the user name for the given user id.
//
// The caller is expected to free the allocated memory.
static char* get_user_name(uid_t uid) {
struct passwd pwent;
// determine the max pwbuf size from sysconf, and hardcode
// Determine the max pwbuf size from sysconf, and hardcode
// a default if this not available through sysconf.
//
long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
if (bufsize == -1)
bufsize = 1024;
@ -344,7 +608,8 @@ static char* get_user_name_slow(int vmid, TRAPS) {
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
DIR* subdirp = os::opendir(usrdir_name);
// Open the user directory.
DIR* subdirp = open_directory_secure(usrdir_name);
if (subdirp == NULL) {
FREE_C_HEAP_ARRAY(char, usrdir_name);
@ -464,28 +729,7 @@ static void remove_file(const char* path) {
}
}
// remove file
//
// this method removes the file with the given file name in the
// named directory.
//
static void remove_file(const char* dirname, const char* filename) {
size_t nbytes = strlen(dirname) + strlen(filename) + 2;
char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
strcpy(path, dirname);
strcat(path, "/");
strcat(path, filename);
remove_file(path);
FREE_C_HEAP_ARRAY(char, path);
}
// cleanup stale shared memory resources
// Cleanup stale shared memory resources
//
// This method attempts to remove all stale shared memory files in
// the named user temporary directory. It scans the named directory
@ -493,33 +737,26 @@ static void remove_file(const char* dirname, const char* filename) {
// process id is extracted from the file name and a test is run to
// determine if the process is alive. If the process is not alive,
// any stale file resources are removed.
//
static void cleanup_sharedmem_resources(const char* dirname) {
// open the user temp directory
DIR* dirp = os::opendir(dirname);
int saved_cwd_fd;
// Open the directory.
DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
// directory doesn't exist, so there is nothing to cleanup
// Directory doesn't exist or is insecure, so there is nothing to cleanup.
return;
}
if (!is_directory_secure(dirname)) {
// the directory is not a secure directory
os::closedir(dirp);
return;
}
// for each entry in the directory that matches the expected file
// For each entry in the directory that matches the expected file
// name pattern, determine if the file resources are stale and if
// so, remove the file resources. Note, instrumented HotSpot processes
// for this user may start and/or terminate during this search and
// remove or create new files in this directory. The behavior of this
// loop under these conditions is dependent upon the implementation of
// opendir/readdir.
//
struct dirent* entry;
char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@ -529,56 +766,55 @@ static void cleanup_sharedmem_resources(const char* dirname) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
// attempt to remove all unexpected files, except "." and ".."
remove_file(dirname, entry->d_name);
// Attempt to remove all unexpected files, except "." and "..".
unlink(entry->d_name);
}
errno = 0;
continue;
}
// we now have a file name that converts to a valid integer
// We now have a file name that converts to a valid integer
// that could represent a process id . if this process id
// matches the current process id or the process is not running,
// then remove the stale file resources.
//
// process liveness is detected by sending signal number 0 to
// Process liveness is detected by sending signal number 0 to
// the process id (see kill(2)). if kill determines that the
// process does not exist, then the file resources are removed.
// if kill determines that that we don't have permission to
// signal the process, then the file resources are assumed to
// be stale and are removed because the resources for such a
// process should be in a different user specific directory.
//
if ((pid == os::current_process_id()) ||
(kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
remove_file(dirname, entry->d_name);
unlink(entry->d_name);
}
errno = 0;
}
os::closedir(dirp);
FREE_C_HEAP_ARRAY(char, dbuf);
// Close the directory and reset the current working directory.
close_directory_secure_cwd(dirp, saved_cwd_fd);
FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
}
// make the user specific temporary directory. Returns true if
// Make the user specific temporary directory. Returns true if
// the directory exists and is secure upon return. Returns false
// if the directory exists but is either a symlink, is otherwise
// insecure, or if an error occurred.
//
static bool make_user_tmp_dir(const char* dirname) {
// create the directory with 0755 permissions. note that the directory
// Create the directory with 0755 permissions. note that the directory
// will be owned by euid::egid, which may not be the same as uid::gid.
//
if (mkdir(dirname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) == OS_ERR) {
if (errno == EEXIST) {
// The directory already exists and was probably created by another
// JVM instance. However, this could also be the result of a
// deliberate symlink. Verify that the existing directory is safe.
//
if (!is_directory_secure(dirname)) {
// directory is not secure
// Directory is not secure.
if (PrintMiscellaneous && Verbose) {
warning("%s directory is insecure\n", dirname);
}
@ -614,19 +850,63 @@ static int create_sharedmem_resources(const char* dirname, const char* filename,
return -1;
}
int result;
RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("could not create file %s: %s\n", filename, strerror(errno));
}
int saved_cwd_fd;
// Open the directory and set the current working directory to it.
DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
// Directory doesn't exist or is insecure, so cannot create shared
// memory file.
return -1;
}
// Open the filename in the current directory.
// Cannot use O_TRUNC here; truncation of an existing file has to happen
// after the is_file_secure() check below.
int result;
// No O_NOFOLLOW defined at buildtime, and it is not documented for open;
// so provide a workaround in this case.
#ifdef O_NOFOLLOW
RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
#else
// workaround function (jdk6 code)
RESTARTABLE(::open_o_nofollow(filename, O_RDWR|O_CREAT, S_IREAD|S_IWRITE), result);
#endif
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
if (errno == ELOOP) {
warning("file %s is a symlink and is not secure\n", filename);
} else {
warning("could not create file %s: %s\n", filename, strerror(errno));
}
}
// Close the directory and reset the current working directory.
close_directory_secure_cwd(dirp, saved_cwd_fd);
return -1;
}
// Close the directory and reset the current working directory.
close_directory_secure_cwd(dirp, saved_cwd_fd);
// save the file descriptor
int fd = result;
// Check to see if the file is secure.
if (!is_file_secure(fd, filename)) {
::close(fd);
return -1;
}
// Truncate the file to get rid of any existing data.
RESTARTABLE(::ftruncate(fd, (off_t)0), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("could not truncate shared memory file: %s\n", strerror(errno));
}
::close(fd);
return -1;
}
// set the file size
RESTARTABLE(::ftruncate(fd, (off_t)size), result);
if (result == OS_ERR) {
@ -648,7 +928,14 @@ static int open_sharedmem_file(const char* filename, int oflags, TRAPS) {
// open the file
int result;
// No O_NOFOLLOW defined at buildtime, and it is not documented for open;
// so provide a workaround in this case
#ifdef O_NOFOLLOW
RESTARTABLE(::open(filename, oflags), result);
#else
RESTARTABLE(::open_o_nofollow(filename, oflags), result);
#endif
if (result == OS_ERR) {
if (errno == ENOENT) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
@ -662,8 +949,15 @@ static int open_sharedmem_file(const char* filename, int oflags, TRAPS) {
THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
}
}
int fd = result;
return result;
// Check to see if the file is secure.
if (!is_file_secure(fd, filename)) {
::close(fd);
return -1;
}
return fd;
}
// create a named shared memory region. returns the address of the
@ -695,13 +989,21 @@ static char* mmap_create_shared(size_t size) {
char* dirname = get_user_tmp_dir(user_name);
char* filename = get_sharedmem_filename(dirname, vmid);
// Get the short filename.
char* short_filename = strrchr(filename, '/');
if (short_filename == NULL) {
short_filename = filename;
} else {
short_filename++;
}
// cleanup any stale shared memory files
cleanup_sharedmem_resources(dirname);
assert(((size > 0) && (size % os::vm_page_size() == 0)),
"unexpected PerfMemory region size");
fd = create_sharedmem_resources(dirname, filename, size);
fd = create_sharedmem_resources(dirname, short_filename, size);
FREE_C_HEAP_ARRAY(char, user_name);
FREE_C_HEAP_ARRAY(char, dirname);
@ -733,6 +1035,9 @@ static char* mmap_create_shared(size_t size) {
// clear the shared memory region
(void)::memset((void*) mapAddress, 0, size);
// It does not go through os api, the operation has to record from here.
MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal);
return mapAddress;
}
@ -807,7 +1112,7 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
char* mapAddress;
int result;
int fd;
size_t size;
size_t size = 0;
const char* luser = NULL;
int mmap_prot;
@ -819,12 +1124,18 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
// constructs for the file and the shared memory mapping.
if (mode == PerfMemory::PERF_MODE_RO) {
mmap_prot = PROT_READ;
// No O_NOFOLLOW defined at buildtime, and it is not documented for open.
#ifdef O_NOFOLLOW
file_flags = O_RDONLY | O_NOFOLLOW;
#else
file_flags = O_RDONLY;
#endif
}
else if (mode == PerfMemory::PERF_MODE_RW) {
#ifdef LATER
mmap_prot = PROT_READ | PROT_WRITE;
file_flags = O_RDWR;
file_flags = O_RDWR | O_NOFOLLOW;
#else
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Unsupported access mode");
@ -853,9 +1164,9 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
// store file, we don't follow them when attaching either.
//
if (!is_directory_secure(dirname)) {
FREE_C_HEAP_ARRAY(char, dirname);
FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
if (luser != user) {
FREE_C_HEAP_ARRAY(char, luser);
FREE_C_HEAP_ARRAY(char, luser, mtInternal);
}
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
@ -901,6 +1212,9 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
"Could not map PerfMemory");
}
// It does not go through os api, the operation has to record from here.
MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal);
*addr = mapAddress;
*sizep = size;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -984,6 +984,14 @@ jlong os::javaTimeMillis() {
return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000);
}
void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) {
timeval time;
int status = gettimeofday(&time, NULL);
assert(status != -1, "bsd error");
seconds = jlong(time.tv_sec);
nanos = jlong(time.tv_usec) * 1000;
}
#ifndef __APPLE__
#ifndef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC (1)

View File

@ -197,7 +197,38 @@ static pid_t filename_to_pid(const char* filename) {
}
// check if the given path is considered a secure directory for
// Check if the given statbuf is considered a secure directory for
// the backing store files. Returns true if the directory is considered
// a secure location. Returns false if the statbuf is a symbolic link or
// if an error occurred.
//
static bool is_statbuf_secure(struct stat *statp) {
if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
// The path represents a link or some non-directory file type,
// which is not what we expected. Declare it insecure.
//
return false;
}
// We have an existing directory, check if the permissions are safe.
//
if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
// The directory is open for writing and could be subjected
// to a symlink or a hard link attack. Declare it insecure.
//
return false;
}
// See if the uid of the directory matches the effective uid of the process.
//
if (statp->st_uid != geteuid()) {
// The directory was not created by this user, declare it insecure.
//
return false;
}
return true;
}
// Check if the given path is considered a secure directory for
// the backing store files. Returns true if the directory exists
// and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
@ -211,27 +242,185 @@ static bool is_directory_secure(const char* path) {
return false;
}
// the path exists, now check it's mode
if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
// the path represents a link or some non-directory file type,
// which is not what we expected. declare it insecure.
//
// The path exists, see if it is secure.
return is_statbuf_secure(&statbuf);
}
// Check if the given directory file descriptor is considered a secure
// directory for the backing store files. Returns true if the directory
// exists and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
//
static bool is_dirfd_secure(int dir_fd) {
struct stat statbuf;
int result = 0;
RESTARTABLE(::fstat(dir_fd, &statbuf), result);
if (result == OS_ERR) {
return false;
}
else {
// we have an existing directory, check if the permissions are safe.
//
if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
// the directory is open for writing and could be subjected
// to a symlnk attack. declare it insecure.
//
return false;
// The path exists, now check its mode.
return is_statbuf_secure(&statbuf);
}
// Check to make sure fd1 and fd2 are referencing the same file system object.
//
static bool is_same_fsobject(int fd1, int fd2) {
struct stat statbuf1;
struct stat statbuf2;
int result = 0;
RESTARTABLE(::fstat(fd1, &statbuf1), result);
if (result == OS_ERR) {
return false;
}
RESTARTABLE(::fstat(fd2, &statbuf2), result);
if (result == OS_ERR) {
return false;
}
if ((statbuf1.st_ino == statbuf2.st_ino) &&
(statbuf1.st_dev == statbuf2.st_dev)) {
return true;
} else {
return false;
}
}
// Open the directory of the given path and validate it.
// Return a DIR * of the open directory.
//
static DIR *open_directory_secure(const char* dirname) {
// Open the directory using open() so that it can be verified
// to be secure by calling is_dirfd_secure(), opendir() and then check
// to see if they are the same file system object. This method does not
// introduce a window of opportunity for the directory to be attacked that
// calling opendir() and is_directory_secure() does.
int result;
DIR *dirp = NULL;
RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
if (result == OS_ERR) {
// Directory doesn't exist or is a symlink, so there is nothing to cleanup.
if (PrintMiscellaneous && Verbose) {
if (errno == ELOOP) {
warning("directory %s is a symlink and is not secure\n", dirname);
} else {
warning("could not open directory %s: %s\n", dirname, strerror(errno));
}
}
return dirp;
}
int fd = result;
// Determine if the open directory is secure.
if (!is_dirfd_secure(fd)) {
// The directory is not a secure directory.
os::close(fd);
return dirp;
}
// Open the directory.
dirp = ::opendir(dirname);
if (dirp == NULL) {
// The directory doesn't exist, close fd and return.
os::close(fd);
return dirp;
}
// Check to make sure fd and dirp are referencing the same file system object.
if (!is_same_fsobject(fd, dirfd(dirp))) {
// The directory is not secure.
os::close(fd);
os::closedir(dirp);
dirp = NULL;
return dirp;
}
// Close initial open now that we know directory is secure
os::close(fd);
return dirp;
}
// NOTE: The code below uses fchdir(), open() and unlink() because
// fdopendir(), openat() and unlinkat() are not supported on all
// versions. Once the support for fdopendir(), openat() and unlinkat()
// is available on all supported versions the code can be changed
// to use these functions.
// Open the directory of the given path, validate it and set the
// current working directory to it.
// Return a DIR * of the open directory and the saved cwd fd.
//
static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
// Open the directory.
DIR* dirp = open_directory_secure(dirname);
if (dirp == NULL) {
// Directory doesn't exist or is insecure, so there is nothing to cleanup.
return dirp;
}
int fd = dirfd(dirp);
// Open a fd to the cwd and save it off.
int result;
RESTARTABLE(::open(".", O_RDONLY), result);
if (result == OS_ERR) {
*saved_cwd_fd = -1;
} else {
*saved_cwd_fd = result;
}
// Set the current directory to dirname by using the fd of the directory.
result = fchdir(fd);
return dirp;
}
// Close the directory and restore the current working directory.
//
static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
int result;
// If we have a saved cwd change back to it and close the fd.
if (saved_cwd_fd != -1) {
result = fchdir(saved_cwd_fd);
::close(saved_cwd_fd);
}
// Close the directory.
os::closedir(dirp);
}
// Check if the given file descriptor is considered a secure.
//
static bool is_file_secure(int fd, const char *filename) {
int result;
struct stat statbuf;
// Determine if the file is secure.
RESTARTABLE(::fstat(fd, &statbuf), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("fstat failed on %s: %s\n", filename, strerror(errno));
}
return false;
}
if (statbuf.st_nlink > 1) {
// A file with multiple links is not expected.
if (PrintMiscellaneous && Verbose) {
warning("file %s has multiple links\n", filename);
}
return false;
}
return true;
}
// return the user name for the given user id
//
// the caller is expected to free the allocated memory.
@ -317,9 +506,11 @@ static char* get_user_name_slow(int vmid, TRAPS) {
const char* tmpdirname = os::get_temp_directory();
// open the temp directory
DIR* tmpdirp = os::opendir(tmpdirname);
if (tmpdirp == NULL) {
// Cannot open the directory to get the user name, return.
return NULL;
}
@ -344,25 +535,14 @@ static char* get_user_name_slow(int vmid, TRAPS) {
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
DIR* subdirp = os::opendir(usrdir_name);
// open the user directory
DIR* subdirp = open_directory_secure(usrdir_name);
if (subdirp == NULL) {
FREE_C_HEAP_ARRAY(char, usrdir_name);
continue;
}
// Since we don't create the backing store files in directories
// pointed to by symbolic links, we also don't follow them when
// looking for the files. We check for a symbolic link after the
// call to opendir in order to eliminate a small window where the
// symlink can be exploited.
//
if (!is_directory_secure(usrdir_name)) {
FREE_C_HEAP_ARRAY(char, usrdir_name);
os::closedir(subdirp);
continue;
}
struct dirent* udentry;
char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
errno = 0;
@ -465,26 +645,6 @@ static void remove_file(const char* path) {
}
// remove file
//
// this method removes the file with the given file name in the
// named directory.
//
static void remove_file(const char* dirname, const char* filename) {
size_t nbytes = strlen(dirname) + strlen(filename) + 2;
char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
strcpy(path, dirname);
strcat(path, "/");
strcat(path, filename);
remove_file(path);
FREE_C_HEAP_ARRAY(char, path);
}
// cleanup stale shared memory resources
//
// This method attempts to remove all stale shared memory files in
@ -496,17 +656,11 @@ static void remove_file(const char* dirname, const char* filename) {
//
static void cleanup_sharedmem_resources(const char* dirname) {
// open the user temp directory
DIR* dirp = os::opendir(dirname);
int saved_cwd_fd;
// open the directory and set the current working directory to it
DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
// directory doesn't exist, so there is nothing to cleanup
return;
}
if (!is_directory_secure(dirname)) {
// the directory is not a secure directory
os::closedir(dirp);
// directory doesn't exist or is insecure, so there is nothing to cleanup
return;
}
@ -520,6 +674,7 @@ static void cleanup_sharedmem_resources(const char* dirname) {
//
struct dirent* entry;
char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@ -530,7 +685,7 @@ static void cleanup_sharedmem_resources(const char* dirname) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
// attempt to remove all unexpected files, except "." and ".."
remove_file(dirname, entry->d_name);
unlink(entry->d_name);
}
errno = 0;
@ -553,11 +708,14 @@ static void cleanup_sharedmem_resources(const char* dirname) {
if ((pid == os::current_process_id()) ||
(kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
remove_file(dirname, entry->d_name);
unlink(entry->d_name);
}
errno = 0;
}
os::closedir(dirp);
// close the directory and reset the current working directory
close_directory_secure_cwd(dirp, saved_cwd_fd);
FREE_C_HEAP_ARRAY(char, dbuf);
}
@ -614,19 +772,54 @@ static int create_sharedmem_resources(const char* dirname, const char* filename,
return -1;
}
int result;
RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("could not create file %s: %s\n", filename, strerror(errno));
}
int saved_cwd_fd;
// open the directory and set the current working directory to it
DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
// Directory doesn't exist or is insecure, so cannot create shared
// memory file.
return -1;
}
// Open the filename in the current directory.
// Cannot use O_TRUNC here; truncation of an existing file has to happen
// after the is_file_secure() check below.
int result;
RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
if (errno == ELOOP) {
warning("file %s is a symlink and is not secure\n", filename);
} else {
warning("could not create file %s: %s\n", filename, strerror(errno));
}
}
// close the directory and reset the current working directory
close_directory_secure_cwd(dirp, saved_cwd_fd);
return -1;
}
// close the directory and reset the current working directory
close_directory_secure_cwd(dirp, saved_cwd_fd);
// save the file descriptor
int fd = result;
// check to see if the file is secure
if (!is_file_secure(fd, filename)) {
::close(fd);
return -1;
}
// truncate the file to get rid of any existing data
RESTARTABLE(::ftruncate(fd, (off_t)0), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("could not truncate shared memory file: %s\n", strerror(errno));
}
::close(fd);
return -1;
}
// set the file size
RESTARTABLE(::ftruncate(fd, (off_t)size), result);
if (result == OS_ERR) {
@ -684,8 +877,15 @@ static int open_sharedmem_file(const char* filename, int oflags, TRAPS) {
THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
}
}
int fd = result;
return result;
// check to see if the file is secure
if (!is_file_secure(fd, filename)) {
::close(fd);
return -1;
}
return fd;
}
// create a named shared memory region. returns the address of the
@ -717,13 +917,21 @@ static char* mmap_create_shared(size_t size) {
char* dirname = get_user_tmp_dir(user_name);
char* filename = get_sharedmem_filename(dirname, vmid);
// get the short filename
char* short_filename = strrchr(filename, '/');
if (short_filename == NULL) {
short_filename = filename;
} else {
short_filename++;
}
// cleanup any stale shared memory files
cleanup_sharedmem_resources(dirname);
assert(((size > 0) && (size % os::vm_page_size() == 0)),
"unexpected PerfMemory region size");
fd = create_sharedmem_resources(dirname, filename, size);
fd = create_sharedmem_resources(dirname, short_filename, size);
FREE_C_HEAP_ARRAY(char, user_name);
FREE_C_HEAP_ARRAY(char, dirname);
@ -838,12 +1046,12 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
// constructs for the file and the shared memory mapping.
if (mode == PerfMemory::PERF_MODE_RO) {
mmap_prot = PROT_READ;
file_flags = O_RDONLY;
file_flags = O_RDONLY | O_NOFOLLOW;
}
else if (mode == PerfMemory::PERF_MODE_RW) {
#ifdef LATER
mmap_prot = PROT_READ | PROT_WRITE;
file_flags = O_RDWR;
file_flags = O_RDWR | O_NOFOLLOW;
#else
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Unsupported access mode");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1322,6 +1322,15 @@ jlong os::javaTimeMillis() {
return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000);
}
void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) {
timeval time;
int status = gettimeofday(&time, NULL);
assert(status != -1, "linux error");
seconds = jlong(time.tv_sec);
nanos = jlong(time.tv_usec) * 1000;
}
#ifndef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC (1)
#endif

View File

@ -197,7 +197,38 @@ static pid_t filename_to_pid(const char* filename) {
}
// check if the given path is considered a secure directory for
// Check if the given statbuf is considered a secure directory for
// the backing store files. Returns true if the directory is considered
// a secure location. Returns false if the statbuf is a symbolic link or
// if an error occurred.
//
static bool is_statbuf_secure(struct stat *statp) {
if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
// The path represents a link or some non-directory file type,
// which is not what we expected. Declare it insecure.
//
return false;
}
// We have an existing directory, check if the permissions are safe.
//
if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
// The directory is open for writing and could be subjected
// to a symlink or a hard link attack. Declare it insecure.
//
return false;
}
// See if the uid of the directory matches the effective uid of the process.
//
if (statp->st_uid != geteuid()) {
// The directory was not created by this user, declare it insecure.
//
return false;
}
return true;
}
// Check if the given path is considered a secure directory for
// the backing store files. Returns true if the directory exists
// and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
@ -211,22 +242,180 @@ static bool is_directory_secure(const char* path) {
return false;
}
// the path exists, now check it's mode
if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
// the path represents a link or some non-directory file type,
// which is not what we expected. declare it insecure.
//
// The path exists, see if it is secure.
return is_statbuf_secure(&statbuf);
}
// Check if the given directory file descriptor is considered a secure
// directory for the backing store files. Returns true if the directory
// exists and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
//
static bool is_dirfd_secure(int dir_fd) {
struct stat statbuf;
int result = 0;
RESTARTABLE(::fstat(dir_fd, &statbuf), result);
if (result == OS_ERR) {
return false;
}
else {
// we have an existing directory, check if the permissions are safe.
//
if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
// the directory is open for writing and could be subjected
// to a symlnk attack. declare it insecure.
//
return false;
// The path exists, now check its mode.
return is_statbuf_secure(&statbuf);
}
// Check to make sure fd1 and fd2 are referencing the same file system object.
//
static bool is_same_fsobject(int fd1, int fd2) {
struct stat statbuf1;
struct stat statbuf2;
int result = 0;
RESTARTABLE(::fstat(fd1, &statbuf1), result);
if (result == OS_ERR) {
return false;
}
RESTARTABLE(::fstat(fd2, &statbuf2), result);
if (result == OS_ERR) {
return false;
}
if ((statbuf1.st_ino == statbuf2.st_ino) &&
(statbuf1.st_dev == statbuf2.st_dev)) {
return true;
} else {
return false;
}
}
// Open the directory of the given path and validate it.
// Return a DIR * of the open directory.
//
static DIR *open_directory_secure(const char* dirname) {
// Open the directory using open() so that it can be verified
// to be secure by calling is_dirfd_secure(), opendir() and then check
// to see if they are the same file system object. This method does not
// introduce a window of opportunity for the directory to be attacked that
// calling opendir() and is_directory_secure() does.
int result;
DIR *dirp = NULL;
RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
if (errno == ELOOP) {
warning("directory %s is a symlink and is not secure\n", dirname);
} else {
warning("could not open directory %s: %s\n", dirname, strerror(errno));
}
}
return dirp;
}
int fd = result;
// Determine if the open directory is secure.
if (!is_dirfd_secure(fd)) {
// The directory is not a secure directory.
os::close(fd);
return dirp;
}
// Open the directory.
dirp = ::opendir(dirname);
if (dirp == NULL) {
// The directory doesn't exist, close fd and return.
os::close(fd);
return dirp;
}
// Check to make sure fd and dirp are referencing the same file system object.
if (!is_same_fsobject(fd, dirfd(dirp))) {
// The directory is not secure.
os::close(fd);
os::closedir(dirp);
dirp = NULL;
return dirp;
}
// Close initial open now that we know directory is secure
os::close(fd);
return dirp;
}
// NOTE: The code below uses fchdir(), open() and unlink() because
// fdopendir(), openat() and unlinkat() are not supported on all
// versions. Once the support for fdopendir(), openat() and unlinkat()
// is available on all supported versions the code can be changed
// to use these functions.
// Open the directory of the given path, validate it and set the
// current working directory to it.
// Return a DIR * of the open directory and the saved cwd fd.
//
static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
// Open the directory.
DIR* dirp = open_directory_secure(dirname);
if (dirp == NULL) {
// Directory doesn't exist or is insecure, so there is nothing to cleanup.
return dirp;
}
int fd = dirfd(dirp);
// Open a fd to the cwd and save it off.
int result;
RESTARTABLE(::open(".", O_RDONLY), result);
if (result == OS_ERR) {
*saved_cwd_fd = -1;
} else {
*saved_cwd_fd = result;
}
// Set the current directory to dirname by using the fd of the directory.
result = fchdir(fd);
return dirp;
}
// Close the directory and restore the current working directory.
//
static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
int result;
// If we have a saved cwd change back to it and close the fd.
if (saved_cwd_fd != -1) {
result = fchdir(saved_cwd_fd);
::close(saved_cwd_fd);
}
// Close the directory.
os::closedir(dirp);
}
// Check if the given file descriptor is considered a secure.
//
static bool is_file_secure(int fd, const char *filename) {
int result;
struct stat statbuf;
// Determine if the file is secure.
RESTARTABLE(::fstat(fd, &statbuf), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("fstat failed on %s: %s\n", filename, strerror(errno));
}
return false;
}
if (statbuf.st_nlink > 1) {
// A file with multiple links is not expected.
if (PrintMiscellaneous && Verbose) {
warning("file %s has multiple links\n", filename);
}
return false;
}
return true;
}
@ -317,9 +506,11 @@ static char* get_user_name_slow(int vmid, TRAPS) {
const char* tmpdirname = os::get_temp_directory();
// open the temp directory
DIR* tmpdirp = os::opendir(tmpdirname);
if (tmpdirp == NULL) {
// Cannot open the directory to get the user name, return.
return NULL;
}
@ -344,7 +535,8 @@ static char* get_user_name_slow(int vmid, TRAPS) {
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
DIR* subdirp = os::opendir(usrdir_name);
// open the user directory
DIR* subdirp = open_directory_secure(usrdir_name);
if (subdirp == NULL) {
FREE_C_HEAP_ARRAY(char, usrdir_name);
@ -465,26 +657,6 @@ static void remove_file(const char* path) {
}
// remove file
//
// this method removes the file with the given file name in the
// named directory.
//
static void remove_file(const char* dirname, const char* filename) {
size_t nbytes = strlen(dirname) + strlen(filename) + 2;
char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
strcpy(path, dirname);
strcat(path, "/");
strcat(path, filename);
remove_file(path);
FREE_C_HEAP_ARRAY(char, path);
}
// cleanup stale shared memory resources
//
// This method attempts to remove all stale shared memory files in
@ -496,17 +668,11 @@ static void remove_file(const char* dirname, const char* filename) {
//
static void cleanup_sharedmem_resources(const char* dirname) {
// open the user temp directory
DIR* dirp = os::opendir(dirname);
int saved_cwd_fd;
// open the directory
DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
// directory doesn't exist, so there is nothing to cleanup
return;
}
if (!is_directory_secure(dirname)) {
// the directory is not a secure directory
os::closedir(dirp);
// directory doesn't exist or is insecure, so there is nothing to cleanup
return;
}
@ -520,6 +686,7 @@ static void cleanup_sharedmem_resources(const char* dirname) {
//
struct dirent* entry;
char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@ -528,9 +695,8 @@ static void cleanup_sharedmem_resources(const char* dirname) {
if (pid == 0) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
// attempt to remove all unexpected files, except "." and ".."
remove_file(dirname, entry->d_name);
unlink(entry->d_name);
}
errno = 0;
@ -552,12 +718,14 @@ static void cleanup_sharedmem_resources(const char* dirname) {
//
if ((pid == os::current_process_id()) ||
(kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
remove_file(dirname, entry->d_name);
unlink(entry->d_name);
}
errno = 0;
}
os::closedir(dirp);
// close the directory and reset the current working directory
close_directory_secure_cwd(dirp, saved_cwd_fd);
FREE_C_HEAP_ARRAY(char, dbuf);
}
@ -614,19 +782,54 @@ static int create_sharedmem_resources(const char* dirname, const char* filename,
return -1;
}
int result;
RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("could not create file %s: %s\n", filename, strerror(errno));
}
int saved_cwd_fd;
// open the directory and set the current working directory to it
DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
// Directory doesn't exist or is insecure, so cannot create shared
// memory file.
return -1;
}
// Open the filename in the current directory.
// Cannot use O_TRUNC here; truncation of an existing file has to happen
// after the is_file_secure() check below.
int result;
RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
if (errno == ELOOP) {
warning("file %s is a symlink and is not secure\n", filename);
} else {
warning("could not create file %s: %s\n", filename, strerror(errno));
}
}
// close the directory and reset the current working directory
close_directory_secure_cwd(dirp, saved_cwd_fd);
return -1;
}
// close the directory and reset the current working directory
close_directory_secure_cwd(dirp, saved_cwd_fd);
// save the file descriptor
int fd = result;
// check to see if the file is secure
if (!is_file_secure(fd, filename)) {
::close(fd);
return -1;
}
// truncate the file to get rid of any existing data
RESTARTABLE(::ftruncate(fd, (off_t)0), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("could not truncate shared memory file: %s\n", strerror(errno));
}
::close(fd);
return -1;
}
// set the file size
RESTARTABLE(::ftruncate(fd, (off_t)size), result);
if (result == OS_ERR) {
@ -684,8 +887,15 @@ static int open_sharedmem_file(const char* filename, int oflags, TRAPS) {
THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
}
}
int fd = result;
return result;
// check to see if the file is secure
if (!is_file_secure(fd, filename)) {
::close(fd);
return -1;
}
return fd;
}
// create a named shared memory region. returns the address of the
@ -716,6 +926,13 @@ static char* mmap_create_shared(size_t size) {
char* dirname = get_user_tmp_dir(user_name);
char* filename = get_sharedmem_filename(dirname, vmid);
// get the short filename
char* short_filename = strrchr(filename, '/');
if (short_filename == NULL) {
short_filename = filename;
} else {
short_filename++;
}
// cleanup any stale shared memory files
cleanup_sharedmem_resources(dirname);
@ -723,7 +940,7 @@ static char* mmap_create_shared(size_t size) {
assert(((size > 0) && (size % os::vm_page_size() == 0)),
"unexpected PerfMemory region size");
fd = create_sharedmem_resources(dirname, filename, size);
fd = create_sharedmem_resources(dirname, short_filename, size);
FREE_C_HEAP_ARRAY(char, user_name);
FREE_C_HEAP_ARRAY(char, dirname);
@ -838,12 +1055,12 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
// constructs for the file and the shared memory mapping.
if (mode == PerfMemory::PERF_MODE_RO) {
mmap_prot = PROT_READ;
file_flags = O_RDONLY;
file_flags = O_RDONLY | O_NOFOLLOW;
}
else if (mode == PerfMemory::PERF_MODE_RW) {
#ifdef LATER
mmap_prot = PROT_READ | PROT_WRITE;
file_flags = O_RDWR;
file_flags = O_RDWR | O_NOFOLLOW;
#else
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Unsupported access mode");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1475,6 +1475,16 @@ jlong os::javaTimeMillis() {
return jlong(t.tv_sec) * 1000 + jlong(t.tv_usec) / 1000;
}
void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) {
timeval t;
if (gettimeofday(&t, NULL) == -1) {
fatal(err_msg("os::javaTimeSystemUTC: gettimeofday (%s)", strerror(errno)));
}
seconds = jlong(t.tv_sec);
nanos = jlong(t.tv_usec) * 1000;
}
jlong os::javaTimeNanos() {
return (jlong)getTimeNanos();
}

View File

@ -199,7 +199,38 @@ static pid_t filename_to_pid(const char* filename) {
}
// check if the given path is considered a secure directory for
// Check if the given statbuf is considered a secure directory for
// the backing store files. Returns true if the directory is considered
// a secure location. Returns false if the statbuf is a symbolic link or
// if an error occurred.
//
static bool is_statbuf_secure(struct stat *statp) {
if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
// The path represents a link or some non-directory file type,
// which is not what we expected. Declare it insecure.
//
return false;
}
// We have an existing directory, check if the permissions are safe.
//
if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
// The directory is open for writing and could be subjected
// to a symlink or a hard link attack. Declare it insecure.
//
return false;
}
// See if the uid of the directory matches the effective uid of the process.
//
if (statp->st_uid != geteuid()) {
// The directory was not created by this user, declare it insecure.
//
return false;
}
return true;
}
// Check if the given path is considered a secure directory for
// the backing store files. Returns true if the directory exists
// and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
@ -213,27 +244,185 @@ static bool is_directory_secure(const char* path) {
return false;
}
// the path exists, now check it's mode
if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
// the path represents a link or some non-directory file type,
// which is not what we expected. declare it insecure.
//
// The path exists, see if it is secure.
return is_statbuf_secure(&statbuf);
}
// Check if the given directory file descriptor is considered a secure
// directory for the backing store files. Returns true if the directory
// exists and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
//
static bool is_dirfd_secure(int dir_fd) {
struct stat statbuf;
int result = 0;
RESTARTABLE(::fstat(dir_fd, &statbuf), result);
if (result == OS_ERR) {
return false;
}
else {
// we have an existing directory, check if the permissions are safe.
//
if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
// the directory is open for writing and could be subjected
// to a symlnk attack. declare it insecure.
//
return false;
// The path exists, now check its mode.
return is_statbuf_secure(&statbuf);
}
// Check to make sure fd1 and fd2 are referencing the same file system object.
//
static bool is_same_fsobject(int fd1, int fd2) {
struct stat statbuf1;
struct stat statbuf2;
int result = 0;
RESTARTABLE(::fstat(fd1, &statbuf1), result);
if (result == OS_ERR) {
return false;
}
RESTARTABLE(::fstat(fd2, &statbuf2), result);
if (result == OS_ERR) {
return false;
}
if ((statbuf1.st_ino == statbuf2.st_ino) &&
(statbuf1.st_dev == statbuf2.st_dev)) {
return true;
} else {
return false;
}
}
// Open the directory of the given path and validate it.
// Return a DIR * of the open directory.
//
static DIR *open_directory_secure(const char* dirname) {
// Open the directory using open() so that it can be verified
// to be secure by calling is_dirfd_secure(), opendir() and then check
// to see if they are the same file system object. This method does not
// introduce a window of opportunity for the directory to be attacked that
// calling opendir() and is_directory_secure() does.
int result;
DIR *dirp = NULL;
RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
if (result == OS_ERR) {
// Directory doesn't exist or is a symlink, so there is nothing to cleanup.
if (PrintMiscellaneous && Verbose) {
if (errno == ELOOP) {
warning("directory %s is a symlink and is not secure\n", dirname);
} else {
warning("could not open directory %s: %s\n", dirname, strerror(errno));
}
}
return dirp;
}
int fd = result;
// Determine if the open directory is secure.
if (!is_dirfd_secure(fd)) {
// The directory is not a secure directory.
os::close(fd);
return dirp;
}
// Open the directory.
dirp = ::opendir(dirname);
if (dirp == NULL) {
// The directory doesn't exist, close fd and return.
os::close(fd);
return dirp;
}
// Check to make sure fd and dirp are referencing the same file system object.
if (!is_same_fsobject(fd, dirp->dd_fd)) {
// The directory is not secure.
os::close(fd);
os::closedir(dirp);
dirp = NULL;
return dirp;
}
// Close initial open now that we know directory is secure
os::close(fd);
return dirp;
}
// NOTE: The code below uses fchdir(), open() and unlink() because
// fdopendir(), openat() and unlinkat() are not supported on all
// versions. Once the support for fdopendir(), openat() and unlinkat()
// is available on all supported versions the code can be changed
// to use these functions.
// Open the directory of the given path, validate it and set the
// current working directory to it.
// Return a DIR * of the open directory and the saved cwd fd.
//
static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
// Open the directory.
DIR* dirp = open_directory_secure(dirname);
if (dirp == NULL) {
// Directory doesn't exist or is insecure, so there is nothing to cleanup.
return dirp;
}
int fd = dirp->dd_fd;
// Open a fd to the cwd and save it off.
int result;
RESTARTABLE(::open(".", O_RDONLY), result);
if (result == OS_ERR) {
*saved_cwd_fd = -1;
} else {
*saved_cwd_fd = result;
}
// Set the current directory to dirname by using the fd of the directory.
result = fchdir(fd);
return dirp;
}
// Close the directory and restore the current working directory.
//
static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
int result;
// If we have a saved cwd change back to it and close the fd.
if (saved_cwd_fd != -1) {
result = fchdir(saved_cwd_fd);
::close(saved_cwd_fd);
}
// Close the directory.
os::closedir(dirp);
}
// Check if the given file descriptor is considered a secure.
//
static bool is_file_secure(int fd, const char *filename) {
int result;
struct stat statbuf;
// Determine if the file is secure.
RESTARTABLE(::fstat(fd, &statbuf), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("fstat failed on %s: %s\n", filename, strerror(errno));
}
return false;
}
if (statbuf.st_nlink > 1) {
// A file with multiple links is not expected.
if (PrintMiscellaneous && Verbose) {
warning("file %s has multiple links\n", filename);
}
return false;
}
return true;
}
// return the user name for the given user id
//
// the caller is expected to free the allocated memory.
@ -308,9 +497,11 @@ static char* get_user_name_slow(int vmid, TRAPS) {
const char* tmpdirname = os::get_temp_directory();
// open the temp directory
DIR* tmpdirp = os::opendir(tmpdirname);
if (tmpdirp == NULL) {
// Cannot open the directory to get the user name, return.
return NULL;
}
@ -335,7 +526,8 @@ static char* get_user_name_slow(int vmid, TRAPS) {
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
DIR* subdirp = os::opendir(usrdir_name);
// open the user directory
DIR* subdirp = open_directory_secure(usrdir_name);
if (subdirp == NULL) {
FREE_C_HEAP_ARRAY(char, usrdir_name);
@ -504,26 +696,6 @@ static void remove_file(const char* path) {
}
// remove file
//
// this method removes the file with the given file name in the
// named directory.
//
static void remove_file(const char* dirname, const char* filename) {
size_t nbytes = strlen(dirname) + strlen(filename) + 2;
char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
strcpy(path, dirname);
strcat(path, "/");
strcat(path, filename);
remove_file(path);
FREE_C_HEAP_ARRAY(char, path);
}
// cleanup stale shared memory resources
//
// This method attempts to remove all stale shared memory files in
@ -535,17 +707,11 @@ static void remove_file(const char* dirname, const char* filename) {
//
static void cleanup_sharedmem_resources(const char* dirname) {
// open the user temp directory
DIR* dirp = os::opendir(dirname);
int saved_cwd_fd;
// open the directory
DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
// directory doesn't exist, so there is nothing to cleanup
return;
}
if (!is_directory_secure(dirname)) {
// the directory is not a secure directory
os::closedir(dirp);
// directory doesn't exist or is insecure, so there is nothing to cleanup
return;
}
@ -559,6 +725,7 @@ static void cleanup_sharedmem_resources(const char* dirname) {
//
struct dirent* entry;
char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@ -569,7 +736,7 @@ static void cleanup_sharedmem_resources(const char* dirname) {
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
// attempt to remove all unexpected files, except "." and ".."
remove_file(dirname, entry->d_name);
unlink(entry->d_name);
}
errno = 0;
@ -592,11 +759,14 @@ static void cleanup_sharedmem_resources(const char* dirname) {
if ((pid == os::current_process_id()) ||
(kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
remove_file(dirname, entry->d_name);
unlink(entry->d_name);
}
errno = 0;
}
os::closedir(dirp);
// close the directory and reset the current working directory
close_directory_secure_cwd(dirp, saved_cwd_fd);
FREE_C_HEAP_ARRAY(char, dbuf);
}
@ -653,19 +823,54 @@ static int create_sharedmem_resources(const char* dirname, const char* filename,
return -1;
}
int result;
RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("could not create file %s: %s\n", filename, strerror(errno));
}
int saved_cwd_fd;
// open the directory and set the current working directory to it
DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
// Directory doesn't exist or is insecure, so cannot create shared
// memory file.
return -1;
}
// Open the filename in the current directory.
// Cannot use O_TRUNC here; truncation of an existing file has to happen
// after the is_file_secure() check below.
int result;
RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
if (errno == ELOOP) {
warning("file %s is a symlink and is not secure\n", filename);
} else {
warning("could not create file %s: %s\n", filename, strerror(errno));
}
}
// close the directory and reset the current working directory
close_directory_secure_cwd(dirp, saved_cwd_fd);
return -1;
}
// close the directory and reset the current working directory
close_directory_secure_cwd(dirp, saved_cwd_fd);
// save the file descriptor
int fd = result;
// check to see if the file is secure
if (!is_file_secure(fd, filename)) {
::close(fd);
return -1;
}
// truncate the file to get rid of any existing data
RESTARTABLE(::ftruncate(fd, (off_t)0), result);
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
warning("could not truncate shared memory file: %s\n", strerror(errno));
}
::close(fd);
return -1;
}
// set the file size
RESTARTABLE(::ftruncate(fd, (off_t)size), result);
if (result == OS_ERR) {
@ -701,8 +906,15 @@ static int open_sharedmem_file(const char* filename, int oflags, TRAPS) {
THROW_MSG_(vmSymbols::java_io_IOException(), strerror(errno), OS_ERR);
}
}
int fd = result;
return result;
// check to see if the file is secure
if (!is_file_secure(fd, filename)) {
::close(fd);
return -1;
}
return fd;
}
// create a named shared memory region. returns the address of the
@ -734,13 +946,21 @@ static char* mmap_create_shared(size_t size) {
char* dirname = get_user_tmp_dir(user_name);
char* filename = get_sharedmem_filename(dirname, vmid);
// get the short filename
char* short_filename = strrchr(filename, '/');
if (short_filename == NULL) {
short_filename = filename;
} else {
short_filename++;
}
// cleanup any stale shared memory files
cleanup_sharedmem_resources(dirname);
assert(((size > 0) && (size % os::vm_page_size() == 0)),
"unexpected PerfMemory region size");
fd = create_sharedmem_resources(dirname, filename, size);
fd = create_sharedmem_resources(dirname, short_filename, size);
FREE_C_HEAP_ARRAY(char, user_name);
FREE_C_HEAP_ARRAY(char, dirname);
@ -856,12 +1076,12 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
// constructs for the file and the shared memory mapping.
if (mode == PerfMemory::PERF_MODE_RO) {
mmap_prot = PROT_READ;
file_flags = O_RDONLY;
file_flags = O_RDONLY | O_NOFOLLOW;
}
else if (mode == PerfMemory::PERF_MODE_RW) {
#ifdef LATER
mmap_prot = PROT_READ | PROT_WRITE;
file_flags = O_RDWR;
file_flags = O_RDWR | O_NOFOLLOW;
#else
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Unsupported access mode");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -428,9 +428,9 @@ static unsigned __stdcall java_start(Thread* thread) {
}
// Diagnostic code to investigate JDK-6573254
int res = 50115; // non-java thread
int res = 30115; // non-java thread
if (thread->is_Java_thread()) {
res = 40115; // java thread
res = 20115; // java thread
}
// Install a win32 structured exception handler around every thread created
@ -839,6 +839,12 @@ jlong windows_to_java_time(FILETIME wt) {
return (a - offset()) / 10000;
}
// Returns time ticks in (10th of micro seconds)
jlong windows_to_time_ticks(FILETIME wt) {
jlong a = jlong_from(wt.dwHighDateTime, wt.dwLowDateTime);
return (a - offset());
}
FILETIME java_to_windows_time(jlong l) {
jlong a = (l * 10000) + offset();
FILETIME result;
@ -874,6 +880,15 @@ jlong os::javaTimeMillis() {
}
}
void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) {
FILETIME wt;
GetSystemTimeAsFileTime(&wt);
jlong ticks = windows_to_time_ticks(wt); // 10th of micros
jlong secs = jlong(ticks / 10000000); // 10000 * 1000
seconds = secs;
nanos = jlong(ticks - (secs*10000000)) * 100;
}
jlong os::javaTimeNanos() {
if (!win32::_has_performance_count) {
return javaTimeMillis() * NANOSECS_PER_MILLISEC; // the best we can do.
@ -1693,7 +1708,7 @@ void os::win32::print_windows_version(outputStream* st) {
}
break;
case 6004:
case 10000:
if (is_workstation) {
st->print("10");
} else {
@ -3791,6 +3806,7 @@ int os::win32::exit_process_or_thread(Ept what, int exit_code) {
static INIT_ONCE init_once_crit_sect = INIT_ONCE_STATIC_INIT;
static CRITICAL_SECTION crit_sect;
static volatile jint process_exiting = 0;
int i, j;
DWORD res;
HANDLE hproc, hthr;
@ -3798,10 +3814,10 @@ int os::win32::exit_process_or_thread(Ept what, int exit_code) {
// The first thread that reached this point, initializes the critical section.
if (!InitOnceExecuteOnce(&init_once_crit_sect, init_crit_sect_call, &crit_sect, NULL)) {
warning("crit_sect initialization failed in %s: %d\n", __FILE__, __LINE__);
} else {
} else if (OrderAccess::load_acquire(&process_exiting) == 0) {
EnterCriticalSection(&crit_sect);
if (what == EPT_THREAD) {
if (what == EPT_THREAD && OrderAccess::load_acquire(&process_exiting) == 0) {
// Remove from the array those handles of the threads that have completed exiting.
for (i = 0, j = 0; i < handle_count; ++i) {
res = WaitForSingleObject(handles[i], 0 /* don't wait */);
@ -3856,7 +3872,7 @@ int os::win32::exit_process_or_thread(Ept what, int exit_code) {
// The current exiting thread has stored its handle in the array, and now
// should leave the critical section before calling _endthreadex().
} else { // what != EPT_THREAD
} else if (what != EPT_THREAD) {
if (handle_count > 0) {
// Before ending the process, make sure all the threads that had called
// _endthreadex() completed.
@ -3882,24 +3898,28 @@ int os::win32::exit_process_or_thread(Ept what, int exit_code) {
handle_count = 0;
}
// End the process, not leaving critical section.
// This makes sure no other thread executes exit-related code at the same
// time, thus a race is avoided.
if (what == EPT_PROCESS) {
::exit(exit_code);
} else {
_exit(exit_code);
}
OrderAccess::release_store(&process_exiting, 1);
}
LeaveCriticalSection(&crit_sect);
}
if (what == EPT_THREAD) {
while (OrderAccess::load_acquire(&process_exiting) != 0) {
// Some other thread is about to call exit(), so we
// don't let the current thread proceed to _endthreadex()
SuspendThread(GetCurrentThread());
// Avoid busy-wait loop, if SuspendThread() failed.
Sleep(EXIT_TIMEOUT);
}
}
}
// We are here if either
// - there's no 'race at exit' bug on this OS release;
// - initialization of the critical section failed (unlikely);
// - the current thread has stored its handle and left the critical section.
// - the current thread has stored its handle and left the critical section;
// - the process-exiting thread has raised the flag and left the critical section.
if (what == EPT_THREAD) {
_endthreadex((unsigned)exit_code);
} else if (what == EPT_PROCESS) {

Some files were not shown because too many files have changed in this diff Show More