Merge
This commit is contained in:
commit
42ad69505d
2
.hgtags
2
.hgtags
@ -184,3 +184,5 @@ ffe6bce5a521be40146af2ac03c509b7bac30595 jdk8-b56
|
||||
5e3adc681779037a2d33b7be6f75680619085492 jdk8-b60
|
||||
cdaa6122185f9bf512dcd6600f56bfccc4824e8c jdk8-b61
|
||||
8d9d430b4244b95f5cf1ebe719f834a1ac5d6cd5 jdk8-b62
|
||||
21ee1dd7b809639284900a128b9b656a592ebc7a jdk8-b63
|
||||
70fa4b11f26522e69b51fd652215f60ce350bac3 jdk8-b64
|
||||
|
@ -184,3 +184,5 @@ dae9821589ccd2611bdf7084269b98e819091770 jdk8-b59
|
||||
e07f499b9dccb529ecf74172cf6ac11a195ec57a jdk8-b60
|
||||
20ff117b509075c3aec4ee3a57990ecd5db5df9c jdk8-b61
|
||||
8a3fe0ae06a8cc21347da5a18384b0aa6c2349f5 jdk8-b62
|
||||
3229597524cab4239325bc3602df6c486397a511 jdk8-b63
|
||||
1c8370a55b305d35353346202bde042ba9e8a9fd jdk8-b64
|
||||
|
@ -373,7 +373,11 @@ else
|
||||
# If we have a spec.gmk, we have run here before and we are OK. Otherwise, check for
|
||||
# other files
|
||||
files_present=`$LS $OUTPUT_ROOT`
|
||||
if test "x$files_present" != x; then
|
||||
# Configure has already touched config.log and confdefs.h in the current dir when this check
|
||||
# is performed.
|
||||
filtered_files=`$ECHO "$files_present" | $SED -e 's/config.log//g' -e 's/confdefs.h//g' -e 's/ //g' \
|
||||
| $TR -d '\n'`
|
||||
if test "x$filtered_files" != x; then
|
||||
AC_MSG_NOTICE([Current directory is $CURDIR.])
|
||||
AC_MSG_NOTICE([Since this is not the source root, configure will output the configuration here])
|
||||
AC_MSG_NOTICE([(as opposed to creating a configuration in <src_root>/build/<conf-name>).])
|
||||
|
@ -172,6 +172,13 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE_CYGWIN],
|
||||
|
||||
# Now try to locate executable using which
|
||||
new_path=`$WHICH "$new_path" 2> /dev/null`
|
||||
# bat and cmd files are not always considered executable in cygwin causing which
|
||||
# to not find them
|
||||
if test "x$new_path" = x \
|
||||
&& test "x`$ECHO \"$path\" | $GREP -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \
|
||||
&& test "x`$LS \"$path\" 2>/dev/null`" != x; then
|
||||
new_path=`$CYGPATH -u "$path"`
|
||||
fi
|
||||
if test "x$new_path" = x; then
|
||||
# Oops. Which didn't find the executable.
|
||||
# The splitting of arguments from the executable at a space might have been incorrect,
|
||||
@ -181,6 +188,13 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE_CYGWIN],
|
||||
arguments="EOL"
|
||||
new_path=`$CYGPATH -u "$path"`
|
||||
new_path=`$WHICH "$new_path" 2> /dev/null`
|
||||
# bat and cmd files are not always considered executable in cygwin causing which
|
||||
# to not find them
|
||||
if test "x$new_path" = x \
|
||||
&& test "x`$ECHO \"$path\" | $GREP -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \
|
||||
&& test "x`$LS \"$path\" 2>/dev/null`" != x; then
|
||||
new_path=`$CYGPATH -u "$path"`
|
||||
fi
|
||||
if test "x$new_path" = x; then
|
||||
# It's still not found. Now this is an unrecoverable error.
|
||||
AC_MSG_NOTICE([The path of $1, which resolves as "$complete", is not found.])
|
||||
|
@ -60,6 +60,7 @@ STAT="@STAT@"
|
||||
STRIP="@POST_STRIP_CMD@"
|
||||
TEE="@TEE@"
|
||||
UNIQ="@UNIQ@"
|
||||
UNPACK200="@FIXPATH@ @BOOT_JDK@/bin/unpack200"
|
||||
UNZIP="@UNZIP@"
|
||||
|
||||
SRC_ROOT="@SRC_ROOT@"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -393,7 +393,9 @@ else
|
||||
# AC_CHECK_LIB does not support use of cl.exe
|
||||
PREV_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="$FREETYPE2_LIBS"
|
||||
AC_CHECK_LIB(freetype, FT_Init_FreeType, [], AC_MSG_ERROR([Could not find freetype2! $HELP_MSG ]))
|
||||
AC_CHECK_LIB(freetype, FT_Init_FreeType,
|
||||
FREETYPE2_FOUND=true,
|
||||
AC_MSG_ERROR([Could not find freetype2! $HELP_MSG ]))
|
||||
LDFLAGS="$PREV_LDFLAGS"
|
||||
fi
|
||||
fi
|
||||
|
@ -253,5 +253,24 @@ AC_DEFUN_ONCE([SRCDIRS_SETUP_OUTPUT_DIRS],
|
||||
BUILD_OUTPUT="$OUTPUT_ROOT"
|
||||
AC_SUBST(BUILD_OUTPUT)
|
||||
|
||||
HOTSPOT_DIST="$OUTPUT_ROOT/hotspot/dist"
|
||||
BUILD_HOTSPOT=true
|
||||
AC_SUBST(HOTSPOT_DIST)
|
||||
AC_SUBST(BUILD_HOTSPOT)
|
||||
AC_ARG_WITH(import-hotspot, [AS_HELP_STRING([--with-import-hotspot],
|
||||
[import hotspot binaries from this jdk image or hotspot build dist dir instead of building from source])])
|
||||
if test "x$with_import_hotspot" != x; then
|
||||
CURDIR="$PWD"
|
||||
cd "$with_import_hotspot"
|
||||
HOTSPOT_DIST="`pwd`"
|
||||
cd "$CURDIR"
|
||||
if ! (test -d $HOTSPOT_DIST/lib && test -d $HOTSPOT_DIST/jre/lib); then
|
||||
AC_MSG_ERROR([You have to import hotspot from a full jdk image or hotspot build dist dir!])
|
||||
fi
|
||||
AC_MSG_CHECKING([if hotspot should be imported])
|
||||
AC_MSG_RESULT([yes from $HOTSPOT_DIST])
|
||||
BUILD_HOTSPOT=false
|
||||
fi
|
||||
|
||||
JDK_OUTPUTDIR="$OUTPUT_ROOT/jdk"
|
||||
])
|
||||
|
@ -224,7 +224,9 @@ LANGTOOLS_DIST=$(LANGTOOLS_OUTPUTDIR)/dist
|
||||
CORBA_DIST=$(CORBA_OUTPUTDIR)/dist
|
||||
JAXP_DIST=$(JAXP_OUTPUTDIR)/dist
|
||||
JAXWS_DIST=$(JAXWS_OUTPUTDIR)/dist
|
||||
HOTSPOT_DIST=$(HOTSPOT_OUTPUTDIR)/dist
|
||||
HOTSPOT_DIST=@HOTSPOT_DIST@
|
||||
|
||||
BUILD_HOTSPOT=@BUILD_HOTSPOT@
|
||||
|
||||
# The boot jdk to use
|
||||
BOOT_JDK:=@BOOT_JDK@
|
||||
@ -244,12 +246,6 @@ ENABLE_SJAVAC:=@ENABLE_SJAVAC@
|
||||
# Store sjavac server synchronization files here, and
|
||||
# the sjavac server log files.
|
||||
SJAVAC_SERVER_DIR:=@SJAVAC_SERVER_DIR@
|
||||
# We can block the Javac server to never use more cores than this.
|
||||
# This is not for performance reasons, but for memory usage, since each
|
||||
# core requires its own JavaCompiler. We might have 64 cores and 4GB
|
||||
# of memory, 64 JavaCompilers will currently not fit in a 3GB heap.
|
||||
# Since there is no sharing of data between the JavaCompilers.
|
||||
SJAVAC_SERVER_CORES:=@SJAVAC_SERVER_CORES@
|
||||
|
||||
# The OpenJDK makefiles should be changed to using the standard
|
||||
# configure output ..._CFLAGS and ..._LIBS. In the meantime we
|
||||
@ -494,7 +490,14 @@ FIXPATH:=@FIXPATH@
|
||||
# Where the build output is stored for your convenience.
|
||||
BUILD_LOG:=@BUILD_LOG@
|
||||
BUILD_LOG_PREVIOUS:=@BUILD_LOG_PREVIOUS@
|
||||
BUILD_LOG_WRAPPER:=@BUILD_LOG_WRAPPER@
|
||||
# Disable the build log wrapper on sjavac+winapi until
|
||||
# we have solved how to prevent the log wrapper to wait
|
||||
# for the background sjavac server process.
|
||||
ifeq (@ENABLE_SJAVAC@X@OPENJDK_BUILD_OS_API@,yesXwinapi)
|
||||
BUILD_LOG_WRAPPER:=
|
||||
else
|
||||
BUILD_LOG_WRAPPER:=@BUILD_LOG_WRAPPER@
|
||||
endif
|
||||
|
||||
# Build setup
|
||||
ENABLE_JFR=@ENABLE_JFR@
|
||||
|
@ -352,6 +352,29 @@ compare_zip_file() {
|
||||
(cd $THIS_UNZIPDIR && $UNARCHIVE $THIS_ZIP)
|
||||
(cd $OTHER_UNZIPDIR && $UNARCHIVE $OTHER_ZIP)
|
||||
|
||||
# Find all archives inside and unzip them as well to compare the contents rather than
|
||||
# the archives.
|
||||
EXCEPTIONS=""
|
||||
for pack in $($FIND $THIS_UNZIPDIR -name "*.pack" -o -name "*.pack.gz"); do
|
||||
($UNPACK200 $pack $pack.jar)
|
||||
# Filter out the unzipped archives from the diff below.
|
||||
EXCEPTIONS="$EXCEPTIONS $pack $pack.jar"
|
||||
done
|
||||
for pack in $($FIND $OTHER_UNZIPDIR -name "*.pack" -o -name "*.pack.gz"); do
|
||||
($UNPACK200 $pack $pack.jar)
|
||||
EXCEPTIONS="$EXCEPTIONS $pack $pack.jar"
|
||||
done
|
||||
for zip in $($FIND $THIS_UNZIPDIR -name "*.jar" -o -name "*.zip"); do
|
||||
$MKDIR $zip.unzip
|
||||
(cd $zip.unzip && $UNARCHIVE $zip)
|
||||
EXCEPTIONS="$EXCEPTIONS $zip"
|
||||
done
|
||||
for zip in $($FIND $OTHER_UNZIPDIR -name "*.jar" -o -name "*.zip"); do
|
||||
$MKDIR $zip.unzip
|
||||
(cd $zip.unzip && $UNARCHIVE $zip)
|
||||
EXCEPTIONS="$EXCEPTIONS $zip"
|
||||
done
|
||||
|
||||
CONTENTS_DIFF_FILE=$WORK_DIR/$ZIP_FILE.diff
|
||||
# On solaris, there is no -q option.
|
||||
if [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
|
||||
@ -389,7 +412,7 @@ compare_zip_file() {
|
||||
|
||||
$RM -f $WORK_DIR/$ZIP_FILE.diffs
|
||||
for file in $DIFFING_FILES; do
|
||||
if [[ "$ACCEPTED_JARZIP_CONTENTS" != *"$file"* ]]; then
|
||||
if [[ "$ACCEPTED_JARZIP_CONTENTS $EXCEPTIONS" != *"$file"* ]]; then
|
||||
diff_text $OTHER_UNZIPDIR/$file $THIS_UNZIPDIR/$file >> $WORK_DIR/$ZIP_FILE.diffs
|
||||
fi
|
||||
done
|
||||
@ -664,8 +687,8 @@ compare_bin_file() {
|
||||
|
||||
# Check dependencies
|
||||
if [ -n "$LDD_CMD" ]; then
|
||||
(cd $FILE_WORK_DIR && $CP $OTHER_FILE . && $LDD_CMD $NAME | $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 | $AWK '{ print $1;}' | $SORT | $TEE $WORK_FILE_BASE.deps.this | $UNIQ > $WORK_FILE_BASE.deps.this.uniq)
|
||||
(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)
|
||||
|
||||
LANG=C $DIFF $WORK_FILE_BASE.deps.other $WORK_FILE_BASE.deps.this > $WORK_FILE_BASE.deps.diff
|
||||
@ -846,7 +869,12 @@ compare_all_execs() {
|
||||
if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
|
||||
EXECS=$(cd $THIS_DIR && $FIND . -type f -name '*.exe' | $SORT | $FILTER)
|
||||
else
|
||||
EXECS=$(cd $THIS_DIR && $FIND . -name db -prune -o -type f -perm -100 \! \( -name '*.so' -o -name '*.dylib' -o -name '*.dll' -o -name '*.cgi' -o -name '*.jar' -o -name '*.diz' \) | $SORT | $FILTER)
|
||||
EXECS=$(cd $THIS_DIR && $FIND . -name db -prune -o -type f -perm -100 \! \
|
||||
\( -name '*.so' -o -name '*.dylib' -o -name '*.dll' -o -name '*.cgi' \
|
||||
-o -name '*.jar' -o -name '*.diz' -o -name 'jcontrol' -o -name '*.properties' \
|
||||
-o -name '*.data' -o -name '*.bfc' -o -name '*.src' -o -name '*.txt' \
|
||||
-o -name '*.cfg' -o -name 'meta-index' -o -name '*.properties.ja' \
|
||||
-o -name 'classlist' \) | $SORT | $FILTER)
|
||||
fi
|
||||
|
||||
if [ -n "$EXECS" ]; then
|
||||
@ -1022,6 +1050,7 @@ fi
|
||||
if [ -d "$THIS/deploy/j2sdk-image" ]; then
|
||||
THIS_J2SDK="$THIS/deploy/j2sdk-image"
|
||||
THIS_J2RE="$THIS/deploy/j2re-image"
|
||||
echo "Comparing deploy images"
|
||||
elif [ -d "$THIS/images/j2sdk-image" ]; then
|
||||
THIS_J2SDK="$THIS/images/j2sdk-image"
|
||||
THIS_J2RE="$THIS/images/j2re-image"
|
||||
|
@ -282,6 +282,14 @@ ACCEPTED_SMALL_SIZE_DIFF="
|
||||
./jre/lib/i386/libunpack.so
|
||||
./jre/lib/i386/libverify.so
|
||||
./jre/lib/i386/libzip.so
|
||||
./jre/lib/i386/libdeploy.so
|
||||
./jre/lib/i386/libjavaplugin.so
|
||||
./jre/lib/i386/libjavaplugin_jni.so
|
||||
./jre/lib/i386/libjavaplugin_nscp.so
|
||||
./jre/lib/i386/libjavaplugin_oji.so
|
||||
./jre/lib/i386/libnpjp2.so
|
||||
./jre/plugin/i386/ns4/libjavaplugin.so
|
||||
./jre/plugin/i386/ns7/libjavaplugin_oji.so
|
||||
./jre/lib/i386/server/libjvm.so
|
||||
./bin/appletviewer
|
||||
./bin/extcheck
|
||||
@ -293,6 +301,7 @@ ACCEPTED_SMALL_SIZE_DIFF="
|
||||
./bin/javadoc
|
||||
./bin/javah
|
||||
./bin/javap
|
||||
./bin/javaws
|
||||
./bin/jcmd
|
||||
./bin/jconsole
|
||||
./bin/jdb
|
||||
@ -322,6 +331,8 @@ ACCEPTED_SMALL_SIZE_DIFF="
|
||||
./bin/wsimport
|
||||
./bin/xjc
|
||||
./jre/bin/java
|
||||
./jre/bin/java_vm
|
||||
./jre/bin/javaws
|
||||
./jre/bin/keytool
|
||||
./jre/bin/orbd
|
||||
./jre/bin/pack200
|
||||
@ -561,6 +572,14 @@ ACCEPTED_SMALL_SIZE_DIFF="
|
||||
./jre/lib/sparc/libunpack.so
|
||||
./jre/lib/sparc/libverify.so
|
||||
./jre/lib/sparc/libzip.so
|
||||
./jre/lib/sparc/libdeploy.so
|
||||
./jre/lib/sparc/libjavaplugin.so
|
||||
./jre/lib/sparc/libjavaplugin_jni.so
|
||||
./jre/lib/sparc/libjavaplugin_nscp.so
|
||||
./jre/lib/sparc/libjavaplugin_oji.so
|
||||
./jre/lib/sparc/libnpjp2.so
|
||||
./jre/plugin/sparc/ns4/libjavaplugin.so
|
||||
./jre/plugin/sparc/ns7/libjavaplugin_oji.so
|
||||
./jre/lib/sparc/server/libjvm.so
|
||||
./bin/appletviewer
|
||||
./bin/extcheck
|
||||
@ -572,6 +591,7 @@ ACCEPTED_SMALL_SIZE_DIFF="
|
||||
./bin/javadoc
|
||||
./bin/javah
|
||||
./bin/javap
|
||||
./bin/javaws
|
||||
./bin/jcmd
|
||||
./bin/jconsole
|
||||
./bin/jdb
|
||||
@ -601,6 +621,8 @@ ACCEPTED_SMALL_SIZE_DIFF="
|
||||
./bin/wsimport
|
||||
./bin/xjc
|
||||
./jre/bin/java
|
||||
./jre/bin/java_vm
|
||||
./jre/bin/javaws
|
||||
./jre/bin/keytool
|
||||
./jre/bin/orbd
|
||||
./jre/bin/pack200
|
||||
|
@ -111,7 +111,7 @@ define SetupArchive
|
||||
ifeq ($$(word 20,$$($1_GREP_INCLUDE_PATTERNS)),)
|
||||
$1_GREP_INCLUDES:=| $(GREP) $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_INCLUDE_PATTERNS))
|
||||
else
|
||||
$$(shell $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_include)
|
||||
$$(shell $(MKDIR) -p $$($1_BIN) && $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_include)
|
||||
$$(eval $$(call ListPathsSafelyNow,$1_GREP_INCLUDE_PATTERNS,\n, \
|
||||
>> $$($1_BIN)/_the.$$($1_JARNAME)_include))
|
||||
$1_GREP_INCLUDES:=| $(GREP) -f $$($1_BIN)/_the.$$($1_JARNAME)_include
|
||||
@ -124,7 +124,7 @@ define SetupArchive
|
||||
ifeq ($$(word 20,$$($1_GREP_EXCLUDE_PATTERNS)),)
|
||||
$1_GREP_EXCLUDES:=| $(GREP) -v $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_EXCLUDE_PATTERNS))
|
||||
else
|
||||
$$(shell $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_exclude)
|
||||
$$(shell $(MKDIR) -p $$($1_BIN) && $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_exclude)
|
||||
$$(eval $$(call ListPathsSafelyNow,$1_GREP_EXCLUDE_PATTERNS,\n, \
|
||||
>> $$($1_BIN)/_the.$$($1_JARNAME)_exclude))
|
||||
$1_GREP_EXCLUDES:=| $(GREP) -v -f $$($1_BIN)/_the.$$($1_JARNAME)_exclude
|
||||
@ -170,9 +170,10 @@ define SetupArchive
|
||||
# tells us what to remove from the jar-file.
|
||||
$1_CAPTURE_DELETES=$$(foreach src,$$($1_SRCS),($(FIND) $$(src) -name _the.package.deleted -newer $$@ -exec $(SED) 's|$$(src)||g' \{\} >> $$($1_DELETES_FILE) \;) $$(NEWLINE))
|
||||
# The update contents macro updates the jar file with the previously capture contents.
|
||||
# xargs is used to trim the whitespace from the contents file, to see if it is empty.
|
||||
$1_UPDATE_CONTENTS=$$(foreach src,$$($1_SRCS),\
|
||||
(cd $$(src) && \
|
||||
if [ -s _the.$$($1_JARNAME)_contents ]; then \
|
||||
if [ -n "`$(CAT) _the.$$($1_JARNAME)_contents | $(XARGS)`" ]; then \
|
||||
$(ECHO) " updating" `$(WC) -l _the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'` files && \
|
||||
$(JAR) $$($1_JAR_UPDATE_OPTIONS) $$@ @_the.$$($1_JARNAME)_contents; \
|
||||
fi) $$(NEWLINE))
|
||||
@ -480,19 +481,24 @@ define SetupJavaCompilation
|
||||
$1_SJAVAC:=$$(word 1,$$($1_JAVAC)) -cp $$(word 3,$$($1_JAVAC)) com.sun.tools.sjavac.Main
|
||||
|
||||
# Set the $1_REMOTE to spawn a background javac server.
|
||||
$1_REMOTE:=--server:portfile=$$($1_SJAVAC_PORTFILE),poolsize=$(SJAVAC_SERVER_CORES),id=$1,sjavac=$$(subst $$(SPACE),%20,$$(subst $$(COMMA),%2C,$$(strip $$($1_SERVER_JVM) $$($1_SJAVAC))))
|
||||
$1_REMOTE:=--server:portfile=$$($1_SJAVAC_PORTFILE),id=$1,sjavac=$$(subst $$(SPACE),%20,$$(subst $$(COMMA),%2C,$$(strip $$($1_SERVER_JVM) $$($1_SJAVAC))))
|
||||
|
||||
$$($1_BIN)/javac_state: $$($1_SRCS) $$($1_DEPENDS)
|
||||
$(MKDIR) -p $$(@D)
|
||||
$$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.batch.tmp)
|
||||
$(ECHO) Compiling $1
|
||||
$$($1_JVM) $$($1_SJAVAC) \
|
||||
$$($1_REMOTE) $$($1_SJAVAC_ARGS) \
|
||||
($$($1_JVM) $$($1_SJAVAC) \
|
||||
$$($1_REMOTE) \
|
||||
-j $(NUM_CORES) \
|
||||
--permit-unidentified-artifacts \
|
||||
--permit-sources-without-package \
|
||||
--compare-found-sources $$($1_BIN)/_the.batch.tmp \
|
||||
--log=$(LOG) \
|
||||
$$($1_SJAVAC_ARGS) \
|
||||
$$($1_FLAGS) \
|
||||
-implicit:none -d $$($1_BIN) $$($1_HEADERS_ARG)
|
||||
$$($1_HEADERS_ARG) \
|
||||
-d $$($1_BIN) && \
|
||||
$(MV) $$($1_BIN)/_the.batch.tmp $$($1_BIN)/_the.batch)
|
||||
else
|
||||
# Using plain javac to batch compile everything.
|
||||
$1 := $$($1_ALL_COPY_TARGETS) $$($1_ALL_COPY_CLEAN_TARGETS) $$($1_BIN)/_the.batch
|
||||
|
@ -94,11 +94,13 @@ jaxws-only: start-make
|
||||
@($(CD) $(JAXWS_TOPDIR)/makefiles && $(BUILD_LOG_WRAPPER) $(MAKE) $(MAKE_ARGS) -f BuildJaxws.gmk)
|
||||
@$(call TargetExit)
|
||||
|
||||
ifeq ($(BUILD_HOTSPOT),true)
|
||||
hotspot: hotspot-only
|
||||
hotspot-only: start-make
|
||||
@$(call TargetEnter)
|
||||
@($(CD) $(SRC_ROOT)/common/makefiles && $(BUILD_LOG_WRAPPER) $(MAKE) $(MAKE_ARGS) -f HotspotWrapper.gmk)
|
||||
@$(call TargetExit)
|
||||
endif
|
||||
|
||||
jdk: langtools hotspot corba jaxp jaxws jdk-only
|
||||
jdk-only: start-make
|
||||
|
@ -65,7 +65,7 @@ endef
|
||||
# The \n argument means translate spaces into \n
|
||||
# if instead , , (a space) is supplied, then spaces remain spaces.
|
||||
define ListPathsSafely
|
||||
$(if $(word 10001,$($1)),$(error Cannot list safely more than 10000 paths. $1 has $(words $($1)) paths!))
|
||||
$(if $(word 16001,$($1)),$(error Cannot list safely more than 16000 paths. $1 has $(words $($1)) paths!))
|
||||
$(call ListPathsSafely_If,$1,$2,1,250)
|
||||
$(call ListPathsSafely_If,$1,$2,251,500)
|
||||
$(call ListPathsSafely_If,$1,$2,501,750)
|
||||
@ -116,6 +116,36 @@ define ListPathsSafely
|
||||
$(call ListPathsSafely_If,$1,$2,9501,9750)
|
||||
$(call ListPathsSafely_If,$1,$2,9751,10000)
|
||||
|
||||
$(call ListPathsSafely_If,$1,$2,10001,10250)
|
||||
$(call ListPathsSafely_If,$1,$2,10251,10500)
|
||||
$(call ListPathsSafely_If,$1,$2,10501,10750)
|
||||
$(call ListPathsSafely_If,$1,$2,10751,11000)
|
||||
|
||||
$(call ListPathsSafely_If,$1,$2,11001,11250)
|
||||
$(call ListPathsSafely_If,$1,$2,11251,11500)
|
||||
$(call ListPathsSafely_If,$1,$2,11501,11750)
|
||||
$(call ListPathsSafely_If,$1,$2,11751,12000)
|
||||
|
||||
$(call ListPathsSafely_If,$1,$2,12001,12250)
|
||||
$(call ListPathsSafely_If,$1,$2,12251,12500)
|
||||
$(call ListPathsSafely_If,$1,$2,12501,12750)
|
||||
$(call ListPathsSafely_If,$1,$2,12751,13000)
|
||||
|
||||
$(call ListPathsSafely_If,$1,$2,13001,13250)
|
||||
$(call ListPathsSafely_If,$1,$2,13251,13500)
|
||||
$(call ListPathsSafely_If,$1,$2,13501,13750)
|
||||
$(call ListPathsSafely_If,$1,$2,13751,14000)
|
||||
|
||||
$(call ListPathsSafely_If,$1,$2,14001,14250)
|
||||
$(call ListPathsSafely_If,$1,$2,14251,14500)
|
||||
$(call ListPathsSafely_If,$1,$2,14501,14750)
|
||||
$(call ListPathsSafely_If,$1,$2,14751,15000)
|
||||
|
||||
$(call ListPathsSafely_If,$1,$2,15001,15250)
|
||||
$(call ListPathsSafely_If,$1,$2,15251,15500)
|
||||
$(call ListPathsSafely_If,$1,$2,15501,15750)
|
||||
$(call ListPathsSafely_If,$1,$2,15751,16000)
|
||||
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,1)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,251)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,501)
|
||||
@ -165,6 +195,36 @@ define ListPathsSafely
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,9251)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,9501)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,9751)
|
||||
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,10001)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,10251)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,10501)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,10751)
|
||||
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,11001)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,11251)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,11501)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,11751)
|
||||
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,12001)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,12251)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,12501)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,12751)
|
||||
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,13001)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,13251)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,13501)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,13751)
|
||||
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,14001)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,14251)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,14501)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,14751)
|
||||
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,15001)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,15251)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,15501)
|
||||
$(call ListPathsSafely_Printf,$1,$2,$3,15751)
|
||||
endef
|
||||
|
||||
define ListPathsSafelyNow_IfPrintf
|
||||
|
@ -157,7 +157,7 @@ endef
|
||||
|
||||
# Hook to be called as the very last thing for targets that are "top level" targets
|
||||
define AtMakeEnd
|
||||
$(if $(SJAVAC_SERVER_DIR),@$(RM) -rf $(SJAVAC_SERVER_DIR)/*.port)
|
||||
[ -f $(SJAVAC_SERVER_DIR)/server.port ] && echo Stopping sjavac server && $(TOUCH) $(SJAVAC_SERVER_DIR)/server.port.stop; true
|
||||
$(call StopGlobalTimer)
|
||||
$(call ReportBuildTimes)
|
||||
@$(PRINTF) "Finished building $(PRODUCT_NAME) for target '$(call GetRealTarget)'\n"
|
||||
@ -174,8 +174,8 @@ endef
|
||||
define ParseLogLevel
|
||||
ifeq ($$(origin VERBOSE),undefined)
|
||||
# Setup logging according to LOG (but only if VERBOSE is not given)
|
||||
|
||||
# If the "nofile" argument is given, act on it and strip it away
|
||||
|
||||
# If the "nofile" argument is given, act on it and strip it away
|
||||
ifneq ($$(findstring nofile,$$(LOG)),)
|
||||
# Reset the build log wrapper, regardless of other values
|
||||
override BUILD_LOG_WRAPPER=
|
||||
|
@ -184,3 +184,5 @@ d54dc53e223ed9ce7d5f4d2cd02ad9d5def3c2db jdk8-b59
|
||||
207ef43ba69ead6cbbab415d81834545e4d46747 jdk8-b60
|
||||
0e08ba7648fb3faa0986cb217887d7c4990977f3 jdk8-b61
|
||||
08afb9c6f44f11c3595b01fd0985db64b29834dd jdk8-b62
|
||||
6ccbf67b68bfed1ab9c44ab8748a5bdc7df33506 jdk8-b63
|
||||
54d599a5b4aad83c235d590652fc81f41c2824fb jdk8-b64
|
||||
|
@ -42,16 +42,6 @@ import java.util.NoSuchElementException;
|
||||
* instead, it uses the System.identityHashcode() method and pointer comparison.
|
||||
* In addition, all synchronization has been removed.
|
||||
*/
|
||||
/**
|
||||
* IdentityHashtable collision list.
|
||||
*/
|
||||
class IdentityHashtableEntry {
|
||||
int hash;
|
||||
Object key;
|
||||
Object value;
|
||||
IdentityHashtableEntry next;
|
||||
}
|
||||
|
||||
public final class IdentityHashtable extends Dictionary {
|
||||
/**
|
||||
* The hash table data.
|
||||
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2004, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Licensed Materials - Property of IBM
|
||||
* RMI-IIOP v1.0
|
||||
* Copyright IBM Corp. 1998 1999 All Rights Reserved
|
||||
*
|
||||
*/
|
||||
|
||||
package com.sun.corba.se.impl.util;
|
||||
|
||||
/**
|
||||
* IdentityHashtable collision list.
|
||||
*/
|
||||
class IdentityHashtableEntry {
|
||||
int hash;
|
||||
Object key;
|
||||
Object value;
|
||||
IdentityHashtableEntry next;
|
||||
}
|
@ -289,3 +289,7 @@ b261523fe66c40a02968f0aa7e73602491bb3386 hs25-b05
|
||||
d0337c31c8be7716369b4e7c3bd5f352983c6a06 hs25-b06
|
||||
dccd40de8db1fa96f186e6179907818d75320440 jdk8-b62
|
||||
dc16fe422c535ecd4e9f80fb814a1bb9704da6f5 hs25-b07
|
||||
acabb5c282f59be7e3238920b2ea06b684ab68f7 jdk8-b63
|
||||
8cb93eadfb6dcab88d91b8e2cd3e0e07d0ac4048 hs25-b08
|
||||
5920f72e799c8133d1066c4a62fa1fafcb729966 jdk8-b64
|
||||
b4ee7b773144a88af8b6b92e4384dea82cb948d8 hs25-b09
|
||||
|
@ -121,7 +121,7 @@ public class ConstantPool extends Metadata implements ClassConstants {
|
||||
Address addr = cache.getValue(getAddress());
|
||||
return (ConstantPoolCache) VMObjectFactory.newObject(ConstantPoolCache.class, addr);
|
||||
}
|
||||
public Klass getPoolHolder() { return (Klass) poolHolder.getValue(this); }
|
||||
public InstanceKlass getPoolHolder() { return (InstanceKlass)poolHolder.getValue(this); }
|
||||
public int getLength() { return (int)length.getValue(getAddress()); }
|
||||
public Oop getResolvedReferences() {
|
||||
Address handle = resolvedReferences.getValue(getAddress());
|
||||
|
@ -177,7 +177,7 @@ public class Method extends Metadata {
|
||||
bci. It is required that there is currently a bytecode at this
|
||||
bci. */
|
||||
public int getOrigBytecodeAt(int bci) {
|
||||
BreakpointInfo bp = ((InstanceKlass) getMethodHolder()).getBreakpoints();
|
||||
BreakpointInfo bp = getMethodHolder().getBreakpoints();
|
||||
for (; bp != null; bp = bp.getNext()) {
|
||||
if (bp.match(this, bci)) {
|
||||
return bp.getOrigBytecode();
|
||||
@ -238,7 +238,7 @@ public class Method extends Metadata {
|
||||
}
|
||||
|
||||
// Method holder (the Klass holding this method)
|
||||
public Klass getMethodHolder() { return getConstants().getPoolHolder(); }
|
||||
public InstanceKlass getMethodHolder() { return getConstants().getPoolHolder(); }
|
||||
|
||||
// Access flags
|
||||
public boolean isPublic() { return getAccessFlagsObj().isPublic(); }
|
||||
|
@ -453,14 +453,30 @@ ifneq ($(OSNAME),windows)
|
||||
ifeq ($(JVM_VARIANT_ZEROSHARK), true)
|
||||
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
|
||||
$(install-file)
|
||||
$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo): $(SHARK_DIR)/%.debuginfo
|
||||
$(install-file)
|
||||
$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(SHARK_DIR)/%.diz
|
||||
$(install-file)
|
||||
$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
|
||||
$(install-file)
|
||||
$(EXPORT_SERVER_DIR)/%.debuginfo: $(SHARK_DIR)/%.debuginfo
|
||||
$(install-file)
|
||||
$(EXPORT_SERVER_DIR)/%.diz: $(SHARK_DIR)/%.diz
|
||||
$(install-file)
|
||||
endif
|
||||
ifeq ($(JVM_VARIANT_ZERO), true)
|
||||
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
|
||||
$(install-file)
|
||||
$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(ZERO_DIR)/%.debuginfo
|
||||
$(install-file)
|
||||
$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(ZERO_DIR)/%.diz
|
||||
$(install-file)
|
||||
$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
|
||||
$(install-file)
|
||||
$(EXPORT_SERVER_DIR)/%.debuginfo: $(ZERO_DIR)/%.debuginfo
|
||||
$(install-file)
|
||||
$(EXPORT_SERVER_DIR)/%.diz: $(ZERO_DIR)/%.diz
|
||||
$(install-file)
|
||||
endif
|
||||
ifeq ($(JVM_VARIANT_MINIMAL1), true)
|
||||
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(MINIMAL1_DIR)/%.$(LIBRARY_SUFFIX)
|
||||
|
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2012
|
||||
|
||||
HS_MAJOR_VER=25
|
||||
HS_MINOR_VER=0
|
||||
HS_BUILD_NUMBER=07
|
||||
HS_BUILD_NUMBER=09
|
||||
|
||||
JDK_MAJOR_VER=1
|
||||
JDK_MINOR_VER=8
|
||||
|
@ -170,68 +170,70 @@ ifeq ($(JDK6_OR_EARLIER),0)
|
||||
# overridden in some situations, e.g., a BUILD_FLAVOR != product
|
||||
# build.
|
||||
|
||||
ifeq ($(BUILD_FLAVOR), product)
|
||||
FULL_DEBUG_SYMBOLS ?= 1
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
|
||||
else
|
||||
# debug variants always get Full Debug Symbols (if available)
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = 1
|
||||
endif
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
# since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
|
||||
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
# Default OBJCOPY comes from GNU Binutils on Linux:
|
||||
DEF_OBJCOPY=/usr/bin/objcopy
|
||||
ifdef CROSS_COMPILE_ARCH
|
||||
# don't try to generate .debuginfo files when cross compiling
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: cross compiling for ARCH $(CROSS_COMPILE_ARCH)," \
|
||||
"skipping .debuginfo generation.")
|
||||
OBJCOPY=
|
||||
# Due to the multiple sub-make processes that occur this logic gets
|
||||
# executed multiple times. We reduce the noise by at least checking that
|
||||
# BUILD_FLAVOR has been set.
|
||||
ifneq ($(BUILD_FLAVOR),)
|
||||
ifeq ($(BUILD_FLAVOR), product)
|
||||
FULL_DEBUG_SYMBOLS ?= 1
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
|
||||
else
|
||||
# debug variants always get Full Debug Symbols (if available)
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = 1
|
||||
endif
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
# since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
|
||||
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
# Default OBJCOPY comes from GNU Binutils on Linux
|
||||
ifeq ($(CROSS_COMPILE_ARCH),)
|
||||
DEF_OBJCOPY=/usr/bin/objcopy
|
||||
else
|
||||
# Assume objcopy is part of the cross-compilation toolset
|
||||
ifneq ($(ALT_COMPILER_PATH),)
|
||||
DEF_OBJCOPY=$(ALT_COMPILER_PATH)/objcopy
|
||||
endif
|
||||
endif
|
||||
OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
|
||||
ifneq ($(ALT_OBJCOPY),)
|
||||
_JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
|
||||
OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
|
||||
endif
|
||||
endif
|
||||
else
|
||||
OBJCOPY=
|
||||
endif
|
||||
|
||||
ifeq ($(OBJCOPY),)
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.")
|
||||
ENABLE_FULL_DEBUG_SYMBOLS=0
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
else
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.")
|
||||
ifeq ($(OBJCOPY),)
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files. You may need to set ALT_OBJCOPY.")
|
||||
ENABLE_FULL_DEBUG_SYMBOLS=0
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
else
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.")
|
||||
|
||||
# Library stripping policies for .debuginfo configs:
|
||||
# all_strip - strips everything from the library
|
||||
# min_strip - strips most stuff from the library; leaves minimum symbols
|
||||
# no_strip - does not strip the library at all
|
||||
#
|
||||
# Oracle security policy requires "all_strip". A waiver was granted on
|
||||
# 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE.
|
||||
#
|
||||
# Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled.
|
||||
#
|
||||
STRIP_POLICY ?= min_strip
|
||||
# Library stripping policies for .debuginfo configs:
|
||||
# all_strip - strips everything from the library
|
||||
# min_strip - strips most stuff from the library; leaves minimum symbols
|
||||
# no_strip - does not strip the library at all
|
||||
#
|
||||
# Oracle security policy requires "all_strip". A waiver was granted on
|
||||
# 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE.
|
||||
#
|
||||
# Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled.
|
||||
#
|
||||
STRIP_POLICY ?= min_strip
|
||||
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)")
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)")
|
||||
|
||||
ZIP_DEBUGINFO_FILES ?= 1
|
||||
ZIP_DEBUGINFO_FILES ?= 1
|
||||
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)")
|
||||
endif
|
||||
endif
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)")
|
||||
endif
|
||||
endif # ENABLE_FULL_DEBUG_SYMBOLS=1
|
||||
endif # BUILD_FLAVOR
|
||||
endif # JDK_6_OR_EARLIER
|
||||
|
||||
JDK_INCLUDE_SUBDIR=linux
|
||||
|
||||
|
@ -336,24 +336,23 @@ $(LIBJVM): $(LIBJVM.o) $(LIBJVM_MAPFILE) $(LD_SCRIPT)
|
||||
fi \
|
||||
fi \
|
||||
}
|
||||
ifeq ($(CROSS_COMPILE_ARCH),)
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DEBUGINFO)
|
||||
$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DEBUGINFO) $@
|
||||
ifeq ($(STRIP_POLICY),all_strip)
|
||||
ifeq ($(STRIP_POLICY),all_strip)
|
||||
$(QUIETLY) $(STRIP) $@
|
||||
else
|
||||
ifeq ($(STRIP_POLICY),min_strip)
|
||||
else
|
||||
ifeq ($(STRIP_POLICY),min_strip)
|
||||
$(QUIETLY) $(STRIP) -g $@
|
||||
# implied else here is no stripping at all
|
||||
endif
|
||||
# implied else here is no stripping at all
|
||||
endif
|
||||
endif
|
||||
$(QUIETLY) [ -f $(LIBJVM_G_DEBUGINFO) ] || ln -s $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
|
||||
ifeq ($(ZIP_DEBUGINFO_FILES),1)
|
||||
ifeq ($(ZIP_DEBUGINFO_FILES),1)
|
||||
$(ZIPEXE) -q -y $(LIBJVM_DIZ) $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
|
||||
$(RM) $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
|
||||
[ -f $(LIBJVM_G_DIZ) ] || { ln -s $(LIBJVM_DIZ) $(LIBJVM_G_DIZ); }
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -109,60 +109,63 @@ ifeq ($(JDK6_OR_EARLIER),0)
|
||||
# overridden in some situations, e.g., a BUILD_FLAVOR != product
|
||||
# build.
|
||||
|
||||
ifeq ($(BUILD_FLAVOR), product)
|
||||
FULL_DEBUG_SYMBOLS ?= 1
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
|
||||
else
|
||||
# debug variants always get Full Debug Symbols (if available)
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = 1
|
||||
endif
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
# since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
|
||||
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
# Default OBJCOPY comes from the SUNWbinutils package:
|
||||
DEF_OBJCOPY=/usr/sfw/bin/gobjcopy
|
||||
OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
|
||||
ifneq ($(ALT_OBJCOPY),)
|
||||
_JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
|
||||
OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
|
||||
# Due to the multiple sub-make processes that occur this logic gets
|
||||
# executed multiple times. We reduce the noise by at least checking that
|
||||
# BUILD_FLAVOR has been set.
|
||||
ifneq ($(BUILD_FLAVOR),)
|
||||
ifeq ($(BUILD_FLAVOR), product)
|
||||
FULL_DEBUG_SYMBOLS ?= 1
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
|
||||
else
|
||||
# debug variants always get Full Debug Symbols (if available)
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = 1
|
||||
endif
|
||||
else
|
||||
OBJCOPY=
|
||||
endif
|
||||
|
||||
ifeq ($(OBJCOPY),)
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.")
|
||||
ENABLE_FULL_DEBUG_SYMBOLS=0
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
else
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.")
|
||||
# since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
|
||||
|
||||
# Library stripping policies for .debuginfo configs:
|
||||
# all_strip - strips everything from the library
|
||||
# min_strip - strips most stuff from the library; leaves minimum symbols
|
||||
# no_strip - does not strip the library at all
|
||||
#
|
||||
# Oracle security policy requires "all_strip". A waiver was granted on
|
||||
# 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE.
|
||||
#
|
||||
# Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled.
|
||||
#
|
||||
STRIP_POLICY ?= min_strip
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
# Default OBJCOPY comes from the SUNWbinutils package:
|
||||
DEF_OBJCOPY=/usr/sfw/bin/gobjcopy
|
||||
OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
|
||||
ifneq ($(ALT_OBJCOPY),)
|
||||
_JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
|
||||
OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
|
||||
endif
|
||||
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)")
|
||||
ifeq ($(OBJCOPY),)
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.")
|
||||
ENABLE_FULL_DEBUG_SYMBOLS=0
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
else
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.")
|
||||
|
||||
ZIP_DEBUGINFO_FILES ?= 1
|
||||
# Library stripping policies for .debuginfo configs:
|
||||
# all_strip - strips everything from the library
|
||||
# min_strip - strips most stuff from the library; leaves minimum symbols
|
||||
# no_strip - does not strip the library at all
|
||||
#
|
||||
# Oracle security policy requires "all_strip". A waiver was granted on
|
||||
# 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE.
|
||||
#
|
||||
# Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled.
|
||||
#
|
||||
STRIP_POLICY ?= min_strip
|
||||
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)")
|
||||
endif
|
||||
endif
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)")
|
||||
|
||||
ZIP_DEBUGINFO_FILES ?= 1
|
||||
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)")
|
||||
endif
|
||||
endif # ENABLE_FULL_DEBUG_SYMBOLS=1
|
||||
endif # BUILD_FLAVOR
|
||||
endif # JDK_6_OR_EARLIER
|
||||
|
||||
JDK_INCLUDE_SUBDIR=solaris
|
||||
|
||||
|
@ -131,23 +131,29 @@ endif
|
||||
# overridden in some situations, e.g., a BUILD_FLAVOR != product
|
||||
# build.
|
||||
|
||||
ifeq ($(BUILD_FLAVOR), product)
|
||||
FULL_DEBUG_SYMBOLS ?= 1
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
|
||||
else
|
||||
# debug variants always get Full Debug Symbols (if available)
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = 1
|
||||
endif
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
MAKE_ARGS += ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)
|
||||
# Due to the multiple sub-make processes that occur this logic gets
|
||||
# executed multiple times. We reduce the noise by at least checking that
|
||||
# BUILD_FLAVOR has been set.
|
||||
ifneq ($(BUILD_FLAVOR),)
|
||||
ifeq ($(BUILD_FLAVOR), product)
|
||||
FULL_DEBUG_SYMBOLS ?= 1
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
|
||||
else
|
||||
# debug variants always get Full Debug Symbols (if available)
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = 1
|
||||
endif
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
MAKE_ARGS += ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)
|
||||
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
ZIP_DEBUGINFO_FILES ?= 1
|
||||
else
|
||||
ZIP_DEBUGINFO_FILES=0
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
ZIP_DEBUGINFO_FILES ?= 1
|
||||
else
|
||||
ZIP_DEBUGINFO_FILES=0
|
||||
endif
|
||||
MAKE_ARGS += ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)
|
||||
endif
|
||||
MAKE_ARGS += ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)
|
||||
|
||||
MAKE_ARGS += RM="$(RM)"
|
||||
MAKE_ARGS += ZIPEXE=$(ZIPEXE)
|
||||
|
||||
|
@ -2322,7 +2322,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
// Pre-load a static method's oop into O1. Used both by locking code and
|
||||
// the normal JNI call code.
|
||||
if (method->is_static() && !is_critical_native) {
|
||||
__ set_oop_constant(JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror()), O1);
|
||||
__ set_oop_constant(JNIHandles::make_local(method->method_holder()->java_mirror()), O1);
|
||||
|
||||
// Now handlize the static class mirror in O1. It's known not-null.
|
||||
__ st_ptr(O1, SP, klass_offset + STACK_BIAS);
|
||||
|
@ -1936,7 +1936,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
if (method->is_static() && !is_critical_native) {
|
||||
|
||||
// load opp into a register
|
||||
__ movoop(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror()));
|
||||
__ movoop(oop_handle_reg, JNIHandles::make_local(method->method_holder()->java_mirror()));
|
||||
|
||||
// Now handlize the static class mirror it's known not-null.
|
||||
__ movptr(Address(rsp, klass_offset), oop_handle_reg);
|
||||
|
@ -2179,7 +2179,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
if (method->is_static() && !is_critical_native) {
|
||||
|
||||
// load oop into a register
|
||||
__ movoop(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror()));
|
||||
__ movoop(oop_handle_reg, JNIHandles::make_local(method->method_holder()->java_mirror()));
|
||||
|
||||
// Now handlize the static class mirror it's known not-null.
|
||||
__ movptr(Address(rsp, klass_offset), oop_handle_reg);
|
||||
|
@ -488,8 +488,8 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
|
||||
// The AES intrinsic stubs require AES instruction support (of course)
|
||||
// but also require AVX mode for misaligned SSE access
|
||||
if (UseAES && (UseAVX > 0)) {
|
||||
// but also require AVX and sse3 modes for instructions it use.
|
||||
if (UseAES && (UseAVX > 0) && (UseSSE > 2)) {
|
||||
if (FLAG_IS_DEFAULT(UseAESIntrinsics)) {
|
||||
UseAESIntrinsics = true;
|
||||
}
|
||||
|
@ -31,12 +31,17 @@
|
||||
return _masm;
|
||||
}
|
||||
|
||||
protected:
|
||||
address generate_entry(address entry_point) {
|
||||
ZeroEntry *entry = (ZeroEntry *) assembler()->pc();
|
||||
assembler()->advance(sizeof(ZeroEntry));
|
||||
public:
|
||||
static address generate_entry_impl(MacroAssembler* masm, address entry_point) {
|
||||
ZeroEntry *entry = (ZeroEntry *) masm->pc();
|
||||
masm->advance(sizeof(ZeroEntry));
|
||||
entry->set_entry_point(entry_point);
|
||||
return (address) entry;
|
||||
}
|
||||
|
||||
protected:
|
||||
address generate_entry(address entry_point) {
|
||||
return generate_entry_impl(assembler(), entry_point);
|
||||
}
|
||||
|
||||
#endif // CPU_ZERO_VM_CPPINTERPRETERGENERATOR_ZERO_HPP
|
||||
|
@ -180,25 +180,6 @@ void CppInterpreter::main_loop(int recurse, TRAPS) {
|
||||
method, istate->osr_entry(), istate->osr_buf(), THREAD);
|
||||
return;
|
||||
}
|
||||
else if (istate->msg() == BytecodeInterpreter::call_method_handle) {
|
||||
oop method_handle = istate->callee();
|
||||
|
||||
// Trim back the stack to put the parameters at the top
|
||||
stack->set_sp(istate->stack() + 1);
|
||||
|
||||
// Make the call
|
||||
process_method_handle(method_handle, THREAD);
|
||||
fixup_after_potential_safepoint();
|
||||
|
||||
// Convert the result
|
||||
istate->set_stack(stack->sp() - 1);
|
||||
|
||||
// Restore the stack
|
||||
stack->set_sp(istate->stack_limit() + 1);
|
||||
|
||||
// Resume the interpreter
|
||||
istate->set_msg(BytecodeInterpreter::method_resume);
|
||||
}
|
||||
else {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
@ -535,35 +516,35 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) {
|
||||
if (entry->is_volatile()) {
|
||||
switch (entry->flag_state()) {
|
||||
case ctos:
|
||||
SET_LOCALS_INT(object->char_field_acquire(entry->f2()), 0);
|
||||
SET_LOCALS_INT(object->char_field_acquire(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
case btos:
|
||||
SET_LOCALS_INT(object->byte_field_acquire(entry->f2()), 0);
|
||||
SET_LOCALS_INT(object->byte_field_acquire(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
case stos:
|
||||
SET_LOCALS_INT(object->short_field_acquire(entry->f2()), 0);
|
||||
SET_LOCALS_INT(object->short_field_acquire(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
case itos:
|
||||
SET_LOCALS_INT(object->int_field_acquire(entry->f2()), 0);
|
||||
SET_LOCALS_INT(object->int_field_acquire(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
case ltos:
|
||||
SET_LOCALS_LONG(object->long_field_acquire(entry->f2()), 0);
|
||||
SET_LOCALS_LONG(object->long_field_acquire(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
case ftos:
|
||||
SET_LOCALS_FLOAT(object->float_field_acquire(entry->f2()), 0);
|
||||
SET_LOCALS_FLOAT(object->float_field_acquire(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
case dtos:
|
||||
SET_LOCALS_DOUBLE(object->double_field_acquire(entry->f2()), 0);
|
||||
SET_LOCALS_DOUBLE(object->double_field_acquire(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
case atos:
|
||||
SET_LOCALS_OBJECT(object->obj_field_acquire(entry->f2()), 0);
|
||||
SET_LOCALS_OBJECT(object->obj_field_acquire(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -573,35 +554,35 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) {
|
||||
else {
|
||||
switch (entry->flag_state()) {
|
||||
case ctos:
|
||||
SET_LOCALS_INT(object->char_field(entry->f2()), 0);
|
||||
SET_LOCALS_INT(object->char_field(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
case btos:
|
||||
SET_LOCALS_INT(object->byte_field(entry->f2()), 0);
|
||||
SET_LOCALS_INT(object->byte_field(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
case stos:
|
||||
SET_LOCALS_INT(object->short_field(entry->f2()), 0);
|
||||
SET_LOCALS_INT(object->short_field(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
case itos:
|
||||
SET_LOCALS_INT(object->int_field(entry->f2()), 0);
|
||||
SET_LOCALS_INT(object->int_field(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
case ltos:
|
||||
SET_LOCALS_LONG(object->long_field(entry->f2()), 0);
|
||||
SET_LOCALS_LONG(object->long_field(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
case ftos:
|
||||
SET_LOCALS_FLOAT(object->float_field(entry->f2()), 0);
|
||||
SET_LOCALS_FLOAT(object->float_field(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
case dtos:
|
||||
SET_LOCALS_DOUBLE(object->double_field(entry->f2()), 0);
|
||||
SET_LOCALS_DOUBLE(object->double_field(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
case atos:
|
||||
SET_LOCALS_OBJECT(object->obj_field(entry->f2()), 0);
|
||||
SET_LOCALS_OBJECT(object->obj_field(entry->f2_as_index()), 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -629,516 +610,6 @@ int CppInterpreter::empty_entry(Method* method, intptr_t UNUSED, TRAPS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CppInterpreter::method_handle_entry(Method* method,
|
||||
intptr_t UNUSED, TRAPS) {
|
||||
JavaThread *thread = (JavaThread *) THREAD;
|
||||
ZeroStack *stack = thread->zero_stack();
|
||||
int argument_slots = method->size_of_parameters();
|
||||
int result_slots = type2size[result_type_of(method)];
|
||||
intptr_t *vmslots = stack->sp();
|
||||
intptr_t *unwind_sp = vmslots + argument_slots;
|
||||
|
||||
// Find the MethodType
|
||||
address p = (address) method;
|
||||
for (jint* pc = method->method_type_offsets_chain(); (*pc) != -1; pc++) {
|
||||
p = *(address*)(p + (*pc));
|
||||
}
|
||||
oop method_type = (oop) p;
|
||||
|
||||
// The MethodHandle is in the slot after the arguments
|
||||
int num_vmslots = argument_slots - 1;
|
||||
oop method_handle = VMSLOTS_OBJECT(num_vmslots);
|
||||
|
||||
// InvokeGeneric requires some extra shuffling
|
||||
oop mhtype = java_lang_invoke_MethodHandle::type(method_handle);
|
||||
bool is_exact = mhtype == method_type;
|
||||
if (!is_exact) {
|
||||
if (true || // FIXME
|
||||
method->intrinsic_id() == vmIntrinsics::_invokeExact) {
|
||||
CALL_VM_NOCHECK_NOFIX(
|
||||
SharedRuntime::throw_WrongMethodTypeException(
|
||||
thread, method_type, mhtype));
|
||||
// NB all oops trashed!
|
||||
assert(HAS_PENDING_EXCEPTION, "should do");
|
||||
stack->set_sp(unwind_sp);
|
||||
return 0;
|
||||
}
|
||||
assert(method->intrinsic_id() == vmIntrinsics::_invokeGeneric, "should be");
|
||||
|
||||
// Load up an adapter from the calling type
|
||||
// NB the x86 code for this (in methodHandles_x86.cpp, search for
|
||||
// "genericInvoker") is really really odd. I'm hoping it's trying
|
||||
// to accomodate odd VM/class library combinations I can ignore.
|
||||
oop adapter = NULL; //FIXME: load the adapter from the CP cache
|
||||
IF (adapter == NULL) {
|
||||
CALL_VM_NOCHECK_NOFIX(
|
||||
SharedRuntime::throw_WrongMethodTypeException(
|
||||
thread, method_type, mhtype));
|
||||
// NB all oops trashed!
|
||||
assert(HAS_PENDING_EXCEPTION, "should do");
|
||||
stack->set_sp(unwind_sp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Adapters are shared among form-families of method-type. The
|
||||
// type being called is passed as a trusted first argument so that
|
||||
// the adapter knows the actual types of its arguments and return
|
||||
// values.
|
||||
insert_vmslots(num_vmslots + 1, 1, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
// NB all oops trashed!
|
||||
stack->set_sp(unwind_sp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vmslots = stack->sp();
|
||||
num_vmslots++;
|
||||
SET_VMSLOTS_OBJECT(method_type, num_vmslots);
|
||||
|
||||
method_handle = adapter;
|
||||
}
|
||||
|
||||
// Start processing
|
||||
process_method_handle(method_handle, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION)
|
||||
result_slots = 0;
|
||||
|
||||
// If this is an invokeExact then the eventual callee will not
|
||||
// have unwound the method handle argument so we have to do it.
|
||||
// If a result is being returned the it will be above the method
|
||||
// handle argument we're unwinding.
|
||||
if (is_exact) {
|
||||
intptr_t result[2];
|
||||
for (int i = 0; i < result_slots; i++)
|
||||
result[i] = stack->pop();
|
||||
stack->pop();
|
||||
for (int i = result_slots - 1; i >= 0; i--)
|
||||
stack->push(result[i]);
|
||||
}
|
||||
|
||||
// Check
|
||||
assert(stack->sp() == unwind_sp - result_slots, "should be");
|
||||
|
||||
// No deoptimized frames on the stack
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CppInterpreter::process_method_handle(oop method_handle, TRAPS) {
|
||||
JavaThread *thread = (JavaThread *) THREAD;
|
||||
ZeroStack *stack = thread->zero_stack();
|
||||
intptr_t *vmslots = stack->sp();
|
||||
|
||||
bool direct_to_method = false;
|
||||
BasicType src_rtype = T_ILLEGAL;
|
||||
BasicType dst_rtype = T_ILLEGAL;
|
||||
|
||||
MethodHandleEntry *entry =
|
||||
java_lang_invoke_MethodHandle::vmentry(method_handle);
|
||||
MethodHandles::EntryKind entry_kind =
|
||||
(MethodHandles::EntryKind) (((intptr_t) entry) & 0xffffffff);
|
||||
|
||||
Method* method = NULL;
|
||||
switch (entry_kind) {
|
||||
case MethodHandles::_invokestatic_mh:
|
||||
direct_to_method = true;
|
||||
break;
|
||||
|
||||
case MethodHandles::_invokespecial_mh:
|
||||
case MethodHandles::_invokevirtual_mh:
|
||||
case MethodHandles::_invokeinterface_mh:
|
||||
{
|
||||
oop receiver =
|
||||
VMSLOTS_OBJECT(
|
||||
java_lang_invoke_MethodHandle::vmslots(method_handle) - 1);
|
||||
if (receiver == NULL) {
|
||||
stack->set_sp(calculate_unwind_sp(stack, method_handle));
|
||||
CALL_VM_NOCHECK_NOFIX(
|
||||
throw_exception(
|
||||
thread, vmSymbols::java_lang_NullPointerException()));
|
||||
// NB all oops trashed!
|
||||
assert(HAS_PENDING_EXCEPTION, "should do");
|
||||
return;
|
||||
}
|
||||
if (entry_kind != MethodHandles::_invokespecial_mh) {
|
||||
intptr_t index = java_lang_invoke_DirectMethodHandle::vmindex(method_handle);
|
||||
InstanceKlass* rcvrKlass =
|
||||
(InstanceKlass *) receiver->klass();
|
||||
if (entry_kind == MethodHandles::_invokevirtual_mh) {
|
||||
method = (Method*) rcvrKlass->start_of_vtable()[index];
|
||||
}
|
||||
else {
|
||||
oop iclass = java_lang_invoke_MethodHandle::next_target(method_handle);
|
||||
itableOffsetEntry* ki =
|
||||
(itableOffsetEntry *) rcvrKlass->start_of_itable();
|
||||
int i, length = rcvrKlass->itable_length();
|
||||
for (i = 0; i < length; i++, ki++ ) {
|
||||
if (ki->interface_klass() == iclass)
|
||||
break;
|
||||
}
|
||||
if (i == length) {
|
||||
stack->set_sp(calculate_unwind_sp(stack, method_handle));
|
||||
CALL_VM_NOCHECK_NOFIX(
|
||||
throw_exception(
|
||||
thread, vmSymbols::java_lang_IncompatibleClassChangeError()));
|
||||
// NB all oops trashed!
|
||||
assert(HAS_PENDING_EXCEPTION, "should do");
|
||||
return;
|
||||
}
|
||||
itableMethodEntry* im = ki->first_method_entry(receiver->klass());
|
||||
method = im[index].method();
|
||||
if (method == NULL) {
|
||||
stack->set_sp(calculate_unwind_sp(stack, method_handle));
|
||||
CALL_VM_NOCHECK_NOFIX(
|
||||
throw_exception(
|
||||
thread, vmSymbols::java_lang_AbstractMethodError()));
|
||||
// NB all oops trashed!
|
||||
assert(HAS_PENDING_EXCEPTION, "should do");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
direct_to_method = true;
|
||||
break;
|
||||
|
||||
case MethodHandles::_bound_ref_direct_mh:
|
||||
case MethodHandles::_bound_int_direct_mh:
|
||||
case MethodHandles::_bound_long_direct_mh:
|
||||
direct_to_method = true;
|
||||
// fall through
|
||||
case MethodHandles::_bound_ref_mh:
|
||||
case MethodHandles::_bound_int_mh:
|
||||
case MethodHandles::_bound_long_mh:
|
||||
{
|
||||
BasicType arg_type = T_ILLEGAL;
|
||||
int arg_mask = -1;
|
||||
int arg_slots = -1;
|
||||
MethodHandles::get_ek_bound_mh_info(
|
||||
entry_kind, arg_type, arg_mask, arg_slots);
|
||||
int arg_slot =
|
||||
java_lang_invoke_BoundMethodHandle::vmargslot(method_handle);
|
||||
|
||||
// Create the new slot(s)
|
||||
intptr_t *unwind_sp = calculate_unwind_sp(stack, method_handle);
|
||||
insert_vmslots(arg_slot, arg_slots, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
// all oops trashed
|
||||
stack->set_sp(unwind_sp);
|
||||
return;
|
||||
}
|
||||
vmslots = stack->sp();
|
||||
|
||||
// Store bound argument into new stack slot
|
||||
oop arg = java_lang_invoke_BoundMethodHandle::argument(method_handle);
|
||||
if (arg_type == T_OBJECT) {
|
||||
assert(arg_slots == 1, "should be");
|
||||
SET_VMSLOTS_OBJECT(arg, arg_slot);
|
||||
}
|
||||
else {
|
||||
jvalue arg_value;
|
||||
arg_type = java_lang_boxing_object::get_value(arg, &arg_value);
|
||||
switch (arg_type) {
|
||||
case T_BOOLEAN:
|
||||
SET_VMSLOTS_INT(arg_value.z, arg_slot);
|
||||
break;
|
||||
case T_CHAR:
|
||||
SET_VMSLOTS_INT(arg_value.c, arg_slot);
|
||||
break;
|
||||
case T_BYTE:
|
||||
SET_VMSLOTS_INT(arg_value.b, arg_slot);
|
||||
break;
|
||||
case T_SHORT:
|
||||
SET_VMSLOTS_INT(arg_value.s, arg_slot);
|
||||
break;
|
||||
case T_INT:
|
||||
SET_VMSLOTS_INT(arg_value.i, arg_slot);
|
||||
break;
|
||||
case T_FLOAT:
|
||||
SET_VMSLOTS_FLOAT(arg_value.f, arg_slot);
|
||||
break;
|
||||
case T_LONG:
|
||||
SET_VMSLOTS_LONG(arg_value.j, arg_slot + 1);
|
||||
break;
|
||||
case T_DOUBLE:
|
||||
SET_VMSLOTS_DOUBLE(arg_value.d, arg_slot + 1);
|
||||
break;
|
||||
default:
|
||||
tty->print_cr("unhandled type %s", type2name(arg_type));
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MethodHandles::_adapter_retype_only:
|
||||
case MethodHandles::_adapter_retype_raw:
|
||||
src_rtype = result_type_of_handle(
|
||||
java_lang_invoke_MethodHandle::next_target(method_handle));
|
||||
dst_rtype = result_type_of_handle(method_handle);
|
||||
break;
|
||||
|
||||
case MethodHandles::_adapter_check_cast:
|
||||
{
|
||||
int arg_slot =
|
||||
java_lang_invoke_AdapterMethodHandle::vmargslot(method_handle);
|
||||
oop arg = VMSLOTS_OBJECT(arg_slot);
|
||||
if (arg != NULL) {
|
||||
Klass* objKlassOop = arg->klass();
|
||||
Klass* klassOf = java_lang_Class::as_Klass(
|
||||
java_lang_invoke_AdapterMethodHandle::argument(method_handle));
|
||||
|
||||
if (objKlassOop != klassOf &&
|
||||
!objKlassOop->is_subtype_of(klassOf)) {
|
||||
ResourceMark rm(THREAD);
|
||||
const char* objName = Klass::cast(objKlassOop)->external_name();
|
||||
const char* klassName = Klass::cast(klassOf)->external_name();
|
||||
char* message = SharedRuntime::generate_class_cast_message(
|
||||
objName, klassName);
|
||||
|
||||
stack->set_sp(calculate_unwind_sp(stack, method_handle));
|
||||
CALL_VM_NOCHECK_NOFIX(
|
||||
throw_exception(
|
||||
thread, vmSymbols::java_lang_ClassCastException(), message));
|
||||
// NB all oops trashed!
|
||||
assert(HAS_PENDING_EXCEPTION, "should do");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MethodHandles::_adapter_dup_args:
|
||||
{
|
||||
int arg_slot =
|
||||
java_lang_invoke_AdapterMethodHandle::vmargslot(method_handle);
|
||||
int conv =
|
||||
java_lang_invoke_AdapterMethodHandle::conversion(method_handle);
|
||||
int num_slots = -MethodHandles::adapter_conversion_stack_move(conv);
|
||||
assert(num_slots > 0, "should be");
|
||||
|
||||
// Create the new slot(s)
|
||||
intptr_t *unwind_sp = calculate_unwind_sp(stack, method_handle);
|
||||
stack->overflow_check(num_slots, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
// all oops trashed
|
||||
stack->set_sp(unwind_sp);
|
||||
return;
|
||||
}
|
||||
|
||||
// Duplicate the arguments
|
||||
for (int i = num_slots - 1; i >= 0; i--)
|
||||
stack->push(*VMSLOTS_SLOT(arg_slot + i));
|
||||
|
||||
vmslots = stack->sp(); // unused, but let the compiler figure that out
|
||||
}
|
||||
break;
|
||||
|
||||
case MethodHandles::_adapter_drop_args:
|
||||
{
|
||||
int arg_slot =
|
||||
java_lang_invoke_AdapterMethodHandle::vmargslot(method_handle);
|
||||
int conv =
|
||||
java_lang_invoke_AdapterMethodHandle::conversion(method_handle);
|
||||
int num_slots = MethodHandles::adapter_conversion_stack_move(conv);
|
||||
assert(num_slots > 0, "should be");
|
||||
|
||||
remove_vmslots(arg_slot, num_slots, THREAD); // doesn't trap
|
||||
vmslots = stack->sp(); // unused, but let the compiler figure that out
|
||||
}
|
||||
break;
|
||||
|
||||
case MethodHandles::_adapter_opt_swap_1:
|
||||
case MethodHandles::_adapter_opt_swap_2:
|
||||
case MethodHandles::_adapter_opt_rot_1_up:
|
||||
case MethodHandles::_adapter_opt_rot_1_down:
|
||||
case MethodHandles::_adapter_opt_rot_2_up:
|
||||
case MethodHandles::_adapter_opt_rot_2_down:
|
||||
{
|
||||
int arg1 =
|
||||
java_lang_invoke_AdapterMethodHandle::vmargslot(method_handle);
|
||||
int conv =
|
||||
java_lang_invoke_AdapterMethodHandle::conversion(method_handle);
|
||||
int arg2 = MethodHandles::adapter_conversion_vminfo(conv);
|
||||
|
||||
int swap_bytes = 0, rotate = 0;
|
||||
MethodHandles::get_ek_adapter_opt_swap_rot_info(
|
||||
entry_kind, swap_bytes, rotate);
|
||||
int swap_slots = swap_bytes >> LogBytesPerWord;
|
||||
|
||||
intptr_t tmp;
|
||||
switch (rotate) {
|
||||
case 0: // swap
|
||||
for (int i = 0; i < swap_slots; i++) {
|
||||
tmp = *VMSLOTS_SLOT(arg1 + i);
|
||||
SET_VMSLOTS_SLOT(VMSLOTS_SLOT(arg2 + i), arg1 + i);
|
||||
SET_VMSLOTS_SLOT(&tmp, arg2 + i);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // up
|
||||
assert(arg1 - swap_slots > arg2, "should be");
|
||||
|
||||
tmp = *VMSLOTS_SLOT(arg1);
|
||||
for (int i = arg1 - swap_slots; i >= arg2; i--)
|
||||
SET_VMSLOTS_SLOT(VMSLOTS_SLOT(i), i + swap_slots);
|
||||
SET_VMSLOTS_SLOT(&tmp, arg2);
|
||||
|
||||
break;
|
||||
|
||||
case -1: // down
|
||||
assert(arg2 - swap_slots > arg1, "should be");
|
||||
|
||||
tmp = *VMSLOTS_SLOT(arg1);
|
||||
for (int i = arg1 + swap_slots; i <= arg2; i++)
|
||||
SET_VMSLOTS_SLOT(VMSLOTS_SLOT(i), i - swap_slots);
|
||||
SET_VMSLOTS_SLOT(&tmp, arg2);
|
||||
break;
|
||||
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MethodHandles::_adapter_opt_i2l:
|
||||
{
|
||||
int arg_slot =
|
||||
java_lang_invoke_AdapterMethodHandle::vmargslot(method_handle);
|
||||
int arg = VMSLOTS_INT(arg_slot);
|
||||
intptr_t *unwind_sp = calculate_unwind_sp(stack, method_handle);
|
||||
insert_vmslots(arg_slot, 1, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
// all oops trashed
|
||||
stack->set_sp(unwind_sp);
|
||||
return;
|
||||
}
|
||||
vmslots = stack->sp();
|
||||
arg_slot++;
|
||||
SET_VMSLOTS_LONG(arg, arg_slot);
|
||||
}
|
||||
break;
|
||||
|
||||
case MethodHandles::_adapter_opt_unboxi:
|
||||
case MethodHandles::_adapter_opt_unboxl:
|
||||
{
|
||||
int arg_slot =
|
||||
java_lang_invoke_AdapterMethodHandle::vmargslot(method_handle);
|
||||
oop arg = VMSLOTS_OBJECT(arg_slot);
|
||||
jvalue arg_value;
|
||||
if (arg == NULL) {
|
||||
// queue a nullpointer exception for the caller
|
||||
stack->set_sp(calculate_unwind_sp(stack, method_handle));
|
||||
CALL_VM_NOCHECK_NOFIX(
|
||||
throw_exception(
|
||||
thread, vmSymbols::java_lang_NullPointerException()));
|
||||
// NB all oops trashed!
|
||||
assert(HAS_PENDING_EXCEPTION, "should do");
|
||||
return;
|
||||
}
|
||||
BasicType arg_type = java_lang_boxing_object::get_value(arg, &arg_value);
|
||||
if (arg_type == T_LONG || arg_type == T_DOUBLE) {
|
||||
intptr_t *unwind_sp = calculate_unwind_sp(stack, method_handle);
|
||||
insert_vmslots(arg_slot, 1, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
// all oops trashed
|
||||
stack->set_sp(unwind_sp);
|
||||
return;
|
||||
}
|
||||
vmslots = stack->sp();
|
||||
arg_slot++;
|
||||
}
|
||||
switch (arg_type) {
|
||||
case T_BOOLEAN:
|
||||
SET_VMSLOTS_INT(arg_value.z, arg_slot);
|
||||
break;
|
||||
case T_CHAR:
|
||||
SET_VMSLOTS_INT(arg_value.c, arg_slot);
|
||||
break;
|
||||
case T_BYTE:
|
||||
SET_VMSLOTS_INT(arg_value.b, arg_slot);
|
||||
break;
|
||||
case T_SHORT:
|
||||
SET_VMSLOTS_INT(arg_value.s, arg_slot);
|
||||
break;
|
||||
case T_INT:
|
||||
SET_VMSLOTS_INT(arg_value.i, arg_slot);
|
||||
break;
|
||||
case T_FLOAT:
|
||||
SET_VMSLOTS_FLOAT(arg_value.f, arg_slot);
|
||||
break;
|
||||
case T_LONG:
|
||||
SET_VMSLOTS_LONG(arg_value.j, arg_slot);
|
||||
break;
|
||||
case T_DOUBLE:
|
||||
SET_VMSLOTS_DOUBLE(arg_value.d, arg_slot);
|
||||
break;
|
||||
default:
|
||||
tty->print_cr("unhandled type %s", type2name(arg_type));
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
tty->print_cr("unhandled entry_kind %s",
|
||||
MethodHandles::entry_name(entry_kind));
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
// Continue along the chain
|
||||
if (direct_to_method) {
|
||||
if (method == NULL) {
|
||||
method =
|
||||
(Method*) java_lang_invoke_MethodHandle::vmtarget(method_handle);
|
||||
}
|
||||
address entry_point = method->from_interpreted_entry();
|
||||
Interpreter::invoke_method(method, entry_point, THREAD);
|
||||
}
|
||||
else {
|
||||
process_method_handle(
|
||||
java_lang_invoke_MethodHandle::next_target(method_handle), THREAD);
|
||||
}
|
||||
// NB all oops now trashed
|
||||
|
||||
// Adapt the result type, if necessary
|
||||
if (src_rtype != dst_rtype && !HAS_PENDING_EXCEPTION) {
|
||||
switch (dst_rtype) {
|
||||
case T_VOID:
|
||||
for (int i = 0; i < type2size[src_rtype]; i++)
|
||||
stack->pop();
|
||||
return;
|
||||
|
||||
case T_INT:
|
||||
switch (src_rtype) {
|
||||
case T_VOID:
|
||||
stack->overflow_check(1, CHECK);
|
||||
stack->push(0);
|
||||
return;
|
||||
|
||||
case T_BOOLEAN:
|
||||
case T_CHAR:
|
||||
case T_BYTE:
|
||||
case T_SHORT:
|
||||
return;
|
||||
}
|
||||
// INT results sometimes need narrowing
|
||||
case T_BOOLEAN:
|
||||
case T_CHAR:
|
||||
case T_BYTE:
|
||||
case T_SHORT:
|
||||
switch (src_rtype) {
|
||||
case T_INT:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
tty->print_cr("unhandled conversion:");
|
||||
tty->print_cr("src_rtype = %s", type2name(src_rtype));
|
||||
tty->print_cr("dst_rtype = %s", type2name(dst_rtype));
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
// The new slots will be inserted before slot insert_before.
|
||||
// Slots < insert_before will have the same slot number after the insert.
|
||||
// Slots >= insert_before will become old_slot + num_slots.
|
||||
@ -1380,10 +851,6 @@ address AbstractInterpreterGenerator::generate_method_entry(
|
||||
entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry();
|
||||
break;
|
||||
|
||||
case Interpreter::method_handle:
|
||||
entry_point = ((InterpreterGenerator*) this)->generate_method_handle_entry();
|
||||
break;
|
||||
|
||||
case Interpreter::java_lang_math_sin:
|
||||
case Interpreter::java_lang_math_cos:
|
||||
case Interpreter::java_lang_math_tan:
|
||||
@ -1391,6 +858,8 @@ address AbstractInterpreterGenerator::generate_method_entry(
|
||||
case Interpreter::java_lang_math_log:
|
||||
case Interpreter::java_lang_math_log10:
|
||||
case Interpreter::java_lang_math_sqrt:
|
||||
case Interpreter::java_lang_math_pow:
|
||||
case Interpreter::java_lang_math_exp:
|
||||
entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind);
|
||||
break;
|
||||
|
||||
|
@ -36,7 +36,6 @@
|
||||
static int native_entry(Method* method, intptr_t UNUSED, TRAPS);
|
||||
static int accessor_entry(Method* method, intptr_t UNUSED, TRAPS);
|
||||
static int empty_entry(Method* method, intptr_t UNUSED, TRAPS);
|
||||
static int method_handle_entry(Method* method, intptr_t UNUSED, TRAPS);
|
||||
|
||||
public:
|
||||
// Main loop of normal_entry
|
||||
@ -44,7 +43,6 @@
|
||||
|
||||
private:
|
||||
// Helpers for method_handle_entry
|
||||
static void process_method_handle(oop method_handle, TRAPS);
|
||||
static void insert_vmslots(int insert_before, int num_slots, TRAPS);
|
||||
static void remove_vmslots(int first_slot, int num_slots, TRAPS);
|
||||
static BasicType result_type_of_handle(oop method_handle);
|
||||
|
@ -351,7 +351,7 @@ void SharkFrame::identify_word(int frame_index,
|
||||
switch (offset) {
|
||||
case pc_off:
|
||||
strncpy(fieldbuf, "pc", buflen);
|
||||
if (method()->is_oop()) {
|
||||
if (method()->is_method()) {
|
||||
nmethod *code = method()->code();
|
||||
if (code && code->pc_desc_at(pc())) {
|
||||
SimpleScopeDesc ssd(code, pc());
|
||||
@ -367,7 +367,7 @@ void SharkFrame::identify_word(int frame_index,
|
||||
|
||||
case method_off:
|
||||
strncpy(fieldbuf, "method", buflen);
|
||||
if (method()->is_oop()) {
|
||||
if (method()->is_method()) {
|
||||
method()->name_and_sig_as_C_string(valuebuf, buflen);
|
||||
}
|
||||
return;
|
||||
@ -378,7 +378,7 @@ void SharkFrame::identify_word(int frame_index,
|
||||
}
|
||||
|
||||
// Variable part
|
||||
if (method()->is_oop()) {
|
||||
if (method()->is_method()) {
|
||||
identify_vp_word(frame_index, addr_of_word(offset),
|
||||
addr_of_word(header_words + 1),
|
||||
unextended_sp() + method()->max_stack(),
|
||||
@ -430,4 +430,3 @@ intptr_t *frame::initial_deoptimization_info() {
|
||||
// unused... but returns fp() to minimize changes introduced by 7087445
|
||||
return fp();
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,8 @@ inline frame::frame() {
|
||||
_deopt_state = unknown;
|
||||
}
|
||||
|
||||
inline address frame::sender_pc() const { ShouldNotCallThis(); }
|
||||
|
||||
inline frame::frame(ZeroFrame* zf, intptr_t* sp) {
|
||||
_zeroframe = zf;
|
||||
_sp = sp;
|
||||
|
@ -40,7 +40,7 @@ int InlineCacheBuffer::ic_stub_code_size() {
|
||||
}
|
||||
|
||||
void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin,
|
||||
Metadata* cached_oop,
|
||||
void* cached_oop,
|
||||
address entry_point) {
|
||||
// NB ic_stub_code_size() must return the size of the code we generate
|
||||
ShouldNotCallThis();
|
||||
@ -51,7 +51,6 @@ address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
||||
Metadata* InlineCacheBuffer::ic_buffer_cached_oop(address code_begin) {
|
||||
// NB ic_stub_code_size() must return the size of the code we generate
|
||||
void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
@ -24,26 +24,159 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "interpreter/interpreterGenerator.hpp"
|
||||
#include "interpreter/interpreter.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "prims/methodHandles.hpp"
|
||||
|
||||
int MethodHandles::adapter_conversion_ops_supported_mask() {
|
||||
return ((1<<java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY)
|
||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW)
|
||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST)
|
||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM)
|
||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM)
|
||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS)
|
||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS)
|
||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS)
|
||||
|(1<<java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS)
|
||||
//|(1<<java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS) //BUG!
|
||||
);
|
||||
// FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS.
|
||||
void MethodHandles::invoke_target(Method* method, TRAPS) {
|
||||
|
||||
JavaThread *thread = (JavaThread *) THREAD;
|
||||
ZeroStack *stack = thread->zero_stack();
|
||||
InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame();
|
||||
interpreterState istate = frame->interpreter_state();
|
||||
|
||||
// Trim back the stack to put the parameters at the top
|
||||
stack->set_sp(istate->stack() + 1);
|
||||
|
||||
Interpreter::invoke_method(method, method->from_interpreted_entry(), THREAD);
|
||||
|
||||
// Convert the result
|
||||
istate->set_stack(stack->sp() - 1);
|
||||
|
||||
}
|
||||
|
||||
void MethodHandles::generate_method_handle_stub(MacroAssembler* masm,
|
||||
MethodHandles::EntryKind ek) {
|
||||
init_entry(ek, (MethodHandleEntry *) ek);
|
||||
oop MethodHandles::popFromStack(TRAPS) {
|
||||
|
||||
JavaThread *thread = (JavaThread *) THREAD;
|
||||
InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame();
|
||||
interpreterState istate = frame->interpreter_state();
|
||||
intptr_t* topOfStack = istate->stack();
|
||||
|
||||
oop top = STACK_OBJECT(-1);
|
||||
MORE_STACK(-1);
|
||||
istate->set_stack(topOfStack);
|
||||
|
||||
return top;
|
||||
|
||||
}
|
||||
|
||||
int MethodHandles::method_handle_entry_invokeBasic(Method* method, intptr_t UNUSED, TRAPS) {
|
||||
|
||||
JavaThread *thread = (JavaThread *) THREAD;
|
||||
InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame();
|
||||
interpreterState istate = frame->interpreter_state();
|
||||
intptr_t* topOfStack = istate->stack();
|
||||
|
||||
// 'this' is a MethodHandle. We resolve the target method by accessing this.form.vmentry.vmtarget.
|
||||
int numArgs = method->size_of_parameters();
|
||||
oop lform1 = java_lang_invoke_MethodHandle::form(STACK_OBJECT(-numArgs)); // this.form
|
||||
oop vmEntry1 = java_lang_invoke_LambdaForm::vmentry(lform1);
|
||||
Method* vmtarget = (Method*) java_lang_invoke_MemberName::vmtarget(vmEntry1);
|
||||
|
||||
invoke_target(vmtarget, THREAD);
|
||||
|
||||
// No deoptimized frames on the stack
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MethodHandles::method_handle_entry_linkToStaticOrSpecial(Method* method, intptr_t UNUSED, TRAPS) {
|
||||
|
||||
// Pop appendix argument from stack. This is a MemberName which we resolve to the
|
||||
// target method.
|
||||
oop vmentry = popFromStack(THREAD);
|
||||
|
||||
Method* vmtarget = (Method*) java_lang_invoke_MemberName::vmtarget(vmentry);
|
||||
|
||||
invoke_target(vmtarget, THREAD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MethodHandles::method_handle_entry_linkToInterface(Method* method, intptr_t UNUSED, TRAPS) {
|
||||
JavaThread *thread = (JavaThread *) THREAD;
|
||||
InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame();
|
||||
interpreterState istate = frame->interpreter_state();
|
||||
|
||||
// Pop appendix argument from stack. This is a MemberName which we resolve to the
|
||||
// target method.
|
||||
oop vmentry = popFromStack(THREAD);
|
||||
intptr_t* topOfStack = istate->stack();
|
||||
|
||||
// Resolve target method by looking up in the receiver object's itable.
|
||||
Klass* clazz = java_lang_Class::as_Klass(java_lang_invoke_MemberName::clazz(vmentry));
|
||||
intptr_t vmindex = java_lang_invoke_MemberName::vmindex(vmentry);
|
||||
Method* target = (Method*) java_lang_invoke_MemberName::vmtarget(vmentry);
|
||||
|
||||
int numArgs = target->size_of_parameters();
|
||||
oop recv = STACK_OBJECT(-numArgs);
|
||||
|
||||
InstanceKlass* klass_part = InstanceKlass::cast(recv->klass());
|
||||
itableOffsetEntry* ki = (itableOffsetEntry*) klass_part->start_of_itable();
|
||||
int i;
|
||||
for ( i = 0 ; i < klass_part->itable_length() ; i++, ki++ ) {
|
||||
if (ki->interface_klass() == clazz) break;
|
||||
}
|
||||
|
||||
itableMethodEntry* im = ki->first_method_entry(recv->klass());
|
||||
Method* vmtarget = im[vmindex].method();
|
||||
|
||||
invoke_target(vmtarget, THREAD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MethodHandles::method_handle_entry_linkToVirtual(Method* method, intptr_t UNUSED, TRAPS) {
|
||||
JavaThread *thread = (JavaThread *) THREAD;
|
||||
|
||||
InterpreterFrame *frame = thread->top_zero_frame()->as_interpreter_frame();
|
||||
interpreterState istate = frame->interpreter_state();
|
||||
|
||||
// Pop appendix argument from stack. This is a MemberName which we resolve to the
|
||||
// target method.
|
||||
oop vmentry = popFromStack(THREAD);
|
||||
intptr_t* topOfStack = istate->stack();
|
||||
|
||||
// Resolve target method by looking up in the receiver object's vtable.
|
||||
intptr_t vmindex = java_lang_invoke_MemberName::vmindex(vmentry);
|
||||
Method* target = (Method*) java_lang_invoke_MemberName::vmtarget(vmentry);
|
||||
int numArgs = target->size_of_parameters();
|
||||
oop recv = STACK_OBJECT(-numArgs);
|
||||
Klass* clazz = recv->klass();
|
||||
Klass* klass_part = InstanceKlass::cast(clazz);
|
||||
klassVtable* vtable = klass_part->vtable();
|
||||
Method* vmtarget = vtable->method_at(vmindex);
|
||||
|
||||
invoke_target(vmtarget, THREAD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MethodHandles::method_handle_entry_invalid(Method* method, intptr_t UNUSED, TRAPS) {
|
||||
ShouldNotReachHere();
|
||||
return 0;
|
||||
}
|
||||
|
||||
address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* masm,
|
||||
vmIntrinsics::ID iid) {
|
||||
switch (iid) {
|
||||
case vmIntrinsics::_invokeGeneric:
|
||||
case vmIntrinsics::_compiledLambdaForm:
|
||||
// Perhaps surprisingly, the symbolic references visible to Java are not directly used.
|
||||
// They are linked to Java-generated adapters via MethodHandleNatives.linkMethod.
|
||||
// They all allow an appendix argument.
|
||||
return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_invalid);
|
||||
case vmIntrinsics::_invokeBasic:
|
||||
return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_invokeBasic);
|
||||
case vmIntrinsics::_linkToStatic:
|
||||
case vmIntrinsics::_linkToSpecial:
|
||||
return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_linkToStaticOrSpecial);
|
||||
case vmIntrinsics::_linkToInterface:
|
||||
return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_linkToInterface);
|
||||
case vmIntrinsics::_linkToVirtual:
|
||||
return InterpreterGenerator::generate_entry_impl(masm, (address) MethodHandles::method_handle_entry_linkToVirtual);
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,14 @@
|
||||
|
||||
// Adapters
|
||||
enum /* platform_dependent_constants */ {
|
||||
adapter_code_size = 0
|
||||
adapter_code_size = sizeof(ZeroEntry) * (Interpreter::method_handle_invoke_LAST - Interpreter::method_handle_invoke_FIRST + 1)
|
||||
};
|
||||
|
||||
private:
|
||||
static oop popFromStack(TRAPS);
|
||||
static void invoke_target(Method* method, TRAPS);
|
||||
static int method_handle_entry_invokeBasic(Method* method, intptr_t UNUSED, TRAPS);
|
||||
static int method_handle_entry_linkToStaticOrSpecial(Method* method, intptr_t UNUSED, TRAPS);
|
||||
static int method_handle_entry_linkToVirtual(Method* method, intptr_t UNUSED, TRAPS);
|
||||
static int method_handle_entry_linkToInterface(Method* method, intptr_t UNUSED, TRAPS);
|
||||
static int method_handle_entry_invalid(Method* method, intptr_t UNUSED, TRAPS);
|
||||
|
@ -114,5 +114,8 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl {
|
||||
};
|
||||
|
||||
CONSTANT_REGISTER_DECLARATION(Register, noreg, (-1));
|
||||
#ifndef DONT_USE_REGISTER_DEFINES
|
||||
#define noreg ((Register)(noreg_RegisterEnumValue))
|
||||
#endif
|
||||
|
||||
#endif // CPU_ZERO_VM_REGISTER_ZERO_HPP
|
||||
|
@ -77,3 +77,7 @@ void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src,
|
||||
CodeBuffer* dst) {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
||||
void metadata_Relocation::pd_fix_value(address x) {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/vframeArray.hpp"
|
||||
#include "vmreg_zero.inline.hpp"
|
||||
|
||||
#ifdef COMPILER1
|
||||
#include "c1/c1_Runtime1.hpp"
|
||||
#endif
|
||||
@ -47,6 +48,12 @@
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static address zero_null_code_stub() {
|
||||
address start = ShouldNotCallThisStub();
|
||||
return start;
|
||||
}
|
||||
|
||||
int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
|
||||
VMRegPair *regs,
|
||||
int total_args_passed,
|
||||
@ -63,16 +70,14 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(
|
||||
AdapterFingerPrint *fingerprint) {
|
||||
return AdapterHandlerLibrary::new_entry(
|
||||
fingerprint,
|
||||
ShouldNotCallThisStub(),
|
||||
ShouldNotCallThisStub(),
|
||||
ShouldNotCallThisStub());
|
||||
CAST_FROM_FN_PTR(address,zero_null_code_stub),
|
||||
CAST_FROM_FN_PTR(address,zero_null_code_stub),
|
||||
CAST_FROM_FN_PTR(address,zero_null_code_stub));
|
||||
}
|
||||
|
||||
nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
|
||||
methodHandle method,
|
||||
int compile_id,
|
||||
int total_args_passed,
|
||||
int max_arg,
|
||||
BasicType *sig_bt,
|
||||
VMRegPair *regs,
|
||||
BasicType ret_type) {
|
||||
@ -96,19 +101,20 @@ uint SharedRuntime::out_preserve_stack_slots() {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
||||
JRT_LEAF(void, zero_stub())
|
||||
ShouldNotCallThis();
|
||||
JRT_END
|
||||
|
||||
static RuntimeStub* generate_empty_runtime_stub(const char* name) {
|
||||
CodeBuffer buffer(name, 0, 0);
|
||||
return RuntimeStub::new_runtime_stub(name, &buffer, 0, 0, NULL, false);
|
||||
return CAST_FROM_FN_PTR(RuntimeStub*,zero_stub);
|
||||
}
|
||||
|
||||
static SafepointBlob* generate_empty_safepoint_blob() {
|
||||
CodeBuffer buffer("handler_blob", 0, 0);
|
||||
return SafepointBlob::create(&buffer, NULL, 0);
|
||||
return CAST_FROM_FN_PTR(SafepointBlob*,zero_stub);
|
||||
}
|
||||
|
||||
static DeoptimizationBlob* generate_empty_deopt_blob() {
|
||||
CodeBuffer buffer("handler_blob", 0, 0);
|
||||
return DeoptimizationBlob::create(&buffer, NULL, 0, 0, 0, 0);
|
||||
return CAST_FROM_FN_PTR(DeoptimizationBlob*,zero_stub);
|
||||
}
|
||||
|
||||
|
||||
@ -116,7 +122,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
_deopt_blob = generate_empty_deopt_blob();
|
||||
}
|
||||
|
||||
SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, bool cause_return) {
|
||||
SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_type) {
|
||||
return generate_empty_safepoint_blob();
|
||||
}
|
||||
|
||||
@ -124,6 +130,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha
|
||||
return generate_empty_runtime_stub("resolve_blob");
|
||||
}
|
||||
|
||||
|
||||
int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
|
||||
VMRegPair *regs,
|
||||
int total_args_passed) {
|
||||
|
@ -342,7 +342,6 @@ BsdAttachOperation* BsdAttachListener::dequeue() {
|
||||
|
||||
// get the credentials of the peer and check the effective uid/guid
|
||||
// - check with jeff on this.
|
||||
#ifdef _ALLBSD_SOURCE
|
||||
uid_t puid;
|
||||
gid_t pgid;
|
||||
if (::getpeereid(s, &puid, &pgid) != 0) {
|
||||
@ -350,17 +349,6 @@ BsdAttachOperation* BsdAttachListener::dequeue() {
|
||||
RESTARTABLE(::close(s), res);
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
struct ucred cred_info;
|
||||
socklen_t optlen = sizeof(cred_info);
|
||||
if (::getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void*)&cred_info, &optlen) == -1) {
|
||||
int res;
|
||||
RESTARTABLE(::close(s), res);
|
||||
continue;
|
||||
}
|
||||
uid_t puid = cred_info.uid;
|
||||
gid_t pgid = cred_info.gid;
|
||||
#endif
|
||||
uid_t euid = geteuid();
|
||||
gid_t egid = getegid();
|
||||
|
||||
|
@ -39,18 +39,12 @@
|
||||
|
||||
private:
|
||||
|
||||
#ifdef _ALLBSD_SOURCE
|
||||
|
||||
#ifdef __APPLE__
|
||||
typedef thread_t thread_id_t;
|
||||
#else
|
||||
typedef pthread_t thread_id_t;
|
||||
#endif
|
||||
|
||||
#else
|
||||
typedef pid_t thread_id_t;
|
||||
#endif
|
||||
|
||||
// _pthread_id is the pthread id, which is used by library calls
|
||||
// (e.g. pthread_kill).
|
||||
pthread_t _pthread_id;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -56,19 +56,6 @@ class Bsd {
|
||||
static int sigflags[MAXSIGNUM];
|
||||
|
||||
static int (*_clock_gettime)(clockid_t, struct timespec *);
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
static int (*_pthread_getcpuclockid)(pthread_t, clockid_t *);
|
||||
|
||||
static address _initial_thread_stack_bottom;
|
||||
static uintptr_t _initial_thread_stack_size;
|
||||
|
||||
static const char *_glibc_version;
|
||||
static const char *_libpthread_version;
|
||||
|
||||
static bool _is_floating_stack;
|
||||
static bool _is_NPTL;
|
||||
static bool _supports_fast_thread_cpu_time;
|
||||
#endif
|
||||
|
||||
static GrowableArray<int>* _cpu_to_node;
|
||||
|
||||
@ -76,28 +63,14 @@ class Bsd {
|
||||
|
||||
static julong _physical_memory;
|
||||
static pthread_t _main_thread;
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
static Mutex* _createThread_lock;
|
||||
#endif
|
||||
static int _page_size;
|
||||
|
||||
static julong available_memory();
|
||||
static julong physical_memory() { return _physical_memory; }
|
||||
static void initialize_system_info();
|
||||
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
static void set_glibc_version(const char *s) { _glibc_version = s; }
|
||||
static void set_libpthread_version(const char *s) { _libpthread_version = s; }
|
||||
#endif
|
||||
|
||||
static bool supports_variable_stack_size();
|
||||
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
static void set_is_NPTL() { _is_NPTL = true; }
|
||||
static void set_is_BsdThreads() { _is_NPTL = false; }
|
||||
static void set_is_floating_stack() { _is_floating_stack = true; }
|
||||
#endif
|
||||
|
||||
static void rebuild_cpu_to_node_map();
|
||||
static GrowableArray<int>* cpu_to_node() { return _cpu_to_node; }
|
||||
|
||||
@ -106,25 +79,10 @@ class Bsd {
|
||||
public:
|
||||
|
||||
static void init_thread_fpu_state();
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
static int get_fpu_control_word();
|
||||
static void set_fpu_control_word(int fpu_control);
|
||||
#endif
|
||||
static pthread_t main_thread(void) { return _main_thread; }
|
||||
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
// returns kernel thread id (similar to LWP id on Solaris), which can be
|
||||
// used to access /proc
|
||||
static pid_t gettid();
|
||||
static void set_createThread_lock(Mutex* lk) { _createThread_lock = lk; }
|
||||
static Mutex* createThread_lock(void) { return _createThread_lock; }
|
||||
#endif
|
||||
static void hotspot_sigmask(Thread* thread);
|
||||
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
static address initial_thread_stack_bottom(void) { return _initial_thread_stack_bottom; }
|
||||
static uintptr_t initial_thread_stack_size(void) { return _initial_thread_stack_size; }
|
||||
#endif
|
||||
static bool is_initial_thread(void);
|
||||
|
||||
static int page_size(void) { return _page_size; }
|
||||
@ -161,23 +119,6 @@ class Bsd {
|
||||
static struct sigaction *get_chained_signal_action(int sig);
|
||||
static bool chained_handler(int sig, siginfo_t* siginfo, void* context);
|
||||
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
// GNU libc and libpthread version strings
|
||||
static const char *glibc_version() { return _glibc_version; }
|
||||
static const char *libpthread_version() { return _libpthread_version; }
|
||||
|
||||
// NPTL or BsdThreads?
|
||||
static bool is_BsdThreads() { return !_is_NPTL; }
|
||||
static bool is_NPTL() { return _is_NPTL; }
|
||||
|
||||
// NPTL is always floating stack. BsdThreads could be using floating
|
||||
// stack or fixed stack.
|
||||
static bool is_floating_stack() { return _is_floating_stack; }
|
||||
|
||||
static void libpthread_init();
|
||||
static bool libnuma_init();
|
||||
static void* libnuma_dlsym(void* handle, const char* name);
|
||||
#endif
|
||||
// Minimum stack size a thread can be created with (allowing
|
||||
// the VM to completely create the thread and enter user code)
|
||||
static size_t min_stack_allowed;
|
||||
@ -186,22 +127,9 @@ class Bsd {
|
||||
static size_t default_stack_size(os::ThreadType thr_type);
|
||||
static size_t default_guard_size(os::ThreadType thr_type);
|
||||
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
static void capture_initial_stack(size_t max_size);
|
||||
|
||||
// Stack overflow handling
|
||||
static bool manually_expand_stack(JavaThread * t, address addr);
|
||||
static int max_register_window_saves_before_flushing();
|
||||
#endif
|
||||
|
||||
// Real-time clock functions
|
||||
static void clock_init(void);
|
||||
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
// fast POSIX clocks support
|
||||
static void fast_thread_clock_init(void);
|
||||
#endif
|
||||
|
||||
static inline bool supports_monotonic_clock() {
|
||||
return _clock_gettime != NULL;
|
||||
}
|
||||
@ -210,18 +138,6 @@ class Bsd {
|
||||
return _clock_gettime ? _clock_gettime(clock_id, tp) : -1;
|
||||
}
|
||||
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
static int pthread_getcpuclockid(pthread_t tid, clockid_t *clock_id) {
|
||||
return _pthread_getcpuclockid ? _pthread_getcpuclockid(tid, clock_id) : -1;
|
||||
}
|
||||
|
||||
static bool supports_fast_thread_cpu_time() {
|
||||
return _supports_fast_thread_cpu_time;
|
||||
}
|
||||
|
||||
static jlong fast_thread_cpu_time(clockid_t clockid);
|
||||
#endif
|
||||
|
||||
// Stack repair handling
|
||||
|
||||
// none present
|
||||
|
@ -22,7 +22,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
// Must be at least Windows 2000 or XP to use VectoredExceptions and IsDebuggerPresent
|
||||
// Must be at least Windows 2000 or XP to use IsDebuggerPresent
|
||||
#define _WIN32_WINNT 0x500
|
||||
|
||||
// no precompiled headers
|
||||
@ -110,10 +110,6 @@ static FILETIME process_exit_time;
|
||||
static FILETIME process_user_time;
|
||||
static FILETIME process_kernel_time;
|
||||
|
||||
#ifdef _WIN64
|
||||
PVOID topLevelVectoredExceptionHandler = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef _M_IA64
|
||||
#define __CPU__ ia64
|
||||
#elif _M_AMD64
|
||||
@ -136,12 +132,6 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) {
|
||||
case DLL_PROCESS_DETACH:
|
||||
if(ForceTimeHighResolution)
|
||||
timeEndPeriod(1L);
|
||||
#ifdef _WIN64
|
||||
if (topLevelVectoredExceptionHandler != NULL) {
|
||||
RemoveVectoredExceptionHandler(topLevelVectoredExceptionHandler);
|
||||
topLevelVectoredExceptionHandler = NULL;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -408,20 +398,14 @@ static unsigned __stdcall java_start(Thread* thread) {
|
||||
}
|
||||
|
||||
|
||||
if (UseVectoredExceptions) {
|
||||
// If we are using vectored exception we don't need to set a SEH
|
||||
thread->run();
|
||||
}
|
||||
else {
|
||||
// Install a win32 structured exception handler around every thread created
|
||||
// by VM, so VM can genrate error dump when an exception occurred in non-
|
||||
// Java thread (e.g. VM thread).
|
||||
__try {
|
||||
thread->run();
|
||||
} __except(topLevelExceptionFilter(
|
||||
(_EXCEPTION_POINTERS*)_exception_info())) {
|
||||
// Nothing to do.
|
||||
}
|
||||
// Install a win32 structured exception handler around every thread created
|
||||
// by VM, so VM can genrate error dump when an exception occurred in non-
|
||||
// Java thread (e.g. VM thread).
|
||||
__try {
|
||||
thread->run();
|
||||
} __except(topLevelExceptionFilter(
|
||||
(_EXCEPTION_POINTERS*)_exception_info())) {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
// One less thread is executing
|
||||
@ -2489,16 +2473,6 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN64
|
||||
// Windows will sometimes generate an access violation
|
||||
// when we call malloc. Since we use VectoredExceptions
|
||||
// on 64 bit platforms, we see this exception. We must
|
||||
// pass this exception on so Windows can recover.
|
||||
// We check to see if the pc of the fault is in NTDLL.DLL
|
||||
// if so, we pass control on to Windows for handling.
|
||||
if (UseVectoredExceptions && _addr_in_ntdll(pc)) return EXCEPTION_CONTINUE_SEARCH;
|
||||
#endif
|
||||
|
||||
// Stack overflow or null pointer exception in native code.
|
||||
report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord,
|
||||
exceptionInfo->ContextRecord);
|
||||
@ -2527,30 +2501,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
||||
}
|
||||
|
||||
if (exception_code != EXCEPTION_BREAKPOINT) {
|
||||
#ifndef _WIN64
|
||||
report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord,
|
||||
exceptionInfo->ContextRecord);
|
||||
#else
|
||||
// Itanium Windows uses a VectoredExceptionHandler
|
||||
// Which means that C++ programatic exception handlers (try/except)
|
||||
// will get here. Continue the search for the right except block if
|
||||
// the exception code is not a fatal code.
|
||||
switch ( exception_code ) {
|
||||
case EXCEPTION_ACCESS_VIOLATION:
|
||||
case EXCEPTION_STACK_OVERFLOW:
|
||||
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
||||
case EXCEPTION_ILLEGAL_INSTRUCTION_2:
|
||||
case EXCEPTION_INT_OVERFLOW:
|
||||
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||
case EXCEPTION_UNCAUGHT_CXX_EXCEPTION:
|
||||
{ report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord,
|
||||
exceptionInfo->ContextRecord);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
@ -3706,18 +3658,6 @@ jint os::init_2(void) {
|
||||
|
||||
// Setup Windows Exceptions
|
||||
|
||||
// On Itanium systems, Structured Exception Handling does not
|
||||
// work since stack frames must be walkable by the OS. Since
|
||||
// much of our code is dynamically generated, and we do not have
|
||||
// proper unwind .xdata sections, the system simply exits
|
||||
// rather than delivering the exception. To work around
|
||||
// this we use VectorExceptions instead.
|
||||
#ifdef _WIN64
|
||||
if (UseVectoredExceptions) {
|
||||
topLevelVectoredExceptionHandler = AddVectoredExceptionHandler( 1, topLevelExceptionFilter);
|
||||
}
|
||||
#endif
|
||||
|
||||
// for debugging float code generation bugs
|
||||
if (ForceFloatExceptions) {
|
||||
#ifndef _WIN64
|
||||
|
@ -25,10 +25,6 @@
|
||||
#ifndef OS_CPU_BSD_X86_VM_BYTES_BSD_X86_INLINE_HPP
|
||||
#define OS_CPU_BSD_X86_VM_BYTES_BSD_X86_INLINE_HPP
|
||||
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
#include <byteswap.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#endif
|
||||
|
@ -48,7 +48,5 @@ define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
|
||||
|
||||
// Used on 64 bit platforms for UseCompressedOops base address or CDS
|
||||
define_pd_global(uintx, HeapBaseMinAddress, 2*G);
|
||||
// Only used on 64 bit Windows platforms
|
||||
define_pd_global(bool, UseVectoredExceptions, false);
|
||||
|
||||
#endif // OS_CPU_BSD_X86_VM_GLOBALS_BSD_X86_HPP
|
||||
|
@ -76,7 +76,7 @@
|
||||
# include <ucontext.h>
|
||||
#endif
|
||||
|
||||
#if defined(_ALLBSD_SOURCE) && !defined(__APPLE__) && !defined(__NetBSD__)
|
||||
#if !defined(__APPLE__) && !defined(__NetBSD__)
|
||||
# include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
@ -489,23 +489,6 @@ JVM_handle_bsd_signal(int sig,
|
||||
// to handle_unexpected_exception way down below.
|
||||
thread->disable_stack_red_zone();
|
||||
tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
} else {
|
||||
// Accessing stack address below sp may cause SEGV if current
|
||||
// thread has MAP_GROWSDOWN stack. This should only happen when
|
||||
// current thread was created by user code with MAP_GROWSDOWN flag
|
||||
// and then attached to VM. See notes in os_bsd.cpp.
|
||||
if (thread->osthread()->expanding_stack() == 0) {
|
||||
thread->osthread()->set_expanding_stack();
|
||||
if (os::Bsd::manually_expand_stack(thread, addr)) {
|
||||
thread->osthread()->clear_expanding_stack();
|
||||
return 1;
|
||||
}
|
||||
thread->osthread()->clear_expanding_stack();
|
||||
} else {
|
||||
fatal("recursive segv. expanding stack.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -744,61 +727,21 @@ JVM_handle_bsd_signal(int sig,
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
#ifdef _ALLBSD_SOURCE
|
||||
// From solaris_i486.s ported to bsd_i486.s
|
||||
extern "C" void fixcw();
|
||||
#endif
|
||||
|
||||
void os::Bsd::init_thread_fpu_state(void) {
|
||||
#ifndef AMD64
|
||||
# ifdef _ALLBSD_SOURCE
|
||||
// Set fpu to 53 bit precision. This happens too early to use a stub.
|
||||
fixcw();
|
||||
# else
|
||||
// set fpu to 53 bit precision
|
||||
set_fpu_control_word(0x27f);
|
||||
# endif
|
||||
#endif // !AMD64
|
||||
}
|
||||
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
int os::Bsd::get_fpu_control_word(void) {
|
||||
#ifdef AMD64
|
||||
return 0;
|
||||
#else
|
||||
int fpu_control;
|
||||
_FPU_GETCW(fpu_control);
|
||||
return fpu_control & 0xffff;
|
||||
#endif // AMD64
|
||||
}
|
||||
|
||||
void os::Bsd::set_fpu_control_word(int fpu_control) {
|
||||
#ifndef AMD64
|
||||
_FPU_SETCW(fpu_control);
|
||||
#endif // !AMD64
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check that the bsd kernel version is 2.4 or higher since earlier
|
||||
// versions do not support SSE without patches.
|
||||
bool os::supports_sse() {
|
||||
#if defined(AMD64) || defined(_ALLBSD_SOURCE)
|
||||
return true;
|
||||
#else
|
||||
struct utsname uts;
|
||||
if( uname(&uts) != 0 ) return false; // uname fails?
|
||||
char *minor_string;
|
||||
int major = strtol(uts.release,&minor_string,10);
|
||||
int minor = strtol(minor_string+1,NULL,10);
|
||||
bool result = (major > 2 || (major==2 && minor >= 4));
|
||||
#ifndef PRODUCT
|
||||
if (PrintMiscellaneous && Verbose) {
|
||||
tty->print("OS version is %d.%d, which %s support SSE/SSE2\n",
|
||||
major,minor, result ? "DOES" : "does NOT");
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
#endif // AMD64
|
||||
}
|
||||
|
||||
bool os::is_allocatable(size_t bytes) {
|
||||
@ -836,46 +779,7 @@ size_t os::Bsd::min_stack_allowed = (48 DEBUG_ONLY(+4))*K;
|
||||
#define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;})
|
||||
#endif
|
||||
|
||||
#ifdef _ALLBSD_SOURCE
|
||||
bool os::Bsd::supports_variable_stack_size() { return true; }
|
||||
#else
|
||||
// Test if pthread library can support variable thread stack size. BsdThreads
|
||||
// in fixed stack mode allocates 2M fixed slot for each thread. BsdThreads
|
||||
// in floating stack mode and NPTL support variable stack size.
|
||||
bool os::Bsd::supports_variable_stack_size() {
|
||||
if (os::Bsd::is_NPTL()) {
|
||||
// NPTL, yes
|
||||
return true;
|
||||
|
||||
} else {
|
||||
// Note: We can't control default stack size when creating a thread.
|
||||
// If we use non-default stack size (pthread_attr_setstacksize), both
|
||||
// floating stack and non-floating stack BsdThreads will return the
|
||||
// same value. This makes it impossible to implement this function by
|
||||
// detecting thread stack size directly.
|
||||
//
|
||||
// An alternative approach is to check %gs. Fixed-stack BsdThreads
|
||||
// do not use %gs, so its value is 0. Floating-stack BsdThreads use
|
||||
// %gs (either as LDT selector or GDT selector, depending on kernel)
|
||||
// to access thread specific data.
|
||||
//
|
||||
// Note that %gs is a reserved glibc register since early 2001, so
|
||||
// applications are not allowed to change its value (Ulrich Drepper from
|
||||
// Redhat confirmed that all known offenders have been modified to use
|
||||
// either %fs or TSD). In the worst case scenario, when VM is embedded in
|
||||
// a native application that plays with %gs, we might see non-zero %gs
|
||||
// even BsdThreads is running in fixed stack mode. As the result, we'll
|
||||
// return true and skip _thread_safety_check(), so we may not be able to
|
||||
// detect stack-heap collisions. But otherwise it's harmless.
|
||||
//
|
||||
#ifdef __GNUC__
|
||||
return (GET_GS() != 0);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // AMD64
|
||||
|
||||
// return default stack size for thr_type
|
||||
@ -943,7 +847,7 @@ static void current_stack_region(address * bottom, size_t * size) {
|
||||
|
||||
*bottom = (address)((char *)ss.ss_sp - ss.ss_size);
|
||||
*size = ss.ss_size;
|
||||
#elif defined(_ALLBSD_SOURCE)
|
||||
#else
|
||||
pthread_attr_t attr;
|
||||
|
||||
int rslt = pthread_attr_init(&attr);
|
||||
@ -963,33 +867,6 @@ static void current_stack_region(address * bottom, size_t * size) {
|
||||
}
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
#else
|
||||
if (os::Bsd::is_initial_thread()) {
|
||||
// initial thread needs special handling because pthread_getattr_np()
|
||||
// may return bogus value.
|
||||
*bottom = os::Bsd::initial_thread_stack_bottom();
|
||||
*size = os::Bsd::initial_thread_stack_size();
|
||||
} else {
|
||||
pthread_attr_t attr;
|
||||
|
||||
int rslt = pthread_getattr_np(pthread_self(), &attr);
|
||||
|
||||
// JVM needs to know exact stack location, abort if it fails
|
||||
if (rslt != 0) {
|
||||
if (rslt == ENOMEM) {
|
||||
vm_exit_out_of_memory(0, "pthread_getattr_np");
|
||||
} else {
|
||||
fatal(err_msg("pthread_getattr_np failed with errno = %d", rslt));
|
||||
}
|
||||
}
|
||||
|
||||
if (pthread_attr_getstack(&attr, (void **)bottom, size) != 0) {
|
||||
fatal("Can not locate current stack attributes!");
|
||||
}
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
}
|
||||
#endif
|
||||
assert(os::current_stack_pointer() >= *bottom &&
|
||||
os::current_stack_pointer() < *bottom + *size, "just checking");
|
||||
|
@ -41,7 +41,6 @@ define_pd_global(intx, VMThreadStackSize, 512);
|
||||
define_pd_global(intx, CompilerThreadStackSize, 0);
|
||||
define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
|
||||
|
||||
define_pd_global(bool, UseVectoredExceptions, false);
|
||||
// Used on 64 bit platforms for UseCompressedOops base address or CDS
|
||||
define_pd_global(uintx, HeapBaseMinAddress, 2*G);
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(_ALLBSD_SOURCE) && !defined(__APPLE__) && !defined(__NetBSD__)
|
||||
#if !defined(__APPLE__) && !defined(__NetBSD__)
|
||||
#include <pthread.h>
|
||||
# include <pthread_np.h> /* For pthread_attr_get_np */
|
||||
#endif
|
||||
@ -178,26 +178,6 @@ JVM_handle_bsd_signal(int sig,
|
||||
thread->disable_stack_red_zone();
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
else {
|
||||
// Accessing stack address below sp may cause SEGV if
|
||||
// current thread has MAP_GROWSDOWN stack. This should
|
||||
// only happen when current thread was created by user
|
||||
// code with MAP_GROWSDOWN flag and then attached to VM.
|
||||
// See notes in os_bsd.cpp.
|
||||
if (thread->osthread()->expanding_stack() == 0) {
|
||||
thread->osthread()->set_expanding_stack();
|
||||
if (os::Bsd::manually_expand_stack(thread, addr)) {
|
||||
thread->osthread()->clear_expanding_stack();
|
||||
return true;
|
||||
}
|
||||
thread->osthread()->clear_expanding_stack();
|
||||
}
|
||||
else {
|
||||
fatal("recursive segv. expanding stack.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,16 +246,6 @@ void os::Bsd::init_thread_fpu_state(void) {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
int os::Bsd::get_fpu_control_word() {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
||||
void os::Bsd::set_fpu_control_word(int fpu) {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool os::is_allocatable(size_t bytes) {
|
||||
#ifdef _LP64
|
||||
return true;
|
||||
@ -339,7 +309,7 @@ static void current_stack_region(address *bottom, size_t *size) {
|
||||
stack_top = (address) ss.ss_sp;
|
||||
stack_bytes = ss.ss_size;
|
||||
stack_bottom = stack_top - stack_bytes;
|
||||
#elif defined(_ALLBSD_SOURCE)
|
||||
#else
|
||||
pthread_attr_t attr;
|
||||
|
||||
int rslt = pthread_attr_init(&attr);
|
||||
@ -362,67 +332,6 @@ static void current_stack_region(address *bottom, size_t *size) {
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
stack_top = stack_bottom + stack_bytes;
|
||||
#else /* Linux */
|
||||
pthread_attr_t attr;
|
||||
int res = pthread_getattr_np(pthread_self(), &attr);
|
||||
if (res != 0) {
|
||||
if (res == ENOMEM) {
|
||||
vm_exit_out_of_memory(0, "pthread_getattr_np");
|
||||
}
|
||||
else {
|
||||
fatal(err_msg("pthread_getattr_np failed with errno = " INT32_FORMAT,
|
||||
res));
|
||||
}
|
||||
}
|
||||
|
||||
res = pthread_attr_getstack(&attr, (void **) &stack_bottom, &stack_bytes);
|
||||
if (res != 0) {
|
||||
fatal(err_msg("pthread_attr_getstack failed with errno = " INT32_FORMAT,
|
||||
res));
|
||||
}
|
||||
stack_top = stack_bottom + stack_bytes;
|
||||
|
||||
// The block of memory returned by pthread_attr_getstack() includes
|
||||
// guard pages where present. We need to trim these off.
|
||||
size_t page_bytes = os::Bsd::page_size();
|
||||
assert(((intptr_t) stack_bottom & (page_bytes - 1)) == 0, "unaligned stack");
|
||||
|
||||
size_t guard_bytes;
|
||||
res = pthread_attr_getguardsize(&attr, &guard_bytes);
|
||||
if (res != 0) {
|
||||
fatal(err_msg(
|
||||
"pthread_attr_getguardsize failed with errno = " INT32_FORMAT, res));
|
||||
}
|
||||
int guard_pages = align_size_up(guard_bytes, page_bytes) / page_bytes;
|
||||
assert(guard_bytes == guard_pages * page_bytes, "unaligned guard");
|
||||
|
||||
#ifdef IA64
|
||||
// IA64 has two stacks sharing the same area of memory, a normal
|
||||
// stack growing downwards and a register stack growing upwards.
|
||||
// Guard pages, if present, are in the centre. This code splits
|
||||
// the stack in two even without guard pages, though in theory
|
||||
// there's nothing to stop us allocating more to the normal stack
|
||||
// or more to the register stack if one or the other were found
|
||||
// to grow faster.
|
||||
int total_pages = align_size_down(stack_bytes, page_bytes) / page_bytes;
|
||||
stack_bottom += (total_pages - guard_pages) / 2 * page_bytes;
|
||||
#endif // IA64
|
||||
|
||||
stack_bottom += guard_bytes;
|
||||
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
// The initial thread has a growable stack, and the size reported
|
||||
// by pthread_attr_getstack is the maximum size it could possibly
|
||||
// be given what currently mapped. This can be huge, so we cap it.
|
||||
if (os::Bsd::is_initial_thread()) {
|
||||
stack_bytes = stack_top - stack_bottom;
|
||||
|
||||
if (stack_bytes > JavaThread::stack_size_at_create())
|
||||
stack_bytes = JavaThread::stack_size_at_create();
|
||||
|
||||
stack_bottom = stack_top - stack_bytes;
|
||||
}
|
||||
#endif
|
||||
|
||||
assert(os::current_stack_pointer() >= stack_bottom, "should do");
|
||||
|
@ -35,7 +35,5 @@ define_pd_global(intx, CompilerThreadStackSize, 0);
|
||||
|
||||
// Used on 64 bit platforms for UseCompressedOops base address or CDS
|
||||
define_pd_global(uintx, HeapBaseMinAddress, CONST64(4)*G);
|
||||
// Only used on 64 bit Windows platforms
|
||||
define_pd_global(bool, UseVectoredExceptions, false);
|
||||
|
||||
#endif // OS_CPU_LINUX_SPARC_VM_GLOBALS_LINUX_SPARC_HPP
|
||||
|
@ -46,7 +46,5 @@ define_pd_global(uintx,JVMInvokeMethodSlack, 8192);
|
||||
|
||||
// Used on 64 bit platforms for UseCompressedOops base address or CDS
|
||||
define_pd_global(uintx,HeapBaseMinAddress, 2*G);
|
||||
// Only used on 64 bit Windows platforms
|
||||
define_pd_global(bool, UseVectoredExceptions, false);
|
||||
|
||||
#endif // OS_CPU_LINUX_X86_VM_GLOBALS_LINUX_X86_HPP
|
||||
|
@ -41,7 +41,6 @@ define_pd_global(intx, VMThreadStackSize, 512);
|
||||
define_pd_global(intx, CompilerThreadStackSize, 0);
|
||||
define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
|
||||
|
||||
define_pd_global(bool, UseVectoredExceptions, false);
|
||||
// Used on 64 bit platforms for UseCompressedOops base address or CDS
|
||||
define_pd_global(uintx, HeapBaseMinAddress, 2*G);
|
||||
|
||||
|
@ -39,8 +39,6 @@ define_pd_global(uintx, HeapBaseMinAddress, CONST64(4)*G);
|
||||
#else
|
||||
define_pd_global(uintx, HeapBaseMinAddress, 2*G);
|
||||
#endif
|
||||
// Only used on 64 bit Windows platforms
|
||||
define_pd_global(bool, UseVectoredExceptions, false);
|
||||
|
||||
|
||||
|
||||
|
@ -45,7 +45,5 @@ define_pd_global(intx, CompilerThreadStackSize, 0);
|
||||
|
||||
// Used on 64 bit platforms for UseCompressedOops base address or CDS
|
||||
define_pd_global(uintx,HeapBaseMinAddress, 256*M);
|
||||
// Only used on 64 bit Windows platforms
|
||||
define_pd_global(bool, UseVectoredExceptions, false);
|
||||
|
||||
#endif // OS_CPU_SOLARIS_X86_VM_GLOBALS_SOLARIS_X86_HPP
|
||||
|
@ -47,7 +47,5 @@ define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
|
||||
|
||||
// Used on 64 bit platforms for UseCompressedOops base address or CDS
|
||||
define_pd_global(uintx, HeapBaseMinAddress, 2*G);
|
||||
// Only used on 64 bit Windows platforms
|
||||
define_pd_global(bool, UseVectoredExceptions, false);
|
||||
|
||||
#endif // OS_CPU_WINDOWS_X86_VM_GLOBALS_WINDOWS_X86_HPP
|
||||
|
@ -175,9 +175,6 @@ bool os::register_code_area(char *low, char *high) {
|
||||
PRUNTIME_FUNCTION prt;
|
||||
PUNWIND_INFO_EH_ONLY punwind;
|
||||
|
||||
// If we are using Vectored Exceptions we don't need this registration
|
||||
if (UseVectoredExceptions) return true;
|
||||
|
||||
BufferBlob* blob = BufferBlob::create("CodeCache Exception Handler", sizeof(DynamicCodeData));
|
||||
CodeBuffer cb(blob);
|
||||
MacroAssembler* masm = new MacroAssembler(&cb);
|
||||
|
@ -85,9 +85,11 @@ void end_of_file() { }
|
||||
|
||||
#include "dlfcn.h"
|
||||
|
||||
#define DECODE_INSTRUCTIONS_NAME "decode_instructions_virtual"
|
||||
#define DECODE_INSTRUCTIONS_VIRTUAL_NAME "decode_instructions_virtual"
|
||||
#define DECODE_INSTRUCTIONS_NAME "decode_instructions"
|
||||
#define HSDIS_NAME "hsdis"
|
||||
static void* decode_instructions_pv = 0;
|
||||
static void* decode_instructions_sv = 0;
|
||||
static const char* hsdis_path[] = {
|
||||
HSDIS_NAME"-"LIBARCH LIB_EXT,
|
||||
"./" HSDIS_NAME"-"LIBARCH LIB_EXT,
|
||||
@ -101,11 +103,12 @@ static const char* load_decode_instructions() {
|
||||
void* dllib = NULL;
|
||||
const char* *next_in_path = hsdis_path;
|
||||
while (1) {
|
||||
decode_instructions_pv = dlsym(dllib, DECODE_INSTRUCTIONS_NAME);
|
||||
if (decode_instructions_pv != NULL)
|
||||
decode_instructions_pv = dlsym(dllib, DECODE_INSTRUCTIONS_VIRTUAL_NAME);
|
||||
decode_instructions_sv = dlsym(dllib, DECODE_INSTRUCTIONS_NAME);
|
||||
if (decode_instructions_pv != NULL || decode_instructions_sv != NULL)
|
||||
return NULL;
|
||||
if (dllib != NULL)
|
||||
return "plugin does not defined "DECODE_INSTRUCTIONS_NAME;
|
||||
return "plugin does not defined "DECODE_INSTRUCTIONS_VIRTUAL_NAME" and "DECODE_INSTRUCTIONS_NAME;
|
||||
for (dllib = NULL; dllib == NULL; ) {
|
||||
const char* next_lib = (*next_in_path++);
|
||||
if (next_lib == NULL)
|
||||
@ -213,20 +216,44 @@ void disassemble(uintptr_t from, uintptr_t to) {
|
||||
printf("%s: %s\n", err, dlerror());
|
||||
exit(1);
|
||||
}
|
||||
printf("Decoding from %p to %p...\n", from, to);
|
||||
decode_instructions_ftype decode_instructions
|
||||
= (decode_instructions_ftype) decode_instructions_pv;
|
||||
decode_func_vtype decode_instructions_v
|
||||
= (decode_func_vtype) decode_instructions_pv;
|
||||
decode_func_stype decode_instructions_s
|
||||
= (decode_func_stype) decode_instructions_sv;
|
||||
void* res;
|
||||
if (raw && xml) {
|
||||
res = (*decode_instructions)(from, to, (unsigned char*)from, to - from, simple_handle_event, stdout, NULL, stdout, options);
|
||||
} else if (raw) {
|
||||
res = (*decode_instructions)(from, to, (unsigned char*)from, to - from, simple_handle_event, stdout, NULL, stdout, options);
|
||||
} else {
|
||||
res = (*decode_instructions)(from, to, (unsigned char*)from, to - from,
|
||||
handle_event, (void*) event_cookie,
|
||||
fprintf_callback, stdout,
|
||||
options);
|
||||
if (decode_instructions_pv != NULL) {
|
||||
printf("\nDecoding from %p to %p...with %s\n", from, to, DECODE_INSTRUCTIONS_VIRTUAL_NAME);
|
||||
if (raw) {
|
||||
res = (*decode_instructions_v)(from, to,
|
||||
(unsigned char*)from, to - from,
|
||||
simple_handle_event, stdout,
|
||||
NULL, stdout,
|
||||
options, 0);
|
||||
} else {
|
||||
res = (*decode_instructions_v)(from, to,
|
||||
(unsigned char*)from, to - from,
|
||||
handle_event, (void*) event_cookie,
|
||||
fprintf_callback, stdout,
|
||||
options, 0);
|
||||
}
|
||||
if (res != (void*)to)
|
||||
printf("*** Result was %p!\n", res);
|
||||
}
|
||||
void* sres;
|
||||
if (decode_instructions_sv != NULL) {
|
||||
printf("\nDecoding from %p to %p...with old decode_instructions\n", from, to, DECODE_INSTRUCTIONS_NAME);
|
||||
if (raw) {
|
||||
sres = (*decode_instructions_s)(from, to,
|
||||
simple_handle_event, stdout,
|
||||
NULL, stdout,
|
||||
options);
|
||||
} else {
|
||||
sres = (*decode_instructions_s)(from, to,
|
||||
handle_event, (void*) event_cookie,
|
||||
fprintf_callback, stdout,
|
||||
options);
|
||||
}
|
||||
if (sres != (void *)to)
|
||||
printf("*** Result of decode_instructions %p!\n", sres);
|
||||
}
|
||||
if (res != (void*)to)
|
||||
printf("*** Result was %p!\n", res);
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va,
|
||||
unsigned char* buffer, uintptr_t length,
|
||||
event_callback_t event_callback_arg, void* event_stream_arg,
|
||||
printf_callback_t printf_callback_arg, void* printf_stream_arg,
|
||||
const char* options) {
|
||||
const char* options, int newline) {
|
||||
struct hsdis_app_data app_data;
|
||||
memset(&app_data, 0, sizeof(app_data));
|
||||
app_data.start_va = start_va;
|
||||
@ -110,7 +110,7 @@ decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va,
|
||||
app_data.event_stream = event_stream_arg;
|
||||
app_data.printf_callback = printf_callback_arg;
|
||||
app_data.printf_stream = printf_stream_arg;
|
||||
app_data.do_newline = false;
|
||||
app_data.do_newline = newline == 0 ? false : true;
|
||||
|
||||
return decode(&app_data, options);
|
||||
}
|
||||
@ -132,7 +132,7 @@ decode_instructions(void* start_pv, void* end_pv,
|
||||
event_stream_arg,
|
||||
printf_callback_arg,
|
||||
printf_stream_arg,
|
||||
options);
|
||||
options, false);
|
||||
}
|
||||
|
||||
static void* decode(struct hsdis_app_data* app_data, const char* options) {
|
||||
@ -173,7 +173,7 @@ static void* decode(struct hsdis_app_data* app_data, const char* options) {
|
||||
if (!app_data->losing) {
|
||||
const char* insn_close = format_insn_close("/insn", &app_data->dinfo,
|
||||
buf, sizeof(buf));
|
||||
(*event_callback)(event_stream, insn_close, (void*) p) != NULL;
|
||||
(*event_callback)(event_stream, insn_close, (void*) p);
|
||||
|
||||
if (app_data->do_newline) {
|
||||
/* follow each complete insn by a nice newline */
|
||||
@ -182,13 +182,14 @@ static void* decode(struct hsdis_app_data* app_data, const char* options) {
|
||||
}
|
||||
}
|
||||
|
||||
(*event_callback)(event_stream, "/insns", (void*) p);
|
||||
if (app_data->losing) (*event_callback)(event_stream, "/insns", (void*) p);
|
||||
return (void*) p;
|
||||
}
|
||||
}
|
||||
|
||||
/* take the address of the function, for luck, and also test the typedef: */
|
||||
const decode_instructions_ftype decode_instructions_address = &decode_instructions_virtual;
|
||||
const decode_func_vtype decode_func_virtual_address = &decode_instructions_virtual;
|
||||
const decode_func_stype decode_func_address = &decode_instructions;
|
||||
|
||||
static const char* format_insn_close(const char* close,
|
||||
disassemble_info* dinfo,
|
||||
|
@ -47,6 +47,9 @@
|
||||
where tag is a simple identifier, signifying (as in XML) a element start,
|
||||
element end, and standalone element. (To render as XML, add angle brackets.)
|
||||
*/
|
||||
#ifndef SHARED_TOOLS_HSDIS_H
|
||||
#define SHARED_TOOLS_HSDIS_H
|
||||
|
||||
extern
|
||||
#ifdef DLL_EXPORT
|
||||
DLL_EXPORT
|
||||
@ -57,16 +60,37 @@ void* decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va,
|
||||
void* event_stream,
|
||||
int (*printf_callback)(void*, const char*, ...),
|
||||
void* printf_stream,
|
||||
const char* options);
|
||||
const char* options,
|
||||
int newline /* bool value for nice new line */);
|
||||
|
||||
/* This is the compatability interface for older versions of hotspot */
|
||||
extern
|
||||
#ifdef DLL_ENTRY
|
||||
DLL_ENTRY
|
||||
#endif
|
||||
void* decode_instructions(void* start_pv, void* end_pv,
|
||||
void* (*event_callback)(void*, const char*, void*),
|
||||
void* event_stream,
|
||||
int (*printf_callback)(void*, const char*, ...),
|
||||
void* printf_stream,
|
||||
const char* options);
|
||||
|
||||
/* convenience typedefs */
|
||||
|
||||
typedef void* (*decode_instructions_event_callback_ftype) (void*, const char*, void*);
|
||||
typedef int (*decode_instructions_printf_callback_ftype) (void*, const char*, ...);
|
||||
typedef void* (*decode_instructions_ftype) (uintptr_t start_va, uintptr_t end_va,
|
||||
unsigned char* buffer, uintptr_t length,
|
||||
decode_instructions_event_callback_ftype event_callback,
|
||||
void* event_stream,
|
||||
decode_instructions_printf_callback_ftype printf_callback,
|
||||
void* printf_stream,
|
||||
const char* options);
|
||||
typedef void* (*decode_func_vtype) (uintptr_t start_va, uintptr_t end_va,
|
||||
unsigned char* buffer, uintptr_t length,
|
||||
decode_instructions_event_callback_ftype event_callback,
|
||||
void* event_stream,
|
||||
decode_instructions_printf_callback_ftype printf_callback,
|
||||
void* printf_stream,
|
||||
const char* options,
|
||||
int newline);
|
||||
typedef void* (*decode_func_stype) (void* start_pv, void* end_pv,
|
||||
decode_instructions_event_callback_ftype event_callback,
|
||||
void* event_stream,
|
||||
decode_instructions_printf_callback_ftype printf_callback,
|
||||
void* printf_stream,
|
||||
const char* options);
|
||||
#endif /* SHARED_TOOLS_HSDIS_H */
|
||||
|
@ -758,7 +758,7 @@ void CodeBuffer::relocate_code_to(CodeBuffer* dest) const {
|
||||
}
|
||||
}
|
||||
|
||||
if (dest->blob() == NULL) {
|
||||
if (dest->blob() == NULL && dest_filled != NULL) {
|
||||
// Destination is a final resting place, not just another buffer.
|
||||
// Normalize uninitialized bytes in the final padding.
|
||||
Copy::fill_to_bytes(dest_filled, dest_end - dest_filled,
|
||||
|
@ -768,8 +768,8 @@ ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool,
|
||||
Method* m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc);
|
||||
if (m != NULL &&
|
||||
(bc == Bytecodes::_invokestatic
|
||||
? InstanceKlass::cast(m->method_holder())->is_not_initialized()
|
||||
: !InstanceKlass::cast(m->method_holder())->is_loaded())) {
|
||||
? m->method_holder()->is_not_initialized()
|
||||
: !m->method_holder()->is_loaded())) {
|
||||
m = NULL;
|
||||
}
|
||||
if (m != NULL) {
|
||||
@ -1056,7 +1056,7 @@ void ciEnv::register_method(ciMethod* target,
|
||||
method_name,
|
||||
entry_bci);
|
||||
}
|
||||
InstanceKlass::cast(method->method_holder())->add_osr_nmethod(nm);
|
||||
method->method_holder()->add_osr_nmethod(nm);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ ciMethod::ciMethod(methodHandle h_m) : ciMetadata(h_m()) {
|
||||
CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
|
||||
}
|
||||
|
||||
if (InstanceKlass::cast(h_m()->method_holder())->is_linked()) {
|
||||
if (h_m()->method_holder()->is_linked()) {
|
||||
_can_be_statically_bound = h_m()->can_be_statically_bound();
|
||||
} else {
|
||||
// Have to use a conservative value in this case.
|
||||
@ -188,7 +188,7 @@ void ciMethod::load_code() {
|
||||
|
||||
// Revert any breakpoint bytecodes in ci's copy
|
||||
if (me->number_of_breakpoints() > 0) {
|
||||
BreakpointInfo* bp = InstanceKlass::cast(me->method_holder())->breakpoints();
|
||||
BreakpointInfo* bp = me->method_holder()->breakpoints();
|
||||
for (; bp != NULL; bp = bp->next()) {
|
||||
if (bp->match(me)) {
|
||||
code_at_put(bp->bci(), bp->orig_bytecode());
|
||||
|
269
hotspot/src/share/vm/classfile/bytecodeAssembler.cpp
Normal file
269
hotspot/src/share/vm/classfile/bytecodeAssembler.cpp
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "classfile/bytecodeAssembler.hpp"
|
||||
#include "interpreter/bytecodes.hpp"
|
||||
#include "memory/oopFactory.hpp"
|
||||
#include "oops/constantPool.hpp"
|
||||
|
||||
#ifdef TARGET_ARCH_x86
|
||||
# include "bytes_x86.hpp"
|
||||
#endif
|
||||
#ifdef TARGET_ARCH_sparc
|
||||
# include "bytes_sparc.hpp"
|
||||
#endif
|
||||
#ifdef TARGET_ARCH_zero
|
||||
# include "bytes_zero.hpp"
|
||||
#endif
|
||||
#ifdef TARGET_ARCH_arm
|
||||
# include "bytes_arm.hpp"
|
||||
#endif
|
||||
#ifdef TARGET_ARCH_ppc
|
||||
# include "bytes_ppc.hpp"
|
||||
#endif
|
||||
|
||||
u2 BytecodeConstantPool::find_or_add(BytecodeCPEntry const& bcpe) {
|
||||
u2 index;
|
||||
u2* probe = _indices.get(bcpe);
|
||||
if (probe == NULL) {
|
||||
index = _entries.length();
|
||||
_entries.append(bcpe);
|
||||
_indices.put(bcpe, index);
|
||||
} else {
|
||||
index = *probe;
|
||||
}
|
||||
return index + _orig->length();
|
||||
}
|
||||
|
||||
ConstantPool* BytecodeConstantPool::create_constant_pool(TRAPS) const {
|
||||
if (_entries.length() == 0) {
|
||||
return _orig;
|
||||
}
|
||||
|
||||
ConstantPool* cp = ConstantPool::allocate(
|
||||
_orig->pool_holder()->class_loader_data(),
|
||||
_orig->length() + _entries.length(), CHECK_NULL);
|
||||
|
||||
cp->set_pool_holder(_orig->pool_holder());
|
||||
_orig->copy_cp_to(1, _orig->length() - 1, cp, 1, CHECK_NULL);
|
||||
|
||||
for (int i = 0; i < _entries.length(); ++i) {
|
||||
BytecodeCPEntry entry = _entries.at(i);
|
||||
int idx = i + _orig->length();
|
||||
switch (entry._tag) {
|
||||
case BytecodeCPEntry::UTF8:
|
||||
cp->symbol_at_put(idx, entry._u.utf8);
|
||||
entry._u.utf8->increment_refcount();
|
||||
break;
|
||||
case BytecodeCPEntry::KLASS:
|
||||
cp->unresolved_klass_at_put(
|
||||
idx, cp->symbol_at(entry._u.klass));
|
||||
break;
|
||||
case BytecodeCPEntry::STRING:
|
||||
cp->unresolved_string_at_put(
|
||||
idx, cp->symbol_at(entry._u.string));
|
||||
break;
|
||||
case BytecodeCPEntry::NAME_AND_TYPE:
|
||||
cp->name_and_type_at_put(idx,
|
||||
entry._u.name_and_type.name_index,
|
||||
entry._u.name_and_type.type_index);
|
||||
break;
|
||||
case BytecodeCPEntry::METHODREF:
|
||||
cp->method_at_put(idx,
|
||||
entry._u.methodref.class_index,
|
||||
entry._u.methodref.name_and_type_index);
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
void BytecodeAssembler::append(u1 imm_u1) {
|
||||
_code->append(imm_u1);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::append(u2 imm_u2) {
|
||||
_code->append(0);
|
||||
_code->append(0);
|
||||
Bytes::put_Java_u2(_code->adr_at(_code->length() - 2), imm_u2);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::append(u4 imm_u4) {
|
||||
_code->append(0);
|
||||
_code->append(0);
|
||||
_code->append(0);
|
||||
_code->append(0);
|
||||
Bytes::put_Java_u4(_code->adr_at(_code->length() - 4), imm_u4);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::xload(u4 index, u1 onebyteop, u1 twobyteop) {
|
||||
if (index < 4) {
|
||||
_code->append(onebyteop + index);
|
||||
} else {
|
||||
_code->append(twobyteop);
|
||||
_code->append((u2)index);
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeAssembler::dup() {
|
||||
_code->append(Bytecodes::_dup);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::_new(Symbol* sym) {
|
||||
u2 cpool_index = _cp->klass(sym);
|
||||
_code->append(Bytecodes::_new);
|
||||
append(cpool_index);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::load_string(Symbol* sym) {
|
||||
u2 cpool_index = _cp->string(sym);
|
||||
if (cpool_index < 0x100) {
|
||||
ldc(cpool_index);
|
||||
} else {
|
||||
ldc_w(cpool_index);
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeAssembler::ldc(u1 index) {
|
||||
_code->append(Bytecodes::_ldc);
|
||||
append(index);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::ldc_w(u2 index) {
|
||||
_code->append(Bytecodes::_ldc_w);
|
||||
append(index);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::athrow() {
|
||||
_code->append(Bytecodes::_athrow);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::iload(u4 index) {
|
||||
xload(index, Bytecodes::_iload_0, Bytecodes::_iload);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::lload(u4 index) {
|
||||
xload(index, Bytecodes::_lload_0, Bytecodes::_lload);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::fload(u4 index) {
|
||||
xload(index, Bytecodes::_fload_0, Bytecodes::_fload);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::dload(u4 index) {
|
||||
xload(index, Bytecodes::_dload_0, Bytecodes::_dload);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::aload(u4 index) {
|
||||
xload(index, Bytecodes::_aload_0, Bytecodes::_aload);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::load(BasicType bt, u4 index) {
|
||||
switch (bt) {
|
||||
case T_BOOLEAN:
|
||||
case T_CHAR:
|
||||
case T_BYTE:
|
||||
case T_SHORT:
|
||||
case T_INT: iload(index); break;
|
||||
case T_FLOAT: fload(index); break;
|
||||
case T_DOUBLE: dload(index); break;
|
||||
case T_LONG: lload(index); break;
|
||||
case T_OBJECT:
|
||||
case T_ARRAY: aload(index); break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeAssembler::checkcast(Symbol* sym) {
|
||||
u2 cpool_index = _cp->klass(sym);
|
||||
_code->append(Bytecodes::_checkcast);
|
||||
append(cpool_index);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::invokespecial(Method* method) {
|
||||
invokespecial(method->klass_name(), method->name(), method->signature());
|
||||
}
|
||||
|
||||
void BytecodeAssembler::invokespecial(Symbol* klss, Symbol* name, Symbol* sig) {
|
||||
u2 methodref_index = _cp->methodref(klss, name, sig);
|
||||
_code->append(Bytecodes::_invokespecial);
|
||||
append(methodref_index);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::invokevirtual(Method* method) {
|
||||
invokevirtual(method->klass_name(), method->name(), method->signature());
|
||||
}
|
||||
|
||||
void BytecodeAssembler::invokevirtual(Symbol* klss, Symbol* name, Symbol* sig) {
|
||||
u2 methodref_index = _cp->methodref(klss, name, sig);
|
||||
_code->append(Bytecodes::_invokevirtual);
|
||||
append(methodref_index);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::ireturn() {
|
||||
_code->append(Bytecodes::_ireturn);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::lreturn() {
|
||||
_code->append(Bytecodes::_lreturn);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::freturn() {
|
||||
_code->append(Bytecodes::_freturn);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::dreturn() {
|
||||
_code->append(Bytecodes::_dreturn);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::areturn() {
|
||||
_code->append(Bytecodes::_areturn);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::_return() {
|
||||
_code->append(Bytecodes::_return);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::_return(BasicType bt) {
|
||||
switch (bt) {
|
||||
case T_BOOLEAN:
|
||||
case T_CHAR:
|
||||
case T_BYTE:
|
||||
case T_SHORT:
|
||||
case T_INT: ireturn(); break;
|
||||
case T_FLOAT: freturn(); break;
|
||||
case T_DOUBLE: dreturn(); break;
|
||||
case T_LONG: lreturn(); break;
|
||||
case T_OBJECT:
|
||||
case T_ARRAY: areturn(); break;
|
||||
case T_VOID: _return(); break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
214
hotspot/src/share/vm/classfile/bytecodeAssembler.hpp
Normal file
214
hotspot/src/share/vm/classfile/bytecodeAssembler.hpp
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_CLASSFILE_BYTECODEASSEMBLER_HPP
|
||||
#define SHARE_VM_CLASSFILE_BYTECODEASSEMBLER_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
#include "oops/method.hpp"
|
||||
#include "oops/symbol.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/resourceHash.hpp"
|
||||
|
||||
|
||||
/**
|
||||
* Bytecode Assembler
|
||||
*
|
||||
* These classes are used to synthesize code for creating new methods from
|
||||
* within the VM. This is only a partial implementation of an assembler;
|
||||
* only the bytecodes that are needed by clients are implemented at this time.
|
||||
* This is used during default method analysis to create overpass methods
|
||||
* and add them to a call during parsing. Other uses (such as creating
|
||||
* bridges) may come later. Any missing bytecodes can be implemented on an
|
||||
* as-need basis.
|
||||
*/
|
||||
|
||||
class BytecodeBuffer : public GrowableArray<u1> {
|
||||
public:
|
||||
BytecodeBuffer() : GrowableArray<u1>(20) {}
|
||||
};
|
||||
|
||||
// Entries in a yet-to-be-created constant pool. Limited types for now.
|
||||
class BytecodeCPEntry VALUE_OBJ_CLASS_SPEC {
|
||||
public:
|
||||
enum tag {
|
||||
ERROR_TAG,
|
||||
UTF8,
|
||||
KLASS,
|
||||
STRING,
|
||||
NAME_AND_TYPE,
|
||||
METHODREF
|
||||
};
|
||||
|
||||
u1 _tag;
|
||||
union {
|
||||
Symbol* utf8;
|
||||
u2 klass;
|
||||
u2 string;
|
||||
struct {
|
||||
u2 name_index;
|
||||
u2 type_index;
|
||||
} name_and_type;
|
||||
struct {
|
||||
u2 class_index;
|
||||
u2 name_and_type_index;
|
||||
} methodref;
|
||||
uintptr_t hash;
|
||||
} _u;
|
||||
|
||||
BytecodeCPEntry() : _tag(ERROR_TAG) { _u.hash = 0; }
|
||||
BytecodeCPEntry(u1 tag) : _tag(tag) { _u.hash = 0; }
|
||||
|
||||
static BytecodeCPEntry utf8(Symbol* symbol) {
|
||||
BytecodeCPEntry bcpe(UTF8);
|
||||
bcpe._u.utf8 = symbol;
|
||||
return bcpe;
|
||||
}
|
||||
|
||||
static BytecodeCPEntry klass(u2 index) {
|
||||
BytecodeCPEntry bcpe(KLASS);
|
||||
bcpe._u.klass = index;
|
||||
return bcpe;
|
||||
}
|
||||
|
||||
static BytecodeCPEntry string(u2 index) {
|
||||
BytecodeCPEntry bcpe(STRING);
|
||||
bcpe._u.string = index;
|
||||
return bcpe;
|
||||
}
|
||||
|
||||
static BytecodeCPEntry name_and_type(u2 name, u2 type) {
|
||||
BytecodeCPEntry bcpe(NAME_AND_TYPE);
|
||||
bcpe._u.name_and_type.name_index = name;
|
||||
bcpe._u.name_and_type.type_index = type;
|
||||
return bcpe;
|
||||
}
|
||||
|
||||
static BytecodeCPEntry methodref(u2 class_index, u2 nat) {
|
||||
BytecodeCPEntry bcpe(METHODREF);
|
||||
bcpe._u.methodref.class_index = class_index;
|
||||
bcpe._u.methodref.name_and_type_index = nat;
|
||||
return bcpe;
|
||||
}
|
||||
|
||||
static bool equals(BytecodeCPEntry const& e0, BytecodeCPEntry const& e1) {
|
||||
return e0._tag == e1._tag && e0._u.hash == e1._u.hash;
|
||||
}
|
||||
|
||||
static unsigned hash(BytecodeCPEntry const& e0) {
|
||||
return (unsigned)(e0._tag ^ e0._u.hash);
|
||||
}
|
||||
};
|
||||
|
||||
class BytecodeConstantPool : ResourceObj {
|
||||
private:
|
||||
typedef ResourceHashtable<BytecodeCPEntry, u2,
|
||||
&BytecodeCPEntry::hash, &BytecodeCPEntry::equals> IndexHash;
|
||||
|
||||
ConstantPool* _orig;
|
||||
GrowableArray<BytecodeCPEntry> _entries;
|
||||
IndexHash _indices;
|
||||
|
||||
u2 find_or_add(BytecodeCPEntry const& bcpe);
|
||||
|
||||
public:
|
||||
|
||||
BytecodeConstantPool(ConstantPool* orig) : _orig(orig) {}
|
||||
|
||||
BytecodeCPEntry const& at(u2 index) const { return _entries.at(index); }
|
||||
|
||||
InstanceKlass* pool_holder() const {
|
||||
return InstanceKlass::cast(_orig->pool_holder());
|
||||
}
|
||||
|
||||
u2 utf8(Symbol* sym) {
|
||||
return find_or_add(BytecodeCPEntry::utf8(sym));
|
||||
}
|
||||
|
||||
u2 klass(Symbol* class_name) {
|
||||
return find_or_add(BytecodeCPEntry::klass(utf8(class_name)));
|
||||
}
|
||||
|
||||
u2 string(Symbol* str) {
|
||||
return find_or_add(BytecodeCPEntry::string(utf8(str)));
|
||||
}
|
||||
|
||||
u2 name_and_type(Symbol* name, Symbol* sig) {
|
||||
return find_or_add(BytecodeCPEntry::name_and_type(utf8(name), utf8(sig)));
|
||||
}
|
||||
|
||||
u2 methodref(Symbol* class_name, Symbol* name, Symbol* sig) {
|
||||
return find_or_add(BytecodeCPEntry::methodref(
|
||||
klass(class_name), name_and_type(name, sig)));
|
||||
}
|
||||
|
||||
ConstantPool* create_constant_pool(TRAPS) const;
|
||||
};
|
||||
|
||||
// Partial bytecode assembler - only what we need for creating
|
||||
// overpass methods for default methods is implemented
|
||||
class BytecodeAssembler : StackObj {
|
||||
private:
|
||||
BytecodeBuffer* _code;
|
||||
BytecodeConstantPool* _cp;
|
||||
|
||||
void append(u1 imm_u1);
|
||||
void append(u2 imm_u2);
|
||||
void append(u4 imm_u4);
|
||||
|
||||
void xload(u4 index, u1 quick, u1 twobyte);
|
||||
|
||||
public:
|
||||
BytecodeAssembler(BytecodeBuffer* buffer, BytecodeConstantPool* cp)
|
||||
: _code(buffer), _cp(cp) {}
|
||||
|
||||
void aload(u4 index);
|
||||
void areturn();
|
||||
void athrow();
|
||||
void checkcast(Symbol* sym);
|
||||
void dload(u4 index);
|
||||
void dreturn();
|
||||
void dup();
|
||||
void fload(u4 index);
|
||||
void freturn();
|
||||
void iload(u4 index);
|
||||
void invokespecial(Method* method);
|
||||
void invokespecial(Symbol* cls, Symbol* name, Symbol* sig);
|
||||
void invokevirtual(Method* method);
|
||||
void invokevirtual(Symbol* cls, Symbol* name, Symbol* sig);
|
||||
void ireturn();
|
||||
void ldc(u1 index);
|
||||
void ldc_w(u2 index);
|
||||
void lload(u4 index);
|
||||
void lreturn();
|
||||
void _new(Symbol* sym);
|
||||
void _return();
|
||||
|
||||
void load_string(Symbol* sym);
|
||||
void load(BasicType bt, u4 index);
|
||||
void _return(BasicType bt);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_CLASSFILE_BYTECODEASSEMBLER_HPP
|
@ -27,6 +27,8 @@
|
||||
#include "classfile/classLoader.hpp"
|
||||
#include "classfile/classLoaderData.hpp"
|
||||
#include "classfile/classLoaderData.inline.hpp"
|
||||
#include "classfile/defaultMethods.hpp"
|
||||
#include "classfile/genericSignatures.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
@ -84,6 +86,9 @@
|
||||
// - to check NameAndType_info signatures more aggressively
|
||||
#define JAVA_7_VERSION 51
|
||||
|
||||
// Extension method support.
|
||||
#define JAVA_8_VERSION 52
|
||||
|
||||
|
||||
void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, constantPoolHandle cp, int length, TRAPS) {
|
||||
// Use a local copy of ClassFileStream. It helps the C++ compiler to optimize
|
||||
@ -785,6 +790,7 @@ Array<Klass*>* ClassFileParser::parse_interfaces(constantPoolHandle cp,
|
||||
ClassLoaderData* loader_data,
|
||||
Handle protection_domain,
|
||||
Symbol* class_name,
|
||||
bool* has_default_methods,
|
||||
TRAPS) {
|
||||
ClassFileStream* cfs = stream();
|
||||
assert(length > 0, "only called for length>0");
|
||||
@ -821,6 +827,9 @@ Array<Klass*>* ClassFileParser::parse_interfaces(constantPoolHandle cp,
|
||||
if (!Klass::cast(interf())->is_interface()) {
|
||||
THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", NULL);
|
||||
}
|
||||
if (InstanceKlass::cast(interf())->has_default_methods()) {
|
||||
*has_default_methods = true;
|
||||
}
|
||||
interfaces->at_put(index, interf());
|
||||
}
|
||||
|
||||
@ -1928,7 +1937,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
if (method_attribute_name == vmSymbols::tag_code()) {
|
||||
// Parse Code attribute
|
||||
if (_need_verify) {
|
||||
guarantee_property(!access_flags.is_native() && !access_flags.is_abstract(),
|
||||
guarantee_property(
|
||||
!access_flags.is_native() && !access_flags.is_abstract(),
|
||||
"Code attribute in native or abstract methods in class file %s",
|
||||
CHECK_(nullHandle));
|
||||
}
|
||||
@ -2125,7 +2135,9 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
runtime_visible_annotations_length = method_attribute_length;
|
||||
runtime_visible_annotations = cfs->get_u1_buffer();
|
||||
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
||||
parse_annotations(runtime_visible_annotations, runtime_visible_annotations_length, cp, &parsed_annotations, CHECK_(nullHandle));
|
||||
parse_annotations(runtime_visible_annotations,
|
||||
runtime_visible_annotations_length, cp, &parsed_annotations,
|
||||
CHECK_(nullHandle));
|
||||
cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
|
||||
} else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
|
||||
runtime_invisible_annotations_length = method_attribute_length;
|
||||
@ -2169,12 +2181,10 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
}
|
||||
|
||||
// All sizing information for a Method* is finally available, now create it
|
||||
Method* m = Method::allocate(loader_data, code_length, access_flags,
|
||||
linenumber_table_length,
|
||||
total_lvt_length,
|
||||
exception_table_length,
|
||||
checked_exceptions_length,
|
||||
CHECK_(nullHandle));
|
||||
Method* m = Method::allocate(
|
||||
loader_data, code_length, access_flags, linenumber_table_length,
|
||||
total_lvt_length, exception_table_length, checked_exceptions_length,
|
||||
ConstMethod::NORMAL, CHECK_(nullHandle));
|
||||
|
||||
ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
|
||||
|
||||
@ -2204,7 +2214,6 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
// Fill in code attribute information
|
||||
m->set_max_stack(max_stack);
|
||||
m->set_max_locals(max_locals);
|
||||
|
||||
m->constMethod()->set_stackmap_data(stackmap_data);
|
||||
|
||||
// Copy byte codes
|
||||
@ -2356,6 +2365,7 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
||||
Array<AnnotationArray*>** methods_annotations,
|
||||
Array<AnnotationArray*>** methods_parameter_annotations,
|
||||
Array<AnnotationArray*>** methods_default_annotations,
|
||||
bool* has_default_methods,
|
||||
TRAPS) {
|
||||
ClassFileStream* cfs = stream();
|
||||
AnnotationArray* method_annotations = NULL;
|
||||
@ -2382,6 +2392,10 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
||||
if (method->is_final()) {
|
||||
*has_final_method = true;
|
||||
}
|
||||
if (is_interface && !method->is_abstract() && !method->is_static()) {
|
||||
// default method
|
||||
*has_default_methods = true;
|
||||
}
|
||||
methods->at_put(index, method());
|
||||
if (*methods_annotations == NULL) {
|
||||
*methods_annotations =
|
||||
@ -2907,6 +2921,34 @@ AnnotationArray* ClassFileParser::assemble_annotations(ClassLoaderData* loader_d
|
||||
}
|
||||
|
||||
|
||||
#ifndef PRODUCT
|
||||
static void parseAndPrintGenericSignatures(
|
||||
instanceKlassHandle this_klass, TRAPS) {
|
||||
assert(ParseAllGenericSignatures == true, "Shouldn't call otherwise");
|
||||
ResourceMark rm;
|
||||
|
||||
if (this_klass->generic_signature() != NULL) {
|
||||
using namespace generic;
|
||||
ClassDescriptor* spec = ClassDescriptor::parse_generic_signature(this_klass(), CHECK);
|
||||
|
||||
tty->print_cr("Parsing %s", this_klass->generic_signature()->as_C_string());
|
||||
spec->print_on(tty);
|
||||
|
||||
for (int i = 0; i < this_klass->methods()->length(); ++i) {
|
||||
Method* m = this_klass->methods()->at(i);
|
||||
MethodDescriptor* method_spec = MethodDescriptor::parse_generic_signature(m, spec);
|
||||
Symbol* sig = m->generic_signature();
|
||||
if (sig == NULL) {
|
||||
sig = m->signature();
|
||||
}
|
||||
tty->print_cr("Parsing %s", sig->as_C_string());
|
||||
method_spec->print_on(tty);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ndef PRODUCT
|
||||
|
||||
|
||||
instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
@ -2923,6 +2965,8 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
unsigned char *cached_class_file_bytes = NULL;
|
||||
jint cached_class_file_length;
|
||||
ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader());
|
||||
bool has_default_methods = false;
|
||||
ResourceMark rm(THREAD);
|
||||
|
||||
ClassFileStream* cfs = stream();
|
||||
// Timing
|
||||
@ -3138,7 +3182,9 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
if (itfs_len == 0) {
|
||||
local_interfaces = Universe::the_empty_klass_array();
|
||||
} else {
|
||||
local_interfaces = parse_interfaces(cp, itfs_len, loader_data, protection_domain, _class_name, CHECK_(nullHandle));
|
||||
local_interfaces = parse_interfaces(
|
||||
cp, itfs_len, loader_data, protection_domain, _class_name,
|
||||
&has_default_methods, CHECK_(nullHandle));
|
||||
}
|
||||
|
||||
u2 java_fields_count = 0;
|
||||
@ -3164,6 +3210,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
&methods_annotations,
|
||||
&methods_parameter_annotations,
|
||||
&methods_default_annotations,
|
||||
&has_default_methods,
|
||||
CHECK_(nullHandle));
|
||||
|
||||
// Additional attributes
|
||||
@ -3193,6 +3240,11 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
super_klass = instanceKlassHandle(THREAD, kh());
|
||||
}
|
||||
if (super_klass.not_null()) {
|
||||
|
||||
if (super_klass->has_default_methods()) {
|
||||
has_default_methods = true;
|
||||
}
|
||||
|
||||
if (super_klass->is_interface()) {
|
||||
ResourceMark rm(THREAD);
|
||||
Exceptions::fthrow(
|
||||
@ -3229,14 +3281,11 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
int itable_size = 0;
|
||||
int num_miranda_methods = 0;
|
||||
|
||||
klassVtable::compute_vtable_size_and_num_mirandas(vtable_size,
|
||||
num_miranda_methods,
|
||||
super_klass(),
|
||||
methods,
|
||||
access_flags,
|
||||
class_loader,
|
||||
class_name,
|
||||
local_interfaces,
|
||||
GrowableArray<Method*> all_mirandas(20);
|
||||
|
||||
klassVtable::compute_vtable_size_and_num_mirandas(
|
||||
&vtable_size, &num_miranda_methods, &all_mirandas, super_klass(), methods,
|
||||
access_flags, class_loader, class_name, local_interfaces,
|
||||
CHECK_(nullHandle));
|
||||
|
||||
// Size of Java itable (in words)
|
||||
@ -3656,6 +3705,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
|
||||
this_klass->set_minor_version(minor_version);
|
||||
this_klass->set_major_version(major_version);
|
||||
this_klass->set_has_default_methods(has_default_methods);
|
||||
|
||||
// Set up Method*::intrinsic_id as soon as we know the names of methods.
|
||||
// (We used to do this lazily, but now we query it in Rewriter,
|
||||
@ -3673,6 +3723,16 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
cached_class_file_length);
|
||||
}
|
||||
|
||||
// Fill in field values obtained by parse_classfile_attributes
|
||||
if (parsed_annotations.has_any_annotations())
|
||||
parsed_annotations.apply_to(this_klass);
|
||||
// Create annotations
|
||||
if (_annotations != NULL && this_klass->annotations() == NULL) {
|
||||
Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
|
||||
this_klass->set_annotations(anno);
|
||||
}
|
||||
apply_parsed_class_attributes(this_klass);
|
||||
|
||||
// Miranda methods
|
||||
if ((num_miranda_methods > 0) ||
|
||||
// if this class introduced new miranda methods or
|
||||
@ -3682,18 +3742,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
this_klass->set_has_miranda_methods(); // then set a flag
|
||||
}
|
||||
|
||||
// Fill in field values obtained by parse_classfile_attributes
|
||||
if (parsed_annotations.has_any_annotations()) {
|
||||
parsed_annotations.apply_to(this_klass);
|
||||
}
|
||||
// Create annotations
|
||||
if (_annotations != NULL && this_klass->annotations() == NULL) {
|
||||
Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
|
||||
this_klass->set_annotations(anno);
|
||||
}
|
||||
apply_parsed_class_attributes(this_klass);
|
||||
|
||||
// Compute transitive closure of interfaces this class implements
|
||||
this_klass->set_transitive_interfaces(transitive_interfaces);
|
||||
|
||||
// Fill in information needed to compute superclasses.
|
||||
@ -3702,6 +3750,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
// Initialize itable offset tables
|
||||
klassItable::setup_itable_offset_table(this_klass);
|
||||
|
||||
// Compute transitive closure of interfaces this class implements
|
||||
// Do final class setup
|
||||
fill_oop_maps(this_klass, nonstatic_oop_map_count, nonstatic_oop_offsets, nonstatic_oop_counts);
|
||||
|
||||
@ -3726,6 +3775,21 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
check_illegal_static_method(this_klass, CHECK_(nullHandle));
|
||||
}
|
||||
|
||||
|
||||
#ifdef ASSERT
|
||||
if (ParseAllGenericSignatures) {
|
||||
parseAndPrintGenericSignatures(this_klass, CHECK_(nullHandle));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Generate any default methods - default methods are interface methods
|
||||
// that have a default implementation. This is new with Lambda project.
|
||||
if (has_default_methods && !access_flags.is_interface() &&
|
||||
local_interfaces->length() > 0) {
|
||||
DefaultMethods::generate_default_methods(
|
||||
this_klass(), &all_mirandas, CHECK_(nullHandle));
|
||||
}
|
||||
|
||||
// Allocate mirror and initialize static fields
|
||||
java_lang_Class::create_mirror(this_klass, CHECK_(nullHandle));
|
||||
|
||||
@ -3744,6 +3808,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
false /* not shared class */);
|
||||
|
||||
if (TraceClassLoading) {
|
||||
ResourceMark rm;
|
||||
// print in a single call to reduce interleaving of output
|
||||
if (cfs->source() != NULL) {
|
||||
tty->print("[Loaded %s from %s]\n", this_klass->external_name(),
|
||||
@ -3758,13 +3823,13 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
tty->print("[Loaded %s]\n", this_klass->external_name());
|
||||
}
|
||||
} else {
|
||||
ResourceMark rm;
|
||||
tty->print("[Loaded %s from %s]\n", this_klass->external_name(),
|
||||
InstanceKlass::cast(class_loader->klass())->external_name());
|
||||
}
|
||||
}
|
||||
|
||||
if (TraceClassResolution) {
|
||||
ResourceMark rm;
|
||||
// print out the superclass.
|
||||
const char * from = Klass::cast(this_klass())->external_name();
|
||||
if (this_klass->java_super() != NULL) {
|
||||
@ -3785,6 +3850,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
|
||||
#ifndef PRODUCT
|
||||
if( PrintCompactFieldsSavings ) {
|
||||
ResourceMark rm;
|
||||
if( nonstatic_field_size < orig_nonstatic_field_size ) {
|
||||
tty->print("[Saved %d of %d bytes in %s]\n",
|
||||
(orig_nonstatic_field_size - nonstatic_field_size)*heapOopSize,
|
||||
@ -3811,7 +3877,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
return this_klass;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
ClassFileParser::compute_oop_map_count(instanceKlassHandle super,
|
||||
unsigned int nonstatic_oop_map_count,
|
||||
@ -4128,7 +4193,7 @@ void ClassFileParser::check_final_method_override(instanceKlassHandle this_klass
|
||||
}
|
||||
|
||||
// continue to look from super_m's holder's super.
|
||||
k = InstanceKlass::cast(super_m->method_holder())->super();
|
||||
k = super_m->method_holder()->super();
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -4263,13 +4328,16 @@ void ClassFileParser::verify_legal_method_modifiers(
|
||||
const bool is_strict = (flags & JVM_ACC_STRICT) != 0;
|
||||
const bool is_synchronized = (flags & JVM_ACC_SYNCHRONIZED) != 0;
|
||||
const bool major_gte_15 = _major_version >= JAVA_1_5_VERSION;
|
||||
const bool major_gte_8 = _major_version >= JAVA_8_VERSION;
|
||||
const bool is_initializer = (name == vmSymbols::object_initializer_name());
|
||||
|
||||
bool is_illegal = false;
|
||||
|
||||
if (is_interface) {
|
||||
if (!is_abstract || !is_public || is_static || is_final ||
|
||||
is_native || (major_gte_15 && (is_synchronized || is_strict))) {
|
||||
if (!is_public || is_static || is_final || is_native ||
|
||||
((is_synchronized || is_strict) && major_gte_15 &&
|
||||
(!major_gte_8 || is_abstract)) ||
|
||||
(!major_gte_8 && !is_abstract)) {
|
||||
is_illegal = true;
|
||||
}
|
||||
} else { // not interface
|
||||
|
@ -151,6 +151,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
ClassLoaderData* loader_data,
|
||||
Handle protection_domain,
|
||||
Symbol* class_name,
|
||||
bool* has_default_methods,
|
||||
TRAPS);
|
||||
void record_defined_class_dependencies(instanceKlassHandle defined_klass, TRAPS);
|
||||
|
||||
@ -188,6 +189,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
Array<AnnotationArray*>** methods_annotations,
|
||||
Array<AnnotationArray*>** methods_parameter_annotations,
|
||||
Array<AnnotationArray*>** methods_default_annotations,
|
||||
bool* has_default_method,
|
||||
TRAPS);
|
||||
Array<int>* sort_methods(ClassLoaderData* loader_data,
|
||||
Array<Method*>* methods,
|
||||
|
1387
hotspot/src/share/vm/classfile/defaultMethods.cpp
Normal file
1387
hotspot/src/share/vm/classfile/defaultMethods.cpp
Normal file
File diff suppressed because it is too large
Load Diff
58
hotspot/src/share/vm/classfile/defaultMethods.hpp
Normal file
58
hotspot/src/share/vm/classfile/defaultMethods.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_CLASSFILE_DEFAULTMETHODS_HPP
|
||||
#define SHARE_VM_CLASSFILE_DEFAULTMETHODS_HPP
|
||||
|
||||
#include "runtime/handles.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/exceptions.hpp"
|
||||
|
||||
class InstanceKlass;
|
||||
class Symbol;
|
||||
class Method;
|
||||
|
||||
class DefaultMethods : AllStatic {
|
||||
public:
|
||||
|
||||
// Analyzes class and determines which default methods are inherited
|
||||
// from interfaces (and has no other implementation). For each method
|
||||
// (and each different signature the method could have), create an
|
||||
// "overpass" method that is an instance method that redirects to the
|
||||
// default method. Overpass methods are added to the methods lists for
|
||||
// the class.
|
||||
static void generate_default_methods(
|
||||
InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS);
|
||||
|
||||
|
||||
// Called during linking when an invokespecial to an direct interface
|
||||
// method is found. Selects and returns a method if there is a unique
|
||||
// default method in the 'super_iface' part of the hierarchy which is
|
||||
// also a candidate default for 'this_klass'. Otherwise throws an AME.
|
||||
static Method* find_super_default(
|
||||
Klass* this_klass, Klass* super_iface,
|
||||
Symbol* method_name, Symbol* method_sig, TRAPS);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_CLASSFILE_DEFAULTMETHODS_HPP
|
1272
hotspot/src/share/vm/classfile/genericSignatures.cpp
Normal file
1272
hotspot/src/share/vm/classfile/genericSignatures.cpp
Normal file
File diff suppressed because it is too large
Load Diff
467
hotspot/src/share/vm/classfile/genericSignatures.hpp
Normal file
467
hotspot/src/share/vm/classfile/genericSignatures.hpp
Normal file
@ -0,0 +1,467 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP
|
||||
#define SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP
|
||||
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "runtime/signature.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/resourceHash.hpp"
|
||||
|
||||
class stringStream;
|
||||
|
||||
namespace generic {
|
||||
|
||||
class Identifier;
|
||||
class ClassDescriptor;
|
||||
class MethodDescriptor;
|
||||
|
||||
class TypeParameter; // a formal type parameter declared in generic signatures
|
||||
class TypeArgument; // The "type value" passed to fill parameters in supertypes
|
||||
class TypeVariable; // A usage of a type parameter as a value
|
||||
/**
|
||||
* Example:
|
||||
*
|
||||
* <T, V> class Foo extends Bar<String> { int m(V v) {} }
|
||||
* ^^^^^^ ^^^^^^ ^^
|
||||
* type parameters type argument type variable
|
||||
*
|
||||
* Note that a type variable could be passed as an argument too:
|
||||
* <T, V> class Foo extends Bar<T> { int m(V v) {} }
|
||||
* ^^^
|
||||
* type argument's value is a type variable
|
||||
*/
|
||||
|
||||
|
||||
class Type;
|
||||
class ClassType;
|
||||
class ArrayType;
|
||||
class PrimitiveType;
|
||||
class Context;
|
||||
class DescriptorCache;
|
||||
|
||||
class DescriptorStream;
|
||||
|
||||
class Identifier : public ResourceObj {
|
||||
private:
|
||||
Symbol* _sym;
|
||||
int _begin;
|
||||
int _end;
|
||||
|
||||
public:
|
||||
Identifier(Symbol* sym, int begin, int end) :
|
||||
_sym(sym), _begin(begin), _end(end) {}
|
||||
|
||||
bool equals(Identifier* other);
|
||||
bool equals(Symbol* sym);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_on(outputStream* str) const;
|
||||
#endif // ndef PRODUCT
|
||||
};
|
||||
|
||||
class Descriptor : public ResourceObj {
|
||||
protected:
|
||||
GrowableArray<TypeParameter*> _type_parameters;
|
||||
ClassDescriptor* _outer_class;
|
||||
|
||||
Descriptor(GrowableArray<TypeParameter*>& params,
|
||||
ClassDescriptor* outer)
|
||||
: _type_parameters(params), _outer_class(outer) {}
|
||||
|
||||
public:
|
||||
|
||||
ClassDescriptor* outer_class() { return _outer_class; }
|
||||
void set_outer_class(ClassDescriptor* sig) { _outer_class = sig; }
|
||||
|
||||
virtual ClassDescriptor* as_class_signature() { return NULL; }
|
||||
virtual MethodDescriptor* as_method_signature() { return NULL; }
|
||||
|
||||
bool is_class_signature() { return as_class_signature() != NULL; }
|
||||
bool is_method_signature() { return as_method_signature() != NULL; }
|
||||
|
||||
GrowableArray<TypeParameter*>& type_parameters() {
|
||||
return _type_parameters;
|
||||
}
|
||||
|
||||
TypeParameter* find_type_parameter(Identifier* id, int* param_depth);
|
||||
|
||||
virtual void bind_variables_to_parameters() = 0;
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void print_on(outputStream* str) const = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
class ClassDescriptor : public Descriptor {
|
||||
private:
|
||||
ClassType* _super;
|
||||
GrowableArray<ClassType*> _interfaces;
|
||||
MethodDescriptor* _outer_method;
|
||||
|
||||
ClassDescriptor(GrowableArray<TypeParameter*>& ftp, ClassType* scs,
|
||||
GrowableArray<ClassType*>& sis, ClassDescriptor* outer_class = NULL,
|
||||
MethodDescriptor* outer_method = NULL)
|
||||
: Descriptor(ftp, outer_class), _super(scs), _interfaces(sis),
|
||||
_outer_method(outer_method) {}
|
||||
|
||||
static u2 get_outer_class_index(InstanceKlass* k, TRAPS);
|
||||
static ClassDescriptor* parse_generic_signature(Klass* k, Symbol* original_name, TRAPS);
|
||||
|
||||
public:
|
||||
|
||||
virtual ClassDescriptor* as_class_signature() { return this; }
|
||||
|
||||
MethodDescriptor* outer_method() { return _outer_method; }
|
||||
void set_outer_method(MethodDescriptor* m) { _outer_method = m; }
|
||||
|
||||
ClassType* super() { return _super; }
|
||||
ClassType* interface_desc(Symbol* sym);
|
||||
|
||||
static ClassDescriptor* parse_generic_signature(Klass* k, TRAPS);
|
||||
static ClassDescriptor* parse_generic_signature(Symbol* sym);
|
||||
|
||||
// For use in superclass chains in positions where this is no generic info
|
||||
static ClassDescriptor* placeholder(InstanceKlass* klass);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
|
||||
ClassDescriptor* canonicalize(Context* ctx);
|
||||
|
||||
// Linking sets the position index in any contained TypeVariable type
|
||||
// to correspond to the location of that identifier in the formal type
|
||||
// parameters.
|
||||
void bind_variables_to_parameters();
|
||||
};
|
||||
|
||||
class MethodDescriptor : public Descriptor {
|
||||
private:
|
||||
GrowableArray<Type*> _parameters;
|
||||
Type* _return_type;
|
||||
GrowableArray<Type*> _throws;
|
||||
|
||||
MethodDescriptor(GrowableArray<TypeParameter*>& ftp, ClassDescriptor* outer,
|
||||
GrowableArray<Type*>& sigs, Type* rt, GrowableArray<Type*>& throws)
|
||||
: Descriptor(ftp, outer), _parameters(sigs), _return_type(rt),
|
||||
_throws(throws) {}
|
||||
|
||||
public:
|
||||
|
||||
static MethodDescriptor* parse_generic_signature(Method* m, ClassDescriptor* outer);
|
||||
static MethodDescriptor* parse_generic_signature(Symbol* sym, ClassDescriptor* outer);
|
||||
|
||||
MethodDescriptor* as_method_signature() { return this; }
|
||||
|
||||
// Performs generic analysis on the method parameters to determine
|
||||
// if both methods refer to the same argument types.
|
||||
bool covariant_match(MethodDescriptor* other, Context* ctx);
|
||||
|
||||
// Returns a new method descriptor with all generic variables
|
||||
// removed and replaced with whatever is indicated using the Context.
|
||||
MethodDescriptor* canonicalize(Context* ctx);
|
||||
|
||||
void bind_variables_to_parameters();
|
||||
|
||||
#ifndef PRODUCT
|
||||
TempNewSymbol reify_signature(Context* ctx, TRAPS);
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class TypeParameter : public ResourceObj {
|
||||
private:
|
||||
Identifier* _identifier;
|
||||
ClassType* _class_bound;
|
||||
GrowableArray<ClassType*> _interface_bounds;
|
||||
|
||||
// The position is the ordinal location of the parameter within the
|
||||
// formal parameter list (excluding outer classes). It is only set for
|
||||
// formal type parameters that are associated with a class -- method
|
||||
// type parameters are left as -1. When resolving a generic variable to
|
||||
// find the actual type, this index is used to access the generic type
|
||||
// argument in the provided context object.
|
||||
int _position; // Assigned during variable linking
|
||||
|
||||
TypeParameter(Identifier* id, ClassType* class_bound,
|
||||
GrowableArray<ClassType*>& interface_bounds) :
|
||||
_identifier(id), _class_bound(class_bound),
|
||||
_interface_bounds(interface_bounds), _position(-1) {}
|
||||
|
||||
public:
|
||||
static TypeParameter* parse_generic_signature(DescriptorStream* str);
|
||||
|
||||
ClassType* bound();
|
||||
int position() { return _position; }
|
||||
|
||||
void bind_variables_to_parameters(Descriptor* sig, int position);
|
||||
Identifier* identifier() { return _identifier; }
|
||||
|
||||
Type* resolve(Context* ctx, int inner_depth, int ctx_depth);
|
||||
TypeParameter* canonicalize(Context* ctx, int ctx_depth);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class Type : public ResourceObj {
|
||||
public:
|
||||
static Type* parse_generic_signature(DescriptorStream* str);
|
||||
|
||||
virtual ClassType* as_class() { return NULL; }
|
||||
virtual TypeVariable* as_variable() { return NULL; }
|
||||
virtual ArrayType* as_array() { return NULL; }
|
||||
virtual PrimitiveType* as_primitive() { return NULL; }
|
||||
|
||||
virtual bool covariant_match(Type* gt, Context* ctx) = 0;
|
||||
virtual Type* canonicalize(Context* ctx, int ctx_depth) = 0;
|
||||
|
||||
virtual void bind_variables_to_parameters(Descriptor* sig) = 0;
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void reify_signature(stringStream* ss, Context* ctx) = 0;
|
||||
virtual void print_on(outputStream* str) const = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
class ClassType : public Type {
|
||||
friend class ClassDescriptor;
|
||||
protected:
|
||||
Identifier* _identifier;
|
||||
GrowableArray<TypeArgument*> _type_arguments;
|
||||
ClassType* _outer_class;
|
||||
|
||||
ClassType(Identifier* identifier,
|
||||
GrowableArray<TypeArgument*>& args,
|
||||
ClassType* outer)
|
||||
: _identifier(identifier), _type_arguments(args), _outer_class(outer) {}
|
||||
|
||||
// Returns true if there are inner classes to read
|
||||
static Identifier* parse_generic_signature_simple(
|
||||
GrowableArray<TypeArgument*>* args,
|
||||
bool* has_inner, DescriptorStream* str);
|
||||
|
||||
static ClassType* parse_generic_signature(ClassType* outer,
|
||||
DescriptorStream* str);
|
||||
static ClassType* from_symbol(Symbol* sym);
|
||||
|
||||
public:
|
||||
ClassType* as_class() { return this; }
|
||||
|
||||
static ClassType* parse_generic_signature(DescriptorStream* str);
|
||||
static ClassType* java_lang_Object();
|
||||
|
||||
Identifier* identifier() { return _identifier; }
|
||||
int type_arguments_length() { return _type_arguments.length(); }
|
||||
TypeArgument* type_argument_at(int i);
|
||||
|
||||
virtual ClassType* outer_class() { return _outer_class; }
|
||||
|
||||
bool covariant_match(Type* gt, Context* ctx);
|
||||
ClassType* canonicalize(Context* ctx, int context_depth);
|
||||
|
||||
void bind_variables_to_parameters(Descriptor* sig);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void reify_signature(stringStream* ss, Context* ctx);
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class TypeVariable : public Type {
|
||||
private:
|
||||
Identifier* _id;
|
||||
TypeParameter* _parameter; // assigned during linking
|
||||
|
||||
// how many steps "out" from inner classes, -1 if method
|
||||
int _inner_depth;
|
||||
|
||||
TypeVariable(Identifier* id)
|
||||
: _id(id), _parameter(NULL), _inner_depth(0) {}
|
||||
|
||||
public:
|
||||
TypeVariable* as_variable() { return this; }
|
||||
|
||||
static TypeVariable* parse_generic_signature(DescriptorStream* str);
|
||||
|
||||
Identifier* identifier() { return _id; }
|
||||
TypeParameter* parameter() { return _parameter; }
|
||||
int inner_depth() { return _inner_depth; }
|
||||
|
||||
void bind_variables_to_parameters(Descriptor* sig);
|
||||
|
||||
Type* resolve(Context* ctx, int ctx_depth);
|
||||
bool covariant_match(Type* gt, Context* ctx);
|
||||
Type* canonicalize(Context* ctx, int ctx_depth);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void reify_signature(stringStream* ss, Context* ctx);
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class ArrayType : public Type {
|
||||
private:
|
||||
Type* _base;
|
||||
|
||||
ArrayType(Type* base) : _base(base) {}
|
||||
|
||||
public:
|
||||
ArrayType* as_array() { return this; }
|
||||
|
||||
static ArrayType* parse_generic_signature(DescriptorStream* str);
|
||||
|
||||
bool covariant_match(Type* gt, Context* ctx);
|
||||
ArrayType* canonicalize(Context* ctx, int ctx_depth);
|
||||
|
||||
void bind_variables_to_parameters(Descriptor* sig);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void reify_signature(stringStream* ss, Context* ctx);
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class PrimitiveType : public Type {
|
||||
friend class Type;
|
||||
private:
|
||||
char _type; // includes V for void
|
||||
|
||||
PrimitiveType(char& type) : _type(type) {}
|
||||
|
||||
public:
|
||||
PrimitiveType* as_primitive() { return this; }
|
||||
|
||||
bool covariant_match(Type* gt, Context* ctx);
|
||||
PrimitiveType* canonicalize(Context* ctx, int ctx_depth);
|
||||
|
||||
void bind_variables_to_parameters(Descriptor* sig);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void reify_signature(stringStream* ss, Context* ctx);
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class TypeArgument : public ResourceObj {
|
||||
private:
|
||||
Type* _lower_bound;
|
||||
Type* _upper_bound; // may be null or == _lower_bound
|
||||
|
||||
TypeArgument(Type* lower_bound, Type* upper_bound)
|
||||
: _lower_bound(lower_bound), _upper_bound(upper_bound) {}
|
||||
|
||||
public:
|
||||
|
||||
static TypeArgument* parse_generic_signature(DescriptorStream* str);
|
||||
|
||||
Type* lower_bound() { return _lower_bound; }
|
||||
Type* upper_bound() { return _upper_bound; }
|
||||
|
||||
void bind_variables_to_parameters(Descriptor* sig);
|
||||
TypeArgument* canonicalize(Context* ctx, int ctx_depth);
|
||||
|
||||
bool covariant_match(TypeArgument* a, Context* ctx);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
class Context : public ResourceObj {
|
||||
private:
|
||||
DescriptorCache* _cache;
|
||||
GrowableArray<ClassType*> _type_arguments;
|
||||
|
||||
void reset_to_mark(int size);
|
||||
|
||||
public:
|
||||
// When this object goes out of scope or 'destroy' is
|
||||
// called, then the application of the type to the
|
||||
// context is wound-back (unless it's been deactivated).
|
||||
class Mark : public StackObj {
|
||||
private:
|
||||
mutable Context* _context;
|
||||
int _marked_size;
|
||||
|
||||
bool is_active() const { return _context != NULL; }
|
||||
void deactivate() const { _context = NULL; }
|
||||
|
||||
public:
|
||||
Mark() : _context(NULL), _marked_size(0) {}
|
||||
Mark(Context* ctx, int sz) : _context(ctx), _marked_size(sz) {}
|
||||
Mark(const Mark& m) : _context(m._context), _marked_size(m._marked_size) {
|
||||
m.deactivate(); // Ownership is transferred
|
||||
}
|
||||
|
||||
Mark& operator=(const Mark& cm) {
|
||||
destroy();
|
||||
_context = cm._context;
|
||||
_marked_size = cm._marked_size;
|
||||
cm.deactivate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void destroy();
|
||||
~Mark() { destroy(); }
|
||||
};
|
||||
|
||||
Context(DescriptorCache* cache) : _cache(cache) {}
|
||||
|
||||
Mark mark() { return Mark(this, _type_arguments.length()); }
|
||||
void apply_type_arguments(InstanceKlass* current, InstanceKlass* super,TRAPS);
|
||||
|
||||
ClassType* at_depth(int i) const;
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains a cache of descriptors for classes and methods so they can be
|
||||
* looked-up instead of reparsing each time they are needed.
|
||||
*/
|
||||
class DescriptorCache : public ResourceObj {
|
||||
private:
|
||||
ResourceHashtable<InstanceKlass*, ClassDescriptor*> _class_descriptors;
|
||||
ResourceHashtable<Method*, MethodDescriptor*> _method_descriptors;
|
||||
|
||||
public:
|
||||
ClassDescriptor* descriptor_for(InstanceKlass* ikh, TRAPS);
|
||||
|
||||
MethodDescriptor* descriptor_for(Method* mh, ClassDescriptor* cd, TRAPS);
|
||||
// Class descriptor derived from method holder
|
||||
MethodDescriptor* descriptor_for(Method* mh, TRAPS);
|
||||
};
|
||||
|
||||
} // namespace generic
|
||||
|
||||
#endif // SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP
|
||||
|
@ -1156,7 +1156,7 @@ void java_lang_Throwable::print(Handle throwable, outputStream* st) {
|
||||
// Print stack trace element to resource allocated buffer
|
||||
char* java_lang_Throwable::print_stack_element_to_buffer(Method* method, int bci) {
|
||||
// Get strings and string lengths
|
||||
InstanceKlass* klass = InstanceKlass::cast(method->method_holder());
|
||||
InstanceKlass* klass = method->method_holder();
|
||||
const char* klass_name = klass->external_name();
|
||||
int buf_len = (int)strlen(klass_name);
|
||||
char* source_file_name;
|
||||
@ -1747,14 +1747,14 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) {
|
||||
Handle element = ik->allocate_instance_handle(CHECK_0);
|
||||
// Fill in class name
|
||||
ResourceMark rm(THREAD);
|
||||
const char* str = InstanceKlass::cast(method->method_holder())->external_name();
|
||||
const char* str = method->method_holder()->external_name();
|
||||
oop classname = StringTable::intern((char*) str, CHECK_0);
|
||||
java_lang_StackTraceElement::set_declaringClass(element(), classname);
|
||||
// Fill in method name
|
||||
oop methodname = StringTable::intern(method->name(), CHECK_0);
|
||||
java_lang_StackTraceElement::set_methodName(element(), methodname);
|
||||
// Fill in source file name
|
||||
Symbol* source = InstanceKlass::cast(method->method_holder())->source_file_name();
|
||||
Symbol* source = method->method_holder()->source_file_name();
|
||||
if (ShowHiddenFrames && source == NULL)
|
||||
source = vmSymbols::unknown_class_name();
|
||||
oop filename = StringTable::intern(source, CHECK_0);
|
||||
|
@ -137,6 +137,7 @@ class SymbolPropertyTable;
|
||||
/* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \
|
||||
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
|
||||
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
||||
do_klass(lambda_MagicLambdaImpl_klass, java_lang_invoke_MagicLambdaImpl, Opt ) \
|
||||
do_klass(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt ) \
|
||||
do_klass(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \
|
||||
do_klass(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \
|
||||
|
@ -446,7 +446,7 @@ void ErrorContext::location_details(outputStream* ss, Method* method) const {
|
||||
bytecode_name = "<illegal>";
|
||||
}
|
||||
}
|
||||
InstanceKlass* ik = InstanceKlass::cast(method->method_holder());
|
||||
InstanceKlass* ik = method->method_holder();
|
||||
ss->indent().print_cr("Location:");
|
||||
streamIndentor si2(ss);
|
||||
ss->indent().print_cr("%s.%s%s @%d: %s",
|
||||
@ -555,9 +555,10 @@ void ClassVerifier::verify_class(TRAPS) {
|
||||
if (was_recursively_verified()) return;
|
||||
|
||||
Method* m = methods->at(index);
|
||||
if (m->is_native() || m->is_abstract()) {
|
||||
if (m->is_native() || m->is_abstract() || m->is_overpass()) {
|
||||
// If m is native or abstract, skip it. It is checked in class file
|
||||
// parser that methods do not override a final method.
|
||||
// parser that methods do not override a final method. Overpass methods
|
||||
// are trusted since the VM generates them.
|
||||
continue;
|
||||
}
|
||||
verify_method(methodHandle(THREAD, m), CHECK_VERIFY(this));
|
||||
@ -1849,7 +1850,7 @@ void ClassVerifier::verify_cp_index(
|
||||
if ((index <= 0) || (index >= nconstants)) {
|
||||
verify_error(ErrorContext::bad_cp_index(bci, index),
|
||||
"Illegal constant pool index %d in class %s",
|
||||
index, InstanceKlass::cast(cp->pool_holder())->external_name());
|
||||
index, cp->pool_holder()->external_name());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1868,7 +1869,7 @@ void ClassVerifier::verify_cp_type(
|
||||
if ((types & (1 << tag)) == 0) {
|
||||
verify_error(ErrorContext::bad_cp_index(bci, index),
|
||||
"Illegal type at constant pool entry %d in class %s",
|
||||
index, InstanceKlass::cast(cp->pool_holder())->external_name());
|
||||
index, cp->pool_holder()->external_name());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1880,7 +1881,7 @@ void ClassVerifier::verify_cp_class_type(
|
||||
if (!tag.is_klass() && !tag.is_unresolved_klass()) {
|
||||
verify_error(ErrorContext::bad_cp_index(bci, index),
|
||||
"Illegal type at constant pool entry %d in class %s",
|
||||
index, InstanceKlass::cast(cp->pool_holder())->external_name());
|
||||
index, cp->pool_holder()->external_name());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2304,11 +2305,21 @@ void ClassVerifier::verify_invoke_instructions(
|
||||
// Make sure the constant pool item is the right type
|
||||
u2 index = bcs->get_index_u2();
|
||||
Bytecodes::Code opcode = bcs->raw_code();
|
||||
unsigned int types = (opcode == Bytecodes::_invokeinterface
|
||||
? 1 << JVM_CONSTANT_InterfaceMethodref
|
||||
: opcode == Bytecodes::_invokedynamic
|
||||
? 1 << JVM_CONSTANT_InvokeDynamic
|
||||
: 1 << JVM_CONSTANT_Methodref);
|
||||
unsigned int types;
|
||||
switch (opcode) {
|
||||
case Bytecodes::_invokeinterface:
|
||||
types = 1 << JVM_CONSTANT_InterfaceMethodref;
|
||||
break;
|
||||
case Bytecodes::_invokedynamic:
|
||||
types = 1 << JVM_CONSTANT_InvokeDynamic;
|
||||
break;
|
||||
case Bytecodes::_invokespecial:
|
||||
types = (1 << JVM_CONSTANT_InterfaceMethodref) |
|
||||
(1 << JVM_CONSTANT_Methodref);
|
||||
break;
|
||||
default:
|
||||
types = 1 << JVM_CONSTANT_Methodref;
|
||||
}
|
||||
verify_cp_type(bcs->bci(), index, cp, types, CHECK_VERIFY(this));
|
||||
|
||||
// Get method name and signature
|
||||
|
@ -507,7 +507,7 @@ static vmIntrinsics::ID match_method_with_klass(Method* m, Symbol* mk) {
|
||||
}
|
||||
|
||||
void vmIntrinsics::verify_method(ID actual_id, Method* m) {
|
||||
Symbol* mk = Klass::cast(m->method_holder())->name();
|
||||
Symbol* mk = m->method_holder()->name();
|
||||
ID declared_id = match_method_with_klass(m, mk);
|
||||
|
||||
if (declared_id == actual_id) return; // success
|
||||
|
@ -115,6 +115,7 @@
|
||||
/* Java runtime version access */ \
|
||||
template(sun_misc_Version, "sun/misc/Version") \
|
||||
template(java_runtime_name_name, "java_runtime_name") \
|
||||
template(java_runtime_version_name, "java_runtime_version") \
|
||||
\
|
||||
/* class file format tags */ \
|
||||
template(tag_source_file, "SourceFile") \
|
||||
@ -258,6 +259,7 @@
|
||||
template(java_lang_invoke_DontInline_signature, "Ljava/lang/invoke/DontInline;") \
|
||||
template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \
|
||||
template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;") \
|
||||
template(java_lang_invoke_MagicLambdaImpl, "java/lang/invoke/MagicLambdaImpl") \
|
||||
/* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \
|
||||
template(findMethodHandleType_name, "findMethodHandleType") \
|
||||
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \
|
||||
|
@ -191,8 +191,8 @@ void CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecod
|
||||
int index = klassItable::compute_itable_index(call_info->resolved_method()());
|
||||
entry = VtableStubs::create_stub(false, index, method());
|
||||
assert(entry != NULL, "entry not computed");
|
||||
Klass* k = call_info->resolved_method()->method_holder();
|
||||
assert(Klass::cast(k)->is_interface(), "sanity check");
|
||||
InstanceKlass* k = call_info->resolved_method()->method_holder();
|
||||
assert(k->is_interface(), "sanity check");
|
||||
InlineCacheBuffer::create_transition_stub(this, k, entry);
|
||||
} else {
|
||||
// Can be different than method->vtable_index(), due to package-private etc.
|
||||
|
@ -829,7 +829,7 @@ class ClassHierarchyWalker {
|
||||
}
|
||||
if ( !Dependencies::is_concrete_method(lm)
|
||||
&& !Dependencies::is_concrete_method(m)
|
||||
&& Klass::cast(lm->method_holder())->is_subtype_of(m->method_holder()))
|
||||
&& lm->method_holder()->is_subtype_of(m->method_holder()))
|
||||
// Method m is overridden by lm, but both are non-concrete.
|
||||
return true;
|
||||
}
|
||||
@ -1160,7 +1160,11 @@ bool Dependencies::is_concrete_method(Method* m) {
|
||||
|
||||
// We could also return false if m does not yet appear to be
|
||||
// executed, if the VM version supports this distinction also.
|
||||
return !m->is_abstract();
|
||||
return !m->is_abstract() &&
|
||||
!InstanceKlass::cast(m->method_holder())->is_interface();
|
||||
// TODO: investigate whether default methods should be
|
||||
// considered as "concrete" in this situation. For now they
|
||||
// are not.
|
||||
}
|
||||
|
||||
|
||||
|
@ -1263,7 +1263,7 @@ void nmethod::invalidate_osr_method() {
|
||||
assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod");
|
||||
// Remove from list of active nmethods
|
||||
if (method() != NULL)
|
||||
InstanceKlass::cast(method()->method_holder())->remove_osr_nmethod(this);
|
||||
method()->method_holder()->remove_osr_nmethod(this);
|
||||
// Set entry as invalid
|
||||
_entry_bci = InvalidOSREntryBci;
|
||||
}
|
||||
|
@ -1051,7 +1051,7 @@ void CompileBroker::compile_method_base(methodHandle method,
|
||||
guarantee(!method->is_abstract(), "cannot compile abstract methods");
|
||||
assert(method->method_holder()->oop_is_instance(),
|
||||
"sanity check");
|
||||
assert(!InstanceKlass::cast(method->method_holder())->is_not_initialized(),
|
||||
assert(!method->method_holder()->is_not_initialized(),
|
||||
"method holder must be initialized");
|
||||
assert(!method->is_method_handle_intrinsic(), "do not enqueue these guys");
|
||||
|
||||
@ -1206,7 +1206,7 @@ nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci,
|
||||
assert(method->method_holder()->oop_is_instance(), "not an instance method");
|
||||
assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range");
|
||||
assert(!method->is_abstract() && (osr_bci == InvocationEntryBci || !method->is_native()), "cannot compile abstract/native methods");
|
||||
assert(!InstanceKlass::cast(method->method_holder())->is_not_initialized(), "method holder must be initialized");
|
||||
assert(!method->method_holder()->is_not_initialized(), "method holder must be initialized");
|
||||
|
||||
if (!TieredCompilation) {
|
||||
comp_level = CompLevel_highest_tier;
|
||||
|
@ -67,7 +67,7 @@ class MethodMatcher : public CHeapObj<mtCompiler> {
|
||||
|
||||
// utility method
|
||||
MethodMatcher* find(methodHandle method) {
|
||||
Symbol* class_name = Klass::cast(method->method_holder())->name();
|
||||
Symbol* class_name = method->method_holder()->name();
|
||||
Symbol* method_name = method->name();
|
||||
for (MethodMatcher* current = this; current != NULL; current = current->_next) {
|
||||
if (match(class_name, current->class_name(), current->_class_mode) &&
|
||||
@ -624,7 +624,7 @@ void CompilerOracle::append_exclude_to_file(methodHandle method) {
|
||||
assert(has_command_file(), "command file must be specified");
|
||||
fileStream stream(fopen(cc_file(), "at"));
|
||||
stream.print("exclude ");
|
||||
Klass::cast(method->method_holder())->name()->print_symbol_on(&stream);
|
||||
method->method_holder()->name()->print_symbol_on(&stream);
|
||||
stream.print(".");
|
||||
method->name()->print_symbol_on(&stream);
|
||||
method->signature()->print_symbol_on(&stream);
|
||||
|
@ -55,16 +55,18 @@ void* Disassembler::_library = NULL;
|
||||
bool Disassembler::_tried_to_load_library = false;
|
||||
|
||||
// This routine is in the shared library:
|
||||
Disassembler::decode_func_virtual Disassembler::_decode_instructions_virtual = NULL;
|
||||
Disassembler::decode_func Disassembler::_decode_instructions = NULL;
|
||||
|
||||
static const char hsdis_library_name[] = "hsdis-"HOTSPOT_LIB_ARCH;
|
||||
static const char decode_instructions_name[] = "decode_instructions_virtual";
|
||||
|
||||
static const char decode_instructions_virtual_name[] = "decode_instructions_virtual";
|
||||
static const char decode_instructions_name[] = "decode_instructions";
|
||||
static bool use_new_version = true;
|
||||
#define COMMENT_COLUMN 40 LP64_ONLY(+8) /*could be an option*/
|
||||
#define BYTES_COMMENT ";..." /* funky byte display comment */
|
||||
|
||||
bool Disassembler::load_library() {
|
||||
if (_decode_instructions != NULL) {
|
||||
if (_decode_instructions_virtual != NULL || _decode_instructions != NULL) {
|
||||
// Already succeeded.
|
||||
return true;
|
||||
}
|
||||
@ -123,11 +125,19 @@ bool Disassembler::load_library() {
|
||||
_library = os::dll_load(buf, ebuf, sizeof ebuf);
|
||||
}
|
||||
if (_library != NULL) {
|
||||
_decode_instructions_virtual = CAST_TO_FN_PTR(Disassembler::decode_func_virtual,
|
||||
os::dll_lookup(_library, decode_instructions_virtual_name));
|
||||
}
|
||||
if (_decode_instructions_virtual == NULL) {
|
||||
// could not spot in new version, try old version
|
||||
_decode_instructions = CAST_TO_FN_PTR(Disassembler::decode_func,
|
||||
os::dll_lookup(_library, decode_instructions_name));
|
||||
use_new_version = false;
|
||||
} else {
|
||||
use_new_version = true;
|
||||
}
|
||||
_tried_to_load_library = true;
|
||||
if (_decode_instructions == NULL) {
|
||||
if (_decode_instructions_virtual == NULL && _decode_instructions == NULL) {
|
||||
tty->print_cr("Could not load %s; %s; %s", buf,
|
||||
((_library != NULL)
|
||||
? "entry point is missing"
|
||||
@ -450,17 +460,31 @@ address decode_env::decode_instructions(address start, address end) {
|
||||
// This is mainly for debugging the library itself.
|
||||
FILE* out = stdout;
|
||||
FILE* xmlout = (_print_raw > 1 ? out : NULL);
|
||||
return (address)
|
||||
(*Disassembler::_decode_instructions)((uintptr_t)start, (uintptr_t)end,
|
||||
start, end - start,
|
||||
return use_new_version ?
|
||||
(address)
|
||||
(*Disassembler::_decode_instructions_virtual)((uintptr_t)start, (uintptr_t)end,
|
||||
start, end - start,
|
||||
NULL, (void*) xmlout,
|
||||
NULL, (void*) out,
|
||||
options(), 0/*nice new line*/)
|
||||
:
|
||||
(address)
|
||||
(*Disassembler::_decode_instructions)(start, end,
|
||||
NULL, (void*) xmlout,
|
||||
NULL, (void*) out,
|
||||
options());
|
||||
}
|
||||
|
||||
return (address)
|
||||
(*Disassembler::_decode_instructions)((uintptr_t)start, (uintptr_t)end,
|
||||
start, end - start,
|
||||
return use_new_version ?
|
||||
(address)
|
||||
(*Disassembler::_decode_instructions_virtual)((uintptr_t)start, (uintptr_t)end,
|
||||
start, end - start,
|
||||
&event_to_env, (void*) this,
|
||||
&printf_to_env, (void*) this,
|
||||
options(), 0/*nice new line*/)
|
||||
:
|
||||
(address)
|
||||
(*Disassembler::_decode_instructions)(start, end,
|
||||
&event_to_env, (void*) this,
|
||||
&printf_to_env, (void*) this,
|
||||
options());
|
||||
|
@ -49,8 +49,16 @@ class Disassembler {
|
||||
friend class decode_env;
|
||||
private:
|
||||
// this is the type of the dll entry point:
|
||||
typedef void* (*decode_func)(uintptr_t start_va, uintptr_t end_va,
|
||||
typedef void* (*decode_func_virtual)(uintptr_t start_va, uintptr_t end_va,
|
||||
unsigned char* buffer, uintptr_t length,
|
||||
void* (*event_callback)(void*, const char*, void*),
|
||||
void* event_stream,
|
||||
int (*printf_callback)(void*, const char*, ...),
|
||||
void* printf_stream,
|
||||
const char* options,
|
||||
int newline);
|
||||
// this is the type of the dll entry point for old version:
|
||||
typedef void* (*decode_func)(void* start_va, void* end_va,
|
||||
void* (*event_callback)(void*, const char*, void*),
|
||||
void* event_stream,
|
||||
int (*printf_callback)(void*, const char*, ...),
|
||||
@ -61,6 +69,7 @@ class Disassembler {
|
||||
// bailout
|
||||
static bool _tried_to_load_library;
|
||||
// points to the decode function.
|
||||
static decode_func_virtual _decode_instructions_virtual;
|
||||
static decode_func _decode_instructions;
|
||||
// tries to load library and return whether it succedded.
|
||||
static bool load_library();
|
||||
@ -85,7 +94,9 @@ class Disassembler {
|
||||
|
||||
public:
|
||||
static bool can_decode() {
|
||||
return (_decode_instructions != NULL) || load_library();
|
||||
return (_decode_instructions_virtual != NULL) ||
|
||||
(_decode_instructions != NULL) ||
|
||||
load_library();
|
||||
}
|
||||
static void decode(CodeBlob *cb, outputStream* st = NULL);
|
||||
static void decode(nmethod* nm, outputStream* st = NULL);
|
||||
|
@ -320,6 +320,7 @@ class AbstractInterpreterGenerator: public StackObj {
|
||||
void bang_stack_shadow_pages(bool native_call);
|
||||
|
||||
void generate_all();
|
||||
void initialize_method_handle_entries();
|
||||
|
||||
public:
|
||||
AbstractInterpreterGenerator(StubQueue* _code);
|
||||
|
@ -235,10 +235,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// JavaStack Implementation
|
||||
#define MORE_STACK(count) \
|
||||
(topOfStack -= ((count) * Interpreter::stackElementWords))
|
||||
|
||||
|
||||
#define UPDATE_PC(opsize) {pc += opsize; }
|
||||
/*
|
||||
@ -575,7 +571,7 @@ BytecodeInterpreter::run(interpreterState istate) {
|
||||
|
||||
/* 0xE0 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
||||
/* 0xE4 */ &&opc_default, &&opc_fast_aldc, &&opc_fast_aldc_w, &&opc_return_register_finalizer,
|
||||
/* 0xE8 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
||||
/* 0xE8 */ &&opc_invokehandle,&&opc_default, &&opc_default, &&opc_default,
|
||||
/* 0xEC */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
||||
|
||||
/* 0xF0 */ &&opc_default, &&opc_default, &&opc_default, &&opc_default,
|
||||
@ -1773,7 +1769,7 @@ run:
|
||||
|
||||
oop obj;
|
||||
if ((Bytecodes::Code)opcode == Bytecodes::_getstatic) {
|
||||
Klass* k = (Klass*) cache->f1();
|
||||
Klass* k = cache->f1_as_klass();
|
||||
obj = k->java_mirror();
|
||||
MORE_STACK(1); // Assume single slot push
|
||||
} else {
|
||||
@ -1885,7 +1881,7 @@ run:
|
||||
--count;
|
||||
}
|
||||
if ((Bytecodes::Code)opcode == Bytecodes::_putstatic) {
|
||||
Klass* k = (Klass*) cache->f1();
|
||||
Klass* k = cache->f1_as_klass();
|
||||
obj = k->java_mirror();
|
||||
} else {
|
||||
--count;
|
||||
@ -2190,6 +2186,7 @@ run:
|
||||
}
|
||||
|
||||
CASE(_invokedynamic): {
|
||||
|
||||
if (!EnableInvokeDynamic) {
|
||||
// We should not encounter this bytecode if !EnableInvokeDynamic.
|
||||
// The verifier will stop it. However, if we get past the verifier,
|
||||
@ -2199,30 +2196,68 @@ run:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
int index = Bytes::get_native_u4(pc+1);
|
||||
u4 index = Bytes::get_native_u4(pc+1);
|
||||
ConstantPoolCacheEntry* cache = cp->constant_pool()->invokedynamic_cp_cache_entry_at(index);
|
||||
|
||||
// We are resolved if the resolved_references field contains a non-null object (CallSite, etc.)
|
||||
// This kind of CP cache entry does not need to match the flags byte, because
|
||||
// there is a 1-1 relation between bytecode type and CP entry type.
|
||||
ConstantPool* constants = METHOD->constants();
|
||||
oop result = constants->resolved_references()->obj_at(index);
|
||||
if (result == NULL) {
|
||||
if (! cache->is_resolved((Bytecodes::Code) opcode)) {
|
||||
CALL_VM(InterpreterRuntime::resolve_invokedynamic(THREAD),
|
||||
handle_exception);
|
||||
result = THREAD->vm_result();
|
||||
cache = cp->constant_pool()->invokedynamic_cp_cache_entry_at(index);
|
||||
}
|
||||
|
||||
VERIFY_OOP(result);
|
||||
oop method_handle = java_lang_invoke_CallSite::target(result);
|
||||
CHECK_NULL(method_handle);
|
||||
Method* method = cache->f1_as_method();
|
||||
VERIFY_OOP(method);
|
||||
|
||||
istate->set_msg(call_method_handle);
|
||||
istate->set_callee((Method*) method_handle);
|
||||
if (cache->has_appendix()) {
|
||||
ConstantPool* constants = METHOD->constants();
|
||||
SET_STACK_OBJECT(cache->appendix_if_resolved(constants), 0);
|
||||
MORE_STACK(1);
|
||||
}
|
||||
|
||||
istate->set_msg(call_method);
|
||||
istate->set_callee(method);
|
||||
istate->set_callee_entry_point(method->from_interpreted_entry());
|
||||
istate->set_bcp_advance(5);
|
||||
|
||||
UPDATE_PC_AND_RETURN(0); // I'll be back...
|
||||
}
|
||||
|
||||
CASE(_invokehandle): {
|
||||
|
||||
if (!EnableInvokeDynamic) {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
u2 index = Bytes::get_native_u2(pc+1);
|
||||
ConstantPoolCacheEntry* cache = cp->entry_at(index);
|
||||
|
||||
if (! cache->is_resolved((Bytecodes::Code) opcode)) {
|
||||
CALL_VM(InterpreterRuntime::resolve_invokehandle(THREAD),
|
||||
handle_exception);
|
||||
cache = cp->entry_at(index);
|
||||
}
|
||||
|
||||
Method* method = cache->f1_as_method();
|
||||
|
||||
VERIFY_OOP(method);
|
||||
|
||||
if (cache->has_appendix()) {
|
||||
ConstantPool* constants = METHOD->constants();
|
||||
SET_STACK_OBJECT(cache->appendix_if_resolved(constants), 0);
|
||||
MORE_STACK(1);
|
||||
}
|
||||
|
||||
istate->set_msg(call_method);
|
||||
istate->set_callee(method);
|
||||
istate->set_callee_entry_point(method->from_interpreted_entry());
|
||||
istate->set_bcp_advance(3);
|
||||
|
||||
UPDATE_PC_AND_RETURN(0); // I'll be back...
|
||||
}
|
||||
|
||||
CASE(_invokeinterface): {
|
||||
u2 index = Bytes::get_native_u2(pc+1);
|
||||
|
||||
|
@ -50,6 +50,10 @@
|
||||
|
||||
#ifdef CC_INTERP
|
||||
|
||||
// JavaStack Implementation
|
||||
#define MORE_STACK(count) \
|
||||
(topOfStack -= ((count) * Interpreter::stackElementWords))
|
||||
|
||||
// CVM definitions find hotspot equivalents...
|
||||
|
||||
union VMJavaVal64 {
|
||||
@ -107,7 +111,6 @@ public:
|
||||
rethrow_exception, // unwinding and throwing exception
|
||||
// requests to frame manager from C++ interpreter
|
||||
call_method, // request for new frame from interpreter, manager responds with method_entry
|
||||
call_method_handle, // like the above, except the callee is a method handle
|
||||
return_from_method, // request from interpreter to unwind, manager responds with method_continue
|
||||
more_monitors, // need a new monitor
|
||||
throwing_exception, // unwind stack and rethrow
|
||||
|
@ -117,7 +117,6 @@ void CppInterpreterGenerator::generate_all() {
|
||||
method_entry(empty);
|
||||
method_entry(accessor);
|
||||
method_entry(abstract);
|
||||
method_entry(method_handle);
|
||||
method_entry(java_lang_math_sin );
|
||||
method_entry(java_lang_math_cos );
|
||||
method_entry(java_lang_math_tan );
|
||||
@ -125,7 +124,12 @@ void CppInterpreterGenerator::generate_all() {
|
||||
method_entry(java_lang_math_sqrt );
|
||||
method_entry(java_lang_math_log );
|
||||
method_entry(java_lang_math_log10 );
|
||||
method_entry(java_lang_math_pow );
|
||||
method_entry(java_lang_math_exp );
|
||||
method_entry(java_lang_ref_reference_get);
|
||||
|
||||
initialize_method_handle_entries();
|
||||
|
||||
Interpreter::_native_entry_begin = Interpreter::code()->code_end();
|
||||
method_entry(native);
|
||||
method_entry(native_synchronized);
|
||||
|
@ -464,3 +464,11 @@ void AbstractInterpreterGenerator::bang_stack_shadow_pages(bool native_call) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractInterpreterGenerator::initialize_method_handle_entries() {
|
||||
// method handle entry kinds are generated later in MethodHandlesAdapterGenerator::generate:
|
||||
for (int i = Interpreter::method_handle_invoke_FIRST; i <= Interpreter::method_handle_invoke_LAST; i++) {
|
||||
Interpreter::MethodKind kind = (Interpreter::MethodKind) i;
|
||||
Interpreter::_entry_table[kind] = Interpreter::_entry_table[Interpreter::abstract];
|
||||
}
|
||||
}
|
||||
|
@ -733,12 +733,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokehandle(JavaThread* thread)) {
|
||||
get_index_u2_cpcache(thread, bytecode), bytecode, CHECK);
|
||||
} // end JvmtiHideSingleStepping
|
||||
|
||||
cache_entry(thread)->set_method_handle(
|
||||
pool,
|
||||
info.resolved_method(),
|
||||
info.resolved_appendix(),
|
||||
info.resolved_method_type(),
|
||||
pool->resolved_references());
|
||||
cache_entry(thread)->set_method_handle(pool, info);
|
||||
}
|
||||
IRT_END
|
||||
|
||||
@ -762,12 +757,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) {
|
||||
} // end JvmtiHideSingleStepping
|
||||
|
||||
ConstantPoolCacheEntry* cp_cache_entry = pool->invokedynamic_cp_cache_entry_at(index);
|
||||
cp_cache_entry->set_dynamic_call(
|
||||
pool,
|
||||
info.resolved_method(),
|
||||
info.resolved_appendix(),
|
||||
info.resolved_method_type(),
|
||||
pool->resolved_references());
|
||||
cp_cache_entry->set_dynamic_call(pool, info);
|
||||
}
|
||||
IRT_END
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/defaultMethods.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
@ -132,7 +133,7 @@ void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass
|
||||
// don't force compilation, resolve was on behalf of compiler
|
||||
return;
|
||||
}
|
||||
if (InstanceKlass::cast(selected_method->method_holder())->is_not_initialized()) {
|
||||
if (selected_method->method_holder()->is_not_initialized()) {
|
||||
// 'is_not_initialized' means not only '!is_initialized', but also that
|
||||
// initialization has not been started yet ('!being_initialized')
|
||||
// Do not force compilation of methods in uninitialized classes.
|
||||
@ -404,21 +405,13 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res
|
||||
Symbol* method_name, Symbol* method_signature,
|
||||
KlassHandle current_klass, bool check_access, TRAPS) {
|
||||
|
||||
// 1. check if klass is not interface
|
||||
if (resolved_klass->is_interface()) {
|
||||
ResourceMark rm(THREAD);
|
||||
char buf[200];
|
||||
jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", Klass::cast(resolved_klass())->external_name());
|
||||
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
}
|
||||
|
||||
Handle nested_exception;
|
||||
|
||||
// 2. lookup method in resolved klass and its super klasses
|
||||
// 1. lookup method in resolved klass and its super klasses
|
||||
lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK);
|
||||
|
||||
if (resolved_method.is_null()) { // not found in the class hierarchy
|
||||
// 3. lookup method in all the interfaces implemented by the resolved klass
|
||||
// 2. lookup method in all the interfaces implemented by the resolved klass
|
||||
lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
|
||||
|
||||
if (resolved_method.is_null()) {
|
||||
@ -432,7 +425,7 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res
|
||||
}
|
||||
|
||||
if (resolved_method.is_null()) {
|
||||
// 4. method lookup failed
|
||||
// 3. method lookup failed
|
||||
ResourceMark rm(THREAD);
|
||||
THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(),
|
||||
Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()),
|
||||
@ -442,6 +435,15 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res
|
||||
}
|
||||
}
|
||||
|
||||
// 4. check if klass is not interface
|
||||
if (resolved_klass->is_interface() && resolved_method->is_abstract()) {
|
||||
ResourceMark rm(THREAD);
|
||||
char buf[200];
|
||||
jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected",
|
||||
resolved_klass()->external_name());
|
||||
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
}
|
||||
|
||||
// 5. check if method is concrete
|
||||
if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) {
|
||||
ResourceMark rm(THREAD);
|
||||
@ -464,7 +466,7 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res
|
||||
|
||||
// check loader constraints
|
||||
Handle loader (THREAD, InstanceKlass::cast(current_klass())->class_loader());
|
||||
Handle class_loader (THREAD, InstanceKlass::cast(resolved_method->method_holder())->class_loader());
|
||||
Handle class_loader (THREAD, resolved_method->method_holder()->class_loader());
|
||||
{
|
||||
ResourceMark rm(THREAD);
|
||||
char* failed_type_name =
|
||||
@ -526,7 +528,7 @@ void LinkResolver::resolve_interface_method(methodHandle& resolved_method,
|
||||
if (check_access) {
|
||||
HandleMark hm(THREAD);
|
||||
Handle loader (THREAD, InstanceKlass::cast(current_klass())->class_loader());
|
||||
Handle class_loader (THREAD, InstanceKlass::cast(resolved_method->method_holder())->class_loader());
|
||||
Handle class_loader (THREAD, resolved_method->method_holder()->class_loader());
|
||||
{
|
||||
ResourceMark rm(THREAD);
|
||||
char* failed_type_name =
|
||||
@ -743,6 +745,27 @@ void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method
|
||||
Symbol* method_name, Symbol* method_signature,
|
||||
KlassHandle current_klass, bool check_access, TRAPS) {
|
||||
|
||||
if (resolved_klass->is_interface() && current_klass() != NULL) {
|
||||
// If the target class is a direct interface, treat this as a "super"
|
||||
// default call.
|
||||
//
|
||||
// If the current method is an overpass that happens to call a direct
|
||||
// super-interface's method, then we'll end up rerunning the default method
|
||||
// analysis even though we don't need to, but that's ok since it will end
|
||||
// up with the same answer.
|
||||
InstanceKlass* ik = InstanceKlass::cast(current_klass());
|
||||
Array<Klass*>* interfaces = ik->local_interfaces();
|
||||
int num_interfaces = interfaces->length();
|
||||
for (int index = 0; index < num_interfaces; index++) {
|
||||
if (interfaces->at(index) == resolved_klass()) {
|
||||
Method* method = DefaultMethods::find_super_default(current_klass(),
|
||||
resolved_klass(), method_name, method_signature, CHECK);
|
||||
resolved_method = methodHandle(THREAD, method);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
|
||||
|
||||
// check if method name is <init>, that it is found in same klass as static type
|
||||
@ -784,11 +807,17 @@ void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle
|
||||
{ KlassHandle method_klass = KlassHandle(THREAD,
|
||||
resolved_method->method_holder());
|
||||
|
||||
if (check_access &&
|
||||
const bool direct_calling_default_method =
|
||||
resolved_klass() != NULL && resolved_method() != NULL &&
|
||||
resolved_klass->is_interface() && !resolved_method->is_abstract();
|
||||
|
||||
if (!direct_calling_default_method &&
|
||||
check_access &&
|
||||
// a) check if ACC_SUPER flag is set for the current class
|
||||
current_klass->is_super() &&
|
||||
// b) check if the method class is a superclass of the current class (superclass relation is not reflexive!)
|
||||
current_klass->is_subtype_of(method_klass()) && current_klass() != method_klass() &&
|
||||
current_klass->is_subtype_of(method_klass()) &&
|
||||
current_klass() != method_klass() &&
|
||||
// c) check if the method is not <init>
|
||||
resolved_method->name() != vmSymbols::object_initializer_name()) {
|
||||
// Lookup super method
|
||||
@ -881,12 +910,12 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result,
|
||||
|
||||
// Virtual methods cannot be resolved before its klass has been linked, for otherwise the Method*'s
|
||||
// has not been rewritten, and the vtable initialized.
|
||||
assert(InstanceKlass::cast(resolved_method->method_holder())->is_linked(), "must be linked");
|
||||
assert(resolved_method->method_holder()->is_linked(), "must be linked");
|
||||
|
||||
// Virtual methods cannot be resolved before its klass has been linked, for otherwise the Method*'s
|
||||
// has not been rewritten, and the vtable initialized. Make sure to do this after the nullcheck, since
|
||||
// a missing receiver might result in a bogus lookup.
|
||||
assert(InstanceKlass::cast(resolved_method->method_holder())->is_linked(), "must be linked");
|
||||
assert(resolved_method->method_holder()->is_linked(), "must be linked");
|
||||
|
||||
// do lookup based on receiver klass using the vtable index
|
||||
if (resolved_method->method_holder()->is_interface()) { // miranda method
|
||||
|
@ -373,11 +373,7 @@ void TemplateInterpreterGenerator::generate_all() {
|
||||
method_entry(java_lang_math_pow )
|
||||
method_entry(java_lang_ref_reference_get)
|
||||
|
||||
// method handle entry kinds are generated later in MethodHandlesAdapterGenerator::generate:
|
||||
for (int i = Interpreter::method_handle_invoke_FIRST; i <= Interpreter::method_handle_invoke_LAST; i++) {
|
||||
Interpreter::MethodKind kind = (Interpreter::MethodKind) i;
|
||||
Interpreter::_entry_table[kind] = Interpreter::_entry_table[Interpreter::abstract];
|
||||
}
|
||||
initialize_method_handle_entries();
|
||||
|
||||
// all native method kinds (must be one contiguous block)
|
||||
Interpreter::_native_entry_begin = Interpreter::code()->code_end();
|
||||
|
@ -742,6 +742,8 @@ MetaWord* CollectorPolicy::satisfy_failed_metadata_allocation(
|
||||
uint gc_count = 0;
|
||||
uint full_gc_count = 0;
|
||||
|
||||
assert(!Heap_lock->owned_by_self(), "Should not be holding the Heap_lock");
|
||||
|
||||
do {
|
||||
MetaWord* result = NULL;
|
||||
if (GC_locker::is_active_and_needs_gc()) {
|
||||
@ -756,7 +758,6 @@ MetaWord* CollectorPolicy::satisfy_failed_metadata_allocation(
|
||||
}
|
||||
JavaThread* jthr = JavaThread::current();
|
||||
if (!jthr->in_critical()) {
|
||||
MutexUnlocker mul(Heap_lock);
|
||||
// Wait for JNI critical section to be exited
|
||||
GC_locker::stall_until_clear();
|
||||
// The GC invoked by the last thread leaving the critical
|
||||
|
@ -34,29 +34,30 @@ const u2 ConstMethod::MAX_IDNUM = 0xFFFE;
|
||||
const u2 ConstMethod::UNSET_IDNUM = 0xFFFF;
|
||||
|
||||
ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data,
|
||||
int byte_code_size,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
TRAPS) {
|
||||
int byte_code_size,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
MethodType method_type,
|
||||
TRAPS) {
|
||||
int size = ConstMethod::size(byte_code_size,
|
||||
compressed_line_number_size,
|
||||
localvariable_table_length,
|
||||
exception_table_length,
|
||||
checked_exceptions_length);
|
||||
return new (loader_data, size, true, THREAD) ConstMethod(
|
||||
byte_code_size, compressed_line_number_size,
|
||||
localvariable_table_length, exception_table_length,
|
||||
checked_exceptions_length, size);
|
||||
byte_code_size, compressed_line_number_size, localvariable_table_length,
|
||||
exception_table_length, checked_exceptions_length, method_type, size);
|
||||
}
|
||||
|
||||
ConstMethod::ConstMethod(int byte_code_size,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
int size) {
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
MethodType method_type,
|
||||
int size) {
|
||||
|
||||
No_Safepoint_Verifier no_safepoint;
|
||||
set_interpreter_kind(Interpreter::invalid);
|
||||
@ -69,6 +70,7 @@ ConstMethod::ConstMethod(int byte_code_size,
|
||||
compressed_line_number_size,
|
||||
localvariable_table_length,
|
||||
exception_table_length);
|
||||
set_method_type(method_type);
|
||||
assert(this->size() == size, "wrong size for object");
|
||||
}
|
||||
|
||||
@ -111,8 +113,7 @@ int ConstMethod::size(int code_size,
|
||||
}
|
||||
|
||||
Method* ConstMethod::method() const {
|
||||
return InstanceKlass::cast(_constants->pool_holder())->method_with_idnum(
|
||||
_method_idnum);
|
||||
return _constants->pool_holder()->method_with_idnum(_method_idnum);
|
||||
}
|
||||
|
||||
// linenumber table - note that length is unknown until decompression,
|
||||
|
@ -108,12 +108,17 @@ class ExceptionTableElement VALUE_OBJ_CLASS_SPEC {
|
||||
|
||||
class ConstMethod : public MetaspaceObj {
|
||||
friend class VMStructs;
|
||||
|
||||
public:
|
||||
typedef enum { NORMAL, OVERPASS } MethodType;
|
||||
|
||||
private:
|
||||
enum {
|
||||
_has_linenumber_table = 1,
|
||||
_has_checked_exceptions = 2,
|
||||
_has_localvariable_table = 4,
|
||||
_has_exception_table = 8
|
||||
_has_exception_table = 8,
|
||||
_is_overpass = 16
|
||||
};
|
||||
|
||||
// Bit vector of signature
|
||||
@ -145,19 +150,22 @@ private:
|
||||
|
||||
// Constructor
|
||||
ConstMethod(int byte_code_size,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
int size);
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
MethodType is_overpass,
|
||||
int size);
|
||||
public:
|
||||
|
||||
static ConstMethod* allocate(ClassLoaderData* loader_data,
|
||||
int byte_code_size,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
TRAPS);
|
||||
int byte_code_size,
|
||||
int compressed_line_number_size,
|
||||
int localvariable_table_length,
|
||||
int exception_table_length,
|
||||
int checked_exceptions_length,
|
||||
MethodType mt,
|
||||
TRAPS);
|
||||
|
||||
bool is_constMethod() const { return true; }
|
||||
|
||||
@ -179,6 +187,19 @@ public:
|
||||
bool has_exception_handler() const
|
||||
{ return (_flags & _has_exception_table) != 0; }
|
||||
|
||||
MethodType method_type() const {
|
||||
return ((_flags & _is_overpass) == 0) ? NORMAL : OVERPASS;
|
||||
}
|
||||
|
||||
void set_method_type(MethodType mt) {
|
||||
if (mt == NORMAL) {
|
||||
_flags &= ~(_is_overpass);
|
||||
} else {
|
||||
_flags |= _is_overpass;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void set_interpreter_kind(int kind) { _interpreter_kind = kind; }
|
||||
int interpreter_kind(void) const { return _interpreter_kind; }
|
||||
|
||||
|
@ -228,7 +228,7 @@ Klass* ConstantPool::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS
|
||||
} else {
|
||||
do_resolve = true;
|
||||
name = this_oop->unresolved_klass_at(which);
|
||||
loader = Handle(THREAD, InstanceKlass::cast(this_oop->pool_holder())->class_loader());
|
||||
loader = Handle(THREAD, this_oop->pool_holder()->class_loader());
|
||||
}
|
||||
}
|
||||
} // unlocking constantPool
|
||||
@ -247,7 +247,7 @@ Klass* ConstantPool::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS
|
||||
|
||||
if (do_resolve) {
|
||||
// this_oop must be unlocked during resolve_or_fail
|
||||
oop protection_domain = Klass::cast(this_oop->pool_holder())->protection_domain();
|
||||
oop protection_domain = this_oop->pool_holder()->protection_domain();
|
||||
Handle h_prot (THREAD, protection_domain);
|
||||
Klass* k_oop = SystemDictionary::resolve_or_fail(name, loader, h_prot, true, THREAD);
|
||||
KlassHandle k;
|
||||
@ -315,7 +315,7 @@ Klass* ConstantPool::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS
|
||||
vframeStream vfst(JavaThread::current());
|
||||
if (!vfst.at_end()) {
|
||||
line_number = vfst.method()->line_number_from_bci(vfst.bci());
|
||||
Symbol* s = InstanceKlass::cast(vfst.method()->method_holder())->source_file_name();
|
||||
Symbol* s = vfst.method()->method_holder()->source_file_name();
|
||||
if (s != NULL) {
|
||||
source_file = s->as_C_string();
|
||||
}
|
||||
@ -325,11 +325,11 @@ Klass* ConstantPool::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS
|
||||
// only print something if the classes are different
|
||||
if (source_file != NULL) {
|
||||
tty->print("RESOLVE %s %s %s:%d\n",
|
||||
InstanceKlass::cast(this_oop->pool_holder())->external_name(),
|
||||
this_oop->pool_holder()->external_name(),
|
||||
InstanceKlass::cast(k())->external_name(), source_file, line_number);
|
||||
} else {
|
||||
tty->print("RESOLVE %s %s\n",
|
||||
InstanceKlass::cast(this_oop->pool_holder())->external_name(),
|
||||
this_oop->pool_holder()->external_name(),
|
||||
InstanceKlass::cast(k())->external_name());
|
||||
}
|
||||
}
|
||||
@ -339,7 +339,7 @@ Klass* ConstantPool::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS
|
||||
// Only updated constant pool - if it is resolved.
|
||||
do_resolve = this_oop->tag_at(which).is_unresolved_klass();
|
||||
if (do_resolve) {
|
||||
ClassLoaderData* this_key = InstanceKlass::cast(this_oop->pool_holder())->class_loader_data();
|
||||
ClassLoaderData* this_key = this_oop->pool_holder()->class_loader_data();
|
||||
if (!this_key->is_the_null_class_loader_data()) {
|
||||
this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM
|
||||
}
|
||||
@ -367,8 +367,8 @@ Klass* ConstantPool::klass_at_if_loaded(constantPoolHandle this_oop, int which)
|
||||
assert(entry.is_unresolved(), "must be either symbol or klass");
|
||||
Thread *thread = Thread::current();
|
||||
Symbol* name = entry.get_symbol();
|
||||
oop loader = InstanceKlass::cast(this_oop->pool_holder())->class_loader();
|
||||
oop protection_domain = Klass::cast(this_oop->pool_holder())->protection_domain();
|
||||
oop loader = this_oop->pool_holder()->class_loader();
|
||||
oop protection_domain = this_oop->pool_holder()->protection_domain();
|
||||
Handle h_prot (thread, protection_domain);
|
||||
Handle h_loader (thread, loader);
|
||||
Klass* k = SystemDictionary::find(name, h_loader, h_prot, thread);
|
||||
@ -409,8 +409,8 @@ Klass* ConstantPool::klass_ref_at_if_loaded_check(constantPoolHandle this_oop, i
|
||||
} else {
|
||||
assert(entry.is_unresolved(), "must be either symbol or klass");
|
||||
Symbol* name = entry.get_symbol();
|
||||
oop loader = InstanceKlass::cast(this_oop->pool_holder())->class_loader();
|
||||
oop protection_domain = Klass::cast(this_oop->pool_holder())->protection_domain();
|
||||
oop loader = this_oop->pool_holder()->class_loader();
|
||||
oop protection_domain = this_oop->pool_holder()->protection_domain();
|
||||
Handle h_loader(THREAD, loader);
|
||||
Handle h_prot (THREAD, protection_domain);
|
||||
KlassHandle k(THREAD, SystemDictionary::find(name, h_loader, h_prot, THREAD));
|
||||
@ -1143,16 +1143,21 @@ void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int
|
||||
int from_oplen = operand_array_length(from_cp->operands());
|
||||
int old_oplen = operand_array_length(to_cp->operands());
|
||||
if (from_oplen != 0) {
|
||||
ClassLoaderData* loader_data = to_cp->pool_holder()->class_loader_data();
|
||||
// append my operands to the target's operands array
|
||||
if (old_oplen == 0) {
|
||||
to_cp->set_operands(from_cp->operands()); // reuse; do not merge
|
||||
// Can't just reuse from_cp's operand list because of deallocation issues
|
||||
int len = from_cp->operands()->length();
|
||||
Array<u2>* new_ops = MetadataFactory::new_array<u2>(loader_data, len, CHECK);
|
||||
Copy::conjoint_memory_atomic(
|
||||
from_cp->operands()->adr_at(0), new_ops->adr_at(0), len * sizeof(u2));
|
||||
to_cp->set_operands(new_ops);
|
||||
} else {
|
||||
int old_len = to_cp->operands()->length();
|
||||
int from_len = from_cp->operands()->length();
|
||||
int old_off = old_oplen * sizeof(u2);
|
||||
int from_off = from_oplen * sizeof(u2);
|
||||
// Use the metaspace for the destination constant pool
|
||||
ClassLoaderData* loader_data = to_cp->pool_holder()->class_loader_data();
|
||||
Array<u2>* new_operands = MetadataFactory::new_array<u2>(loader_data, old_len + from_len, CHECK);
|
||||
int fillp = 0, len = 0;
|
||||
// first part of dest
|
||||
@ -1785,7 +1790,7 @@ void ConstantPool::patch_resolved_references(
|
||||
assert(cp_patches->at(index).is_null(),
|
||||
err_msg("Unused constant pool patch at %d in class file %s",
|
||||
index,
|
||||
InstanceKlass::cast(pool_holder())->external_name()));
|
||||
pool_holder()->external_name()));
|
||||
}
|
||||
#endif // ASSERT
|
||||
}
|
||||
@ -1943,7 +1948,7 @@ void ConstantPool::print_value_on(outputStream* st) const {
|
||||
st->print(" for ");
|
||||
pool_holder()->print_value_on(st);
|
||||
if (pool_holder() != NULL) {
|
||||
bool extra = (InstanceKlass::cast(pool_holder())->constants() != this);
|
||||
bool extra = (pool_holder()->constants() != this);
|
||||
if (extra) st->print(" (extra)");
|
||||
}
|
||||
if (cache() != NULL) {
|
||||
|
@ -86,8 +86,8 @@ class ConstantPool : public Metadata {
|
||||
friend class Universe; // For null constructor
|
||||
private:
|
||||
Array<u1>* _tags; // the tag array describing the constant pool's contents
|
||||
ConstantPoolCache* _cache; // the cache holding interpreter runtime information
|
||||
Klass* _pool_holder; // the corresponding class
|
||||
ConstantPoolCache* _cache; // the cache holding interpreter runtime information
|
||||
InstanceKlass* _pool_holder; // the corresponding class
|
||||
Array<u2>* _operands; // for variable-sized (InvokeDynamic) nodes, usually empty
|
||||
|
||||
// Array of resolved objects from the constant pool and map from resolved
|
||||
@ -193,9 +193,9 @@ class ConstantPool : public Metadata {
|
||||
void set_on_stack(const bool value);
|
||||
|
||||
// Klass holding pool
|
||||
Klass* pool_holder() const { return _pool_holder; }
|
||||
void set_pool_holder(Klass* k) { _pool_holder = k; }
|
||||
Klass** pool_holder_addr() { return &_pool_holder; }
|
||||
InstanceKlass* pool_holder() const { return _pool_holder; }
|
||||
void set_pool_holder(InstanceKlass* k) { _pool_holder = k; }
|
||||
InstanceKlass** pool_holder_addr() { return &_pool_holder; }
|
||||
|
||||
// Interpreter runtime support
|
||||
ConstantPoolCache* cache() const { return _cache; }
|
||||
|
@ -231,8 +231,8 @@ void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code,
|
||||
|
||||
|
||||
void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) {
|
||||
Klass* interf = method->method_holder();
|
||||
assert(InstanceKlass::cast(interf)->is_interface(), "must be an interface");
|
||||
InstanceKlass* interf = method->method_holder();
|
||||
assert(interf->is_interface(), "must be an interface");
|
||||
assert(!method->is_final_method(), "interfaces do not have final methods; cannot link to one here");
|
||||
set_f1(interf);
|
||||
set_f2(index);
|
||||
@ -243,25 +243,17 @@ void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index)
|
||||
}
|
||||
|
||||
|
||||
void ConstantPoolCacheEntry::set_method_handle(constantPoolHandle cpool,
|
||||
methodHandle adapter,
|
||||
Handle appendix, Handle method_type,
|
||||
objArrayHandle resolved_references) {
|
||||
set_method_handle_common(cpool, Bytecodes::_invokehandle, adapter, appendix, method_type, resolved_references);
|
||||
void ConstantPoolCacheEntry::set_method_handle(constantPoolHandle cpool, const CallInfo &call_info) {
|
||||
set_method_handle_common(cpool, Bytecodes::_invokehandle, call_info);
|
||||
}
|
||||
|
||||
void ConstantPoolCacheEntry::set_dynamic_call(constantPoolHandle cpool,
|
||||
methodHandle adapter,
|
||||
Handle appendix, Handle method_type,
|
||||
objArrayHandle resolved_references) {
|
||||
set_method_handle_common(cpool, Bytecodes::_invokedynamic, adapter, appendix, method_type, resolved_references);
|
||||
void ConstantPoolCacheEntry::set_dynamic_call(constantPoolHandle cpool, const CallInfo &call_info) {
|
||||
set_method_handle_common(cpool, Bytecodes::_invokedynamic, call_info);
|
||||
}
|
||||
|
||||
void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool,
|
||||
Bytecodes::Code invoke_code,
|
||||
methodHandle adapter,
|
||||
Handle appendix, Handle method_type,
|
||||
objArrayHandle resolved_references) {
|
||||
const CallInfo &call_info) {
|
||||
// NOTE: This CPCE can be the subject of data races.
|
||||
// There are three words to update: flags, refs[f2], f1 (in that order).
|
||||
// Writers must store all other values before f1.
|
||||
@ -276,6 +268,9 @@ void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool,
|
||||
return;
|
||||
}
|
||||
|
||||
const methodHandle adapter = call_info.resolved_method();
|
||||
const Handle appendix = call_info.resolved_appendix();
|
||||
const Handle method_type = call_info.resolved_method_type();
|
||||
const bool has_appendix = appendix.not_null();
|
||||
const bool has_method_type = method_type.not_null();
|
||||
|
||||
@ -315,6 +310,7 @@ void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool,
|
||||
// This allows us to create fewer method oops, while keeping type safety.
|
||||
//
|
||||
|
||||
objArrayHandle resolved_references = cpool->resolved_references();
|
||||
// Store appendix, if any.
|
||||
if (has_appendix) {
|
||||
const int appendix_index = f2_as_index() + _indy_resolved_references_appendix_offset;
|
||||
@ -421,7 +417,7 @@ bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
|
||||
if (!(*trace_name_printed)) {
|
||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
||||
RC_TRACE_MESG(("adjust: name=%s",
|
||||
Klass::cast(old_method->method_holder())->external_name()));
|
||||
old_method->method_holder()->external_name()));
|
||||
*trace_name_printed = true;
|
||||
}
|
||||
// RC_TRACE macro has an embedded ResourceMark
|
||||
@ -449,7 +445,7 @@ bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
|
||||
if (!(*trace_name_printed)) {
|
||||
// RC_TRACE_MESG macro has an embedded ResourceMark
|
||||
RC_TRACE_MESG(("adjust: name=%s",
|
||||
Klass::cast(old_method->method_holder())->external_name()));
|
||||
old_method->method_holder()->external_name()));
|
||||
*trace_name_printed = true;
|
||||
}
|
||||
// RC_TRACE macro has an embedded ResourceMark
|
||||
|
@ -117,6 +117,8 @@ class PSPromotionManager;
|
||||
// The fields are volatile so that they are stored in the order written in the
|
||||
// source code. The _indices field with the bytecode must be written last.
|
||||
|
||||
class CallInfo;
|
||||
|
||||
class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
||||
friend class VMStructs;
|
||||
friend class constantPoolCacheKlass;
|
||||
@ -223,18 +225,12 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
||||
|
||||
void set_method_handle(
|
||||
constantPoolHandle cpool, // holding constant pool (required for locking)
|
||||
methodHandle method, // adapter for invokeExact, etc.
|
||||
Handle appendix, // stored in refs[f2+0]; could be a java.lang.invoke.MethodType
|
||||
Handle method_type, // stored in refs[f2+1]; is a java.lang.invoke.MethodType
|
||||
objArrayHandle resolved_references
|
||||
const CallInfo &call_info // Call link information
|
||||
);
|
||||
|
||||
void set_dynamic_call(
|
||||
constantPoolHandle cpool, // holding constant pool (required for locking)
|
||||
methodHandle method, // adapter for this call site
|
||||
Handle appendix, // stored in refs[f2+0]; could be a java.lang.invoke.CallSite
|
||||
Handle method_type, // stored in refs[f2+1]; is a java.lang.invoke.MethodType
|
||||
objArrayHandle resolved_references
|
||||
const CallInfo &call_info // Call link information
|
||||
);
|
||||
|
||||
// Common code for invokedynamic and MH invocations.
|
||||
@ -255,10 +251,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
||||
void set_method_handle_common(
|
||||
constantPoolHandle cpool, // holding constant pool (required for locking)
|
||||
Bytecodes::Code invoke_code, // _invokehandle or _invokedynamic
|
||||
methodHandle adapter, // invoker method (f1)
|
||||
Handle appendix, // appendix such as CallSite, MethodType, etc. (refs[f2+0])
|
||||
Handle method_type, // MethodType (refs[f2+1])
|
||||
objArrayHandle resolved_references
|
||||
const CallInfo &call_info // Call link information
|
||||
);
|
||||
|
||||
// invokedynamic and invokehandle call sites have two entries in the
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user