--- a/.hgtags-top-repo Thu Oct 24 09:10:35 2013 -0700
+++ b/.hgtags-top-repo Wed Jul 05 19:19:29 2017 +0200
@@ -234,3 +234,4 @@
4faa09c7fe555de086dd9048d3c5cc92317d6f45 jdk8-b110
d086227bfc45d124f09b3bd72a07956b4073bf71 jdk8-b111
547316ea137d83d9c63083a9b83db64198fe0c81 jdk8-b112
+6ba4c7cb623ec612031e05cf8bf279d8f407bd1e jdk8-b113
--- a/common/autoconf/basics.m4 Thu Oct 24 09:10:35 2013 -0700
+++ b/common/autoconf/basics.m4 Wed Jul 05 19:19:29 2017 +0200
@@ -656,7 +656,7 @@
fi
if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then
- BASIC_REQUIRE_PROG(DSYMUTIL, dsymutil)
+ BASIC_REQUIRE_PROG(DSYMUTIL, dsymutil)
BASIC_REQUIRE_PROG(XATTR, xattr)
AC_PATH_PROG(CODESIGN, codesign)
if test "x$CODESIGN" != "x"; then
--- a/common/autoconf/generated-configure.sh Thu Oct 24 09:10:35 2013 -0700
+++ b/common/autoconf/generated-configure.sh Wed Jul 05 19:19:29 2017 +0200
@@ -869,6 +869,7 @@
ZERO_ARCHDEF
DEFINE_CROSS_COMPILE_ARCH
LP64
+OPENJDK_TARGET_OS_EXPORT_DIR
OPENJDK_TARGET_OS_API_DIR
OPENJDK_TARGET_CPU_JLI_CFLAGS
OPENJDK_TARGET_CPU_OSARCH
@@ -3864,7 +3865,7 @@
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1382540536
+DATE_WHEN_GENERATED=1382702260
###############################################################################
#
@@ -7149,6 +7150,13 @@
fi
+ if test "x$OPENJDK_TARGET_OS" = xmacosx; then
+ OPENJDK_TARGET_OS_EXPORT_DIR=macosx
+ else
+ OPENJDK_TARGET_OS_EXPORT_DIR=${OPENJDK_TARGET_OS_API_DIR}
+ fi
+
+
if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
A_LP64="LP64:="
# -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in
@@ -29638,7 +29646,7 @@
-I${JDK_OUTPUTDIR}/include \
-I${JDK_OUTPUTDIR}/include/$OPENJDK_TARGET_OS \
-I${JDK_TOPDIR}/src/share/javavm/export \
- -I${JDK_TOPDIR}/src/$OPENJDK_TARGET_OS_API_DIR/javavm/export \
+ -I${JDK_TOPDIR}/src/$OPENJDK_TARGET_OS_EXPORT_DIR/javavm/export \
-I${JDK_TOPDIR}/src/share/native/common \
-I${JDK_TOPDIR}/src/$OPENJDK_TARGET_OS_API_DIR/native/common"
@@ -29905,11 +29913,11 @@
elif test "x$enable_debug_symbols" = "xno"; then
ENABLE_DEBUG_SYMBOLS=false
else
- # Default is on if objcopy is found
- if test "x$OBJCOPY" != x; then
- ENABLE_DEBUG_SYMBOLS=true
- # MacOS X and Windows don't use objcopy but default is on for those OSes
- elif test "x$OPENJDK_TARGET_OS" = xmacosx || test "x$OPENJDK_TARGET_OS" = xwindows; then
+ # Default is on if objcopy is found
+ if test "x$OBJCOPY" != x; then
+ ENABLE_DEBUG_SYMBOLS=true
+ # MacOS X and Windows don't use objcopy but default is on for those OSes
+ elif test "x$OPENJDK_TARGET_OS" = xmacosx || test "x$OPENJDK_TARGET_OS" = xwindows; then
ENABLE_DEBUG_SYMBOLS=true
else
ENABLE_DEBUG_SYMBOLS=false
@@ -34245,10 +34253,10 @@
ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
PREV_CXXCFLAGS="$CXXFLAGS"
- PREV_LDFLAGS="$LDFLAGS"
+ PREV_LIBS="$LIBS"
PREV_CXX="$CXX"
CXXFLAGS="$CXXFLAGS $FREETYPE_CFLAGS"
- LDFLAGS="$LDFLAGS $FREETYPE_LIBS"
+ LIBS="$LIBS $FREETYPE_LIBS"
CXX="$FIXPATH $CXX"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -34315,7 +34323,7 @@
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
CXXCFLAGS="$PREV_CXXFLAGS"
- LDFLAGS="$PREV_LDFLAGS"
+ LIBS="$PREV_LIBS"
CXX="$PREV_CXX"
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
--- a/common/autoconf/jdk-options.m4 Thu Oct 24 09:10:35 2013 -0700
+++ b/common/autoconf/jdk-options.m4 Wed Jul 05 19:19:29 2017 +0200
@@ -516,11 +516,11 @@
elif test "x$enable_debug_symbols" = "xno"; then
ENABLE_DEBUG_SYMBOLS=false
else
- # Default is on if objcopy is found
- if test "x$OBJCOPY" != x; then
- ENABLE_DEBUG_SYMBOLS=true
- # MacOS X and Windows don't use objcopy but default is on for those OSes
- elif test "x$OPENJDK_TARGET_OS" = xmacosx || test "x$OPENJDK_TARGET_OS" = xwindows; then
+ # Default is on if objcopy is found
+ if test "x$OBJCOPY" != x; then
+ ENABLE_DEBUG_SYMBOLS=true
+ # MacOS X and Windows don't use objcopy but default is on for those OSes
+ elif test "x$OPENJDK_TARGET_OS" = xmacosx || test "x$OPENJDK_TARGET_OS" = xwindows; then
ENABLE_DEBUG_SYMBOLS=true
else
ENABLE_DEBUG_SYMBOLS=false
--- a/common/autoconf/libraries.m4 Thu Oct 24 09:10:35 2013 -0700
+++ b/common/autoconf/libraries.m4 Wed Jul 05 19:19:29 2017 +0200
@@ -481,10 +481,10 @@
AC_MSG_CHECKING([if we can compile and link with freetype])
AC_LANG_PUSH(C++)
PREV_CXXCFLAGS="$CXXFLAGS"
- PREV_LDFLAGS="$LDFLAGS"
+ PREV_LIBS="$LIBS"
PREV_CXX="$CXX"
CXXFLAGS="$CXXFLAGS $FREETYPE_CFLAGS"
- LDFLAGS="$LDFLAGS $FREETYPE_LIBS"
+ LIBS="$LIBS $FREETYPE_LIBS"
CXX="$FIXPATH $CXX"
AC_LINK_IFELSE([AC_LANG_SOURCE([[
#include<ft2build.h>
@@ -508,7 +508,7 @@
]
)
CXXCFLAGS="$PREV_CXXFLAGS"
- LDFLAGS="$PREV_LDFLAGS"
+ LIBS="$PREV_LIBS"
CXX="$PREV_CXX"
AC_LANG_POP(C++)
--- a/common/autoconf/platform.m4 Thu Oct 24 09:10:35 2013 -0700
+++ b/common/autoconf/platform.m4 Wed Jul 05 19:19:29 2017 +0200
@@ -327,6 +327,13 @@
fi
AC_SUBST(OPENJDK_TARGET_OS_API_DIR)
+ if test "x$OPENJDK_TARGET_OS" = xmacosx; then
+ OPENJDK_TARGET_OS_EXPORT_DIR=macosx
+ else
+ OPENJDK_TARGET_OS_EXPORT_DIR=${OPENJDK_TARGET_OS_API_DIR}
+ fi
+ AC_SUBST(OPENJDK_TARGET_OS_EXPORT_DIR)
+
if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
A_LP64="LP64:="
# -D_LP64=1 is only set on linux and mac. Setting on windows causes diff in
--- a/common/autoconf/spec.gmk.in Thu Oct 24 09:10:35 2013 -0700
+++ b/common/autoconf/spec.gmk.in Wed Jul 05 19:19:29 2017 +0200
@@ -92,6 +92,7 @@
OPENJDK_TARGET_CPU_OSARCH:=@OPENJDK_TARGET_CPU_OSARCH@
OPENJDK_TARGET_CPU_JLI_CFLAGS:=@OPENJDK_TARGET_CPU_JLI_CFLAGS@
OPENJDK_TARGET_OS_API_DIR:=@OPENJDK_TARGET_OS_API_DIR@
+OPENJDK_TARGET_OS_EXPORT_DIR:=@OPENJDK_TARGET_OS_EXPORT_DIR@
# We are building on this build system.
# When not cross-compiling, it is the same as the target.
--- a/common/autoconf/toolchain.m4 Thu Oct 24 09:10:35 2013 -0700
+++ b/common/autoconf/toolchain.m4 Wed Jul 05 19:19:29 2017 +0200
@@ -942,7 +942,7 @@
-I${JDK_OUTPUTDIR}/include \
-I${JDK_OUTPUTDIR}/include/$OPENJDK_TARGET_OS \
-I${JDK_TOPDIR}/src/share/javavm/export \
- -I${JDK_TOPDIR}/src/$OPENJDK_TARGET_OS_API_DIR/javavm/export \
+ -I${JDK_TOPDIR}/src/$OPENJDK_TARGET_OS_EXPORT_DIR/javavm/export \
-I${JDK_TOPDIR}/src/share/native/common \
-I${JDK_TOPDIR}/src/$OPENJDK_TARGET_OS_API_DIR/native/common"
--- a/common/makefiles/JavaCompilation.gmk Thu Oct 24 09:10:35 2013 -0700
+++ b/common/makefiles/JavaCompilation.gmk Wed Jul 05 19:19:29 2017 +0200
@@ -506,30 +506,30 @@
$$($1_BIN)/javac_state: $$($1_SRCS) $$($1_DEPENDS)
$(MKDIR) -p $$(@D)
- $$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.batch.tmp)
+ $$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.$1_batch.tmp)
$(ECHO) Compiling $1
($$($1_JVM) $$($1_SJAVAC) \
$$($1_REMOTE) \
-j $(JOBS) \
--permit-unidentified-artifacts \
--permit-sources-without-package \
- --compare-found-sources $$($1_BIN)/_the.batch.tmp \
+ --compare-found-sources $$($1_BIN)/_the.$1_batch.tmp \
--log=$(LOG_LEVEL) \
$$($1_SJAVAC_ARGS) \
$$($1_FLAGS) \
$$($1_HEADERS_ARG) \
-d $$($1_BIN) && \
- $(MV) $$($1_BIN)/_the.batch.tmp $$($1_BIN)/_the.batch)
+ $(MV) $$($1_BIN)/_the.$1_batch.tmp $$($1_BIN)/_the.$1_batch)
else
# Using plain javac to batch compile everything.
- $1 := $$($1_ALL_COPY_TARGETS) $$($1_ALL_COPY_CLEAN_TARGETS) $$($1_BIN)/_the.batch
+ $1 := $$($1_ALL_COPY_TARGETS) $$($1_ALL_COPY_CLEAN_TARGETS) $$($1_BIN)/_the.$1_batch
# When building in batch, put headers in a temp dir to filter out those that actually
# changed before copying them to the real header dir.
ifneq (,$$($1_HEADERS))
$1_HEADERS_ARG := -h $$($1_HEADERS).tmp
- $$($1_HEADERS)/_the.headers: $$($1_BIN)/_the.batch
+ $$($1_HEADERS)/_the.$1_headers: $$($1_BIN)/_the.$1_batch
$(MKDIR) -p $$(@D)
for f in `ls $$($1_HEADERS).tmp`; do \
if [ ! -f "$$($1_HEADERS)/$$$$f" ] || [ "`$(DIFF) $$($1_HEADERS)/$$$$f $$($1_HEADERS).tmp/$$$$f`" != "" ]; then \
@@ -539,19 +539,19 @@
$(RM) -r $$($1_HEADERS).tmp
$(TOUCH) $$@
- $1 += $$($1_HEADERS)/_the.headers
+ $1 += $$($1_HEADERS)/_the.$1_headers
endif
# When not using sjavac, pass along all sources to javac using an @file.
- $$($1_BIN)/_the.batch: $$($1_SRCS) $$($1_DEPENDS)
+ $$($1_BIN)/_the.$1_batch: $$($1_SRCS) $$($1_DEPENDS)
$(MKDIR) -p $$(@D)
- $(RM) $$($1_BIN)/_the.batch $$($1_BIN)/_the.batch.tmp
- $$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.batch.tmp)
- $(ECHO) Compiling `$(WC) $$($1_BIN)/_the.batch.tmp | $(TR) -s ' ' | $(CUT) -f 2 -d ' '` files for $1
+ $(RM) $$($1_BIN)/_the.$1_batch $$($1_BIN)/_the.$1_batch.tmp
+ $$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.$1_batch.tmp)
+ $(ECHO) Compiling `$(WC) $$($1_BIN)/_the.$1_batch.tmp | $(TR) -s ' ' | $(CUT) -f 2 -d ' '` files for $1
($$($1_JVM) $$($1_JAVAC) $$($1_FLAGS) \
-implicit:none -sourcepath "$$($1_SRCROOTSC)" \
- -d $$($1_BIN) $$($1_HEADERS_ARG) @$$($1_BIN)/_the.batch.tmp && \
- $(MV) $$($1_BIN)/_the.batch.tmp $$($1_BIN)/_the.batch)
+ -d $$($1_BIN) $$($1_HEADERS_ARG) @$$($1_BIN)/_the.$1_batch.tmp && \
+ $(MV) $$($1_BIN)/_the.$1_batch.tmp $$($1_BIN)/_the.$1_batch)
endif
--- a/common/makefiles/NativeCompilation.gmk Thu Oct 24 09:10:35 2013 -0700
+++ b/common/makefiles/NativeCompilation.gmk Wed Jul 05 19:19:29 2017 +0200
@@ -435,36 +435,36 @@
$(CP) $$< $$@
endif
- ifneq ($(OPENJDK_TARGET_OS), macosx) # OBJCOPY is not used on MacOS X
- ifneq ($(OPENJDK_TARGET_OS), windows) # nor on Windows
- ifeq ($(OPENJDK_TARGET_OS), solaris)
- # gobjcopy crashes on "empty" section headers with the SHF_ALLOC flag set.
- # Use $(FIX_EMPTY_SEC_HDR_FLAGS) to clear the SHF_ALLOC flag (if set) from
- # empty section headers until a fixed $(OBJCOPY) is available.
- # An empty section header has sh_addr == 0 and sh_size == 0.
- # This problem has only been seen on Solaris X64, but we call this tool
- # on all Solaris builds just in case.
- #
- # $(OBJCOPY) --add-gnu-debuglink=... corrupts SUNW_* sections.
- # Use $(ADD_GNU_DEBUGLINK) until a fixed $(OBJCOPY) is available.
- $$($1_OBJECT_DIR)/$$(LIBRARY_PREFIX)$$($1_LIBRARY).debuginfo : $$($1_TARGET) \
- $(FIX_EMPTY_SEC_HDR_FLAGS) $(ADD_GNU_DEBUGLINK)
- $(RM) $$@
- $(FIX_EMPTY_SEC_HDR_FLAGS) $(LOG_INFO) $$<
- $(OBJCOPY) --only-keep-debug $$< $$@
- $(CD) $$(@D) && $(ADD_GNU_DEBUGLINK) $(LOG_INFO) $$(@F) $$<
- else # not solaris
- $$($1_OBJECT_DIR)/$$(LIBRARY_PREFIX)$$($1_LIBRARY).debuginfo : $$($1_TARGET)
- $(RM) $$@
- $(OBJCOPY) --only-keep-debug $$< $$@
- $(CD) $$(@D) && $(OBJCOPY) --add-gnu-debuglink=$$(@F) $$<
- endif # Touch to not retrigger rule on rebuild
+ ifneq ($(OPENJDK_TARGET_OS), macosx) # OBJCOPY is not used on MacOS X
+ ifneq ($(OPENJDK_TARGET_OS), windows) # nor on Windows
+ ifeq ($(OPENJDK_TARGET_OS), solaris)
+ # gobjcopy crashes on "empty" section headers with the SHF_ALLOC flag set.
+ # Use $(FIX_EMPTY_SEC_HDR_FLAGS) to clear the SHF_ALLOC flag (if set) from
+ # empty section headers until a fixed $(OBJCOPY) is available.
+ # An empty section header has sh_addr == 0 and sh_size == 0.
+ # This problem has only been seen on Solaris X64, but we call this tool
+ # on all Solaris builds just in case.
+ #
+ # $(OBJCOPY) --add-gnu-debuglink=... corrupts SUNW_* sections.
+ # Use $(ADD_GNU_DEBUGLINK) until a fixed $(OBJCOPY) is available.
+ $$($1_OBJECT_DIR)/$$(LIBRARY_PREFIX)$$($1_LIBRARY).debuginfo : $$($1_TARGET) \
+ $(FIX_EMPTY_SEC_HDR_FLAGS) $(ADD_GNU_DEBUGLINK)
+ $(RM) $$@
+ $(FIX_EMPTY_SEC_HDR_FLAGS) $(LOG_INFO) $$<
+ $(OBJCOPY) --only-keep-debug $$< $$@
+ $(CD) $$(@D) && $(ADD_GNU_DEBUGLINK) $(LOG_INFO) $$(@F) $$<
+ else # not solaris
+ $$($1_OBJECT_DIR)/$$(LIBRARY_PREFIX)$$($1_LIBRARY).debuginfo : $$($1_TARGET)
+ $(RM) $$@
+ $(OBJCOPY) --only-keep-debug $$< $$@
+ $(CD) $$(@D) && $(OBJCOPY) --add-gnu-debuglink=$$(@F) $$<
+ endif # Touch to not retrigger rule on rebuild
$(TOUCH) $$@
- endif # !windows
- endif # !macosx
+ endif # !windows
+ endif # !macosx
ifeq ($(ZIP_DEBUGINFO_FILES), true)
- ifneq ($(OPENJDK_TARGET_OS), macosx) # no MacOS X support yet
+ifneq ($(OPENJDK_TARGET_OS), macosx) # no MacOS X support yet
$1 += $$($1_OUTPUT_DIR)/$$(LIBRARY_PREFIX)$$($1_LIBRARY).diz
ifeq ($(OPENJDK_TARGET_OS), windows)
@@ -477,12 +477,12 @@
$(CD) $$($1_OBJECT_DIR) \
&& $(ZIP) -q $$@ $$(LIBRARY_PREFIX)$$($1_LIBRARY).debuginfo
endif
- endif # no MacOS X support yet
+endif # no MacOS X support yet
else
ifeq ($(OPENJDK_TARGET_OS), windows)
$1 += $$($1_OUTPUT_DIR)/$$($1_LIBRARY).map \
$$($1_OUTPUT_DIR)/$$($1_LIBRARY).pdb
- else ifneq ($(OPENJDK_TARGET_OS), macosx) # MacOS X does not use .debuginfo files
+ else ifneq ($(OPENJDK_TARGET_OS), macosx) # MacOS X does not use .debuginfo files
$1 += $$($1_OUTPUT_DIR)/$$(LIBRARY_PREFIX)$$($1_LIBRARY).debuginfo
endif
endif
@@ -519,36 +519,36 @@
$(CP) $$< $$@
endif
- ifneq ($(OPENJDK_TARGET_OS), macosx) # OBJCOPY is not used on MacOS X
- ifneq ($(OPENJDK_TARGET_OS), windows) # nor on Windows
- ifeq ($(OPENJDK_TARGET_OS), solaris)
- # gobjcopy crashes on "empty" section headers with the SHF_ALLOC flag set.
- # Use $(FIX_EMPTY_SEC_HDR_FLAGS) to clear the SHF_ALLOC flag (if set) from
- # empty section headers until a fixed $(OBJCOPY) is available.
- # An empty section header has sh_addr == 0 and sh_size == 0.
- # This problem has only been seen on Solaris X64, but we call this tool
- # on all Solaris builds just in case.
- #
- # $(OBJCOPY) --add-gnu-debuglink=... corrupts SUNW_* sections.
- # Use $(ADD_GNU_DEBUGLINK) until a fixed $(OBJCOPY) is available.
- $$($1_OBJECT_DIR)/$$($1_PROGRAM).debuginfo : $$($1_TARGET) \
- $(FIX_EMPTY_SEC_HDR_FLAGS) $(ADD_GNU_DEBUGLINK)
- $(RM) $$@
- $(FIX_EMPTY_SEC_HDR_FLAGS) $(LOG_INFO) $$<
- $(OBJCOPY) --only-keep-debug $$< $$@
- $(CD) $$(@D) && $(ADD_GNU_DEBUGLINK) $(LOG_INFO) $$(@F) $$<
- else # not solaris
- $$($1_OBJECT_DIR)/$$($1_PROGRAM).debuginfo : $$($1_TARGET)
- $(RM) $$@
- $(OBJCOPY) --only-keep-debug $$< $$@
- $(CD) $$(@D) && $(OBJCOPY) --add-gnu-debuglink=$$(@F) $$<
- endif
- $(TOUCH) $$@
- endif # !windows
- endif # !macosx
+ ifneq ($(OPENJDK_TARGET_OS), macosx) # OBJCOPY is not used on MacOS X
+ ifneq ($(OPENJDK_TARGET_OS), windows) # nor on Windows
+ ifeq ($(OPENJDK_TARGET_OS), solaris)
+ # gobjcopy crashes on "empty" section headers with the SHF_ALLOC flag set.
+ # Use $(FIX_EMPTY_SEC_HDR_FLAGS) to clear the SHF_ALLOC flag (if set) from
+ # empty section headers until a fixed $(OBJCOPY) is available.
+ # An empty section header has sh_addr == 0 and sh_size == 0.
+ # This problem has only been seen on Solaris X64, but we call this tool
+ # on all Solaris builds just in case.
+ #
+ # $(OBJCOPY) --add-gnu-debuglink=... corrupts SUNW_* sections.
+ # Use $(ADD_GNU_DEBUGLINK) until a fixed $(OBJCOPY) is available.
+ $$($1_OBJECT_DIR)/$$($1_PROGRAM).debuginfo : $$($1_TARGET) \
+ $(FIX_EMPTY_SEC_HDR_FLAGS) $(ADD_GNU_DEBUGLINK)
+ $(RM) $$@
+ $(FIX_EMPTY_SEC_HDR_FLAGS) $(LOG_INFO) $$<
+ $(OBJCOPY) --only-keep-debug $$< $$@
+ $(CD) $$(@D) && $(ADD_GNU_DEBUGLINK) $(LOG_INFO) $$(@F) $$<
+ else # not solaris
+ $$($1_OBJECT_DIR)/$$($1_PROGRAM).debuginfo : $$($1_TARGET)
+ $(RM) $$@
+ $(OBJCOPY) --only-keep-debug $$< $$@
+ $(CD) $$(@D) && $(OBJCOPY) --add-gnu-debuglink=$$(@F) $$<
+ endif
+ $(TOUCH) $$@
+ endif # !windows
+ endif # !macosx
ifeq ($(ZIP_DEBUGINFO_FILES), true)
- ifneq ($(OPENJDK_TARGET_OS), macosx) # no MacOS X support yet
+ifneq ($(OPENJDK_TARGET_OS), macosx) # no MacOS X support yet
$1 += $$($1_OUTPUT_DIR)/$$($1_PROGRAM).diz
ifeq ($(OPENJDK_TARGET_OS), windows)
@@ -561,12 +561,12 @@
$(CD) $$($1_OBJECT_DIR) \
&& $(ZIP) -q $$@ $$($1_PROGRAM).debuginfo
endif
- endif # no MacOS X support yet
+endif # no MacOS X support yet
else
ifeq ($(OPENJDK_TARGET_OS), windows)
$1 += $$($1_OUTPUT_DIR)/$$($1_PROGRAM).map \
$$($1_OUTPUT_DIR)/$$($1_PROGRAM).pdb
- else ifneq ($(OPENJDK_TARGET_OS), macosx) # MacOS X does not use .debuginfo files
+ else ifneq ($(OPENJDK_TARGET_OS), macosx) # MacOS X does not use .debuginfo files
$1 += $$($1_OUTPUT_DIR)/$$($1_PROGRAM).debuginfo
endif
endif
--- a/corba/.hgtags Thu Oct 24 09:10:35 2013 -0700
+++ b/corba/.hgtags Wed Jul 05 19:19:29 2017 +0200
@@ -234,3 +234,4 @@
3d2b7ce93c5c2e3db748f29c3d29620a8b3b748a jdk8-b110
85c1c94e723582f9a1dd0251502c42b73d6deea7 jdk8-b111
43cec76d1d62587a07af07e2d9bec93aba2a506b jdk8-b112
+a259ff3e42d91da68f4d4f09d7eb9dc22bc024fc jdk8-b113
--- a/hotspot/.hgtags Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/.hgtags Wed Jul 05 19:19:29 2017 +0200
@@ -387,3 +387,5 @@
4a845c7a463844cead9e1e1641d6bcfb8a77f1c7 hs25-b54
0ed9a90f45e1b392c671005f9ee22ce1acf02984 jdk8-b112
23b8db5ea31d3079f1326afde4cd5c67b1dac49c hs25-b55
+4589b398ab03aba6a5da8c06ff53603488d1b8f4 jdk8-b113
+82a9cdbf683e374a76f2009352de53e16bed5a91 hs25-b56
--- a/hotspot/agent/src/os/linux/ps_core.c Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/os/linux/ps_core.c Wed Jul 05 19:19:29 2017 +0200
@@ -719,7 +719,7 @@
ELF_PHDR* phbuf;
ELF_PHDR* lib_php = NULL;
- int page_size=sysconf(_SC_PAGE_SIZE);
+ int page_size = sysconf(_SC_PAGE_SIZE);
if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) {
return false;
@@ -736,26 +736,29 @@
if (existing_map == NULL){
if (add_map_info(ph, lib_fd, lib_php->p_offset,
- target_vaddr, lib_php->p_filesz) == NULL) {
+ target_vaddr, lib_php->p_memsz) == NULL) {
goto err;
}
} else {
+ // Coredump stores value of p_memsz elf field
+ // rounded up to page boundary.
+
if ((existing_map->memsz != page_size) &&
(existing_map->fd != lib_fd) &&
- (existing_map->memsz != lib_php->p_filesz)){
+ (ROUNDUP(existing_map->memsz, page_size) != ROUNDUP(lib_php->p_memsz, page_size))) {
- print_debug("address conflict @ 0x%lx (size = %ld, flags = %d\n)",
- target_vaddr, lib_php->p_filesz, lib_php->p_flags);
+ print_debug("address conflict @ 0x%lx (existing map size = %ld, size = %ld, flags = %d)\n",
+ target_vaddr, existing_map->memsz, lib_php->p_memsz, lib_php->p_flags);
goto err;
}
/* replace PT_LOAD segment with library segment */
print_debug("overwrote with new address mapping (memsz %ld -> %ld)\n",
- existing_map->memsz, lib_php->p_filesz);
+ existing_map->memsz, ROUNDUP(lib_php->p_memsz, page_size));
existing_map->fd = lib_fd;
existing_map->offset = lib_php->p_offset;
- existing_map->memsz = lib_php->p_filesz;
+ existing_map->memsz = ROUNDUP(lib_php->p_memsz, page_size);
}
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java Wed Jul 05 19:19:29 2017 +0200
@@ -51,6 +51,7 @@
private static int HAS_GENERIC_SIGNATURE;
private static int HAS_METHOD_ANNOTATIONS;
private static int HAS_PARAMETER_ANNOTATIONS;
+ private static int HAS_METHOD_PARAMETERS;
private static int HAS_DEFAULT_ANNOTATIONS;
private static int HAS_TYPE_ANNOTATIONS;
@@ -70,6 +71,7 @@
HAS_GENERIC_SIGNATURE = db.lookupIntConstant("ConstMethod::_has_generic_signature").intValue();
HAS_METHOD_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_method_annotations").intValue();
HAS_PARAMETER_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_parameter_annotations").intValue();
+ HAS_METHOD_PARAMETERS = db.lookupIntConstant("ConstMethod::_has_method_parameters").intValue();
HAS_DEFAULT_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_default_annotations").intValue();
HAS_TYPE_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_type_annotations").intValue();
@@ -85,6 +87,9 @@
// start of byte code
bytecodeOffset = type.getSize();
+ type = db.lookupType("MethodParametersElement");
+ methodParametersElementSize = type.getSize();
+
type = db.lookupType("CheckedExceptionElement");
checkedExceptionElementSize = type.getSize();
@@ -113,7 +118,7 @@
// start of bytecode
private static long bytecodeOffset;
-
+ private static long methodParametersElementSize;
private static long checkedExceptionElementSize;
private static long localVariableTableElementSize;
private static long exceptionTableElementSize;
@@ -387,6 +392,10 @@
return ret;
}
+ private boolean hasMethodParameters() {
+ return (getFlags() & HAS_METHOD_PARAMETERS) != 0;
+ }
+
private boolean hasGenericSignature() {
return (getFlags() & HAS_GENERIC_SIGNATURE) != 0;
}
@@ -442,11 +451,41 @@
return offsetOfLastU2Element();
}
- private long offsetOfCheckedExceptionsLength() {
+ private long offsetOfMethodParametersLength() {
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(hasMethodParameters(), "should only be called if table is present");
+ }
return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
offsetOfLastU2Element();
}
+ private int getMethodParametersLength() {
+ if (hasMethodParameters())
+ return (int) getAddress().getCIntegerAt(offsetOfMethodParametersLength(), 2, true);
+ else
+ return 0;
+ }
+
+ // Offset of start of checked exceptions
+ private long offsetOfMethodParameters() {
+ long offset = offsetOfMethodParametersLength();
+ long length = getMethodParametersLength();
+ if (Assert.ASSERTS_ENABLED) {
+ Assert.that(length > 0, "should only be called if method parameter information is present");
+ }
+ offset -= length * methodParametersElementSize;
+ return offset;
+ }
+
+ private long offsetOfCheckedExceptionsLength() {
+ if (hasMethodParameters())
+ return offsetOfMethodParameters() - sizeofShort;
+ else {
+ return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
+ offsetOfLastU2Element();
+ }
+ }
+
private int getCheckedExceptionsLength() {
if (hasCheckedExceptions()) {
return (int) getAddress().getCIntegerAt(offsetOfCheckedExceptionsLength(), 2, true);
@@ -496,6 +535,8 @@
return offsetOfExceptionTable() - sizeofShort;
} else if (hasCheckedExceptions()) {
return offsetOfCheckedExceptions() - sizeofShort;
+ } else if (hasMethodParameters()) {
+ return offsetOfMethodParameters() - sizeofShort;
} else {
return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
offsetOfLastU2Element();
@@ -526,6 +567,8 @@
}
if (hasCheckedExceptions()) {
return offsetOfCheckedExceptions() - sizeofShort;
+ } else if (hasMethodParameters()) {
+ return offsetOfMethodParameters() - sizeofShort;
} else {
return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
offsetOfLastU2Element();
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java Wed Jul 05 19:19:29 2017 +0200
@@ -51,8 +51,7 @@
public static void main(String[] args) {
ClassLoaderStats cls = new ClassLoaderStats();
- cls.start(args);
- cls.stop();
+ cls.execute(args);
}
private static class ClassData {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java Wed Jul 05 19:19:29 2017 +0200
@@ -54,8 +54,7 @@
public static void main(String[] args) {
FinalizerInfo finfo = new FinalizerInfo();
- finfo.start(args);
- finfo.stop();
+ finfo.execute(args);
}
public void run() {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/FlagDumper.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/FlagDumper.java Wed Jul 05 19:19:29 2017 +0200
@@ -54,7 +54,6 @@
public static void main(String[] args) {
FlagDumper fd = new FlagDumper();
- fd.start(args);
- fd.stop();
+ fd.execute(args);
}
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapDumper.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapDumper.java Wed Jul 05 19:19:29 2017 +0200
@@ -80,8 +80,7 @@
}
HeapDumper dumper = new HeapDumper(file);
- dumper.start(args);
- dumper.stop();
+ dumper.execute(args);
}
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java Wed Jul 05 19:19:29 2017 +0200
@@ -46,8 +46,7 @@
public static void main(String[] args) {
HeapSummary hs = new HeapSummary();
- hs.start(args);
- hs.stop();
+ hs.execute(args);
}
public void run() {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/JInfo.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/JInfo.java Wed Jul 05 19:19:29 2017 +0200
@@ -134,8 +134,7 @@
}
JInfo jinfo = new JInfo(mode);
- jinfo.start(args);
- jinfo.stop();
+ jinfo.execute(args);
}
private void printVMFlags() {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/JMap.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/JMap.java Wed Jul 05 19:19:29 2017 +0200
@@ -136,7 +136,9 @@
mode = MODE_HEAP_GRAPH_GXL;
} else {
System.err.println("unknown heap format:" + format);
- return;
+
+ // Exit with error status
+ System.exit(1);
}
} else {
copyArgs = false;
@@ -153,8 +155,7 @@
}
JMap jmap = new JMap(mode);
- jmap.start(args);
- jmap.stop();
+ jmap.execute(args);
}
public boolean writeHeapHprofBin(String fileName) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/JSnap.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/JSnap.java Wed Jul 05 19:19:29 2017 +0200
@@ -64,7 +64,6 @@
public static void main(String[] args) {
JSnap js = new JSnap();
- js.start(args);
- js.stop();
+ js.execute(args);
}
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/JStack.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/JStack.java Wed Jul 05 19:19:29 2017 +0200
@@ -89,8 +89,7 @@
}
JStack jstack = new JStack(mixedMode, concurrentLocks);
- jstack.start(args);
- jstack.stop();
+ jstack.execute(args);
}
private boolean mixedMode;
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/ObjectHistogram.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/ObjectHistogram.java Wed Jul 05 19:19:29 2017 +0200
@@ -61,7 +61,6 @@
public static void main(String[] args) {
ObjectHistogram oh = new ObjectHistogram();
- oh.start(args);
- oh.stop();
+ oh.execute(args);
}
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/PMap.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/PMap.java Wed Jul 05 19:19:29 2017 +0200
@@ -69,7 +69,6 @@
public static void main(String[] args) throws Exception {
PMap t = new PMap();
- t.start(args);
- t.stop();
+ t.execute(args);
}
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java Wed Jul 05 19:19:29 2017 +0200
@@ -182,8 +182,7 @@
public static void main(String[] args) throws Exception {
PStack t = new PStack();
- t.start(args);
- t.stop();
+ t.execute(args);
}
// -- Internals only below this point
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/StackTrace.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/StackTrace.java Wed Jul 05 19:19:29 2017 +0200
@@ -137,8 +137,7 @@
public static void main(String[] args) {
StackTrace st = new StackTrace();
- st.start(args);
- st.stop();
+ st.execute(args);
}
private boolean verbose;
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/SysPropsDumper.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/SysPropsDumper.java Wed Jul 05 19:19:29 2017 +0200
@@ -58,7 +58,6 @@
public static void main(String[] args) {
SysPropsDumper pd = new SysPropsDumper();
- pd.start(args);
- pd.stop();
+ pd.execute(args);
}
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java Wed Jul 05 19:19:29 2017 +0200
@@ -26,6 +26,7 @@
import java.io.PrintStream;
import java.util.Hashtable;
+
import sun.jvm.hotspot.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.debugger.*;
@@ -105,26 +106,44 @@
public static void main(String[] args) {
<derived class> obj = new <derived class>;
- obj.start(args);
+ obj.execute(args);
}
*/
- protected void stop() {
+ protected void execute(String[] args) {
+ int returnStatus = 1;
+
+ try {
+ returnStatus = start(args);
+ } finally {
+ stop();
+ }
+
+ // Exit with 0 or 1
+ System.exit(returnStatus);
+ }
+
+ public void stop() {
if (agent != null) {
agent.detach();
}
}
- protected void start(String[] args) {
+ private int start(String[] args) {
+
if ((args.length < 1) || (args.length > 2)) {
usage();
- return;
+ return 1;
}
// Attempt to handle -h or -help or some invalid flag
- if (args[0].startsWith("-")) {
+ if (args[0].startsWith("-h")) {
usage();
+ return 0;
+ } else if (args[0].startsWith("-")) {
+ usage();
+ return 1;
}
PrintStream err = System.err;
@@ -154,6 +173,7 @@
default:
usage();
+ return 1;
}
agent = new HotSpotAgent();
@@ -191,15 +211,16 @@
break;
}
if (e.getMessage() != null) {
- err.print(e.getMessage());
+ err.println(e.getMessage());
e.printStackTrace();
}
err.println();
- return;
+ return 1;
}
err.println("Debugger attached successfully.");
startInternal();
+ return 0;
}
// When using an existing JVMDebugger.
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java Wed Jul 05 19:19:29 2017 +0200
@@ -177,7 +177,6 @@
public static void main(String[] args) {
ClassDump cd = new ClassDump();
- cd.start(args);
- cd.stop();
+ cd.execute(args);
}
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/soql/JSDB.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/soql/JSDB.java Wed Jul 05 19:19:29 2017 +0200
@@ -42,8 +42,7 @@
public static void main(String[] args) {
JSDB jsdb = new JSDB();
- jsdb.start(args);
- jsdb.stop();
+ jsdb.execute(args);
}
public void run() {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/soql/SOQL.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/soql/SOQL.java Wed Jul 05 19:19:29 2017 +0200
@@ -40,8 +40,7 @@
public class SOQL extends Tool {
public static void main(String[] args) {
SOQL soql = new SOQL();
- soql.start(args);
- soql.stop();
+ soql.execute(args);
}
public SOQL() {
--- a/hotspot/make/hotspot_version Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/make/hotspot_version Wed Jul 05 19:19:29 2017 +0200
@@ -35,7 +35,7 @@
HS_MAJOR_VER=25
HS_MINOR_VER=0
-HS_BUILD_NUMBER=55
+HS_BUILD_NUMBER=56
JDK_MAJOR_VER=1
JDK_MINOR_VER=8
--- a/hotspot/make/jprt.properties Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/make/jprt.properties Wed Jul 05 19:19:29 2017 +0200
@@ -24,12 +24,7 @@
# Properties for jprt
-# All build result bundles are full jdks, so the 64bit testing does not
-# need the 32bit sibling bundle installed.
-# Note: If the hotspot/make/Makefile changed to only bundle the 64bit files
-# when bundling 64bit, and stripped out the 64bit files from any 32bit
-# bundles, then this setting would be need to be "true".
-
+# All build result bundles are full jdks.
jprt.need.sibling.build=false
# At submit time, the release supplied will be in jprt.submit.release
@@ -52,21 +47,11 @@
# sparc etc.
# Define the Solaris platforms we want for the various releases
-jprt.my.solaris.sparc.jdk8=solaris_sparc_5.10
-jprt.my.solaris.sparc.jdk7=solaris_sparc_5.10
-jprt.my.solaris.sparc.jdk7u8=${jprt.my.solaris.sparc.jdk7}
-jprt.my.solaris.sparc=${jprt.my.solaris.sparc.${jprt.tools.default.release}}
-
jprt.my.solaris.sparcv9.jdk8=solaris_sparcv9_5.10
jprt.my.solaris.sparcv9.jdk7=solaris_sparcv9_5.10
jprt.my.solaris.sparcv9.jdk7u8=${jprt.my.solaris.sparcv9.jdk7}
jprt.my.solaris.sparcv9=${jprt.my.solaris.sparcv9.${jprt.tools.default.release}}
-jprt.my.solaris.i586.jdk8=solaris_i586_5.10
-jprt.my.solaris.i586.jdk7=solaris_i586_5.10
-jprt.my.solaris.i586.jdk7u8=${jprt.my.solaris.i586.jdk7}
-jprt.my.solaris.i586=${jprt.my.solaris.i586.${jprt.tools.default.release}}
-
jprt.my.solaris.x64.jdk8=solaris_x64_5.10
jprt.my.solaris.x64.jdk7=solaris_x64_5.10
jprt.my.solaris.x64.jdk7u8=${jprt.my.solaris.x64.jdk7}
@@ -133,9 +118,7 @@
# Standard list of jprt build targets for this source tree
jprt.build.targets.standard= \
- ${jprt.my.solaris.sparc}-{product|fastdebug}, \
${jprt.my.solaris.sparcv9}-{product|fastdebug|optimized}, \
- ${jprt.my.solaris.i586}-{product|fastdebug}, \
${jprt.my.solaris.x64}-{product|fastdebug}, \
${jprt.my.linux.i586}-{product|fastdebug}, \
${jprt.my.linux.x64}-{product|fastdebug|optimized}, \
@@ -145,7 +128,6 @@
${jprt.my.linux.armvh}-{product|fastdebug}
jprt.build.targets.open= \
- ${jprt.my.solaris.i586}-{productOpen}, \
${jprt.my.solaris.x64}-{debugOpen}, \
${jprt.my.linux.x64}-{productOpen}
@@ -168,31 +150,6 @@
# Subset lists of test targets for this source tree
-jprt.my.solaris.sparc.test.targets= \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jvm98, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-c2-jvm98_nontiered, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-scimark, \
- ${jprt.my.solaris.sparc}-product-{c1|c2}-runThese, \
- ${jprt.my.solaris.sparc}-fastdebug-c1-runThese_Xshare, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_CMS, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_G1, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCBasher_ParOldGC, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_SerialGC, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParallelGC, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParNewGC, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_CMS, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_G1, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-GCOld_ParOldGC, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-c2-jbb_default_nontiered, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_SerialGC, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_ParallelGC, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_CMS, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_G1, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-{c1|c2}-jbb_ParOldGC
-
jprt.my.solaris.sparcv9.test.targets= \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-jvm98_nontiered, \
@@ -242,37 +199,6 @@
${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_G1, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-GCOld_ParOldGC
-jprt.my.solaris.i586.test.targets= \
- ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-jvm98, \
- ${jprt.my.solaris.i586}-{product|fastdebug}-c2-jvm98_nontiered, \
- ${jprt.my.solaris.i586}-{product|fastdebug}-{c1|c2}-scimark, \
- ${jprt.my.solaris.i586}-product-{c1|c2}-runThese_Xcomp, \
- ${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xcomp, \
- ${jprt.my.solaris.i586}-fastdebug-c1-runThese_Xshare, \
- ${jprt.my.solaris.i586}-product-c1-GCBasher_SerialGC, \
- ${jprt.my.solaris.i586}-product-c1-GCBasher_ParallelGC, \
- ${jprt.my.solaris.i586}-product-c1-GCBasher_ParNewGC, \
- ${jprt.my.solaris.i586}-product-c1-GCBasher_CMS, \
- ${jprt.my.solaris.i586}-product-c1-GCBasher_G1, \
- ${jprt.my.solaris.i586}-product-c1-GCBasher_ParOldGC, \
- ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_SerialGC, \
- ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParallelGC, \
- ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParNewGC, \
- ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_CMS, \
- ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_G1, \
- ${jprt.my.solaris.i586}-fastdebug-c2-GCBasher_ParOldGC, \
- ${jprt.my.solaris.i586}-product-c1-GCOld_SerialGC, \
- ${jprt.my.solaris.i586}-product-c1-GCOld_ParallelGC, \
- ${jprt.my.solaris.i586}-product-c1-GCOld_ParNewGC, \
- ${jprt.my.solaris.i586}-product-c1-GCOld_CMS, \
- ${jprt.my.solaris.i586}-product-c1-GCOld_G1, \
- ${jprt.my.solaris.i586}-product-c1-GCOld_ParOldGC, \
- ${jprt.my.solaris.i586}-fastdebug-c2-jbb_default_nontiered, \
- ${jprt.my.solaris.i586}-fastdebug-c2-jbb_ParallelGC, \
- ${jprt.my.solaris.i586}-fastdebug-c2-jbb_CMS, \
- ${jprt.my.solaris.i586}-fastdebug-c2-jbb_G1, \
- ${jprt.my.solaris.i586}-fastdebug-c2-jbb_ParOldGC
-
jprt.my.linux.i586.test.targets = \
${jprt.my.linux.i586}-{product|fastdebug}-{c1|c2}-jvm98, \
${jprt.my.linux.i586}-{product|fastdebug}-c2-jvm98_nontiered, \
@@ -395,7 +321,6 @@
# Some basic "smoke" tests for OpenJDK builds
jprt.test.targets.open = \
${jprt.my.solaris.x64}-{productOpen|fastdebugOpen}-c2-jvm98, \
- ${jprt.my.solaris.i586}-{productOpen|fastdebugOpen}-c2-jvm98, \
${jprt.my.linux.x64}-{productOpen|fastdebugOpen}-c2-jvm98
# Testing for actual embedded builds is different to standard
@@ -407,9 +332,7 @@
jprt.test.targets.standard = \
${jprt.my.linux.i586.test.targets.embedded}, \
- ${jprt.my.solaris.sparc.test.targets}, \
${jprt.my.solaris.sparcv9.test.targets}, \
- ${jprt.my.solaris.i586.test.targets}, \
${jprt.my.solaris.x64.test.targets}, \
${jprt.my.linux.i586.test.targets}, \
${jprt.my.linux.x64.test.targets}, \
@@ -420,15 +343,12 @@
jprt.test.targets.embedded= \
${jprt.my.linux.i586.test.targets.embedded}, \
- ${jprt.my.solaris.sparc.test.targets}, \
${jprt.my.solaris.sparcv9.test.targets}, \
- ${jprt.my.solaris.i586.test.targets}, \
${jprt.my.solaris.x64.test.targets}, \
${jprt.my.linux.x64.test.targets}, \
${jprt.my.windows.i586.test.targets}, \
${jprt.my.windows.x64.test.targets}
-
jprt.test.targets.jdk8=${jprt.test.targets.standard}
jprt.test.targets.jdk7=${jprt.test.targets.standard}
jprt.test.targets.jdk7u8=${jprt.test.targets.jdk7}
@@ -439,15 +359,11 @@
#jprt.make.rule.test.targets=*-product-*-packtest
jprt.make.rule.test.targets.standard.client = \
- ${jprt.my.solaris.sparc}-*-c1-clienttest, \
- ${jprt.my.solaris.i586}-*-c1-clienttest, \
${jprt.my.linux.i586}-*-c1-clienttest, \
${jprt.my.windows.i586}-*-c1-clienttest
jprt.make.rule.test.targets.standard.server = \
- ${jprt.my.solaris.sparc}-*-c2-servertest, \
${jprt.my.solaris.sparcv9}-*-c2-servertest, \
- ${jprt.my.solaris.i586}-*-c2-servertest, \
${jprt.my.solaris.x64}-*-c2-servertest, \
${jprt.my.linux.i586}-*-c2-servertest, \
${jprt.my.linux.x64}-*-c2-servertest, \
@@ -456,9 +372,7 @@
${jprt.my.windows.x64}-*-c2-servertest
jprt.make.rule.test.targets.standard.internalvmtests = \
- ${jprt.my.solaris.sparc}-fastdebug-c2-internalvmtests, \
${jprt.my.solaris.sparcv9}-fastdebug-c2-internalvmtests, \
- ${jprt.my.solaris.i586}-fastdebug-c2-internalvmtests, \
${jprt.my.solaris.x64}-fastdebug-c2-internalvmtests, \
${jprt.my.linux.i586}-fastdebug-c2-internalvmtests, \
${jprt.my.linux.x64}-fastdebug-c2-internalvmtests, \
@@ -467,16 +381,12 @@
${jprt.my.windows.x64}-fastdebug-c2-internalvmtests
jprt.make.rule.test.targets.standard.wbapi = \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-c2-wbapitest, \
${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-wbapitest, \
- ${jprt.my.solaris.i586}-{product|fastdebug}-c2-wbapitest, \
${jprt.my.solaris.x64}-{product|fastdebug}-c2-wbapitest, \
${jprt.my.linux.i586}-{product|fastdebug}-c2-wbapitest, \
${jprt.my.linux.x64}-{product|fastdebug}-c2-wbapitest, \
${jprt.my.windows.i586}-{product|fastdebug}-c2-wbapitest, \
${jprt.my.windows.x64}-{product|fastdebug}-c2-wbapitest, \
- ${jprt.my.solaris.sparc}-{product|fastdebug}-c1-wbapitest, \
- ${jprt.my.solaris.i586}-{product|fastdebug}-c1-wbapitest, \
${jprt.my.linux.i586}-{product|fastdebug}-c1-wbapitest, \
${jprt.my.windows.i586}-{product|fastdebug}-c1-wbapitest
--- a/hotspot/make/windows/makefiles/trace.make Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/make/windows/makefiles/trace.make Wed Jul 05 19:19:29 2017 +0200
@@ -40,8 +40,7 @@
traceEventIds.hpp \
traceTypes.hpp
-
-!if "$(OPENJDK)" != "true"
+!if EXISTS($(TraceAltSrcDir))
TraceGeneratedNames = $(TraceGeneratedNames) \
traceRequestables.hpp \
traceEventControl.hpp \
@@ -56,7 +55,7 @@
$(TraceOutDir)/traceEventIds.hpp \
$(TraceOutDir)/traceTypes.hpp
-!if "$(OPENJDK)" != "true"
+!if EXISTS($(TraceAltSrcDir))
TraceGeneratedFiles = $(TraceGeneratedFiles) \
$(TraceOutDir)/traceRequestables.hpp \
$(TraceOutDir)/traceEventControl.hpp \
@@ -68,7 +67,7 @@
XML_DEPS = $(TraceSrcDir)/trace.xml $(TraceSrcDir)/tracetypes.xml \
$(TraceSrcDir)/trace.dtd $(TraceSrcDir)/xinclude.mod
-!if "$(OPENJDK)" != "true"
+!if EXISTS($(TraceAltSrcDir))
XML_DEPS = $(XML_DEPS) $(TraceAltSrcDir)/traceevents.xml
!endif
@@ -87,7 +86,7 @@
@echo Generating $@
@$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceSrcDir)/traceTypes.xsl -OUT $(TraceOutDir)/traceTypes.hpp
-!if "$(OPENJDK)" == "true"
+!if !EXISTS($(TraceAltSrcDir))
$(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceSrcDir)/traceEventClasses.xsl $(XML_DEPS)
@echo Generating OpenJDK $@
--- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -53,6 +53,8 @@
opr = as_long_opr(reg);
} else if (type == T_OBJECT || type == T_ARRAY) {
opr = as_oop_opr(reg);
+ } else if (type == T_METADATA) {
+ opr = as_metadata_opr(reg);
} else {
opr = as_opr(reg);
}
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -2565,7 +2565,7 @@
Address receiver_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)) -
mdo_offset_bias);
__ ld_ptr(receiver_addr, tmp1);
- __ verify_oop(tmp1);
+ __ verify_klass_ptr(tmp1);
__ cmp_and_brx_short(recv, tmp1, Assembler::notEqual, Assembler::pt, next_test);
Address data_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i)) -
mdo_offset_bias);
--- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -404,7 +404,9 @@
if (id == fast_new_instance_init_check_id) {
// make sure the klass is initialized
__ ldub(G5_klass, in_bytes(InstanceKlass::init_state_offset()), G3_t1);
- __ cmp_and_br_short(G3_t1, InstanceKlass::fully_initialized, Assembler::notEqual, Assembler::pn, slow_path);
+ __ cmp(G3_t1, InstanceKlass::fully_initialized);
+ __ br(Assembler::notEqual, false, Assembler::pn, slow_path);
+ __ delayed()->nop();
}
#ifdef ASSERT
// assert object can be fast path allocated
@@ -515,7 +517,9 @@
// check that array length is small enough for fast path
__ set(C1_MacroAssembler::max_array_allocation_length, G3_t1);
- __ cmp_and_br_short(G4_length, G3_t1, Assembler::greaterUnsigned, Assembler::pn, slow_path);
+ __ cmp(G4_length, G3_t1);
+ __ br(Assembler::greaterUnsigned, false, Assembler::pn, slow_path);
+ __ delayed()->nop();
// if we got here then the TLAB allocation failed, so try
// refilling the TLAB or allocating directly from eden.
--- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -3333,7 +3333,8 @@
if (CMSIncrementalMode || !Universe::heap()->supports_inline_contig_alloc()) {
// No allocation in the shared eden.
- ba_short(slow_case);
+ ba(slow_case);
+ delayed()->nop();
}
ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), top);
@@ -3358,7 +3359,8 @@
add(t2, 1, t2);
stw(t2, G2_thread, in_bytes(JavaThread::tlab_slow_allocations_offset()));
}
- ba_short(try_eden);
+ ba(try_eden);
+ delayed()->nop();
bind(discard_tlab);
if (TLABStats) {
@@ -3420,7 +3422,8 @@
sub(top, ThreadLocalAllocBuffer::alignment_reserve_in_bytes(), top);
st_ptr(top, G2_thread, in_bytes(JavaThread::tlab_end_offset()));
verify_tlab();
- ba_short(retry);
+ ba(retry);
+ delayed()->nop();
}
void MacroAssembler::incr_allocated_bytes(RegisterOrConstant size_in_bytes,
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad Wed Jul 05 19:19:29 2017 +0200
@@ -2022,6 +2022,10 @@
return G1_REGI_mask();
}
+const RegMask Matcher::mathExactL_result_proj_mask() {
+ return G1_REGL_mask();
+}
+
const RegMask Matcher::mathExactI_flags_proj_mask() {
return INT_FLAGS_mask();
}
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -1405,6 +1405,15 @@
}
}
+void Assembler::imull(Register dst, Address src) {
+ InstructionMark im(this);
+ prefix(src, dst);
+ emit_int8(0x0F);
+ emit_int8((unsigned char) 0xAF);
+ emit_operand(dst, src);
+}
+
+
void Assembler::incl(Address dst) {
// Don't use it directly. Use MacroAssembler::increment() instead.
InstructionMark im(this);
@@ -5024,6 +5033,14 @@
}
}
+void Assembler::imulq(Register dst, Address src) {
+ InstructionMark im(this);
+ prefixq(src, dst);
+ emit_int8(0x0F);
+ emit_int8((unsigned char) 0xAF);
+ emit_operand(dst, src);
+}
+
void Assembler::incl(Register dst) {
// Don't use it directly. Use MacroAssembler::incrementl() instead.
// Use two-byte form (one-byte from is a REX prefix in 64-bit mode)
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -1162,9 +1162,13 @@
void imull(Register dst, Register src);
void imull(Register dst, Register src, int value);
+ void imull(Register dst, Address src);
void imulq(Register dst, Register src);
void imulq(Register dst, Register src, int value);
+#ifdef _LP64
+ void imulq(Register dst, Address src);
+#endif
// jcc is the generic conditional branch generator to run-
--- a/hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/bytecodeInterpreter_x86.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -40,11 +40,8 @@
#include "runtime/synchronizer.hpp"
#include "runtime/vframeArray.hpp"
#include "utilities/debug.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
-# include "interp_masm_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
-# include "interp_masm_x86_64.hpp"
+#ifdef TARGET_ARCH_x86
+# include "interp_masm_x86.hpp"
#endif
#ifdef CC_INTERP
--- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -52,6 +52,8 @@
#endif // _LP64
} else if (type == T_OBJECT || type == T_ARRAY) {
opr = as_oop_opr(reg);
+ } else if (type == T_METADATA) {
+ opr = as_metadata_opr(reg);
} else {
opr = as_opr(reg);
}
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -432,15 +432,16 @@
int offset = code_offset();
// Fetch the exception from TLS and clear out exception related thread state
- __ get_thread(rsi);
- __ movptr(rax, Address(rsi, JavaThread::exception_oop_offset()));
- __ movptr(Address(rsi, JavaThread::exception_oop_offset()), (intptr_t)NULL_WORD);
- __ movptr(Address(rsi, JavaThread::exception_pc_offset()), (intptr_t)NULL_WORD);
+ Register thread = NOT_LP64(rsi) LP64_ONLY(r15_thread);
+ NOT_LP64(__ get_thread(rsi));
+ __ movptr(rax, Address(thread, JavaThread::exception_oop_offset()));
+ __ movptr(Address(thread, JavaThread::exception_oop_offset()), (intptr_t)NULL_WORD);
+ __ movptr(Address(thread, JavaThread::exception_pc_offset()), (intptr_t)NULL_WORD);
__ bind(_unwind_handler_entry);
__ verify_not_null_oop(rax);
if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) {
- __ mov(rsi, rax); // Preserve the exception
+ __ mov(rbx, rax); // Preserve the exception (rbx is always callee-saved)
}
// Preform needed unlocking
@@ -448,19 +449,24 @@
if (method()->is_synchronized()) {
monitor_address(0, FrameMap::rax_opr);
stub = new MonitorExitStub(FrameMap::rax_opr, true, 0);
- __ unlock_object(rdi, rbx, rax, *stub->entry());
+ __ unlock_object(rdi, rsi, rax, *stub->entry());
__ bind(*stub->continuation());
}
if (compilation()->env()->dtrace_method_probes()) {
+#ifdef _LP64
+ __ mov(rdi, r15_thread);
+ __ mov_metadata(rsi, method()->constant_encoding());
+#else
__ get_thread(rax);
__ movptr(Address(rsp, 0), rax);
__ mov_metadata(Address(rsp, sizeof(void*)), method()->constant_encoding());
+#endif
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit)));
}
if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) {
- __ mov(rax, rsi); // Restore the exception
+ __ mov(rax, rbx); // Restore the exception
}
// remove the activation and dispatch to the unwind handler
@@ -1206,6 +1212,10 @@
LIR_Address* addr = src->as_address_ptr();
Address from_addr = as_Address(addr);
+ if (addr->base()->type() == T_OBJECT) {
+ __ verify_oop(addr->base()->as_pointer_register());
+ }
+
switch (type) {
case T_BOOLEAN: // fall through
case T_BYTE: // fall through
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -79,7 +79,7 @@
// GC Ergo Flags
define_pd_global(uintx, CMSYoungGenPerWorker, 64*M); // default max size of CMS young gen, per GC worker thread
-define_pd_global(uintx, TypeProfileLevel, 11);
+define_pd_global(uintx, TypeProfileLevel, 111);
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct) \
\
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "interp_masm_x86.hpp"
+#include "interpreter/interpreter.hpp"
+#include "oops/methodData.hpp"
+
+#ifndef CC_INTERP
+void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) {
+ Label update, next, none;
+
+ verify_oop(obj);
+
+ testptr(obj, obj);
+ jccb(Assembler::notZero, update);
+ orptr(mdo_addr, TypeEntries::null_seen);
+ jmpb(next);
+
+ bind(update);
+ load_klass(obj, obj);
+
+ xorptr(obj, mdo_addr);
+ testptr(obj, TypeEntries::type_klass_mask);
+ jccb(Assembler::zero, next); // klass seen before, nothing to
+ // do. The unknown bit may have been
+ // set already but no need to check.
+
+ testptr(obj, TypeEntries::type_unknown);
+ jccb(Assembler::notZero, next); // already unknown. Nothing to do anymore.
+
+ cmpptr(mdo_addr, 0);
+ jccb(Assembler::equal, none);
+ cmpptr(mdo_addr, TypeEntries::null_seen);
+ jccb(Assembler::equal, none);
+ // There is a chance that the checks above (re-reading profiling
+ // data from memory) fail if another thread has just set the
+ // profiling to this obj's klass
+ xorptr(obj, mdo_addr);
+ testptr(obj, TypeEntries::type_klass_mask);
+ jccb(Assembler::zero, next);
+
+ // different than before. Cannot keep accurate profile.
+ orptr(mdo_addr, TypeEntries::type_unknown);
+ jmpb(next);
+
+ bind(none);
+ // first time here. Set profile type.
+ movptr(mdo_addr, obj);
+
+ bind(next);
+}
+
+void InterpreterMacroAssembler::profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual) {
+ if (!ProfileInterpreter) {
+ return;
+ }
+
+ if (MethodData::profile_arguments() || MethodData::profile_return()) {
+ Label profile_continue;
+
+ test_method_data_pointer(mdp, profile_continue);
+
+ int off_to_start = is_virtual ? in_bytes(VirtualCallData::virtual_call_data_size()) : in_bytes(CounterData::counter_data_size());
+
+ cmpb(Address(mdp, in_bytes(DataLayout::tag_offset()) - off_to_start), is_virtual ? DataLayout::virtual_call_type_data_tag : DataLayout::call_type_data_tag);
+ jcc(Assembler::notEqual, profile_continue);
+
+ if (MethodData::profile_arguments()) {
+ Label done;
+ int off_to_args = in_bytes(TypeEntriesAtCall::args_data_offset());
+ addptr(mdp, off_to_args);
+
+ for (int i = 0; i < TypeProfileArgsLimit; i++) {
+ if (i > 0 || MethodData::profile_return()) {
+ // If return value type is profiled we may have no argument to profile
+ movptr(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
+ subl(tmp, i*TypeStackSlotEntries::per_arg_count());
+ cmpl(tmp, TypeStackSlotEntries::per_arg_count());
+ jcc(Assembler::less, done);
+ }
+ movptr(tmp, Address(callee, Method::const_offset()));
+ load_unsigned_short(tmp, Address(tmp, ConstMethod::size_of_parameters_offset()));
+ // stack offset o (zero based) from the start of the argument
+ // list, for n arguments translates into offset n - o - 1 from
+ // the end of the argument list
+ subptr(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::stack_slot_offset(i))-off_to_args));
+ subl(tmp, 1);
+ Address arg_addr = argument_address(tmp);
+ movptr(tmp, arg_addr);
+
+ Address mdo_arg_addr(mdp, in_bytes(TypeEntriesAtCall::argument_type_offset(i))-off_to_args);
+ profile_obj_type(tmp, mdo_arg_addr);
+
+ int to_add = in_bytes(TypeStackSlotEntries::per_arg_size());
+ addptr(mdp, to_add);
+ off_to_args += to_add;
+ }
+
+ if (MethodData::profile_return()) {
+ movptr(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
+ subl(tmp, TypeProfileArgsLimit*TypeStackSlotEntries::per_arg_count());
+ }
+
+ bind(done);
+
+ if (MethodData::profile_return()) {
+ // We're right after the type profile for the last
+ // argument. tmp is the number of cell left in the
+ // CallTypeData/VirtualCallTypeData to reach its end. Non null
+ // if there's a return to profile.
+ assert(ReturnTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(), "can't move past ret type");
+ shll(tmp, exact_log2(DataLayout::cell_size));
+ addptr(mdp, tmp);
+ }
+ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp);
+ } else {
+ assert(MethodData::profile_return(), "either profile call args or call ret");
+ update_mdp_by_constant(mdp, in_bytes(ReturnTypeEntry::size()));
+ }
+
+ // mdp points right after the end of the
+ // CallTypeData/VirtualCallTypeData, right after the cells for the
+ // return value type if there's one
+
+ bind(profile_continue);
+ }
+}
+
+void InterpreterMacroAssembler::profile_return_type(Register mdp, Register ret, Register tmp) {
+ assert_different_registers(mdp, ret, tmp, _bcp_register);
+ if (ProfileInterpreter && MethodData::profile_return()) {
+ Label profile_continue, done;
+
+ test_method_data_pointer(mdp, profile_continue);
+
+ if (MethodData::profile_return_jsr292_only()) {
+ // If we don't profile all invoke bytecodes we must make sure
+ // it's a bytecode we indeed profile. We can't go back to the
+ // begining of the ProfileData we intend to update to check its
+ // type because we're right after it and we don't known its
+ // length
+ Label do_profile;
+ cmpb(Address(_bcp_register, 0), Bytecodes::_invokedynamic);
+ jcc(Assembler::equal, do_profile);
+ cmpb(Address(_bcp_register, 0), Bytecodes::_invokehandle);
+ jcc(Assembler::equal, do_profile);
+ get_method(tmp);
+ cmpb(Address(tmp, Method::intrinsic_id_offset_in_bytes()), vmIntrinsics::_compiledLambdaForm);
+ jcc(Assembler::notEqual, profile_continue);
+
+ bind(do_profile);
+ }
+
+ Address mdo_ret_addr(mdp, -in_bytes(ReturnTypeEntry::size()));
+ mov(tmp, ret);
+ profile_obj_type(tmp, mdo_ret_addr);
+
+ bind(profile_continue);
+ }
+}
+
+void InterpreterMacroAssembler::profile_parameters_type(Register mdp, Register tmp1, Register tmp2) {
+ if (ProfileInterpreter && MethodData::profile_parameters()) {
+ Label profile_continue, done;
+
+ test_method_data_pointer(mdp, profile_continue);
+
+ // Load the offset of the area within the MDO used for
+ // parameters. If it's negative we're not profiling any parameters
+ movl(tmp1, Address(mdp, in_bytes(MethodData::parameters_type_data_di_offset()) - in_bytes(MethodData::data_offset())));
+ testl(tmp1, tmp1);
+ jcc(Assembler::negative, profile_continue);
+
+ // Compute a pointer to the area for parameters from the offset
+ // and move the pointer to the slot for the last
+ // parameters. Collect profiling from last parameter down.
+ // mdo start + parameters offset + array length - 1
+ addptr(mdp, tmp1);
+ movptr(tmp1, Address(mdp, in_bytes(ArrayData::array_len_offset())));
+ decrement(tmp1, TypeStackSlotEntries::per_arg_count());
+
+ Label loop;
+ bind(loop);
+
+ int off_base = in_bytes(ParametersTypeData::stack_slot_offset(0));
+ int type_base = in_bytes(ParametersTypeData::type_offset(0));
+ Address::ScaleFactor per_arg_scale = Address::times(DataLayout::cell_size);
+ Address arg_off(mdp, tmp1, per_arg_scale, off_base);
+ Address arg_type(mdp, tmp1, per_arg_scale, type_base);
+
+ // load offset on the stack from the slot for this parameter
+ movptr(tmp2, arg_off);
+ negptr(tmp2);
+ // read the parameter from the local area
+ movptr(tmp2, Address(_locals_register, tmp2, Interpreter::stackElementScale()));
+
+ // profile the parameter
+ profile_obj_type(tmp2, arg_type);
+
+ // go to next parameter
+ decrement(tmp1, TypeStackSlotEntries::per_arg_count());
+ jcc(Assembler::positive, loop);
+
+ bind(profile_continue);
+ }
+}
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef CPU_X86_VM_INTERP_MASM_X86_HPP
+#define CPU_X86_VM_INTERP_MASM_X86_HPP
+
+#include "asm/macroAssembler.hpp"
+#include "asm/macroAssembler.inline.hpp"
+#include "interpreter/invocationCounter.hpp"
+#include "runtime/frame.hpp"
+
+// This file specializes the assember with interpreter-specific macros
+
+
+class InterpreterMacroAssembler: public MacroAssembler {
+
+#ifdef TARGET_ARCH_MODEL_x86_32
+# include "interp_masm_x86_32.hpp"
+#endif
+#ifdef TARGET_ARCH_MODEL_x86_64
+# include "interp_masm_x86_64.hpp"
+#endif
+
+ private:
+
+ Register _locals_register; // register that contains the pointer to the locals
+ Register _bcp_register; // register that contains the bcp
+
+ public:
+#ifndef CC_INTERP
+ void profile_obj_type(Register obj, const Address& mdo_addr);
+ void profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual);
+ void profile_return_type(Register mdp, Register ret, Register tmp);
+ void profile_parameters_type(Register mdp, Register tmp1, Register tmp2);
+#endif /* !CC_INTERP */
+
+};
+
+#endif // CPU_X86_VM_INTERP_MASM_X86_HPP
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
-#include "interp_masm_x86_32.hpp"
+#include "interp_masm_x86.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreterRuntime.hpp"
#include "oops/arrayOop.hpp"
@@ -1046,159 +1046,6 @@
}
}
-void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) {
- Label update, next, none;
-
- verify_oop(obj);
-
- testptr(obj, obj);
- jccb(Assembler::notZero, update);
- orptr(mdo_addr, TypeEntries::null_seen);
- jmpb(next);
-
- bind(update);
- load_klass(obj, obj);
-
- xorptr(obj, mdo_addr);
- testptr(obj, TypeEntries::type_klass_mask);
- jccb(Assembler::zero, next); // klass seen before, nothing to
- // do. The unknown bit may have been
- // set already but no need to check.
-
- testptr(obj, TypeEntries::type_unknown);
- jccb(Assembler::notZero, next); // already unknown. Nothing to do anymore.
-
- cmpptr(mdo_addr, 0);
- jccb(Assembler::equal, none);
- cmpptr(mdo_addr, TypeEntries::null_seen);
- jccb(Assembler::equal, none);
- // There is a chance that the checks above (re-reading profiling
- // data from memory) fail if another thread has just set the
- // profiling to this obj's klass
- xorptr(obj, mdo_addr);
- testptr(obj, TypeEntries::type_klass_mask);
- jccb(Assembler::zero, next);
-
- // different than before. Cannot keep accurate profile.
- orptr(mdo_addr, TypeEntries::type_unknown);
- jmpb(next);
-
- bind(none);
- // first time here. Set profile type.
- movptr(mdo_addr, obj);
-
- bind(next);
-}
-
-void InterpreterMacroAssembler::profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual) {
- if (!ProfileInterpreter) {
- return;
- }
-
- if (MethodData::profile_arguments() || MethodData::profile_return()) {
- Label profile_continue;
-
- test_method_data_pointer(mdp, profile_continue);
-
- int off_to_start = is_virtual ? in_bytes(VirtualCallData::virtual_call_data_size()) : in_bytes(CounterData::counter_data_size());
-
- cmpb(Address(mdp, in_bytes(DataLayout::tag_offset()) - off_to_start), is_virtual ? DataLayout::virtual_call_type_data_tag : DataLayout::call_type_data_tag);
- jcc(Assembler::notEqual, profile_continue);
-
- if (MethodData::profile_arguments()) {
- Label done;
- int off_to_args = in_bytes(TypeEntriesAtCall::args_data_offset());
- addptr(mdp, off_to_args);
-
- for (int i = 0; i < TypeProfileArgsLimit; i++) {
- if (i > 0 || MethodData::profile_return()) {
- // If return value type is profiled we may have no argument to profile
- movl(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
- subl(tmp, i*TypeStackSlotEntries::per_arg_count());
- cmpl(tmp, TypeStackSlotEntries::per_arg_count());
- jcc(Assembler::less, done);
- }
- movptr(tmp, Address(callee, Method::const_offset()));
- load_unsigned_short(tmp, Address(tmp, ConstMethod::size_of_parameters_offset()));
- // stack offset o (zero based) from the start of the argument
- // list, for n arguments translates into offset n - o - 1 from
- // the end of the argument list
- subl(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::stack_slot_offset(i))-off_to_args));
- subl(tmp, 1);
- Address arg_addr = argument_address(tmp);
- movptr(tmp, arg_addr);
-
- Address mdo_arg_addr(mdp, in_bytes(TypeEntriesAtCall::argument_type_offset(i))-off_to_args);
- profile_obj_type(tmp, mdo_arg_addr);
-
- int to_add = in_bytes(TypeStackSlotEntries::per_arg_size());
- addptr(mdp, to_add);
- off_to_args += to_add;
- }
-
- if (MethodData::profile_return()) {
- movl(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
- subl(tmp, TypeProfileArgsLimit*TypeStackSlotEntries::per_arg_count());
- }
-
- bind(done);
-
- if (MethodData::profile_return()) {
- // We're right after the type profile for the last
- // argument. tmp is the number of cell left in the
- // CallTypeData/VirtualCallTypeData to reach its end. Non null
- // if there's a return to profile.
- assert(ReturnTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(), "can't move past ret type");
- shll(tmp, exact_log2(DataLayout::cell_size));
- addptr(mdp, tmp);
- }
- movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp);
- } else {
- assert(MethodData::profile_return(), "either profile call args or call ret");
- update_mdp_by_constant(mdp, in_bytes(ReturnTypeEntry::size()));
- }
-
- // mdp points right after the end of the
- // CallTypeData/VirtualCallTypeData, right after the cells for the
- // return value type if there's one
-
- bind(profile_continue);
- }
-}
-
-void InterpreterMacroAssembler::profile_return_type(Register mdp, Register ret, Register tmp) {
- assert_different_registers(mdp, ret, tmp, rsi);
- if (ProfileInterpreter && MethodData::profile_return()) {
- Label profile_continue, done;
-
- test_method_data_pointer(mdp, profile_continue);
-
- if (MethodData::profile_return_jsr292_only()) {
- // If we don't profile all invoke bytecodes we must make sure
- // it's a bytecode we indeed profile. We can't go back to the
- // begining of the ProfileData we intend to update to check its
- // type because we're right after it and we don't known its
- // length
- Label do_profile;
- cmpb(Address(rsi, 0), Bytecodes::_invokedynamic);
- jcc(Assembler::equal, do_profile);
- cmpb(Address(rsi, 0), Bytecodes::_invokehandle);
- jcc(Assembler::equal, do_profile);
- get_method(tmp);
- cmpb(Address(tmp, Method::intrinsic_id_offset_in_bytes()), vmIntrinsics::_compiledLambdaForm);
- jcc(Assembler::notEqual, profile_continue);
-
- bind(do_profile);
- }
-
- Address mdo_ret_addr(mdp, -in_bytes(ReturnTypeEntry::size()));
- mov(tmp, ret);
- profile_obj_type(tmp, mdo_ret_addr);
-
- bind(profile_continue);
- }
-}
-
void InterpreterMacroAssembler::profile_call(Register mdp) {
if (ProfileInterpreter) {
Label profile_continue;
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -22,18 +22,6 @@
*
*/
-#ifndef CPU_X86_VM_INTERP_MASM_X86_32_HPP
-#define CPU_X86_VM_INTERP_MASM_X86_32_HPP
-
-#include "asm/macroAssembler.hpp"
-#include "asm/macroAssembler.inline.hpp"
-#include "interpreter/invocationCounter.hpp"
-#include "runtime/frame.hpp"
-
-// This file specializes the assember with interpreter-specific macros
-
-
-class InterpreterMacroAssembler: public MacroAssembler {
#ifndef CC_INTERP
protected:
// Interpreter specific version of call_VM_base
@@ -59,7 +47,7 @@
#endif /* CC_INTERP */
public:
- InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code) {}
+ InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code), _locals_register(rdi), _bcp_register(rsi) {}
void load_earlyret_value(TosState state);
@@ -215,9 +203,6 @@
void profile_taken_branch(Register mdp, Register bumped_count);
void profile_not_taken_branch(Register mdp);
- void profile_obj_type(Register obj, const Address& mdo_addr);
- void profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual);
- void profile_return_type(Register mdp, Register ret, Register tmp);
void profile_call(Register mdp);
void profile_final_call(Register mdp);
void profile_virtual_call(Register receiver, Register mdp, Register scratch2,
@@ -236,7 +221,3 @@
// support for jvmti
void notify_method_entry();
void notify_method_exit(TosState state, NotifyMethodExitMode mode);
-
-};
-
-#endif // CPU_X86_VM_INTERP_MASM_X86_32_HPP
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -23,7 +23,7 @@
*/
#include "precompiled.hpp"
-#include "interp_masm_x86_64.hpp"
+#include "interp_masm_x86.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreterRuntime.hpp"
#include "oops/arrayOop.hpp"
@@ -1067,160 +1067,6 @@
}
}
-void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) {
- Label update, next, none;
-
- verify_oop(obj);
-
- testptr(obj, obj);
- jccb(Assembler::notZero, update);
- orptr(mdo_addr, TypeEntries::null_seen);
- jmpb(next);
-
- bind(update);
- load_klass(obj, obj);
-
- xorptr(obj, mdo_addr);
- testptr(obj, TypeEntries::type_klass_mask);
- jccb(Assembler::zero, next); // klass seen before, nothing to
- // do. The unknown bit may have been
- // set already but no need to check.
-
- testptr(obj, TypeEntries::type_unknown);
- jccb(Assembler::notZero, next); // already unknown. Nothing to do anymore.
-
- // There is a chance that by the time we do these checks (re-reading
- // profiling data from memory) another thread has set the profling
- // to this obj's klass and we set the profiling as unknow
- // erroneously
- cmpptr(mdo_addr, 0);
- jccb(Assembler::equal, none);
- cmpptr(mdo_addr, TypeEntries::null_seen);
- jccb(Assembler::equal, none);
- // There is a chance that the checks above (re-reading profiling
- // data from memory) fail if another thread has just set the
- // profiling to this obj's klass
- xorptr(obj, mdo_addr);
- testptr(obj, TypeEntries::type_klass_mask);
- jccb(Assembler::zero, next);
-
- // different than before. Cannot keep accurate profile.
- orptr(mdo_addr, TypeEntries::type_unknown);
- jmpb(next);
-
- bind(none);
- // first time here. Set profile type.
- movptr(mdo_addr, obj);
-
- bind(next);
-}
-
-void InterpreterMacroAssembler::profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual) {
- if (!ProfileInterpreter) {
- return;
- }
-
- if (MethodData::profile_arguments() || MethodData::profile_return()) {
- Label profile_continue;
-
- test_method_data_pointer(mdp, profile_continue);
-
- int off_to_start = is_virtual ? in_bytes(VirtualCallData::virtual_call_data_size()) : in_bytes(CounterData::counter_data_size());
-
- cmpb(Address(mdp, in_bytes(DataLayout::tag_offset()) - off_to_start), is_virtual ? DataLayout::virtual_call_type_data_tag : DataLayout::call_type_data_tag);
- jcc(Assembler::notEqual, profile_continue);
-
- if (MethodData::profile_arguments()) {
- Label done;
- int off_to_args = in_bytes(TypeEntriesAtCall::args_data_offset());
- addptr(mdp, off_to_args);
-
- for (int i = 0; i < TypeProfileArgsLimit; i++) {
- if (i > 0 || MethodData::profile_return()) {
- // If return value type is profiled we may have no argument to profile
- movq(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
- subl(tmp, i*TypeStackSlotEntries::per_arg_count());
- cmpl(tmp, TypeStackSlotEntries::per_arg_count());
- jcc(Assembler::less, done);
- }
- movptr(tmp, Address(callee, Method::const_offset()));
- load_unsigned_short(tmp, Address(tmp, ConstMethod::size_of_parameters_offset()));
- subq(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::stack_slot_offset(i))-off_to_args));
- subl(tmp, 1);
- Address arg_addr = argument_address(tmp);
- movptr(tmp, arg_addr);
-
- Address mdo_arg_addr(mdp, in_bytes(TypeEntriesAtCall::argument_type_offset(i))-off_to_args);
- profile_obj_type(tmp, mdo_arg_addr);
-
- int to_add = in_bytes(TypeStackSlotEntries::per_arg_size());
- addptr(mdp, to_add);
- off_to_args += to_add;
- }
-
- if (MethodData::profile_return()) {
- movq(tmp, Address(mdp, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args));
- subl(tmp, TypeProfileArgsLimit*TypeStackSlotEntries::per_arg_count());
- }
-
- bind(done);
-
- if (MethodData::profile_return()) {
- // We're right after the type profile for the last
- // argument. tmp is the number of cell left in the
- // CallTypeData/VirtualCallTypeData to reach its end. Non null
- // if there's a return to profile.
- assert(ReturnTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(), "can't move past ret type");
- shll(tmp, exact_log2(DataLayout::cell_size));
- addptr(mdp, tmp);
- }
- movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp);
- } else {
- assert(MethodData::profile_return(), "either profile call args or call ret");
- update_mdp_by_constant(mdp, in_bytes(ReturnTypeEntry::size()));
- }
-
- // mdp points right after the end of the
- // CallTypeData/VirtualCallTypeData, right after the cells for the
- // return value type if there's one
-
- bind(profile_continue);
- }
-}
-
-void InterpreterMacroAssembler::profile_return_type(Register mdp, Register ret, Register tmp) {
- assert_different_registers(mdp, ret, tmp, r13);
- if (ProfileInterpreter && MethodData::profile_return()) {
- Label profile_continue, done;
-
- test_method_data_pointer(mdp, profile_continue);
-
- if (MethodData::profile_return_jsr292_only()) {
- // If we don't profile all invoke bytecodes we must make sure
- // it's a bytecode we indeed profile. We can't go back to the
- // begining of the ProfileData we intend to update to check its
- // type because we're right after it and we don't known its
- // length
- Label do_profile;
- cmpb(Address(r13, 0), Bytecodes::_invokedynamic);
- jcc(Assembler::equal, do_profile);
- cmpb(Address(r13, 0), Bytecodes::_invokehandle);
- jcc(Assembler::equal, do_profile);
- get_method(tmp);
- cmpb(Address(tmp, Method::intrinsic_id_offset_in_bytes()), vmIntrinsics::_compiledLambdaForm);
- jcc(Assembler::notEqual, profile_continue);
-
- bind(do_profile);
- }
-
- Address mdo_ret_addr(mdp, -in_bytes(ReturnTypeEntry::size()));
- mov(tmp, ret);
- profile_obj_type(tmp, mdo_ret_addr);
-
- bind(profile_continue);
- }
-}
-
void InterpreterMacroAssembler::profile_call(Register mdp) {
if (ProfileInterpreter) {
Label profile_continue;
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -22,18 +22,6 @@
*
*/
-#ifndef CPU_X86_VM_INTERP_MASM_X86_64_HPP
-#define CPU_X86_VM_INTERP_MASM_X86_64_HPP
-
-#include "asm/macroAssembler.hpp"
-#include "asm/macroAssembler.inline.hpp"
-#include "interpreter/invocationCounter.hpp"
-#include "runtime/frame.hpp"
-
-// This file specializes the assember with interpreter-specific macros
-
-
-class InterpreterMacroAssembler: public MacroAssembler {
#ifndef CC_INTERP
protected:
// Interpreter specific version of call_VM_base
@@ -55,7 +43,7 @@
#endif // CC_INTERP
public:
- InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code) {}
+ InterpreterMacroAssembler(CodeBuffer* code) : MacroAssembler(code), _locals_register(r14), _bcp_register(r13) {}
void load_earlyret_value(TosState state);
@@ -224,9 +212,6 @@
void profile_taken_branch(Register mdp, Register bumped_count);
void profile_not_taken_branch(Register mdp);
- void profile_obj_type(Register obj, const Address& mdo_addr);
- void profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual);
- void profile_return_type(Register mdp, Register ret, Register tmp);
void profile_call(Register mdp);
void profile_final_call(Register mdp);
void profile_virtual_call(Register receiver, Register mdp,
@@ -253,6 +238,3 @@
// support for jvmti/dtrace
void notify_method_entry();
void notify_method_exit(TosState state, NotifyMethodExitMode mode);
-};
-
-#endif // CPU_X86_VM_INTERP_MASM_X86_64_HPP
--- a/hotspot/src/cpu/x86/vm/register_definitions_x86.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/register_definitions_x86.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -26,11 +26,8 @@
#include "asm/assembler.hpp"
#include "asm/register.hpp"
#include "register_x86.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
-# include "interp_masm_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
-# include "interp_masm_x86_64.hpp"
+#ifdef TARGET_ARCH_x86
+# include "interp_masm_x86.hpp"
#endif
REGISTER_DEFINITION(Register, noreg);
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -34,9 +34,9 @@
// Run with +PrintInterpreter to get the VM to print out the size.
// Max size with JVMTI
#ifdef AMD64
- const static int InterpreterCodeSize = 208 * 1024;
+ const static int InterpreterCodeSize = 256 * 1024;
#else
- const static int InterpreterCodeSize = 176 * 1024;
+ const static int InterpreterCodeSize = 224 * 1024;
#endif // AMD64
#endif // CPU_X86_VM_TEMPLATEINTERPRETER_X86_HPP
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -1490,6 +1490,7 @@
in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()));
__ movbool(do_not_unlock_if_synchronized, true);
+ __ profile_parameters_type(rax, rcx, rdx);
// increment invocation count & check for overflow
Label invocation_counter_overflow;
Label profile_method;
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -1497,6 +1497,7 @@
in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()));
__ movbool(do_not_unlock_if_synchronized, true);
+ __ profile_parameters_type(rax, rcx, rdx);
// increment invocation count & check for overflow
Label invocation_counter_overflow;
Label profile_method;
--- a/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -25,7 +25,7 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "code/vtableStubs.hpp"
-#include "interp_masm_x86_32.hpp"
+#include "interp_masm_x86.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
--- a/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -25,7 +25,7 @@
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "code/vtableStubs.hpp"
-#include "interp_masm_x86_64.hpp"
+#include "interp_masm_x86.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
--- a/hotspot/src/cpu/x86/vm/x86_32.ad Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad Wed Jul 05 19:19:29 2017 +0200
@@ -1538,6 +1538,11 @@
return EAX_REG_mask();
}
+const RegMask Matcher::mathExactL_result_proj_mask() {
+ ShouldNotReachHere();
+ return RegMask();
+}
+
const RegMask Matcher::mathExactI_flags_proj_mask() {
return INT_FLAGS_mask();
}
@@ -7519,7 +7524,7 @@
//----------Arithmetic Instructions--------------------------------------------
//----------Addition Instructions----------------------------------------------
-instruct addExactI_rReg(eAXRegI dst, rRegI src, eFlagsReg cr)
+instruct addExactI_eReg(eAXRegI dst, rRegI src, eFlagsReg cr)
%{
match(AddExactI dst src);
effect(DEF cr);
@@ -7531,7 +7536,7 @@
ins_pipe(ialu_reg_reg);
%}
-instruct addExactI_rReg_imm(eAXRegI dst, immI src, eFlagsReg cr)
+instruct addExactI_eReg_imm(eAXRegI dst, immI src, eFlagsReg cr)
%{
match(AddExactI dst src);
effect(DEF cr);
@@ -7543,6 +7548,20 @@
ins_pipe(ialu_reg_reg);
%}
+instruct addExactI_eReg_mem(eAXRegI dst, memory src, eFlagsReg cr)
+%{
+ match(AddExactI dst (LoadI src));
+ effect(DEF cr);
+
+ ins_cost(125);
+ format %{ "ADD $dst,$src\t# addExact int" %}
+ ins_encode %{
+ __ addl($dst$$Register, $src$$Address);
+ %}
+ ins_pipe( ialu_reg_mem );
+%}
+
+
// Integer Addition Instructions
instruct addI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{
match(Set dst (AddI dst src));
@@ -7851,6 +7870,44 @@
%}
//----------Subtraction Instructions-------------------------------------------
+
+instruct subExactI_eReg(eAXRegI dst, rRegI src, eFlagsReg cr)
+%{
+ match(SubExactI dst src);
+ effect(DEF cr);
+
+ format %{ "SUB $dst, $src\t# subExact int" %}
+ ins_encode %{
+ __ subl($dst$$Register, $src$$Register);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
+instruct subExactI_eReg_imm(eAXRegI dst, immI src, eFlagsReg cr)
+%{
+ match(SubExactI dst src);
+ effect(DEF cr);
+
+ format %{ "SUB $dst, $src\t# subExact int" %}
+ ins_encode %{
+ __ subl($dst$$Register, $src$$constant);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
+instruct subExactI_eReg_mem(eAXRegI dst, memory src, eFlagsReg cr)
+%{
+ match(SubExactI dst (LoadI src));
+ effect(DEF cr);
+
+ ins_cost(125);
+ format %{ "SUB $dst,$src\t# subExact int" %}
+ ins_encode %{
+ __ subl($dst$$Register, $src$$Address);
+ %}
+ ins_pipe( ialu_reg_mem );
+%}
+
// Integer Subtraction Instructions
instruct subI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{
match(Set dst (SubI dst src));
@@ -7919,6 +7976,16 @@
ins_pipe( ialu_reg );
%}
+instruct negExactI_eReg(eAXRegI dst, eFlagsReg cr) %{
+ match(NegExactI dst);
+ effect(DEF cr);
+
+ format %{ "NEG $dst\t# negExact int"%}
+ ins_encode %{
+ __ negl($dst$$Register);
+ %}
+ ins_pipe(ialu_reg);
+%}
//----------Multiplication/Division Instructions-------------------------------
// Integer Multiplication Instructions
@@ -8131,6 +8198,46 @@
ins_pipe( pipe_slow );
%}
+instruct mulExactI_eReg(eAXRegI dst, rRegI src, eFlagsReg cr)
+%{
+ match(MulExactI dst src);
+ effect(DEF cr);
+
+ ins_cost(300);
+ format %{ "IMUL $dst, $src\t# mulExact int" %}
+ ins_encode %{
+ __ imull($dst$$Register, $src$$Register);
+ %}
+ ins_pipe(ialu_reg_reg_alu0);
+%}
+
+instruct mulExactI_eReg_imm(eAXRegI dst, rRegI src, immI imm, eFlagsReg cr)
+%{
+ match(MulExactI src imm);
+ effect(DEF cr);
+
+ ins_cost(300);
+ format %{ "IMUL $dst, $src, $imm\t# mulExact int" %}
+ ins_encode %{
+ __ imull($dst$$Register, $src$$Register, $imm$$constant);
+ %}
+ ins_pipe(ialu_reg_reg_alu0);
+%}
+
+instruct mulExactI_eReg_mem(eAXRegI dst, memory src, eFlagsReg cr)
+%{
+ match(MulExactI dst (LoadI src));
+ effect(DEF cr);
+
+ ins_cost(350);
+ format %{ "IMUL $dst, $src\t# mulExact int" %}
+ ins_encode %{
+ __ imull($dst$$Register, $src$$Address);
+ %}
+ ins_pipe(ialu_reg_mem_alu0);
+%}
+
+
// Integer DIV with Register
instruct divI_eReg(eAXRegI rax, eDXRegI rdx, eCXRegI div, eFlagsReg cr) %{
match(Set rax (DivI rax div));
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad Wed Jul 05 19:19:29 2017 +0200
@@ -1653,6 +1653,10 @@
return INT_RAX_REG_mask();
}
+const RegMask Matcher::mathExactL_result_proj_mask() {
+ return LONG_RAX_REG_mask();
+}
+
const RegMask Matcher::mathExactI_flags_proj_mask() {
return INT_FLAGS_mask();
}
@@ -6962,6 +6966,58 @@
ins_pipe(ialu_reg_reg);
%}
+instruct addExactI_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr)
+%{
+ match(AddExactI dst (LoadI src));
+ effect(DEF cr);
+
+ ins_cost(125); // XXX
+ format %{ "addl $dst, $src\t# addExact int" %}
+ ins_encode %{
+ __ addl($dst$$Register, $src$$Address);
+ %}
+
+ ins_pipe(ialu_reg_mem);
+%}
+
+instruct addExactL_rReg(rax_RegL dst, rRegL src, rFlagsReg cr)
+%{
+ match(AddExactL dst src);
+ effect(DEF cr);
+
+ format %{ "addq $dst, $src\t# addExact long" %}
+ ins_encode %{
+ __ addq($dst$$Register, $src$$Register);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
+instruct addExactL_rReg_imm(rax_RegL dst, immL32 src, rFlagsReg cr)
+%{
+ match(AddExactL dst src);
+ effect(DEF cr);
+
+ format %{ "addq $dst, $src\t# addExact long" %}
+ ins_encode %{
+ __ addq($dst$$Register, $src$$constant);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
+instruct addExactL_rReg_mem(rax_RegL dst, memory src, rFlagsReg cr)
+%{
+ match(AddExactL dst (LoadL src));
+ effect(DEF cr);
+
+ ins_cost(125); // XXX
+ format %{ "addq $dst, $src\t# addExact long" %}
+ ins_encode %{
+ __ addq($dst$$Register, $src$$Address);
+ %}
+
+ ins_pipe(ialu_reg_mem);
+%}
+
instruct addI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
%{
match(Set dst (AddI dst src));
@@ -7574,6 +7630,80 @@
ins_pipe(ialu_mem_imm);
%}
+instruct subExactI_rReg(rax_RegI dst, rRegI src, rFlagsReg cr)
+%{
+ match(SubExactI dst src);
+ effect(DEF cr);
+
+ format %{ "subl $dst, $src\t# subExact int" %}
+ ins_encode %{
+ __ subl($dst$$Register, $src$$Register);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
+instruct subExactI_rReg_imm(rax_RegI dst, immI src, rFlagsReg cr)
+%{
+ match(SubExactI dst src);
+ effect(DEF cr);
+
+ format %{ "subl $dst, $src\t# subExact int" %}
+ ins_encode %{
+ __ subl($dst$$Register, $src$$constant);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
+instruct subExactI_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr)
+%{
+ match(SubExactI dst (LoadI src));
+ effect(DEF cr);
+
+ ins_cost(125);
+ format %{ "subl $dst, $src\t# subExact int" %}
+ ins_encode %{
+ __ subl($dst$$Register, $src$$Address);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
+instruct subExactL_rReg(rax_RegL dst, rRegL src, rFlagsReg cr)
+%{
+ match(SubExactL dst src);
+ effect(DEF cr);
+
+ format %{ "subq $dst, $src\t# subExact long" %}
+ ins_encode %{
+ __ subq($dst$$Register, $src$$Register);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
+instruct subExactL_rReg_imm(rax_RegL dst, immL32 src, rFlagsReg cr)
+%{
+ match(SubExactL dst (LoadL src));
+ effect(DEF cr);
+
+ format %{ "subq $dst, $src\t# subExact long" %}
+ ins_encode %{
+ __ subq($dst$$Register, $src$$constant);
+ %}
+ ins_pipe(ialu_reg_reg);
+%}
+
+instruct subExactL_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr)
+%{
+ match(SubExactI dst src);
+ effect(DEF cr);
+
+ ins_cost(125);
+ format %{ "subq $dst, $src\t# subExact long" %}
+ ins_encode %{
+ __ subq($dst$$Register, $src$$Address);
+ %}
+ ins_pipe(ialu_reg_mem);
+%}
+
instruct subL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
%{
match(Set dst (SubL dst src));
@@ -7690,6 +7820,30 @@
ins_pipe(ialu_reg);
%}
+instruct negExactI_rReg(rax_RegI dst, rFlagsReg cr)
+%{
+ match(NegExactI dst);
+ effect(KILL cr);
+
+ format %{ "negl $dst\t# negExact int" %}
+ ins_encode %{
+ __ negl($dst$$Register);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
+instruct negExactL_rReg(rax_RegL dst, rFlagsReg cr)
+%{
+ match(NegExactL dst);
+ effect(KILL cr);
+
+ format %{ "negq $dst\t# negExact long" %}
+ ins_encode %{
+ __ negq($dst$$Register);
+ %}
+ ins_pipe(ialu_reg);
+%}
+
//----------Multiplication/Division Instructions-------------------------------
// Integer Multiplication Instructions
@@ -7807,6 +7961,86 @@
ins_pipe(ialu_reg_reg_alu0);
%}
+
+instruct mulExactI_rReg(rax_RegI dst, rRegI src, rFlagsReg cr)
+%{
+ match(MulExactI dst src);
+ effect(DEF cr);
+
+ ins_cost(300);
+ format %{ "imull $dst, $src\t# mulExact int" %}
+ ins_encode %{
+ __ imull($dst$$Register, $src$$Register);
+ %}
+ ins_pipe(ialu_reg_reg_alu0);
+%}
+
+
+instruct mulExactI_rReg_imm(rax_RegI dst, rRegI src, immI imm, rFlagsReg cr)
+%{
+ match(MulExactI src imm);
+ effect(DEF cr);
+
+ ins_cost(300);
+ format %{ "imull $dst, $src, $imm\t# mulExact int" %}
+ ins_encode %{
+ __ imull($dst$$Register, $src$$Register, $imm$$constant);
+ %}
+ ins_pipe(ialu_reg_reg_alu0);
+%}
+
+instruct mulExactI_rReg_mem(rax_RegI dst, memory src, rFlagsReg cr)
+%{
+ match(MulExactI dst (LoadI src));
+ effect(DEF cr);
+
+ ins_cost(350);
+ format %{ "imull $dst, $src\t# mulExact int" %}
+ ins_encode %{
+ __ imull($dst$$Register, $src$$Address);
+ %}
+ ins_pipe(ialu_reg_mem_alu0);
+%}
+
+instruct mulExactL_rReg(rax_RegL dst, rRegL src, rFlagsReg cr)
+%{
+ match(MulExactL dst src);
+ effect(DEF cr);
+
+ ins_cost(300);
+ format %{ "imulq $dst, $src\t# mulExact long" %}
+ ins_encode %{
+ __ imulq($dst$$Register, $src$$Register);
+ %}
+ ins_pipe(ialu_reg_reg_alu0);
+%}
+
+instruct mulExactL_rReg_imm(rax_RegL dst, rRegL src, immL32 imm, rFlagsReg cr)
+%{
+ match(MulExactL src imm);
+ effect(DEF cr);
+
+ ins_cost(300);
+ format %{ "imulq $dst, $src, $imm\t# mulExact long" %}
+ ins_encode %{
+ __ imulq($dst$$Register, $src$$Register, $imm$$constant);
+ %}
+ ins_pipe(ialu_reg_reg_alu0);
+%}
+
+instruct mulExactL_rReg_mem(rax_RegL dst, memory src, rFlagsReg cr)
+%{
+ match(MulExactL dst (LoadL src));
+ effect(DEF cr);
+
+ ins_cost(350);
+ format %{ "imulq $dst, $src\t# mulExact long" %}
+ ins_encode %{
+ __ imulq($dst$$Register, $src$$Address);
+ %}
+ ins_pipe(ialu_reg_mem_alu0);
+%}
+
instruct divI_rReg(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div,
rFlagsReg cr)
%{
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -4746,6 +4746,10 @@
// as libawt.so, and renamed libawt_xawt.so
//
bool os::is_headless_jre() {
+#ifdef __APPLE__
+ // We no longer build headless-only on Mac OS X
+ return false;
+#else
struct stat statbuf;
char buf[MAXPATHLEN];
char libmawtpath[MAXPATHLEN];
@@ -4777,6 +4781,7 @@
if (::stat(libmawtpath, &statbuf) == 0) return false;
return true;
+#endif
}
// Get the default path to the core file
--- a/hotspot/src/share/vm/adlc/archDesc.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/adlc/archDesc.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -1193,6 +1193,13 @@
|| strcmp(idealName,"FastLock") == 0
|| strcmp(idealName,"FastUnlock") == 0
|| strcmp(idealName,"AddExactI") == 0
+ || strcmp(idealName,"AddExactL") == 0
+ || strcmp(idealName,"SubExactI") == 0
+ || strcmp(idealName,"SubExactL") == 0
+ || strcmp(idealName,"MulExactI") == 0
+ || strcmp(idealName,"MulExactL") == 0
+ || strcmp(idealName,"NegExactI") == 0
+ || strcmp(idealName,"NegExactL") == 0
|| strcmp(idealName,"FlagsProj") == 0
|| strcmp(idealName,"Bool") == 0
|| strcmp(idealName,"Binary") == 0 ) {
--- a/hotspot/src/share/vm/adlc/formssel.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/adlc/formssel.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -536,12 +536,6 @@
if( data_type != Form::none )
rematerialize = true;
- // Ugly: until a better fix is implemented, disable rematerialization for
- // negD nodes because they are proved to be problematic.
- if (is_ideal_negD()) {
- return false;
- }
-
// Constants
if( _components.count() == 1 && _components[0]->is(Component::USE_DEF) )
rematerialize = true;
--- a/hotspot/src/share/vm/c1/c1_Compilation.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compilation.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -238,7 +238,18 @@
return env()->comp_level() == CompLevel_full_profile &&
C1UpdateMethodData && C1ProfileCheckcasts;
}
-
+ bool profile_parameters() {
+ return env()->comp_level() == CompLevel_full_profile &&
+ C1UpdateMethodData && MethodData::profile_parameters();
+ }
+ bool profile_arguments() {
+ return env()->comp_level() == CompLevel_full_profile &&
+ C1UpdateMethodData && MethodData::profile_arguments();
+ }
+ bool profile_return() {
+ return env()->comp_level() == CompLevel_full_profile &&
+ C1UpdateMethodData && MethodData::profile_return();
+ }
// will compilation make optimistic assumptions that might lead to
// deoptimization and that the runtime will account for?
bool is_optimistic() const {
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -1470,7 +1470,7 @@
set_state(state()->caller_state()->copy_for_parsing());
if (x != NULL) {
state()->push(x->type(), x);
- if (profile_calls() && MethodData::profile_return() && x->type()->is_object_kind()) {
+ if (profile_return() && x->type()->is_object_kind()) {
ciMethod* caller = state()->scope()->method();
ciMethodData* md = caller->method_data_or_null();
ciProfileData* data = md->bci_to_data(invoke_bci);
@@ -1672,15 +1672,23 @@
}
// How many arguments do we want to profile?
-Values* GraphBuilder::args_list_for_profiling(int& start, bool may_have_receiver) {
+Values* GraphBuilder::args_list_for_profiling(ciMethod* target, int& start, bool may_have_receiver) {
int n = 0;
- assert(start == 0, "should be initialized");
- if (MethodData::profile_arguments()) {
+ bool has_receiver = may_have_receiver && Bytecodes::has_receiver(method()->java_code_at_bci(bci()));
+ start = has_receiver ? 1 : 0;
+ if (profile_arguments()) {
ciProfileData* data = method()->method_data()->bci_to_data(bci());
if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) {
n = data->is_CallTypeData() ? data->as_CallTypeData()->number_of_arguments() : data->as_VirtualCallTypeData()->number_of_arguments();
- bool has_receiver = may_have_receiver && Bytecodes::has_receiver(method()->java_code_at_bci(bci()));
- start = has_receiver ? 1 : 0;
+ }
+ }
+ // If we are inlining then we need to collect arguments to profile parameters for the target
+ if (profile_parameters() && target != NULL) {
+ if (target->method_data() != NULL && target->method_data()->parameters_type_data() != NULL) {
+ // The receiver is profiled on method entry so it's included in
+ // the number of parameters but here we're only interested in
+ // actual arguments.
+ n = MAX2(n, target->method_data()->parameters_type_data()->number_of_parameters() - start);
}
}
if (n > 0) {
@@ -1690,9 +1698,9 @@
}
// Collect arguments that we want to profile in a list
-Values* GraphBuilder::collect_args_for_profiling(Values* args, bool may_have_receiver) {
+Values* GraphBuilder::collect_args_for_profiling(Values* args, ciMethod* target, bool may_have_receiver) {
int start = 0;
- Values* obj_args = args_list_for_profiling(start, may_have_receiver);
+ Values* obj_args = args_list_for_profiling(target, start, may_have_receiver);
if (obj_args == NULL) {
return NULL;
}
@@ -2006,7 +2014,7 @@
} else if (exact_target != NULL) {
target_klass = exact_target->holder();
}
- profile_call(target, recv, target_klass, collect_args_for_profiling(args, false), false);
+ profile_call(target, recv, target_klass, collect_args_for_profiling(args, NULL, false), false);
}
}
@@ -2021,7 +2029,7 @@
push(result_type, result);
}
}
- if (profile_calls() && MethodData::profile_return() && result_type->is_object_kind()) {
+ if (profile_return() && result_type->is_object_kind()) {
profile_return_type(result, target);
}
}
@@ -3561,7 +3569,7 @@
recv = args->at(0);
null_check(recv);
}
- profile_call(callee, recv, NULL, collect_args_for_profiling(args, true), true);
+ profile_call(callee, recv, NULL, collect_args_for_profiling(args, callee, true), true);
}
}
}
@@ -3572,7 +3580,7 @@
Value value = append_split(result);
if (result_type != voidType) push(result_type, value);
- if (callee != method() && profile_calls() && MethodData::profile_return() && result_type->is_object_kind()) {
+ if (callee != method() && profile_return() && result_type->is_object_kind()) {
profile_return_type(result, callee);
}
@@ -3760,6 +3768,7 @@
// now perform tests that are based on flag settings
if (callee->force_inline()) {
+ if (inline_level() > MaxForceInlineLevel) INLINE_BAILOUT("MaxForceInlineLevel");
print_inlining(callee, "force inline by annotation");
} else if (callee->should_inline()) {
print_inlining(callee, "force inline by CompileOracle");
@@ -3820,7 +3829,7 @@
if (profile_calls()) {
int start = 0;
- Values* obj_args = args_list_for_profiling(start, has_receiver);
+ Values* obj_args = args_list_for_profiling(callee, start, has_receiver);
if (obj_args != NULL) {
int s = obj_args->size();
// if called through method handle invoke, some arguments may have been popped
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -386,9 +386,12 @@
bool profile_calls() { return _compilation->profile_calls(); }
bool profile_inlined_calls() { return _compilation->profile_inlined_calls(); }
bool profile_checkcasts() { return _compilation->profile_checkcasts(); }
+ bool profile_parameters() { return _compilation->profile_parameters(); }
+ bool profile_arguments() { return _compilation->profile_arguments(); }
+ bool profile_return() { return _compilation->profile_return(); }
- Values* args_list_for_profiling(int& start, bool may_have_receiver);
- Values* collect_args_for_profiling(Values* args, bool may_have_receiver);
+ Values* args_list_for_profiling(ciMethod* target, int& start, bool may_have_receiver);
+ Values* collect_args_for_profiling(Values* args, ciMethod* target, bool may_have_receiver);
public:
NOT_PRODUCT(void print_stats();)
--- a/hotspot/src/share/vm/c1/c1_LIR.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIR.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -183,10 +183,10 @@
case T_LONG:
case T_OBJECT:
case T_ADDRESS:
- case T_METADATA:
case T_VOID:
return ::type2char(t);
-
+ case T_METADATA:
+ return 'M';
case T_ILLEGAL:
return '?';
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -1175,7 +1175,7 @@
if (compilation()->env()->dtrace_method_probes()) {
BasicTypeList signature;
signature.append(LP64_ONLY(T_LONG) NOT_LP64(T_INT)); // thread
- signature.append(T_OBJECT); // Method*
+ signature.append(T_METADATA); // Method*
LIR_OprList* args = new LIR_OprList();
args->append(getThreadPointer());
LIR_Opr meth = new_register(T_METADATA);
@@ -1265,6 +1265,7 @@
LIRItem rcvr(x->argument_at(0), this);
rcvr.load_item();
+ LIR_Opr temp = new_register(T_METADATA);
LIR_Opr result = rlock_result(x);
// need to perform the null check on the rcvr
@@ -1272,8 +1273,11 @@
if (x->needs_null_check()) {
info = state_for(x);
}
- __ move(new LIR_Address(rcvr.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), result, info);
- __ move_wide(new LIR_Address(result, in_bytes(Klass::java_mirror_offset()), T_OBJECT), result);
+
+ // FIXME T_ADDRESS should actually be T_METADATA but it can't because the
+ // meaning of these two is mixed up (see JDK-8026837).
+ __ move(new LIR_Address(rcvr.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), temp, info);
+ __ move_wide(new LIR_Address(temp, in_bytes(Klass::java_mirror_offset()), T_OBJECT), result);
}
@@ -2643,6 +2647,39 @@
return result;
}
+// profile parameters on entry to the root of the compilation
+void LIRGenerator::profile_parameters(Base* x) {
+ if (compilation()->profile_parameters()) {
+ CallingConvention* args = compilation()->frame_map()->incoming_arguments();
+ ciMethodData* md = scope()->method()->method_data_or_null();
+ assert(md != NULL, "Sanity");
+
+ if (md->parameters_type_data() != NULL) {
+ ciParametersTypeData* parameters_type_data = md->parameters_type_data();
+ ciTypeStackSlotEntries* parameters = parameters_type_data->parameters();
+ LIR_Opr mdp = LIR_OprFact::illegalOpr;
+ for (int java_index = 0, i = 0, j = 0; j < parameters_type_data->number_of_parameters(); i++) {
+ LIR_Opr src = args->at(i);
+ assert(!src->is_illegal(), "check");
+ BasicType t = src->type();
+ if (t == T_OBJECT || t == T_ARRAY) {
+ intptr_t profiled_k = parameters->type(j);
+ Local* local = x->state()->local_at(java_index)->as_Local();
+ ciKlass* exact = profile_arg_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)),
+ in_bytes(ParametersTypeData::type_offset(j)) - in_bytes(ParametersTypeData::type_offset(0)),
+ profiled_k, local, mdp, false, local->declared_type()->as_klass());
+ // If the profile is known statically set it once for all and do not emit any code
+ if (exact != NULL) {
+ md->set_parameter_type(j, exact);
+ }
+ j++;
+ }
+ java_index += type2size[t];
+ }
+ }
+ }
+}
+
void LIRGenerator::do_Base(Base* x) {
__ std_entry(LIR_OprFact::illegalOpr);
// Emit moves from physical registers / stack slots to virtual registers
@@ -2683,7 +2720,7 @@
if (compilation()->env()->dtrace_method_probes()) {
BasicTypeList signature;
signature.append(LP64_ONLY(T_LONG) NOT_LP64(T_INT)); // thread
- signature.append(T_OBJECT); // Method*
+ signature.append(T_METADATA); // Method*
LIR_OprList* args = new LIR_OprList();
args->append(getThreadPointer());
LIR_Opr meth = new_register(T_METADATA);
@@ -2718,6 +2755,7 @@
// increment invocation counters if needed
if (!method()->is_accessor()) { // Accessors do not have MDOs, so no counting.
+ profile_parameters(x);
CodeEmitInfo* info = new CodeEmitInfo(scope()->start()->state()->copy(ValueStack::StateBefore, SynchronizationEntryBCI), NULL, false);
increment_invocation_counter(info);
}
@@ -3077,11 +3115,12 @@
}
void LIRGenerator::profile_arguments(ProfileCall* x) {
- if (MethodData::profile_arguments()) {
+ if (compilation()->profile_arguments()) {
int bci = x->bci_of_invoke();
ciMethodData* md = x->method()->method_data_or_null();
ciProfileData* data = md->bci_to_data(bci);
- if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) {
+ if ((data->is_CallTypeData() && data->as_CallTypeData()->has_arguments()) ||
+ (data->is_VirtualCallTypeData() && data->as_VirtualCallTypeData()->has_arguments())) {
ByteSize extra = data->is_CallTypeData() ? CallTypeData::args_data_offset() : VirtualCallTypeData::args_data_offset();
int base_offset = md->byte_offset_of_slot(data, extra);
LIR_Opr mdp = LIR_OprFact::illegalOpr;
@@ -3107,6 +3146,71 @@
md->set_argument_type(bci, i, exact);
}
}
+ } else {
+#ifdef ASSERT
+ Bytecodes::Code code = x->method()->raw_code_at_bci(x->bci_of_invoke());
+ int n = x->nb_profiled_args();
+ assert(MethodData::profile_parameters() && x->inlined() &&
+ ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)),
+ "only at JSR292 bytecodes");
+#endif
+ }
+ }
+}
+
+// profile parameters on entry to an inlined method
+void LIRGenerator::profile_parameters_at_call(ProfileCall* x) {
+ if (compilation()->profile_parameters() && x->inlined()) {
+ ciMethodData* md = x->callee()->method_data_or_null();
+ if (md != NULL) {
+ ciParametersTypeData* parameters_type_data = md->parameters_type_data();
+ if (parameters_type_data != NULL) {
+ ciTypeStackSlotEntries* parameters = parameters_type_data->parameters();
+ LIR_Opr mdp = LIR_OprFact::illegalOpr;
+ bool has_receiver = !x->callee()->is_static();
+ ciSignature* sig = x->callee()->signature();
+ ciSignatureStream sig_stream(sig, has_receiver ? x->callee()->holder() : NULL);
+ int i = 0; // to iterate on the Instructions
+ Value arg = x->recv();
+ bool not_null = false;
+ int bci = x->bci_of_invoke();
+ Bytecodes::Code bc = x->method()->java_code_at_bci(bci);
+ // The first parameter is the receiver so that's what we start
+ // with if it exists. On exception if method handle call to
+ // virtual method has receiver in the args list
+ if (arg == NULL || !Bytecodes::has_receiver(bc)) {
+ i = 1;
+ arg = x->profiled_arg_at(0);
+ not_null = !x->arg_needs_null_check(0);
+ }
+ int k = 0; // to iterate on the profile data
+ for (;;) {
+ intptr_t profiled_k = parameters->type(k);
+ ciKlass* exact = profile_arg_type(md, md->byte_offset_of_slot(parameters_type_data, ParametersTypeData::type_offset(0)),
+ in_bytes(ParametersTypeData::type_offset(k)) - in_bytes(ParametersTypeData::type_offset(0)),
+ profiled_k, arg, mdp, not_null, sig_stream.next_klass());
+ // If the profile is known statically set it once for all and do not emit any code
+ if (exact != NULL) {
+ md->set_parameter_type(k, exact);
+ }
+ k++;
+ if (k >= parameters_type_data->number_of_parameters()) {
+#ifdef ASSERT
+ int extra = 0;
+ if (MethodData::profile_arguments() && TypeProfileParmsLimit != -1 &&
+ x->nb_profiled_args() >= TypeProfileParmsLimit &&
+ x->recv() != NULL && Bytecodes::has_receiver(bc)) {
+ extra += 1;
+ }
+ assert(i == x->nb_profiled_args() - extra || (TypeProfileParmsLimit != -1 && TypeProfileArgsLimit > TypeProfileParmsLimit), "unused parameters?");
+#endif
+ break;
+ }
+ arg = x->profiled_arg_at(i);
+ not_null = !x->arg_needs_null_check(i);
+ i++;
+ }
+ }
}
}
}
@@ -3122,6 +3226,11 @@
profile_arguments(x);
}
+ // profile parameters on inlined method entry including receiver
+ if (x->recv() != NULL || x->nb_profiled_args() > 0) {
+ profile_parameters_at_call(x);
+ }
+
if (x->recv() != NULL) {
LIRItem value(x->recv(), this);
value.load_item();
@@ -3222,7 +3331,7 @@
BasicTypeList* signature = new BasicTypeList(x->number_of_arguments());
if (x->pass_thread()) {
- signature->append(T_ADDRESS);
+ signature->append(LP64_ONLY(T_LONG) NOT_LP64(T_INT)); // thread
args->append(getThreadPointer());
}
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -436,6 +436,8 @@
#endif
ciKlass* profile_arg_type(ciMethodData* md, int md_first_offset, int md_offset, intptr_t profiled_k, Value arg, LIR_Opr& mdp, bool not_null, ciKlass* signature_k);
void profile_arguments(ProfileCall* x);
+ void profile_parameters(Base* x);
+ void profile_parameters_at_call(ProfileCall* x);
public:
Compilation* compilation() const { return _compilation; }
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -75,9 +75,9 @@
// Map BasicType to spill size in 32-bit words, matching VMReg's notion of words
#ifdef _LP64
-static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 0, 1, -1};
+static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 0, 2, 1, 2, 1, -1};
#else
-static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, -1};
+static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, -1, 1, 1, -1};
#endif
--- a/hotspot/src/share/vm/c1/c1_globals.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/c1/c1_globals.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -341,6 +341,8 @@
diagnostic(bool, C1PatchInvokeDynamic, true, \
"Patch invokedynamic appendix not known at compile time") \
\
+ develop(intx, MaxForceInlineLevel, 100, \
+ "maximum number of nested @ForceInline calls that are inlined") \
\
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -483,8 +483,7 @@
{
// We have to lock the cpool to keep the oop from being resolved
// while we are accessing it.
- oop cplock = cpool->lock();
- ObjectLocker ol(cplock, THREAD, cplock != NULL);
+ MonitorLockerEx ml(cpool->lock());
constantTag tag = cpool->tag_at(index);
if (tag.is_klass()) {
// The klass has been inserted into the constant pool
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -565,6 +565,116 @@
if (_limit < MorphismLimit) _limit++;
}
+
+void ciMethod::assert_virtual_call_type_ok(int bci) {
+ assert(java_code_at_bci(bci) == Bytecodes::_invokevirtual ||
+ java_code_at_bci(bci) == Bytecodes::_invokeinterface, err_msg("unexpected bytecode %s", Bytecodes::name(java_code_at_bci(bci))));
+}
+
+void ciMethod::assert_call_type_ok(int bci) {
+ assert(java_code_at_bci(bci) == Bytecodes::_invokestatic ||
+ java_code_at_bci(bci) == Bytecodes::_invokespecial ||
+ java_code_at_bci(bci) == Bytecodes::_invokedynamic, err_msg("unexpected bytecode %s", Bytecodes::name(java_code_at_bci(bci))));
+}
+
+/**
+ * Check whether profiling provides a type for the argument i to the
+ * call at bci bci
+ *
+ * @param bci bci of the call
+ * @param i argument number
+ * @return profiled type
+ *
+ * If the profile reports that the argument may be null, return false
+ * at least for now.
+ */
+ciKlass* ciMethod::argument_profiled_type(int bci, int i) {
+ if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) {
+ ciProfileData* data = method_data()->bci_to_data(bci);
+ if (data != NULL) {
+ if (data->is_VirtualCallTypeData()) {
+ assert_virtual_call_type_ok(bci);
+ ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData();
+ if (i >= call->number_of_arguments()) {
+ return NULL;
+ }
+ ciKlass* type = call->valid_argument_type(i);
+ if (type != NULL && !call->argument_maybe_null(i)) {
+ return type;
+ }
+ } else if (data->is_CallTypeData()) {
+ assert_call_type_ok(bci);
+ ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData();
+ if (i >= call->number_of_arguments()) {
+ return NULL;
+ }
+ ciKlass* type = call->valid_argument_type(i);
+ if (type != NULL && !call->argument_maybe_null(i)) {
+ return type;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Check whether profiling provides a type for the return value from
+ * the call at bci bci
+ *
+ * @param bci bci of the call
+ * @return profiled type
+ *
+ * If the profile reports that the argument may be null, return false
+ * at least for now.
+ */
+ciKlass* ciMethod::return_profiled_type(int bci) {
+ if (MethodData::profile_return() && method_data() != NULL && method_data()->is_mature()) {
+ ciProfileData* data = method_data()->bci_to_data(bci);
+ if (data != NULL) {
+ if (data->is_VirtualCallTypeData()) {
+ assert_virtual_call_type_ok(bci);
+ ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData();
+ ciKlass* type = call->valid_return_type();
+ if (type != NULL && !call->return_maybe_null()) {
+ return type;
+ }
+ } else if (data->is_CallTypeData()) {
+ assert_call_type_ok(bci);
+ ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData();
+ ciKlass* type = call->valid_return_type();
+ if (type != NULL && !call->return_maybe_null()) {
+ return type;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Check whether profiling provides a type for the parameter i
+ *
+ * @param i parameter number
+ * @return profiled type
+ *
+ * If the profile reports that the argument may be null, return false
+ * at least for now.
+ */
+ciKlass* ciMethod::parameter_profiled_type(int i) {
+ if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) {
+ ciParametersTypeData* parameters = method_data()->parameters_type_data();
+ if (parameters != NULL && i < parameters->number_of_parameters()) {
+ ciKlass* type = parameters->valid_parameter_type(i);
+ if (type != NULL && !parameters->parameter_maybe_null(i)) {
+ return type;
+ }
+ }
+ }
+ return NULL;
+}
+
+
// ------------------------------------------------------------------
// ciMethod::find_monomorphic_target
//
--- a/hotspot/src/share/vm/ci/ciMethod.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -117,6 +117,10 @@
*bcp = code;
}
+ // Check bytecode and profile data collected are compatible
+ void assert_virtual_call_type_ok(int bci);
+ void assert_call_type_ok(int bci);
+
public:
// Basic method information.
ciFlags flags() const { check_is_loaded(); return _flags; }
@@ -230,6 +234,11 @@
ciCallProfile call_profile_at_bci(int bci);
int interpreter_call_site_count(int bci);
+ // Does type profiling provide a useful type at this point?
+ ciKlass* argument_profiled_type(int bci, int i);
+ ciKlass* parameter_profiled_type(int i);
+ ciKlass* return_profiled_type(int bci);
+
ciField* get_field_at_bci( int bci, bool &will_link);
ciMethod* get_method_at_bci(int bci, bool &will_link, ciSignature* *declared_signature);
--- a/hotspot/src/share/vm/ci/ciMethodData.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/ci/ciMethodData.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -53,6 +53,7 @@
_hint_di = first_di();
// Initialize the escape information (to "don't know.");
_eflags = _arg_local = _arg_stack = _arg_returned = 0;
+ _parameters = NULL;
}
// ------------------------------------------------------------------
@@ -74,6 +75,7 @@
_hint_di = first_di();
// Initialize the escape information (to "don't know.");
_eflags = _arg_local = _arg_stack = _arg_returned = 0;
+ _parameters = NULL;
}
void ciMethodData::load_data() {
@@ -108,6 +110,12 @@
ci_data = next_data(ci_data);
data = mdo->next_data(data);
}
+ if (mdo->parameters_type_data() != NULL) {
+ _parameters = data_layout_at(mdo->parameters_type_data_di());
+ ciParametersTypeData* parameters = new ciParametersTypeData(_parameters);
+ parameters->translate_from(mdo->parameters_type_data());
+ }
+
// Note: Extra data are all BitData, and do not need translation.
_current_mileage = MethodData::mileage_of(mdo->method());
_invocation_counter = mdo->invocation_count();
@@ -182,6 +190,8 @@
return new ciCallTypeData(data_layout);
case DataLayout::virtual_call_type_data_tag:
return new ciVirtualCallTypeData(data_layout);
+ case DataLayout::parameters_type_data_tag:
+ return new ciParametersTypeData(data_layout);
};
}
@@ -318,6 +328,14 @@
}
}
+void ciMethodData::set_parameter_type(int i, ciKlass* k) {
+ VM_ENTRY_MARK;
+ MethodData* mdo = get_MethodData();
+ if (mdo != NULL) {
+ mdo->parameters_type_data()->set_type(i, k->get_Klass());
+ }
+}
+
void ciMethodData::set_return_type(int bci, ciKlass* k) {
VM_ENTRY_MARK;
MethodData* mdo = get_MethodData();
@@ -605,4 +623,9 @@
ret()->print_data_on(st);
}
}
+
+void ciParametersTypeData::print_data_on(outputStream* st) const {
+ st->print_cr("Parametertypes");
+ parameters()->print_data_on(st);
+}
#endif
--- a/hotspot/src/share/vm/ci/ciMethodData.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/ci/ciMethodData.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -43,6 +43,7 @@
class ciArgInfoData;
class ciCallTypeData;
class ciVirtualCallTypeData;
+class ciParametersTypeData;
typedef ProfileData ciProfileData;
@@ -99,6 +100,10 @@
return valid_ciklass(type(i));
}
+ bool maybe_null(int i) const {
+ return was_null_seen(type(i));
+ }
+
#ifndef PRODUCT
void print_data_on(outputStream* st) const;
#endif
@@ -112,6 +117,10 @@
return valid_ciklass(type());
}
+ bool maybe_null() const {
+ return was_null_seen(type());
+ }
+
#ifndef PRODUCT
void print_data_on(outputStream* st) const;
#endif
@@ -124,7 +133,7 @@
ciTypeStackSlotEntries* args() const { return (ciTypeStackSlotEntries*)CallTypeData::args(); }
ciReturnTypeEntry* ret() const { return (ciReturnTypeEntry*)CallTypeData::ret(); }
- void translate_type_data_from(const ProfileData* data) {
+ void translate_from(const ProfileData* data) {
if (has_arguments()) {
args()->translate_type_data_from(data->as_CallTypeData()->args());
}
@@ -153,6 +162,14 @@
return ret()->valid_type();
}
+ bool argument_maybe_null(int i) const {
+ return args()->maybe_null(i);
+ }
+
+ bool return_maybe_null() const {
+ return ret()->maybe_null();
+ }
+
#ifndef PRODUCT
void print_data_on(outputStream* st) const;
#endif
@@ -259,6 +276,14 @@
return ret()->valid_type();
}
+ bool argument_maybe_null(int i) const {
+ return args()->maybe_null(i);
+ }
+
+ bool return_maybe_null() const {
+ return ret()->maybe_null();
+ }
+
#ifndef PRODUCT
void print_data_on(outputStream* st) const;
#endif
@@ -290,6 +315,29 @@
ciArgInfoData(DataLayout* layout) : ArgInfoData(layout) {};
};
+class ciParametersTypeData : public ParametersTypeData {
+public:
+ ciParametersTypeData(DataLayout* layout) : ParametersTypeData(layout) {}
+
+ virtual void translate_from(const ProfileData* data) {
+ parameters()->translate_type_data_from(data->as_ParametersTypeData()->parameters());
+ }
+
+ ciTypeStackSlotEntries* parameters() const { return (ciTypeStackSlotEntries*)ParametersTypeData::parameters(); }
+
+ ciKlass* valid_parameter_type(int i) const {
+ return parameters()->valid_type(i);
+ }
+
+ bool parameter_maybe_null(int i) const {
+ return parameters()->maybe_null(i);
+ }
+
+#ifndef PRODUCT
+ void print_data_on(outputStream* st) const;
+#endif
+};
+
// ciMethodData
//
// This class represents a MethodData* in the HotSpot virtual
@@ -335,6 +383,10 @@
// Coherent snapshot of original header.
MethodData _orig;
+ // Dedicated area dedicated to parameters. Null if no parameter
+ // profiling for this method.
+ DataLayout* _parameters;
+
ciMethodData(MethodData* md);
ciMethodData();
@@ -403,6 +455,7 @@
// If the compiler finds a profiled type that is known statically
// for sure, set it in the MethodData
void set_argument_type(int bci, int i, ciKlass* k);
+ void set_parameter_type(int i, ciKlass* k);
void set_return_type(int bci, ciKlass* k);
void load_data();
@@ -467,6 +520,10 @@
bool is_arg_returned(int i) const;
uint arg_modified(int arg) const;
+ ciParametersTypeData* parameters_type_data() const {
+ return _parameters != NULL ? new ciParametersTypeData(_parameters) : NULL;
+ }
+
// Code generation helper
ByteSize offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data);
int byte_offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data) { return in_bytes(offset_of_slot(data, slot_offset_in_data)); }
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -2360,6 +2360,11 @@
objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty));
assert(appendix_box->obj_at(0) == NULL, "");
+ // This should not happen. JDK code should take care of that.
+ if (accessing_klass.is_null() || method_type.is_null()) {
+ THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad invokehandle", empty);
+ }
+
// call java.lang.invoke.MethodHandleNatives::linkMethod(... String, MethodType) -> MemberName
JavaCallArguments args;
args.push_oop(accessing_klass()->java_mirror());
@@ -2485,6 +2490,9 @@
Handle type;
if (signature->utf8_length() > 0 && signature->byte_at(0) == '(') {
type = find_method_handle_type(signature, caller, CHECK_(empty));
+ } else if (caller.is_null()) {
+ // This should not happen. JDK code should take care of that.
+ THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad MH constant", empty);
} else {
ResourceMark rm(THREAD);
SignatureStream ss(signature, false);
@@ -2548,6 +2556,11 @@
Handle method_name = java_lang_String::create_from_symbol(name, CHECK_(empty));
Handle method_type = find_method_handle_type(type, caller, CHECK_(empty));
+ // This should not happen. JDK code should take care of that.
+ if (caller.is_null() || method_type.is_null()) {
+ THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad invokedynamic", empty);
+ }
+
objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty));
assert(appendix_box->obj_at(0) == NULL, "");
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -624,6 +624,7 @@
do_class(java_lang_StrictMath, "java/lang/StrictMath") \
do_signature(double2_double_signature, "(DD)D") \
do_signature(int2_int_signature, "(II)I") \
+ do_signature(long2_long_signature, "(JJ)J") \
\
/* here are the math names, all together: */ \
do_name(abs_name,"abs") do_name(sin_name,"sin") do_name(cos_name,"cos") \
@@ -632,8 +633,11 @@
do_name(exp_name,"exp") do_name(min_name,"min") do_name(max_name,"max") \
\
do_name(addExact_name,"addExact") \
+ do_name(decrementExact_name,"decrementExact") \
+ do_name(incrementExact_name,"incrementExact") \
+ do_name(multiplyExact_name,"multiplyExact") \
+ do_name(negateExact_name,"negateExact") \
do_name(subtractExact_name,"subtractExact") \
- do_name(multiplyExact_name,"multiplyExact") \
\
do_intrinsic(_dabs, java_lang_Math, abs_name, double_double_signature, F_S) \
do_intrinsic(_dsin, java_lang_Math, sin_name, double_double_signature, F_S) \
@@ -647,7 +651,18 @@
do_intrinsic(_dexp, java_lang_Math, exp_name, double_double_signature, F_S) \
do_intrinsic(_min, java_lang_Math, min_name, int2_int_signature, F_S) \
do_intrinsic(_max, java_lang_Math, max_name, int2_int_signature, F_S) \
- do_intrinsic(_addExact, java_lang_Math, addExact_name, int2_int_signature, F_S) \
+ do_intrinsic(_addExactI, java_lang_Math, addExact_name, int2_int_signature, F_S) \
+ do_intrinsic(_addExactL, java_lang_Math, addExact_name, long2_long_signature, F_S) \
+ do_intrinsic(_decrementExactI, java_lang_Math, decrementExact_name, int_int_signature, F_S) \
+ do_intrinsic(_decrementExactL, java_lang_Math, decrementExact_name, long2_long_signature, F_S) \
+ do_intrinsic(_incrementExactI, java_lang_Math, incrementExact_name, int_int_signature, F_S) \
+ do_intrinsic(_incrementExactL, java_lang_Math, incrementExact_name, long2_long_signature, F_S) \
+ do_intrinsic(_multiplyExactI, java_lang_Math, multiplyExact_name, int2_int_signature, F_S) \
+ do_intrinsic(_multiplyExactL, java_lang_Math, multiplyExact_name, long2_long_signature, F_S) \
+ do_intrinsic(_negateExactI, java_lang_Math, negateExact_name, int_int_signature, F_S) \
+ do_intrinsic(_negateExactL, java_lang_Math, negateExact_name, long_long_signature, F_S) \
+ do_intrinsic(_subtractExactI, java_lang_Math, subtractExact_name, int2_int_signature, F_S) \
+ do_intrinsic(_subtractExactL, java_lang_Math, subtractExact_name, long2_long_signature, F_S) \
\
do_intrinsic(_floatToRawIntBits, java_lang_Float, floatToRawIntBits_name, float_int_signature, F_S) \
do_name( floatToRawIntBits_name, "floatToRawIntBits") \
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -1297,13 +1297,6 @@
method->jmethod_id();
}
- // If the compiler is shut off due to code cache getting full
- // fail out now so blocking compiles dont hang the java thread
- if (!should_compile_new_jobs()) {
- CompilationPolicy::policy()->delay_compilation(method());
- return NULL;
- }
-
// do the compilation
if (method->is_native()) {
if (!PreferInterpreterNativeStubs || method->is_method_handle_intrinsic()) {
@@ -1313,11 +1306,22 @@
MutexLocker locker(MethodCompileQueue_lock, THREAD);
compile_id = assign_compile_id(method, standard_entry_bci);
}
+ // To properly handle the appendix argument for out-of-line calls we are using a small trampoline that
+ // pops off the appendix argument and jumps to the target (see gen_special_dispatch in SharedRuntime).
+ //
+ // Since normal compiled-to-compiled calls are not able to handle such a thing we MUST generate an adapter
+ // in this case. If we can't generate one and use it we can not execute the out-of-line method handle calls.
(void) AdapterHandlerLibrary::create_native_wrapper(method, compile_id);
} else {
return NULL;
}
} else {
+ // If the compiler is shut off due to code cache getting full
+ // fail out now so blocking compiles dont hang the java thread
+ if (!should_compile_new_jobs()) {
+ CompilationPolicy::policy()->delay_compilation(method());
+ return NULL;
+ }
compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, THREAD);
}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -55,7 +55,7 @@
// then _alloc_region is NULL and this object should not be used to
// satisfy allocation requests (it was done this way to force the
// correct use of init() and release()).
- HeapRegion* _alloc_region;
+ HeapRegion* volatile _alloc_region;
// It keeps track of the distinct number of regions that are used
// for allocation in the active interval of this object, i.e.,
@@ -132,8 +132,9 @@
static void setup(G1CollectedHeap* g1h, HeapRegion* dummy_region);
HeapRegion* get() const {
+ HeapRegion * hr = _alloc_region;
// Make sure that the dummy region does not escape this class.
- return (_alloc_region == _dummy_region) ? NULL : _alloc_region;
+ return (hr == _dummy_region) ? NULL : hr;
}
uint count() { return _count; }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -187,19 +187,23 @@
size_t code_root_elems() const { return _code_root_elems; }
void print_rs_mem_info_on(outputStream * out, size_t total) {
- out->print_cr(" %8dK (%5.1f%%) by %zd %s regions", round_to_K(rs_mem_size()), rs_mem_size_percent_of(total), amount(), _name);
+ out->print_cr(" "SIZE_FORMAT_W(8)"K (%5.1f%%) by "SIZE_FORMAT" %s regions",
+ round_to_K(rs_mem_size()), rs_mem_size_percent_of(total), amount(), _name);
}
void print_cards_occupied_info_on(outputStream * out, size_t total) {
- out->print_cr(" %8d (%5.1f%%) entries by %zd %s regions", cards_occupied(), cards_occupied_percent_of(total), amount(), _name);
+ out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) entries by "SIZE_FORMAT" %s regions",
+ cards_occupied(), cards_occupied_percent_of(total), amount(), _name);
}
void print_code_root_mem_info_on(outputStream * out, size_t total) {
- out->print_cr(" %8dK (%5.1f%%) by %zd %s regions", round_to_K(code_root_mem_size()), code_root_mem_size_percent_of(total), amount(), _name);
+ out->print_cr(" "SIZE_FORMAT_W(8)"K (%5.1f%%) by "SIZE_FORMAT" %s regions",
+ round_to_K(code_root_mem_size()), code_root_mem_size_percent_of(total), amount(), _name);
}
void print_code_root_elems_info_on(outputStream * out, size_t total) {
- out->print_cr(" %8d (%5.1f%%) elements by %zd %s regions", code_root_elems(), code_root_elems_percent_of(total), amount(), _name);
+ out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) elements by "SIZE_FORMAT" %s regions",
+ code_root_elems(), code_root_elems_percent_of(total), amount(), _name);
}
};
@@ -327,14 +331,14 @@
out->print_cr("\n Recent concurrent refinement statistics");
out->print_cr(" Processed "SIZE_FORMAT" cards",
num_concurrent_refined_cards());
- out->print_cr(" Of %d completed buffers:", num_processed_buf_total());
- out->print_cr(" %8d (%5.1f%%) by concurrent RS threads.",
+ out->print_cr(" Of "SIZE_FORMAT" completed buffers:", num_processed_buf_total());
+ out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) by concurrent RS threads.",
num_processed_buf_total(),
percent_of(num_processed_buf_rs_threads(), num_processed_buf_total()));
- out->print_cr(" %8d (%5.1f%%) by mutator threads.",
+ out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) by mutator threads.",
num_processed_buf_mutator(),
percent_of(num_processed_buf_mutator(), num_processed_buf_total()));
- out->print_cr(" Did %d coarsenings.", num_coarsenings());
+ out->print_cr(" Did "SIZE_FORMAT" coarsenings.", num_coarsenings());
out->print_cr(" Concurrent RS threads times (s)");
out->print(" ");
for (uint i = 0; i < _num_vtimes; i++) {
--- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -30,11 +30,8 @@
#include "runtime/thread.inline.hpp"
#include "runtime/vmThread.hpp"
#include "utilities/top.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
-# include "interp_masm_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
-# include "interp_masm_x86_64.hpp"
+#ifdef TARGET_ARCH_x86
+# include "interp_masm_x86.hpp"
#endif
#ifdef TARGET_ARCH_MODEL_sparc
# include "interp_masm_sparc.hpp"
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -1,6 +1,5 @@
/*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -265,7 +264,7 @@
void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
Method* result_oop = klass->uncached_lookup_method(name, signature);
result = methodHandle(THREAD, result_oop);
- while (!result.is_null() && result->is_static()) {
+ while (!result.is_null() && result->is_static() && result->method_holder()->super() != NULL) {
klass = KlassHandle(THREAD, result->method_holder()->super());
result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature));
}
@@ -419,18 +418,28 @@
AccessFlags flags = sel_method->access_flags();
- // Special case: arrays always override "clone". JVMS 2.15.
+ // Special case #1: arrays always override "clone". JVMS 2.15.
// If the resolved klass is an array class, and the declaring class
// is java.lang.Object and the method is "clone", set the flags
// to public.
+ // Special case #2: If the resolved klass is an interface, and
+ // the declaring class is java.lang.Object, and the method is
+ // "clone" or "finalize", set the flags to public. If the
+ // resolved interface does not contain "clone" or "finalize"
+ // methods, the method/interface method resolution looks to
+ // the interface's super class, java.lang.Object. With JDK 8
+ // interface accessability check requirement, special casing
+ // this scenario is necessary to avoid an IAE.
//
- // We'll check for the method name first, as that's most likely
- // to be false (so we'll short-circuit out of these tests).
- if (sel_method->name() == vmSymbols::clone_name() &&
- sel_klass() == SystemDictionary::Object_klass() &&
- resolved_klass->oop_is_array()) {
+ // We'll check for each method name first and then java.lang.Object
+ // to best short-circuit out of these tests.
+ if (((sel_method->name() == vmSymbols::clone_name() &&
+ (resolved_klass->oop_is_array() || resolved_klass->is_interface())) ||
+ (sel_method->name() == vmSymbols::finalize_method_name() &&
+ resolved_klass->is_interface())) &&
+ sel_klass() == SystemDictionary::Object_klass()) {
// We need to change "protected" to "public".
- assert(flags.is_protected(), "clone not protected?");
+ assert(flags.is_protected(), "clone or finalize not protected?");
jint new_flags = flags.as_int();
new_flags = new_flags & (~JVM_ACC_PROTECTED);
new_flags = new_flags | JVM_ACC_PUBLIC;
--- a/hotspot/src/share/vm/interpreter/templateTable.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/interpreter/templateTable.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -28,11 +28,8 @@
#include "interpreter/bytecodes.hpp"
#include "memory/allocation.hpp"
#include "runtime/frame.hpp"
-#ifdef TARGET_ARCH_MODEL_x86_32
-# include "interp_masm_x86_32.hpp"
-#endif
-#ifdef TARGET_ARCH_MODEL_x86_64
-# include "interp_masm_x86_64.hpp"
+#ifdef TARGET_ARCH_x86
+# include "interp_masm_x86.hpp"
#endif
#ifdef TARGET_ARCH_MODEL_sparc
# include "interp_masm_sparc.hpp"
--- a/hotspot/src/share/vm/memory/metaspace.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/memory/metaspace.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -75,8 +75,7 @@
ClassSmallChunk = 256,
SmallChunk = 512,
ClassMediumChunk = 4 * K,
- MediumChunk = 8 * K,
- HumongousChunkGranularity = 8
+ MediumChunk = 8 * K
};
static ChunkIndex next_chunk_index(ChunkIndex i) {
@@ -92,6 +91,7 @@
// Manages the global free lists of chunks.
class ChunkManager : public CHeapObj<mtInternal> {
+ friend class TestVirtualSpaceNodeTest;
// Free list of chunks of different sizes.
// SpecializedChunk
@@ -257,6 +257,8 @@
// VirtualSpace
Metachunk* first_chunk() { return (Metachunk*) bottom(); }
+ // Committed but unused space in the virtual space
+ size_t free_words_in_vs() const;
public:
VirtualSpaceNode(size_t byte_size);
@@ -301,7 +303,6 @@
// used and capacity in this single entry in the list
size_t used_words_in_vs() const;
size_t capacity_words_in_vs() const;
- size_t free_words_in_vs() const;
bool initialize();
@@ -319,6 +320,13 @@
// in the node from any freelist.
void purge(ChunkManager* chunk_manager);
+ // If an allocation doesn't fit in the current node a new node is created.
+ // Allocate chunks out of the remaining committed space in this node
+ // to avoid wasting that memory.
+ // This always adds up because all the chunk sizes are multiples of
+ // the smallest chunk size.
+ void retire(ChunkManager* chunk_manager);
+
#ifdef ASSERT
// Debug support
void mangle();
@@ -461,6 +469,10 @@
// and is typically followed by the allocation of a chunk.
bool create_new_virtual_space(size_t vs_word_size);
+ // Chunk up the unused committed space in the current
+ // virtual space and add the chunks to the free list.
+ void retire_current_virtual_space();
+
public:
VirtualSpaceList(size_t word_size);
VirtualSpaceList(ReservedSpace rs);
@@ -624,10 +636,12 @@
bool is_class() { return _mdtype == Metaspace::ClassType; }
// Accessors
- size_t specialized_chunk_size() { return SpecializedChunk; }
- size_t small_chunk_size() { return (size_t) is_class() ? ClassSmallChunk : SmallChunk; }
- size_t medium_chunk_size() { return (size_t) is_class() ? ClassMediumChunk : MediumChunk; }
- size_t medium_chunk_bunch() { return medium_chunk_size() * MediumChunkMultiple; }
+ size_t specialized_chunk_size() { return (size_t) is_class() ? ClassSpecializedChunk : SpecializedChunk; }
+ size_t small_chunk_size() { return (size_t) is_class() ? ClassSmallChunk : SmallChunk; }
+ size_t medium_chunk_size() { return (size_t) is_class() ? ClassMediumChunk : MediumChunk; }
+ size_t medium_chunk_bunch() { return medium_chunk_size() * MediumChunkMultiple; }
+
+ size_t smallest_chunk_size() { return specialized_chunk_size(); }
size_t allocated_blocks_words() const { return _allocated_blocks_words; }
size_t allocated_blocks_bytes() const { return _allocated_blocks_words * BytesPerWord; }
@@ -1056,6 +1070,35 @@
#endif
}
+void VirtualSpaceList::retire_current_virtual_space() {
+ assert_lock_strong(SpaceManager::expand_lock());
+
+ VirtualSpaceNode* vsn = current_virtual_space();
+
+ ChunkManager* cm = is_class() ? Metaspace::chunk_manager_class() :
+ Metaspace::chunk_manager_metadata();
+
+ vsn->retire(cm);
+}
+
+void VirtualSpaceNode::retire(ChunkManager* chunk_manager) {
+ for (int i = (int)MediumIndex; i >= (int)ZeroIndex; --i) {
+ ChunkIndex index = (ChunkIndex)i;
+ size_t chunk_size = chunk_manager->free_chunks(index)->size();
+
+ while (free_words_in_vs() >= chunk_size) {
+ DEBUG_ONLY(verify_container_count();)
+ Metachunk* chunk = get_chunk_vs(chunk_size);
+ assert(chunk != NULL, "allocation should have been successful");
+
+ chunk_manager->return_chunks(index, chunk);
+ chunk_manager->inc_free_chunks_total(chunk_size);
+ DEBUG_ONLY(verify_container_count();)
+ }
+ }
+ assert(free_words_in_vs() == 0, "should be empty now");
+}
+
VirtualSpaceList::VirtualSpaceList(size_t word_size) :
_is_class(false),
_virtual_space_list(NULL),
@@ -1181,6 +1224,7 @@
if (vs_expanded) {
return true;
}
+ retire_current_virtual_space();
// Get another virtual space.
size_t grow_vs_words = MAX2((size_t)VirtualSpaceSize, preferred_words);
@@ -1902,12 +1946,12 @@
chunk_word_size = medium_chunk_size();
}
- // Might still need a humongous chunk. Enforce an
- // eight word granularity to facilitate reuse (some
- // wastage but better chance of reuse).
+ // Might still need a humongous chunk. Enforce
+ // humongous allocations sizes to be aligned up to
+ // the smallest chunk size.
size_t if_humongous_sized_chunk =
align_size_up(word_size + Metachunk::overhead(),
- HumongousChunkGranularity);
+ smallest_chunk_size());
chunk_word_size =
MAX2((size_t) chunk_word_size, if_humongous_sized_chunk);
@@ -2151,10 +2195,10 @@
}
assert(humongous_chunks->word_size() == (size_t)
align_size_up(humongous_chunks->word_size(),
- HumongousChunkGranularity),
+ smallest_chunk_size()),
err_msg("Humongous chunk size is wrong: word size " SIZE_FORMAT
" granularity %d",
- humongous_chunks->word_size(), HumongousChunkGranularity));
+ humongous_chunks->word_size(), smallest_chunk_size()));
Metachunk* next_humongous_chunks = humongous_chunks->next();
humongous_chunks->container()->dec_container_count();
chunk_manager()->humongous_dictionary()->return_chunk(humongous_chunks);
@@ -3301,9 +3345,7 @@
}
if (result == NULL) {
- report_metadata_oome(loader_data, word_size, mdtype, THREAD);
- // Will not reach here.
- return NULL;
+ report_metadata_oome(loader_data, word_size, mdtype, CHECK_NULL);
}
// Zero initialize.
@@ -3494,4 +3536,94 @@
TestMetaspaceAuxTest::test();
}
+class TestVirtualSpaceNodeTest {
+ static void chunk_up(size_t words_left, size_t& num_medium_chunks,
+ size_t& num_small_chunks,
+ size_t& num_specialized_chunks) {
+ num_medium_chunks = words_left / MediumChunk;
+ words_left = words_left % MediumChunk;
+
+ num_small_chunks = words_left / SmallChunk;
+ words_left = words_left % SmallChunk;
+ // how many specialized chunks can we get?
+ num_specialized_chunks = words_left / SpecializedChunk;
+ assert(words_left % SpecializedChunk == 0, "should be nothing left");
+ }
+
+ public:
+ static void test() {
+ MutexLockerEx ml(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag);
+ const size_t vsn_test_size_words = MediumChunk * 4;
+ const size_t vsn_test_size_bytes = vsn_test_size_words * BytesPerWord;
+
+ // The chunk sizes must be multiples of eachother, or this will fail
+ STATIC_ASSERT(MediumChunk % SmallChunk == 0);
+ STATIC_ASSERT(SmallChunk % SpecializedChunk == 0);
+
+ { // No committed memory in VSN
+ ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk);
+ VirtualSpaceNode vsn(vsn_test_size_bytes);
+ vsn.initialize();
+ vsn.retire(&cm);
+ assert(cm.sum_free_chunks_count() == 0, "did not commit any memory in the VSN");
+ }
+
+ { // All of VSN is committed, half is used by chunks
+ ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk);
+ VirtualSpaceNode vsn(vsn_test_size_bytes);
+ vsn.initialize();
+ vsn.expand_by(vsn_test_size_words, vsn_test_size_words);
+ vsn.get_chunk_vs(MediumChunk);
+ vsn.get_chunk_vs(MediumChunk);
+ vsn.retire(&cm);
+ assert(cm.sum_free_chunks_count() == 2, "should have been memory left for 2 medium chunks");
+ assert(cm.sum_free_chunks() == 2*MediumChunk, "sizes should add up");
+ }
+
+ { // 4 pages of VSN is committed, some is used by chunks
+ ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk);
+ VirtualSpaceNode vsn(vsn_test_size_bytes);
+ const size_t page_chunks = 4 * (size_t)os::vm_page_size() / BytesPerWord;
+ assert(page_chunks < MediumChunk, "Test expects medium chunks to be at least 4*page_size");
+ vsn.initialize();
+ vsn.expand_by(page_chunks, page_chunks);
+ vsn.get_chunk_vs(SmallChunk);
+ vsn.get_chunk_vs(SpecializedChunk);
+ vsn.retire(&cm);
+
+ // committed - used = words left to retire
+ const size_t words_left = page_chunks - SmallChunk - SpecializedChunk;
+
+ size_t num_medium_chunks, num_small_chunks, num_spec_chunks;
+ chunk_up(words_left, num_medium_chunks, num_small_chunks, num_spec_chunks);
+
+ assert(num_medium_chunks == 0, "should not get any medium chunks");
+ assert(cm.sum_free_chunks_count() == (num_small_chunks + num_spec_chunks), "should be space for 3 chunks");
+ assert(cm.sum_free_chunks() == words_left, "sizes should add up");
+ }
+
+ { // Half of VSN is committed, a humongous chunk is used
+ ChunkManager cm(SpecializedChunk, SmallChunk, MediumChunk);
+ VirtualSpaceNode vsn(vsn_test_size_bytes);
+ vsn.initialize();
+ vsn.expand_by(MediumChunk * 2, MediumChunk * 2);
+ vsn.get_chunk_vs(MediumChunk + SpecializedChunk); // Humongous chunks will be aligned up to MediumChunk + SpecializedChunk
+ vsn.retire(&cm);
+
+ const size_t words_left = MediumChunk * 2 - (MediumChunk + SpecializedChunk);
+ size_t num_medium_chunks, num_small_chunks, num_spec_chunks;
+ chunk_up(words_left, num_medium_chunks, num_small_chunks, num_spec_chunks);
+
+ assert(num_medium_chunks == 0, "should not get any medium chunks");
+ assert(cm.sum_free_chunks_count() == (num_small_chunks + num_spec_chunks), "should be space for 3 chunks");
+ assert(cm.sum_free_chunks() == words_left, "sizes should add up");
+ }
+
+ }
+};
+
+void TestVirtualSpaceNode_test() {
+ TestVirtualSpaceNodeTest::test();
+}
+
#endif
--- a/hotspot/src/share/vm/oops/constantPool.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/oops/constantPool.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -40,7 +40,6 @@
#include "runtime/init.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/signature.hpp"
-#include "runtime/synchronizer.hpp"
#include "runtime/vframe.hpp"
ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, TRAPS) {
@@ -70,6 +69,7 @@
// only set to non-zero if constant pool is merged by RedefineClasses
set_version(0);
+ set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock"));
// initialize tag array
int length = tags->length();
@@ -95,6 +95,9 @@
void ConstantPool::release_C_heap_structures() {
// walk constant pool and decrement symbol reference counts
unreference_symbols();
+
+ delete _lock;
+ set_lock(NULL);
}
objArrayOop ConstantPool::resolved_references() const {
@@ -151,6 +154,9 @@
ClassLoaderData* loader_data = pool_holder()->class_loader_data();
set_resolved_references(loader_data->add_handle(refs_handle));
}
+
+ // Also need to recreate the mutex. Make sure this matches the constructor
+ set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock"));
}
}
@@ -161,23 +167,7 @@
set_resolved_reference_length(
resolved_references() != NULL ? resolved_references()->length() : 0);
set_resolved_references(NULL);
-}
-
-oop ConstantPool::lock() {
- if (_pool_holder) {
- // We re-use the _pool_holder's init_lock to reduce footprint.
- // Notes on deadlocks:
- // [1] This lock is a Java oop, so it can be recursively locked by
- // the same thread without self-deadlocks.
- // [2] Deadlock will happen if there is circular dependency between
- // the <clinit> of two Java classes. However, in this case,
- // the deadlock would have happened long before we reach
- // ConstantPool::lock(), so reusing init_lock does not
- // increase the possibility of deadlock.
- return _pool_holder->init_lock();
- } else {
- return NULL;
- }
+ set_lock(NULL);
}
int ConstantPool::cp_to_object_index(int cp_index) {
@@ -211,9 +201,7 @@
Symbol* name = NULL;
Handle loader;
- {
- oop cplock = this_oop->lock();
- ObjectLocker ol(cplock , THREAD, cplock != NULL);
+ { MonitorLockerEx ml(this_oop->lock());
if (this_oop->tag_at(which).is_unresolved_klass()) {
if (this_oop->tag_at(which).is_unresolved_klass_in_error()) {
@@ -260,8 +248,7 @@
bool throw_orig_error = false;
{
- oop cplock = this_oop->lock();
- ObjectLocker ol(cplock, THREAD, cplock != NULL);
+ MonitorLockerEx ml(this_oop->lock());
// some other thread has beaten us and has resolved the class.
if (this_oop->tag_at(which).is_klass()) {
@@ -329,8 +316,7 @@
}
return k();
} else {
- oop cplock = this_oop->lock();
- ObjectLocker ol(cplock, THREAD, cplock != NULL);
+ MonitorLockerEx ml(this_oop->lock());
// Only updated constant pool - if it is resolved.
do_resolve = this_oop->tag_at(which).is_unresolved_klass();
if (do_resolve) {
@@ -600,8 +586,7 @@
int tag, TRAPS) {
ResourceMark rm;
Symbol* error = PENDING_EXCEPTION->klass()->name();
- oop cplock = this_oop->lock();
- ObjectLocker ol(cplock, THREAD, cplock != NULL); // lock cpool to change tag.
+ MonitorLockerEx ml(this_oop->lock()); // lock cpool to change tag.
int error_tag = (tag == JVM_CONSTANT_MethodHandle) ?
JVM_CONSTANT_MethodHandleInError : JVM_CONSTANT_MethodTypeInError;
@@ -762,8 +747,7 @@
if (cache_index >= 0) {
// Cache the oop here also.
Handle result_handle(THREAD, result_oop);
- oop cplock = this_oop->lock();
- ObjectLocker ol(cplock, THREAD, cplock != NULL); // don't know if we really need this
+ MonitorLockerEx ml(this_oop->lock()); // don't know if we really need this
oop result = this_oop->resolved_references()->obj_at(cache_index);
// Benign race condition: resolved_references may already be filled in while we were trying to lock.
// The important thing here is that all threads pick up the same result.
--- a/hotspot/src/share/vm/oops/constantPool.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/oops/constantPool.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -111,6 +111,7 @@
int _version;
} _saved;
+ Monitor* _lock;
void set_tags(Array<u1>* tags) { _tags = tags; }
void tag_at_put(int which, jbyte t) { tags()->at_put(which, t); }
@@ -843,17 +844,8 @@
void set_resolved_reference_length(int length) { _saved._resolved_reference_length = length; }
int resolved_reference_length() const { return _saved._resolved_reference_length; }
-
- // lock() may return null -- constant pool updates may happen before this lock is
- // initialized, because the _pool_holder has not been fully initialized and
- // has not been registered into the system dictionary. In this case, no other
- // thread can be modifying this constantpool, so no synchronization is
- // necessary.
- //
- // Use cplock() like this:
- // oop cplock = cp->lock();
- // ObjectLocker ol(cplock , THREAD, cplock != NULL);
- oop lock();
+ void set_lock(Monitor* lock) { _lock = lock; }
+ Monitor* lock() { return _lock; }
// Decrease ref counts of symbols that are in the constant pool
// when the holder class is unloaded
--- a/hotspot/src/share/vm/oops/cpCache.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/oops/cpCache.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -284,8 +284,7 @@
// the lock, so that when the losing writer returns, he can use the linked
// cache entry.
- oop cplock = cpool->lock();
- ObjectLocker ol(cplock, Thread::current(), cplock != NULL);
+ MonitorLockerEx ml(cpool->lock());
if (!is_f1_null()) {
return;
}
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -498,13 +498,27 @@
oop InstanceKlass::init_lock() const {
// return the init lock from the mirror
- return java_lang_Class::init_lock(java_mirror());
+ oop lock = java_lang_Class::init_lock(java_mirror());
+ assert((oop)lock != NULL || !is_not_initialized(), // initialized or in_error state
+ "only fully initialized state can have a null lock");
+ return lock;
+}
+
+// Set the initialization lock to null so the object can be GC'ed. Any racing
+// threads to get this lock will see a null lock and will not lock.
+// That's okay because they all check for initialized state after getting
+// the lock and return.
+void InstanceKlass::fence_and_clear_init_lock() {
+ // make sure previous stores are all done, notably the init_state.
+ OrderAccess::storestore();
+ java_lang_Class::set_init_lock(java_mirror(), NULL);
+ assert(!is_not_initialized(), "class must be initialized now");
}
void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_oop) {
EXCEPTION_MARK;
oop init_lock = this_oop->init_lock();
- ObjectLocker ol(init_lock, THREAD);
+ ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
// abort if someone beat us to the initialization
if (!this_oop->is_not_initialized()) return; // note: not equivalent to is_initialized()
@@ -523,6 +537,7 @@
} else {
// linking successfull, mark class as initialized
this_oop->set_init_state (fully_initialized);
+ this_oop->fence_and_clear_init_lock();
// trace
if (TraceClassInitialization) {
ResourceMark rm(THREAD);
@@ -649,7 +664,7 @@
// verification & rewriting
{
oop init_lock = this_oop->init_lock();
- ObjectLocker ol(init_lock, THREAD);
+ ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
// rewritten will have been set if loader constraint error found
// on an earlier link attempt
// don't verify or rewrite if already rewritten
@@ -772,7 +787,7 @@
// Step 1
{
oop init_lock = this_oop->init_lock();
- ObjectLocker ol(init_lock, THREAD);
+ ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
Thread *self = THREAD; // it's passed the current thread
@@ -920,8 +935,9 @@
void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_oop, ClassState state, TRAPS) {
oop init_lock = this_oop->init_lock();
- ObjectLocker ol(init_lock, THREAD);
+ ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
this_oop->set_init_state(state);
+ this_oop->fence_and_clear_init_lock();
ol.notify_all(CHECK);
}
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -1023,6 +1023,7 @@
// It has to be an object not a Mutex because it's held through java calls.
oop init_lock() const;
private:
+ void fence_and_clear_init_lock();
// Static methods that are used to implement member methods where an exposed this pointer
// is needed due to possible GCs
--- a/hotspot/src/share/vm/oops/methodData.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/oops/methodData.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -41,7 +41,7 @@
// Some types of data layouts need a length field.
bool DataLayout::needs_array_len(u1 tag) {
- return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag);
+ return (tag == multi_branch_data_tag) || (tag == arg_info_data_tag) || (tag == parameters_type_data_tag);
}
// Perform generic initialization of the data. More specific
@@ -156,10 +156,13 @@
}
#endif // !PRODUCT
-int TypeStackSlotEntries::compute_cell_count(Symbol* signature, int max) {
+int TypeStackSlotEntries::compute_cell_count(Symbol* signature, bool include_receiver, int max) {
+ // Parameter profiling include the receiver
+ int args_count = include_receiver ? 1 : 0;
ResourceMark rm;
SignatureStream ss(signature);
- int args_count = MIN2(ss.reference_parameter_count(), max);
+ args_count += ss.reference_parameter_count();
+ args_count = MIN2(args_count, max);
return args_count * per_arg_cell_count;
}
@@ -169,7 +172,7 @@
Bytecode_invoke inv(stream->method(), stream->bci());
int args_cell = 0;
if (arguments_profiling_enabled()) {
- args_cell = TypeStackSlotEntries::compute_cell_count(inv.signature(), TypeProfileArgsLimit);
+ args_cell = TypeStackSlotEntries::compute_cell_count(inv.signature(), false, TypeProfileArgsLimit);
}
int ret_cell = 0;
if (return_profiling_enabled() && (inv.result_type() == T_OBJECT || inv.result_type() == T_ARRAY)) {
@@ -212,12 +215,19 @@
int off_at(int i) const { return _offsets.at(i); }
};
-void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver) {
+void TypeStackSlotEntries::post_initialize(Symbol* signature, bool has_receiver, bool include_receiver) {
ResourceMark rm;
- ArgumentOffsetComputer aos(signature, _number_of_entries);
+ int start = 0;
+ // Parameter profiling include the receiver
+ if (include_receiver && has_receiver) {
+ set_stack_slot(0, 0);
+ set_type(0, type_none());
+ start += 1;
+ }
+ ArgumentOffsetComputer aos(signature, _number_of_entries-start);
aos.total();
- for (int i = 0; i < _number_of_entries; i++) {
- set_stack_slot(i, aos.off_at(i) + (has_receiver ? 1 : 0));
+ for (int i = start; i < _number_of_entries; i++) {
+ set_stack_slot(i, aos.off_at(i-start) + (has_receiver ? 1 : 0));
set_type(i, type_none());
}
}
@@ -234,7 +244,7 @@
assert(count > 0, "room for args type but none found?");
check_number_of_arguments(count);
#endif
- _args.post_initialize(inv.signature(), inv.has_receiver());
+ _args.post_initialize(inv.signature(), inv.has_receiver(), false);
}
if (has_return()) {
@@ -255,7 +265,7 @@
assert(count > 0, "room for args type but none found?");
check_number_of_arguments(count);
#endif
- _args.post_initialize(inv.signature(), inv.has_receiver());
+ _args.post_initialize(inv.signature(), inv.has_receiver(), false);
}
if (has_return()) {
@@ -579,6 +589,34 @@
}
#endif
+
+int ParametersTypeData::compute_cell_count(Method* m) {
+ if (!MethodData::profile_parameters_for_method(m)) {
+ return 0;
+ }
+ int max = TypeProfileParmsLimit == -1 ? INT_MAX : TypeProfileParmsLimit;
+ int obj_args = TypeStackSlotEntries::compute_cell_count(m->signature(), !m->is_static(), max);
+ if (obj_args > 0) {
+ return obj_args + 1; // 1 cell for array len
+ }
+ return 0;
+}
+
+void ParametersTypeData::post_initialize(BytecodeStream* stream, MethodData* mdo) {
+ _parameters.post_initialize(mdo->method()->signature(), !mdo->method()->is_static(), true);
+}
+
+bool ParametersTypeData::profiling_enabled() {
+ return MethodData::profile_parameters();
+}
+
+#ifndef PRODUCT
+void ParametersTypeData::print_data_on(outputStream* st) const {
+ st->print("parameter types");
+ _parameters.print_data_on(st);
+}
+#endif
+
// ==================================================================
// MethodData*
//
@@ -741,6 +779,12 @@
int arg_size = method->size_of_parameters();
object_size += DataLayout::compute_size_in_bytes(arg_size+1);
+ // Reserve room for an area of the MDO dedicated to profiling of
+ // parameters
+ int args_cell = ParametersTypeData::compute_cell_count(method());
+ if (args_cell > 0) {
+ object_size += DataLayout::compute_size_in_bytes(args_cell);
+ }
return object_size;
}
@@ -915,6 +959,8 @@
return new CallTypeData(this);
case DataLayout::virtual_call_type_data_tag:
return new VirtualCallTypeData(this);
+ case DataLayout::parameters_type_data_tag:
+ return new ParametersTypeData(this);
};
}
@@ -936,6 +982,9 @@
stream->next();
data->post_initialize(stream, this);
}
+ if (_parameters_type_data_di != -1) {
+ parameters_type_data()->post_initialize(NULL, this);
+ }
}
// Initialize the MethodData* corresponding to a given method.
@@ -975,7 +1024,23 @@
int arg_size = method->size_of_parameters();
dp->initialize(DataLayout::arg_info_data_tag, 0, arg_size+1);
- object_size += extra_size + DataLayout::compute_size_in_bytes(arg_size+1);
+ int arg_data_size = DataLayout::compute_size_in_bytes(arg_size+1);
+ object_size += extra_size + arg_data_size;
+
+ int args_cell = ParametersTypeData::compute_cell_count(method());
+ // If we are profiling parameters, we reserver an area near the end
+ // of the MDO after the slots for bytecodes (because there's no bci
+ // for method entry so they don't fit with the framework for the
+ // profiling of bytecodes). We store the offset within the MDO of
+ // this area (or -1 if no parameter is profiled)
+ if (args_cell > 0) {
+ object_size += DataLayout::compute_size_in_bytes(args_cell);
+ _parameters_type_data_di = data_size + extra_size + arg_data_size;
+ DataLayout *dp = data_layout_at(data_size + extra_size + arg_data_size);
+ dp->initialize(DataLayout::parameters_type_data_tag, 0, args_cell);
+ } else {
+ _parameters_type_data_di = -1;
+ }
// Set an initial hint. Don't use set_hint_di() because
// first_di() may be out of bounds if data_size is 0.
@@ -1134,6 +1199,9 @@
void MethodData::print_data_on(outputStream* st) const {
ResourceMark rm;
ProfileData* data = first_data();
+ if (_parameters_type_data_di != -1) {
+ parameters_type_data()->print_data_on(st);
+ }
for ( ; is_valid(data); data = next_data(data)) {
st->print("%d", dp_to_di(data->dp()));
st->fill_to(6);
@@ -1222,7 +1290,7 @@
}
int MethodData::profile_return_flag() {
- return TypeProfileLevel / 10;
+ return (TypeProfileLevel % 100) / 10;
}
bool MethodData::profile_return() {
@@ -1249,3 +1317,32 @@
assert(profile_return_jsr292_only(), "inconsistent");
return profile_jsr292(m, bci);
}
+
+int MethodData::profile_parameters_flag() {
+ return TypeProfileLevel / 100;
+}
+
+bool MethodData::profile_parameters() {
+ return profile_parameters_flag() > no_type_profile && profile_parameters_flag() <= type_profile_all;
+}
+
+bool MethodData::profile_parameters_jsr292_only() {
+ return profile_parameters_flag() == type_profile_jsr292;
+}
+
+bool MethodData::profile_all_parameters() {
+ return profile_parameters_flag() == type_profile_all;
+}
+
+bool MethodData::profile_parameters_for_method(methodHandle m) {
+ if (!profile_parameters()) {
+ return false;
+ }
+
+ if (profile_all_parameters()) {
+ return true;
+ }
+
+ assert(profile_parameters_jsr292_only(), "inconsistent");
+ return m->is_compiled_lambda_form();
+}
--- a/hotspot/src/share/vm/oops/methodData.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/oops/methodData.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -119,7 +119,8 @@
multi_branch_data_tag,
arg_info_data_tag,
call_type_data_tag,
- virtual_call_type_data_tag
+ virtual_call_type_data_tag,
+ parameters_type_data_tag
};
enum {
@@ -264,6 +265,7 @@
class ArrayData;
class MultiBranchData;
class ArgInfoData;
+class ParametersTypeData;
// ProfileData
//
@@ -397,6 +399,7 @@
virtual bool is_ArgInfoData() const { return false; }
virtual bool is_CallTypeData() const { return false; }
virtual bool is_VirtualCallTypeData()const { return false; }
+ virtual bool is_ParametersTypeData() const { return false; }
BitData* as_BitData() const {
@@ -447,6 +450,10 @@
assert(is_VirtualCallTypeData(), "wrong type");
return is_VirtualCallTypeData() ? (VirtualCallTypeData*)this : NULL;
}
+ ParametersTypeData* as_ParametersTypeData() const {
+ assert(is_ParametersTypeData(), "wrong type");
+ return is_ParametersTypeData() ? (ParametersTypeData*)this : NULL;
+ }
// Subclass specific initialization
@@ -767,9 +774,9 @@
TypeStackSlotEntries(int base_off, int nb_entries)
: TypeEntries(base_off), _number_of_entries(nb_entries) {}
- static int compute_cell_count(Symbol* signature, int max);
+ static int compute_cell_count(Symbol* signature, bool include_receiver, int max);
- void post_initialize(Symbol* signature, bool has_receiver);
+ void post_initialize(Symbol* signature, bool has_receiver, bool include_receiver);
// offset of cell for stack slot for entry i within this block of cells for a TypeStackSlotEntries
static int stack_slot_local_offset(int i) {
@@ -946,17 +953,6 @@
assert(number_of_arguments() == total, "should be set in DataLayout::initialize");
}
-protected:
- // An entry for a return value takes less space than an entry for an
- // argument so if the number of cells exceeds the number of cells
- // needed for an argument, this object contains type information for
- // at least one argument.
- bool has_arguments() const {
- bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count();
- assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments");
- return res;
- }
-
public:
CallTypeData(DataLayout* layout) :
CounterData(layout),
@@ -1018,6 +1014,16 @@
}
// An entry for a return value takes less space than an entry for an
+ // argument so if the number of cells exceeds the number of cells
+ // needed for an argument, this object contains type information for
+ // at least one argument.
+ bool has_arguments() const {
+ bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count();
+ assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments");
+ return res;
+ }
+
+ // An entry for a return value takes less space than an entry for an
// argument, so if the remainder of the number of cells divided by
// the number of cells for an argument is not null, a return value
// is profiled in this object.
@@ -1213,17 +1219,6 @@
assert(number_of_arguments() == total, "should be set in DataLayout::initialize");
}
-protected:
- // An entry for a return value takes less space than an entry for an
- // argument so if the number of cells exceeds the number of cells
- // needed for an argument, this object contains type information for
- // at least one argument.
- bool has_arguments() const {
- bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count();
- assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments");
- return res;
- }
-
public:
VirtualCallTypeData(DataLayout* layout) :
VirtualCallData(layout),
@@ -1294,6 +1289,16 @@
return res;
}
+ // An entry for a return value takes less space than an entry for an
+ // argument so if the number of cells exceeds the number of cells
+ // needed for an argument, this object contains type information for
+ // at least one argument.
+ bool has_arguments() const {
+ bool res = cell_count_no_header() >= TypeStackSlotEntries::per_arg_count();
+ assert (!res || TypeEntriesAtCall::arguments_profiling_enabled(), "no profiling of arguments");
+ return res;
+ }
+
// Code generation support
static ByteSize args_data_offset() {
return cell_offset(VirtualCallData::static_cell_count()) + TypeEntriesAtCall::args_data_offset();
@@ -1662,6 +1667,75 @@
#endif
};
+// ParametersTypeData
+//
+// A ParametersTypeData is used to access profiling information about
+// types of parameters to a method
+class ParametersTypeData : public ArrayData {
+
+private:
+ TypeStackSlotEntries _parameters;
+
+ static int stack_slot_local_offset(int i) {
+ assert_profiling_enabled();
+ return array_start_off_set + TypeStackSlotEntries::stack_slot_local_offset(i);
+ }
+
+ static int type_local_offset(int i) {
+ assert_profiling_enabled();
+ return array_start_off_set + TypeStackSlotEntries::type_local_offset(i);
+ }
+
+ static bool profiling_enabled();
+ static void assert_profiling_enabled() {
+ assert(profiling_enabled(), "method parameters profiling should be on");
+ }
+
+public:
+ ParametersTypeData(DataLayout* layout) : ArrayData(layout), _parameters(1, number_of_parameters()) {
+ assert(layout->tag() == DataLayout::parameters_type_data_tag, "wrong type");
+ // Some compilers (VC++) don't want this passed in member initialization list
+ _parameters.set_profile_data(this);
+ }
+
+ static int compute_cell_count(Method* m);
+
+ virtual bool is_ParametersTypeData() const { return true; }
+
+ virtual void post_initialize(BytecodeStream* stream, MethodData* mdo);
+
+ int number_of_parameters() const {
+ return array_len() / TypeStackSlotEntries::per_arg_count();
+ }
+
+ const TypeStackSlotEntries* parameters() const { return &_parameters; }
+
+ uint stack_slot(int i) const {
+ return _parameters.stack_slot(i);
+ }
+
+ void set_type(int i, Klass* k) {
+ intptr_t current = _parameters.type(i);
+ _parameters.set_type(i, TypeEntries::with_status((intptr_t)k, current));
+ }
+
+ virtual void clean_weak_klass_links(BoolObjectClosure* is_alive_closure) {
+ _parameters.clean_weak_klass_links(is_alive_closure);
+ }
+
+#ifndef PRODUCT
+ virtual void print_data_on(outputStream* st) const;
+#endif
+
+ static ByteSize stack_slot_offset(int i) {
+ return cell_offset(stack_slot_local_offset(i));
+ }
+
+ static ByteSize type_offset(int i) {
+ return cell_offset(type_local_offset(i));
+ }
+};
+
// MethodData*
//
// A MethodData* holds information which has been collected about
@@ -1773,6 +1847,10 @@
// Size of _data array in bytes. (Excludes header and extra_data fields.)
int _data_size;
+ // data index for the area dedicated to parameters. -1 if no
+ // parameter profiling.
+ int _parameters_type_data_di;
+
// Beginning of the data entries
intptr_t _data[1];
@@ -1842,6 +1920,9 @@
static int profile_return_flag();
static bool profile_all_return();
static bool profile_return_for_invoke(methodHandle m, int bci);
+ static int profile_parameters_flag();
+ static bool profile_parameters_jsr292_only();
+ static bool profile_all_parameters();
public:
static int header_size() {
@@ -2048,6 +2129,16 @@
}
}
+ // Return pointer to area dedicated to parameters in MDO
+ ParametersTypeData* parameters_type_data() const {
+ return _parameters_type_data_di != -1 ? data_layout_at(_parameters_type_data_di)->data_in()->as_ParametersTypeData() : NULL;
+ }
+
+ int parameters_type_data_di() const {
+ assert(_parameters_type_data_di != -1, "no args type data");
+ return _parameters_type_data_di;
+ }
+
// Support for code generation
static ByteSize data_offset() {
return byte_offset_of(MethodData, _data[0]);
@@ -2060,6 +2151,10 @@
return byte_offset_of(MethodData, _backedge_counter);
}
+ static ByteSize parameters_type_data_di_offset() {
+ return byte_offset_of(MethodData, _parameters_type_data_di);
+ }
+
// Deallocation support - no pointer fields to deallocate
void deallocate_contents(ClassLoaderData* loader_data) {}
@@ -2083,8 +2178,10 @@
void verify_on(outputStream* st);
void verify_data_on(outputStream* st);
+ static bool profile_parameters_for_method(methodHandle m);
static bool profile_arguments();
static bool profile_return();
+ static bool profile_parameters();
static bool profile_return_jsr292_only();
};
--- a/hotspot/src/share/vm/opto/c2_globals.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -638,7 +638,13 @@
"Find best control for expensive operations") \
\
product(bool, UseMathExactIntrinsics, true, \
- "Enables intrinsification of various java.lang.Math funcitons")
+ "Enables intrinsification of various java.lang.Math functions") \
+ \
+ experimental(bool, ReplaceInParentMaps, false, \
+ "Propagate type improvements in callers of inlinee if possible") \
+ \
+ experimental(bool, UseTypeSpeculation, false, \
+ "Speculatively propagate types from profiles")
C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG)
--- a/hotspot/src/share/vm/opto/callGenerator.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -63,12 +63,12 @@
}
virtual bool is_parse() const { return true; }
- virtual JVMState* generate(JVMState* jvms);
+ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
int is_osr() { return _is_osr; }
};
-JVMState* ParseGenerator::generate(JVMState* jvms) {
+JVMState* ParseGenerator::generate(JVMState* jvms, Parse* parent_parser) {
Compile* C = Compile::current();
if (is_osr()) {
@@ -80,7 +80,7 @@
return NULL; // bailing out of the compile; do not try to parse
}
- Parse parser(jvms, method(), _expected_uses);
+ Parse parser(jvms, method(), _expected_uses, parent_parser);
// Grab signature for matching/allocation
#ifdef ASSERT
if (parser.tf() != (parser.depth() == 1 ? C->tf() : tf())) {
@@ -119,12 +119,12 @@
_separate_io_proj(separate_io_proj)
{
}
- virtual JVMState* generate(JVMState* jvms);
+ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
CallStaticJavaNode* call_node() const { return _call_node; }
};
-JVMState* DirectCallGenerator::generate(JVMState* jvms) {
+JVMState* DirectCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
GraphKit kit(jvms);
bool is_static = method()->is_static();
address target = is_static ? SharedRuntime::get_resolve_static_call_stub()
@@ -171,10 +171,10 @@
vtable_index >= 0, "either invalid or usable");
}
virtual bool is_virtual() const { return true; }
- virtual JVMState* generate(JVMState* jvms);
+ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
};
-JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
+JVMState* VirtualCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
GraphKit kit(jvms);
Node* receiver = kit.argument(0);
@@ -276,7 +276,7 @@
// Convert the CallStaticJava into an inline
virtual void do_late_inline();
- virtual JVMState* generate(JVMState* jvms) {
+ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
Compile *C = Compile::current();
C->print_inlining_skip(this);
@@ -290,7 +290,7 @@
// that the late inlining logic can distinguish between fall
// through and exceptional uses of the memory and io projections
// as is done for allocations and macro expansion.
- return DirectCallGenerator::generate(jvms);
+ return DirectCallGenerator::generate(jvms, parent_parser);
}
virtual void print_inlining_late(const char* msg) {
@@ -389,7 +389,7 @@
}
// Now perform the inling using the synthesized JVMState
- JVMState* new_jvms = _inline_cg->generate(jvms);
+ JVMState* new_jvms = _inline_cg->generate(jvms, NULL);
if (new_jvms == NULL) return; // no change
if (C->failing()) return;
@@ -429,8 +429,8 @@
virtual bool is_mh_late_inline() const { return true; }
- virtual JVMState* generate(JVMState* jvms) {
- JVMState* new_jvms = LateInlineCallGenerator::generate(jvms);
+ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
+ JVMState* new_jvms = LateInlineCallGenerator::generate(jvms, parent_parser);
if (_input_not_const) {
// inlining won't be possible so no need to enqueue right now.
call_node()->set_generator(this);
@@ -477,15 +477,17 @@
LateInlineStringCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
LateInlineCallGenerator(method, inline_cg) {}
- virtual JVMState* generate(JVMState* jvms) {
+ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
Compile *C = Compile::current();
C->print_inlining_skip(this);
C->add_string_late_inline(this);
- JVMState* new_jvms = DirectCallGenerator::generate(jvms);
+ JVMState* new_jvms = DirectCallGenerator::generate(jvms, parent_parser);
return new_jvms;
}
+
+ virtual bool is_string_late_inline() const { return true; }
};
CallGenerator* CallGenerator::for_string_late_inline(ciMethod* method, CallGenerator* inline_cg) {
@@ -498,13 +500,13 @@
LateInlineBoxingCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
LateInlineCallGenerator(method, inline_cg) {}
- virtual JVMState* generate(JVMState* jvms) {
+ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
Compile *C = Compile::current();
C->print_inlining_skip(this);
C->add_boxing_late_inline(this);
- JVMState* new_jvms = DirectCallGenerator::generate(jvms);
+ JVMState* new_jvms = DirectCallGenerator::generate(jvms, parent_parser);
return new_jvms;
}
};
@@ -540,7 +542,7 @@
virtual bool is_virtual() const { return _is_virtual; }
virtual bool is_deferred() const { return true; }
- virtual JVMState* generate(JVMState* jvms);
+ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
};
@@ -550,12 +552,12 @@
return new WarmCallGenerator(ci, if_cold, if_hot);
}
-JVMState* WarmCallGenerator::generate(JVMState* jvms) {
+JVMState* WarmCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
Compile* C = Compile::current();
if (C->log() != NULL) {
C->log()->elem("warm_call bci='%d'", jvms->bci());
}
- jvms = _if_cold->generate(jvms);
+ jvms = _if_cold->generate(jvms, parent_parser);
if (jvms != NULL) {
Node* m = jvms->map()->control();
if (m->is_CatchProj()) m = m->in(0); else m = C->top();
@@ -616,7 +618,7 @@
virtual bool is_inline() const { return _if_hit->is_inline(); }
virtual bool is_deferred() const { return _if_hit->is_deferred(); }
- virtual JVMState* generate(JVMState* jvms);
+ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
};
@@ -628,7 +630,7 @@
}
-JVMState* PredictedCallGenerator::generate(JVMState* jvms) {
+JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
GraphKit kit(jvms);
PhaseGVN& gvn = kit.gvn();
// We need an explicit receiver null_check before checking its type.
@@ -656,7 +658,7 @@
{ PreserveJVMState pjvms(&kit);
kit.set_control(slow_ctl);
if (!kit.stopped()) {
- slow_jvms = _if_missed->generate(kit.sync_jvms());
+ slow_jvms = _if_missed->generate(kit.sync_jvms(), parent_parser);
if (kit.failing())
return NULL; // might happen because of NodeCountInliningCutoff
assert(slow_jvms != NULL, "must be");
@@ -677,12 +679,12 @@
kit.replace_in_map(receiver, exact_receiver);
// Make the hot call:
- JVMState* new_jvms = _if_hit->generate(kit.sync_jvms());
+ JVMState* new_jvms = _if_hit->generate(kit.sync_jvms(), parent_parser);
if (new_jvms == NULL) {
// Inline failed, so make a direct call.
assert(_if_hit->is_inline(), "must have been a failed inline");
CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
- new_jvms = cg->generate(kit.sync_jvms());
+ new_jvms = cg->generate(kit.sync_jvms(), parent_parser);
}
kit.add_exception_states_from(new_jvms);
kit.set_jvms(new_jvms);
@@ -773,7 +775,7 @@
ciMethod* target = oop_ptr->const_oop()->as_method_handle()->get_vmtarget();
guarantee(!target->is_method_handle_intrinsic(), "should not happen"); // XXX remove
const int vtable_index = Method::invalid_vtable_index;
- CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS, true, true);
+ CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS, NULL, true, true);
assert(!cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
if (cg != NULL && cg->is_inline())
return cg;
@@ -829,6 +831,7 @@
int vtable_index = Method::invalid_vtable_index;
bool call_does_dispatch = false;
+ ciKlass* speculative_receiver_type = NULL;
if (is_virtual_or_interface) {
ciInstanceKlass* klass = target->holder();
Node* receiver_node = kit.argument(0);
@@ -837,9 +840,12 @@
target = C->optimize_virtual_call(caller, jvms->bci(), klass, target, receiver_type,
is_virtual,
call_does_dispatch, vtable_index); // out-parameters
+ // We lack profiling at this call but type speculation may
+ // provide us with a type
+ speculative_receiver_type = receiver_type->speculative_type();
}
- CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, true, true);
+ CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, speculative_receiver_type, true, true);
assert(!cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
if (cg != NULL && cg->is_inline())
return cg;
@@ -874,7 +880,7 @@
virtual bool is_inlined() const { return true; }
virtual bool is_intrinsic() const { return true; }
- virtual JVMState* generate(JVMState* jvms);
+ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
};
@@ -884,7 +890,7 @@
}
-JVMState* PredictedIntrinsicGenerator::generate(JVMState* jvms) {
+JVMState* PredictedIntrinsicGenerator::generate(JVMState* jvms, Parse* parent_parser) {
GraphKit kit(jvms);
PhaseGVN& gvn = kit.gvn();
@@ -904,7 +910,7 @@
PreserveJVMState pjvms(&kit);
kit.set_control(slow_ctl);
if (!kit.stopped()) {
- slow_jvms = _cg->generate(kit.sync_jvms());
+ slow_jvms = _cg->generate(kit.sync_jvms(), parent_parser);
if (kit.failing())
return NULL; // might happen because of NodeCountInliningCutoff
assert(slow_jvms != NULL, "must be");
@@ -922,12 +928,12 @@
}
// Generate intrinsic code:
- JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms());
+ JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms(), parent_parser);
if (new_jvms == NULL) {
// Intrinsic failed, so use slow code or make a direct call.
if (slow_map == NULL) {
CallGenerator* cg = CallGenerator::for_direct_call(method());
- new_jvms = cg->generate(kit.sync_jvms());
+ new_jvms = cg->generate(kit.sync_jvms(), parent_parser);
} else {
kit.set_jvms(slow_jvms);
return kit.transfer_exceptions_into_jvms();
@@ -997,7 +1003,7 @@
virtual bool is_virtual() const { ShouldNotReachHere(); return false; }
virtual bool is_trap() const { return true; }
- virtual JVMState* generate(JVMState* jvms);
+ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
};
@@ -1009,7 +1015,7 @@
}
-JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms) {
+JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
GraphKit kit(jvms);
// Take the trap with arguments pushed on the stack. (Cf. null_check_receiver).
int nargs = method()->arg_size();
--- a/hotspot/src/share/vm/opto/callGenerator.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/callGenerator.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -31,6 +31,8 @@
#include "opto/type.hpp"
#include "runtime/deoptimization.hpp"
+class Parse;
+
//---------------------------CallGenerator-------------------------------------
// The subclasses of this class handle generation of ideal nodes for
// call sites and method entry points.
@@ -72,6 +74,7 @@
virtual bool is_late_inline() const { return false; }
// same but for method handle calls
virtual bool is_mh_late_inline() const { return false; }
+ virtual bool is_string_late_inline() const{ return false; }
// for method handle calls: have we tried inlinining the call already?
virtual bool already_attempted() const { ShouldNotReachHere(); return false; }
@@ -108,7 +111,7 @@
//
// If the result is NULL, it means that this CallGenerator was unable
// to handle the given call, and another CallGenerator should be consulted.
- virtual JVMState* generate(JVMState* jvms) = 0;
+ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) = 0;
// How to generate a call site that is inlined:
static CallGenerator* for_inline(ciMethod* m, float expected_uses = -1);
--- a/hotspot/src/share/vm/opto/classes.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/classes.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -30,6 +30,7 @@
macro(AbsI)
macro(AddD)
macro(AddExactI)
+macro(AddExactL)
macro(AddF)
macro(AddI)
macro(AddL)
@@ -170,6 +171,8 @@
macro(Mach)
macro(MachProj)
macro(MathExact)
+macro(MathExactI)
+macro(MathExactL)
macro(MaxI)
macro(MemBarAcquire)
macro(MemBarAcquireLock)
@@ -189,12 +192,16 @@
macro(MoveL2D)
macro(MoveD2L)
macro(MulD)
+macro(MulExactI)
+macro(MulExactL)
macro(MulF)
macro(MulHiL)
macro(MulI)
macro(MulL)
macro(Multi)
macro(NegD)
+macro(NegExactI)
+macro(NegExactL)
macro(NegF)
macro(NeverBranch)
macro(Opaque1)
@@ -244,6 +251,8 @@
macro(StrEquals)
macro(StrIndexOf)
macro(SubD)
+macro(SubExactI)
+macro(SubExactL)
macro(SubF)
macro(SubI)
macro(SubL)
--- a/hotspot/src/share/vm/opto/compile.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/compile.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -655,7 +655,8 @@
_inlining_progress(false),
_inlining_incrementally(false),
_print_inlining_list(NULL),
- _print_inlining_idx(0) {
+ _print_inlining_idx(0),
+ _preserve_jvm_state(0) {
C = this;
CompileWrapper cw(this);
@@ -763,7 +764,7 @@
return;
}
JVMState* jvms = build_start_state(start(), tf());
- if ((jvms = cg->generate(jvms)) == NULL) {
+ if ((jvms = cg->generate(jvms, NULL)) == NULL) {
record_method_not_compilable("method parse failed");
return;
}
@@ -940,7 +941,8 @@
_inlining_progress(false),
_inlining_incrementally(false),
_print_inlining_list(NULL),
- _print_inlining_idx(0) {
+ _print_inlining_idx(0),
+ _preserve_jvm_state(0) {
C = this;
#ifndef PRODUCT
@@ -1358,7 +1360,7 @@
// During the 2nd round of IterGVN, NotNull castings are removed.
// Make sure the Bottom and NotNull variants alias the same.
// Also, make sure exact and non-exact variants alias the same.
- if( ptr == TypePtr::NotNull || ta->klass_is_exact() ) {
+ if (ptr == TypePtr::NotNull || ta->klass_is_exact() || ta->speculative() != NULL) {
tj = ta = TypeAryPtr::make(TypePtr::BotPTR,ta->ary(),ta->klass(),false,offset);
}
}
@@ -1383,6 +1385,9 @@
// Also, make sure exact and non-exact variants alias the same.
tj = to = TypeInstPtr::make(TypePtr::BotPTR,to->klass(),false,0,offset);
}
+ if (to->speculative() != NULL) {
+ tj = to = TypeInstPtr::make(to->ptr(),to->klass(),to->klass_is_exact(),to->const_oop(),to->offset(), to->instance_id());
+ }
// Canonicalize the holder of this field
if (offset >= 0 && offset < instanceOopDesc::base_offset_in_bytes()) {
// First handle header references such as a LoadKlassNode, even if the
@@ -2011,6 +2016,12 @@
if (failing()) return;
}
+ // Remove the speculative part of types and clean up the graph from
+ // the extra CastPP nodes whose only purpose is to carry them. Do
+ // that early so that optimizations are not disrupted by the extra
+ // CastPP nodes.
+ remove_speculative_types(igvn);
+
// No more new expensive nodes will be added to the list from here
// so keep only the actual candidates for optimizations.
cleanup_expensive_nodes(igvn);
@@ -3004,10 +3015,15 @@
if (result != NULL) {
for (DUIterator_Fast jmax, j = result->fast_outs(jmax); j < jmax; j++) {
Node* out = result->fast_out(j);
- if (out->in(0) == NULL) {
- out->set_req(0, non_throwing);
- } else if (out->in(0) == ctrl) {
- out->set_req(0, non_throwing);
+ // Phi nodes shouldn't be moved. They would only match below if they
+ // had the same control as the MathExactNode. The only time that
+ // would happen is if the Phi is also an input to the MathExact
+ if (!out->is_Phi()) {
+ if (out->in(0) == NULL) {
+ out->set_req(0, non_throwing);
+ } else if (out->in(0) == ctrl) {
+ out->set_req(0, non_throwing);
+ }
}
}
}
@@ -3792,6 +3808,45 @@
}
}
+/**
+ * Remove the speculative part of types and clean up the graph
+ */
+void Compile::remove_speculative_types(PhaseIterGVN &igvn) {
+ if (UseTypeSpeculation) {
+ Unique_Node_List worklist;
+ worklist.push(root());
+ int modified = 0;
+ // Go over all type nodes that carry a speculative type, drop the
+ // speculative part of the type and enqueue the node for an igvn
+ // which may optimize it out.
+ for (uint next = 0; next < worklist.size(); ++next) {
+ Node *n = worklist.at(next);
+ if (n->is_Type() && n->as_Type()->type()->isa_oopptr() != NULL &&
+ n->as_Type()->type()->is_oopptr()->speculative() != NULL) {
+ TypeNode* tn = n->as_Type();
+ const TypeOopPtr* t = tn->type()->is_oopptr();
+ bool in_hash = igvn.hash_delete(n);
+ assert(in_hash, "node should be in igvn hash table");
+ tn->set_type(t->remove_speculative());
+ igvn.hash_insert(n);
+ igvn._worklist.push(n); // give it a chance to go away
+ modified++;
+ }
+ uint max = n->len();
+ for( uint i = 0; i < max; ++i ) {
+ Node *m = n->in(i);
+ if (not_a_node(m)) continue;
+ worklist.push(m);
+ }
+ }
+ // Drop the speculative part of all types in the igvn's type table
+ igvn.remove_speculative_types();
+ if (modified > 0) {
+ igvn.optimize();
+ }
+ }
+}
+
// Auxiliary method to support randomized stressing/fuzzing.
//
// This method can be called the arbitrary number of times, with current count
--- a/hotspot/src/share/vm/opto/compile.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/compile.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -424,6 +424,11 @@
static int cmp_expensive_nodes(Node** n1, Node** n2);
// Expensive nodes list already sorted?
bool expensive_nodes_sorted() const;
+ // Remove the speculative part of types and clean up the graph
+ void remove_speculative_types(PhaseIterGVN &igvn);
+
+ // Are we within a PreserveJVMState block?
+ int _preserve_jvm_state;
public:
@@ -820,7 +825,9 @@
// Decide how to build a call.
// The profile factor is a discount to apply to this site's interp. profile.
- CallGenerator* call_generator(ciMethod* call_method, int vtable_index, bool call_does_dispatch, JVMState* jvms, bool allow_inline, float profile_factor, bool allow_intrinsics = true, bool delayed_forbidden = false);
+ CallGenerator* call_generator(ciMethod* call_method, int vtable_index, bool call_does_dispatch,
+ JVMState* jvms, bool allow_inline, float profile_factor, ciKlass* speculative_receiver_type = NULL,
+ bool allow_intrinsics = true, bool delayed_forbidden = false);
bool should_delay_inlining(ciMethod* call_method, JVMState* jvms) {
return should_delay_string_inlining(call_method, jvms) ||
should_delay_boxing_inlining(call_method, jvms);
@@ -1156,6 +1163,21 @@
// Auxiliary method for randomized fuzzing/stressing
static bool randomized_select(int count);
+
+ // enter a PreserveJVMState block
+ void inc_preserve_jvm_state() {
+ _preserve_jvm_state++;
+ }
+
+ // exit a PreserveJVMState block
+ void dec_preserve_jvm_state() {
+ _preserve_jvm_state--;
+ assert(_preserve_jvm_state >= 0, "_preserve_jvm_state shouldn't be negative");
+ }
+
+ bool has_preserve_jvm_state() const {
+ return _preserve_jvm_state > 0;
+ }
};
#endif // SHARE_VM_OPTO_COMPILE_HPP
--- a/hotspot/src/share/vm/opto/doCall.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/doCall.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -63,7 +63,8 @@
CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool call_does_dispatch,
JVMState* jvms, bool allow_inline,
- float prof_factor, bool allow_intrinsics, bool delayed_forbidden) {
+ float prof_factor, ciKlass* speculative_receiver_type,
+ bool allow_intrinsics, bool delayed_forbidden) {
ciMethod* caller = jvms->method();
int bci = jvms->bci();
Bytecodes::Code bytecode = caller->java_code_at_bci(bci);
@@ -117,7 +118,7 @@
if (cg->is_predicted()) {
// Code without intrinsic but, hopefully, inlined.
CallGenerator* inline_cg = this->call_generator(callee,
- vtable_index, call_does_dispatch, jvms, allow_inline, prof_factor, false);
+ vtable_index, call_does_dispatch, jvms, allow_inline, prof_factor, speculative_receiver_type, false);
if (inline_cg != NULL) {
cg = CallGenerator::for_predicted_intrinsic(cg, inline_cg);
}
@@ -212,8 +213,24 @@
// The major receiver's count >= TypeProfileMajorReceiverPercent of site_count.
bool have_major_receiver = (100.*profile.receiver_prob(0) >= (float)TypeProfileMajorReceiverPercent);
ciMethod* receiver_method = NULL;
- if (have_major_receiver || profile.morphism() == 1 ||
- (profile.morphism() == 2 && UseBimorphicInlining)) {
+
+ int morphism = profile.morphism();
+ if (speculative_receiver_type != NULL) {
+ // We have a speculative type, we should be able to resolve
+ // the call. We do that before looking at the profiling at
+ // this invoke because it may lead to bimorphic inlining which
+ // a speculative type should help us avoid.
+ receiver_method = callee->resolve_invoke(jvms->method()->holder(),
+ speculative_receiver_type);
+ if (receiver_method == NULL) {
+ speculative_receiver_type = NULL;
+ } else {
+ morphism = 1;
+ }
+ }
+ if (receiver_method == NULL &&
+ (have_major_receiver || morphism == 1 ||
+ (morphism == 2 && UseBimorphicInlining))) {
// receiver_method = profile.method();
// Profiles do not suggest methods now. Look it up in the major receiver.
receiver_method = callee->resolve_invoke(jvms->method()->holder(),
@@ -227,7 +244,7 @@
// Look up second receiver.
CallGenerator* next_hit_cg = NULL;
ciMethod* next_receiver_method = NULL;
- if (profile.morphism() == 2 && UseBimorphicInlining) {
+ if (morphism == 2 && UseBimorphicInlining) {
next_receiver_method = callee->resolve_invoke(jvms->method()->holder(),
profile.receiver(1));
if (next_receiver_method != NULL) {
@@ -242,11 +259,10 @@
}
}
CallGenerator* miss_cg;
- Deoptimization::DeoptReason reason = (profile.morphism() == 2) ?
+ Deoptimization::DeoptReason reason = morphism == 2 ?
Deoptimization::Reason_bimorphic :
Deoptimization::Reason_class_check;
- if (( profile.morphism() == 1 ||
- (profile.morphism() == 2 && next_hit_cg != NULL) ) &&
+ if ((morphism == 1 || (morphism == 2 && next_hit_cg != NULL)) &&
!too_many_traps(jvms->method(), jvms->bci(), reason)
) {
// Generate uncommon trap for class check failure path
@@ -260,6 +276,7 @@
}
if (miss_cg != NULL) {
if (next_hit_cg != NULL) {
+ assert(speculative_receiver_type == NULL, "shouldn't end up here if we used speculation");
trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), next_receiver_method, profile.receiver(1), site_count, profile.receiver_count(1));
// We don't need to record dependency on a receiver here and below.
// Whenever we inline, the dependency is added by Parse::Parse().
@@ -267,7 +284,9 @@
}
if (miss_cg != NULL) {
trace_type_profile(C, jvms->method(), jvms->depth() - 1, jvms->bci(), receiver_method, profile.receiver(0), site_count, receiver_count);
- CallGenerator* cg = CallGenerator::for_predicted_call(profile.receiver(0), miss_cg, hit_cg, profile.receiver_prob(0));
+ ciKlass* k = speculative_receiver_type != NULL ? speculative_receiver_type : profile.receiver(0);
+ float hit_prob = speculative_receiver_type != NULL ? 1.0 : profile.receiver_prob(0);
+ CallGenerator* cg = CallGenerator::for_predicted_call(k, miss_cg, hit_cg, hit_prob);
if (cg != NULL) return cg;
}
}
@@ -446,13 +465,16 @@
int vtable_index = Method::invalid_vtable_index;
bool call_does_dispatch = false;
+ // Speculative type of the receiver if any
+ ciKlass* speculative_receiver_type = NULL;
if (is_virtual_or_interface) {
- Node* receiver_node = stack(sp() - nargs);
+ Node* receiver_node = stack(sp() - nargs);
const TypeOopPtr* receiver_type = _gvn.type(receiver_node)->isa_oopptr();
// call_does_dispatch and vtable_index are out-parameters. They might be changed.
callee = C->optimize_virtual_call(method(), bci(), klass, orig_callee, receiver_type,
is_virtual,
call_does_dispatch, vtable_index); // out-parameters
+ speculative_receiver_type = receiver_type != NULL ? receiver_type->speculative_type() : NULL;
}
// Note: It's OK to try to inline a virtual call.
@@ -468,7 +490,7 @@
// Decide call tactic.
// This call checks with CHA, the interpreter profile, intrinsics table, etc.
// It decides whether inlining is desirable or not.
- CallGenerator* cg = C->call_generator(callee, vtable_index, call_does_dispatch, jvms, try_inline, prof_factor());
+ CallGenerator* cg = C->call_generator(callee, vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), speculative_receiver_type);
// NOTE: Don't use orig_callee and callee after this point! Use cg->method() instead.
orig_callee = callee = NULL;
@@ -477,6 +499,10 @@
// Round double arguments before call
round_double_arguments(cg->method());
+ // Feed profiling data for arguments to the type system so it can
+ // propagate it as speculative types
+ record_profiled_arguments_for_speculation(cg->method(), bc());
+
#ifndef PRODUCT
// bump global counters for calls
count_compiled_calls(/*at_method_entry*/ false, cg->is_inline());
@@ -491,11 +517,18 @@
// save across call, for a subsequent cast_not_null.
Node* receiver = has_receiver ? argument(0) : NULL;
+ // The extra CheckCastPP for speculative types mess with PhaseStringOpts
+ if (receiver != NULL && !call_does_dispatch && !cg->is_string_late_inline()) {
+ // Feed profiling data for a single receiver to the type system so
+ // it can propagate it as a speculative type
+ receiver = record_profiled_receiver_for_speculation(receiver);
+ }
+
// Bump method data counters (We profile *before* the call is made
// because exceptions don't return to the call site.)
profile_call(receiver);
- JVMState* new_jvms = cg->generate(jvms);
+ JVMState* new_jvms = cg->generate(jvms, this);
if (new_jvms == NULL) {
// When inlining attempt fails (e.g., too many arguments),
// it may contaminate the current compile state, making it
@@ -508,8 +541,8 @@
// the call site, perhaps because it did not match a pattern the
// intrinsic was expecting to optimize. Should always be possible to
// get a normal java call that may inline in that case
- cg = C->call_generator(cg->method(), vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), /* allow_intrinsics= */ false);
- if ((new_jvms = cg->generate(jvms)) == NULL) {
+ cg = C->call_generator(cg->method(), vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), speculative_receiver_type, /* allow_intrinsics= */ false);
+ if ((new_jvms = cg->generate(jvms, this)) == NULL) {
guarantee(failing(), "call failed to generate: calls should work");
return;
}
@@ -607,6 +640,16 @@
null_assert(peek());
set_bci(iter().cur_bci()); // put it back
}
+ BasicType ct = ctype->basic_type();
+ if (ct == T_OBJECT || ct == T_ARRAY) {
+ ciKlass* better_type = method()->return_profiled_type(bci());
+ if (UseTypeSpeculation && better_type != NULL) {
+ // If profiling reports a single type for the return value,
+ // feed it to the type system so it can propagate it as a
+ // speculative type
+ record_profile_for_speculation(stack(sp()-1), better_type);
+ }
+ }
}
// Restart record of parsing work after possible inlining of call
--- a/hotspot/src/share/vm/opto/graphKit.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/graphKit.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -639,6 +639,7 @@
_map = kit->map(); // preserve the map
_sp = kit->sp();
kit->set_map(clone_map ? kit->clone_map() : NULL);
+ Compile::current()->inc_preserve_jvm_state();
#ifdef ASSERT
_bci = kit->bci();
Parse* parser = kit->is_Parse();
@@ -656,6 +657,7 @@
#endif
kit->set_map(_map);
kit->set_sp(_sp);
+ Compile::current()->dec_preserve_jvm_state();
}
@@ -1373,17 +1375,70 @@
//--------------------------replace_in_map-------------------------------------
void GraphKit::replace_in_map(Node* old, Node* neww) {
- this->map()->replace_edge(old, neww);
+ if (old == neww) {
+ return;
+ }
+
+ map()->replace_edge(old, neww);
// Note: This operation potentially replaces any edge
// on the map. This includes locals, stack, and monitors
// of the current (innermost) JVM state.
- // We can consider replacing in caller maps.
- // The idea would be that an inlined function's null checks
- // can be shared with the entire inlining tree.
- // The expense of doing this is that the PreserveJVMState class
- // would have to preserve caller states too, with a deep copy.
+ if (!ReplaceInParentMaps) {
+ return;
+ }
+
+ // PreserveJVMState doesn't do a deep copy so we can't modify
+ // parents
+ if (Compile::current()->has_preserve_jvm_state()) {
+ return;
+ }
+
+ Parse* parser = is_Parse();
+ bool progress = true;
+ Node* ctrl = map()->in(0);
+ // Follow the chain of parsers and see whether the update can be
+ // done in the map of callers. We can do the replace for a caller if
+ // the current control post dominates the control of a caller.
+ while (parser != NULL && parser->caller() != NULL && progress) {
+ progress = false;
+ Node* parent_map = parser->caller()->map();
+ assert(parser->exits().map()->jvms()->depth() == parser->caller()->depth(), "map mismatch");
+
+ Node* parent_ctrl = parent_map->in(0);
+
+ while (parent_ctrl->is_Region()) {
+ Node* n = parent_ctrl->as_Region()->is_copy();
+ if (n == NULL) {
+ break;
+ }
+ parent_ctrl = n;
+ }
+
+ for (;;) {
+ if (ctrl == parent_ctrl) {
+ // update the map of the exits which is the one that will be
+ // used when compilation resume after inlining
+ parser->exits().map()->replace_edge(old, neww);
+ progress = true;
+ break;
+ }
+ if (ctrl->is_Proj() && ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) {
+ ctrl = ctrl->in(0)->in(0);
+ } else if (ctrl->is_Region()) {
+ Node* n = ctrl->as_Region()->is_copy();
+ if (n == NULL) {
+ break;
+ }
+ ctrl = n;
+ } else {
+ break;
+ }
+ }
+
+ parser = parser->parent_parser();
+ }
}
@@ -2043,6 +2098,104 @@
}
}
+/**
+ * Record profiling data exact_kls for Node n with the type system so
+ * that it can propagate it (speculation)
+ *
+ * @param n node that the type applies to
+ * @param exact_kls type from profiling
+ *
+ * @return node with improved type
+ */
+Node* GraphKit::record_profile_for_speculation(Node* n, ciKlass* exact_kls) {
+ const TypeOopPtr* current_type = _gvn.type(n)->isa_oopptr();
+ assert(UseTypeSpeculation, "type speculation must be on");
+ if (exact_kls != NULL &&
+ // nothing to improve if type is already exact
+ (current_type == NULL ||
+ (!current_type->klass_is_exact() &&
+ (current_type->speculative() == NULL ||
+ !current_type->speculative()->klass_is_exact())))) {
+ const TypeKlassPtr* tklass = TypeKlassPtr::make(exact_kls);
+ const TypeOopPtr* xtype = tklass->as_instance_type();
+ assert(xtype->klass_is_exact(), "Should be exact");
+
+ // Build a type with a speculative type (what we think we know
+ // about the type but will need a guard when we use it)
+ const TypeOopPtr* spec_type = TypeOopPtr::make(TypePtr::BotPTR, Type::OffsetBot, TypeOopPtr::InstanceBot, xtype);
+ // We're changing the type, we need a new cast node to carry the
+ // new type. The new type depends on the control: what profiling
+ // tells us is only valid from here as far as we can tell.
+ Node* cast = new(C) CastPPNode(n, spec_type);
+ cast->init_req(0, control());
+ cast = _gvn.transform(cast);
+ replace_in_map(n, cast);
+ n = cast;
+ }
+ return n;
+}
+
+/**
+ * Record profiling data from receiver profiling at an invoke with the
+ * type system so that it can propagate it (speculation)
+ *
+ * @param n receiver node
+ *
+ * @return node with improved type
+ */
+Node* GraphKit::record_profiled_receiver_for_speculation(Node* n) {
+ if (!UseTypeSpeculation) {
+ return n;
+ }
+ ciKlass* exact_kls = profile_has_unique_klass();
+ return record_profile_for_speculation(n, exact_kls);
+}
+
+/**
+ * Record profiling data from argument profiling at an invoke with the
+ * type system so that it can propagate it (speculation)
+ *
+ * @param dest_method target method for the call
+ * @param bc what invoke bytecode is this?
+ */
+void GraphKit::record_profiled_arguments_for_speculation(ciMethod* dest_method, Bytecodes::Code bc) {
+ if (!UseTypeSpeculation) {
+ return;
+ }
+ const TypeFunc* tf = TypeFunc::make(dest_method);
+ int nargs = tf->_domain->_cnt - TypeFunc::Parms;
+ int skip = Bytecodes::has_receiver(bc) ? 1 : 0;
+ for (int j = skip, i = 0; j < nargs && i < TypeProfileArgsLimit; j++) {
+ const Type *targ = tf->_domain->field_at(j + TypeFunc::Parms);
+ if (targ->basic_type() == T_OBJECT || targ->basic_type() == T_ARRAY) {
+ ciKlass* better_type = method()->argument_profiled_type(bci(), i);
+ if (better_type != NULL) {
+ record_profile_for_speculation(argument(j), better_type);
+ }
+ i++;
+ }
+ }
+}
+
+/**
+ * Record profiling data from parameter profiling at an invoke with
+ * the type system so that it can propagate it (speculation)
+ */
+void GraphKit::record_profiled_parameters_for_speculation() {
+ if (!UseTypeSpeculation) {
+ return;
+ }
+ for (int i = 0, j = 0; i < method()->arg_size() ; i++) {
+ if (_gvn.type(local(i))->isa_oopptr()) {
+ ciKlass* better_type = method()->parameter_profiled_type(j);
+ if (better_type != NULL) {
+ record_profile_for_speculation(local(i), better_type);
+ }
+ j++;
+ }
+ }
+}
+
void GraphKit::round_double_result(ciMethod* dest_method) {
// A non-strict method may return a double value which has an extended
// exponent, but this must not be visible in a caller which is 'strict'
@@ -2580,10 +2733,10 @@
// If the profile has seen exactly one type, narrow to exactly that type.
// Subsequent type checks will always fold up.
Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj,
- ciProfileData* data,
- ciKlass* require_klass) {
+ ciKlass* require_klass,
+ ciKlass* spec_klass,
+ bool safe_for_replace) {
if (!UseTypeProfile || !TypeProfileCasts) return NULL;
- if (data == NULL) return NULL;
// Make sure we haven't already deoptimized from this tactic.
if (too_many_traps(Deoptimization::Reason_class_check))
@@ -2591,15 +2744,15 @@
// (No, this isn't a call, but it's enough like a virtual call
// to use the same ciMethod accessor to get the profile info...)
- ciCallProfile profile = method()->call_profile_at_bci(bci());
- if (profile.count() >= 0 && // no cast failures here
- profile.has_receiver(0) &&
- profile.morphism() == 1) {
- ciKlass* exact_kls = profile.receiver(0);
+ // If we have a speculative type use it instead of profiling (which
+ // may not help us)
+ ciKlass* exact_kls = spec_klass == NULL ? profile_has_unique_klass() : spec_klass;
+ if (exact_kls != NULL) {// no cast failures here
if (require_klass == NULL ||
static_subtype_check(require_klass, exact_kls) == SSC_always_true) {
- // If we narrow the type to match what the type profile sees,
- // we can then remove the rest of the cast.
+ // If we narrow the type to match what the type profile sees or
+ // the speculative type, we can then remove the rest of the
+ // cast.
// This is a win, even if the exact_kls is very specific,
// because downstream operations, such as method calls,
// will often benefit from the sharper type.
@@ -2611,7 +2764,9 @@
uncommon_trap(Deoptimization::Reason_class_check,
Deoptimization::Action_maybe_recompile);
}
- replace_in_map(not_null_obj, exact_obj);
+ if (safe_for_replace) {
+ replace_in_map(not_null_obj, exact_obj);
+ }
return exact_obj;
}
// assert(ssc == SSC_always_true)... except maybe the profile lied to us.
@@ -2620,11 +2775,59 @@
return NULL;
}
+/**
+ * Cast obj to type and emit guard unless we had too many traps here
+ * already
+ *
+ * @param obj node being casted
+ * @param type type to cast the node to
+ * @param not_null true if we know node cannot be null
+ */
+Node* GraphKit::maybe_cast_profiled_obj(Node* obj,
+ ciKlass* type,
+ bool not_null) {
+ // type == NULL if profiling tells us this object is always null
+ if (type != NULL) {
+ if (!too_many_traps(Deoptimization::Reason_null_check) &&
+ !too_many_traps(Deoptimization::Reason_class_check)) {
+ Node* not_null_obj = NULL;
+ // not_null is true if we know the object is not null and
+ // there's no need for a null check
+ if (!not_null) {
+ Node* null_ctl = top();
+ not_null_obj = null_check_oop(obj, &null_ctl, true, true);
+ assert(null_ctl->is_top(), "no null control here");
+ } else {
+ not_null_obj = obj;
+ }
+
+ Node* exact_obj = not_null_obj;
+ ciKlass* exact_kls = type;
+ Node* slow_ctl = type_check_receiver(exact_obj, exact_kls, 1.0,
+ &exact_obj);
+ {
+ PreserveJVMState pjvms(this);
+ set_control(slow_ctl);
+ uncommon_trap(Deoptimization::Reason_class_check,
+ Deoptimization::Action_maybe_recompile);
+ }
+ replace_in_map(not_null_obj, exact_obj);
+ obj = exact_obj;
+ }
+ } else {
+ if (!too_many_traps(Deoptimization::Reason_null_assert)) {
+ Node* exact_obj = null_assert(obj);
+ replace_in_map(obj, exact_obj);
+ obj = exact_obj;
+ }
+ }
+ return obj;
+}
//-------------------------------gen_instanceof--------------------------------
// Generate an instance-of idiom. Used by both the instance-of bytecode
// and the reflective instance-of call.
-Node* GraphKit::gen_instanceof(Node* obj, Node* superklass) {
+Node* GraphKit::gen_instanceof(Node* obj, Node* superklass, bool safe_for_replace) {
kill_dead_locals(); // Benefit all the uncommon traps
assert( !stopped(), "dead parse path should be checked in callers" );
assert(!TypePtr::NULL_PTR->higher_equal(_gvn.type(superklass)->is_klassptr()),
@@ -2637,10 +2840,8 @@
C->set_has_split_ifs(true); // Has chance for split-if optimization
ciProfileData* data = NULL;
- bool safe_for_replace = false;
if (java_bc() == Bytecodes::_instanceof) { // Only for the bytecode
data = method()->method_data()->bci_to_data(bci());
- safe_for_replace = true;
}
bool never_see_null = (ProfileDynamicTypes // aggressive use of profile
&& seems_never_null(obj, data));
@@ -2664,14 +2865,37 @@
phi ->del_req(_null_path);
}
- if (ProfileDynamicTypes && data != NULL) {
- Node* cast_obj = maybe_cast_profiled_receiver(not_null_obj, data, NULL);
- if (stopped()) { // Profile disagrees with this path.
- set_control(null_ctl); // Null is the only remaining possibility.
- return intcon(0);
+ // Do we know the type check always succeed?
+ bool known_statically = false;
+ if (_gvn.type(superklass)->singleton()) {
+ ciKlass* superk = _gvn.type(superklass)->is_klassptr()->klass();
+ ciKlass* subk = _gvn.type(obj)->is_oopptr()->klass();
+ if (subk != NULL && subk->is_loaded()) {
+ int static_res = static_subtype_check(superk, subk);
+ known_statically = (static_res == SSC_always_true || static_res == SSC_always_false);
}
- if (cast_obj != NULL)
- not_null_obj = cast_obj;
+ }
+
+ if (known_statically && UseTypeSpeculation) {
+ // If we know the type check always succeed then we don't use the
+ // profiling data at this bytecode. Don't lose it, feed it to the
+ // type system as a speculative type.
+ not_null_obj = record_profiled_receiver_for_speculation(not_null_obj);
+ } else {
+ const TypeOopPtr* obj_type = _gvn.type(obj)->is_oopptr();
+ // We may not have profiling here or it may not help us. If we
+ // have a speculative type use it to perform an exact cast.
+ ciKlass* spec_obj_type = obj_type->speculative_type();
+ if (spec_obj_type != NULL || (ProfileDynamicTypes && data != NULL)) {
+ Node* cast_obj = maybe_cast_profiled_receiver(not_null_obj, NULL, spec_obj_type, safe_for_replace);
+ if (stopped()) { // Profile disagrees with this path.
+ set_control(null_ctl); // Null is the only remaining possibility.
+ return intcon(0);
+ }
+ if (cast_obj != NULL) {
+ not_null_obj = cast_obj;
+ }
+ }
}
// Load the object's klass
@@ -2718,7 +2942,10 @@
if (objtp != NULL && objtp->klass() != NULL) {
switch (static_subtype_check(tk->klass(), objtp->klass())) {
case SSC_always_true:
- return obj;
+ // If we know the type check always succeed then we don't use
+ // the profiling data at this bytecode. Don't lose it, feed it
+ // to the type system as a speculative type.
+ return record_profiled_receiver_for_speculation(obj);
case SSC_always_false:
// It needs a null check because a null will *pass* the cast check.
// A non-null value will always produce an exception.
@@ -2767,12 +2994,17 @@
}
Node* cast_obj = NULL;
- if (data != NULL &&
- // Counter has never been decremented (due to cast failure).
- // ...This is a reasonable thing to expect. It is true of
- // all casts inserted by javac to implement generic types.
- data->as_CounterData()->count() >= 0) {
- cast_obj = maybe_cast_profiled_receiver(not_null_obj, data, tk->klass());
+ const TypeOopPtr* obj_type = _gvn.type(obj)->is_oopptr();
+ // We may not have profiling here or it may not help us. If we have
+ // a speculative type use it to perform an exact cast.
+ ciKlass* spec_obj_type = obj_type->speculative_type();
+ if (spec_obj_type != NULL ||
+ (data != NULL &&
+ // Counter has never been decremented (due to cast failure).
+ // ...This is a reasonable thing to expect. It is true of
+ // all casts inserted by javac to implement generic types.
+ data->as_CounterData()->count() >= 0)) {
+ cast_obj = maybe_cast_profiled_receiver(not_null_obj, tk->klass(), spec_obj_type, safe_for_replace);
if (cast_obj != NULL) {
if (failure_control != NULL) // failure is now impossible
(*failure_control) = top();
--- a/hotspot/src/share/vm/opto/graphKit.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/graphKit.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -386,10 +386,33 @@
// Check the null_seen bit.
bool seems_never_null(Node* obj, ciProfileData* data);
+ // Check for unique class for receiver at call
+ ciKlass* profile_has_unique_klass() {
+ ciCallProfile profile = method()->call_profile_at_bci(bci());
+ if (profile.count() >= 0 && // no cast failures here
+ profile.has_receiver(0) &&
+ profile.morphism() == 1) {
+ return profile.receiver(0);
+ }
+ return NULL;
+ }
+
+ // record type from profiling with the type system
+ Node* record_profile_for_speculation(Node* n, ciKlass* exact_kls);
+ Node* record_profiled_receiver_for_speculation(Node* n);
+ void record_profiled_arguments_for_speculation(ciMethod* dest_method, Bytecodes::Code bc);
+ void record_profiled_parameters_for_speculation();
+
// Use the type profile to narrow an object type.
Node* maybe_cast_profiled_receiver(Node* not_null_obj,
- ciProfileData* data,
- ciKlass* require_klass);
+ ciKlass* require_klass,
+ ciKlass* spec,
+ bool safe_for_replace);
+
+ // Cast obj to type and emit guard unless we had too many traps here already
+ Node* maybe_cast_profiled_obj(Node* obj,
+ ciKlass* type,
+ bool not_null = false);
// Cast obj to not-null on this path
Node* cast_not_null(Node* obj, bool do_replace_in_map = true);
@@ -775,7 +798,7 @@
// Generate an instance-of idiom. Used by both the instance-of bytecode
// and the reflective instance-of call.
- Node* gen_instanceof( Node *subobj, Node* superkls );
+ Node* gen_instanceof(Node *subobj, Node* superkls, bool safe_for_replace = false);
// Generate a check-cast idiom. Used by both the check-cast bytecode
// and the array-store bytecode
--- a/hotspot/src/share/vm/opto/ifnode.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/ifnode.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -1019,7 +1019,7 @@
// be skipped. For example, range check predicate has two checks
// for lower and upper bounds.
ProjNode* unc_proj = proj_out(1 - prev_dom->as_Proj()->_con)->as_Proj();
- if (PhaseIdealLoop::is_uncommon_trap_proj(unc_proj, Deoptimization::Reason_predicate))
+ if (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate))
prev_dom = idom;
// Now walk the current IfNode's projections.
--- a/hotspot/src/share/vm/opto/library_call.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -63,7 +63,7 @@
virtual bool is_virtual() const { return _is_virtual; }
virtual bool is_predicted() const { return _is_predicted; }
virtual bool does_virtual_dispatch() const { return _does_virtual_dispatch; }
- virtual JVMState* generate(JVMState* jvms);
+ virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
virtual Node* generate_predicate(JVMState* jvms);
vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; }
};
@@ -203,8 +203,15 @@
bool inline_math_native(vmIntrinsics::ID id);
bool inline_trig(vmIntrinsics::ID id);
bool inline_math(vmIntrinsics::ID id);
- bool inline_math_mathExact(Node* math);
- bool inline_math_addExact();
+ void inline_math_mathExact(Node* math);
+ bool inline_math_addExactI(bool is_increment);
+ bool inline_math_addExactL(bool is_increment);
+ bool inline_math_multiplyExactI();
+ bool inline_math_multiplyExactL();
+ bool inline_math_negateExactI();
+ bool inline_math_negateExactL();
+ bool inline_math_subtractExactI(bool is_decrement);
+ bool inline_math_subtractExactL(bool is_decrement);
bool inline_exp();
bool inline_pow();
void finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName);
@@ -507,13 +514,33 @@
if (!UseCRC32Intrinsics) return NULL;
break;
- case vmIntrinsics::_addExact:
- if (!Matcher::match_rule_supported(Op_AddExactI)) {
- return NULL;
- }
- if (!UseMathExactIntrinsics) {
- return NULL;
- }
+ case vmIntrinsics::_incrementExactI:
+ case vmIntrinsics::_addExactI:
+ if (!Matcher::match_rule_supported(Op_AddExactI) || !UseMathExactIntrinsics) return NULL;
+ break;
+ case vmIntrinsics::_incrementExactL:
+ case vmIntrinsics::_addExactL:
+ if (!Matcher::match_rule_supported(Op_AddExactL) || !UseMathExactIntrinsics) return NULL;
+ break;
+ case vmIntrinsics::_decrementExactI:
+ case vmIntrinsics::_subtractExactI:
+ if (!Matcher::match_rule_supported(Op_SubExactI) || !UseMathExactIntrinsics) return NULL;
+ break;
+ case vmIntrinsics::_decrementExactL:
+ case vmIntrinsics::_subtractExactL:
+ if (!Matcher::match_rule_supported(Op_SubExactL) || !UseMathExactIntrinsics) return NULL;
+ break;
+ case vmIntrinsics::_negateExactI:
+ if (!Matcher::match_rule_supported(Op_NegExactI) || !UseMathExactIntrinsics) return NULL;
+ break;
+ case vmIntrinsics::_negateExactL:
+ if (!Matcher::match_rule_supported(Op_NegExactL) || !UseMathExactIntrinsics) return NULL;
+ break;
+ case vmIntrinsics::_multiplyExactI:
+ if (!Matcher::match_rule_supported(Op_MulExactI) || !UseMathExactIntrinsics) return NULL;
+ break;
+ case vmIntrinsics::_multiplyExactL:
+ if (!Matcher::match_rule_supported(Op_MulExactL) || !UseMathExactIntrinsics) return NULL;
break;
default:
@@ -556,7 +583,7 @@
// Nothing to do here.
}
-JVMState* LibraryIntrinsic::generate(JVMState* jvms) {
+JVMState* LibraryIntrinsic::generate(JVMState* jvms, Parse* parent_parser) {
LibraryCallKit kit(jvms, this);
Compile* C = kit.C;
int nodes = C->unique();
@@ -686,7 +713,18 @@
case vmIntrinsics::_min:
case vmIntrinsics::_max: return inline_min_max(intrinsic_id());
- case vmIntrinsics::_addExact: return inline_math_addExact();
+ case vmIntrinsics::_addExactI: return inline_math_addExactI(false /* add */);
+ case vmIntrinsics::_addExactL: return inline_math_addExactL(false /* add */);
+ case vmIntrinsics::_decrementExactI: return inline_math_subtractExactI(true /* decrement */);
+ case vmIntrinsics::_decrementExactL: return inline_math_subtractExactL(true /* decrement */);
+ case vmIntrinsics::_incrementExactI: return inline_math_addExactI(true /* increment */);
+ case vmIntrinsics::_incrementExactL: return inline_math_addExactL(true /* increment */);
+ case vmIntrinsics::_multiplyExactI: return inline_math_multiplyExactI();
+ case vmIntrinsics::_multiplyExactL: return inline_math_multiplyExactL();
+ case vmIntrinsics::_negateExactI: return inline_math_negateExactI();
+ case vmIntrinsics::_negateExactL: return inline_math_negateExactL();
+ case vmIntrinsics::_subtractExactI: return inline_math_subtractExactI(false /* subtract */);
+ case vmIntrinsics::_subtractExactL: return inline_math_subtractExactL(false /* subtract */);
case vmIntrinsics::_arraycopy: return inline_arraycopy();
@@ -1931,7 +1969,14 @@
return true;
}
-bool LibraryCallKit::inline_math_mathExact(Node* math) {
+void LibraryCallKit::inline_math_mathExact(Node* math) {
+ // If we didn't get the expected opcode it means we have optimized
+ // the node to something else and don't need the exception edge.
+ if (!math->is_MathExact()) {
+ set_result(math);
+ return;
+ }
+
Node* result = _gvn.transform( new(C) ProjNode(math, MathExactNode::result_proj_node));
Node* flags = _gvn.transform( new(C) FlagsProjNode(math, MathExactNode::flags_proj_node));
@@ -1954,19 +1999,106 @@
set_control(fast_path);
set_result(result);
+}
+
+bool LibraryCallKit::inline_math_addExactI(bool is_increment) {
+ Node* arg1 = argument(0);
+ Node* arg2 = NULL;
+
+ if (is_increment) {
+ arg2 = intcon(1);
+ } else {
+ arg2 = argument(1);
+ }
+
+ Node* add = _gvn.transform( new(C) AddExactINode(NULL, arg1, arg2) );
+ inline_math_mathExact(add);
+ return true;
+}
+
+bool LibraryCallKit::inline_math_addExactL(bool is_increment) {
+ Node* arg1 = argument(0); // type long
+ // argument(1) == TOP
+ Node* arg2 = NULL;
+
+ if (is_increment) {
+ arg2 = longcon(1);
+ } else {
+ arg2 = argument(2); // type long
+ // argument(3) == TOP
+ }
+
+ Node* add = _gvn.transform(new(C) AddExactLNode(NULL, arg1, arg2));
+ inline_math_mathExact(add);
return true;
}
-bool LibraryCallKit::inline_math_addExact() {
+bool LibraryCallKit::inline_math_subtractExactI(bool is_decrement) {
+ Node* arg1 = argument(0);
+ Node* arg2 = NULL;
+
+ if (is_decrement) {
+ arg2 = intcon(1);
+ } else {
+ arg2 = argument(1);
+ }
+
+ Node* sub = _gvn.transform(new(C) SubExactINode(NULL, arg1, arg2));
+ inline_math_mathExact(sub);
+ return true;
+}
+
+bool LibraryCallKit::inline_math_subtractExactL(bool is_decrement) {
+ Node* arg1 = argument(0); // type long
+ // argument(1) == TOP
+ Node* arg2 = NULL;
+
+ if (is_decrement) {
+ arg2 = longcon(1);
+ } else {
+ Node* arg2 = argument(2); // type long
+ // argument(3) == TOP
+ }
+
+ Node* sub = _gvn.transform(new(C) SubExactLNode(NULL, arg1, arg2));
+ inline_math_mathExact(sub);
+ return true;
+}
+
+bool LibraryCallKit::inline_math_negateExactI() {
+ Node* arg1 = argument(0);
+
+ Node* neg = _gvn.transform(new(C) NegExactINode(NULL, arg1));
+ inline_math_mathExact(neg);
+ return true;
+}
+
+bool LibraryCallKit::inline_math_negateExactL() {
+ Node* arg1 = argument(0);
+ // argument(1) == TOP
+
+ Node* neg = _gvn.transform(new(C) NegExactLNode(NULL, arg1));
+ inline_math_mathExact(neg);
+ return true;
+}
+
+bool LibraryCallKit::inline_math_multiplyExactI() {
Node* arg1 = argument(0);
Node* arg2 = argument(1);
- Node* add = _gvn.transform( new(C) AddExactINode(NULL, arg1, arg2) );
- if (add->Opcode() == Op_AddExactI) {
- return inline_math_mathExact(add);
- } else {
- set_result(add);
- }
+ Node* mul = _gvn.transform(new(C) MulExactINode(NULL, arg1, arg2));
+ inline_math_mathExact(mul);
+ return true;
+}
+
+bool LibraryCallKit::inline_math_multiplyExactL() {
+ Node* arg1 = argument(0);
+ // argument(1) == TOP
+ Node* arg2 = argument(2);
+ // argument(3) == TOP
+
+ Node* mul = _gvn.transform(new(C) MulExactLNode(NULL, arg1, arg2));
+ inline_math_mathExact(mul);
return true;
}
@@ -3353,6 +3485,7 @@
// If kls is null, we have a primitive mirror.
phi->init_req(_prim_path, prim_return_value);
if (stopped()) { set_result(region, phi); return true; }
+ bool safe_for_replace = (region->in(_prim_path) == top());
Node* p; // handy temp
Node* null_ctl;
@@ -3363,7 +3496,7 @@
switch (id) {
case vmIntrinsics::_isInstance:
// nothing is an instance of a primitive type
- query_value = gen_instanceof(obj, kls);
+ query_value = gen_instanceof(obj, kls, safe_for_replace);
break;
case vmIntrinsics::_getModifiers:
@@ -4553,8 +4686,62 @@
const Type* dest_type = dest->Value(&_gvn);
const TypeAryPtr* top_src = src_type->isa_aryptr();
const TypeAryPtr* top_dest = dest_type->isa_aryptr();
- if (top_src == NULL || top_src->klass() == NULL ||
- top_dest == NULL || top_dest->klass() == NULL) {
+
+ // Do we have the type of src?
+ bool has_src = (top_src != NULL && top_src->klass() != NULL);
+ // Do we have the type of dest?
+ bool has_dest = (top_dest != NULL && top_dest->klass() != NULL);
+ // Is the type for src from speculation?
+ bool src_spec = false;
+ // Is the type for dest from speculation?
+ bool dest_spec = false;
+
+ if (!has_src || !has_dest) {
+ // We don't have sufficient type information, let's see if
+ // speculative types can help. We need to have types for both src
+ // and dest so that it pays off.
+
+ // Do we already have or could we have type information for src
+ bool could_have_src = has_src;
+ // Do we already have or could we have type information for dest
+ bool could_have_dest = has_dest;
+
+ ciKlass* src_k = NULL;
+ if (!has_src) {
+ src_k = src_type->speculative_type();
+ if (src_k != NULL && src_k->is_array_klass()) {
+ could_have_src = true;
+ }
+ }
+
+ ciKlass* dest_k = NULL;
+ if (!has_dest) {
+ dest_k = dest_type->speculative_type();
+ if (dest_k != NULL && dest_k->is_array_klass()) {
+ could_have_dest = true;
+ }
+ }
+
+ if (could_have_src && could_have_dest) {
+ // This is going to pay off so emit the required guards
+ if (!has_src) {
+ src = maybe_cast_profiled_obj(src, src_k);
+ src_type = _gvn.type(src);
+ top_src = src_type->isa_aryptr();
+ has_src = (top_src != NULL && top_src->klass() != NULL);
+ src_spec = true;
+ }
+ if (!has_dest) {
+ dest = maybe_cast_profiled_obj(dest, dest_k);
+ dest_type = _gvn.type(dest);
+ top_dest = dest_type->isa_aryptr();
+ has_dest = (top_dest != NULL && top_dest->klass() != NULL);
+ dest_spec = true;
+ }
+ }
+ }
+
+ if (!has_src || !has_dest) {
// Conservatively insert a memory barrier on all memory slices.
// Do not let writes into the source float below the arraycopy.
insert_mem_bar(Op_MemBarCPUOrder);
@@ -4589,6 +4776,40 @@
return true;
}
+ if (src_elem == T_OBJECT) {
+ // If both arrays are object arrays then having the exact types
+ // for both will remove the need for a subtype check at runtime
+ // before the call and may make it possible to pick a faster copy
+ // routine (without a subtype check on every element)
+ // Do we have the exact type of src?
+ bool could_have_src = src_spec;
+ // Do we have the exact type of dest?
+ bool could_have_dest = dest_spec;
+ ciKlass* src_k = top_src->klass();
+ ciKlass* dest_k = top_dest->klass();
+ if (!src_spec) {
+ src_k = src_type->speculative_type();
+ if (src_k != NULL && src_k->is_array_klass()) {
+ could_have_src = true;
+ }
+ }
+ if (!dest_spec) {
+ dest_k = dest_type->speculative_type();
+ if (dest_k != NULL && dest_k->is_array_klass()) {
+ could_have_dest = true;
+ }
+ }
+ if (could_have_src && could_have_dest) {
+ // If we can have both exact types, emit the missing guards
+ if (could_have_src && !src_spec) {
+ src = maybe_cast_profiled_obj(src, src_k);
+ }
+ if (could_have_dest && !dest_spec) {
+ dest = maybe_cast_profiled_obj(dest, dest_k);
+ }
+ }
+ }
+
//---------------------------------------------------------------------------
// We will make a fast path for this call to arraycopy.
--- a/hotspot/src/share/vm/opto/loopPredicate.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/loopPredicate.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -41,63 +41,6 @@
* checks (such as null checks).
*/
-//-------------------------------is_uncommon_trap_proj----------------------------
-// Return true if proj is the form of "proj->[region->..]call_uct"
-bool PhaseIdealLoop::is_uncommon_trap_proj(ProjNode* proj, Deoptimization::DeoptReason reason) {
- int path_limit = 10;
- assert(proj, "invalid argument");
- Node* out = proj;
- for (int ct = 0; ct < path_limit; ct++) {
- out = out->unique_ctrl_out();
- if (out == NULL)
- return false;
- if (out->is_CallStaticJava()) {
- int req = out->as_CallStaticJava()->uncommon_trap_request();
- if (req != 0) {
- Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req);
- if (trap_reason == reason || reason == Deoptimization::Reason_none) {
- return true;
- }
- }
- return false; // don't do further after call
- }
- if (out->Opcode() != Op_Region)
- return false;
- }
- return false;
-}
-
-//-------------------------------is_uncommon_trap_if_pattern-------------------------
-// Return true for "if(test)-> proj -> ...
-// |
-// V
-// other_proj->[region->..]call_uct"
-//
-// "must_reason_predicate" means the uct reason must be Reason_predicate
-bool PhaseIdealLoop::is_uncommon_trap_if_pattern(ProjNode *proj, Deoptimization::DeoptReason reason) {
- Node *in0 = proj->in(0);
- if (!in0->is_If()) return false;
- // Variation of a dead If node.
- if (in0->outcnt() < 2) return false;
- IfNode* iff = in0->as_If();
-
- // we need "If(Conv2B(Opaque1(...)))" pattern for reason_predicate
- if (reason != Deoptimization::Reason_none) {
- if (iff->in(1)->Opcode() != Op_Conv2B ||
- iff->in(1)->in(1)->Opcode() != Op_Opaque1) {
- return false;
- }
- }
-
- ProjNode* other_proj = iff->proj_out(1-proj->_con)->as_Proj();
- if (is_uncommon_trap_proj(other_proj, reason)) {
- assert(reason == Deoptimization::Reason_none ||
- Compile::current()->is_predicate_opaq(iff->in(1)->in(1)), "should be on the list");
- return true;
- }
- return false;
-}
-
//-------------------------------register_control-------------------------
void PhaseIdealLoop::register_control(Node* n, IdealLoopTree *loop, Node* pred) {
assert(n->is_CFG(), "must be control node");
@@ -147,7 +90,7 @@
// This code is also used to clone predicates to clonned loops.
ProjNode* PhaseIdealLoop::create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry,
Deoptimization::DeoptReason reason) {
- assert(is_uncommon_trap_if_pattern(cont_proj, reason), "must be a uct if pattern!");
+ assert(cont_proj->is_uncommon_trap_if_pattern(reason), "must be a uct if pattern!");
IfNode* iff = cont_proj->in(0)->as_If();
ProjNode *uncommon_proj = iff->proj_out(1 - cont_proj->_con);
@@ -235,7 +178,7 @@
ProjNode* PhaseIterGVN::create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry,
Deoptimization::DeoptReason reason) {
assert(new_entry != 0, "only used for clone predicate");
- assert(PhaseIdealLoop::is_uncommon_trap_if_pattern(cont_proj, reason), "must be a uct if pattern!");
+ assert(cont_proj->is_uncommon_trap_if_pattern(reason), "must be a uct if pattern!");
IfNode* iff = cont_proj->in(0)->as_If();
ProjNode *uncommon_proj = iff->proj_out(1 - cont_proj->_con);
@@ -422,7 +365,7 @@
ProjNode* PhaseIdealLoop::find_predicate_insertion_point(Node* start_c, Deoptimization::DeoptReason reason) {
if (start_c == NULL || !start_c->is_Proj())
return NULL;
- if (is_uncommon_trap_if_pattern(start_c->as_Proj(), reason)) {
+ if (start_c->as_Proj()->is_uncommon_trap_if_pattern(reason)) {
return start_c->as_Proj();
}
return NULL;
@@ -773,7 +716,7 @@
ProjNode* proj = if_proj_list.pop()->as_Proj();
IfNode* iff = proj->in(0)->as_If();
- if (!is_uncommon_trap_if_pattern(proj, Deoptimization::Reason_none)) {
+ if (!proj->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) {
if (loop->is_loop_exit(iff)) {
// stop processing the remaining projs in the list because the execution of them
// depends on the condition of "iff" (iff->in(1)).
--- a/hotspot/src/share/vm/opto/loopnode.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -167,7 +167,7 @@
// expensive nodes will notice the loop and skip over it to try to
// move the node further up.
if (ctl->is_CountedLoop() && ctl->in(1) != NULL && ctl->in(1)->in(0) != NULL && ctl->in(1)->in(0)->is_If()) {
- if (!is_uncommon_trap_if_pattern(ctl->in(1)->as_Proj(), Deoptimization::Reason_none)) {
+ if (!ctl->in(1)->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) {
break;
}
next = idom(ctl->in(1)->in(0));
@@ -181,7 +181,7 @@
} else if (parent_ctl->is_CountedLoopEnd() && parent_ctl->as_CountedLoopEnd()->loopnode() != NULL) {
next = parent_ctl->as_CountedLoopEnd()->loopnode()->init_control();
} else if (parent_ctl->is_If()) {
- if (!is_uncommon_trap_if_pattern(ctl->as_Proj(), Deoptimization::Reason_none)) {
+ if (!ctl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) {
break;
}
assert(idom(ctl) == parent_ctl, "strange");
--- a/hotspot/src/share/vm/opto/loopnode.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/loopnode.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -876,13 +876,6 @@
// Return true if exp is a scaled induction var plus (or minus) constant
bool is_scaled_iv_plus_offset(Node* exp, Node* iv, int* p_scale, Node** p_offset, int depth = 0);
- // Return true if proj is for "proj->[region->..]call_uct"
- static bool is_uncommon_trap_proj(ProjNode* proj, Deoptimization::DeoptReason reason);
- // Return true for "if(test)-> proj -> ...
- // |
- // V
- // other_proj->[region->..]call_uct"
- static bool is_uncommon_trap_if_pattern(ProjNode* proj, Deoptimization::DeoptReason reason);
// Create a new if above the uncommon_trap_if_pattern for the predicate to be promoted
ProjNode* create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry,
Deoptimization::DeoptReason reason);
--- a/hotspot/src/share/vm/opto/loopopts.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/loopopts.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -238,7 +238,7 @@
ProjNode* dp_proj = dp->as_Proj();
ProjNode* unc_proj = iff->as_If()->proj_out(1 - dp_proj->_con)->as_Proj();
if (exclude_loop_predicate &&
- is_uncommon_trap_proj(unc_proj, Deoptimization::Reason_predicate))
+ unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate))
return; // Let IGVN transformation change control dependence.
IdealLoopTree *old_loop = get_loop(dp);
--- a/hotspot/src/share/vm/opto/matcher.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/matcher.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -338,6 +338,7 @@
static RegMask modL_proj_mask();
static const RegMask mathExactI_result_proj_mask();
+ static const RegMask mathExactL_result_proj_mask();
static const RegMask mathExactI_flags_proj_mask();
// Use hardware DIV instruction when it is faster than
--- a/hotspot/src/share/vm/opto/mathexactnode.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/mathexactnode.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -31,10 +31,17 @@
#include "opto/mathexactnode.hpp"
#include "opto/subnode.hpp"
-MathExactNode::MathExactNode(Node* ctrl, Node* n1, Node* n2) : MultiNode(3) {
+MathExactNode::MathExactNode(Node* ctrl, Node* in1) : MultiNode(2) {
+ init_class_id(Class_MathExact);
init_req(0, ctrl);
- init_req(1, n1);
- init_req(2, n2);
+ init_req(1, in1);
+}
+
+MathExactNode::MathExactNode(Node* ctrl, Node* in1, Node* in2) : MultiNode(3) {
+ init_class_id(Class_MathExact);
+ init_req(0, ctrl);
+ init_req(1, in1);
+ init_req(2, in2);
}
BoolNode* MathExactNode::bool_node() const {
@@ -64,23 +71,10 @@
return ifnode->proj_out(1);
}
-Node* AddExactINode::match(const ProjNode* proj, const Matcher* m) {
- uint ideal_reg = proj->ideal_reg();
- RegMask rm;
- if (proj->_con == result_proj_node) {
- rm = m->mathExactI_result_proj_mask();
- } else {
- assert(proj->_con == flags_proj_node, "must be result or flags");
- assert(ideal_reg == Op_RegFlags, "sanity");
- rm = m->mathExactI_flags_proj_mask();
- }
- return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg);
-}
-
// If the MathExactNode won't overflow we have to replace the
// FlagsProjNode and ProjNode that is generated by the MathExactNode
-Node* MathExactNode::no_overflow(PhaseGVN *phase, Node* new_result) {
- PhaseIterGVN *igvn = phase->is_IterGVN();
+Node* MathExactNode::no_overflow(PhaseGVN* phase, Node* new_result) {
+ PhaseIterGVN* igvn = phase->is_IterGVN();
if (igvn) {
ProjNode* result = result_node();
ProjNode* flags = flags_node();
@@ -110,9 +104,35 @@
return new_result;
}
-Node *AddExactINode::Ideal(PhaseGVN *phase, bool can_reshape) {
- Node *arg1 = in(1);
- Node *arg2 = in(2);
+Node* MathExactINode::match(const ProjNode* proj, const Matcher* m) {
+ uint ideal_reg = proj->ideal_reg();
+ RegMask rm;
+ if (proj->_con == result_proj_node) {
+ rm = m->mathExactI_result_proj_mask();
+ } else {
+ assert(proj->_con == flags_proj_node, "must be result or flags");
+ assert(ideal_reg == Op_RegFlags, "sanity");
+ rm = m->mathExactI_flags_proj_mask();
+ }
+ return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg);
+}
+
+Node* MathExactLNode::match(const ProjNode* proj, const Matcher* m) {
+ uint ideal_reg = proj->ideal_reg();
+ RegMask rm;
+ if (proj->_con == result_proj_node) {
+ rm = m->mathExactL_result_proj_mask();
+ } else {
+ assert(proj->_con == flags_proj_node, "must be result or flags");
+ assert(ideal_reg == Op_RegFlags, "sanity");
+ rm = m->mathExactI_flags_proj_mask();
+ }
+ return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg);
+}
+
+Node* AddExactINode::Ideal(PhaseGVN* phase, bool can_reshape) {
+ Node* arg1 = in(1);
+ Node* arg2 = in(2);
const Type* type1 = phase->type(arg1);
const Type* type2 = phase->type(arg2);
@@ -130,12 +150,7 @@
return NULL;
}
- if (type1 == TypeInt::ZERO) { // (Add 0 x) == x
- Node* add_result = new (phase->C) AddINode(arg1, arg2);
- return no_overflow(phase, add_result);
- }
-
- if (type2 == TypeInt::ZERO) { // (Add x 0) == x
+ if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) { // (Add 0 x) == x
Node* add_result = new (phase->C) AddINode(arg1, arg2);
return no_overflow(phase, add_result);
}
@@ -169,3 +184,247 @@
return NULL;
}
+Node* AddExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+ Node* arg1 = in(1);
+ Node* arg2 = in(2);
+
+ const Type* type1 = phase->type(arg1);
+ const Type* type2 = phase->type(arg2);
+
+ if (type1 != Type::TOP && type1->singleton() &&
+ type2 != Type::TOP && type2->singleton()) {
+ jlong val1 = arg1->get_long();
+ jlong val2 = arg2->get_long();
+ jlong result = val1 + val2;
+ // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result
+ if ( (((val1 ^ result) & (val2 ^ result)) >= 0)) {
+ Node* con_result = ConLNode::make(phase->C, result);
+ return no_overflow(phase, con_result);
+ }
+ return NULL;
+ }
+
+ if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) { // (Add 0 x) == x
+ Node* add_result = new (phase->C) AddLNode(arg1, arg2);
+ return no_overflow(phase, add_result);
+ }
+
+ if (type2->singleton()) {
+ return NULL; // no change - keep constant on the right
+ }
+
+ if (type1->singleton()) {
+ // Make it x + Constant - move constant to the right
+ swap_edges(1, 2);
+ return this;
+ }
+
+ if (arg2->is_Load()) {
+ return NULL; // no change - keep load on the right
+ }
+
+ if (arg1->is_Load()) {
+ // Make it x + Load - move load to the right
+ swap_edges(1, 2);
+ return this;
+ }
+
+ if (arg1->_idx > arg2->_idx) {
+ // Sort the edges
+ swap_edges(1, 2);
+ return this;
+ }
+
+ return NULL;
+}
+
+Node* SubExactINode::Ideal(PhaseGVN* phase, bool can_reshape) {
+ Node* arg1 = in(1);
+ Node* arg2 = in(2);
+
+ const Type* type1 = phase->type(arg1);
+ const Type* type2 = phase->type(arg2);
+
+ if (type1 != Type::TOP && type1->singleton() &&
+ type2 != Type::TOP && type2->singleton()) {
+ jint val1 = arg1->get_int();
+ jint val2 = arg2->get_int();
+ jint result = val1 - val2;
+
+ // Hacker's Delight 2-12 Overflow iff the arguments have different signs and
+ // the sign of the result is different than the sign of arg1
+ if (((val1 ^ val2) & (val1 ^ result)) >= 0) {
+ Node* con_result = ConINode::make(phase->C, result);
+ return no_overflow(phase, con_result);
+ }
+ return NULL;
+ }
+
+ if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) {
+ // Sub with zero is the same as add with zero
+ Node* add_result = new (phase->C) AddINode(arg1, arg2);
+ return no_overflow(phase, add_result);
+ }
+
+ return NULL;
+}
+
+Node* SubExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+ Node* arg1 = in(1);
+ Node* arg2 = in(2);
+
+ const Type* type1 = phase->type(arg1);
+ const Type* type2 = phase->type(arg2);
+
+ if (type1 != Type::TOP && type1->singleton() &&
+ type2 != Type::TOP && type2->singleton()) {
+ jlong val1 = arg1->get_long();
+ jlong val2 = arg2->get_long();
+ jlong result = val1 - val2;
+
+ // Hacker's Delight 2-12 Overflow iff the arguments have different signs and
+ // the sign of the result is different than the sign of arg1
+ if (((val1 ^ val2) & (val1 ^ result)) >= 0) {
+ Node* con_result = ConLNode::make(phase->C, result);
+ return no_overflow(phase, con_result);
+ }
+ return NULL;
+ }
+
+ if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) {
+ // Sub with zero is the same as add with zero
+ Node* add_result = new (phase->C) AddLNode(arg1, arg2);
+ return no_overflow(phase, add_result);
+ }
+
+ return NULL;
+}
+
+Node* NegExactINode::Ideal(PhaseGVN* phase, bool can_reshape) {
+ Node *arg = in(1);
+
+ const Type* type = phase->type(arg);
+ if (type != Type::TOP && type->singleton()) {
+ jint value = arg->get_int();
+ if (value != min_jint) {
+ Node* neg_result = ConINode::make(phase->C, -value);
+ return no_overflow(phase, neg_result);
+ }
+ }
+ return NULL;
+}
+
+Node* NegExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+ Node *arg = in(1);
+
+ const Type* type = phase->type(arg);
+ if (type != Type::TOP && type->singleton()) {
+ jlong value = arg->get_long();
+ if (value != min_jlong) {
+ Node* neg_result = ConLNode::make(phase->C, -value);
+ return no_overflow(phase, neg_result);
+ }
+ }
+ return NULL;
+}
+
+Node* MulExactINode::Ideal(PhaseGVN* phase, bool can_reshape) {
+ Node* arg1 = in(1);
+ Node* arg2 = in(2);
+
+ const Type* type1 = phase->type(arg1);
+ const Type* type2 = phase->type(arg2);
+
+ if (type1 != Type::TOP && type1->singleton() &&
+ type2 != Type::TOP && type2->singleton()) {
+ jint val1 = arg1->get_int();
+ jint val2 = arg2->get_int();
+ jlong result = (jlong) val1 * (jlong) val2;
+ if ((jint) result == result) {
+ // no overflow
+ Node* mul_result = ConINode::make(phase->C, result);
+ return no_overflow(phase, mul_result);
+ }
+ }
+
+ if (type1 == TypeInt::ZERO || type2 == TypeInt::ZERO) {
+ return no_overflow(phase, ConINode::make(phase->C, 0));
+ }
+
+ if (type1 == TypeInt::ONE) {
+ Node* mul_result = new (phase->C) AddINode(arg2, phase->intcon(0));
+ return no_overflow(phase, mul_result);
+ }
+ if (type2 == TypeInt::ONE) {
+ Node* mul_result = new (phase->C) AddINode(arg1, phase->intcon(0));
+ return no_overflow(phase, mul_result);
+ }
+
+ if (type1 == TypeInt::MINUS_1) {
+ return new (phase->C) NegExactINode(NULL, arg2);
+ }
+
+ if (type2 == TypeInt::MINUS_1) {
+ return new (phase->C) NegExactINode(NULL, arg1);
+ }
+
+ return NULL;
+}
+
+Node* MulExactLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
+ Node* arg1 = in(1);
+ Node* arg2 = in(2);
+
+ const Type* type1 = phase->type(arg1);
+ const Type* type2 = phase->type(arg2);
+
+ if (type1 != Type::TOP && type1->singleton() &&
+ type2 != Type::TOP && type2->singleton()) {
+ jlong val1 = arg1->get_long();
+ jlong val2 = arg2->get_long();
+
+ jlong result = val1 * val2;
+ jlong ax = (val1 < 0 ? -val1 : val1);
+ jlong ay = (val2 < 0 ? -val2 : val2);
+
+ bool overflow = false;
+ if ((ax | ay) & CONST64(0xFFFFFFFF00000000)) {
+ // potential overflow if any bit in upper 32 bits are set
+ if ((val1 == min_jlong && val2 == -1) || (val2 == min_jlong && val1 == -1)) {
+ // -1 * Long.MIN_VALUE will overflow
+ overflow = true;
+ } else if (val2 != 0 && (result / val2 != val1)) {
+ overflow = true;
+ }
+ }
+
+ if (!overflow) {
+ Node* mul_result = ConLNode::make(phase->C, result);
+ return no_overflow(phase, mul_result);
+ }
+ }
+
+ if (type1 == TypeLong::ZERO || type2 == TypeLong::ZERO) {
+ return no_overflow(phase, ConLNode::make(phase->C, 0));
+ }
+
+ if (type1 == TypeLong::ONE) {
+ Node* mul_result = new (phase->C) AddLNode(arg2, phase->longcon(0));
+ return no_overflow(phase, mul_result);
+ }
+ if (type2 == TypeLong::ONE) {
+ Node* mul_result = new (phase->C) AddLNode(arg1, phase->longcon(0));
+ return no_overflow(phase, mul_result);
+ }
+
+ if (type1 == TypeLong::MINUS_1) {
+ return new (phase->C) NegExactLNode(NULL, arg2);
+ }
+
+ if (type2 == TypeLong::MINUS_1) {
+ return new (phase->C) NegExactLNode(NULL, arg1);
+ }
+
+ return NULL;
+}
+
--- a/hotspot/src/share/vm/opto/mathexactnode.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/mathexactnode.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -39,6 +39,7 @@
class MathExactNode : public MultiNode {
public:
+ MathExactNode(Node* ctrl, Node* in1);
MathExactNode(Node* ctrl, Node* in1, Node* in2);
enum {
result_proj_node = 0,
@@ -62,13 +63,78 @@
Node* no_overflow(PhaseGVN *phase, Node* new_result);
};
-class AddExactINode : public MathExactNode {
+class MathExactINode : public MathExactNode {
+ public:
+ MathExactINode(Node* ctrl, Node* in1) : MathExactNode(ctrl, in1) {}
+ MathExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactNode(ctrl, in1, in2) {}
+ virtual int Opcode() const;
+ virtual Node* match(const ProjNode* proj, const Matcher* m);
+ virtual const Type* bottom_type() const { return TypeTuple::INT_CC_PAIR; }
+};
+
+class MathExactLNode : public MathExactNode {
public:
- AddExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactNode(ctrl, in1, in2) {}
+ MathExactLNode(Node* ctrl, Node* in1) : MathExactNode(ctrl, in1) {}
+ MathExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactNode(ctrl, in1, in2) {}
+ virtual int Opcode() const;
+ virtual Node* match(const ProjNode* proj, const Matcher* m);
+ virtual const Type* bottom_type() const { return TypeTuple::LONG_CC_PAIR; }
+};
+
+class AddExactINode : public MathExactINode {
+public:
+ AddExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactINode(ctrl, in1, in2) {}
+ virtual int Opcode() const;
+ virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+};
+
+class AddExactLNode : public MathExactLNode {
+public:
+ AddExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactLNode(ctrl, in1, in2) {}
+ virtual int Opcode() const;
+ virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
+class SubExactINode : public MathExactINode {
+public:
+ SubExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactINode(ctrl, in1, in2) {}
virtual int Opcode() const;
- virtual const Type* bottom_type() const { return TypeTuple::INT_CC_PAIR; }
- virtual Node* match(const ProjNode* proj, const Matcher* m);
- virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
+ virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
+class SubExactLNode : public MathExactLNode {
+public:
+ SubExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactLNode(ctrl, in1, in2) {}
+ virtual int Opcode() const;
+ virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
+class NegExactINode : public MathExactINode {
+public:
+ NegExactINode(Node* ctrl, Node* in1) : MathExactINode(ctrl, in1) {}
+ virtual int Opcode() const;
+ virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
+class NegExactLNode : public MathExactLNode {
+public:
+ NegExactLNode(Node* ctrl, Node* in1) : MathExactLNode(ctrl, in1) {}
+ virtual int Opcode() const;
+ virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
+class MulExactINode : public MathExactINode {
+public:
+ MulExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactINode(ctrl, in1, in2) {}
+ virtual int Opcode() const;
+ virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
+};
+
+class MulExactLNode : public MathExactLNode {
+public:
+ MulExactLNode(Node* ctrl, Node* in1, Node* in2) : MathExactLNode(ctrl, in1, in2) {}
+ virtual int Opcode() const;
+ virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
};
class FlagsProjNode : public ProjNode {
--- a/hotspot/src/share/vm/opto/multnode.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/multnode.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "opto/callnode.hpp"
+#include "opto/cfgnode.hpp"
#include "opto/matcher.hpp"
#include "opto/mathexactnode.hpp"
#include "opto/multnode.hpp"
@@ -150,3 +151,59 @@
uint ProjNode::ideal_reg() const {
return bottom_type()->ideal_reg();
}
+
+//-------------------------------is_uncommon_trap_proj----------------------------
+// Return true if proj is the form of "proj->[region->..]call_uct"
+bool ProjNode::is_uncommon_trap_proj(Deoptimization::DeoptReason reason) {
+ int path_limit = 10;
+ Node* out = this;
+ for (int ct = 0; ct < path_limit; ct++) {
+ out = out->unique_ctrl_out();
+ if (out == NULL)
+ return false;
+ if (out->is_CallStaticJava()) {
+ int req = out->as_CallStaticJava()->uncommon_trap_request();
+ if (req != 0) {
+ Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req);
+ if (trap_reason == reason || reason == Deoptimization::Reason_none) {
+ return true;
+ }
+ }
+ return false; // don't do further after call
+ }
+ if (out->Opcode() != Op_Region)
+ return false;
+ }
+ return false;
+}
+
+//-------------------------------is_uncommon_trap_if_pattern-------------------------
+// Return true for "if(test)-> proj -> ...
+// |
+// V
+// other_proj->[region->..]call_uct"
+//
+// "must_reason_predicate" means the uct reason must be Reason_predicate
+bool ProjNode::is_uncommon_trap_if_pattern(Deoptimization::DeoptReason reason) {
+ Node *in0 = in(0);
+ if (!in0->is_If()) return false;
+ // Variation of a dead If node.
+ if (in0->outcnt() < 2) return false;
+ IfNode* iff = in0->as_If();
+
+ // we need "If(Conv2B(Opaque1(...)))" pattern for reason_predicate
+ if (reason != Deoptimization::Reason_none) {
+ if (iff->in(1)->Opcode() != Op_Conv2B ||
+ iff->in(1)->in(1)->Opcode() != Op_Opaque1) {
+ return false;
+ }
+ }
+
+ ProjNode* other_proj = iff->proj_out(1-_con)->as_Proj();
+ if (other_proj->is_uncommon_trap_proj(reason)) {
+ assert(reason == Deoptimization::Reason_none ||
+ Compile::current()->is_predicate_opaq(iff->in(1)->in(1)), "should be on the list");
+ return true;
+ }
+ return false;
+}
--- a/hotspot/src/share/vm/opto/multnode.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/multnode.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -88,6 +88,14 @@
#ifndef PRODUCT
virtual void dump_spec(outputStream *st) const;
#endif
+
+ // Return true if proj is for "proj->[region->..]call_uct"
+ bool is_uncommon_trap_proj(Deoptimization::DeoptReason reason);
+ // Return true for "if(test)-> proj -> ...
+ // |
+ // V
+ // other_proj->[region->..]call_uct"
+ bool is_uncommon_trap_if_pattern(Deoptimization::DeoptReason reason);
};
#endif // SHARE_VM_OPTO_MULTNODE_HPP
--- a/hotspot/src/share/vm/opto/node.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/node.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -100,6 +100,7 @@
class MachSpillCopyNode;
class MachTempNode;
class Matcher;
+class MathExactNode;
class MemBarNode;
class MemBarStoreStoreNode;
class MemNode;
@@ -568,6 +569,7 @@
DEFINE_CLASS_ID(MemBar, Multi, 3)
DEFINE_CLASS_ID(Initialize, MemBar, 0)
DEFINE_CLASS_ID(MemBarStoreStore, MemBar, 1)
+ DEFINE_CLASS_ID(MathExact, Multi, 4)
DEFINE_CLASS_ID(Mach, Node, 1)
DEFINE_CLASS_ID(MachReturn, Mach, 0)
@@ -757,6 +759,7 @@
DEFINE_CLASS_QUERY(MachSafePoint)
DEFINE_CLASS_QUERY(MachSpillCopy)
DEFINE_CLASS_QUERY(MachTemp)
+ DEFINE_CLASS_QUERY(MathExact)
DEFINE_CLASS_QUERY(Mem)
DEFINE_CLASS_QUERY(MemBar)
DEFINE_CLASS_QUERY(MemBarStoreStore)
--- a/hotspot/src/share/vm/opto/parse.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/parse.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -349,13 +349,15 @@
int _est_switch_depth; // Debugging SwitchRanges.
#endif
+ // parser for the caller of the method of this object
+ Parse* const _parent;
+
public:
// Constructor
- Parse(JVMState* caller, ciMethod* parse_method, float expected_uses);
+ Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, Parse* parent);
virtual Parse* is_Parse() const { return (Parse*)this; }
- public:
// Accessors.
JVMState* caller() const { return _caller; }
float expected_uses() const { return _expected_uses; }
@@ -407,6 +409,8 @@
return block()->successor_for_bci(bci);
}
+ Parse* parent_parser() const { return _parent; }
+
private:
// Create a JVMS & map for the initial state of this method.
SafePointNode* create_entry_map();
@@ -603,6 +607,9 @@
// Assumes that there is no applicable local handler.
void throw_to_exit(SafePointNode* ex_map);
+ // Use speculative type to optimize CmpP node
+ Node* optimize_cmp_with_klass(Node* c);
+
public:
#ifndef PRODUCT
// Handle PrintOpto, etc.
--- a/hotspot/src/share/vm/opto/parse1.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/parse1.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -381,8 +381,8 @@
//------------------------------Parse------------------------------------------
// Main parser constructor.
-Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses)
- : _exits(caller)
+Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, Parse* parent)
+ : _exits(caller), _parent(parent)
{
// Init some variables
_caller = caller;
@@ -1102,6 +1102,10 @@
_synch_lock = shared_lock(lock_obj);
}
+ // Feed profiling data for parameters to the type system so it can
+ // propagate it as speculative types
+ record_profiled_parameters_for_speculation();
+
if (depth() == 1) {
increment_and_test_invocation_counter(Tier2CompileThreshold);
}
--- a/hotspot/src/share/vm/opto/parse2.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/parse2.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -1366,6 +1366,56 @@
}
}
+/**
+ * Use speculative type to optimize CmpP node: if comparison is
+ * against the low level class, cast the object to the speculative
+ * type if any. CmpP should then go away.
+ *
+ * @param c expected CmpP node
+ * @return result of CmpP on object casted to speculative type
+ *
+ */
+Node* Parse::optimize_cmp_with_klass(Node* c) {
+ // If this is transformed by the _gvn to a comparison with the low
+ // level klass then we may be able to use speculation
+ if (c->Opcode() == Op_CmpP &&
+ (c->in(1)->Opcode() == Op_LoadKlass || c->in(1)->Opcode() == Op_DecodeNKlass) &&
+ c->in(2)->is_Con()) {
+ Node* load_klass = NULL;
+ Node* decode = NULL;
+ if (c->in(1)->Opcode() == Op_DecodeNKlass) {
+ decode = c->in(1);
+ load_klass = c->in(1)->in(1);
+ } else {
+ load_klass = c->in(1);
+ }
+ if (load_klass->in(2)->is_AddP()) {
+ Node* addp = load_klass->in(2);
+ Node* obj = addp->in(AddPNode::Address);
+ const TypeOopPtr* obj_type = _gvn.type(obj)->is_oopptr();
+ if (obj_type->speculative_type() != NULL) {
+ ciKlass* k = obj_type->speculative_type();
+ inc_sp(2);
+ obj = maybe_cast_profiled_obj(obj, k);
+ dec_sp(2);
+ // Make the CmpP use the casted obj
+ addp = basic_plus_adr(obj, addp->in(AddPNode::Offset));
+ load_klass = load_klass->clone();
+ load_klass->set_req(2, addp);
+ load_klass = _gvn.transform(load_klass);
+ if (decode != NULL) {
+ decode = decode->clone();
+ decode->set_req(1, load_klass);
+ load_klass = _gvn.transform(decode);
+ }
+ c = c->clone();
+ c->set_req(1, load_klass);
+ c = _gvn.transform(c);
+ }
+ }
+ }
+ return c;
+}
//------------------------------do_one_bytecode--------------------------------
// Parse this bytecode, and alter the Parsers JVM->Node mapping
@@ -2239,6 +2289,7 @@
a = pop();
b = pop();
c = _gvn.transform( new (C) CmpPNode(b, a) );
+ c = optimize_cmp_with_klass(c);
do_if(btest, c);
break;
--- a/hotspot/src/share/vm/opto/parseHelper.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/parseHelper.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -128,7 +128,7 @@
}
// Push the bool result back on stack
- Node* res = gen_instanceof(peek(), makecon(TypeKlassPtr::make(klass)));
+ Node* res = gen_instanceof(peek(), makecon(TypeKlassPtr::make(klass)), true);
// Pop from stack AFTER gen_instanceof because it can uncommon trap.
pop();
--- a/hotspot/src/share/vm/opto/phaseX.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -1385,6 +1385,20 @@
}
}
+/**
+ * Remove the speculative part of all types that we know of
+ */
+void PhaseIterGVN::remove_speculative_types() {
+ assert(UseTypeSpeculation, "speculation is off");
+ for (uint i = 0; i < _types.Size(); i++) {
+ const Type* t = _types.fast_lookup(i);
+ if (t != NULL && t->isa_oopptr()) {
+ const TypeOopPtr* to = t->is_oopptr();
+ _types.map(i, to->remove_speculative());
+ }
+ }
+}
+
//=============================================================================
#ifndef PRODUCT
uint PhaseCCP::_total_invokes = 0;
--- a/hotspot/src/share/vm/opto/phaseX.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -500,6 +500,8 @@
ProjNode* create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry,
Deoptimization::DeoptReason reason);
+ void remove_speculative_types();
+
#ifndef PRODUCT
protected:
// Sub-quadratic implementation of VerifyIterativeGVN.
--- a/hotspot/src/share/vm/opto/reg_split.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/reg_split.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -51,15 +51,6 @@
static const char out_of_nodes[] = "out of nodes during split";
-static bool contains_no_live_range_input(const Node* def) {
- for (uint i = 1; i < def->req(); ++i) {
- if (def->in(i) != NULL && def->in_RegMask(i).is_NotEmpty()) {
- return false;
- }
- }
- return true;
-}
-
//------------------------------get_spillcopy_wide-----------------------------
// Get a SpillCopy node with wide-enough masks. Use the 'wide-mask', the
// wide ideal-register spill-mask if possible. If the 'wide-mask' does
@@ -326,12 +317,11 @@
if( def->req() > 1 ) {
for( uint i = 1; i < def->req(); i++ ) {
Node *in = def->in(i);
- // Check for single-def (LRG cannot redefined)
uint lidx = _lrg_map.live_range_id(in);
- if (lidx >= _lrg_map.max_lrg_id()) {
- continue; // Value is a recent spill-copy
- }
- if (lrgs(lidx).is_singledef()) {
+ // We do not need this for live ranges that are only defined once.
+ // However, this is not true for spill copies that are added in this
+ // Split() pass, since they might get coalesced later on in this pass.
+ if (lidx < _lrg_map.max_lrg_id() && lrgs(lidx).is_singledef()) {
continue;
}
@@ -375,7 +365,6 @@
}
if (lidx < _lrg_map.max_lrg_id() && lrgs(lidx).reg() >= LRG::SPILL_REG) {
- assert(Reachblock != NULL, "Reachblock must be non-NULL");
Node *rdef = Reachblock[lrg2reach[lidx]];
if (rdef) {
spill->set_req(i, rdef);
@@ -486,7 +475,6 @@
uint bidx, pidx, slidx, insidx, inpidx, twoidx;
uint non_phi = 1, spill_cnt = 0;
- Node **Reachblock;
Node *n1, *n2, *n3;
Node_List *defs,*phis;
bool *UPblock;
@@ -569,7 +557,7 @@
b = _cfg.get_block(bidx);
// Reaches & UP arrays for this block
- Reachblock = Reaches[b->_pre_order];
+ Node** Reachblock = Reaches[b->_pre_order];
UPblock = UP[b->_pre_order];
// Reset counter of start of non-Phi nodes in block
non_phi = 1;
@@ -1325,9 +1313,10 @@
pidx = pred->_pre_order;
// Grab reaching def
Node *def = Reaches[pidx][slidx];
+ Node** Reachblock = Reaches[pidx];
assert( def, "must have reaching def" );
// If input up/down sense and reg-pressure DISagree
- if (def->rematerialize() && contains_no_live_range_input(def)) {
+ if (def->rematerialize()) {
// Place the rematerialized node above any MSCs created during
// phi node splitting. end_idx points at the insertion point
// so look at the node before it.
@@ -1337,8 +1326,7 @@
_lrg_map.find(pred->get_node(insert - 1)) >= lrgs_before_phi_split) {
insert--;
}
- // since the def cannot contain any live range input, we can pass in NULL as Reachlock parameter
- def = split_Rematerialize(def, pred, insert, maxlrg, splits, slidx, lrg2reach, NULL, false);
+ def = split_Rematerialize(def, pred, insert, maxlrg, splits, slidx, lrg2reach, Reachblock, false);
if (!def) {
return 0; // Bail out
}
--- a/hotspot/src/share/vm/opto/type.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/type.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -358,7 +358,7 @@
false, 0, oopDesc::mark_offset_in_bytes());
TypeInstPtr::KLASS = TypeInstPtr::make(TypePtr::BotPTR, current->env()->Object_klass(),
false, 0, oopDesc::klass_offset_in_bytes());
- TypeOopPtr::BOTTOM = TypeOopPtr::make(TypePtr::BotPTR, OffsetBot, TypeOopPtr::InstanceBot);
+ TypeOopPtr::BOTTOM = TypeOopPtr::make(TypePtr::BotPTR, OffsetBot, TypeOopPtr::InstanceBot, NULL);
TypeMetadataPtr::BOTTOM = TypeMetadataPtr::make(TypePtr::BotPTR, NULL, OffsetBot);
@@ -435,6 +435,11 @@
intccpair[1] = TypeInt::CC;
TypeTuple::INT_CC_PAIR = TypeTuple::make(2, intccpair);
+ const Type **longccpair = TypeTuple::fields(2);
+ longccpair[0] = TypeLong::LONG;
+ longccpair[1] = TypeInt::CC;
+ TypeTuple::LONG_CC_PAIR = TypeTuple::make(2, longccpair);
+
_const_basic_type[T_NARROWOOP] = TypeNarrowOop::BOTTOM;
_const_basic_type[T_NARROWKLASS] = Type::BOTTOM;
_const_basic_type[T_BOOLEAN] = TypeInt::BOOL;
@@ -577,7 +582,7 @@
//----------------------interface_vs_oop---------------------------------------
#ifdef ASSERT
-bool Type::interface_vs_oop(const Type *t) const {
+bool Type::interface_vs_oop_helper(const Type *t) const {
bool result = false;
const TypePtr* this_ptr = this->make_ptr(); // In case it is narrow_oop
@@ -595,6 +600,29 @@
return result;
}
+
+bool Type::interface_vs_oop(const Type *t) const {
+ if (interface_vs_oop_helper(t)) {
+ return true;
+ }
+ // Now check the speculative parts as well
+ const TypeOopPtr* this_spec = isa_oopptr() != NULL ? isa_oopptr()->speculative() : NULL;
+ const TypeOopPtr* t_spec = t->isa_oopptr() != NULL ? t->isa_oopptr()->speculative() : NULL;
+ if (this_spec != NULL && t_spec != NULL) {
+ if (this_spec->interface_vs_oop_helper(t_spec)) {
+ return true;
+ }
+ return false;
+ }
+ if (this_spec != NULL && this_spec->interface_vs_oop_helper(t)) {
+ return true;
+ }
+ if (t_spec != NULL && interface_vs_oop_helper(t_spec)) {
+ return true;
+ }
+ return false;
+}
+
#endif
//------------------------------meet-------------------------------------------
@@ -1652,6 +1680,7 @@
const TypeTuple *TypeTuple::INT_PAIR;
const TypeTuple *TypeTuple::LONG_PAIR;
const TypeTuple *TypeTuple::INT_CC_PAIR;
+const TypeTuple *TypeTuple::LONG_CC_PAIR;
//------------------------------make-------------------------------------------
@@ -2407,14 +2436,15 @@
const TypeOopPtr *TypeOopPtr::BOTTOM;
//------------------------------TypeOopPtr-------------------------------------
-TypeOopPtr::TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id )
+TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative)
: TypePtr(t, ptr, offset),
_const_oop(o), _klass(k),
_klass_is_exact(xk),
_is_ptr_to_narrowoop(false),
_is_ptr_to_narrowklass(false),
_is_ptr_to_boxed_value(false),
- _instance_id(instance_id) {
+ _instance_id(instance_id),
+ _speculative(speculative) {
if (Compile::current()->eliminate_boxing() && (t == InstPtr) &&
(offset > 0) && xk && (k != 0) && k->is_instance_klass()) {
_is_ptr_to_boxed_value = k->as_instance_klass()->is_boxed_value_offset(offset);
@@ -2481,12 +2511,12 @@
//------------------------------make-------------------------------------------
const TypeOopPtr *TypeOopPtr::make(PTR ptr,
- int offset, int instance_id) {
+ int offset, int instance_id, const TypeOopPtr* speculative) {
assert(ptr != Constant, "no constant generic pointers");
ciKlass* k = Compile::current()->env()->Object_klass();
bool xk = false;
ciObject* o = NULL;
- return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id))->hashcons();
+ return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id, speculative))->hashcons();
}
@@ -2494,7 +2524,7 @@
const Type *TypeOopPtr::cast_to_ptr_type(PTR ptr) const {
assert(_base == OopPtr, "subclass must override cast_to_ptr_type");
if( ptr == _ptr ) return this;
- return make(ptr, _offset, _instance_id);
+ return make(ptr, _offset, _instance_id, _speculative);
}
//-----------------------------cast_to_instance_id----------------------------
@@ -2524,10 +2554,31 @@
return TypeKlassPtr::make(xk? Constant: NotNull, k, 0);
}
+const Type *TypeOopPtr::xmeet(const Type *t) const {
+ const Type* res = xmeet_helper(t);
+ if (res->isa_oopptr() == NULL) {
+ return res;
+ }
+
+ if (res->isa_oopptr() != NULL) {
+ // type->speculative() == NULL means that speculation is no better
+ // than type, i.e. type->speculative() == type. So there are 2
+ // ways to represent the fact that we have no useful speculative
+ // data and we should use a single one to be able to test for
+ // equality between types. Check whether type->speculative() ==
+ // type and set speculative to NULL if it is the case.
+ const TypeOopPtr* res_oopptr = res->is_oopptr();
+ if (res_oopptr->remove_speculative() == res_oopptr->speculative()) {
+ return res_oopptr->remove_speculative();
+ }
+ }
+
+ return res;
+}
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
-const Type *TypeOopPtr::xmeet( const Type *t ) const {
+const Type *TypeOopPtr::xmeet_helper(const Type *t) const {
// Perform a fast test for common case; meeting the same types together.
if( this == t ) return this; // Meeting same type-rep?
@@ -2569,7 +2620,8 @@
case TopPTR:
case AnyNull: {
int instance_id = meet_instance_id(InstanceTop);
- return make(ptr, offset, instance_id);
+ const TypeOopPtr* speculative = _speculative;
+ return make(ptr, offset, instance_id, speculative);
}
case BotPTR:
case NotNull:
@@ -2581,7 +2633,8 @@
case OopPtr: { // Meeting to other OopPtrs
const TypeOopPtr *tp = t->is_oopptr();
int instance_id = meet_instance_id(tp->instance_id());
- return make( meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id );
+ const TypeOopPtr* speculative = meet_speculative(tp);
+ return make(meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id, speculative);
}
case InstPtr: // For these, flip the call around to cut down
@@ -2598,7 +2651,7 @@
const Type *TypeOopPtr::xdual() const {
assert(klass() == Compile::current()->env()->Object_klass(), "no klasses here");
assert(const_oop() == NULL, "no constants here");
- return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id() );
+ return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative());
}
//--------------------------make_from_klass_common-----------------------------
@@ -2689,7 +2742,7 @@
} else if (!o->should_be_constant()) {
return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0);
}
- const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0, InstanceBot, is_autobox_cache);
+ const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0, InstanceBot, NULL, is_autobox_cache);
return arr;
} else if (klass->is_type_array_klass()) {
// Element is an typeArray
@@ -2789,7 +2842,8 @@
bool TypeOopPtr::eq( const Type *t ) const {
const TypeOopPtr *a = (const TypeOopPtr*)t;
if (_klass_is_exact != a->_klass_is_exact ||
- _instance_id != a->_instance_id) return false;
+ _instance_id != a->_instance_id ||
+ !eq_speculative(a)) return false;
ciObject* one = const_oop();
ciObject* two = a->const_oop();
if (one == NULL || two == NULL) {
@@ -2806,6 +2860,7 @@
(const_oop() ? const_oop()->hash() : 0) +
_klass_is_exact +
_instance_id +
+ hash_speculative() +
TypePtr::hash();
}
@@ -2825,6 +2880,19 @@
st->print(",iid=top");
else if (_instance_id != InstanceBot)
st->print(",iid=%d",_instance_id);
+
+ dump_speculative(st);
+}
+
+/**
+ *dump the speculative part of the type
+ */
+void TypeOopPtr::dump_speculative(outputStream *st) const {
+ if (_speculative != NULL) {
+ st->print(" (speculative=");
+ _speculative->dump_on(st);
+ st->print(")");
+ }
}
#endif
@@ -2838,8 +2906,15 @@
}
//------------------------------add_offset-------------------------------------
-const TypePtr *TypeOopPtr::add_offset( intptr_t offset ) const {
- return make( _ptr, xadd_offset(offset), _instance_id);
+const TypePtr *TypeOopPtr::add_offset(intptr_t offset) const {
+ return make(_ptr, xadd_offset(offset), _instance_id, add_offset_speculative(offset));
+}
+
+/**
+ * Return same type without a speculative part
+ */
+const TypeOopPtr* TypeOopPtr::remove_speculative() const {
+ return make(_ptr, _offset, _instance_id, NULL);
}
//------------------------------meet_instance_id--------------------------------
@@ -2859,6 +2934,89 @@
return _instance_id; // Map everything else into self
}
+/**
+ * meet of the speculative parts of 2 types
+ *
+ * @param other type to meet with
+ */
+const TypeOopPtr* TypeOopPtr::meet_speculative(const TypeOopPtr* other) const {
+ bool this_has_spec = (_speculative != NULL);
+ bool other_has_spec = (other->speculative() != NULL);
+
+ if (!this_has_spec && !other_has_spec) {
+ return NULL;
+ }
+
+ // If we are at a point where control flow meets and one branch has
+ // a speculative type and the other has not, we meet the speculative
+ // type of one branch with the actual type of the other. If the
+ // actual type is exact and the speculative is as well, then the
+ // result is a speculative type which is exact and we can continue
+ // speculation further.
+ const TypeOopPtr* this_spec = _speculative;
+ const TypeOopPtr* other_spec = other->speculative();
+
+ if (!this_has_spec) {
+ this_spec = this;
+ }
+
+ if (!other_has_spec) {
+ other_spec = other;
+ }
+
+ return this_spec->meet(other_spec)->is_oopptr();
+}
+
+/**
+ * dual of the speculative part of the type
+ */
+const TypeOopPtr* TypeOopPtr::dual_speculative() const {
+ if (_speculative == NULL) {
+ return NULL;
+ }
+ return _speculative->dual()->is_oopptr();
+}
+
+/**
+ * add offset to the speculative part of the type
+ *
+ * @param offset offset to add
+ */
+const TypeOopPtr* TypeOopPtr::add_offset_speculative(intptr_t offset) const {
+ if (_speculative == NULL) {
+ return NULL;
+ }
+ return _speculative->add_offset(offset)->is_oopptr();
+}
+
+/**
+ * Are the speculative parts of 2 types equal?
+ *
+ * @param other type to compare this one to
+ */
+bool TypeOopPtr::eq_speculative(const TypeOopPtr* other) const {
+ if (_speculative == NULL || other->speculative() == NULL) {
+ return _speculative == other->speculative();
+ }
+
+ if (_speculative->base() != other->speculative()->base()) {
+ return false;
+ }
+
+ return _speculative->eq(other->speculative());
+}
+
+/**
+ * Hash of the speculative part of the type
+ */
+int TypeOopPtr::hash_speculative() const {
+ if (_speculative == NULL) {
+ return 0;
+ }
+
+ return _speculative->hash();
+}
+
//=============================================================================
// Convenience common pre-built types.
@@ -2869,8 +3027,8 @@
const TypeInstPtr *TypeInstPtr::KLASS;
//------------------------------TypeInstPtr-------------------------------------
-TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, int instance_id)
- : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id), _name(k->name()) {
+TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, int instance_id, const TypeOopPtr* speculative)
+ : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative), _name(k->name()) {
assert(k != NULL &&
(k->is_loaded() || o == NULL),
"cannot have constants with non-loaded klass");
@@ -2882,7 +3040,8 @@
bool xk,
ciObject* o,
int offset,
- int instance_id) {
+ int instance_id,
+ const TypeOopPtr* speculative) {
assert( !k->is_loaded() || k->is_instance_klass(), "Must be for instance");
// Either const_oop() is NULL or else ptr is Constant
assert( (!o && ptr != Constant) || (o && ptr == Constant),
@@ -2903,7 +3062,7 @@
// Now hash this baby
TypeInstPtr *result =
- (TypeInstPtr*)(new TypeInstPtr(ptr, k, xk, o ,offset, instance_id))->hashcons();
+ (TypeInstPtr*)(new TypeInstPtr(ptr, k, xk, o ,offset, instance_id, speculative))->hashcons();
return result;
}
@@ -2936,7 +3095,7 @@
if( ptr == _ptr ) return this;
// Reconstruct _sig info here since not a problem with later lazy
// construction, _sig will show up on demand.
- return make(ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id);
+ return make(ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative);
}
@@ -2948,13 +3107,13 @@
ciInstanceKlass* ik = _klass->as_instance_klass();
if( (ik->is_final() || _const_oop) ) return this; // cannot clear xk
if( ik->is_interface() ) return this; // cannot set xk
- return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _instance_id);
+ return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _instance_id, _speculative);
}
//-----------------------------cast_to_instance_id----------------------------
const TypeOopPtr *TypeInstPtr::cast_to_instance_id(int instance_id) const {
if( instance_id == _instance_id ) return this;
- return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id);
+ return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id, _speculative);
}
//------------------------------xmeet_unloaded---------------------------------
@@ -2964,6 +3123,7 @@
int off = meet_offset(tinst->offset());
PTR ptr = meet_ptr(tinst->ptr());
int instance_id = meet_instance_id(tinst->instance_id());
+ const TypeOopPtr* speculative = meet_speculative(tinst);
const TypeInstPtr *loaded = is_loaded() ? this : tinst;
const TypeInstPtr *unloaded = is_loaded() ? tinst : this;
@@ -2984,7 +3144,7 @@
assert(loaded->ptr() != TypePtr::Null, "insanity check");
//
if( loaded->ptr() == TypePtr::TopPTR ) { return unloaded; }
- else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make( ptr, unloaded->klass(), false, NULL, off, instance_id ); }
+ else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make(ptr, unloaded->klass(), false, NULL, off, instance_id, speculative); }
else if (loaded->ptr() == TypePtr::BotPTR ) { return TypeInstPtr::BOTTOM; }
else if (loaded->ptr() == TypePtr::Constant || loaded->ptr() == TypePtr::NotNull) {
if (unloaded->ptr() == TypePtr::BotPTR ) { return TypeInstPtr::BOTTOM; }
@@ -3006,7 +3166,7 @@
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
-const Type *TypeInstPtr::xmeet( const Type *t ) const {
+const Type *TypeInstPtr::xmeet_helper(const Type *t) const {
// Perform a fast test for common case; meeting the same types together.
if( this == t ) return this; // Meeting same type-rep?
@@ -3040,16 +3200,20 @@
int offset = meet_offset(tp->offset());
PTR ptr = meet_ptr(tp->ptr());
int instance_id = meet_instance_id(tp->instance_id());
+ const TypeOopPtr* speculative = meet_speculative(tp);
switch (ptr) {
case TopPTR:
case AnyNull: // Fall 'down' to dual of object klass
- if (klass()->equals(ciEnv::current()->Object_klass())) {
- return TypeAryPtr::make(ptr, tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id);
+ // For instances when a subclass meets a superclass we fall
+ // below the centerline when the superclass is exact. We need to
+ // do the same here.
+ if (klass()->equals(ciEnv::current()->Object_klass()) && !klass_is_exact()) {
+ return TypeAryPtr::make(ptr, tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative);
} else {
// cannot subclass, so the meet has to fall badly below the centerline
ptr = NotNull;
instance_id = InstanceBot;
- return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id);
+ return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative);
}
case Constant:
case NotNull:
@@ -3058,10 +3222,13 @@
if( above_centerline(_ptr) ) { // if( _ptr == TopPTR || _ptr == AnyNull )
// If 'this' (InstPtr) is above the centerline and it is Object class
// then we can subclass in the Java class hierarchy.
- if (klass()->equals(ciEnv::current()->Object_klass())) {
+ // For instances when a subclass meets a superclass we fall
+ // below the centerline when the superclass is exact. We need
+ // to do the same here.
+ if (klass()->equals(ciEnv::current()->Object_klass()) && !klass_is_exact()) {
// that is, tp's array type is a subtype of my klass
return TypeAryPtr::make(ptr, (ptr == Constant ? tp->const_oop() : NULL),
- tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id);
+ tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative);
}
}
// The other case cannot happen, since I cannot be a subtype of an array.
@@ -3069,7 +3236,7 @@
if( ptr == Constant )
ptr = NotNull;
instance_id = InstanceBot;
- return make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id );
+ return make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative);
default: typerr(t);
}
}
@@ -3083,13 +3250,15 @@
case TopPTR:
case AnyNull: {
int instance_id = meet_instance_id(InstanceTop);
+ const TypeOopPtr* speculative = meet_speculative(tp);
return make(ptr, klass(), klass_is_exact(),
- (ptr == Constant ? const_oop() : NULL), offset, instance_id);
+ (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative);
}
case NotNull:
case BotPTR: {
int instance_id = meet_instance_id(tp->instance_id());
- return TypeOopPtr::make(ptr, offset, instance_id);
+ const TypeOopPtr* speculative = meet_speculative(tp);
+ return TypeOopPtr::make(ptr, offset, instance_id, speculative);
}
default: typerr(t);
}
@@ -3102,17 +3271,18 @@
PTR ptr = meet_ptr(tp->ptr());
switch (tp->ptr()) {
case Null:
- if( ptr == Null ) return TypePtr::make( AnyPtr, ptr, offset );
+ if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset);
// else fall through to AnyNull
case TopPTR:
case AnyNull: {
int instance_id = meet_instance_id(InstanceTop);
- return make( ptr, klass(), klass_is_exact(),
- (ptr == Constant ? const_oop() : NULL), offset, instance_id);
+ const TypeOopPtr* speculative = _speculative;
+ return make(ptr, klass(), klass_is_exact(),
+ (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative);
}
case NotNull:
case BotPTR:
- return TypePtr::make( AnyPtr, ptr, offset );
+ return TypePtr::make(AnyPtr, ptr, offset);
default: typerr(t);
}
}
@@ -3139,13 +3309,14 @@
int off = meet_offset( tinst->offset() );
PTR ptr = meet_ptr( tinst->ptr() );
int instance_id = meet_instance_id(tinst->instance_id());
+ const TypeOopPtr* speculative = meet_speculative(tinst);
// Check for easy case; klasses are equal (and perhaps not loaded!)
// If we have constants, then we created oops so classes are loaded
// and we can handle the constants further down. This case handles
// both-not-loaded or both-loaded classes
if (ptr != Constant && klass()->equals(tinst->klass()) && klass_is_exact() == tinst->klass_is_exact()) {
- return make( ptr, klass(), klass_is_exact(), NULL, off, instance_id );
+ return make(ptr, klass(), klass_is_exact(), NULL, off, instance_id, speculative);
}
// Classes require inspection in the Java klass hierarchy. Must be loaded.
@@ -3167,7 +3338,8 @@
}
// Handle mixing oops and interfaces first.
- if( this_klass->is_interface() && !tinst_klass->is_interface() ) {
+ if( this_klass->is_interface() && !(tinst_klass->is_interface() ||
+ tinst_klass == ciEnv::current()->Object_klass())) {
ciKlass *tmp = tinst_klass; // Swap interface around
tinst_klass = this_klass;
this_klass = tmp;
@@ -3208,7 +3380,7 @@
// Find out which constant.
o = (this_klass == klass()) ? const_oop() : tinst->const_oop();
}
- return make( ptr, k, xk, o, off, instance_id );
+ return make(ptr, k, xk, o, off, instance_id, speculative);
}
// Either oop vs oop or interface vs interface or interface vs Object
@@ -3285,7 +3457,7 @@
else
ptr = NotNull;
}
- return make( ptr, this_klass, this_xk, o, off, instance_id );
+ return make(ptr, this_klass, this_xk, o, off, instance_id, speculative);
} // Else classes are not equal
// Since klasses are different, we require a LCA in the Java
@@ -3296,7 +3468,7 @@
// Now we find the LCA of Java classes
ciKlass* k = this_klass->least_common_ancestor(tinst_klass);
- return make( ptr, k, false, NULL, off, instance_id );
+ return make(ptr, k, false, NULL, off, instance_id, speculative);
} // End of case InstPtr
} // End of switch
@@ -3320,7 +3492,7 @@
// Dual: do NOT dual on klasses. This means I do NOT understand the Java
// inheritance mechanism.
const Type *TypeInstPtr::xdual() const {
- return new TypeInstPtr( dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id() );
+ return new TypeInstPtr(dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative());
}
//------------------------------eq---------------------------------------------
@@ -3376,12 +3548,18 @@
st->print(",iid=top");
else if (_instance_id != InstanceBot)
st->print(",iid=%d",_instance_id);
+
+ dump_speculative(st);
}
#endif
//------------------------------add_offset-------------------------------------
-const TypePtr *TypeInstPtr::add_offset( intptr_t offset ) const {
- return make( _ptr, klass(), klass_is_exact(), const_oop(), xadd_offset(offset), _instance_id );
+const TypePtr *TypeInstPtr::add_offset(intptr_t offset) const {
+ return make(_ptr, klass(), klass_is_exact(), const_oop(), xadd_offset(offset), _instance_id, add_offset_speculative(offset));
+}
+
+const TypeOopPtr *TypeInstPtr::remove_speculative() const {
+ return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, NULL);
}
//=============================================================================
@@ -3398,30 +3576,30 @@
const TypeAryPtr *TypeAryPtr::DOUBLES;
//------------------------------make-------------------------------------------
-const TypeAryPtr *TypeAryPtr::make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id ) {
+const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative) {
assert(!(k == NULL && ary->_elem->isa_int()),
"integral arrays must be pre-equipped with a class");
if (!xk) xk = ary->ary_must_be_exact();
assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed");
if (!UseExactTypes) xk = (ptr == Constant);
- return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id, false))->hashcons();
+ return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id, false, speculative))->hashcons();
}
//------------------------------make-------------------------------------------
-const TypeAryPtr *TypeAryPtr::make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, bool is_autobox_cache) {
+const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, bool is_autobox_cache) {
assert(!(k == NULL && ary->_elem->isa_int()),
"integral arrays must be pre-equipped with a class");
assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" );
if (!xk) xk = (o != NULL) || ary->ary_must_be_exact();
assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed");
if (!UseExactTypes) xk = (ptr == Constant);
- return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id, is_autobox_cache))->hashcons();
+ return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id, is_autobox_cache, speculative))->hashcons();
}
//------------------------------cast_to_ptr_type-------------------------------
const Type *TypeAryPtr::cast_to_ptr_type(PTR ptr) const {
if( ptr == _ptr ) return this;
- return make(ptr, const_oop(), _ary, klass(), klass_is_exact(), _offset, _instance_id);
+ return make(ptr, const_oop(), _ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative);
}
@@ -3430,13 +3608,13 @@
if( klass_is_exact == _klass_is_exact ) return this;
if (!UseExactTypes) return this;
if (_ary->ary_must_be_exact()) return this; // cannot clear xk
- return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id);
+ return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id, _speculative);
}
//-----------------------------cast_to_instance_id----------------------------
const TypeOopPtr *TypeAryPtr::cast_to_instance_id(int instance_id) const {
if( instance_id == _instance_id ) return this;
- return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id);
+ return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id, _speculative);
}
//-----------------------------narrow_size_type-------------------------------
@@ -3499,7 +3677,7 @@
new_size = narrow_size_type(new_size);
if (new_size == size()) return this;
const TypeAry* new_ary = TypeAry::make(elem(), new_size, is_stable());
- return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id);
+ return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative);
}
@@ -3548,7 +3726,7 @@
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. It returns a new Type object.
-const Type *TypeAryPtr::xmeet( const Type *t ) const {
+const Type *TypeAryPtr::xmeet_helper(const Type *t) const {
// Perform a fast test for common case; meeting the same types together.
if( this == t ) return this; // Meeting same type-rep?
// Current "this->_base" is Pointer
@@ -3582,13 +3760,15 @@
case TopPTR:
case AnyNull: {
int instance_id = meet_instance_id(InstanceTop);
+ const TypeOopPtr* speculative = meet_speculative(tp);
return make(ptr, (ptr == Constant ? const_oop() : NULL),
- _ary, _klass, _klass_is_exact, offset, instance_id);
+ _ary, _klass, _klass_is_exact, offset, instance_id, speculative);
}
case BotPTR:
case NotNull: {
int instance_id = meet_instance_id(tp->instance_id());
- return TypeOopPtr::make(ptr, offset, instance_id);
+ const TypeOopPtr* speculative = meet_speculative(tp);
+ return TypeOopPtr::make(ptr, offset, instance_id, speculative);
}
default: ShouldNotReachHere();
}
@@ -3610,8 +3790,9 @@
// else fall through to AnyNull
case AnyNull: {
int instance_id = meet_instance_id(InstanceTop);
- return make( ptr, (ptr == Constant ? const_oop() : NULL),
- _ary, _klass, _klass_is_exact, offset, instance_id);
+ const TypeOopPtr* speculative = _speculative;
+ return make(ptr, (ptr == Constant ? const_oop() : NULL),
+ _ary, _klass, _klass_is_exact, offset, instance_id, speculative);
}
default: ShouldNotReachHere();
}
@@ -3627,6 +3808,7 @@
const TypeAry *tary = _ary->meet(tap->_ary)->is_ary();
PTR ptr = meet_ptr(tap->ptr());
int instance_id = meet_instance_id(tap->instance_id());
+ const TypeOopPtr* speculative = meet_speculative(tap);
ciKlass* lazy_klass = NULL;
if (tary->_elem->isa_int()) {
// Integral array element types have irrelevant lattice relations.
@@ -3654,7 +3836,7 @@
// 'this' is exact and super or unrelated:
(this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) {
tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable);
- return make( NotNull, NULL, tary, lazy_klass, false, off, InstanceBot );
+ return make(NotNull, NULL, tary, lazy_klass, false, off, InstanceBot);
}
bool xk = false;
@@ -3662,8 +3844,12 @@
case AnyNull:
case TopPTR:
// Compute new klass on demand, do not use tap->_klass
- xk = (tap->_klass_is_exact | this->_klass_is_exact);
- return make( ptr, const_oop(), tary, lazy_klass, xk, off, instance_id );
+ if (below_centerline(this->_ptr)) {
+ xk = this->_klass_is_exact;
+ } else {
+ xk = (tap->_klass_is_exact | this->_klass_is_exact);
+ }
+ return make(ptr, const_oop(), tary, lazy_klass, xk, off, instance_id, speculative);
case Constant: {
ciObject* o = const_oop();
if( _ptr == Constant ) {
@@ -3675,25 +3861,23 @@
} else {
xk = true;
}
- } else if( above_centerline(_ptr) ) {
+ } else if(above_centerline(_ptr)) {
o = tap->const_oop();
xk = true;
} else {
// Only precise for identical arrays
xk = this->_klass_is_exact && (klass() == tap->klass());
}
- return TypeAryPtr::make( ptr, o, tary, lazy_klass, xk, off, instance_id );
+ return TypeAryPtr::make(ptr, o, tary, lazy_klass, xk, off, instance_id, speculative);
}
case NotNull:
case BotPTR:
// Compute new klass on demand, do not use tap->_klass
if (above_centerline(this->_ptr))
xk = tap->_klass_is_exact;
- else if (above_centerline(tap->_ptr))
- xk = this->_klass_is_exact;
else xk = (tap->_klass_is_exact & this->_klass_is_exact) &&
(klass() == tap->klass()); // Only precise for identical arrays
- return TypeAryPtr::make( ptr, NULL, tary, lazy_klass, xk, off, instance_id );
+ return TypeAryPtr::make(ptr, NULL, tary, lazy_klass, xk, off, instance_id, speculative);
default: ShouldNotReachHere();
}
}
@@ -3704,16 +3888,20 @@
int offset = meet_offset(tp->offset());
PTR ptr = meet_ptr(tp->ptr());
int instance_id = meet_instance_id(tp->instance_id());
+ const TypeOopPtr* speculative = meet_speculative(tp);
switch (ptr) {
case TopPTR:
case AnyNull: // Fall 'down' to dual of object klass
- if( tp->klass()->equals(ciEnv::current()->Object_klass()) ) {
- return TypeAryPtr::make( ptr, _ary, _klass, _klass_is_exact, offset, instance_id );
+ // For instances when a subclass meets a superclass we fall
+ // below the centerline when the superclass is exact. We need to
+ // do the same here.
+ if (tp->klass()->equals(ciEnv::current()->Object_klass()) && !tp->klass_is_exact()) {
+ return TypeAryPtr::make(ptr, _ary, _klass, _klass_is_exact, offset, instance_id, speculative);
} else {
// cannot subclass, so the meet has to fall badly below the centerline
ptr = NotNull;
instance_id = InstanceBot;
- return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id);
+ return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative);
}
case Constant:
case NotNull:
@@ -3722,10 +3910,13 @@
if (above_centerline(tp->ptr())) {
// If 'tp' is above the centerline and it is Object class
// then we can subclass in the Java class hierarchy.
- if( tp->klass()->equals(ciEnv::current()->Object_klass()) ) {
+ // For instances when a subclass meets a superclass we fall
+ // below the centerline when the superclass is exact. We need
+ // to do the same here.
+ if (tp->klass()->equals(ciEnv::current()->Object_klass()) && !tp->klass_is_exact()) {
// that is, my array type is a subtype of 'tp' klass
- return make( ptr, (ptr == Constant ? const_oop() : NULL),
- _ary, _klass, _klass_is_exact, offset, instance_id );
+ return make(ptr, (ptr == Constant ? const_oop() : NULL),
+ _ary, _klass, _klass_is_exact, offset, instance_id, speculative);
}
}
// The other case cannot happen, since t cannot be a subtype of an array.
@@ -3733,7 +3924,7 @@
if( ptr == Constant )
ptr = NotNull;
instance_id = InstanceBot;
- return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id);
+ return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative);
default: typerr(t);
}
}
@@ -3744,7 +3935,7 @@
//------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual
const Type *TypeAryPtr::xdual() const {
- return new TypeAryPtr( dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id(), is_autobox_cache() );
+ return new TypeAryPtr(dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id(), is_autobox_cache(), dual_speculative());
}
//----------------------interface_vs_oop---------------------------------------
@@ -3796,6 +3987,8 @@
st->print(",iid=top");
else if (_instance_id != InstanceBot)
st->print(",iid=%d",_instance_id);
+
+ dump_speculative(st);
}
#endif
@@ -3805,10 +3998,13 @@
}
//------------------------------add_offset-------------------------------------
-const TypePtr *TypeAryPtr::add_offset( intptr_t offset ) const {
- return make( _ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _instance_id );
-}
-
+const TypePtr *TypeAryPtr::add_offset(intptr_t offset) const {
+ return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _instance_id, add_offset_speculative(offset));
+}
+
+const TypeOopPtr *TypeAryPtr::remove_speculative() const {
+ return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, _offset, _instance_id, NULL);
+}
//=============================================================================
--- a/hotspot/src/share/vm/opto/type.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/opto/type.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -159,6 +159,11 @@
// Table for efficient dualing of base types
static const TYPES dual_type[lastype];
+#ifdef ASSERT
+ // One type is interface, the other is oop
+ virtual bool interface_vs_oop_helper(const Type *t) const;
+#endif
+
protected:
// Each class of type is also identified by its base.
const TYPES _base; // Enum of Types type
@@ -376,6 +381,9 @@
bool require_constant = false,
bool is_autobox_cache = false);
+ // Speculative type. See TypeInstPtr
+ virtual ciKlass* speculative_type() const { return NULL; }
+
private:
// support arrays
static const BasicType _basic_type[];
@@ -585,6 +593,7 @@
static const TypeTuple *INT_PAIR;
static const TypeTuple *LONG_PAIR;
static const TypeTuple *INT_CC_PAIR;
+ static const TypeTuple *LONG_CC_PAIR;
#ifndef PRODUCT
virtual void dump2( Dict &d, uint, outputStream *st ) const; // Specialized per-Type dumping
#endif
@@ -784,7 +793,7 @@
// Some kind of oop (Java pointer), either klass or instance or array.
class TypeOopPtr : public TypePtr {
protected:
- TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id );
+ TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative);
public:
virtual bool eq( const Type *t ) const;
virtual int hash() const; // Type specific hashing
@@ -810,11 +819,27 @@
// This is the the node index of the allocation node creating this instance.
int _instance_id;
+ // Extra type information profiling gave us. We propagate it the
+ // same way the rest of the type info is propagated. If we want to
+ // use it, then we have to emit a guard: this part of the type is
+ // not something we know but something we speculate about the type.
+ const TypeOopPtr* _speculative;
+
static const TypeOopPtr* make_from_klass_common(ciKlass* klass, bool klass_change, bool try_for_exact);
int dual_instance_id() const;
int meet_instance_id(int uid) const;
+ // utility methods to work on the speculative part of the type
+ const TypeOopPtr* dual_speculative() const;
+ const TypeOopPtr* meet_speculative(const TypeOopPtr* other) const;
+ bool eq_speculative(const TypeOopPtr* other) const;
+ int hash_speculative() const;
+ const TypeOopPtr* add_offset_speculative(intptr_t offset) const;
+#ifndef PRODUCT
+ void dump_speculative(outputStream *st) const;
+#endif
+
public:
// Creates a type given a klass. Correctly handles multi-dimensional arrays
// Respects UseUniqueSubclasses.
@@ -841,7 +866,7 @@
bool not_null_elements = false);
// Make a generic (unclassed) pointer to an oop.
- static const TypeOopPtr* make(PTR ptr, int offset, int instance_id);
+ static const TypeOopPtr* make(PTR ptr, int offset, int instance_id, const TypeOopPtr* speculative);
ciObject* const_oop() const { return _const_oop; }
virtual ciKlass* klass() const { return _klass; }
@@ -855,6 +880,7 @@
bool is_known_instance() const { return _instance_id > 0; }
int instance_id() const { return _instance_id; }
bool is_known_instance_field() const { return is_known_instance() && _offset >= 0; }
+ const TypeOopPtr* speculative() const { return _speculative; }
virtual intptr_t get_con() const;
@@ -868,9 +894,13 @@
const TypeKlassPtr* as_klass_type() const;
virtual const TypePtr *add_offset( intptr_t offset ) const;
+ // Return same type without a speculative part
+ virtual const TypeOopPtr* remove_speculative() const;
- virtual const Type *xmeet( const Type *t ) const;
+ virtual const Type *xmeet(const Type *t) const;
virtual const Type *xdual() const; // Compute dual right now.
+ // the core of the computation of the meet for TypeOopPtr and for its subclasses
+ virtual const Type *xmeet_helper(const Type *t) const;
// Do not allow interface-vs.-noninterface joins to collapse to top.
virtual const Type *filter( const Type *kills ) const;
@@ -880,13 +910,24 @@
#ifndef PRODUCT
virtual void dump2( Dict &d, uint depth, outputStream *st ) const;
#endif
+
+ // Return the speculative type if any
+ ciKlass* speculative_type() const {
+ if (_speculative != NULL) {
+ const TypeOopPtr* speculative = _speculative->join(this)->is_oopptr();
+ if (speculative->klass_is_exact()) {
+ return speculative->klass();
+ }
+ }
+ return NULL;
+ }
};
//------------------------------TypeInstPtr------------------------------------
// Class of Java object pointers, pointing either to non-array Java instances
// or to a Klass* (including array klasses).
class TypeInstPtr : public TypeOopPtr {
- TypeInstPtr( PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id );
+ TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative);
virtual bool eq( const Type *t ) const;
virtual int hash() const; // Type specific hashing
@@ -899,30 +940,30 @@
// Make a pointer to a constant oop.
static const TypeInstPtr *make(ciObject* o) {
- return make(TypePtr::Constant, o->klass(), true, o, 0);
+ return make(TypePtr::Constant, o->klass(), true, o, 0, InstanceBot);
}
// Make a pointer to a constant oop with offset.
static const TypeInstPtr *make(ciObject* o, int offset) {
- return make(TypePtr::Constant, o->klass(), true, o, offset);
+ return make(TypePtr::Constant, o->klass(), true, o, offset, InstanceBot);
}
// Make a pointer to some value of type klass.
static const TypeInstPtr *make(PTR ptr, ciKlass* klass) {
- return make(ptr, klass, false, NULL, 0);
+ return make(ptr, klass, false, NULL, 0, InstanceBot);
}
// Make a pointer to some non-polymorphic value of exactly type klass.
static const TypeInstPtr *make_exact(PTR ptr, ciKlass* klass) {
- return make(ptr, klass, true, NULL, 0);
+ return make(ptr, klass, true, NULL, 0, InstanceBot);
}
// Make a pointer to some value of type klass with offset.
static const TypeInstPtr *make(PTR ptr, ciKlass* klass, int offset) {
- return make(ptr, klass, false, NULL, offset);
+ return make(ptr, klass, false, NULL, offset, InstanceBot);
}
// Make a pointer to an oop.
- static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot );
+ static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL);
/** Create constant type for a constant boxed value */
const Type* get_const_boxed_value() const;
@@ -939,8 +980,11 @@
virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const;
virtual const TypePtr *add_offset( intptr_t offset ) const;
+ // Return same type without a speculative part
+ virtual const TypeOopPtr* remove_speculative() const;
- virtual const Type *xmeet( const Type *t ) const;
+ // the core of the computation of the meet of 2 types
+ virtual const Type *xmeet_helper(const Type *t) const;
virtual const TypeInstPtr *xmeet_unloaded( const TypeInstPtr *t ) const;
virtual const Type *xdual() const; // Compute dual right now.
@@ -959,8 +1003,8 @@
// Class of Java array pointers
class TypeAryPtr : public TypeOopPtr {
TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk,
- int offset, int instance_id, bool is_autobox_cache )
- : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id),
+ int offset, int instance_id, bool is_autobox_cache, const TypeOopPtr* speculative)
+ : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id, speculative),
_ary(ary),
_is_autobox_cache(is_autobox_cache)
{
@@ -998,9 +1042,9 @@
bool is_autobox_cache() const { return _is_autobox_cache; }
- static const TypeAryPtr *make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot);
+ static const TypeAryPtr *make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL);
// Constant pointer to array
- static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, bool is_autobox_cache = false);
+ static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, bool is_autobox_cache = false);
// Return a 'ptr' version of this type
virtual const Type *cast_to_ptr_type(PTR ptr) const;
@@ -1014,8 +1058,11 @@
virtual bool empty(void) const; // TRUE if type is vacuous
virtual const TypePtr *add_offset( intptr_t offset ) const;
+ // Return same type without a speculative part
+ virtual const TypeOopPtr* remove_speculative() const;
- virtual const Type *xmeet( const Type *t ) const;
+ // the core of the computation of the meet of 2 types
+ virtual const Type *xmeet_helper(const Type *t) const;
virtual const Type *xdual() const; // Compute dual right now.
const TypeAryPtr* cast_to_stable(bool stable, int stable_dimension = 1) const;
--- a/hotspot/src/share/vm/prims/jni.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/prims/jni.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -5060,6 +5060,7 @@
void TestVirtualSpace_test();
void TestMetaspaceAux_test();
void TestMetachunk_test();
+void TestVirtualSpaceNode_test();
#if INCLUDE_ALL_GCS
void TestG1BiasedArray_test();
#endif
@@ -5072,6 +5073,7 @@
run_unit_test(TestVirtualSpace_test());
run_unit_test(TestMetaspaceAux_test());
run_unit_test(TestMetachunk_test());
+ run_unit_test(TestVirtualSpaceNode_test());
run_unit_test(GlobalDefinitions::test_globals());
run_unit_test(GCTimerAllTest::all());
run_unit_test(arrayOopDesc::test_max_array_length());
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -259,8 +259,7 @@
// bytes to the InstanceKlass here because they have not been
// validated and we're not at a safepoint.
constantPoolHandle constants(current_thread, ikh->constants());
- oop cplock = constants->lock();
- ObjectLocker ol(cplock, current_thread, cplock != NULL); // lock constant pool while we query it
+ MonitorLockerEx ml(constants->lock()); // lock constant pool while we query it
JvmtiClassFileReconstituter reconstituter(ikh);
if (reconstituter.get_error() != JVMTI_ERROR_NONE) {
@@ -2418,8 +2417,7 @@
instanceKlassHandle ikh(thread, k_oop);
constantPoolHandle constants(thread, ikh->constants());
- oop cplock = constants->lock();
- ObjectLocker ol(cplock, thread, cplock != NULL); // lock constant pool while we query it
+ MonitorLockerEx ml(constants->lock()); // lock constant pool while we query it
JvmtiConstantPoolReconstituter reconstituter(ikh);
if (reconstituter.get_error() != JVMTI_ERROR_NONE) {
--- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -225,18 +225,20 @@
_method = NULL;
_bci = 0;
_class_loader = NULL;
-#ifdef CHECK_UNHANDLED_OOPS
- // This one is always allocated with new, but check it just in case.
- Thread *thread = Thread::current();
- if (thread->is_in_stack((address)&_method)) {
- thread->allow_unhandled_oop((oop*)&_method);
- }
-#endif // CHECK_UNHANDLED_OOPS
}
JvmtiBreakpoint::JvmtiBreakpoint(Method* m_method, jlocation location) {
_method = m_method;
_class_loader = _method->method_holder()->class_loader_data()->class_loader();
+#ifdef CHECK_UNHANDLED_OOPS
+ // _class_loader can't be wrapped in a Handle, because JvmtiBreakpoint:s are
+ // eventually allocated on the heap.
+ //
+ // The code handling JvmtiBreakpoint:s allocated on the stack can't be
+ // interrupted by a GC until _class_loader is reachable by the GC via the
+ // oops_do method.
+ Thread::current()->allow_unhandled_oop(&_class_loader);
+#endif // CHECK_UNHANDLED_OOPS
assert(_method != NULL, "_method != NULL");
_bci = (int) location;
assert(_bci >= 0, "_bci >= 0");
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -1194,9 +1194,7 @@
} else if (vmtarget->is_klass()) {
x = ((Klass*) vmtarget)->java_mirror();
} else if (vmtarget->is_method()) {
- Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL);
- CallInfo info((Method*)vmtarget);
- x = MethodHandles::init_method_MemberName(mname2, info);
+ x = mname();
}
result->obj_at_put(1, x);
return JNIHandles::make_local(env, result());
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -1957,12 +1957,6 @@
"please refer to the release notes for the combinations "
"allowed\n");
status = false;
- } else if (ReservedCodeCacheSize > 2*G) {
- // Code cache size larger than MAXINT is not supported.
- jio_fprintf(defaultStream::error_stream(),
- "Invalid ReservedCodeCacheSize=%dM. Must be at most %uM.\n", ReservedCodeCacheSize/M,
- (2*G)/M);
- status = false;
}
return status;
}
@@ -3721,6 +3715,18 @@
// incremental inlining: bump MaxNodeLimit
FLAG_SET_DEFAULT(MaxNodeLimit, (intx)75000);
}
+ if (!UseTypeSpeculation && FLAG_IS_DEFAULT(TypeProfileLevel)) {
+ // nothing to use the profiling, turn if off
+ FLAG_SET_DEFAULT(TypeProfileLevel, 0);
+ }
+ if (UseTypeSpeculation && FLAG_IS_DEFAULT(ReplaceInParentMaps)) {
+ // Doing the replace in parent maps helps speculation
+ FLAG_SET_DEFAULT(ReplaceInParentMaps, true);
+ }
+#ifndef X86
+ // Only on x86 for now
+ FLAG_SET_DEFAULT(TypeProfileLevel, 0);
+#endif
#endif
if (PrintAssembly && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -2671,13 +2671,18 @@
"Enable aggressive optimizations - see arguments.cpp") \
\
product_pd(uintx, TypeProfileLevel, \
- "=XY, with Y, Type profiling of arguments at call" \
- " X, Type profiling of return value at call" \
- "X and Y in 0->off ; 1->js292 only; 2->all methods") \
+ "=XYZ, with Z: Type profiling of arguments at call; " \
+ "Y: Type profiling of return value at call; " \
+ "X: Type profiling of parameters to methods; " \
+ "X, Y and Z in 0=off ; 1=jsr292 only; 2=all methods") \
\
product(intx, TypeProfileArgsLimit, 2, \
"max number of call arguments to consider for type profiling") \
\
+ product(intx, TypeProfileParmsLimit, 2, \
+ "max number of incoming parameters to consider for type profiling"\
+ ", -1 for all") \
+ \
/* statistics */ \
develop(bool, CountCompiledCalls, false, \
"Count method invocations") \
--- a/hotspot/src/share/vm/runtime/java.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/runtime/java.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -193,6 +193,11 @@
m->print_invocation_count();
tty->print_cr(" mdo size: %d bytes", m->method_data()->size_in_bytes());
tty->cr();
+ // Dump data on parameters if any
+ if (m->method_data() != NULL && m->method_data()->parameters_type_data() != NULL) {
+ tty->fill_to(2);
+ m->method_data()->parameters_type_data()->print_data_on(tty);
+ }
m->print_codes();
total_size += m->method_data()->size_in_bytes();
}
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -1464,6 +1464,7 @@
declare_toplevel_type(CheckedExceptionElement) \
declare_toplevel_type(LocalVariableTableElement) \
declare_toplevel_type(ExceptionTableElement) \
+ declare_toplevel_type(MethodParametersElement) \
\
declare_toplevel_type(ClassLoaderData) \
declare_toplevel_type(ClassLoaderDataGraph) \
@@ -1938,7 +1939,13 @@
declare_c2_type(CmpDNode, CmpNode) \
declare_c2_type(CmpD3Node, CmpDNode) \
declare_c2_type(MathExactNode, MultiNode) \
- declare_c2_type(AddExactINode, MathExactNode) \
+ declare_c2_type(MathExactINode, MathExactNode) \
+ declare_c2_type(AddExactINode, MathExactINode) \
+ declare_c2_type(AddExactLNode, MathExactLNode) \
+ declare_c2_type(SubExactINode, MathExactINode) \
+ declare_c2_type(SubExactLNode, MathExactLNode) \
+ declare_c2_type(NegExactINode, MathExactINode) \
+ declare_c2_type(MulExactINode, MathExactINode) \
declare_c2_type(FlagsProjNode, ProjNode) \
declare_c2_type(BoolNode, Node) \
declare_c2_type(AbsNode, Node) \
@@ -2336,6 +2343,7 @@
declare_constant(ConstMethod::_has_localvariable_table) \
declare_constant(ConstMethod::_has_exception_table) \
declare_constant(ConstMethod::_has_generic_signature) \
+ declare_constant(ConstMethod::_has_method_parameters) \
declare_constant(ConstMethod::_has_method_annotations) \
declare_constant(ConstMethod::_has_parameter_annotations) \
declare_constant(ConstMethod::_has_default_annotations) \
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Wed Jul 05 19:19:29 2017 +0200
@@ -505,7 +505,11 @@
_jdp_pause
("jdp.pause",
- "set com.sun.management.jdp.pause", "INT", false)
+ "set com.sun.management.jdp.pause", "INT", false),
+
+ _jdp_name
+ ("jdp.name",
+ "set com.sun.management.jdp.name", "STRING", false)
{
_dcmdparser.add_dcmd_option(&_config_file);
@@ -527,6 +531,7 @@
_dcmdparser.add_dcmd_option(&_jdp_source_addr);
_dcmdparser.add_dcmd_option(&_jdp_ttl);
_dcmdparser.add_dcmd_option(&_jdp_pause);
+ _dcmdparser.add_dcmd_option(&_jdp_name);
}
@@ -596,6 +601,7 @@
PUT_OPTION(_jdp_source_addr);
PUT_OPTION(_jdp_ttl);
PUT_OPTION(_jdp_pause);
+ PUT_OPTION(_jdp_name);
#undef PUT_OPTION
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp Wed Jul 05 19:19:29 2017 +0200
@@ -302,6 +302,7 @@
DCmdArgument<char *> _jdp_source_addr;
DCmdArgument<jlong> _jdp_ttl;
DCmdArgument<jlong> _jdp_pause;
+ DCmdArgument<char *> _jdp_name;
public:
JMXStartRemoteDCmd(outputStream *output, bool heap_allocated);
--- a/hotspot/src/share/vm/trace/traceEventClasses.xsl Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/trace/traceEventClasses.xsl Wed Jul 05 19:19:29 2017 +0200
@@ -23,8 +23,8 @@
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:import href="xsl_util.xsl"/>
<xsl:output method="text" indent="no" omit-xml-declaration="yes"/>
-<xsl:import href="xsl_util.xsl"/>
<xsl:template match="/">
<xsl:call-template name="file-header"/>
--- a/hotspot/src/share/vm/trace/traceEventIds.xsl Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/trace/traceEventIds.xsl Wed Jul 05 19:19:29 2017 +0200
@@ -23,8 +23,8 @@
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:import href="xsl_util.xsl"/>
<xsl:output method="text" indent="no" omit-xml-declaration="yes"/>
-<xsl:import href="xsl_util.xsl"/>
<xsl:template match="/">
<xsl:call-template name="file-header"/>
--- a/hotspot/src/share/vm/trace/traceTypes.xsl Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/src/share/vm/trace/traceTypes.xsl Wed Jul 05 19:19:29 2017 +0200
@@ -23,8 +23,8 @@
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+<xsl:import href="xsl_util.xsl"/>
<xsl:output method="text" indent="no" omit-xml-declaration="yes"/>
-<xsl:import href="xsl_util.xsl"/>
<xsl:template match="/">
<xsl:call-template name="file-header"/>
--- a/hotspot/test/TEST.groups Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/test/TEST.groups Wed Jul 05 19:19:29 2017 +0200
@@ -64,6 +64,7 @@
gc/TestG1ZeroPGCTJcmdThreadPrint.java \
gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java \
gc/metaspace/TestMetaspacePerfCounters.java \
+ gc/metaspace/TestPerfCountersAndMemoryPools.java \
runtime/6819213/TestBootNativeLibraryPath.java \
runtime/6925573/SortMethodsTest.java \
runtime/7107135/Test7107135.sh \
@@ -101,7 +102,9 @@
needs_jre = \
compiler/6852078/Test6852078.java \
compiler/7047069/Test7047069.java \
- runtime/6294277/SourceDebugExtension.java
+ runtime/6294277/SourceDebugExtension.java \
+ runtime/ClassFile/JsrRewriting.java \
+ runtime/ClassFile/OomWhileParsingRepeatedJsr.java
# Compact 3 adds further tests to compact2
#
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactICondTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8024924
+ * @summary Test non constant addExact
+ * @compile AddExactICondTest.java
+ * @run main AddExactICondTest
+ *
+ */
+
+public class AddExactICondTest {
+ public static int result = 0;
+
+ public static void main(String[] args) {
+ for (int i = 0; i < 50000; ++i) {
+ runTest();
+ }
+ }
+
+ public static void runTest() {
+ int i = 7;
+ while (java.lang.Math.addExact(i, result) < 89361) {
+ if ((java.lang.Math.addExact(i, i) & 1) == 1) {
+ i += 3;
+ } else if ((i & 5) == 4) {
+ i += 7;
+ } else if ((i & 0xf) == 6) {
+ i += 2;
+ } else {
+ i += 1;
+ }
+ result += 2;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactIConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8024924
+ * @summary Test constant addExact
+ * @compile AddExactIConstantTest.java Verify.java
+ * @run main AddExactIConstantTest
+ *
+ */
+
+public class AddExactIConstantTest {
+ public static void main(String[] args) {
+ Verify.ConstantTest.verify(new Verify.AddExactI());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactILoadTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8024924
+ * @summary Test non constant addExact
+ * @compile AddExactILoadTest.java Verify.java
+ * @run main AddExactILoadTest
+ *
+ */
+
+public class AddExactILoadTest {
+ public static void main(String[] args) {
+ Verify.LoadTest.init();
+ Verify.LoadTest.verify(new Verify.AddExactI());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactILoopDependentTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8024924
+ * @summary Test non constant addExact
+ * @compile AddExactILoopDependentTest.java Verify.java
+ * @run main AddExactILoopDependentTest
+ *
+ */
+
+public class AddExactILoopDependentTest {
+ public static void main(String[] args) {
+ Verify.LoopDependentTest.verify(new Verify.AddExactI());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactINonConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8024924
+ * @summary Test non constant addExact
+ * @compile AddExactINonConstantTest.java Verify.java
+ * @run main AddExactINonConstantTest
+ *
+ */
+
+public class AddExactINonConstantTest {
+ public static void main(String[] args) {
+ Verify.NonConstantTest.verify(new Verify.AddExactI());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactIRepeatTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8025657
+ * @summary Test repeating addExact
+ * @compile AddExactIRepeatTest.java Verify.java
+ * @run main AddExactIRepeatTest
+ *
+ */
+
+public class AddExactIRepeatTest {
+ public static void main(String[] args) {
+ runTest(new Verify.AddExactI());
+ }
+
+ public static int nonExact(int x, int y, Verify.BinaryMethod method) {
+ int result = method.unchecked(x, y);
+ result += method.unchecked(x, y);
+ result += method.unchecked(x, y);
+ result += method.unchecked(x, y);
+ return result;
+ }
+
+ public static void runTest(Verify.BinaryMethod method) {
+ java.util.Random rnd = new java.util.Random();
+ for (int i = 0; i < 50000; ++i) {
+ int x = Integer.MAX_VALUE - 10;
+ int y = Integer.MAX_VALUE - 10 + rnd.nextInt(5);
+
+ int c = rnd.nextInt() / 2;
+ int d = rnd.nextInt() / 2;
+
+ int a = catchingExact(x, y, method);
+
+ if (a != 36) {
+ throw new RuntimeException("a != 36 : " + a);
+ }
+
+ int b = nonExact(c, d, method);
+ int n = exact(c, d, method);
+
+
+ if (n != b) {
+ throw new RuntimeException("n != b : " + n + " != " + b);
+ }
+ }
+ }
+
+ public static int exact(int x, int y, Verify.BinaryMethod method) {
+ int result = 0;
+ result += method.checkMethod(x, y);
+ result += method.checkMethod(x, y);
+ result += method.checkMethod(x, y);
+ result += method.checkMethod(x, y);
+ return result;
+ }
+
+ public static int catchingExact(int x, int y, Verify.BinaryMethod method) {
+ int result = 0;
+ try {
+ result += 5;
+ result = method.checkMethod(x, y);
+ } catch (ArithmeticException e) {
+ result += 1;
+ }
+ try {
+ result += 6;
+
+ result += method.checkMethod(x, y);
+ } catch (ArithmeticException e) {
+ result += 2;
+ }
+ try {
+ result += 7;
+ result += method.checkMethod(x, y);
+ } catch (ArithmeticException e) {
+ result += 3;
+ }
+ try {
+ result += 8;
+ result += method.checkMethod(x, y);
+ } catch (ArithmeticException e) {
+ result += 4;
+ }
+ return result;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactLConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test constant addExact
+ * @compile AddExactLConstantTest.java Verify.java
+ * @run main AddExactLConstantTest
+ *
+ */
+
+public class AddExactLConstantTest {
+ public static void main(String[] args) {
+ Verify.ConstantLongTest.verify(new Verify.AddExactL());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/AddExactLNonConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test non constant addExact
+ * @compile AddExactLNonConstantTest.java Verify.java
+ * @run main AddExactLNonConstantTest
+ *
+ */
+
+public class AddExactLNonConstantTest {
+ public static void main(String[] args) {
+ Verify.NonConstantLongTest.verify(new Verify.AddExactL());
+ }
+}
--- a/hotspot/test/compiler/intrinsics/mathexact/CondTest.java Thu Oct 24 09:10:35 2013 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8024924
- * @summary Test non constant addExact
- * @compile CondTest.java Verify.java
- * @run main CondTest
- *
- */
-
-import java.lang.ArithmeticException;
-
-public class CondTest {
- public static int result = 0;
-
- public static void main(String[] args) {
- for (int i = 0; i < 50000; ++i) {
- runTest();
- }
- }
-
- public static void runTest() {
- int i = 7;
- while (java.lang.Math.addExact(i, result) < 89361) {
- if ((java.lang.Math.addExact(i, i) & 1) == 1) {
- i += 3;
- } else if ((i & 5) == 4) {
- i += 7;
- } else if ((i & 0xf) == 6) {
- i += 2;
- } else {
- i += 1;
- }
- result += 2;
- }
- }
-}
--- a/hotspot/test/compiler/intrinsics/mathexact/ConstantTest.java Thu Oct 24 09:10:35 2013 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8024924
- * @summary Test constant addExact
- * @compile ConstantTest.java Verify.java
- * @run main ConstantTest
- *
- */
-
-import java.lang.ArithmeticException;
-
-public class ConstantTest {
- public static void main(String[] args) {
- for (int i = 0; i < 50000; ++i) {
- Verify.verify(5, 7);
- Verify.verify(Integer.MAX_VALUE, 1);
- Verify.verify(Integer.MIN_VALUE, -1);
- Verify.verify(Integer.MAX_VALUE, -1);
- Verify.verify(Integer.MIN_VALUE, 1);
- Verify.verify(Integer.MAX_VALUE / 2, Integer.MAX_VALUE / 2);
- Verify.verify(Integer.MAX_VALUE / 2, (Integer.MAX_VALUE / 2) + 3);
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/DecExactITest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test decrementExact
+ * @compile DecExactITest.java Verify.java
+ * @run main DecExactITest
+ *
+ */
+
+public class DecExactITest {
+ public static int[] values = {1, 1, 1, 1};
+ public static int[] minvalues = {Integer.MIN_VALUE, Integer.MIN_VALUE};
+
+ public static void main(String[] args) {
+ runTest(new Verify.DecExactI());
+ }
+
+ public static void runTest(Verify.UnaryMethod method) {
+ for (int i = 0; i < 20000; ++i) {
+ Verify.verifyUnary(Integer.MIN_VALUE, method);
+ Verify.verifyUnary(minvalues[0], method);
+ Verify.verifyUnary(Integer.MIN_VALUE - values[2], method);
+ Verify.verifyUnary(0, method);
+ Verify.verifyUnary(values[2], method);
+ Verify.verifyUnary(Integer.MAX_VALUE, method);
+ Verify.verifyUnary(Integer.MIN_VALUE - values[0] + values[3], method);
+ Verify.verifyUnary(Integer.MIN_VALUE + 1 - values[0], method);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/DecExactLTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test decrementExact
+ * @compile DecExactITest.java Verify.java
+ * @run main DecExactITest
+ *
+ */
+
+public class DecExactLTest {
+ public static long[] values = {1, 1, 1, 1};
+ public static long[] minvalues = {Long.MIN_VALUE, Long.MIN_VALUE};
+
+ public static void main(String[] args) {
+ runTest(new Verify.DecExactL());
+ }
+
+ public static void runTest(Verify.UnaryLongMethod method) {
+ for (int i = 0; i < 20000; ++i) {
+ Verify.verifyUnary(Long.MIN_VALUE, method);
+ Verify.verifyUnary(minvalues[0], method);
+ Verify.verifyUnary(Long.MIN_VALUE - values[2], method);
+ Verify.verifyUnary(0, method);
+ Verify.verifyUnary(values[2], method);
+ Verify.verifyUnary(Long.MAX_VALUE, method);
+ Verify.verifyUnary(Long.MIN_VALUE - values[0] + values[3], method);
+ Verify.verifyUnary(Long.MIN_VALUE + 1 - values[0], method);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/IncExactITest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test incrementExact
+ * @compile IncExactITest.java Verify.java
+ * @run main IncExactITest
+ *
+ */
+
+
+public class IncExactITest {
+ public static int[] values = {1, 1, 1, 1};
+ public static void main(String[] args) {
+ runTest(new Verify.IncExactI());
+ }
+
+ public static void runTest(Verify.UnaryMethod method) {
+ for (int i = 0; i < 20000; ++i) {
+ Verify.verifyUnary(Integer.MIN_VALUE, method);
+ Verify.verifyUnary(Integer.MAX_VALUE - 1, method);
+ Verify.verifyUnary(0, method);
+ Verify.verifyUnary(values[1], method);
+ Verify.verifyUnary(Integer.MAX_VALUE, method);
+ Verify.verifyUnary(Integer.MAX_VALUE - values[0] + values[3], method);
+ Verify.verifyUnary(Integer.MAX_VALUE - 1 + values[0], method);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/IncExactLTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test incrementExact
+ * @compile IncExactLTest.java Verify.java
+ * @run main IncExactLTest
+ *
+ */
+
+public class IncExactLTest {
+ public static long[] values = {1, 1, 1, 1};
+ public static void main(String[] args) {
+ runTest(new Verify.IncExactL());
+ }
+
+ public static void runTest(Verify.UnaryLongMethod method) {
+ for (int i = 0; i < 20000; ++i) {
+ Verify.verifyUnary(Long.MIN_VALUE, method);
+ Verify.verifyUnary(Long.MAX_VALUE - 1, method);
+ Verify.verifyUnary(0, method);
+ Verify.verifyUnary(values[1], method);
+ Verify.verifyUnary(Long.MAX_VALUE, method);
+ Verify.verifyUnary(Long.MAX_VALUE - values[0] + values[3], method);
+ Verify.verifyUnary(Long.MAX_VALUE - 1 + values[0], method);
+ }
+ }
+}
--- a/hotspot/test/compiler/intrinsics/mathexact/LoadTest.java Thu Oct 24 09:10:35 2013 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8024924
- * @summary Test non constant addExact
- * @compile LoadTest.java Verify.java
- * @run main LoadTest
- *
- */
-
-import java.lang.ArithmeticException;
-
-public class LoadTest {
- public static java.util.Random rnd = new java.util.Random();
- public static int[] values = new int[256];
-
- public static void main(String[] args) {
- for (int i = 0; i < values.length; ++i) {
- values[i] = rnd.nextInt();
- }
-
- for (int i = 0; i < 50000; ++i) {
- Verify.verify(values[i & 255], values[i & 255] - i);
- Verify.verify(values[i & 255] + i, values[i & 255] - i);
- Verify.verify(values[i & 255], values[i & 255]);
- if ((i & 1) == 1 && i > 5) {
- Verify.verify(values[i & 255] + i, values[i & 255] - i);
- } else {
- Verify.verify(values[i & 255] - i, values[i & 255] + i);
- }
- }
- }
-}
--- a/hotspot/test/compiler/intrinsics/mathexact/LoopDependentTest.java Thu Oct 24 09:10:35 2013 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8024924
- * @summary Test non constant addExact
- * @compile LoopDependentTest.java Verify.java
- * @run main LoopDependentTest
- *
- */
-
-import java.lang.ArithmeticException;
-
-public class LoopDependentTest {
- public static java.util.Random rnd = new java.util.Random();
-
- public static void main(String[] args) {
- int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
- for (int i = 0; i < 50000; ++i) {
- Verify.verify(rnd1 + i, rnd2 + i);
- Verify.verify(rnd1 + i, rnd2 + (i & 0xff));
- Verify.verify(rnd1 - i, rnd2 - (i & 0xff));
- Verify.verify(rnd1 + i + 1, rnd2 + i + 2);
- Verify.verify(rnd1 + i * 2, rnd2 + i);
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactICondTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test multiplyExact as condition
+ * @compile MulExactICondTest.java
+ * @run main MulExactICondTest
+ *
+ */
+
+public class MulExactICondTest {
+ public static int result = 0;
+
+ public static void main(String[] args) {
+ for (int i = 0; i < 50000; ++i) {
+ runTest();
+ }
+ }
+
+ public static void runTest() {
+ int i = 7;
+ while (java.lang.Math.multiplyExact(i, result) < 89361) {
+ if ((java.lang.Math.multiplyExact(i, i) & 1) == 1) {
+ i += 3;
+ } else if ((i & 5) == 4) {
+ i += 7;
+ } else if ((i & 0xf) == 6) {
+ i += 2;
+ } else {
+ i += 1;
+ }
+ result += 2;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactIConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test constant multiplyExact
+ * @compile MulExactIConstantTest.java Verify.java
+ * @run main MulExactIConstantTest
+ *
+ */
+
+public class MulExactIConstantTest {
+ public static void main(String[] args) {
+ Verify.ConstantTest.verify(new Verify.MulExactI());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactILoadTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test multiplyExact
+ * @compile MulExactILoadTest.java Verify.java
+ * @run main MulExactILoadTest
+ *
+ */
+
+public class MulExactILoadTest {
+ public static void main(String[] args) {
+ Verify.LoadTest.init();
+ Verify.LoadTest.verify(new Verify.MulExactI());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactILoopDependentTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test loop dependent multiplyExact
+ * @compile MulExactILoopDependentTest.java Verify.java
+ * @run main MulExactILoopDependentTest
+ *
+ */
+public class MulExactILoopDependentTest {
+ public static void main(String[] args) {
+ Verify.LoopDependentTest.verify(new Verify.MulExactI());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactINonConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test non constant multiplyExact
+ * @compile MulExactINonConstantTest.java Verify.java
+ * @run main MulExactINonConstantTest
+ *
+ */
+
+public class MulExactINonConstantTest {
+ public static void main(String[] args) {
+ Verify.NonConstantTest.verify(new Verify.MulExactI());
+ Verify.LoadTest.verify(new Verify.MulExactI());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactIRepeatTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test repeating multiplyExact
+ * @compile MulExactIRepeatTest.java Verify.java
+ * @run main MulExactIRepeatTest
+ *
+ */
+
+public class MulExactIRepeatTest {
+ public static void main(String[] args) {
+ runTest(new Verify.MulExactI());
+ }
+
+ public static int nonExact(int x, int y, Verify.BinaryMethod method) {
+ int result = method.unchecked(x, y);
+ result += method.unchecked(x, y);
+ result += method.unchecked(x, y);
+ result += method.unchecked(x, y);
+ return result;
+ }
+
+ public static void runTest(Verify.BinaryMethod method) {
+ java.util.Random rnd = new java.util.Random();
+ for (int i = 0; i < 50000; ++i) {
+ int x = Integer.MAX_VALUE - 10;
+ int y = Integer.MAX_VALUE - 10 + rnd.nextInt(5);
+
+ int c = rnd.nextInt() / 10;
+ int d = rnd.nextInt(9);
+
+ int a = catchingExact(x, y, method);
+
+ if (a != 36) {
+ throw new RuntimeException("a != 36 : " + a);
+ }
+
+ int b = nonExact(c, d, method);
+ int n = exact(c, d, method);
+
+
+ if (n != b) {
+ throw new RuntimeException("n != b : " + n + " != " + b);
+ }
+ }
+ }
+
+ public static int exact(int x, int y, Verify.BinaryMethod method) {
+ int result = 0;
+ result += method.checkMethod(x, y);
+ result += method.checkMethod(x, y);
+ result += method.checkMethod(x, y);
+ result += method.checkMethod(x, y);
+ return result;
+ }
+
+ public static int catchingExact(int x, int y, Verify.BinaryMethod method) {
+ int result = 0;
+ try {
+ result += 5;
+ result = method.checkMethod(x, y);
+ } catch (ArithmeticException e) {
+ result += 1;
+ }
+ try {
+ result += 6;
+
+ result += method.checkMethod(x, y);
+ } catch (ArithmeticException e) {
+ result += 2;
+ }
+ try {
+ result += 7;
+ result += method.checkMethod(x, y);
+ } catch (ArithmeticException e) {
+ result += 3;
+ }
+ try {
+ result += 8;
+ result += method.checkMethod(x, y);
+ } catch (ArithmeticException e) {
+ result += 4;
+ }
+ return result;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactLConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test constant mulExact
+ * @compile MulExactLConstantTest.java Verify.java
+ * @run main MulExactLConstantTest
+ *
+ */
+
+public class MulExactLConstantTest {
+ public static void main(String[] args) {
+ Verify.ConstantLongTest.verify(new Verify.MulExactL());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/MulExactLNonConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test non constant mulExact
+ * @compile MulExactLNonConstantTest.java Verify.java
+ * @run main MulExactLNonConstantTest
+ *
+ */
+
+public class MulExactLNonConstantTest {
+ public static void main(String[] args) {
+ Verify.NonConstantLongTest.verify(new Verify.MulExactL());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactIConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test constant negExact
+ * @compile NegExactIConstantTest.java Verify.java
+ * @run main NegExactIConstantTest
+ *
+ */
+
+public class NegExactIConstantTest {
+ public static void main(String[] args) {
+ Verify.ConstantTest.verify(new Verify.UnaryToBinary(new Verify.NegExactI()));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactILoadTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test negExact
+ * @compile NegExactILoadTest.java Verify.java
+ * @run main NegExactILoadTest
+ *
+ */
+
+public class NegExactILoadTest {
+ public static void main(String[] args) {
+ Verify.LoadTest.init();
+ Verify.LoadTest.verify(new Verify.UnaryToBinary(new Verify.NegExactI()));
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactILoopDependentTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test negExact loop dependent
+ * @compile NegExactILoopDependentTest.java Verify.java
+ * @run main NegExactILoopDependentTest
+ *
+ */
+public class NegExactILoopDependentTest {
+ public static void main(String[] args) {
+ Verify.LoopDependentTest.verify(new Verify.UnaryToBinary(new Verify.NegExactI()));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactINonConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test non constant negExact
+ * @compile NegExactINonConstantTest.java Verify.java
+ * @run main NegExactINonConstantTest
+ *
+ */
+
+public class NegExactINonConstantTest {
+ public static void main(String[] args) {
+ Verify.NonConstantTest.verify(new Verify.UnaryToBinary(new Verify.NegExactI()));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactLConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test constant negExact
+ * @compile NegExactLConstantTest.java Verify.java
+ * @run main NegExactLConstantTest
+ *
+ */
+
+public class NegExactLConstantTest {
+ public static void main(String[] args) {
+ Verify.ConstantLongTest.verify(new Verify.UnaryToBinaryLong(new Verify.NegExactL()));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/NegExactLNonConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test constant negExact
+ * @compile NegExactLNonConstantTest.java Verify.java
+ * @run main NegExactLNonConstantTest
+ *
+ */
+
+public class NegExactLNonConstantTest {
+ public static void main(String[] args) {
+ Verify.NonConstantLongTest.verify(new Verify.UnaryToBinaryLong(new Verify.NegExactL()));
+ }
+}
--- a/hotspot/test/compiler/intrinsics/mathexact/NonConstantTest.java Thu Oct 24 09:10:35 2013 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8024924
- * @summary Test non constant addExact
- * @compile NonConstantTest.java Verify.java
- * @run main NonConstantTest
- *
- */
-
-import java.lang.ArithmeticException;
-
-public class NonConstantTest {
- public static java.util.Random rnd = new java.util.Random();
-
- public static void main(String[] args) {
- for (int i = 0; i < 50000; ++i) {
- int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
- Verify.verify(rnd1, rnd2);
- Verify.verify(rnd1, rnd2 + 1);
- Verify.verify(rnd1 + 1, rnd2);
- Verify.verify(rnd1 - 1, rnd2);
- Verify.verify(rnd1, rnd2 - 1);
- }
- }
-}
--- a/hotspot/test/compiler/intrinsics/mathexact/RepeatTest.java Thu Oct 24 09:10:35 2013 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8025657
- * @summary Test repeating addExact
- * @compile RepeatTest.java
- * @run main RepeatTest
- *
- */
-
-import java.lang.ArithmeticException;
-
-public class RepeatTest {
- public static void main(String[] args) {
- java.util.Random rnd = new java.util.Random();
- for (int i = 0; i < 50000; ++i) {
- int x = Integer.MAX_VALUE - 10;
- int y = Integer.MAX_VALUE - 10 + rnd.nextInt(5); //rnd.nextInt() / 2;
-
- int c = rnd.nextInt() / 2;
- int d = rnd.nextInt() / 2;
-
- int a = addExact(x, y);
-
- if (a != 36) {
- throw new RuntimeException("a != 0 : " + a);
- }
-
- int b = nonExact(c, d);
- int n = addExact2(c, d);
-
-
- if (n != b) {
- throw new RuntimeException("n != b : " + n + " != " + b);
- }
- }
- }
-
- public static int addExact2(int x, int y) {
- int result = 0;
- result += java.lang.Math.addExact(x, y);
- result += java.lang.Math.addExact(x, y);
- result += java.lang.Math.addExact(x, y);
- result += java.lang.Math.addExact(x, y);
- return result;
- }
-
- public static int addExact(int x, int y) {
- int result = 0;
- try {
- result += 5;
- result = java.lang.Math.addExact(x, y);
- } catch (ArithmeticException e) {
- result += 1;
- }
- try {
- result += 6;
-
- result += java.lang.Math.addExact(x, y);
- } catch (ArithmeticException e) {
- result += 2;
- }
- try {
- result += 7;
- result += java.lang.Math.addExact(x, y);
- } catch (ArithmeticException e) {
- result += 3;
- }
- try {
- result += 8;
- result += java.lang.Math.addExact(x, y);
- } catch (ArithmeticException e) {
- result += 4;
- }
- return result;
- }
-
- public static int nonExact(int x, int y) {
- int result = x + y;
- result += x + y;
- result += x + y;
- result += x + y;
- return result;
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactICondTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test subtractExact as condition
+ * @compile SubExactICondTest.java Verify.java
+ * @run main SubExactICondTest
+ *
+ */
+
+public class SubExactICondTest {
+ public static int result = 0;
+
+ public static void main(String[] args) {
+ for (int i = 0; i < 50000; ++i) {
+ runTest();
+ }
+ }
+
+ public static void runTest() {
+ int i = 7;
+ while (java.lang.Math.subtractExact(i, result) > -31361) {
+ if ((java.lang.Math.subtractExact(i, i) & 1) == 1) {
+ i -= 3;
+ } else if ((i & 5) == 4) {
+ i -= 7;
+ } else if ((i & 0xf) == 6) {
+ i -= 2;
+ } else {
+ i -= 1;
+ }
+ result += 2;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactIConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test constant subtractExact
+ * @compile SubExactIConstantTest.java Verify.java
+ * @run main SubExactIConstantTest
+ *
+ */
+
+public class SubExactIConstantTest {
+ public static void main(String[] args) {
+ Verify.ConstantTest.verify(new Verify.SubExactI());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactILoadTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test non constant subtractExact
+ * @compile SubExactILoadTest.java Verify.java
+ * @run main SubExactILoadTest
+ *
+ */
+
+public class SubExactILoadTest {
+ public static void main(String[] args) {
+ Verify.LoadTest.init();
+ Verify.LoadTest.verify(new Verify.SubExactI());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactILoopDependentTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test non constant subtractExact
+ * @compile SubExactILoopDependentTest.java Verify.java
+ * @run main SubExactILoopDependentTest
+ *
+ */
+
+public class SubExactILoopDependentTest {
+ public static void main(String[] args) {
+ Verify.LoopDependentTest.verify(new Verify.SubExactI());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactINonConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test non constant subtractExact
+ * @compile SubExactINonConstantTest.java Verify.java
+ * @run main SubExactINonConstantTest
+ *
+ */
+
+public class SubExactINonConstantTest {
+ public static void main(String[] args) {
+ Verify.NonConstantTest.verify(new Verify.SubExactI());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactIRepeatTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test repeating subtractExact
+ * @compile SubExactIRepeatTest.java Verify.java
+ * @run main SubExactIRepeatTest
+ *
+ */
+
+import java.lang.ArithmeticException;
+
+public class SubExactIRepeatTest {
+ public static void main(String[] args) {
+ runTest(new Verify.SubExactI());
+ }
+
+ public static int nonExact(int x, int y, Verify.BinaryMethod method) {
+ int result = method.unchecked(x, y);
+ result += method.unchecked(x, y);
+ result += method.unchecked(x, y);
+ result += method.unchecked(x, y);
+ return result;
+ }
+
+ public static void runTest(Verify.BinaryMethod method) {
+ java.util.Random rnd = new java.util.Random();
+ for (int i = 0; i < 50000; ++i) {
+ int x = Integer.MIN_VALUE + 10;
+ int y = Integer.MAX_VALUE - 10 + rnd.nextInt(5);
+
+ int c = rnd.nextInt() / 2;
+ int d = rnd.nextInt() / 2;
+
+ int a = catchingExact(x, y, method);
+
+ if (a != 36) {
+ throw new RuntimeException("a != 36 : " + a);
+ }
+
+ int b = nonExact(c, d, method);
+ int n = exact(c, d, method);
+
+
+ if (n != b) {
+ throw new RuntimeException("n != b : " + n + " != " + b);
+ }
+ }
+ }
+
+ public static int exact(int x, int y, Verify.BinaryMethod method) {
+ int result = 0;
+ result += method.checkMethod(x, y);
+ result += method.checkMethod(x, y);
+ result += method.checkMethod(x, y);
+ result += method.checkMethod(x, y);
+ return result;
+ }
+
+ public static int catchingExact(int x, int y, Verify.BinaryMethod method) {
+ int result = 0;
+ try {
+ result += 5;
+ result = method.checkMethod(x, y);
+ } catch (ArithmeticException e) {
+ result += 1;
+ }
+ try {
+ result += 6;
+
+ result += method.checkMethod(x, y);
+ } catch (ArithmeticException e) {
+ result += 2;
+ }
+ try {
+ result += 7;
+ result += method.checkMethod(x, y);
+ } catch (ArithmeticException e) {
+ result += 3;
+ }
+ try {
+ result += 8;
+ result += method.checkMethod(x, y);
+ } catch (ArithmeticException e) {
+ result += 4;
+ }
+ return result;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactLConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test constant subtractExact
+ * @compile SubExactLConstantTest.java Verify.java
+ * @run main SubExactLConstantTest
+ *
+ */
+
+public class SubExactLConstantTest {
+ public static void main(String[] args) {
+ Verify.ConstantLongTest.verify(new Verify.SubExactL());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/intrinsics/mathexact/SubExactLNonConstantTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026844
+ * @summary Test non constant subtractExact
+ * @compile SubExactLNonConstantTest.java Verify.java
+ * @run main SubExactLNonConstantTest
+ *
+ */
+
+public class SubExactLNonConstantTest {
+ public static void main(String[] args) {
+ Verify.NonConstantLongTest.verify(new Verify.SubExactL());
+ }
+}
--- a/hotspot/test/compiler/intrinsics/mathexact/Verify.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/test/compiler/intrinsics/mathexact/Verify.java Wed Jul 05 19:19:29 2017 +0200
@@ -22,47 +22,641 @@
*/
public class Verify {
- public static String throwWord(boolean threw) {
- return (threw ? "threw" : "didn't throw");
- }
+ public static String throwWord(boolean threw) {
+ return (threw ? "threw" : "didn't throw");
+ }
+
+ public static void verifyResult(UnaryMethod method, int result1, int result2, boolean exception1, boolean exception2, int value) {
+ if (exception1 != exception2) {
+ throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version" + throwWord(exception2) + " for: " + value);
+ }
+ if (result1 != result2) {
+ throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2);
+ }
+ }
+
+ public static void verifyResult(UnaryLongMethod method, long result1, long result2, boolean exception1, boolean exception2, long value) {
+ if (exception1 != exception2) {
+ throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version" + throwWord(exception2) + " for: " + value);
+ }
+ if (result1 != result2) {
+ throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2);
+ }
+ }
+
+ private static void verifyResult(BinaryMethod method, int result1, int result2, boolean exception1, boolean exception2, int a, int b) {
+ if (exception1 != exception2) {
+ throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version " + throwWord(exception2) + " for: " + a + " + " + b);
+ }
+ if (result1 != result2) {
+ throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2);
+ }
+ }
+
+ private static void verifyResult(BinaryLongMethod method, long result1, long result2, boolean exception1, boolean exception2, long a, long b) {
+ if (exception1 != exception2) {
+ throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version " + throwWord(exception2) + " for: " + a + " + " + b);
+ }
+ if (result1 != result2) {
+ throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2);
+ }
+ }
+
+
+ public static void verifyUnary(int a, UnaryMethod method) {
+ boolean exception1 = false, exception2 = false;
+ int result1 = 0, result2 = 0;
+ try {
+ result1 = method.checkMethod(a);
+ } catch (ArithmeticException e) {
+ exception1 = true;
+ }
+ try {
+ result2 = method.safeMethod(a);
+ } catch (ArithmeticException e) {
+ exception2 = true;
+ }
+
+ verifyResult(method, result1, result2, exception1, exception2, a);
+ }
+
+ public static void verifyUnary(long a, UnaryLongMethod method) {
+ boolean exception1 = false, exception2 = false;
+ long result1 = 0, result2 = 0;
+ try {
+ result1 = method.checkMethod(a);
+ } catch (ArithmeticException e) {
+ exception1 = true;
+ }
+ try {
+ result2 = method.safeMethod(a);
+ } catch (ArithmeticException e) {
+ exception2 = true;
+ }
+
+ verifyResult(method, result1, result2, exception1, exception2, a);
+ }
+
+
+ public static void verifyBinary(int a, int b, BinaryMethod method) {
+ boolean exception1 = false, exception2 = false;
+ int result1 = 0, result2 = 0;
+ try {
+ result1 = method.checkMethod(a, b);
+ } catch (ArithmeticException e) {
+ exception1 = true;
+ }
+ try {
+ result2 = method.safeMethod(a, b);
+ } catch (ArithmeticException e) {
+ exception2 = true;
+ }
+
+ verifyResult(method, result1, result2, exception1, exception2, a, b);
+ }
+
+ public static void verifyBinary(long a, long b, BinaryLongMethod method) {
+ boolean exception1 = false, exception2 = false;
+ long result1 = 0, result2 = 0;
+ try {
+ result1 = method.checkMethod(a, b);
+ } catch (ArithmeticException e) {
+ exception1 = true;
+ }
+ try {
+ result2 = method.safeMethod(a, b);
+ } catch (ArithmeticException e) {
+ exception2 = true;
+ }
+
+ verifyResult(method, result1, result2, exception1, exception2, a, b);
+ }
+
+
+ public static class LoadTest {
+ public static java.util.Random rnd = new java.util.Random();
+ public static int[] values = new int[256];
+
+ public static void init() {
+ for (int i = 0; i < values.length; ++i) {
+ values[i] = rnd.nextInt();
+ }
+ }
+
+ public static void verify(BinaryMethod method) {
+ for (int i = 0; i < 50000; ++i) {
+ Verify.verifyBinary(values[i & 255], values[i & 255] - i, method);
+ Verify.verifyBinary(values[i & 255] + i, values[i & 255] - i, method);
+ Verify.verifyBinary(values[i & 255], values[i & 255], method);
+ if ((i & 1) == 1 && i > 5) {
+ Verify.verifyBinary(values[i & 255] + i, values[i & 255] - i, method);
+ } else {
+ Verify.verifyBinary(values[i & 255] - i, values[i & 255] + i, method);
+ }
+ Verify.verifyBinary(values[i & 255], values[(i + 1) & 255], method);
+ }
+ }
+ }
+
+ public static class NonConstantTest {
+ public static java.util.Random rnd = new java.util.Random();
+
+ public static void verify(BinaryMethod method) {
+ for (int i = 0; i < 50000; ++i) {
+ int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
+ Verify.verifyBinary(rnd1, rnd2, method);
+ Verify.verifyBinary(rnd1, rnd2 + 1, method);
+ Verify.verifyBinary(rnd1 + 1, rnd2, method);
+ Verify.verifyBinary(rnd1 - 1, rnd2, method);
+ Verify.verifyBinary(rnd1, rnd2 - 1, method);
+ }
+ }
+ }
- public static void verify(int a, int b) {
- boolean exception1 = false, exception2 = false;
- int result1 = 0, result2 = 0;
- try {
- result1 = testIntrinsic(a, b);
- } catch (ArithmeticException e) {
- exception1 = true;
+ public static class NonConstantLongTest {
+ public static long[] values = { Long.MIN_VALUE, Long.MAX_VALUE, 0, Long.MAX_VALUE - 1831 };
+ public static java.util.Random rnd = new java.util.Random();
+
+ public static void verify(BinaryLongMethod method) {
+ for (int i = 0; i < 50000; ++i) {
+ long rnd1 = rnd.nextLong(), rnd2 = rnd.nextLong();
+ Verify.verifyBinary(rnd1, rnd2, method);
+ Verify.verifyBinary(rnd1, rnd2 + 1, method);
+ Verify.verifyBinary(rnd1 + 1, rnd2, method);
+ Verify.verifyBinary(rnd1 - 1, rnd2, method);
+ Verify.verifyBinary(rnd1, rnd2 - 1, method);
+ Verify.verifyBinary(rnd1 + Long.MAX_VALUE - rnd2, rnd2 + 1, method);
+ Verify.verifyBinary(values[0], values[2], method);
+ Verify.verifyBinary(values[1], values[2], method);
+ Verify.verifyBinary(values[3], 74L, method);
+ }
+ }
+ }
+
+ public static class LoopDependentTest {
+ public static java.util.Random rnd = new java.util.Random();
+
+ public static void verify(BinaryMethod method) {
+ int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
+ runTest(rnd1, rnd2, method);
+ }
+
+ private static void runTest(int rnd1, int rnd2, BinaryMethod method) {
+ for (int i = 0; i < 50000; ++i) {
+ Verify.verifyBinary(rnd1 + i, rnd2 + i, method);
+ Verify.verifyBinary(rnd1 + i, rnd2 + (i & 0xff), method);
+ Verify.verifyBinary(rnd1 - i, rnd2 - (i & 0xff), method);
+ Verify.verifyBinary(rnd1 + i + 1, rnd2 + i + 2, method);
+ Verify.verifyBinary(rnd1 + i * 2, rnd2 + i, method);
+ }
+ }
+ }
+
+ public static class ConstantTest {
+ public static void verify(BinaryMethod method) {
+ for (int i = 0; i < 50000; ++i) {
+ Verify.verifyBinary(5, 7, method);
+ Verify.verifyBinary(Integer.MAX_VALUE, 1, method);
+ Verify.verifyBinary(Integer.MIN_VALUE, -1, method);
+ Verify.verifyBinary(Integer.MAX_VALUE, -1, method);
+ Verify.verifyBinary(Integer.MIN_VALUE, 1, method);
+ Verify.verifyBinary(Integer.MAX_VALUE / 2, Integer.MAX_VALUE / 2, method);
+ Verify.verifyBinary(Integer.MAX_VALUE / 2, (Integer.MAX_VALUE / 2) + 3, method);
+ Verify.verifyBinary(Integer.MAX_VALUE, Integer.MIN_VALUE, method);
+ }
+ }
+ }
+
+ public static class ConstantLongTest {
+ public static void verify(BinaryLongMethod method) {
+ for (int i = 0; i < 50000; ++i) {
+ Verify.verifyBinary(5, 7, method);
+ Verify.verifyBinary(Long.MAX_VALUE, 1, method);
+ Verify.verifyBinary(Long.MIN_VALUE, -1, method);
+ Verify.verifyBinary(Long.MAX_VALUE, -1, method);
+ Verify.verifyBinary(Long.MIN_VALUE, 1, method);
+ Verify.verifyBinary(Long.MAX_VALUE / 2, Long.MAX_VALUE / 2, method);
+ Verify.verifyBinary(Long.MAX_VALUE / 2, (Long.MAX_VALUE / 2) + 3, method);
+ Verify.verifyBinary(Long.MAX_VALUE, Long.MIN_VALUE, method);
+ }
+ }
+ }
+
+ public static interface BinaryMethod {
+ int safeMethod(int a, int b);
+ int checkMethod(int a, int b);
+ int unchecked(int a, int b);
+ String name();
}
- try {
- result2 = testNonIntrinsic(a, b);
- } catch (ArithmeticException e) {
- exception2 = true;
+
+ public static interface UnaryMethod {
+ int safeMethod(int value);
+ int checkMethod(int value);
+ int unchecked(int value);
+ String name();
+ }
+
+ public static interface BinaryLongMethod {
+ long safeMethod(long a, long b);
+ long checkMethod(long a, long b);
+ long unchecked(long a, long b);
+ String name();
+ }
+
+ public static interface UnaryLongMethod {
+ long safeMethod(long value);
+ long checkMethod(long value);
+ long unchecked(long value);
+ String name();
+ }
+
+ public static class UnaryToBinary implements BinaryMethod {
+ private final UnaryMethod method;
+ public UnaryToBinary(UnaryMethod method) {
+ this.method = method;
+ }
+
+ @Override
+ public int safeMethod(int a, int b) {
+ return method.safeMethod(a);
+ }
+
+ @Override
+ public int checkMethod(int a, int b) {
+ return method.checkMethod(a);
+ }
+
+ @Override
+ public int unchecked(int a, int b) {
+ return method.unchecked(a);
+
+ }
+
+ @Override
+ public String name() {
+ return method.name();
+ }
+ }
+
+ public static class UnaryToBinaryLong implements BinaryLongMethod {
+ private final UnaryLongMethod method;
+ public UnaryToBinaryLong(UnaryLongMethod method) {
+ this.method = method;
+ }
+
+ @Override
+ public long safeMethod(long a, long b) {
+ return method.safeMethod(a);
+ }
+
+ @Override
+ public long checkMethod(long a, long b) {
+ return method.checkMethod(a);
+ }
+
+ @Override
+ public long unchecked(long a, long b) {
+ return method.unchecked(a);
+
+ }
+
+ @Override
+ public String name() {
+ return method.name();
+ }
}
- if (exception1 != exception2) {
- throw new RuntimeException("Intrinsic version " + throwWord(exception1) + " exception, NonIntrinsic version " + throwWord(exception2) + " for: " + a + " + " + b);
+
+ public static class AddExactI implements BinaryMethod {
+ @Override
+ public int safeMethod(int x, int y) {
+ int r = x + y;
+ // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+ if (((x ^ r) & (y ^ r)) < 0) {
+ throw new ArithmeticException("integer overflow");
+ }
+ return r;
+
+ }
+
+ @Override
+ public int checkMethod(int a, int b) {
+ return Math.addExact(a, b);
+ }
+
+ @Override
+ public String name() {
+ return "addExact";
+ }
+
+ @Override
+ public int unchecked(int a, int b) {
+ return a + b;
+ }
}
- if (result1 != result2) {
- throw new RuntimeException("Intrinsic version returned: " + a + " while NonIntrinsic version returned: " + b);
+
+ public static class AddExactL implements BinaryLongMethod {
+ @Override
+ public long safeMethod(long x, long y) {
+ long r = x + y;
+ // HD 2-12 Overflow iff both arguments have the opposite sign of the result
+ if (((x ^ r) & (y ^ r)) < 0) {
+ throw new ArithmeticException("integer overflow");
+ }
+ return r;
+
+ }
+
+ @Override
+ public long checkMethod(long a, long b) {
+ return Math.addExact(a, b);
+ }
+
+ @Override
+ public String name() {
+ return "addExactLong";
+ }
+
+ @Override
+ public long unchecked(long a, long b) {
+ return a + b;
+ }
+ }
+
+ public static class MulExactI implements BinaryMethod {
+ @Override
+ public int safeMethod(int x, int y) {
+ long r = (long)x * (long)y;
+ if ((int)r != r) {
+ throw new ArithmeticException("integer overflow");
+ }
+ return (int)r;
+
+ }
+
+ @Override
+ public int checkMethod(int a, int b) {
+ return Math.multiplyExact(a, b);
+ }
+
+ @Override
+ public int unchecked(int a, int b) {
+ return a * b;
+ }
+
+ @Override
+ public String name() {
+ return "multiplyExact";
+ }
}
- }
+
+ public static class MulExactL implements BinaryLongMethod {
+ @Override
+ public long safeMethod(long x, long y) {
+ long r = x * y;
+ long ax = Math.abs(x);
+ long ay = Math.abs(y);
+ if (((ax | ay) >>> 31 != 0)) {
+ // Some bits greater than 2^31 that might cause overflow
+ // Check the result using the divide operator
+ // and check for the special case of Long.MIN_VALUE * -1
+ if (((y != 0) && (r / y != x)) ||
+ (x == Long.MIN_VALUE && y == -1)) {
+ throw new ArithmeticException("long overflow");
+ }
+ }
+ return r;
+ }
+
+ @Override
+ public long checkMethod(long a, long b) {
+ return Math.multiplyExact(a, b);
+ }
+
+ @Override
+ public long unchecked(long a, long b) {
+ return a * b;
+ }
+
+ @Override
+ public String name() {
+ return "multiplyExact";
+ }
+ }
- public static int testIntrinsic(int a, int b) {
- return java.lang.Math.addExact(a, b);
- }
+ public static class NegExactL implements UnaryLongMethod {
+ @Override
+ public long safeMethod(long a) {
+ if (a == Long.MIN_VALUE) {
+ throw new ArithmeticException("long overflow");
+ }
+
+ return -a;
+
+ }
+
+ @Override
+ public long checkMethod(long value) {
+ return Math.negateExact(value);
+ }
+
+ @Override
+ public long unchecked(long value) {
+ return -value;
+ }
+
+ @Override
+ public String name() {
+ return "negateExactLong";
+ }
+ }
+
+ public static class NegExactI implements UnaryMethod {
+ @Override
+ public int safeMethod(int a) {
+ if (a == Integer.MIN_VALUE) {
+ throw new ArithmeticException("integer overflow");
+ }
+
+ return -a;
+
+ }
+
+ @Override
+ public int checkMethod(int value) {
+ return Math.negateExact(value);
+ }
+
+ @Override
+ public int unchecked(int value) {
+ return -value;
+ }
- public static int testNonIntrinsic(int a, int b) {
- return safeAddExact(a, b);
- }
+ @Override
+ public String name() {
+ return "negateExact";
+ }
+ }
+
+ public static class SubExactI implements BinaryMethod {
+ @Override
+ public int safeMethod(int x, int y) {
+ int r = x - y;
+ // HD 2-12 Overflow iff the arguments have different signs and
+ // the sign of the result is different than the sign of x
+ if (((x ^ y) & (x ^ r)) < 0) {
+ throw new ArithmeticException("integer overflow");
+ }
+ return r;
+ }
+
+ @Override
+ public int checkMethod(int a, int b) {
+ return Math.subtractExact(a, b);
+ }
+
+ @Override
+ public int unchecked(int a, int b) {
+ return a - b;
+ }
+
+ @Override
+ public String name() {
+ return "subtractExact";
+ }
+ }
+
+ public static class SubExactL implements BinaryLongMethod {
+ @Override
+ public long safeMethod(long x, long y) {
+ long r = x - y;
+ // HD 2-12 Overflow iff the arguments have different signs and
+ // the sign of the result is different than the sign of x
+ if (((x ^ y) & (x ^ r)) < 0) {
+ throw new ArithmeticException("integer overflow");
+ }
+ return r;
+ }
+
+ @Override
+ public long checkMethod(long a, long b) {
+ return Math.subtractExact(a, b);
+ }
+
+ @Override
+ public long unchecked(long a, long b) {
+ return a - b;
+ }
+
+ @Override
+ public String name() {
+ return "subtractExactLong";
+ }
+ }
+
+ static class IncExactL implements UnaryLongMethod {
+ @Override
+ public long safeMethod(long a) {
+ if (a == Long.MAX_VALUE) {
+ throw new ArithmeticException("long overflow");
+ }
+
+ return a + 1L;
+
+ }
+
+ @Override
+ public long checkMethod(long value) {
+ return Math.incrementExact(value);
+ }
+
+ @Override
+ public long unchecked(long value) {
+ return value + 1;
+ }
- // Copied java.lang.Math.addExact to avoid intrinsification
- public static int safeAddExact(int x, int y) {
- int r = x + y;
- // HD 2-12 Overflow iff both arguments have the opposite sign of the result
- if (((x ^ r) & (y ^ r)) < 0) {
- throw new ArithmeticException("integer overflow");
+ @Override
+ public String name() {
+ return "incrementExactLong";
+ }
+ }
+
+ static class IncExactI implements UnaryMethod {
+ @Override
+ public int safeMethod(int a) {
+ if (a == Integer.MAX_VALUE) {
+ throw new ArithmeticException("integer overflow");
+ }
+
+ return a + 1;
+ }
+
+ @Override
+ public int checkMethod(int value) {
+ return Math.incrementExact(value);
+ }
+
+ @Override
+ public int unchecked(int value) {
+ return value + 1;
+ }
+
+ @Override
+ public String name() {
+ return "incrementExact";
+ }
}
- return r;
- }
+
+ static class DecExactL implements UnaryLongMethod {
+ @Override
+ public long safeMethod(long a) {
+ if (a == Long.MIN_VALUE) {
+ throw new ArithmeticException("long overflow");
+ }
+
+ return a - 1L;
+ }
+
+ @Override
+ public long checkMethod(long value) {
+ return Math.decrementExact(value);
+ }
+
+ @Override
+ public long unchecked(long value) {
+ return value - 1;
+ }
+
+ @Override
+ public String name() {
+ return "decExactLong";
+ }
+ }
+
+ static class DecExactI implements UnaryMethod {
+ @Override
+ public int safeMethod(int a) {
+ if (a == Integer.MIN_VALUE) {
+ throw new ArithmeticException("integer overflow");
+ }
+
+ return a - 1;
+ }
+
+ @Override
+ public int checkMethod(int value) {
+ return Math.decrementExact(value);
+ }
+
+ @Override
+ public int unchecked(int value) {
+ return value - 1;
+ }
+
+ @Override
+ public String name() {
+ return "decrementExact";
+ }
+ }
+
}
--- a/hotspot/test/compiler/print/PrintInlining.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/test/compiler/print/PrintInlining.java Wed Jul 05 19:19:29 2017 +0200
@@ -25,7 +25,7 @@
* @test
* @bug 8022585
* @summary VM crashes when ran with -XX:+PrintInlining
- * @run main/othervm -Xcomp -XX:+PrintInlining PrintInlining
+ * @run main/othervm -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining PrintInlining
*
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/tiered/CompLevelsTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Abstract class for testing of used compilation levels correctness.
+ *
+ * @author igor.ignatyev@oracle.com
+ */
+public abstract class CompLevelsTest extends CompilerWhiteBoxTest {
+ protected CompLevelsTest(TestCase testCase) {
+ super(testCase);
+ // to prevent inlining of #method
+ WHITE_BOX.testSetDontInlineMethod(method, true);
+ }
+
+ /**
+ * Checks that level is available.
+ * @param compLevel level to check
+ */
+ protected void testAvailableLevel(int compLevel, int bci) {
+ if (IS_VERBOSE) {
+ System.out.printf("testAvailableLevel(level = %d, bci = %d)%n",
+ compLevel, bci);
+ }
+ WHITE_BOX.enqueueMethodForCompilation(method, compLevel, bci);
+ checkCompiled();
+ checkLevel(compLevel, getCompLevel());
+ deoptimize();
+ }
+
+ /**
+ * Checks that level is unavailable.
+ * @param compLevel level to check
+ */
+ protected void testUnavailableLevel(int compLevel, int bci) {
+ if (IS_VERBOSE) {
+ System.out.printf("testUnavailableLevel(level = %d, bci = %d)%n",
+ compLevel, bci);
+ }
+ WHITE_BOX.enqueueMethodForCompilation(method, compLevel, bci);
+ checkNotCompiled();
+ }
+
+ /**
+ * Checks validity of compilation level.
+ * @param expected expected level
+ * @param actual actually level
+ */
+ protected void checkLevel(int expected, int actual) {
+ if (expected != actual) {
+ throw new RuntimeException("expected[" + expected + "] != actual["
+ + actual + "]");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/tiered/NonTieredLevelsTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.function.IntPredicate;
+
+/**
+ * @test NonTieredLevelsTest
+ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * @build NonTieredLevelsTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:-TieredCompilation
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -XX:CompileCommand=compileonly,TestCase$Helper::*
+ * NonTieredLevelsTest
+ * @summary Verify that only one level can be used
+ * @author igor.ignatyev@oracle.com
+ */
+public class NonTieredLevelsTest extends CompLevelsTest {
+ private static final int AVAILABLE_COMP_LEVEL;
+ private static final IntPredicate IS_AVAILABLE_COMPLEVEL;
+ static {
+ String vmName = System.getProperty("java.vm.name");
+ if (vmName.endsWith(" Server VM")) {
+ AVAILABLE_COMP_LEVEL = COMP_LEVEL_FULL_OPTIMIZATION;
+ IS_AVAILABLE_COMPLEVEL = x -> x == COMP_LEVEL_FULL_OPTIMIZATION;
+ } else if (vmName.endsWith(" Client VM")
+ || vmName.endsWith(" Minimal VM")) {
+ AVAILABLE_COMP_LEVEL = COMP_LEVEL_SIMPLE;
+ IS_AVAILABLE_COMPLEVEL = x -> x >= COMP_LEVEL_SIMPLE
+ && x <= COMP_LEVEL_FULL_PROFILE;
+ } else {
+ throw new RuntimeException("Unknown VM: " + vmName);
+ }
+
+ }
+ public static void main(String[] args) throws Exception {
+ if (TIERED_COMPILATION) {
+ System.err.println("Test isn't applicable w/ enabled "
+ + "TieredCompilation. Skip test.");
+ return;
+ }
+ for (TestCase test : TestCase.values()) {
+ new NonTieredLevelsTest(test).runTest();
+ }
+ }
+
+ private NonTieredLevelsTest(TestCase testCase) {
+ super(testCase);
+ // to prevent inlining of #method
+ WHITE_BOX.testSetDontInlineMethod(method, true);
+ }
+
+ @Override
+ protected void test() throws Exception {
+ checkNotCompiled();
+ compile();
+ checkCompiled();
+
+ int compLevel = getCompLevel();
+ checkLevel(AVAILABLE_COMP_LEVEL, compLevel);
+ int bci = WHITE_BOX.getMethodEntryBci(method);
+ deoptimize();
+ if (!testCase.isOsr) {
+ for (int level = 1; level <= COMP_LEVEL_MAX; ++level) {
+ if (IS_AVAILABLE_COMPLEVEL.test(level)) {
+ testAvailableLevel(level, bci);
+ } else {
+ testUnavailableLevel(level, bci);
+ }
+ }
+ } else {
+ System.out.println("skip other levels testing in OSR");
+ testAvailableLevel(AVAILABLE_COMP_LEVEL, bci);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/tiered/TieredLevelsTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test TieredLevelsTest
+ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * @build TieredLevelsTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+TieredCompilation
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -XX:CompileCommand=compileonly,TestCase$Helper::*
+ * TieredLevelsTest
+ * @summary Verify that all levels < 'TieredStopAtLevel' can be used
+ * @author igor.ignatyev@oracle.com
+ */
+public class TieredLevelsTest extends CompLevelsTest {
+ public static void main(String[] args) throws Exception {
+ if (!TIERED_COMPILATION) {
+ System.err.println("Test isn't applicable w/ disabled "
+ + "TieredCompilation. Skip test.");
+ return;
+ }
+ for (TestCase test : TestCase.values()) {
+ new TieredLevelsTest(test).runTest();
+ }
+ }
+
+ private TieredLevelsTest(TestCase testCase) {
+ super(testCase);
+ // to prevent inlining of #method
+ WHITE_BOX.testSetDontInlineMethod(method, true);
+ }
+
+ @Override
+ protected void test() throws Exception {
+ checkNotCompiled();
+ compile();
+ checkCompiled();
+
+ int compLevel = getCompLevel();
+ if (compLevel > TIERED_STOP_AT_LEVEL) {
+ throw new RuntimeException("method.compLevel[" + compLevel
+ + "] > TieredStopAtLevel [" + TIERED_STOP_AT_LEVEL + "]");
+ }
+ int bci = WHITE_BOX.getMethodEntryBci(method);
+ deoptimize();
+
+ for (int testedTier = 1; testedTier <= TIERED_STOP_AT_LEVEL;
+ ++testedTier) {
+ testAvailableLevel(testedTier, bci);
+ }
+ for (int testedTier = TIERED_STOP_AT_LEVEL + 1;
+ testedTier <= COMP_LEVEL_MAX; ++testedTier) {
+ testUnavailableLevel(testedTier, bci);
+ }
+ }
+
+
+ @Override
+ protected void checkLevel(int expected, int actual) {
+ if (expected == COMP_LEVEL_FULL_PROFILE
+ && actual == COMP_LEVEL_LIMITED_PROFILE) {
+ // for simple method full_profile may be replaced by limited_profile
+ return;
+ }
+ super.checkLevel(expected, actual);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/types/TypeSpeculation.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8024070
+ * @summary Test that type speculation doesn't cause incorrect execution
+ * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:TypeProfileLevel=222 TypeSpeculation
+ *
+ */
+
+public class TypeSpeculation {
+
+ interface I {
+ }
+
+ static class A {
+ int m() {
+ return 1;
+ }
+ }
+
+ static class B extends A implements I {
+ int m() {
+ return 2;
+ }
+ }
+
+ static class C extends B {
+ int m() {
+ return 3;
+ }
+ }
+
+ static int test1_invokevirtual(A a) {
+ return a.m();
+ }
+
+ static int test1_1(A a) {
+ return test1_invokevirtual(a);
+ }
+
+ static boolean test1() {
+ A a = new A();
+ B b = new B();
+ C c = new C();
+
+ // pollute profile at test1_invokevirtual to make sure the
+ // compiler cannot rely on it
+ for (int i = 0; i < 5000; i++) {
+ test1_invokevirtual(a);
+ test1_invokevirtual(b);
+ test1_invokevirtual(c);
+ }
+
+ // profiling + speculation should make test1_invokevirtual
+ // inline A.m() with a guard
+ for (int i = 0; i < 20000; i++) {
+ int res = test1_1(b);
+ if (res != b.m()) {
+ System.out.println("test1 failed with class B");
+ return false;
+ }
+ }
+ // check that the guard works as expected by passing a
+ // different type
+ int res = test1_1(a);
+ if (res != a.m()) {
+ System.out.println("test1 failed with class A");
+ return false;
+ }
+ return true;
+ }
+
+ static int test2_invokevirtual(A a) {
+ return a.m();
+ }
+
+ static int test2_1(A a, boolean t) {
+ A aa;
+ if (t) {
+ aa = (B)a;
+ } else {
+ aa = a;
+ }
+ // if a of type B is passed to test2_1, the static type of aa
+ // here is no better than A but the profiled type is B so this
+ // should inline
+ return test2_invokevirtual(aa);
+ }
+
+ static boolean test2() {
+ A a = new A();
+ B b = new B();
+ C c = new C();
+
+ // pollute profile at test2_invokevirtual to make sure the
+ // compiler cannot rely on it
+ for (int i = 0; i < 5000; i++) {
+ test2_invokevirtual(a);
+ test2_invokevirtual(b);
+ test2_invokevirtual(c);
+ }
+
+ // profiling + speculation should make test2_invokevirtual
+ // inline A.m() with a guard
+ for (int i = 0; i < 20000; i++) {
+ int res = test2_1(b, (i % 2) == 0);
+ if (res != b.m()) {
+ System.out.println("test2 failed with class B");
+ return false;
+ }
+ }
+ // check that the guard works as expected by passing a
+ // different type
+ int res = test2_1(a, false);
+ if (res != a.m()) {
+ System.out.println("test2 failed with class A");
+ return false;
+ }
+ return true;
+ }
+
+ static int test3_invokevirtual(A a) {
+ return a.m();
+ }
+
+ static void test3_2(A a) {
+ }
+
+ static int test3_1(A a, int i) {
+ if (i == 0) {
+ return 0;
+ }
+ // If we come here and a is of type B but parameter profiling
+ // is polluted, both branches of the if below should have
+ // profiling that tell us and inlining of the virtual call
+ // should happen
+ if (i == 1) {
+ test3_2(a);
+ } else {
+ test3_2(a);
+ }
+ return test3_invokevirtual(a);
+ }
+
+ static boolean test3() {
+ A a = new A();
+ B b = new B();
+ C c = new C();
+
+ // pollute profile at test3_invokevirtual and test3_1 to make
+ // sure the compiler cannot rely on it
+ for (int i = 0; i < 3000; i++) {
+ test3_invokevirtual(a);
+ test3_invokevirtual(b);
+ test3_invokevirtual(c);
+ test3_1(a, 0);
+ test3_1(b, 0);
+ }
+
+ // profiling + speculation should make test3_invokevirtual
+ // inline A.m() with a guard
+ for (int i = 0; i < 20000; i++) {
+ int res = test3_1(b, (i % 2) + 1);
+ if (res != b.m()) {
+ System.out.println("test3 failed with class B");
+ return false;
+ }
+ }
+ // check that the guard works as expected by passing a
+ // different type
+ int res = test3_1(a, 1);
+ if (res != a.m()) {
+ System.out.println("test3 failed with class A");
+ return false;
+ }
+ return true;
+ }
+
+ // Mix 2 incompatible profiled types
+ static int test4_invokevirtual(A a) {
+ return a.m();
+ }
+
+ static void test4_2(A a) {
+ }
+
+ static int test4_1(A a, boolean b) {
+ if (b) {
+ test4_2(a);
+ } else {
+ test4_2(a);
+ }
+ // shouldn't inline
+ return test4_invokevirtual(a);
+ }
+
+ static boolean test4() {
+ A a = new A();
+ B b = new B();
+ C c = new C();
+
+ // pollute profile at test3_invokevirtual and test3_1 to make
+ // sure the compiler cannot rely on it
+ for (int i = 0; i < 3000; i++) {
+ test4_invokevirtual(a);
+ test4_invokevirtual(b);
+ test4_invokevirtual(c);
+ }
+
+ for (int i = 0; i < 20000; i++) {
+ if ((i % 2) == 0) {
+ int res = test4_1(a, true);
+ if (res != a.m()) {
+ System.out.println("test4 failed with class A");
+ return false;
+ }
+ } else {
+ int res = test4_1(b, false);
+ if (res != b.m()) {
+ System.out.println("test4 failed with class B");
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ // Mix one profiled type with an incompatible type
+ static int test5_invokevirtual(A a) {
+ return a.m();
+ }
+
+ static void test5_2(A a) {
+ }
+
+ static int test5_1(A a, boolean b) {
+ if (b) {
+ test5_2(a);
+ } else {
+ A aa = (B)a;
+ }
+ // shouldn't inline
+ return test5_invokevirtual(a);
+ }
+
+ static boolean test5() {
+ A a = new A();
+ B b = new B();
+ C c = new C();
+
+ // pollute profile at test3_invokevirtual and test3_1 to make
+ // sure the compiler cannot rely on it
+ for (int i = 0; i < 3000; i++) {
+ test5_invokevirtual(a);
+ test5_invokevirtual(b);
+ test5_invokevirtual(c);
+ }
+
+ for (int i = 0; i < 20000; i++) {
+ if ((i % 2) == 0) {
+ int res = test5_1(a, true);
+ if (res != a.m()) {
+ System.out.println("test5 failed with class A");
+ return false;
+ }
+ } else {
+ int res = test5_1(b, false);
+ if (res != b.m()) {
+ System.out.println("test5 failed with class B");
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ // Mix incompatible profiled types
+ static void test6_2(Object o) {
+ }
+
+ static Object test6_1(Object o, boolean b) {
+ if (b) {
+ test6_2(o);
+ } else {
+ test6_2(o);
+ }
+ return o;
+ }
+
+ static boolean test6() {
+ A a = new A();
+ A[] aa = new A[10];
+
+ for (int i = 0; i < 20000; i++) {
+ if ((i % 2) == 0) {
+ test6_1(a, true);
+ } else {
+ test6_1(aa, false);
+ }
+ }
+ return true;
+ }
+
+ // Mix a profiled type with an incompatible type
+ static void test7_2(Object o) {
+ }
+
+ static Object test7_1(Object o, boolean b) {
+ if (b) {
+ test7_2(o);
+ } else {
+ Object oo = (A[])o;
+ }
+ return o;
+ }
+
+ static boolean test7() {
+ A a = new A();
+ A[] aa = new A[10];
+
+ for (int i = 0; i < 20000; i++) {
+ if ((i % 2) == 0) {
+ test7_1(a, true);
+ } else {
+ test7_1(aa, false);
+ }
+ }
+ return true;
+ }
+
+ // Mix a profiled type with an interface
+ static void test8_2(Object o) {
+ }
+
+ static I test8_1(Object o) {
+ test8_2(o);
+ return (I)o;
+ }
+
+ static boolean test8() {
+ A a = new A();
+ B b = new B();
+ C c = new C();
+
+ for (int i = 0; i < 20000; i++) {
+ test8_1(b);
+ }
+ return true;
+ }
+
+ // Mix a profiled type with a constant
+ static void test9_2(Object o) {
+ }
+
+ static Object test9_1(Object o, boolean b) {
+ Object oo;
+ if (b) {
+ test9_2(o);
+ oo = o;
+ } else {
+ oo = "some string";
+ }
+ return oo;
+ }
+
+ static boolean test9() {
+ A a = new A();
+
+ for (int i = 0; i < 20000; i++) {
+ if ((i % 2) == 0) {
+ test9_1(a, true);
+ } else {
+ test9_1(a, false);
+ }
+ }
+ return true;
+ }
+
+ static public void main(String[] args) {
+ boolean success = true;
+
+ success = test1() && success;
+
+ success = test2() && success;
+
+ success = test3() && success;
+
+ success = test4() && success;
+
+ success = test5() && success;
+
+ success = test6() && success;
+
+ success = test7() && success;
+
+ success = test8() && success;
+
+ success = test9() && success;
+
+ if (success) {
+ System.out.println("TEST PASSED");
+ } else {
+ throw new RuntimeException("TEST FAILED: erroneous bound check elimination");
+ }
+ }
+}
--- a/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -80,8 +80,7 @@
static {
if (TIERED_COMPILATION) {
- THRESHOLD = 150000;
- BACKEDGE_THRESHOLD = 0xFFFFFFFFL;
+ BACKEDGE_THRESHOLD = THRESHOLD = 150000;
} else {
THRESHOLD = COMPILE_THRESHOLD;
BACKEDGE_THRESHOLD = COMPILE_THRESHOLD * Long.parseLong(getVMOption(
@@ -364,7 +363,7 @@
/** OSR constructor test case */
OSR_CONSTRUCTOR_TEST(Helper.OSR_CONSTRUCTOR,
Helper.OSR_CONSTRUCTOR_CALLABLE, true),
- /** OSR method test case */
+ /** OSR method test case */
OSR_METOD_TEST(Helper.OSR_METHOD, Helper.OSR_METHOD_CALLABLE, true),
/** OSR static method test case */
OSR_STATIC_TEST(Helper.OSR_STATIC, Helper.OSR_STATIC_CALLABLE, true);
@@ -373,7 +372,7 @@
final Executable executable;
/** object to invoke {@linkplain #executable} */
final Callable<Integer> callable;
- /** flag for OSR test case */
+ /** flag for OSR test case */
final boolean isOsr;
private TestCase(Executable executable, Callable<Integer> callable,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/TestSystemGC.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,46 @@
+/*
+* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*/
+
+/*
+ * @test TestSystemGC
+ * @key gc
+ * @summary Runs System.gc() with different flags.
+ * @run main/othervm TestSystemGC
+ * @run main/othervm -XX:+UseSerialGC TestSystemGC
+ * @run main/othervm -XX:+UseParNewGC TestSystemGC
+ * @run main/othervm -XX:+UseParallelGC TestSystemGC
+ * @run main/othervm -XX:+UseParallelGC -XX:-UseParallelOldGC TestSystemGC
+ * @run main/othervm -XX:+UseConcMarkSweepGC TestSystemGC
+ * @run main/othervm -XX:+UseConcMarkSweepGC -XX:+ExplicitGCInvokesConcurrent TestSystemGC
+ * @run main/othervm -XX:+UseConcMarkSweepGC -XX:+ExplicitGCInvokesConcurrent -XX:-UseParNewGC TestSystemGC
+ * @run main/othervm -XX:+UseG1GC TestSystemGC
+ * @run main/othervm -XX:+UseG1GC -XX:+ExplicitGCInvokesConcurrent TestSystemGC
+ * @run main/othervm -XX:+UseLargePages TestSystemGC
+ * @run main/othervm -XX:+UseLargePages -XX:+UseLargePagesInMetaspace TestSystemGC
+ */
+
+public class TestSystemGC {
+ public static void main(String args[]) throws Exception {
+ System.gc();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/8024804/RegisterNatives.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8024804
+ * @summary registerNatives() interface resolution should receive IAE
+ * @run main RegisterNatives
+ */
+public class RegisterNatives {
+ interface I { void registerNatives(); }
+ interface J extends I {}
+ static class B implements J { public void registerNatives() { System.out.println("B"); } }
+ public static void main(String... args) {
+ System.out.println("Regression test for JDK-8024804, crash when InterfaceMethodref resolves to Object.registerNatives\n");
+ J val = new B();
+ try {
+ val.registerNatives();
+ } catch (IllegalAccessError e) {
+ System.out.println("TEST PASSES - according to current JVM spec, IAE expected\n");
+ return;
+ }
+ System.out.println("TEST FAILS - no IAE resulted\n");
+ System.exit(1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/8026394/InterfaceObjectTest.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8026394
+ * @summary clone() and finalize() interface resolution should not receive IAE
+ * @run main InterfaceObjectTest
+ */
+interface IClone extends Cloneable {
+ void finalize() throws Throwable;
+ Object clone();
+}
+
+interface ICloneExtend extends IClone { }
+
+public class InterfaceObjectTest implements ICloneExtend {
+
+ public Object clone() {
+ System.out.println("In InterfaceObjectTest's clone() method\n");
+ return null;
+ }
+
+ public void finalize() throws Throwable {
+ try {
+ System.out.println("In InterfaceObjectTest's finalize() method\n");
+ } catch (Throwable t) {
+ throw new AssertionError(t);
+ }
+ }
+
+ public static void tryIt(ICloneExtend o1) {
+ try {
+ Object o2 = o1.clone();
+ o1.finalize();
+ } catch (Throwable t) {
+ if (t instanceof IllegalAccessError) {
+ System.out.println("TEST FAILS - IAE resulted\n");
+ System.exit(1);
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ InterfaceObjectTest o1 = new InterfaceObjectTest();
+ tryIt(o1);
+ System.out.println("TEST PASSES - no IAE resulted\n");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/CommandLine/PrintGCApplicationConcurrentTime.java Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @bug 8026041
+ * @run main/othervm -XX:+PrintGCApplicationConcurrentTime -Xcomp PrintGCApplicationConcurrentTime
+ */
+
+public class PrintGCApplicationConcurrentTime {
+
+ public static void main(String args[]) throws Exception {
+ }
+}
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolLauncher.java Thu Oct 24 09:10:35 2013 -0700
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolLauncher.java Wed Jul 05 19:19:29 2017 +0200
@@ -100,7 +100,7 @@
* @return The JDKToolLauncher instance
*/
public JDKToolLauncher addVMArg(String arg) {
- vmArgs.add("-J" + arg);
+ vmArgs.add(arg);
return this;
}
@@ -124,7 +124,10 @@
public String[] getCommand() {
List<String> command = new ArrayList<String>();
command.add(executable);
- command.addAll(vmArgs);
+ // Add -J in front of all vmArgs
+ for (String arg : vmArgs) {
+ command.add("-J" + arg);
+ }
command.addAll(toolArgs);
return command.toArray(new String[command.size()]);
}
--- a/jdk/.hgtags Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/.hgtags Wed Jul 05 19:19:29 2017 +0200
@@ -234,3 +234,4 @@
54e099776f08430d3a7f4feabd9f2ba886b55320 jdk8-b110
719befd87c7b96ae103c05730ca555227bfc0116 jdk8-b111
f002f5f3a16cca62e139cb8eed05ffaeb373587d jdk8-b112
+5b4261b4b72af53e8e178933ef6bc6c7f8cdbc60 jdk8-b113
--- a/jdk/makefiles/BuildJdk.gmk Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/makefiles/BuildJdk.gmk Wed Jul 05 19:19:29 2017 +0200
@@ -80,7 +80,11 @@
# to execute launchers.
+$(MAKE) -f GenerateClasses.gmk
-jdk: genclasses
+securityjars: genclasses securityjars-only
+securityjars-only:
+ +$(MAKE) -f CreateSecurityJars.gmk
+
+jdk: securityjars
# Now we have a complete jdk, which you can run.
# It is not yet wrapped up as an installed image.
--- a/jdk/makefiles/CompileJavaClasses.gmk Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/makefiles/CompileJavaClasses.gmk Wed Jul 05 19:19:29 2017 +0200
@@ -96,11 +96,7 @@
EXCLUDES += com/oracle/security
endif
-# In the old build, this isn't excluded on macosx, even though it probably
-# should be.
-ifneq ($(OPENJDK_TARGET_OS), macosx)
- EXFILES += WrapperGenerator.java
-endif
+EXFILES += WrapperGenerator.java
ifneq ($(OPENJDK_TARGET_OS), windows)
# Exclude Window security related files in src/share/classes
@@ -169,7 +165,11 @@
EXFILES += sun/awt/AWTCharset.java
endif
-ifneq ($(OPENJDK_TARGET_OS), macosx)
+ifeq ($(OPENJDK_TARGET_OS), macosx)
+ # exclude all X11 on Mac, we can't exclude some like below or we'll have compilation errors
+ EXCLUDES += sun/awt/X11
+else
+ # TBD: figure out how to eliminate this long list
EXFILES += sun/awt/X11/ScreenFormat.java \
sun/awt/X11/XArc.java \
sun/awt/X11/XChar2b.java \
@@ -281,6 +281,19 @@
EXCLUDES += com/apple/jobjc
endif
+# The security classes should not end up in the classes directory as that will prevent them
+# from working when running the exploded jdk image. Compile them separately to a different
+# directory from where the jars can be created.
+SECURITY_PKGS := \
+ com/oracle/security/ucrypto \
+ com/sun/crypto/provider \
+ javax/crypto \
+ sun/security/ec \
+ sun/security/internal \
+ sun/security/mscapi \
+ sun/security/pkcs11 \
+ #
+
# The exception handling of swing beaninfo
# These resources violates the convention of having code and resources together under
# $(JDK_TOPDIR)/src/.../classes directories
@@ -293,22 +306,46 @@
# space separated list.
JDK_USER_DEFINED_FILTER := $(strip $(subst $(COMMA),$(SPACE), $(JDK_FILTER)))
-$(eval $(call SetupJavaCompilation,BUILD_JDK, \
+ifeq ($(ENABLE_SJAVAC),yes)
+ # With sjavac enabled, excluded sources are not even considered for linking.
+ # Explicitly add the security sources to sourcepath for linking.
+ BUILD_JDK_SOURCEPATH:=$(patsubst %,-i$(SPACE)%.*,$(subst /,.,$(SECURITY_PKGS))) \
+ -sourcepath $(JDK_TOPDIR)/src/share/classes
+endif
+
+$(eval $(call SetupJavaCompilation,BUILD_JDK,\
+ SETUP:=GENERATE_JDKBYTECODE,\
+ SRC:=$(JDK_TOPDIR)/src/share/classes \
+ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes \
+ $(MACOSX_SRC_DIRS) \
+ $(JDK_OUTPUTDIR)/gensrc \
+ $(JDK_OUTPUTDIR)/gensrc_no_srczip \
+ $(CLOSED_SRC_DIRS),\
+ INCLUDES:=$(JDK_USER_DEFINED_FILTER),\
+ EXCLUDES:=$(EXCLUDES) $(SECURITY_PKGS),\
+ EXCLUDE_FILES:=$(EXFILES),\
+ BIN:=$(JDK_OUTPUTDIR)/classes,\
+ COPY:=$(COPY_PATTERNS),\
+ COPY_FILES:=$(COPY_FILES),\
+ HEADERS:=$(JDK_OUTPUTDIR)/gensrc_headers,\
+ ADD_JAVAC_FLAGS:=$(BUILD_JDK_SOURCEPATH)))
+
+##########################################################################################
+
+$(eval $(call SetupJavaCompilation,BUILD_SECURITY, \
SETUP := GENERATE_JDKBYTECODE, \
SRC := $(JDK_TOPDIR)/src/share/classes \
- $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes \
- $(MACOSX_SRC_DIRS) \
- $(JDK_OUTPUTDIR)/gensrc \
- $(JDK_OUTPUTDIR)/gensrc_no_srczip \
- $(CLOSED_SRC_DIRS), \
- INCLUDES := $(JDK_USER_DEFINED_FILTER), \
+ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes \
+ $(MACOSX_SRC_DIRS) \
+ $(CLOSED_SRC_DIRS), \
+ INCLUDES := $(SECURITY_PKGS), \
EXCLUDES := $(EXCLUDES), \
EXCLUDE_FILES := $(EXFILES), \
- BIN := $(JDK_OUTPUTDIR)/classes, \
- COPY := $(COPY_PATTERNS), \
- COPY_FILES := $(COPY_FILES), \
+ BIN := $(JDK_OUTPUTDIR)/classes_security, \
HEADERS := $(JDK_OUTPUTDIR)/gensrc_headers))
+$(BUILD_SECURITY): $(BUILD_JDK)
+
##########################################################################################
$(JDK_OUTPUTDIR)/classes/META-INF/services/com.sun.tools.xjc.Plugin:
@@ -393,7 +430,7 @@
##########################################################################################
-all: $(BUILD_JDK) $(BUILD_JOBJC) $(BUILD_JOBJC_HEADERS) $(COPY_EXTRA) \
+all: $(BUILD_JDK) $(BUILD_SECURITY) $(BUILD_JOBJC) $(BUILD_JOBJC_HEADERS) $(COPY_EXTRA) \
$(JDK_OUTPUTDIR)/classes/META-INF/services/com.sun.tools.xjc.Plugin \
$(BUILD_ACCESSBRIDGE_32) $(BUILD_ACCESSBRIDGE_64) \
$(BUILD_ACCESSBRIDGE_LEGACY)
--- a/jdk/makefiles/CopyFiles.gmk Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/makefiles/CopyFiles.gmk Wed Jul 05 19:19:29 2017 +0200
@@ -48,7 +48,7 @@
$(INCLUDEDIR)/%.h: $(JDK_TOPDIR)/src/share/javavm/export/%.h
$(call install-file)
-$(OPENJDK_TARGET_OS_INCLUDE)/%.h: $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/javavm/export/%.h
+$(OPENJDK_TARGET_OS_INCLUDE)/%.h: $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_EXPORT_DIR)/javavm/export/%.h
$(call install-file)
COPY_FILES = $(H_TARGET_FILES)
--- a/jdk/makefiles/CreateJars.gmk Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/makefiles/CreateJars.gmk Wed Jul 05 19:19:29 2017 +0200
@@ -102,7 +102,6 @@
# This value should exclude types destined for jars other than rt.jar and resources.jar.
# When building a Profile this value augments the profile specific exclusions
RT_JAR_EXCLUDES += \
- com/oracle/security \
com/sun/codemodel \
com/sun/crypto/provider \
com/sun/istack/internal/tools \
@@ -415,86 +414,6 @@
CHECK_COMPRESS_JAR := true))
##########################################################################################
-# Create manifest for security jars
-
-#
-# Include these extra attributes for now, should probably take out.
-#
-JCE_MANIFEST := $(IMAGES_OUTPUTDIR)/lib/_the.security.manifest.mf
-$(JCE_MANIFEST): $(MAINMANIFEST)
- $(MKDIR) -p $(@D)
- $(RM) $@ $@.tmp
- $(SED) -e "s#@@RELEASE@@#$(JDK_VERSION)#" \
- -e "s#@@COMPANY_NAME@@#$(COMPANY_NAME)#" \
- $(MAINMANIFEST) >> $@.tmp
- $(ECHO) "Extension-Name: javax.crypto" >> $@.tmp
- $(ECHO) "Implementation-Vendor-Id: com.sun" >> $@.tmp
- $(MV) $@.tmp $@
-
-##########################################################################################
-# For security and crypto jars, always build the jar, but for closed, install the prebuilt
-# signed version instead of the newly built jar. Unsigned jars are treated as intermediate
-# targets and explicitly added to the JARS list. For open, signing is not needed. See
-# SignJars.gmk for more information.
-#
-# The source for the crypto jars is not available for all licensees. The BUILD_CRYPTO
-# variable is set to no if these jars can't be built to skip that step of the build.
-# Note that for OPENJDK, the build will fail if BUILD_CRYPTO=no since then there is no
-# other way to get the jars than to build them.
-
-SUNPKCS11_JAR_DST := $(IMAGES_OUTPUTDIR)/lib/ext/sunpkcs11.jar
-SUNPKCS11_JAR_UNSIGNED := $(IMAGES_OUTPUTDIR)/unsigned/sunpkcs11.jar
-
-$(eval $(call SetupArchive,BUILD_SUNPKCS11_JAR, , \
- SRCS := $(JDK_OUTPUTDIR)/classes, \
- SUFFIXES := .class, \
- INCLUDES := sun/security/pkcs11, \
- JAR := $(SUNPKCS11_JAR_UNSIGNED), \
- MANIFEST := $(JCE_MANIFEST), \
- SKIP_METAINF := true))
-
-$(SUNPKCS11_JAR_UNSIGNED): $(JCE_MANIFEST)
-
-ifndef OPENJDK
- SUNPKCS11_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/pkcs11/sunpkcs11.jar
- $(SUNPKCS11_JAR_DST): $(SUNPKCS11_JAR_SRC)
- @$(ECHO) $(LOG_INFO) "\n>>>Installing prebuilt SunPKCS11 provider..."
- $(install-file)
-else
- $(SUNPKCS11_JAR_DST): $(SUNPKCS11_JAR_UNSIGNED)
- $(install-file)
-endif
-
-JARS += $(SUNPKCS11_JAR_UNSIGNED)
-
-##########################################################################################
-
-SUNEC_JAR_DST := $(IMAGES_OUTPUTDIR)/lib/ext/sunec.jar
-SUNEC_JAR_UNSIGNED := $(IMAGES_OUTPUTDIR)/unsigned/sunec.jar
-
-$(eval $(call SetupArchive,BUILD_SUNEC_JAR, , \
- SRCS := $(JDK_OUTPUTDIR)/classes, \
- SUFFIXES := .class, \
- INCLUDES := sun/security/ec, \
- JAR := $(SUNEC_JAR_UNSIGNED), \
- MANIFEST := $(JCE_MANIFEST), \
- SKIP_METAINF := true))
-
-$(SUNEC_JAR_UNSIGNED): $(JCE_MANIFEST)
-
-ifndef OPENJDK
- SUNEC_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/ec/sunec.jar
- $(SUNEC_JAR_DST): $(SUNEC_JAR_SRC)
- @$(ECHO) $(LOG_INFO) "\n>>>Installing prebuilt SunEC provider..."
- $(install-file)
-else
- $(SUNEC_JAR_DST): $(SUNEC_JAR_UNSIGNED)
- $(install-file)
-endif
-
-JARS += $(SUNEC_JAR_UNSIGNED)
-
-##########################################################################################
$(eval $(call SetupArchive,BUILD_SWINGBEANS_JAR, , \
SRCS := $(JDK_OUTPUTDIR)/classes, \
@@ -507,208 +426,6 @@
##########################################################################################
-SUNJCE_PROVIDER_JAR_DST := $(IMAGES_OUTPUTDIR)/lib/ext/sunjce_provider.jar
-SUNJCE_PROVIDER_JAR_UNSIGNED := $(IMAGES_OUTPUTDIR)/unsigned/sunjce_provider.jar
-
-ifneq ($(BUILD_CRYPTO), no)
- $(eval $(call SetupArchive,BUILD_SUNJCE_PROVIDER_JAR, , \
- SRCS := $(JDK_OUTPUTDIR)/classes, \
- SUFFIXES := .class, \
- INCLUDES := com/sun/crypto/provider, \
- JAR := $(SUNJCE_PROVIDER_JAR_UNSIGNED), \
- MANIFEST := $(JCE_MANIFEST), \
- SKIP_METAINF := true))
-
- $(SUNJCE_PROVIDER_JAR_UNSIGNED): $(JCE_MANIFEST)
-
- JARS += $(SUNJCE_PROVIDER_JAR_UNSIGNED)
-endif
-
-ifndef OPENJDK
- SUNJCE_PROVIDER_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/jce/sunjce_provider.jar
- $(SUNJCE_PROVIDER_JAR_DST): $(SUNJCE_PROVIDER_JAR_SRC)
- @$(ECHO) $(LOG_INFO) "\n>>>Installing prebuilt SunJCE provider..."
- $(install-file)
-else
- $(SUNJCE_PROVIDER_JAR_DST): $(SUNJCE_PROVIDER_JAR_UNSIGNED)
- $(install-file)
-endif
-
-##########################################################################################
-
-JCE_JAR_DST := $(IMAGES_OUTPUTDIR)/lib/jce.jar
-JCE_JAR_UNSIGNED := $(IMAGES_OUTPUTDIR)/unsigned/jce.jar
-
-ifneq ($(BUILD_CRYPTO), no)
- $(eval $(call SetupArchive,BUILD_JCE_JAR, , \
- SRCS := $(JDK_OUTPUTDIR)/classes, \
- SUFFIXES := .class, \
- INCLUDES := javax/crypto sun/security/internal, \
- JAR := $(JCE_JAR_UNSIGNED), \
- MANIFEST := $(JCE_MANIFEST), \
- SKIP_METAINF := true))
-
- $(JCE_JAR_UNSIGNED): $(JCE_MANIFEST)
-
- JARS += $(JCE_JAR_UNSIGNED)
-endif
-
-ifndef OPENJDK
- JCE_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/jce/jce.jar
- $(JCE_JAR_DST): $(JCE_JAR_SRC)
- @$(ECHO) $(LOG_INFO) "\n>>>Installing prebuilt jce.jar..."
- $(install-file)
-else
- $(JCE_JAR_DST): $(JCE_JAR_UNSIGNED)
- $(install-file)
-endif
-
-##########################################################################################
-
-US_EXPORT_POLICY_JAR_DST := $(IMAGES_OUTPUTDIR)/lib/security/US_export_policy.jar
-US_EXPORT_POLICY_JAR_UNSIGNED := $(IMAGES_OUTPUTDIR)/unsigned/US_export_policy.jar
-
-ifneq ($(BUILD_CRYPTO), no)
- #
- # TODO fix so that SetupArchive does not write files into SRCS
- # then we don't need this extra copying
-
- # NOTE: We currently do not place restrictions on our limited export
- # policy. This was not a typo.
- #
- US_EXPORT_POLICY_JAR_SRC_DIR := $(JDK_TOPDIR)/make/javax/crypto/policy/unlimited
- US_EXPORT_POLICY_JAR_TMP := $(IMAGES_OUTPUTDIR)/US_export_policy_jar.tmp
-
- $(US_EXPORT_POLICY_JAR_TMP)/%: $(US_EXPORT_POLICY_JAR_SRC_DIR)/%
- $(install-file)
-
- US_EXPORT_POLICY_JAR_DEPS := $(US_EXPORT_POLICY_JAR_TMP)/default_US_export.policy
-
- $(eval $(call SetupArchive,BUILD_US_EXPORT_POLICY_JAR, $(US_EXPORT_POLICY_JAR_DEPS), \
- SRCS := $(US_EXPORT_POLICY_JAR_TMP), \
- SUFFIXES := .policy, \
- JAR := $(US_EXPORT_POLICY_JAR_UNSIGNED), \
- EXTRA_MANIFEST_ATTR := Crypto-Strength: unlimited, \
- SKIP_METAINF := true))
-
- JARS += $(US_EXPORT_POLICY_JAR_UNSIGNED)
-endif
-
-ifndef OPENJDK
- $(US_EXPORT_POLICY_JAR_DST): $(JDK_TOPDIR)/make/closed/tools/crypto/jce/US_export_policy.jar
- $(ECHO) $(LOG_INFO) Copying $(@F)
- $(install-file)
-else
- $(US_EXPORT_POLICY_JAR_DST): $(US_EXPORT_POLICY_JAR_UNSIGNED)
- $(install-file)
-endif
-
-##########################################################################################
-
-LOCAL_POLICY_JAR_DST := $(IMAGES_OUTPUTDIR)/lib/security/local_policy.jar
-LOCAL_POLICY_JAR_UNSIGNED := $(IMAGES_OUTPUTDIR)/unsigned/local_policy.jar
-
-ifneq ($(BUILD_CRYPTO), no)
- #
- # TODO fix so that SetupArchive does not write files into SRCS
- # then we don't need this extra copying
- #
- LOCAL_POLICY_JAR_TMP := $(IMAGES_OUTPUTDIR)/local_policy_jar.tmp
-
- ifeq ($(UNLIMITED_CRYPTO), true)
- LOCAL_POLICY_JAR_SRC_DIR := $(JDK_TOPDIR)/make/javax/crypto/policy/unlimited
- LOCAL_POLICY_JAR_DEPS := $(LOCAL_POLICY_JAR_TMP)/default_local.policy
- LOCAL_POLICY_JAR_ATTR := Crypto-Strength: unlimited
- else
- LOCAL_POLICY_JAR_SRC_DIR := $(JDK_TOPDIR)/make/javax/crypto/policy/limited
- LOCAL_POLICY_JAR_DEPS := $(LOCAL_POLICY_JAR_TMP)/exempt_local.policy \
- $(LOCAL_POLICY_JAR_TMP)/default_local.policy
- LOCAL_POLICY_JAR_ATTR := Crypto-Strength: limited
- endif
-
- $(LOCAL_POLICY_JAR_TMP)/%: $(LOCAL_POLICY_JAR_SRC_DIR)/%
- $(install-file)
-
- $(eval $(call SetupArchive,BUILD_LOCAL_POLICY_JAR, $(LOCAL_POLICY_JAR_DEPS), \
- SRCS := $(LOCAL_POLICY_JAR_TMP), \
- SUFFIXES := .policy, \
- JAR := $(LOCAL_POLICY_JAR_UNSIGNED), \
- EXTRA_MANIFEST_ATTR := $(LOCAL_POLICY_JAR_ATTR), \
- SKIP_METAINF := true))
-
- JARS += $(LOCAL_POLICY_JAR_UNSIGNED)
-endif
-
-ifndef OPENJDK
- $(LOCAL_POLICY_JAR_DST): $(JDK_TOPDIR)/make/closed/tools/crypto/jce/local_policy.jar
- $(ECHO) $(LOG_INFO) Copying $(@F)
- $(install-file)
-else
- $(LOCAL_POLICY_JAR_DST): $(LOCAL_POLICY_JAR_UNSIGNED)
- $(install-file)
-endif
-
-##########################################################################################
-
-ifeq ($(OPENJDK_TARGET_OS), windows)
-
- SUNMSCAPI_JAR_DST := $(IMAGES_OUTPUTDIR)/lib/ext/sunmscapi.jar
- SUNMSCAPI_JAR_UNSIGNED := $(IMAGES_OUTPUTDIR)/unsigned/sunmscapi.jar
-
- $(eval $(call SetupArchive,BUILD_SUNMSCAPI_JAR, , \
- SRCS := $(JDK_OUTPUTDIR)/classes, \
- SUFFIXES := .class, \
- INCLUDES := sun/security/mscapi, \
- JAR := $(SUNMSCAPI_JAR_UNSIGNED), \
- MANIFEST := $(JCE_MANIFEST), \
- SKIP_METAINF := true))
-
- $(SUNMSCAPI_JAR_UNSIGNED): $(JCE_MANIFEST)
-
- ifndef OPENJDK
- SUNMSCAPI_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/mscapi/sunmscapi.jar
- $(SUNMSCAPI_JAR_DST): $(SUNMSCAPI_JAR_SRC)
- @$(ECHO) $(LOG_INFO) "\n>>>Installing prebuilt SunMSCAPI provider..."
- $(install-file)
- else
- $(SUNMSCAPI_JAR_DST): $(SUNMSCAPI_JAR_UNSIGNED)
- $(install-file)
- endif
-
- JARS += $(SUNMSCAPI_JAR_UNSIGNED)
-
-endif
-
-##########################################################################################
-
-ifeq ($(OPENJDK_TARGET_OS), solaris)
- ifndef OPENJDK
-
- UCRYPTO_JAR_DST := $(IMAGES_OUTPUTDIR)/lib/ext/ucrypto.jar
- UCRYPTO_JAR_UNSIGNED := $(IMAGES_OUTPUTDIR)/unsigned/ucrypto.jar
- UCRYPTO_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/ucrypto/ucrypto.jar
-
- $(eval $(call SetupArchive,BUILD_UCRYPTO_JAR, , \
- SRCS := $(JDK_OUTPUTDIR)/classes, \
- SUFFIXES := .class, \
- INCLUDES := com/oracle/security/ucrypto, \
- JAR := $(UCRYPTO_JAR_UNSIGNED), \
- MANIFEST := $(JCE_MANIFEST), \
- SKIP_METAINF := true))
-
- $(UCRYPTO_JAR_UNSIGNED): $(JCE_MANIFEST)
-
- $(UCRYPTO_JAR_DST): $(UCRYPTO_JAR_SRC)
- @$(ECHO) $(LOG_INFO) "\n>>>Installing prebuilt OracleUcrypto provider..."
- $(install-file)
-
- JARS += $(UCRYPTO_JAR_UNSIGNED)
-
- endif
-endif
-
-##########################################################################################
-
# Get the CLDRVERSION
include gensrc/GensrcCLDR.gmk
@@ -1047,6 +764,13 @@
##########################################################################################
+# This rule copies all jars from jdk/lib/... to images/lib/... to avoid having to track
+# which jars are where
+$(IMAGES_OUTPUTDIR)/lib/%: $(JDK_OUTPUTDIR)/lib/%
+ $(install-file)
+
+##########################################################################################
+
# Import nashorn.jar from nashorn dist dir.
$(IMAGES_OUTPUTDIR)/lib/ext/nashorn.jar: $(NASHORN_DIST)/nashorn.jar
$(install-file)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/makefiles/CreateSecurityJars.gmk Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,329 @@
+#
+# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+include JavaCompilation.gmk
+include Setup.gmk
+
+# The jars created in this file are required for the exploded jdk image to function and
+# cannot wait to be built in the images target.
+
+##########################################################################################
+# Create manifest for security jars
+#
+# Include these extra attributes for now, should probably take out.
+#
+MAINMANIFEST := $(JDK_TOPDIR)/make/tools/manifest.mf
+JCE_MANIFEST := $(JDK_OUTPUTDIR)/lib/_the.security.manifest.mf
+
+$(JCE_MANIFEST): $(MAINMANIFEST)
+ $(MKDIR) -p $(@D)
+ $(RM) $@ $@.tmp
+ $(SED) -e "s#@@RELEASE@@#$(JDK_VERSION)#" \
+ -e "s#@@COMPANY_NAME@@#$(COMPANY_NAME)#" \
+ $(MAINMANIFEST) >> $@.tmp
+ $(ECHO) "Extension-Name: javax.crypto" >> $@.tmp
+ $(ECHO) "Implementation-Vendor-Id: com.sun" >> $@.tmp
+ $(MV) $@.tmp $@
+
+##########################################################################################
+# For security and crypto jars, always build the jar, but for closed, install the prebuilt
+# signed version instead of the newly built jar. Unsigned jars are treated as intermediate
+# targets and explicitly added to the JARS list. For open, signing is not needed. See
+# SignJars.gmk for more information.
+#
+# The source for the crypto jars is not available for all licensees. The BUILD_CRYPTO
+# variable is set to no if these jars can't be built to skip that step of the build.
+# Note that for OPENJDK, the build will fail if BUILD_CRYPTO=no since then there is no
+# other way to get the jars than to build them.
+
+SUNPKCS11_JAR_DST := $(JDK_OUTPUTDIR)/lib/ext/sunpkcs11.jar
+SUNPKCS11_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/unsigned/sunpkcs11.jar
+
+$(eval $(call SetupArchive,BUILD_SUNPKCS11_JAR, , \
+ SRCS := $(JDK_OUTPUTDIR)/classes_security, \
+ SUFFIXES := .class, \
+ INCLUDES := sun/security/pkcs11, \
+ JAR := $(SUNPKCS11_JAR_UNSIGNED), \
+ MANIFEST := $(JCE_MANIFEST), \
+ SKIP_METAINF := true))
+
+$(SUNPKCS11_JAR_UNSIGNED): $(JCE_MANIFEST)
+
+ifndef OPENJDK
+ SUNPKCS11_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/pkcs11/sunpkcs11.jar
+ $(SUNPKCS11_JAR_DST): $(SUNPKCS11_JAR_SRC)
+ @$(ECHO) $(LOG_INFO) "\n>>>Installing prebuilt SunPKCS11 provider..."
+ $(install-file)
+else
+ $(SUNPKCS11_JAR_DST): $(SUNPKCS11_JAR_UNSIGNED)
+ $(install-file)
+endif
+
+JARS += $(SUNPKCS11_JAR_UNSIGNED) $(SUNPKCS11_JAR_DST)
+
+##########################################################################################
+
+SUNEC_JAR_DST := $(JDK_OUTPUTDIR)/lib/ext/sunec.jar
+SUNEC_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/unsigned/sunec.jar
+
+$(eval $(call SetupArchive,BUILD_SUNEC_JAR, , \
+ SRCS := $(JDK_OUTPUTDIR)/classes_security, \
+ SUFFIXES := .class, \
+ INCLUDES := sun/security/ec, \
+ JAR := $(SUNEC_JAR_UNSIGNED), \
+ MANIFEST := $(JCE_MANIFEST), \
+ SKIP_METAINF := true))
+
+$(SUNEC_JAR_UNSIGNED): $(JCE_MANIFEST)
+
+ifndef OPENJDK
+ SUNEC_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/ec/sunec.jar
+ $(SUNEC_JAR_DST): $(SUNEC_JAR_SRC)
+ @$(ECHO) $(LOG_INFO) "\n>>>Installing prebuilt SunEC provider..."
+ $(install-file)
+else
+ $(SUNEC_JAR_DST): $(SUNEC_JAR_UNSIGNED)
+ $(install-file)
+endif
+
+JARS += $(SUNEC_JAR_UNSIGNED) $(SUNEC_JAR_DST)
+
+##########################################################################################
+
+SUNJCE_PROVIDER_JAR_DST := $(JDK_OUTPUTDIR)/lib/ext/sunjce_provider.jar
+SUNJCE_PROVIDER_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/unsigned/sunjce_provider.jar
+
+ifneq ($(BUILD_CRYPTO), no)
+ $(eval $(call SetupArchive,BUILD_SUNJCE_PROVIDER_JAR, , \
+ SRCS := $(JDK_OUTPUTDIR)/classes_security, \
+ SUFFIXES := .class, \
+ INCLUDES := com/sun/crypto/provider, \
+ JAR := $(SUNJCE_PROVIDER_JAR_UNSIGNED), \
+ MANIFEST := $(JCE_MANIFEST), \
+ SKIP_METAINF := true))
+
+ $(SUNJCE_PROVIDER_JAR_UNSIGNED): $(JCE_MANIFEST)
+
+ JARS += $(SUNJCE_PROVIDER_JAR_UNSIGNED)
+endif
+
+ifndef OPENJDK
+ SUNJCE_PROVIDER_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/jce/sunjce_provider.jar
+ $(SUNJCE_PROVIDER_JAR_DST): $(SUNJCE_PROVIDER_JAR_SRC)
+ @$(ECHO) $(LOG_INFO) "\n>>>Installing prebuilt SunJCE provider..."
+ $(install-file)
+else
+ $(SUNJCE_PROVIDER_JAR_DST): $(SUNJCE_PROVIDER_JAR_UNSIGNED)
+ $(install-file)
+endif
+
+JARS += $(SUNJCE_PROVIDER_JAR_DST)
+
+##########################################################################################
+
+JCE_JAR_DST := $(JDK_OUTPUTDIR)/lib/jce.jar
+JCE_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/unsigned/jce.jar
+
+ifneq ($(BUILD_CRYPTO), no)
+ $(eval $(call SetupArchive,BUILD_JCE_JAR, , \
+ SRCS := $(JDK_OUTPUTDIR)/classes_security, \
+ SUFFIXES := .class, \
+ INCLUDES := javax/crypto sun/security/internal, \
+ JAR := $(JCE_JAR_UNSIGNED), \
+ MANIFEST := $(JCE_MANIFEST), \
+ SKIP_METAINF := true))
+
+ $(JCE_JAR_UNSIGNED): $(JCE_MANIFEST)
+
+ JARS += $(JCE_JAR_UNSIGNED)
+endif
+
+ifndef OPENJDK
+ JCE_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/jce/jce.jar
+ $(JCE_JAR_DST): $(JCE_JAR_SRC)
+ @$(ECHO) $(LOG_INFO) "\n>>>Installing prebuilt jce.jar..."
+ $(install-file)
+else
+ $(JCE_JAR_DST): $(JCE_JAR_UNSIGNED)
+ $(install-file)
+endif
+
+JARS += $(JCE_JAR_DST)
+
+##########################################################################################
+
+US_EXPORT_POLICY_JAR_DST := $(JDK_OUTPUTDIR)/lib/security/US_export_policy.jar
+US_EXPORT_POLICY_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/unsigned/US_export_policy.jar
+
+ifneq ($(BUILD_CRYPTO), no)
+ #
+ # TODO fix so that SetupArchive does not write files into SRCS
+ # then we don't need this extra copying
+ #
+ # NOTE: We currently do not place restrictions on our limited export
+ # policy. This was not a typo.
+ #
+ US_EXPORT_POLICY_JAR_SRC_DIR := $(JDK_TOPDIR)/make/javax/crypto/policy/unlimited
+ US_EXPORT_POLICY_JAR_TMP := $(JDK_OUTPUTDIR)/US_export_policy_jar.tmp
+
+ $(US_EXPORT_POLICY_JAR_TMP)/%: $(US_EXPORT_POLICY_JAR_SRC_DIR)/%
+ $(install-file)
+
+ US_EXPORT_POLICY_JAR_DEPS := $(US_EXPORT_POLICY_JAR_TMP)/default_US_export.policy
+
+ $(eval $(call SetupArchive,BUILD_US_EXPORT_POLICY_JAR, $(US_EXPORT_POLICY_JAR_DEPS), \
+ SRCS := $(US_EXPORT_POLICY_JAR_TMP), \
+ SUFFIXES := .policy, \
+ JAR := $(US_EXPORT_POLICY_JAR_UNSIGNED), \
+ EXTRA_MANIFEST_ATTR := Crypto-Strength: unlimited, \
+ SKIP_METAINF := true))
+
+ JARS += $(US_EXPORT_POLICY_JAR_UNSIGNED)
+endif
+
+ifndef OPENJDK
+ $(US_EXPORT_POLICY_JAR_DST): $(JDK_TOPDIR)/make/closed/tools/crypto/jce/US_export_policy.jar
+ $(ECHO) $(LOG_INFO) Copying $(@F)
+ $(install-file)
+else
+ $(US_EXPORT_POLICY_JAR_DST): $(US_EXPORT_POLICY_JAR_UNSIGNED)
+ $(install-file)
+endif
+
+JARS += $(US_EXPORT_POLICY_JAR_DST)
+
+##########################################################################################
+
+LOCAL_POLICY_JAR_DST := $(JDK_OUTPUTDIR)/lib/security/local_policy.jar
+LOCAL_POLICY_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/unsigned/local_policy.jar
+
+ifneq ($(BUILD_CRYPTO), no)
+ #
+ # TODO fix so that SetupArchive does not write files into SRCS
+ # then we don't need this extra copying
+ #
+ LOCAL_POLICY_JAR_TMP := $(JDK_OUTPUTDIR)/local_policy_jar.tmp
+
+ ifeq ($(UNLIMITED_CRYPTO), true)
+ LOCAL_POLICY_JAR_SRC_DIR := $(JDK_TOPDIR)/make/javax/crypto/policy/unlimited
+ LOCAL_POLICY_JAR_DEPS := $(LOCAL_POLICY_JAR_TMP)/default_local.policy
+ LOCAL_POLICY_JAR_ATTR := Crypto-Strength: unlimited
+ else
+ LOCAL_POLICY_JAR_SRC_DIR := $(JDK_TOPDIR)/make/javax/crypto/policy/limited
+ LOCAL_POLICY_JAR_DEPS := $(LOCAL_POLICY_JAR_TMP)/exempt_local.policy \
+ $(LOCAL_POLICY_JAR_TMP)/default_local.policy
+ LOCAL_POLICY_JAR_ATTR := Crypto-Strength: limited
+ endif
+
+ $(LOCAL_POLICY_JAR_TMP)/%: $(LOCAL_POLICY_JAR_SRC_DIR)/%
+ $(install-file)
+
+ $(eval $(call SetupArchive,BUILD_LOCAL_POLICY_JAR, $(LOCAL_POLICY_JAR_DEPS), \
+ SRCS := $(LOCAL_POLICY_JAR_TMP), \
+ SUFFIXES := .policy, \
+ JAR := $(LOCAL_POLICY_JAR_UNSIGNED), \
+ EXTRA_MANIFEST_ATTR := $(LOCAL_POLICY_JAR_ATTR), \
+ SKIP_METAINF := true))
+
+ JARS += $(LOCAL_POLICY_JAR_UNSIGNED)
+endif
+
+ifndef OPENJDK
+ $(LOCAL_POLICY_JAR_DST): $(JDK_TOPDIR)/make/closed/tools/crypto/jce/local_policy.jar
+ $(ECHO) $(LOG_INFO) Copying $(@F)
+ $(install-file)
+else
+ $(LOCAL_POLICY_JAR_DST): $(LOCAL_POLICY_JAR_UNSIGNED)
+ $(install-file)
+endif
+
+JARS += $(LOCAL_POLICY_JAR_DST)
+
+##########################################################################################
+
+ifeq ($(OPENJDK_TARGET_OS), windows)
+
+ SUNMSCAPI_JAR_DST := $(JDK_OUTPUTDIR)/lib/ext/sunmscapi.jar
+ SUNMSCAPI_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/unsigned/sunmscapi.jar
+
+ $(eval $(call SetupArchive,BUILD_SUNMSCAPI_JAR, , \
+ SRCS := $(JDK_OUTPUTDIR)/classes_security, \
+ SUFFIXES := .class, \
+ INCLUDES := sun/security/mscapi, \
+ JAR := $(SUNMSCAPI_JAR_UNSIGNED), \
+ MANIFEST := $(JCE_MANIFEST), \
+ SKIP_METAINF := true))
+
+ $(SUNMSCAPI_JAR_UNSIGNED): $(JCE_MANIFEST)
+
+ ifndef OPENJDK
+ SUNMSCAPI_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/mscapi/sunmscapi.jar
+ $(SUNMSCAPI_JAR_DST): $(SUNMSCAPI_JAR_SRC)
+ @$(ECHO) $(LOG_INFO) "\n>>>Installing prebuilt SunMSCAPI provider..."
+ $(install-file)
+ else
+ $(SUNMSCAPI_JAR_DST): $(SUNMSCAPI_JAR_UNSIGNED)
+ $(install-file)
+ endif
+
+ JARS += $(SUNMSCAPI_JAR_UNSIGNED) $(SUNMSCAPI_JAR_DST)
+
+endif
+
+##########################################################################################
+
+ifeq ($(OPENJDK_TARGET_OS), solaris)
+ ifndef OPENJDK
+
+ UCRYPTO_JAR_DST := $(JDK_OUTPUTDIR)/lib/ext/ucrypto.jar
+ UCRYPTO_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/unsigned/ucrypto.jar
+ UCRYPTO_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/ucrypto/ucrypto.jar
+
+ $(eval $(call SetupArchive,BUILD_UCRYPTO_JAR, , \
+ SRCS := $(JDK_OUTPUTDIR)/classes_security, \
+ SUFFIXES := .class, \
+ INCLUDES := com/oracle/security/ucrypto, \
+ JAR := $(UCRYPTO_JAR_UNSIGNED), \
+ MANIFEST := $(JCE_MANIFEST), \
+ SKIP_METAINF := true))
+
+ $(UCRYPTO_JAR_UNSIGNED): $(JCE_MANIFEST)
+
+ $(UCRYPTO_JAR_DST): $(UCRYPTO_JAR_SRC)
+ @$(ECHO) $(LOG_INFO) "\n>>>Installing prebuilt OracleUcrypto provider..."
+ $(install-file)
+
+ JARS += $(UCRYPTO_JAR_UNSIGNED) $(UCRYPTO_JAR_DST)
+
+ endif
+endif
+
+all: $(JARS)
+
+.PHONY: default all
--- a/jdk/makefiles/GenerateSources.gmk Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/makefiles/GenerateSources.gmk Wed Jul 05 19:19:29 2017 +0200
@@ -66,15 +66,17 @@
GENSRC += $(GENSRC_EXCEPTIONS)
ifneq ($(OPENJDK_TARGET_OS), windows)
-include gensrc/GensrcIcons.gmk
-GENSRC += $(GENSRC_AWT_ICONS)
+ include gensrc/GensrcIcons.gmk
+ GENSRC += $(GENSRC_AWT_ICONS)
-ifeq ($(OPENJDK_TARGET_OS), macosx)
-GENSRC += $(GENSRC_OSX_ICONS)
-endif
+ ifeq ($(OPENJDK_TARGET_OS), macosx)
+ GENSRC += $(GENSRC_OSX_ICONS)
+ endif
-include gensrc/GensrcX11Wrappers.gmk
-GENSRC += $(GENSRC_X11WRAPPERS)
+ ifneq ($(OPENJDK_TARGET_OS), macosx)
+ include gensrc/GensrcX11Wrappers.gmk
+ GENSRC += $(GENSRC_X11WRAPPERS)
+ endif
endif
include gensrc/GensrcCLDR.gmk
--- a/jdk/makefiles/Import.gmk Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/makefiles/Import.gmk Wed Jul 05 19:19:29 2017 +0200
@@ -120,11 +120,11 @@
$(eval $(call CopyDir,HOTSPOT1, $(HOTSPOT_DIST)/lib, $(JDK_OUTPUTDIR)/lib, $(HOTSPOT_IMPORT_FILES)))
ifeq ($(OPENJDK_TARGET_OS), macosx)
- JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/jre/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.dSYM) \
- $(wildcard $(HOTSPOT_DIST)/jre/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) )
+ JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/jre/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig$(SHARED_LIBRARY_SUFFIX).dSYM) \
+ $(wildcard $(HOTSPOT_DIST)/jre/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) )
else
- JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/jre/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.debuginfo) \
- $(wildcard $(HOTSPOT_DIST)/jre/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) )
+ JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/jre/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.debuginfo) \
+ $(wildcard $(HOTSPOT_DIST)/jre/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) )
endif
ifneq ($(OPENJDK_TARGET_OS), windows)
@@ -140,14 +140,14 @@
IMPORT_TARGET_FILES += $(INSTALL_LIBRARIES_HERE)/client/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
endif
endif
- ifneq ($(OPENJDK_TARGET_OS), macosx)
- ifeq ($(JVM_VARIANT_MINIMAL1), true)
- IMPORT_TARGET_FILES += $(INSTALL_LIBRARIES_HERE)/minimal/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
- ifneq (,$(JSIG_DEBUGINFO))
- IMPORT_TARGET_FILES += $(INSTALL_LIBRARIES_HERE)/minimal/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
- endif
- endif
+ ifneq ($(OPENJDK_TARGET_OS), macosx)
+ ifeq ($(JVM_VARIANT_MINIMAL1), true)
+ IMPORT_TARGET_FILES += $(INSTALL_LIBRARIES_HERE)/minimal/$(LIBRARY_PREFIX)jsig$(SHARED_LIBRARY_SUFFIX)
+ ifneq (,$(JSIG_DEBUGINFO))
+ IMPORT_TARGET_FILES += $(INSTALL_LIBRARIES_HERE)/minimal/$(foreach I,$(JSIG_DEBUGINFO),$(notdir $I))
+ endif
endif
+ endif
endif
$(INSTALL_LIBRARIES_HERE)/server/%$(SHARED_LIBRARY_SUFFIX): $(INSTALL_LIBRARIES_HERE)/%$(SHARED_LIBRARY_SUFFIX)
@@ -156,26 +156,26 @@
$(LN) -s ../$(@F) $@
ifeq ($(OPENJDK_TARGET_OS), macosx)
-$(INSTALL_LIBRARIES_HERE)/server/%.dSYM : $(INSTALL_LIBRARIES_HERE)/%.dSYM
+ $(INSTALL_LIBRARIES_HERE)/server/%.dSYM : $(INSTALL_LIBRARIES_HERE)/%.dSYM
$(MKDIR) -p $(@D)
$(RM) $@
$(LN) -s ../$(@F) $@
-$(INSTALL_LIBRARIES_HERE)/server/%.diz : $(INSTALL_LIBRARIES_HERE)/%.diz
+ $(INSTALL_LIBRARIES_HERE)/server/%.diz : $(INSTALL_LIBRARIES_HERE)/%.diz
$(MKDIR) -p $(@D)
$(RM) $@
- $(RM) $@.tmp $(basename $@).dSYM
- $(LN) -s ../$(basename $(@F)).dSYM $(basename $@).dSYM
- $(CD) $(@D) && $(ZIP) -q -y $@.tmp $(basename $(@F)).dSYM
- $(RM) $(basename $@).dSYM
+ $(RM) $@.tmp $(basename $@)$(SHARED_LIBRARY_SUFFIX).dSYM
+ $(LN) -s ../$(basename $(@F))$(SHARED_LIBRARY_SUFFIX).dSYM $(basename $@)$(SHARED_LIBRARY_SUFFIX).dSYM
+ $(CD) $(@D) && $(ZIP) -q -y $@.tmp $(basename $(@F))$(SHARED_LIBRARY_SUFFIX).dSYM
+ $(RM) $(basename $@)$(SHARED_LIBRARY_SUFFIX).dSYM
$(MV) $@.tmp $@
else
-$(INSTALL_LIBRARIES_HERE)/server/%.debuginfo: $(INSTALL_LIBRARIES_HERE)/%.debuginfo
+ $(INSTALL_LIBRARIES_HERE)/server/%.debuginfo: $(INSTALL_LIBRARIES_HERE)/%.debuginfo
$(MKDIR) -p $(@D)
$(RM) $@
$(LN) -s ../$(@F) $@
-$(INSTALL_LIBRARIES_HERE)/server/%.diz: $(INSTALL_LIBRARIES_HERE)/%.diz
+ $(INSTALL_LIBRARIES_HERE)/server/%.diz: $(INSTALL_LIBRARIES_HERE)/%.diz
$(MKDIR) -p $(@D)
$(RM) $@
$(RM) $@.tmp $(basename $@).debuginfo
@@ -191,26 +191,26 @@
$(LN) -s ../$(@F) $@
ifeq ($(OPENJDK_TARGET_OS), macosx)
-$(INSTALL_LIBRARIES_HERE)/client/%.dSYM : $(INSTALL_LIBRARIES_HERE)/%.dSYM
+ $(INSTALL_LIBRARIES_HERE)/client/%.dSYM : $(INSTALL_LIBRARIES_HERE)/%.dSYM
$(MKDIR) -p $(@D)
$(RM) $@
$(LN) -s ../$(@F) $@
-$(INSTALL_LIBRARIES_HERE)/client/%.diz : $(INSTALL_LIBRARIES_HERE)/%.diz
+ $(INSTALL_LIBRARIES_HERE)/client/%.diz : $(INSTALL_LIBRARIES_HERE)/%.diz
$(MKDIR) -p $(@D)
$(RM) $@
- $(RM) $@.tmp $(basename $@).dSYM
- $(LN) -s ../$(basename $(@F)).dSYM $(basename $@).dSYM
- $(CD) $(@D) && $(ZIP) -q -y $@.tmp $(basename $(@F)).dSYM
- $(RM) $(basename $@).dSYM
+ $(RM) $@.tmp $(basename $@)$(SHARED_LIBRARY_SUFFIX).dSYM
+ $(LN) -s ../$(basename $(@F))$(SHARED_LIBRARY_SUFFIX).dSYM $(basename $@)$(SHARED_LIBRARY_SUFFIX).dSYM
+ $(CD) $(@D) && $(ZIP) -q -y $@.tmp $(basename $(@F))$(SHARED_LIBRARY_SUFFIX).dSYM
+ $(RM) $(basename $@)$(SHARED_LIBRARY_SUFFIX).dSYM
$(MV) $@.tmp $@
else
-$(INSTALL_LIBRARIES_HERE)/client/%.debuginfo: $(INSTALL_LIBRARIES_HERE)/%.debuginfo
+ $(INSTALL_LIBRARIES_HERE)/client/%.debuginfo: $(INSTALL_LIBRARIES_HERE)/%.debuginfo
$(MKDIR) -p $(@D)
$(RM) $@
$(LN) -s ../$(@F) $@
-$(INSTALL_LIBRARIES_HERE)/client/%.diz: $(INSTALL_LIBRARIES_HERE)/%.diz
+ $(INSTALL_LIBRARIES_HERE)/client/%.diz: $(INSTALL_LIBRARIES_HERE)/%.diz
$(MKDIR) -p $(@D)
$(RM) $@
$(RM) $@.tmp $(basename $@).debuginfo
@@ -226,12 +226,12 @@
$(LN) -s ../$(@F) $@
ifneq ($(OPENJDK_TARGET_OS), macosx)
-$(INSTALL_LIBRARIES_HERE)/minimal/%.debuginfo: $(INSTALL_LIBRARIES_HERE)/%.debuginfo
+ $(INSTALL_LIBRARIES_HERE)/minimal/%.debuginfo: $(INSTALL_LIBRARIES_HERE)/%.debuginfo
$(MKDIR) -p $(@D)
$(RM) $@
$(LN) -s ../$(@F) $@
-$(INSTALL_LIBRARIES_HERE)/minimal/%.diz: $(INSTALL_LIBRARIES_HERE)/%.diz
+ $(INSTALL_LIBRARIES_HERE)/minimal/%.diz: $(INSTALL_LIBRARIES_HERE)/%.diz
$(MKDIR) -p $(@D)
$(RM) $@
$(RM) $@.tmp $(basename $@).debuginfo
--- a/jdk/makefiles/SignJars.gmk Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/makefiles/SignJars.gmk Wed Jul 05 19:19:29 2017 +0200
@@ -78,7 +78,7 @@
exit 2; \
fi
-$(JCE_OUTPUTDIR)/%: $(IMAGES_OUTPUTDIR)/unsigned/%
+$(JCE_OUTPUTDIR)/%: $(JDK_OUTPUTDIR)/unsigned/%
$(call install-file)
$(JARSIGNER) -keystore $(SIGNING_KEYSTORE) \
$@ $(SIGNING_ALIAS) < $(SIGNING_PASSPHRASE)
--- a/jdk/makefiles/Tools.gmk Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/makefiles/Tools.gmk Wed Jul 05 19:19:29 2017 +0200
@@ -32,7 +32,7 @@
$(JDK_TOPDIR)/makefiles/sun/osxapp \
$(JDK_TOPDIR)/make/tools/swing-beans
-ifneq ($(OPENJDK_TARGET_OS), windows)
+ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),)
TOOLS_SRC += $(JDK_TOPDIR)/src/solaris/classes/sun/awt/X11/generator
endif
--- a/jdk/makefiles/gensrc/GensrcX11Wrappers.gmk Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/makefiles/gensrc/GensrcX11Wrappers.gmk Wed Jul 05 19:19:29 2017 +0200
@@ -99,7 +99,7 @@
$(X_LIBS) \
-I$(JDK_OUTPUTDIR)/include \
-I$(JDK_TOPDIR)/src/share/javavm/export \
- -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/javavm/export \
+ -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_EXPORT_DIR)/javavm/export \
-I$(JDK_TOPDIR)/src/share/native/common \
-I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/common \
-I$(JDK_TOPDIR)/src/solaris/native/sun/awt \
--- a/jdk/makefiles/lib/Awt2dLibraries.gmk Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/makefiles/lib/Awt2dLibraries.gmk Wed Jul 05 19:19:29 2017 +0200
@@ -226,7 +226,7 @@
$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/windows \
$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/windows \
$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/d3d
-else
+else ifneq ($(OPENJDK_TARGET_OS), macosx)
LIBAWT_DIRS += \
$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/x11
endif
@@ -509,15 +509,7 @@
##########################################################################################
-# TODO!!
-# Even though this variable as a general name, it is
-# only used on macos, in fontpath.c, as prefix for where to find fonts.
-#
-# It's used for libawt_headless _and_ libawt_xawt
-#
-X11_PATH := /usr/X11R6
-
-ifneq ($(OPENJDK_TARGET_OS), windows)
+ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),)
ifndef BUILD_HEADLESS_ONLY
LIBAWT_XAWT_DIRS := \
@@ -532,7 +524,7 @@
$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/xawt \
LIBAWT_XAWT_CFLAGS := -DXAWT -DXAWT_HACK \
- -DX11_PATH=\"$(X11_PATH)\" -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \
+ -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \
$(CUPS_CFLAGS) \
$(foreach dir, $(LIBAWT_XAWT_DIRS), -I$(dir)) \
-I$(JDK_TOPDIR)/src/share/native/sun/java2d \
@@ -627,11 +619,6 @@
LIBAWT_XAWT_LDFLAGS += -lpthread
endif
- ifeq ($(OPENJDK_TARGET_OS), macosx)
- LIBAWT_XAWT_LDFLAGS_SUFFIX += -lpthread
- endif
-
- # On macosx, the shared library origin is set twice for this lib.
$(eval $(call SetupNativeCompilation,BUILD_LIBAWT_XAWT, \
LIBRARY := awt_xawt, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
@@ -653,10 +640,6 @@
-R/usr/dt/lib$(OPENJDK_TARGET_CPU_ISADIR) \
$(call SET_SHARED_LIBRARY_ORIGIN) \
$(call SET_SHARED_LIBRARY_ORIGIN,/..), \
- LDFLAGS_macosx := $(call SET_SHARED_LIBRARY_ORIGIN) \
- $(call SET_SHARED_LIBRARY_ORIGIN). \
- $(call SET_SHARED_LIBRARY_ORIGIN) \
- $(call SET_SHARED_LIBRARY_ORIGIN)., \
LDFLAGS_SUFFIX := $(LIBAWT_XAWT_LDFLAGS_SUFFIX), \
VERSIONINFO_RESOURCE := $(JDK_TOPDIR)/src/windows/resource/version.rc, \
RC_FLAGS := $(RC_FLAGS) \
@@ -788,6 +771,11 @@
LIBFONTMANAGER_EXCLUDE_FILES += X11FontScaler.c \
X11TextRenderer.c
LIBFONTMANAGER_OPTIMIZATION := HIGHEST
+else ifeq ($(OPENJDK_TARGET_OS), macosx)
+ LIBFONTMANAGER_EXCLUDE_FILES += X11FontScaler.c \
+ X11TextRenderer.c \
+ fontpath.c \
+ lcdglyph.c
else
LIBFONTMANAGER_EXCLUDE_FILES += fontpath.c \
lcdglyph.c
@@ -845,7 +833,7 @@
$(BUILD_LIBFONTMANAGER): $(BUILD_LIBAWT)
-ifneq (, $(findstring $(OPENJDK_TARGET_OS), solaris macosx))
+ifeq ($(OPENJDK_TARGET_OS), solaris)
$(BUILD_LIBFONTMANAGER): $(BUILD_LIBAWT_XAWT)
endif
@@ -947,22 +935,21 @@
else # OPENJDK_TARGET_OS not windows
- JAWT_LIBS :=
- ifneq ($(OPENJDK_TARGET_OS), solaris)
- JAWT_LIBS += -lawt
- endif
-
- ifndef BUILD_HEADLESS_ONLY
- JAWT_LIBS += -lawt_xawt
- else
- JAWT_LIBS += -lawt_headless
- HEADLESS_CFLAG += -DHEADLESS
- endif
-
- JAWT_FILES := jawt.c
ifeq ($(OPENJDK_TARGET_OS), macosx)
JAWT_FILES := jawt.m
JAWT_LIBS := -lawt_lwawt
+ else
+ JAWT_FILES := jawt.c
+ JAWT_LIBS :=
+ ifneq ($(OPENJDK_TARGET_OS), solaris)
+ JAWT_LIBS += -lawt
+ endif
+ ifndef BUILD_HEADLESS_ONLY
+ JAWT_LIBS += -lawt_xawt
+ else
+ JAWT_LIBS += -lawt_headless
+ HEADLESS_CFLAG += -DHEADLESS
+ endif
endif
$(eval $(call SetupNativeCompilation,BUILD_LIBJAWT, \
@@ -1094,7 +1081,8 @@
##########################################################################################
ifeq ($(BUILD_HEADLESS), true)
- ifneq ($(OPENJDK_TARGET_OS), windows)
+ # Mac and Windows only use the native AWT lib, do not build libawt_headless
+ ifeq ($(findstring $(OPENJDK_TARGET_OS), windows macosx),)
LIBAWT_HEADLESS_DIRS := $(JDK_TOPDIR)/src/share/native/sun/font \
$(JDK_TOPDIR)/src/share/native/sun/java2d/opengl \
@@ -1108,7 +1096,7 @@
endif
LIBAWT_HEADLESS_CFLAGS := -DHEADLESS=true \
- -DX11_PATH=\"$(X11_PATH)\" -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \
+ -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" \
$(CUPS_CFLAGS) \
$(X_CFLAGS) \
-I$(JDK_TOPDIR)/src/share/native/sun/java2d \
@@ -1155,16 +1143,6 @@
AccelGlyphCache.c \
CUPSfuncs.c
- ifeq ($(OPENJDK_TARGET_OS), macosx)
- LIBAWT_HEADLESS_FILES += \
- AWTFont.m \
- AWTStrike.m \
- CCharToGlyphMapper.m \
- CGGlyphImages.m \
- CGGlyphOutlines.m \
- CoreTextSupport.m
- endif
-
LIBAWT_HEADLESS_REORDER :=
ifeq ($(OPENJDK_TARGET_OS), solaris)
ifneq ($(OPENJDK_TARGET_CPU), x86_64)
@@ -1191,13 +1169,6 @@
REORDER := $(LIBAWT_HEADLESS_REORDER), \
LDFLAGS_SUFFIX_linux := -ljvm -lawt -lm $(LIBDL) -ljava, \
LDFLAGS_SUFFIX_solaris := $(LIBDL) -ljvm -lawt -lm -ljava $(LIBCXX) -lc, \
- LDFLAGS_SUFFIX_macosx := -ljvm $(LIBCXX) -lawt $(LIBDL) -ljava \
- -framework Accelerate \
- -framework ApplicationServices \
- -framework Cocoa \
- -F/System/Library/Frameworks/JavaVM.framework/Frameworks \
- -framework JavaNativeFoundation \
- -framework JavaRuntimeSupport, \
OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libawt_headless, \
DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/macosx/javavm/export/jawt_md.h Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1999, 2013 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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.
+ */
+
+#ifndef _JAVASOFT_JAWT_MD_H_
+#define _JAVASOFT_JAWT_MD_H_
+
+#include "jawt.h"
+
+#ifdef __OBJC__
+#import <QuartzCore/CALayer.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Mac OS X specific declarations for AWT native interface.
+ * See notes in jawt.h for an example of use.
+ */
+
+/*
+ * When calling JAWT_GetAWT with a JAWT version less than 1.7, you must pass this
+ * flag or you will not be able to get a valid drawing surface and JAWT_GetAWT will
+ * return false. This is to maintain compatibility with applications that used the
+ * interface with Java 6 which had multiple rendering models. This flag is not necessary
+ * when JAWT version 1.7 or greater is used as this is the only supported rendering mode.
+ *
+ * Example:
+ * JAWT awt;
+ * awt.version = JAWT_VERSION_1_4 | JAWT_MACOSX_USE_CALAYER;
+ * jboolean success = JAWT_GetAWT(env, &awt);
+ */
+#define JAWT_MACOSX_USE_CALAYER 0x80000000
+
+/*
+ * When the native Cocoa toolkit is in use, the pointer stored in
+ * JAWT_DrawingSurfaceInfo->platformInfo points to a NSObject that conforms to the
+ * JAWT_SurfaceLayers protocol. Setting the layer property of this object will cause the
+ * specified layer to be overlaid on the Components rectangle. If the window the
+ * Component belongs to has a CALayer attached to it, this layer will be accessible via
+ * the windowLayer property.
+ */
+#ifdef __OBJC__
+@protocol JAWT_SurfaceLayers
+@property (readwrite, retain) CALayer *layer;
+@property (readonly) CALayer *windowLayer;
+@end
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_JAVASOFT_JAWT_MD_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/macosx/javavm/export/jni_md.h Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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.
+ */
+
+#ifndef _JAVASOFT_JNI_MD_H_
+#define _JAVASOFT_JNI_MD_H_
+
+#define JNIEXPORT __attribute__((visibility("default")))
+#define JNIIMPORT __attribute__((visibility("default")))
+#define JNICALL
+
+typedef int jint;
+#ifdef _LP64 /* 64-bit */
+typedef long jlong;
+#else
+typedef long long jlong;
+#endif
+
+typedef signed char jbyte;
+
+#endif /* !_JAVASOFT_JNI_MD_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/macosx/javavm/export/jvm_md.h Wed Jul 05 19:19:29 2017 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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.
+ */
+
+#ifndef _JAVASOFT_JVM_MD_H_
+#define _JAVASOFT_JVM_MD_H_
+
+/*
+ * This file is currently collecting system-specific dregs for the
+ * JNI conversion, which should be sorted out later.
+ */
+
+#include <dirent.h> /* For DIR */
+#include <sys/param.h> /* For MAXPATHLEN */
+#include <unistd.h> /* For F_OK, R_OK, W_OK */
+#include <stddef.h> /* For ptrdiff_t */
+#include <stdint.h> /* For uintptr_t */
+
+#define JNI_ONLOAD_SYMBOLS {"JNI_OnLoad"}
+#define JNI_ONUNLOAD_SYMBOLS {"JNI_OnUnload"}
+
+#define JNI_LIB_PREFIX "lib"
+#define JNI_LIB_SUFFIX ".dylib"
+#define VERSIONED_JNI_LIB_NAME(NAME, VERSION) JNI_LIB_PREFIX NAME "." VERSION JNI_LIB_SUFFIX
+#define JNI_LIB_NAME(NAME) JNI_LIB_PREFIX NAME JNI_LIB_SUFFIX
+
+#define JVM_MAXPATHLEN MAXPATHLEN
+
+#define JVM_R_OK R_OK
+#define JVM_W_OK W_OK
+#define JVM_X_OK X_OK
+#define JVM_F_OK F_OK
+
+/*
+ * File I/O
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/signal.h>
+
+/* O Flags */
+
+#define JVM_O_RDONLY O_RDONLY
+#define JVM_O_WRONLY O_WRONLY
+#define JVM_O_RDWR O_RDWR
+#define JVM_O_O_APPEND O_APPEND
+#define JVM_O_EXCL O_EXCL
+#define JVM_O_CREAT O_CREAT
+#define JVM_O_DELETE 0x10000
+
+/* Signals */
+
+#define JVM_SIGINT SIGINT
+#define JVM_SIGTERM SIGTERM
+
+
+#endif /* !_JAVASOFT_JVM_MD_H_ */
--- a/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.h Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/src/macosx/native/sun/awt/AWTSurfaceLayers.h Wed Jul 05 19:19:29 2017 +0200
@@ -23,8 +23,7 @@
* questions.
*/
-// REMIND: import <jawt_md.h>
-#import <JavaVM/jawt_md.h>
+#import <jawt_md.h>
/*
* The CALayer-based rendering model returns an object conforming
--- a/jdk/src/macosx/native/sun/awt/CMenuComponent.h Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/src/macosx/native/sun/awt/CMenuComponent.h Wed Jul 05 19:19:29 2017 +0200
@@ -24,7 +24,7 @@
*/
#import <AppKit/AppKit.h>
-#import <JavaVM/jni.h>
+#import <jni.h>
@interface CMenuComponent : NSObject {
--- a/jdk/src/macosx/native/sun/awt/jawt.m Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/src/macosx/native/sun/awt/jawt.m Wed Jul 05 19:19:29 2017 +0200
@@ -25,8 +25,7 @@
#import <jawt.h>
-// REMIND: import <jawt_md.h>
-#import <JavaVM/jawt_md.h>
+#import <jawt_md.h>
#import "awt_DrawingSurface.h"
--- a/jdk/src/macosx/native/sun/font/CoreTextSupport.h Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/src/macosx/native/sun/font/CoreTextSupport.h Wed Jul 05 19:19:29 2017 +0200
@@ -24,7 +24,7 @@
*/
#import <Cocoa/Cocoa.h>
-#import <JavaVM/jni.h>
+#import <jni.h>
#import <JavaRuntimeSupport/JavaRuntimeSupport.h>
#include "AWTFont.h"
--- a/jdk/src/share/javavm/export/jawt.h Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/src/share/javavm/export/jawt.h Wed Jul 05 19:19:29 2017 +0200
@@ -154,7 +154,9 @@
/*
* Pointer to the platform-specific information. This can be safely
* cast to a JAWT_Win32DrawingSurfaceInfo on Windows or a
- * JAWT_X11DrawingSurfaceInfo on Solaris. See jawt_md.h for details.
+ * JAWT_X11DrawingSurfaceInfo on Solaris. On Mac OS X this is a
+ * pointer to a NSObject that conforms to the JAWT_SurfaceLayers
+ * protocol. See jawt_md.h for details.
*/
void* platformInfo;
/* Cached pointer to the underlying drawing surface */
--- a/jdk/src/share/native/java/lang/System.c Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/src/share/native/java/lang/System.c Wed Jul 05 19:19:29 2017 +0200
@@ -206,6 +206,11 @@
if (sprops->awt_toolkit) {
PUTPROP(props, "awt.toolkit", sprops->awt_toolkit);
}
+#ifdef MACOSX
+ if (sprops->awt_headless) {
+ PUTPROP(props, "java.awt.headless", sprops->awt_headless);
+ }
+#endif
/* os properties */
PUTPROP(props, "os.name", sprops->os_name);
--- a/jdk/src/share/native/java/lang/java_props.h Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/src/share/native/java/lang/java_props.h Wed Jul 05 19:19:29 2017 +0200
@@ -116,6 +116,8 @@
char *gopherPort;
char *exceptionList;
+
+ char *awt_headless /* java.awt.headless setting, if NULL (default) will not be set */
#endif
} java_props_t;
--- a/jdk/src/solaris/native/java/lang/java_props_macosx.c Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/src/solaris/native/java/lang/java_props_macosx.c Wed Jul 05 19:19:29 2017 +0200
@@ -105,40 +105,17 @@
}
}
-/* There are several toolkit options on Mac OS X, so we should try to
- * pick the "best" one, given what we know about the environment Java
- * is running under
- */
-
-static PreferredToolkit getPreferredToolkitFromEnv() {
- char *envVar = getenv("AWT_TOOLKIT");
- if (envVar == NULL) return unset;
-
- if (strcasecmp(envVar, "CToolkit") == 0) return CToolkit;
- if (strcasecmp(envVar, "XToolkit") == 0) return XToolkit;
- if (strcasecmp(envVar, "HToolkit") == 0) return HToolkit;
- return unset;
-}
-
-static bool isInAquaSession() {
+int isInAquaSession() {
// Is the WindowServer available?
SecuritySessionId session_id;
SessionAttributeBits session_info;
OSStatus status = SessionGetInfo(callerSecuritySession, &session_id, &session_info);
- if (status != noErr) return false;
- if (!(session_info & sessionHasGraphicAccess)) return false;
- return true;
-}
-
-PreferredToolkit getPreferredToolkit() {
- static PreferredToolkit pref = unset;
- if (pref != unset) return pref;
-
- PreferredToolkit prefFromEnv = getPreferredToolkitFromEnv();
- if (prefFromEnv != unset) return pref = prefFromEnv;
-
- if (isInAquaSession()) return pref = CToolkit;
- return pref = HToolkit;
+ if (status == noErr) {
+ if (session_info & sessionHasGraphicAccess) {
+ return 1;
+ }
+ }
+ return 0;
}
void setOSNameAndVersion(java_props_t *sprops) {
--- a/jdk/src/solaris/native/java/lang/java_props_macosx.h Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/src/solaris/native/java/lang/java_props_macosx.h Wed Jul 05 19:19:29 2017 +0200
@@ -29,10 +29,4 @@
void setOSNameAndVersion(java_props_t *sprops);
void setUserHome(java_props_t *sprops);
void setProxyProperties(java_props_t *sProps);
-
-enum PreferredToolkit_enum {
- unset = 0, CToolkit, XToolkit, HToolkit
-};
-typedef enum PreferredToolkit_enum PreferredToolkit;
-
-PreferredToolkit getPreferredToolkit();
+int isInAquaSession();
--- a/jdk/src/solaris/native/java/lang/java_props_md.c Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/src/solaris/native/java/lang/java_props_md.c Wed Jul 05 19:19:29 2017 +0200
@@ -454,40 +454,21 @@
/* patches/service packs installed */
sprops.patch_level = "unknown";
- /* Java 2D properties */
+ /* Java 2D/AWT properties */
#ifdef MACOSX
- PreferredToolkit prefToolkit = getPreferredToolkit();
- switch (prefToolkit) {
- case CToolkit:
- case HToolkit:
- sprops.graphics_env = "sun.awt.CGraphicsEnvironment";
- break;
- case XToolkit:
-#endif
+ // Always the same GraphicsEnvironment and Toolkit on Mac OS X
+ sprops.graphics_env = "sun.awt.CGraphicsEnvironment";
+ sprops.awt_toolkit = "sun.lwawt.macosx.LWCToolkit";
+
+ // check if we're in a GUI login session and set java.awt.headless=true if not
+ sprops.awt_headless = isInAquaSession() ? NULL : "true";
+#else
sprops.graphics_env = "sun.awt.X11GraphicsEnvironment";
-#ifdef MACOSX
- break;
- }
-#endif
- /* AWT properties */
#ifdef JAVASE_EMBEDDED
sprops.awt_toolkit = getEmbeddedToolkit();
if (sprops.awt_toolkit == NULL) // default as below
#endif
-#ifdef MACOSX
- switch (prefToolkit) {
- case CToolkit:
- sprops.awt_toolkit = "sun.lwawt.macosx.LWCToolkit";
- break;
- case XToolkit:
-#endif
sprops.awt_toolkit = "sun.awt.X11.XToolkit";
-#ifdef MACOSX
- break;
- default:
- sprops.awt_toolkit = "sun.awt.HToolkit";
- break;
- }
#endif
/* This is used only for debugging of font problems. */
--- a/jdk/src/solaris/native/sun/awt/fontpath.c Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/src/solaris/native/sun/awt/fontpath.c Wed Jul 05 19:19:29 2017 +0200
@@ -23,7 +23,7 @@
* questions.
*/
-#if defined(__linux__) || defined(MACOSX)
+#if defined(__linux__)
#include <string.h>
#endif /* __linux__ */
#include <stdio.h>
@@ -59,26 +59,12 @@
extern Display *awt_display;
#endif /* !HEADLESS */
-#ifdef MACOSX
-
-//
-// XXXDARWIN: Hard-code the path to Apple's fontconfig, as it is
-// not included in the dyld search path by default, and 10.4
-// does not support -rpath.
-//
-// This ignores the build time setting of ALT_FREETYPE_LIB_PATH,
-// and should be replaced with -rpath/@rpath support on 10.5 or later,
-// or via support for a the FREETYPE_LIB_PATH define.
-#define FONTCONFIG_DLL_VERSIONED X11_PATH "/lib/" VERSIONED_JNI_LIB_NAME("fontconfig", "1")
-#define FONTCONFIG_DLL X11_PATH "/lib/" JNI_LIB_NAME("fontconfig")
-#else
#define FONTCONFIG_DLL_VERSIONED VERSIONED_JNI_LIB_NAME("fontconfig", "1")
#define FONTCONFIG_DLL JNI_LIB_NAME("fontconfig")
-#endif
#define MAXFDIRS 512 /* Max number of directories that contain fonts */
-#if !defined(__linux__) && !defined(MACOSX)
+#if !defined(__linux__)
/*
* This can be set in the makefile to "/usr/X11" if so desired.
*/
@@ -128,22 +114,6 @@
NULL, /* terminates the list */
};
-#elif MACOSX
-static char *full_MACOSX_X11FontPath[] = {
- X11_PATH "/lib/X11/fonts/TrueType",
- X11_PATH "/lib/X11/fonts/truetype",
- X11_PATH "/lib/X11/fonts/tt",
- X11_PATH "/lib/X11/fonts/TTF",
- X11_PATH "/lib/X11/fonts/OTF",
- PACKAGE_PATH "/share/fonts/TrueType",
- PACKAGE_PATH "/share/fonts/truetype",
- PACKAGE_PATH "/share/fonts/tt",
- PACKAGE_PATH "/share/fonts/TTF",
- PACKAGE_PATH "/share/fonts/OTF",
- X11_PATH "/lib/X11/fonts/Type1",
- PACKAGE_PATH "/share/fonts/Type1",
- NULL, /* terminates the list */
-};
#else /* __linux */
/* All the known interesting locations we have discovered on
* various flavors of Linux
@@ -400,7 +370,7 @@
#endif /* !HEADLESS */
-#if defined(__linux__) || defined(MACOSX)
+#if defined(__linux__)
/* from awt_LoadLibrary.c */
JNIEXPORT jboolean JNICALL AWTIsHeadless();
#endif
@@ -527,8 +497,6 @@
#if defined(__linux__)
knowndirs = fullLinuxFontPath;
-#elif defined(MACOSX)
- knowndirs = full_MACOSX_X11FontPath;
#else /* IF SOLARIS */
knowndirs = fullSolarisFontPath;
#endif
@@ -539,7 +507,7 @@
* be initialised.
*/
#ifndef HEADLESS
-#if defined(__linux__) || defined(MACOSX)
+#if defined(__linux__)
/* There's no headless build on linux ... */
if (!AWTIsHeadless()) { /* .. so need to call a function to check */
#endif
@@ -555,7 +523,7 @@
x11dirs = getX11FontPath();
}
AWT_UNLOCK();
-#if defined(__linux__) || defined(MACOSX)
+#if defined(__linux__)
}
#endif
#endif /* !HEADLESS */
--- a/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh Thu Oct 24 09:10:35 2013 -0700
+++ b/jdk/test/java/awt/Toolkit/Headless/WrappedToolkitTest/WrappedToolkitTest.sh Wed Jul 05 19:19:29 2017 +0200
@@ -77,6 +77,12 @@
FILESEP="\\"
;;
+ Darwin)
+ VAR="Lets not forget about Mac"
+ DEFAULT_JDK=$(/usr/libexec/java_home)
+ FILESEP="/"
+ ;;
+
# catch all other OSs
* )
echo "Unrecognized system! $OS"
@@ -171,6 +177,22 @@
fi
;;
+ Darwin)
+ ${TESTJAVA}/bin/java -Djava.awt.headless=true \
+ TestWrapped sun.lwawt.macosx.LWCToolkit
+ status=$?
+ if [ ! $status -eq "0" ]; then
+ fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.lwawt.macosx.LWCToolkit";
+ fi
+ ${TESTJAVA}/bin/java -Djava.awt.headless=true \
+ -Dawt.toolkit=sun.lwawt.macosx.LWCToolkit \
+ TestWrapped sun.lwawt.macosx.LWCToolkit
+ status=$?
+ if [ ! $status -eq "0" ]; then
+ fail "Test FAILED: toolkit wrapped into HeadlessToolkit is not an instance of sun.lwawt.macosx.LWCToolkit";
+ fi
+ ;;
+
esac
pass "All the tests are PASSED";
--- a/nashorn/.hgtags Thu Oct 24 09:10:35 2013 -0700
+++ b/nashorn/.hgtags Wed Jul 05 19:19:29 2017 +0200
@@ -222,3 +222,4 @@
d49a8c2173f5f90c9a39cc4af8e03cfa8f35ee4c jdk8-b110
75fd3486e584f20475c064a2cd4d01ac6406a511 jdk8-b111
6a4fdb3bb4e34af4c5bb8db467bb01e13b1a7e31 jdk8-b112
+676cd7bf5e092356f7ee2116c8cf88cdc12377c7 jdk8-b113