Merge
This commit is contained in:
commit
8936d472bd
1
.hgtags
1
.hgtags
@ -198,3 +198,4 @@ fe94b40ffd9390f6cffcdf51c0389b0e6dde0c13 jdk8-b73
|
|||||||
f627eff819628822a0777af8062244352f2a29cf jdk8-b74
|
f627eff819628822a0777af8062244352f2a29cf jdk8-b74
|
||||||
f1478a6d25fddd311a84dcbfac50824cc1858bdd jdk8-b75
|
f1478a6d25fddd311a84dcbfac50824cc1858bdd jdk8-b75
|
||||||
f407160c280d1c5b00d314c535441ac26f195fee jdk8-b76
|
f407160c280d1c5b00d314c535441ac26f195fee jdk8-b76
|
||||||
|
d17eb2e13e362085e866d46235314c50cc4661cc jdk8-b77
|
||||||
|
@ -198,3 +198,4 @@ c1be681d80a1f1c848dc671d664fccb19e046a12 jdk8-b72
|
|||||||
b43aa5bd8ca5c8121336495382d35ecfa7a71536 jdk8-b74
|
b43aa5bd8ca5c8121336495382d35ecfa7a71536 jdk8-b74
|
||||||
2a713921952cbd77a1e699626976cb6cdfe3e57e jdk8-b75
|
2a713921952cbd77a1e699626976cb6cdfe3e57e jdk8-b75
|
||||||
278af9fc67e7eba2884936b49ec07345f423aabb jdk8-b76
|
278af9fc67e7eba2884936b49ec07345f423aabb jdk8-b76
|
||||||
|
3933eebc659d58c597aa8cb4b3e58f2250ce3e1a jdk8-b77
|
||||||
|
@ -96,6 +96,7 @@ help:
|
|||||||
$(info . make all # Compile everything, all repos and images)
|
$(info . make all # Compile everything, all repos and images)
|
||||||
$(info . make images # Create complete j2sdk and j2re images)
|
$(info . make images # Create complete j2sdk and j2re images)
|
||||||
$(info . make overlay-images # Create limited images for sparc 64 bit platforms)
|
$(info . make overlay-images # Create limited images for sparc 64 bit platforms)
|
||||||
|
$(info . make profiles # Create complete j2re compact profile images)
|
||||||
$(info . make bootcycle-images # Build images twice, second time with newly build JDK)
|
$(info . make bootcycle-images # Build images twice, second time with newly build JDK)
|
||||||
$(info . make install # Install the generated images locally)
|
$(info . make install # Install the generated images locally)
|
||||||
$(info . make clean # Remove all files generated by make, but not those)
|
$(info . make clean # Remove all files generated by make, but not those)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -282,6 +282,9 @@ X_CFLAGS:=@X_CFLAGS@
|
|||||||
X_LIBS:=@X_LIBS@
|
X_LIBS:=@X_LIBS@
|
||||||
OPENWIN_HOME:=@OPENWIN_HOME@
|
OPENWIN_HOME:=@OPENWIN_HOME@
|
||||||
|
|
||||||
|
# The lowest required version of macosx to enforce compatiblity for
|
||||||
|
MACOSX_REQUIRED_VERSION=@MACOSX_REQUIRED_VERSION@
|
||||||
|
|
||||||
# There are two types: CC or CL
|
# There are two types: CC or CL
|
||||||
# CC is gcc and others behaving reasonably similar.
|
# CC is gcc and others behaving reasonably similar.
|
||||||
# CL is cl.exe only.
|
# CL is cl.exe only.
|
||||||
|
@ -876,6 +876,10 @@ if test "x$OPENJDK_TARGET_OS" = xsolaris; then
|
|||||||
fi
|
fi
|
||||||
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
|
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
|
||||||
CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DMACOSX -D_ALLBSD_SOURCE"
|
CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DMACOSX -D_ALLBSD_SOURCE"
|
||||||
|
# Adding these macros will make it an error to link to mac APIs newer than OS version 10.7
|
||||||
|
MACOSX_REQUIRED_VERSION=1070
|
||||||
|
AC_SUBST(MACOSX_REQUIRED_VERSION)
|
||||||
|
CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(MACOSX_REQUIRED_VERSION) -DMAC_OS_X_VERSION_MIN_REQUIRED=\$(MACOSX_REQUIRED_VERSION)"
|
||||||
fi
|
fi
|
||||||
if test "x$OPENJDK_TARGET_OS" = xbsd; then
|
if test "x$OPENJDK_TARGET_OS" = xbsd; then
|
||||||
CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DBSD -D_ALLBSD_SOURCE"
|
CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DBSD -D_ALLBSD_SOURCE"
|
||||||
|
@ -64,33 +64,33 @@ rm -f -r ${tmp}
|
|||||||
mkdir -p ${tmp}
|
mkdir -p ${tmp}
|
||||||
|
|
||||||
safe_interrupt () {
|
safe_interrupt () {
|
||||||
if [ -d ${tmp} ]; then
|
if [ -d ${tmp} ]; then
|
||||||
if [ "`ls ${tmp}`" != "" ]; then
|
if [ "`ls ${tmp}/*.pid`" != "" ]; then
|
||||||
echo "Waiting for processes ( `cat ${tmp}/* | tr '\n' ' '`) to terminate nicely!"
|
echo "Waiting for processes ( `cat ${tmp}/*.pid | tr '\n' ' '`) to terminate nicely!"
|
||||||
sleep 1
|
sleep 1
|
||||||
# Pipe stderr to dev/null to silence kill, that complains when trying to kill
|
# Pipe stderr to dev/null to silence kill, that complains when trying to kill
|
||||||
# a subprocess that has already exited.
|
# a subprocess that has already exited.
|
||||||
kill -TERM `cat ${tmp}/* | tr '\n' ' '` 2> /dev/null
|
kill -TERM `cat ${tmp}/*.pid | tr '\n' ' '` 2> /dev/null
|
||||||
wait
|
wait
|
||||||
echo Interrupt complete!
|
echo Interrupt complete!
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
rm -f -r ${tmp}
|
rm -f -r ${tmp}
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
nice_exit () {
|
nice_exit () {
|
||||||
if [ -d ${tmp} ]; then
|
if [ -d ${tmp} ]; then
|
||||||
if [ "`ls ${tmp}`" != "" ]; then
|
if [ "`ls ${tmp}`" != "" ]; then
|
||||||
wait
|
wait
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
rm -f -r ${tmp}
|
rm -f -r ${tmp}
|
||||||
}
|
}
|
||||||
|
|
||||||
trap 'safe_interrupt' INT QUIT
|
trap 'safe_interrupt' INT QUIT
|
||||||
trap 'nice_exit' EXIT
|
trap 'nice_exit' EXIT
|
||||||
|
|
||||||
# Only look in specific locations for possible forests (avoids long searches)
|
# Only look in specific locations for possible forests (avoids long searches)
|
||||||
pull_default=""
|
pull_default=""
|
||||||
repos=""
|
repos=""
|
||||||
@ -172,14 +172,26 @@ for i in ${repos} ${repos_extra} ; do
|
|||||||
if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then
|
if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then
|
||||||
pull_newrepo="`echo ${pull_base}/${i} | sed -e 's@\([^:]/\)//*@\1@g'`"
|
pull_newrepo="`echo ${pull_base}/${i} | sed -e 's@\([^:]/\)//*@\1@g'`"
|
||||||
echo ${hg} clone ${pull_newrepo} ${i}
|
echo ${hg} clone ${pull_newrepo} ${i}
|
||||||
${hg} clone ${pull_newrepo} ${i} &
|
path="`dirname ${i}`"
|
||||||
|
if [ "${path}" != "." ] ; then
|
||||||
|
times=0
|
||||||
|
while [ ! -d "${path}" ] ## nested repo, ensure containing dir exists
|
||||||
|
do
|
||||||
|
times=`expr ${times} '+' 1`
|
||||||
|
if [ `expr ${times} '%' 10` -eq 0 ] ; then
|
||||||
|
echo ${path} still not created, waiting...
|
||||||
|
fi
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
(${hg} clone ${pull_newrepo} ${i}; echo "$?" > ${tmp}/${repopidfile}.pid.rc )&
|
||||||
else
|
else
|
||||||
echo "cd ${i} && ${hg} $*"
|
echo "cd ${i} && ${hg} $*"
|
||||||
cd ${i} && ${hg} "$@" &
|
cd ${i} && (${hg} "$@"; echo "$?" > ${tmp}/${repopidfile}.pid.rc )&
|
||||||
fi
|
fi
|
||||||
echo $! > ${tmp}/${repopidfile}.pid
|
echo $! > ${tmp}/${repopidfile}.pid
|
||||||
) 2>&1 | sed -e "s@^@${reponame}: @") &
|
) 2>&1 | sed -e "s@^@${reponame}: @") &
|
||||||
|
|
||||||
if [ `expr ${n} '%' ${at_a_time}` -eq 0 ] ; then
|
if [ `expr ${n} '%' ${at_a_time}` -eq 0 ] ; then
|
||||||
sleep 2
|
sleep 2
|
||||||
echo Waiting 5 secs before spawning next background command.
|
echo Waiting 5 secs before spawning next background command.
|
||||||
@ -189,6 +201,15 @@ done
|
|||||||
# Wait for all hg commands to complete
|
# Wait for all hg commands to complete
|
||||||
wait
|
wait
|
||||||
|
|
||||||
# Terminate with exit 0 all the time (hard to know when to say "failed")
|
# Terminate with exit 0 only if all subprocesses were successful
|
||||||
exit 0
|
ec=0
|
||||||
|
if [ -d ${tmp} ]; then
|
||||||
|
for rc in ${tmp}/*.pid.rc ; do
|
||||||
|
exit_code=`cat ${rc} | tr -d ' \n\r'`
|
||||||
|
if [ "${exit_code}" != "0" ] ; then
|
||||||
|
echo "WARNING: ${rc} exited abnormally."
|
||||||
|
ec=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
exit ${ec}
|
||||||
|
@ -129,7 +129,9 @@ demos-only: start-make
|
|||||||
@($(CD) $(JDK_TOPDIR)/makefiles && $(BUILD_LOG_WRAPPER) $(MAKE) $(MAKE_ARGS) -f BuildJdk.gmk demos)
|
@($(CD) $(JDK_TOPDIR)/makefiles && $(BUILD_LOG_WRAPPER) $(MAKE) $(MAKE_ARGS) -f BuildJdk.gmk demos)
|
||||||
@$(call TargetExit)
|
@$(call TargetExit)
|
||||||
|
|
||||||
images: source-tips demos images-only
|
# Note: This double-colon rule is intentional, to support
|
||||||
|
# custom make file integration.
|
||||||
|
images:: source-tips demos images-only
|
||||||
images-only: start-make
|
images-only: start-make
|
||||||
@$(call TargetEnter)
|
@$(call TargetEnter)
|
||||||
@($(CD) $(JDK_TOPDIR)/makefiles && $(BUILD_LOG_WRAPPER) $(MAKE) $(MAKE_ARGS) -f BuildJdk.gmk images)
|
@($(CD) $(JDK_TOPDIR)/makefiles && $(BUILD_LOG_WRAPPER) $(MAKE) $(MAKE_ARGS) -f BuildJdk.gmk images)
|
||||||
@ -141,6 +143,17 @@ overlay-images-only: start-make
|
|||||||
@($(CD) $(JDK_TOPDIR)/makefiles && $(BUILD_LOG_WRAPPER) $(MAKE) $(MAKE_ARGS) -f BuildJdk.gmk overlay-images)
|
@($(CD) $(JDK_TOPDIR)/makefiles && $(BUILD_LOG_WRAPPER) $(MAKE) $(MAKE_ARGS) -f BuildJdk.gmk overlay-images)
|
||||||
@$(call TargetExit)
|
@$(call TargetExit)
|
||||||
|
|
||||||
|
profiles: profiles-oscheck source-tips jdk hotspot profiles-only
|
||||||
|
profiles-only: start-make
|
||||||
|
@$(call TargetEnter)
|
||||||
|
@($(CD) $(JDK_TOPDIR)/makefiles && $(BUILD_LOG_WRAPPER) $(MAKE) $(MAKE_ARGS) -f BuildJdk.gmk profiles)
|
||||||
|
@$(call TargetExit)
|
||||||
|
|
||||||
|
profiles-oscheck:
|
||||||
|
ifneq ($(OPENJDK_TARGET_OS), linux)
|
||||||
|
@echo "Error: The Java SE 8 Compact Profiles are only implemented for Linux at this time" && exit 1
|
||||||
|
endif
|
||||||
|
|
||||||
install: images install-only
|
install: images install-only
|
||||||
install-only: start-make
|
install-only: start-make
|
||||||
@$(call TargetEnter)
|
@$(call TargetEnter)
|
||||||
@ -167,7 +180,7 @@ bootcycle-images:
|
|||||||
|
|
||||||
test: start-make
|
test: start-make
|
||||||
@$(call TargetEnter)
|
@$(call TargetEnter)
|
||||||
@($(CD) $(SRC_ROOT)/test && $(BUILD_LOG_WRAPPER) $(MAKE) MAKEFLAGS= -j1 PRODUCT_HOME=$(OUTPUT_ROOT)/jdk JPRT_JAVA_HOME=$(OUTPUT_ROOT)/jdk ALT_OUTPUTDIR=$(OUTPUT_ROOT) $(TEST)) || true
|
@($(CD) $(SRC_ROOT)/test && $(BUILD_LOG_WRAPPER) $(MAKE) -j1 -k MAKEFLAGS= PRODUCT_HOME=$(OUTPUT_ROOT)/jdk JPRT_JAVA_HOME=$(OUTPUT_ROOT)/jdk ALT_OUTPUTDIR=$(OUTPUT_ROOT) $(TEST)) || true
|
||||||
@$(call TargetExit)
|
@$(call TargetExit)
|
||||||
|
|
||||||
# Stores the tips for each repository. This file is be used when constructing the jdk image and can be
|
# Stores the tips for each repository. This file is be used when constructing the jdk image and can be
|
||||||
@ -224,5 +237,6 @@ clean-docs:
|
|||||||
.PHONY: langtools-only corba-only jaxp-only jaxws-only hotspot-only jdk-only images-only overlay-images-only install-only
|
.PHONY: langtools-only corba-only jaxp-only jaxws-only hotspot-only jdk-only images-only overlay-images-only install-only
|
||||||
.PHONY: all test clean dist-clean bootcycle-images start-make
|
.PHONY: all test clean dist-clean bootcycle-images start-make
|
||||||
.PHONY: clean-langtools clean-corba clean-jaxp clean-jaxws clean-hotspot clean-jdk clean-images clean-overlay-images clean-bootcycle-build
|
.PHONY: clean-langtools clean-corba clean-jaxp clean-jaxws clean-hotspot clean-jdk clean-images clean-overlay-images clean-bootcycle-build
|
||||||
|
.PHONY: profiles profiles-only profiles-oscheck
|
||||||
|
|
||||||
FRC: # Force target
|
FRC: # Force target
|
||||||
|
@ -128,9 +128,9 @@ CORE_PKGS = \
|
|||||||
java.text \
|
java.text \
|
||||||
java.text.spi \
|
java.text.spi \
|
||||||
java.time \
|
java.time \
|
||||||
java.time.temporal \
|
java.time.chrono \
|
||||||
java.time.calendar \
|
|
||||||
java.time.format \
|
java.time.format \
|
||||||
|
java.time.temporal \
|
||||||
java.time.zone \
|
java.time.zone \
|
||||||
java.util \
|
java.util \
|
||||||
java.util.concurrent \
|
java.util.concurrent \
|
||||||
|
@ -267,6 +267,7 @@ COMMON_JAVADOCFLAGS = \
|
|||||||
-use \
|
-use \
|
||||||
-keywords \
|
-keywords \
|
||||||
-Xdoclint:none \
|
-Xdoclint:none \
|
||||||
|
-Xprofilespath $(JDK_TOPDIR)/makefiles/profile-rtjar-includes.txt \
|
||||||
$(ADDITIONAL_JAVADOCFLAGS)
|
$(ADDITIONAL_JAVADOCFLAGS)
|
||||||
|
|
||||||
ifdef OPENJDK
|
ifdef OPENJDK
|
||||||
|
@ -198,3 +198,4 @@ cb40427f47145b01b7e53c3e02b38ff7625efbda jdk8-b72
|
|||||||
2132845cf5f717ff5c240a2431c0c0e03e66e3a5 jdk8-b74
|
2132845cf5f717ff5c240a2431c0c0e03e66e3a5 jdk8-b74
|
||||||
d4e68ce17795601017ac2f952baad7272942c36e jdk8-b75
|
d4e68ce17795601017ac2f952baad7272942c36e jdk8-b75
|
||||||
58be6ca3c0603882a1ec478724e337aac85e0da0 jdk8-b76
|
58be6ca3c0603882a1ec478724e337aac85e0da0 jdk8-b76
|
||||||
|
35684a40c5845782324dbcc9ac8969528020ff61 jdk8-b77
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
# Get clones of all nested repositories
|
# Get clones of all nested repositories
|
||||||
sh ./common/bin/hgforest.sh clone "$@"
|
sh ./common/bin/hgforest.sh clone "$@" || exit 1
|
||||||
|
|
||||||
# Update all existing repositories to the latest sources
|
# Update all existing repositories to the latest sources
|
||||||
sh ./common/bin/hgforest.sh pull -u
|
sh ./common/bin/hgforest.sh pull -u
|
||||||
|
@ -314,3 +314,5 @@ b4391649e91ea8d37f66317a03d6d2573a93d10d hs25-b17
|
|||||||
6778d0b1659323a506ca47600ca29a9d9f8b383d jdk8-b75
|
6778d0b1659323a506ca47600ca29a9d9f8b383d jdk8-b75
|
||||||
20b605466ccb1b3725eb25314d9e8782199630c5 jdk8-b76
|
20b605466ccb1b3725eb25314d9e8782199630c5 jdk8-b76
|
||||||
412d722168bc23f8e6d98995202728678561417f hs25-b18
|
412d722168bc23f8e6d98995202728678561417f hs25-b18
|
||||||
|
cdb46031e7184d37301288f5719121a63c7054b5 jdk8-b77
|
||||||
|
9f19f4a7d48a4ebe7f616b6068971ea5f8b075fa hs25-b19
|
||||||
|
@ -97,7 +97,8 @@ static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) {
|
|||||||
* Method: init0
|
* Method: init0
|
||||||
* Signature: ()V
|
* Signature: ()V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) {
|
JNIEXPORT void JNICALL
|
||||||
|
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) {
|
||||||
symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J");
|
symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J");
|
||||||
taskID = (*env)->GetFieldID(env, cls, "task", "J");
|
taskID = (*env)->GetFieldID(env, cls, "task", "J");
|
||||||
CHECK_EXCEPTION;
|
CHECK_EXCEPTION;
|
||||||
@ -108,7 +109,11 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(
|
|||||||
* Method: lookupByName0
|
* Method: lookupByName0
|
||||||
* Signature: (Ljava/lang/String;Ljava/lang/String;)J
|
* Signature: (Ljava/lang/String;Ljava/lang/String;)J
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
|
JNIEXPORT jlong JNICALL
|
||||||
|
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(
|
||||||
|
JNIEnv *env, jobject this_obj,
|
||||||
|
jstring objectName, jstring symbolName)
|
||||||
|
{
|
||||||
jlong address = 0;
|
jlong address = 0;
|
||||||
|
|
||||||
JNF_COCOA_ENTER(env);
|
JNF_COCOA_ENTER(env);
|
||||||
@ -137,7 +142,11 @@ JNF_COCOA_EXIT(env);
|
|||||||
* Method: readBytesFromProcess0
|
* Method: readBytesFromProcess0
|
||||||
* Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
|
* Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult;
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) {
|
JNIEXPORT jbyteArray JNICALL
|
||||||
|
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(
|
||||||
|
JNIEnv *env, jobject this_obj,
|
||||||
|
jlong addr, jlong numBytes)
|
||||||
|
{
|
||||||
if (debug) printf("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes);
|
if (debug) printf("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes);
|
||||||
|
|
||||||
// must allocate storage instead of using former parameter buf
|
// must allocate storage instead of using former parameter buf
|
||||||
@ -209,12 +218,74 @@ JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_
|
|||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal
|
* Lookup the thread_t that corresponds to the given thread_id.
|
||||||
* Method: getThreadIntegerRegisterSet0
|
* The thread_id should be the result from calling thread_info() with THREAD_IDENTIFIER_INFO
|
||||||
* Signature: (I)[J
|
* and reading the m_ident_info.thread_id returned.
|
||||||
|
* The returned thread_t is the mach send right to the kernel port for the corresponding thread.
|
||||||
|
*
|
||||||
|
* We cannot simply use the OSThread._thread_id field in the JVM. This is set to ::mach_thread_self()
|
||||||
|
* in the VM, but that thread port is not valid for a remote debugger to access the thread.
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(JNIEnv *env, jobject this_obj, jint lwp_id) {
|
thread_t
|
||||||
|
lookupThreadFromThreadId(task_t task, jlong thread_id) {
|
||||||
|
if (debug) {
|
||||||
|
printf("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_array_t thread_list = NULL;
|
||||||
|
mach_msg_type_number_t thread_list_count = 0;
|
||||||
|
thread_t result_thread = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// get the list of all the send rights
|
||||||
|
kern_return_t result = task_threads(task, &thread_list, &thread_list_count);
|
||||||
|
if (result != KERN_SUCCESS) {
|
||||||
|
if (debug) {
|
||||||
|
printf("task_threads returned 0x%x\n", result);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0 ; i < thread_list_count; i++) {
|
||||||
|
thread_identifier_info_data_t m_ident_info;
|
||||||
|
mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
|
||||||
|
|
||||||
|
// get the THREAD_IDENTIFIER_INFO for the send right
|
||||||
|
result = thread_info(thread_list[i], THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count);
|
||||||
|
if (result != KERN_SUCCESS) {
|
||||||
|
if (debug) {
|
||||||
|
printf("thread_info returned 0x%x\n", result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this is the one we're looking for, return the send right
|
||||||
|
if (thread_id == m_ident_info.thread_id)
|
||||||
|
{
|
||||||
|
result_thread = thread_list[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (thread_t));
|
||||||
|
vm_deallocate(mach_task_self(), (vm_address_t) thread_list, thread_list_count);
|
||||||
|
|
||||||
|
return result_thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||||
|
* Method: getThreadIntegerRegisterSet0
|
||||||
|
* Signature: (J)[J
|
||||||
|
*/
|
||||||
|
JNIEXPORT jlongArray JNICALL
|
||||||
|
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(
|
||||||
|
JNIEnv *env, jobject this_obj,
|
||||||
|
jlong thread_id)
|
||||||
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
printf("getThreadRegisterSet0 called\n");
|
printf("getThreadRegisterSet0 called\n");
|
||||||
|
|
||||||
@ -226,8 +297,9 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_
|
|||||||
int i;
|
int i;
|
||||||
jlongArray registerArray;
|
jlongArray registerArray;
|
||||||
jlong *primitiveArray;
|
jlong *primitiveArray;
|
||||||
|
task_t gTask = getTask(env, this_obj);
|
||||||
|
|
||||||
tid = lwp_id;
|
tid = lookupThreadFromThreadId(gTask, thread_id);
|
||||||
|
|
||||||
result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count);
|
result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count);
|
||||||
|
|
||||||
@ -328,19 +400,21 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal
|
* Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
|
||||||
* Method: translateTID0
|
* Method: translateTID0
|
||||||
* Signature: (I)I
|
* Signature: (I)I
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jint JNICALL
|
JNIEXPORT jint JNICALL
|
||||||
Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(JNIEnv *env, jobject this_obj, jint tid) {
|
Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(
|
||||||
|
JNIEnv *env, jobject this_obj, jint tid)
|
||||||
|
{
|
||||||
if (debug)
|
if (debug)
|
||||||
printf("translateTID0 called on tid = 0x%x\n", (int)tid);
|
printf("translateTID0 called on tid = 0x%x\n", (int)tid);
|
||||||
|
|
||||||
kern_return_t result;
|
kern_return_t result;
|
||||||
thread_t foreign_tid, usable_tid;
|
thread_t foreign_tid, usable_tid;
|
||||||
mach_msg_type_name_t type;
|
mach_msg_type_name_t type;
|
||||||
|
|
||||||
foreign_tid = tid;
|
foreign_tid = tid;
|
||||||
|
|
||||||
task_t gTask = getTask(env, this_obj);
|
task_t gTask = getTask(env, this_obj);
|
||||||
@ -361,7 +435,10 @@ Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(JNIEnv *e
|
|||||||
* Method: attach0
|
* Method: attach0
|
||||||
* Signature: (I)V
|
* Signature: (I)V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(JNIEnv *env, jobject this_obj, jint jpid) {
|
JNIEXPORT void JNICALL
|
||||||
|
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(
|
||||||
|
JNIEnv *env, jobject this_obj, jint jpid)
|
||||||
|
{
|
||||||
JNF_COCOA_ENTER(env);
|
JNF_COCOA_ENTER(env);
|
||||||
if (getenv("JAVA_SAPROC_DEBUG") != NULL)
|
if (getenv("JAVA_SAPROC_DEBUG") != NULL)
|
||||||
debug = JNI_TRUE;
|
debug = JNI_TRUE;
|
||||||
@ -401,7 +478,10 @@ JNF_COCOA_EXIT(env);
|
|||||||
* Method: detach0
|
* Method: detach0
|
||||||
* Signature: ()V
|
* Signature: ()V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(JNIEnv *env, jobject this_obj) {
|
JNIEXPORT void JNICALL
|
||||||
|
Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(
|
||||||
|
JNIEnv *env, jobject this_obj)
|
||||||
|
{
|
||||||
JNF_COCOA_ENTER(env);
|
JNF_COCOA_ENTER(env);
|
||||||
if (debug) printf("detach0 called\n");
|
if (debug) printf("detach0 called\n");
|
||||||
|
|
||||||
@ -419,10 +499,13 @@ JNF_COCOA_EXIT(env);
|
|||||||
* Method: load_library
|
* Method: load_library
|
||||||
* Signature: (Ljava/lang/String;)L
|
* Signature: (Ljava/lang/String;)L
|
||||||
*/
|
*/
|
||||||
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIEnv * env,
|
JNIEXPORT jlong JNICALL
|
||||||
jclass disclass,
|
Java_sun_jvm_hotspot_asm_Disassembler_load_1library(
|
||||||
jstring jrepath_s,
|
JNIEnv * env,
|
||||||
jstring libname_s) {
|
jclass disclass,
|
||||||
|
jstring jrepath_s,
|
||||||
|
jstring libname_s)
|
||||||
|
{
|
||||||
uintptr_t func = 0;
|
uintptr_t func = 0;
|
||||||
const char* error_message = NULL;
|
const char* error_message = NULL;
|
||||||
const char* java_home;
|
const char* java_home;
|
||||||
@ -533,13 +616,16 @@ static int printf_to_env(void* env_pv, const char* format, ...) {
|
|||||||
* Method: decode
|
* Method: decode
|
||||||
* Signature: (Lsun/jvm/hotspot/asm/InstructionVisitor;J[BLjava/lang/String;J)V
|
* Signature: (Lsun/jvm/hotspot/asm/InstructionVisitor;J[BLjava/lang/String;J)V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env,
|
JNIEXPORT void JNICALL
|
||||||
jobject dis,
|
Java_sun_jvm_hotspot_asm_Disassembler_decode(
|
||||||
jobject visitor,
|
JNIEnv * env,
|
||||||
jlong startPc,
|
jobject dis,
|
||||||
jbyteArray code,
|
jobject visitor,
|
||||||
jstring options_s,
|
jlong startPc,
|
||||||
jlong decode_instructions_virtual) {
|
jbyteArray code,
|
||||||
|
jstring options_s,
|
||||||
|
jlong decode_instructions_virtual)
|
||||||
|
{
|
||||||
jboolean isCopy;
|
jboolean isCopy;
|
||||||
jbyte* start = (*env)->GetByteArrayElements(env, code, &isCopy);
|
jbyte* start = (*env)->GetByteArrayElements(env, code, &isCopy);
|
||||||
jbyte* end = start + (*env)->GetArrayLength(env, code);
|
jbyte* end = start + (*env)->GetArrayLength(env, code);
|
||||||
|
@ -49,7 +49,7 @@ public interface BsdDebugger extends JVMDebugger {
|
|||||||
public BsdAddress readCompKlassAddress(long address) throws DebuggerException;
|
public BsdAddress readCompKlassAddress(long address) throws DebuggerException;
|
||||||
public BsdOopHandle readOopHandle(long address) throws DebuggerException;
|
public BsdOopHandle readOopHandle(long address) throws DebuggerException;
|
||||||
public BsdOopHandle readCompOopHandle(long address) throws DebuggerException;
|
public BsdOopHandle readCompOopHandle(long address) throws DebuggerException;
|
||||||
public long[] getThreadIntegerRegisterSet(int lwp_id) throws DebuggerException;
|
public long[] getThreadIntegerRegisterSet(long unique_thread_id) throws DebuggerException;
|
||||||
public long getAddressValue(Address addr) throws DebuggerException;
|
public long getAddressValue(Address addr) throws DebuggerException;
|
||||||
public Address newAddress(long value) throws DebuggerException;
|
public Address newAddress(long value) throws DebuggerException;
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
|
|||||||
throws DebuggerException;
|
throws DebuggerException;
|
||||||
private native ClosestSymbol lookupByAddress0(long address)
|
private native ClosestSymbol lookupByAddress0(long address)
|
||||||
throws DebuggerException;
|
throws DebuggerException;
|
||||||
private native long[] getThreadIntegerRegisterSet0(int lwp_id)
|
private native long[] getThreadIntegerRegisterSet0(long unique_thread_id)
|
||||||
throws DebuggerException;
|
throws DebuggerException;
|
||||||
private native byte[] readBytesFromProcess0(long address, long numBytes)
|
private native byte[] readBytesFromProcess0(long address, long numBytes)
|
||||||
throws DebuggerException;
|
throws DebuggerException;
|
||||||
@ -400,9 +400,14 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
|
|||||||
//
|
//
|
||||||
|
|
||||||
/** From the ThreadAccess interface via Debugger and JVMDebugger */
|
/** From the ThreadAccess interface via Debugger and JVMDebugger */
|
||||||
public ThreadProxy getThreadForIdentifierAddress(Address addr) {
|
public ThreadProxy getThreadForIdentifierAddress(Address threadIdAddr, Address uniqueThreadIdAddr) {
|
||||||
return new BsdThread(this, addr);
|
return new BsdThread(this, threadIdAddr, uniqueThreadIdAddr);
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public ThreadProxy getThreadForIdentifierAddress(Address addr) {
|
||||||
|
throw new RuntimeException("unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** From the ThreadAccess interface via Debugger and JVMDebugger */
|
/** From the ThreadAccess interface via Debugger and JVMDebugger */
|
||||||
public ThreadProxy getThreadForThreadId(long id) {
|
public ThreadProxy getThreadForThreadId(long id) {
|
||||||
@ -455,22 +460,22 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
|
|||||||
// Thread context access
|
// Thread context access
|
||||||
//
|
//
|
||||||
|
|
||||||
public synchronized long[] getThreadIntegerRegisterSet(int lwp_id)
|
public synchronized long[] getThreadIntegerRegisterSet(long unique_thread_id)
|
||||||
throws DebuggerException {
|
throws DebuggerException {
|
||||||
requireAttach();
|
requireAttach();
|
||||||
if (isCore) {
|
if (isCore) {
|
||||||
return getThreadIntegerRegisterSet0(lwp_id);
|
return getThreadIntegerRegisterSet0(unique_thread_id);
|
||||||
} else {
|
} else {
|
||||||
class GetThreadIntegerRegisterSetTask implements WorkerThreadTask {
|
class GetThreadIntegerRegisterSetTask implements WorkerThreadTask {
|
||||||
int lwp_id;
|
long unique_thread_id;
|
||||||
long[] result;
|
long[] result;
|
||||||
public void doit(BsdDebuggerLocal debugger) {
|
public void doit(BsdDebuggerLocal debugger) {
|
||||||
result = debugger.getThreadIntegerRegisterSet0(lwp_id);
|
result = debugger.getThreadIntegerRegisterSet0(unique_thread_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GetThreadIntegerRegisterSetTask task = new GetThreadIntegerRegisterSetTask();
|
GetThreadIntegerRegisterSetTask task = new GetThreadIntegerRegisterSetTask();
|
||||||
task.lwp_id = lwp_id;
|
task.unique_thread_id = unique_thread_id;
|
||||||
workerThread.execute(task);
|
workerThread.execute(task);
|
||||||
return task.result;
|
return task.result;
|
||||||
}
|
}
|
||||||
|
@ -28,21 +28,23 @@ import sun.jvm.hotspot.debugger.*;
|
|||||||
|
|
||||||
class BsdThread implements ThreadProxy {
|
class BsdThread implements ThreadProxy {
|
||||||
private BsdDebugger debugger;
|
private BsdDebugger debugger;
|
||||||
private int lwp_id;
|
private int thread_id;
|
||||||
|
private long unique_thread_id;
|
||||||
|
|
||||||
/** The address argument must be the address of the _thread_id in the
|
/** The address argument must be the address of the _thread_id in the
|
||||||
OSThread. It's value is result ::gettid() call. */
|
OSThread. It's value is result ::gettid() call. */
|
||||||
BsdThread(BsdDebugger debugger, Address addr) {
|
BsdThread(BsdDebugger debugger, Address threadIdAddr, Address uniqueThreadIdAddr) {
|
||||||
this.debugger = debugger;
|
this.debugger = debugger;
|
||||||
// FIXME: size of data fetched here should be configurable.
|
// FIXME: size of data fetched here should be configurable.
|
||||||
// However, making it so would produce a dependency on the "types"
|
// However, making it so would produce a dependency on the "types"
|
||||||
// package from the debugger package, which is not desired.
|
// package from the debugger package, which is not desired.
|
||||||
this.lwp_id = (int) addr.getCIntegerAt(0, 4, true);
|
this.thread_id = (int) threadIdAddr.getCIntegerAt(0, 4, true);
|
||||||
|
this.unique_thread_id = uniqueThreadIdAddr.getCIntegerAt(0, 8, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BsdThread(BsdDebugger debugger, long id) {
|
BsdThread(BsdDebugger debugger, long id) {
|
||||||
this.debugger = debugger;
|
this.debugger = debugger;
|
||||||
this.lwp_id = (int) id;
|
this.thread_id = (int) id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
@ -50,19 +52,19 @@ class BsdThread implements ThreadProxy {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (((BsdThread) obj).lwp_id == lwp_id);
|
return (((BsdThread) obj).thread_id == thread_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return lwp_id;
|
return thread_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return Integer.toString(lwp_id);
|
return Integer.toString(thread_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ThreadContext getContext() throws IllegalThreadStateException {
|
public ThreadContext getContext() throws IllegalThreadStateException {
|
||||||
long[] data = debugger.getThreadIntegerRegisterSet(lwp_id);
|
long[] data = debugger.getThreadIntegerRegisterSet(unique_thread_id);
|
||||||
ThreadContext context = BsdThreadContextFactory.createThreadContext(debugger);
|
ThreadContext context = BsdThreadContextFactory.createThreadContext(debugger);
|
||||||
for (int i = 0; i < data.length; i++) {
|
for (int i = 0; i < data.length; i++) {
|
||||||
context.setRegister(i, data[i]);
|
context.setRegister(i, data[i]);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -49,12 +49,18 @@ public class ConstMethod extends VMObject {
|
|||||||
private static int HAS_LOCALVARIABLE_TABLE;
|
private static int HAS_LOCALVARIABLE_TABLE;
|
||||||
private static int HAS_EXCEPTION_TABLE;
|
private static int HAS_EXCEPTION_TABLE;
|
||||||
private static int HAS_GENERIC_SIGNATURE;
|
private static int HAS_GENERIC_SIGNATURE;
|
||||||
|
private static int HAS_METHOD_ANNOTATIONS;
|
||||||
|
private static int HAS_PARAMETER_ANNOTATIONS;
|
||||||
|
private static int HAS_DEFAULT_ANNOTATIONS;
|
||||||
|
private static int HAS_TYPE_ANNOTATIONS;
|
||||||
|
|
||||||
|
private static final int sizeofShort = 2;
|
||||||
|
|
||||||
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
|
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
|
||||||
Type type = db.lookupType("ConstMethod");
|
Type type = db.lookupType("ConstMethod");
|
||||||
constants = new MetadataField(type.getAddressField("_constants"), 0);
|
constants = new MetadataField(type.getAddressField("_constants"), 0);
|
||||||
constMethodSize = new CIntField(type.getCIntegerField("_constMethod_size"), 0);
|
constMethodSize = new CIntField(type.getCIntegerField("_constMethod_size"), 0);
|
||||||
flags = new ByteField(type.getJByteField("_flags"), 0);
|
flags = new CIntField(type.getCIntegerField("_flags"), 0);
|
||||||
|
|
||||||
// enum constants for flags
|
// enum constants for flags
|
||||||
HAS_LINENUMBER_TABLE = db.lookupIntConstant("ConstMethod::_has_linenumber_table").intValue();
|
HAS_LINENUMBER_TABLE = db.lookupIntConstant("ConstMethod::_has_linenumber_table").intValue();
|
||||||
@ -62,6 +68,10 @@ public class ConstMethod extends VMObject {
|
|||||||
HAS_LOCALVARIABLE_TABLE = db.lookupIntConstant("ConstMethod::_has_localvariable_table").intValue();
|
HAS_LOCALVARIABLE_TABLE = db.lookupIntConstant("ConstMethod::_has_localvariable_table").intValue();
|
||||||
HAS_EXCEPTION_TABLE = db.lookupIntConstant("ConstMethod::_has_exception_table").intValue();
|
HAS_EXCEPTION_TABLE = db.lookupIntConstant("ConstMethod::_has_exception_table").intValue();
|
||||||
HAS_GENERIC_SIGNATURE = db.lookupIntConstant("ConstMethod::_has_generic_signature").intValue();
|
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_DEFAULT_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_default_annotations").intValue();
|
||||||
|
HAS_TYPE_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_type_annotations").intValue();
|
||||||
|
|
||||||
// Size of Java bytecodes allocated immediately after ConstMethod*.
|
// Size of Java bytecodes allocated immediately after ConstMethod*.
|
||||||
codeSize = new CIntField(type.getCIntegerField("_code_size"), 0);
|
codeSize = new CIntField(type.getCIntegerField("_code_size"), 0);
|
||||||
@ -92,7 +102,7 @@ public class ConstMethod extends VMObject {
|
|||||||
// Fields
|
// Fields
|
||||||
private static MetadataField constants;
|
private static MetadataField constants;
|
||||||
private static CIntField constMethodSize;
|
private static CIntField constMethodSize;
|
||||||
private static ByteField flags;
|
private static CIntField flags;
|
||||||
private static CIntField codeSize;
|
private static CIntField codeSize;
|
||||||
private static CIntField nameIndex;
|
private static CIntField nameIndex;
|
||||||
private static CIntField signatureIndex;
|
private static CIntField signatureIndex;
|
||||||
@ -123,7 +133,7 @@ public class ConstMethod extends VMObject {
|
|||||||
return constMethodSize.getValue(this);
|
return constMethodSize.getValue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getFlags() {
|
public long getFlags() {
|
||||||
return flags.getValue(this);
|
return flags.getValue(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,7 +263,7 @@ public class ConstMethod extends VMObject {
|
|||||||
public void iterateFields(MetadataVisitor visitor) {
|
public void iterateFields(MetadataVisitor visitor) {
|
||||||
visitor.doMetadata(constants, true);
|
visitor.doMetadata(constants, true);
|
||||||
visitor.doCInt(constMethodSize, true);
|
visitor.doCInt(constMethodSize, true);
|
||||||
visitor.doByte(flags, true);
|
visitor.doCInt(flags, true);
|
||||||
visitor.doCInt(codeSize, true);
|
visitor.doCInt(codeSize, true);
|
||||||
visitor.doCInt(nameIndex, true);
|
visitor.doCInt(nameIndex, true);
|
||||||
visitor.doCInt(signatureIndex, true);
|
visitor.doCInt(signatureIndex, true);
|
||||||
@ -381,6 +391,22 @@ public class ConstMethod extends VMObject {
|
|||||||
return (getFlags() & HAS_GENERIC_SIGNATURE) != 0;
|
return (getFlags() & HAS_GENERIC_SIGNATURE) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasMethodAnnotations() {
|
||||||
|
return (getFlags() & HAS_METHOD_ANNOTATIONS) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasParameterAnnotations() {
|
||||||
|
return (getFlags() & HAS_PARAMETER_ANNOTATIONS) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasDefaultAnnotations() {
|
||||||
|
return (getFlags() & HAS_DEFAULT_ANNOTATIONS) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasTypeAnnotations() {
|
||||||
|
return (getFlags() & HAS_TYPE_ANNOTATIONS) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Internals only below this point
|
// Internals only below this point
|
||||||
@ -400,9 +426,15 @@ public class ConstMethod extends VMObject {
|
|||||||
return offsetOfCodeEnd() + (isNative() ? 2 * VM.getVM().getAddressSize() : 0);
|
return offsetOfCodeEnd() + (isNative() ? 2 * VM.getVM().getAddressSize() : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Offset of last short in Method*
|
// Offset of last short in Method* before annotations, if present
|
||||||
private long offsetOfLastU2Element() {
|
private long offsetOfLastU2Element() {
|
||||||
return getSize() * VM.getVM().getObjectHeap().getOopSize() - 2;
|
int offset = 0;
|
||||||
|
if (hasMethodAnnotations()) offset++;
|
||||||
|
if (hasParameterAnnotations()) offset++;
|
||||||
|
if (hasTypeAnnotations()) offset++;
|
||||||
|
if (hasDefaultAnnotations()) offset++;
|
||||||
|
long wordSize = VM.getVM().getObjectHeap().getOopSize();
|
||||||
|
return (getSize() * wordSize) - (offset * wordSize) - sizeofShort;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Offset of the generic signature index
|
// Offset of the generic signature index
|
||||||
@ -411,7 +443,7 @@ public class ConstMethod extends VMObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private long offsetOfCheckedExceptionsLength() {
|
private long offsetOfCheckedExceptionsLength() {
|
||||||
return hasGenericSignature() ? offsetOfLastU2Element() - 2 :
|
return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
|
||||||
offsetOfLastU2Element();
|
offsetOfLastU2Element();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,11 +493,11 @@ public class ConstMethod extends VMObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hasExceptionTable()) {
|
if (hasExceptionTable()) {
|
||||||
return offsetOfExceptionTable() - 2;
|
return offsetOfExceptionTable() - sizeofShort;
|
||||||
} else if (hasCheckedExceptions()) {
|
} else if (hasCheckedExceptions()) {
|
||||||
return offsetOfCheckedExceptions() - 2;
|
return offsetOfCheckedExceptions() - sizeofShort;
|
||||||
} else {
|
} else {
|
||||||
return hasGenericSignature() ? offsetOfLastU2Element() - 2 :
|
return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
|
||||||
offsetOfLastU2Element();
|
offsetOfLastU2Element();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -493,9 +525,9 @@ public class ConstMethod extends VMObject {
|
|||||||
Assert.that(hasExceptionTable(), "should only be called if table is present");
|
Assert.that(hasExceptionTable(), "should only be called if table is present");
|
||||||
}
|
}
|
||||||
if (hasCheckedExceptions()) {
|
if (hasCheckedExceptions()) {
|
||||||
return offsetOfCheckedExceptions() - 2;
|
return offsetOfCheckedExceptions() - sizeofShort;
|
||||||
} else {
|
} else {
|
||||||
return hasGenericSignature() ? offsetOfLastU2Element() - 2 :
|
return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort :
|
||||||
offsetOfLastU2Element();
|
offsetOfLastU2Element();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,8 @@ import java.io.*;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import sun.jvm.hotspot.debugger.*;
|
import sun.jvm.hotspot.debugger.*;
|
||||||
import sun.jvm.hotspot.debugger.amd64.*;
|
import sun.jvm.hotspot.debugger.amd64.*;
|
||||||
|
import sun.jvm.hotspot.debugger.bsd.BsdDebugger;
|
||||||
|
import sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal;
|
||||||
import sun.jvm.hotspot.runtime.*;
|
import sun.jvm.hotspot.runtime.*;
|
||||||
import sun.jvm.hotspot.runtime.amd64.*;
|
import sun.jvm.hotspot.runtime.amd64.*;
|
||||||
import sun.jvm.hotspot.runtime.x86.*;
|
import sun.jvm.hotspot.runtime.x86.*;
|
||||||
@ -38,8 +40,9 @@ public class BsdAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
|
|||||||
private static AddressField lastJavaFPField;
|
private static AddressField lastJavaFPField;
|
||||||
private static AddressField osThreadField;
|
private static AddressField osThreadField;
|
||||||
|
|
||||||
// Field from OSThread
|
// Fields from OSThread
|
||||||
private static CIntegerField osThreadThreadIDField;
|
private static CIntegerField osThreadThreadIDField;
|
||||||
|
private static CIntegerField osThreadUniqueThreadIDField;
|
||||||
|
|
||||||
// This is currently unneeded but is being kept in case we change
|
// This is currently unneeded but is being kept in case we change
|
||||||
// the currentFrameGuess algorithm
|
// the currentFrameGuess algorithm
|
||||||
@ -61,7 +64,8 @@ public class BsdAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
|
|||||||
lastJavaFPField = anchorType.getAddressField("_last_Java_fp");
|
lastJavaFPField = anchorType.getAddressField("_last_Java_fp");
|
||||||
|
|
||||||
Type osThreadType = db.lookupType("OSThread");
|
Type osThreadType = db.lookupType("OSThread");
|
||||||
osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id");
|
osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id");
|
||||||
|
osThreadUniqueThreadIDField = osThreadType.getCIntegerField("_unique_thread_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Address getLastJavaFP(Address addr) {
|
public Address getLastJavaFP(Address addr) {
|
||||||
@ -125,8 +129,9 @@ public class BsdAMD64JavaThreadPDAccess implements JavaThreadPDAccess {
|
|||||||
Address osThreadAddr = osThreadField.getValue(addr);
|
Address osThreadAddr = osThreadField.getValue(addr);
|
||||||
// Get the address of the _thread_id from the OSThread
|
// Get the address of the _thread_id from the OSThread
|
||||||
Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
|
Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset());
|
||||||
|
Address uniqueThreadIdAddr = osThreadAddr.addOffsetTo(osThreadUniqueThreadIDField.getOffset());
|
||||||
|
|
||||||
JVMDebugger debugger = VM.getVM().getDebugger();
|
BsdDebuggerLocal debugger = (BsdDebuggerLocal) VM.getVM().getDebugger();
|
||||||
return debugger.getThreadForIdentifierAddress(threadIdAddr);
|
return debugger.getThreadForIdentifierAddress(threadIdAddr, uniqueThreadIdAddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2013
|
|||||||
|
|
||||||
HS_MAJOR_VER=25
|
HS_MAJOR_VER=25
|
||||||
HS_MINOR_VER=0
|
HS_MINOR_VER=0
|
||||||
HS_BUILD_NUMBER=18
|
HS_BUILD_NUMBER=19
|
||||||
|
|
||||||
JDK_MAJOR_VER=1
|
JDK_MAJOR_VER=1
|
||||||
JDK_MINOR_VER=8
|
JDK_MINOR_VER=8
|
||||||
|
@ -2270,10 +2270,11 @@ void Assembler::vpackuswb(XMMRegister dst, XMMRegister nds, XMMRegister src, boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Assembler::vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256) {
|
void Assembler::vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256) {
|
||||||
int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, true, vector256);
|
assert(VM_Version::supports_avx2(), "");
|
||||||
emit_int8(0x00);
|
int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, true, vector256);
|
||||||
emit_int8(0xC0 | encode);
|
emit_int8(0x00);
|
||||||
emit_int8(imm8);
|
emit_int8(0xC0 | encode);
|
||||||
|
emit_int8(imm8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) {
|
void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) {
|
||||||
|
@ -5691,7 +5691,7 @@ void MacroAssembler::string_compare(Register str1, Register str2,
|
|||||||
Address::ScaleFactor scale = Address::times_2;
|
Address::ScaleFactor scale = Address::times_2;
|
||||||
int stride = 8;
|
int stride = 8;
|
||||||
|
|
||||||
if (UseAVX >= 2) {
|
if (UseAVX >= 2 && UseSSE42Intrinsics) {
|
||||||
Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_WIDE_TAIL, COMPARE_SMALL_STR;
|
Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_WIDE_TAIL, COMPARE_SMALL_STR;
|
||||||
Label COMPARE_WIDE_VECTORS_LOOP, COMPARE_16_CHARS, COMPARE_INDEX_CHAR;
|
Label COMPARE_WIDE_VECTORS_LOOP, COMPARE_16_CHARS, COMPARE_INDEX_CHAR;
|
||||||
Label COMPARE_TAIL_LONG;
|
Label COMPARE_TAIL_LONG;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright 2008, 2009, 2010 Red Hat, Inc.
|
* Copyright 2008, 2009, 2010 Red Hat, Inc.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -51,7 +51,7 @@ define_pd_global(intx, Tier4BackEdgeThreshold, 100000);
|
|||||||
define_pd_global(intx, OnStackReplacePercentage, 933 );
|
define_pd_global(intx, OnStackReplacePercentage, 933 );
|
||||||
define_pd_global(intx, FreqInlineSize, 325 );
|
define_pd_global(intx, FreqInlineSize, 325 );
|
||||||
define_pd_global(intx, InlineSmallCode, 1000 );
|
define_pd_global(intx, InlineSmallCode, 1000 );
|
||||||
define_pd_global(intx, NewRatio, 12 );
|
define_pd_global(uintx, NewRatio, 12 );
|
||||||
define_pd_global(intx, NewSizeThreadIncrease, 4*K );
|
define_pd_global(intx, NewSizeThreadIncrease, 4*K );
|
||||||
define_pd_global(intx, InitialCodeCacheSize, 160*K);
|
define_pd_global(intx, InitialCodeCacheSize, 160*K);
|
||||||
define_pd_global(intx, ReservedCodeCacheSize, 32*M );
|
define_pd_global(intx, ReservedCodeCacheSize, 32*M );
|
||||||
|
@ -49,6 +49,11 @@
|
|||||||
// (e.g. pthread_kill).
|
// (e.g. pthread_kill).
|
||||||
pthread_t _pthread_id;
|
pthread_t _pthread_id;
|
||||||
|
|
||||||
|
// This is the "thread_id" from struct thread_identifier_info. According to a
|
||||||
|
// comment in thread_info.h, this is a "system-wide unique 64-bit thread id".
|
||||||
|
// The value is used by SA to correlate threads.
|
||||||
|
uint64_t _unique_thread_id;
|
||||||
|
|
||||||
sigset_t _caller_sigmask; // Caller's signal mask
|
sigset_t _caller_sigmask; // Caller's signal mask
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -77,6 +82,10 @@
|
|||||||
_pthread_id = tid;
|
_pthread_id = tid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_unique_thread_id(uint64_t id) {
|
||||||
|
_unique_thread_id = id;
|
||||||
|
}
|
||||||
|
|
||||||
// ***************************************************************
|
// ***************************************************************
|
||||||
// suspension support.
|
// suspension support.
|
||||||
// ***************************************************************
|
// ***************************************************************
|
||||||
|
@ -657,6 +657,18 @@ extern "C" objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFu
|
|||||||
objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFunction = NULL;
|
objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFunction = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
static uint64_t locate_unique_thread_id() {
|
||||||
|
// Additional thread_id used to correlate threads in SA
|
||||||
|
thread_identifier_info_data_t m_ident_info;
|
||||||
|
mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
|
||||||
|
|
||||||
|
thread_info(::mach_thread_self(), THREAD_IDENTIFIER_INFO,
|
||||||
|
(thread_info_t) &m_ident_info, &count);
|
||||||
|
return m_ident_info.thread_id;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Thread start routine for all newly created threads
|
// Thread start routine for all newly created threads
|
||||||
static void *java_start(Thread *thread) {
|
static void *java_start(Thread *thread) {
|
||||||
// Try to randomize the cache line index of hot stack frames.
|
// Try to randomize the cache line index of hot stack frames.
|
||||||
@ -685,6 +697,7 @@ static void *java_start(Thread *thread) {
|
|||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
// thread_id is mach thread on macos
|
// thread_id is mach thread on macos
|
||||||
osthread->set_thread_id(::mach_thread_self());
|
osthread->set_thread_id(::mach_thread_self());
|
||||||
|
osthread->set_unique_thread_id(locate_unique_thread_id());
|
||||||
#else
|
#else
|
||||||
// thread_id is pthread_id on BSD
|
// thread_id is pthread_id on BSD
|
||||||
osthread->set_thread_id(::pthread_self());
|
osthread->set_thread_id(::pthread_self());
|
||||||
@ -847,6 +860,7 @@ bool os::create_attached_thread(JavaThread* thread) {
|
|||||||
// Store pthread info into the OSThread
|
// Store pthread info into the OSThread
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
osthread->set_thread_id(::mach_thread_self());
|
osthread->set_thread_id(::mach_thread_self());
|
||||||
|
osthread->set_unique_thread_id(locate_unique_thread_id());
|
||||||
#else
|
#else
|
||||||
osthread->set_thread_id(::pthread_self());
|
osthread->set_thread_id(::pthread_self());
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -42,7 +42,7 @@ define_pd_global(intx, VMThreadStackSize, 512);
|
|||||||
#endif // AMD64
|
#endif // AMD64
|
||||||
|
|
||||||
define_pd_global(intx, CompilerThreadStackSize, 0);
|
define_pd_global(intx, CompilerThreadStackSize, 0);
|
||||||
define_pd_global(intx, SurvivorRatio, 8);
|
define_pd_global(uintx, SurvivorRatio, 8);
|
||||||
|
|
||||||
define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
|
define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
|
||||||
|
|
||||||
|
@ -35,17 +35,16 @@
|
|||||||
/* Threads (NOTE: incomplete) */ \
|
/* Threads (NOTE: incomplete) */ \
|
||||||
/******************************/ \
|
/******************************/ \
|
||||||
nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \
|
nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \
|
||||||
nonstatic_field(OSThread, _pthread_id, pthread_t)
|
nonstatic_field(OSThread, _unique_thread_id, uint64_t)
|
||||||
|
|
||||||
|
|
||||||
#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
|
#define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \
|
||||||
\
|
\
|
||||||
/**********************/ \
|
/**********************/ \
|
||||||
/* Posix Thread IDs */ \
|
/* Thread IDs */ \
|
||||||
/**********************/ \
|
/**********************/ \
|
||||||
\
|
\
|
||||||
declare_unsigned_integer_type(OSThread::thread_id_t) \
|
declare_unsigned_integer_type(OSThread::thread_id_t)
|
||||||
declare_unsigned_integer_type(pthread_t)
|
|
||||||
|
|
||||||
#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
|
#define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
package sun.hotspot;
|
package sun.hotspot;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.security.BasicPermission;
|
import java.security.BasicPermission;
|
||||||
import sun.hotspot.parser.DiagnosticCommand;
|
import sun.hotspot.parser.DiagnosticCommand;
|
||||||
|
|
||||||
@ -81,4 +83,15 @@ public class WhiteBox {
|
|||||||
public native boolean NMTAllocTest();
|
public native boolean NMTAllocTest();
|
||||||
public native boolean NMTFreeTestMemory();
|
public native boolean NMTFreeTestMemory();
|
||||||
public native boolean NMTWaitForDataMerge();
|
public native boolean NMTWaitForDataMerge();
|
||||||
|
|
||||||
|
// Compiler
|
||||||
|
public native void deoptimizeAll();
|
||||||
|
public native boolean isMethodCompiled(Method method);
|
||||||
|
public native boolean isMethodCompilable(Method method);
|
||||||
|
public native boolean isMethodQueuedForCompilation(Method method);
|
||||||
|
public native int deoptimizeMethod(Method method);
|
||||||
|
public native void makeMethodNotCompilable(Method method);
|
||||||
|
public native int getMethodCompilationLevel(Method method);
|
||||||
|
public native boolean setDontInlineMethod(Method method, boolean value);
|
||||||
|
public native int getCompileQueuesSize();
|
||||||
}
|
}
|
||||||
|
@ -37,10 +37,10 @@
|
|||||||
# include "assembler_zero.hpp"
|
# include "assembler_zero.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_ARCH_arm
|
#ifdef TARGET_ARCH_arm
|
||||||
# include "assembler_arm.hpp"
|
# include "macroAssembler_arm.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_ARCH_ppc
|
#ifdef TARGET_ARCH_ppc
|
||||||
# include "assembler_ppc.hpp"
|
# include "macroAssembler_ppc.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // SHARE_VM_ASM_MACROASSEMBLER_HPP
|
#endif // SHARE_VM_ASM_MACROASSEMBLER_HPP
|
||||||
|
@ -37,10 +37,10 @@
|
|||||||
# include "assembler_zero.inline.hpp"
|
# include "assembler_zero.inline.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_ARCH_arm
|
#ifdef TARGET_ARCH_arm
|
||||||
# include "assembler_arm.inline.hpp"
|
# include "macroAssembler_arm.inline.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_ARCH_ppc
|
#ifdef TARGET_ARCH_ppc
|
||||||
# include "assembler_ppc.inline.hpp"
|
# include "macroAssembler_ppc.inline.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // SHARE_VM_ASM_MACROASSEMBLER_INLINE_HPP
|
#endif // SHARE_VM_ASM_MACROASSEMBLER_INLINE_HPP
|
||||||
|
@ -1856,6 +1856,154 @@ void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k)
|
|||||||
#define MAX_CODE_SIZE 65535
|
#define MAX_CODE_SIZE 65535
|
||||||
#define INITIAL_MAX_LVT_NUMBER 256
|
#define INITIAL_MAX_LVT_NUMBER 256
|
||||||
|
|
||||||
|
/* Copy class file LVT's/LVTT's into the HotSpot internal LVT.
|
||||||
|
*
|
||||||
|
* Rules for LVT's and LVTT's are:
|
||||||
|
* - There can be any number of LVT's and LVTT's.
|
||||||
|
* - If there are n LVT's, it is the same as if there was just
|
||||||
|
* one LVT containing all the entries from the n LVT's.
|
||||||
|
* - There may be no more than one LVT entry per local variable.
|
||||||
|
* Two LVT entries are 'equal' if these fields are the same:
|
||||||
|
* start_pc, length, name, slot
|
||||||
|
* - There may be no more than one LVTT entry per each LVT entry.
|
||||||
|
* Each LVTT entry has to match some LVT entry.
|
||||||
|
* - HotSpot internal LVT keeps natural ordering of class file LVT entries.
|
||||||
|
*/
|
||||||
|
void ClassFileParser::copy_localvariable_table(ConstMethod* cm,
|
||||||
|
int lvt_cnt,
|
||||||
|
u2* localvariable_table_length,
|
||||||
|
u2** localvariable_table_start,
|
||||||
|
int lvtt_cnt,
|
||||||
|
u2* localvariable_type_table_length,
|
||||||
|
u2** localvariable_type_table_start,
|
||||||
|
TRAPS) {
|
||||||
|
|
||||||
|
LVT_Hash** lvt_Hash = NEW_RESOURCE_ARRAY(LVT_Hash*, HASH_ROW_SIZE);
|
||||||
|
initialize_hashtable(lvt_Hash);
|
||||||
|
|
||||||
|
// To fill LocalVariableTable in
|
||||||
|
Classfile_LVT_Element* cf_lvt;
|
||||||
|
LocalVariableTableElement* lvt = cm->localvariable_table_start();
|
||||||
|
|
||||||
|
for (int tbl_no = 0; tbl_no < lvt_cnt; tbl_no++) {
|
||||||
|
cf_lvt = (Classfile_LVT_Element *) localvariable_table_start[tbl_no];
|
||||||
|
for (int idx = 0; idx < localvariable_table_length[tbl_no]; idx++, lvt++) {
|
||||||
|
copy_lvt_element(&cf_lvt[idx], lvt);
|
||||||
|
// If no duplicates, add LVT elem in hashtable lvt_Hash.
|
||||||
|
if (LVT_put_after_lookup(lvt, lvt_Hash) == false
|
||||||
|
&& _need_verify
|
||||||
|
&& _major_version >= JAVA_1_5_VERSION) {
|
||||||
|
clear_hashtable(lvt_Hash);
|
||||||
|
ConstantPool* cp = cm->constants();
|
||||||
|
classfile_parse_error("Duplicated LocalVariableTable attribute "
|
||||||
|
"entry for '%s' in class file %s",
|
||||||
|
cp->symbol_at(lvt->name_cp_index)->as_utf8(),
|
||||||
|
CHECK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// To merge LocalVariableTable and LocalVariableTypeTable
|
||||||
|
Classfile_LVT_Element* cf_lvtt;
|
||||||
|
LocalVariableTableElement lvtt_elem;
|
||||||
|
|
||||||
|
for (int tbl_no = 0; tbl_no < lvtt_cnt; tbl_no++) {
|
||||||
|
cf_lvtt = (Classfile_LVT_Element *) localvariable_type_table_start[tbl_no];
|
||||||
|
for (int idx = 0; idx < localvariable_type_table_length[tbl_no]; idx++) {
|
||||||
|
copy_lvt_element(&cf_lvtt[idx], &lvtt_elem);
|
||||||
|
int index = hash(&lvtt_elem);
|
||||||
|
LVT_Hash* entry = LVT_lookup(&lvtt_elem, index, lvt_Hash);
|
||||||
|
if (entry == NULL) {
|
||||||
|
if (_need_verify) {
|
||||||
|
clear_hashtable(lvt_Hash);
|
||||||
|
ConstantPool* cp = cm->constants();
|
||||||
|
classfile_parse_error("LVTT entry for '%s' in class file %s "
|
||||||
|
"does not match any LVT entry",
|
||||||
|
cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
|
||||||
|
CHECK);
|
||||||
|
}
|
||||||
|
} else if (entry->_elem->signature_cp_index != 0 && _need_verify) {
|
||||||
|
clear_hashtable(lvt_Hash);
|
||||||
|
ConstantPool* cp = cm->constants();
|
||||||
|
classfile_parse_error("Duplicated LocalVariableTypeTable attribute "
|
||||||
|
"entry for '%s' in class file %s",
|
||||||
|
cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
|
||||||
|
CHECK);
|
||||||
|
} else {
|
||||||
|
// to add generic signatures into LocalVariableTable
|
||||||
|
entry->_elem->signature_cp_index = lvtt_elem.descriptor_cp_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clear_hashtable(lvt_Hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data,
|
||||||
|
ConstMethod* cm,
|
||||||
|
u1* runtime_visible_annotations,
|
||||||
|
int runtime_visible_annotations_length,
|
||||||
|
u1* runtime_invisible_annotations,
|
||||||
|
int runtime_invisible_annotations_length,
|
||||||
|
u1* runtime_visible_parameter_annotations,
|
||||||
|
int runtime_visible_parameter_annotations_length,
|
||||||
|
u1* runtime_invisible_parameter_annotations,
|
||||||
|
int runtime_invisible_parameter_annotations_length,
|
||||||
|
u1* runtime_visible_type_annotations,
|
||||||
|
int runtime_visible_type_annotations_length,
|
||||||
|
u1* runtime_invisible_type_annotations,
|
||||||
|
int runtime_invisible_type_annotations_length,
|
||||||
|
u1* annotation_default,
|
||||||
|
int annotation_default_length,
|
||||||
|
TRAPS) {
|
||||||
|
|
||||||
|
AnnotationArray* a;
|
||||||
|
|
||||||
|
if (runtime_visible_annotations_length +
|
||||||
|
runtime_invisible_annotations_length > 0) {
|
||||||
|
a = assemble_annotations(loader_data,
|
||||||
|
runtime_visible_annotations,
|
||||||
|
runtime_visible_annotations_length,
|
||||||
|
runtime_invisible_annotations,
|
||||||
|
runtime_invisible_annotations_length,
|
||||||
|
CHECK);
|
||||||
|
cm->set_method_annotations(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runtime_visible_parameter_annotations_length +
|
||||||
|
runtime_invisible_parameter_annotations_length > 0) {
|
||||||
|
a = assemble_annotations(loader_data,
|
||||||
|
runtime_visible_parameter_annotations,
|
||||||
|
runtime_visible_parameter_annotations_length,
|
||||||
|
runtime_invisible_parameter_annotations,
|
||||||
|
runtime_invisible_parameter_annotations_length,
|
||||||
|
CHECK);
|
||||||
|
cm->set_parameter_annotations(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (annotation_default_length > 0) {
|
||||||
|
a = assemble_annotations(loader_data,
|
||||||
|
annotation_default,
|
||||||
|
annotation_default_length,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
CHECK);
|
||||||
|
cm->set_default_annotations(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runtime_visible_type_annotations_length +
|
||||||
|
runtime_invisible_type_annotations_length > 0) {
|
||||||
|
a = assemble_annotations(loader_data,
|
||||||
|
runtime_visible_type_annotations,
|
||||||
|
runtime_visible_type_annotations_length,
|
||||||
|
runtime_invisible_type_annotations,
|
||||||
|
runtime_invisible_type_annotations_length,
|
||||||
|
CHECK);
|
||||||
|
cm->set_type_annotations(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Note: the parse_method below is big and clunky because all parsing of the code and exceptions
|
// Note: the parse_method below is big and clunky because all parsing of the code and exceptions
|
||||||
// attribute is inlined. This is cumbersome to avoid since we inline most of the parts in the
|
// attribute is inlined. This is cumbersome to avoid since we inline most of the parts in the
|
||||||
// Method* to save footprint, so we only know the size of the resulting Method* when the
|
// Method* to save footprint, so we only know the size of the resulting Method* when the
|
||||||
@ -1869,10 +2017,6 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
|||||||
constantPoolHandle cp,
|
constantPoolHandle cp,
|
||||||
bool is_interface,
|
bool is_interface,
|
||||||
AccessFlags *promoted_flags,
|
AccessFlags *promoted_flags,
|
||||||
AnnotationArray** method_annotations,
|
|
||||||
AnnotationArray** method_parameter_annotations,
|
|
||||||
AnnotationArray** method_default_annotations,
|
|
||||||
AnnotationArray** method_type_annotations,
|
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
ClassFileStream* cfs = stream();
|
ClassFileStream* cfs = stream();
|
||||||
methodHandle nullHandle;
|
methodHandle nullHandle;
|
||||||
@ -2273,10 +2417,24 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// All sizing information for a Method* is finally available, now create it
|
// All sizing information for a Method* is finally available, now create it
|
||||||
|
InlineTableSizes sizes(
|
||||||
|
total_lvt_length,
|
||||||
|
linenumber_table_length,
|
||||||
|
exception_table_length,
|
||||||
|
checked_exceptions_length,
|
||||||
|
method_parameters_length,
|
||||||
|
generic_signature_index,
|
||||||
|
runtime_visible_annotations_length +
|
||||||
|
runtime_invisible_annotations_length,
|
||||||
|
runtime_visible_parameter_annotations_length +
|
||||||
|
runtime_invisible_parameter_annotations_length,
|
||||||
|
runtime_visible_type_annotations_length +
|
||||||
|
runtime_invisible_type_annotations_length,
|
||||||
|
annotation_default_length,
|
||||||
|
0);
|
||||||
|
|
||||||
Method* m = Method::allocate(
|
Method* m = Method::allocate(
|
||||||
loader_data, code_length, access_flags, linenumber_table_length,
|
loader_data, code_length, access_flags, &sizes,
|
||||||
total_lvt_length, exception_table_length, checked_exceptions_length,
|
|
||||||
method_parameters_length, generic_signature_index,
|
|
||||||
ConstMethod::NORMAL, CHECK_(nullHandle));
|
ConstMethod::NORMAL, CHECK_(nullHandle));
|
||||||
|
|
||||||
ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
|
ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
|
||||||
@ -2347,107 +2505,37 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
|||||||
copy_u2_with_conversion((u2*) m->checked_exceptions_start(), checked_exceptions_start, size);
|
copy_u2_with_conversion((u2*) m->checked_exceptions_start(), checked_exceptions_start, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy class file LVT's/LVTT's into the HotSpot internal LVT.
|
// Copy class file LVT's/LVTT's into the HotSpot internal LVT.
|
||||||
*
|
|
||||||
* Rules for LVT's and LVTT's are:
|
|
||||||
* - There can be any number of LVT's and LVTT's.
|
|
||||||
* - If there are n LVT's, it is the same as if there was just
|
|
||||||
* one LVT containing all the entries from the n LVT's.
|
|
||||||
* - There may be no more than one LVT entry per local variable.
|
|
||||||
* Two LVT entries are 'equal' if these fields are the same:
|
|
||||||
* start_pc, length, name, slot
|
|
||||||
* - There may be no more than one LVTT entry per each LVT entry.
|
|
||||||
* Each LVTT entry has to match some LVT entry.
|
|
||||||
* - HotSpot internal LVT keeps natural ordering of class file LVT entries.
|
|
||||||
*/
|
|
||||||
if (total_lvt_length > 0) {
|
if (total_lvt_length > 0) {
|
||||||
int tbl_no, idx;
|
|
||||||
|
|
||||||
promoted_flags->set_has_localvariable_table();
|
promoted_flags->set_has_localvariable_table();
|
||||||
|
copy_localvariable_table(m->constMethod(), lvt_cnt,
|
||||||
LVT_Hash** lvt_Hash = NEW_RESOURCE_ARRAY(LVT_Hash*, HASH_ROW_SIZE);
|
localvariable_table_length,
|
||||||
initialize_hashtable(lvt_Hash);
|
localvariable_table_start,
|
||||||
|
lvtt_cnt,
|
||||||
// To fill LocalVariableTable in
|
localvariable_type_table_length,
|
||||||
Classfile_LVT_Element* cf_lvt;
|
localvariable_type_table_start, CHECK_NULL);
|
||||||
LocalVariableTableElement* lvt = m->localvariable_table_start();
|
|
||||||
|
|
||||||
for (tbl_no = 0; tbl_no < lvt_cnt; tbl_no++) {
|
|
||||||
cf_lvt = (Classfile_LVT_Element *) localvariable_table_start[tbl_no];
|
|
||||||
for (idx = 0; idx < localvariable_table_length[tbl_no]; idx++, lvt++) {
|
|
||||||
copy_lvt_element(&cf_lvt[idx], lvt);
|
|
||||||
// If no duplicates, add LVT elem in hashtable lvt_Hash.
|
|
||||||
if (LVT_put_after_lookup(lvt, lvt_Hash) == false
|
|
||||||
&& _need_verify
|
|
||||||
&& _major_version >= JAVA_1_5_VERSION ) {
|
|
||||||
clear_hashtable(lvt_Hash);
|
|
||||||
classfile_parse_error("Duplicated LocalVariableTable attribute "
|
|
||||||
"entry for '%s' in class file %s",
|
|
||||||
cp->symbol_at(lvt->name_cp_index)->as_utf8(),
|
|
||||||
CHECK_(nullHandle));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// To merge LocalVariableTable and LocalVariableTypeTable
|
|
||||||
Classfile_LVT_Element* cf_lvtt;
|
|
||||||
LocalVariableTableElement lvtt_elem;
|
|
||||||
|
|
||||||
for (tbl_no = 0; tbl_no < lvtt_cnt; tbl_no++) {
|
|
||||||
cf_lvtt = (Classfile_LVT_Element *) localvariable_type_table_start[tbl_no];
|
|
||||||
for (idx = 0; idx < localvariable_type_table_length[tbl_no]; idx++) {
|
|
||||||
copy_lvt_element(&cf_lvtt[idx], &lvtt_elem);
|
|
||||||
int index = hash(&lvtt_elem);
|
|
||||||
LVT_Hash* entry = LVT_lookup(&lvtt_elem, index, lvt_Hash);
|
|
||||||
if (entry == NULL) {
|
|
||||||
if (_need_verify) {
|
|
||||||
clear_hashtable(lvt_Hash);
|
|
||||||
classfile_parse_error("LVTT entry for '%s' in class file %s "
|
|
||||||
"does not match any LVT entry",
|
|
||||||
cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
|
|
||||||
CHECK_(nullHandle));
|
|
||||||
}
|
|
||||||
} else if (entry->_elem->signature_cp_index != 0 && _need_verify) {
|
|
||||||
clear_hashtable(lvt_Hash);
|
|
||||||
classfile_parse_error("Duplicated LocalVariableTypeTable attribute "
|
|
||||||
"entry for '%s' in class file %s",
|
|
||||||
cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(),
|
|
||||||
CHECK_(nullHandle));
|
|
||||||
} else {
|
|
||||||
// to add generic signatures into LocalVariableTable
|
|
||||||
entry->_elem->signature_cp_index = lvtt_elem.descriptor_cp_index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clear_hashtable(lvt_Hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsed_annotations.has_any_annotations())
|
if (parsed_annotations.has_any_annotations())
|
||||||
parsed_annotations.apply_to(m);
|
parsed_annotations.apply_to(m);
|
||||||
*method_annotations = assemble_annotations(loader_data,
|
|
||||||
runtime_visible_annotations,
|
// Copy annotations
|
||||||
runtime_visible_annotations_length,
|
copy_method_annotations(loader_data, m->constMethod(),
|
||||||
runtime_invisible_annotations,
|
runtime_visible_annotations,
|
||||||
runtime_invisible_annotations_length,
|
runtime_visible_annotations_length,
|
||||||
CHECK_(nullHandle));
|
runtime_invisible_annotations,
|
||||||
*method_parameter_annotations = assemble_annotations(loader_data,
|
runtime_invisible_annotations_length,
|
||||||
runtime_visible_parameter_annotations,
|
runtime_visible_parameter_annotations,
|
||||||
runtime_visible_parameter_annotations_length,
|
runtime_visible_parameter_annotations_length,
|
||||||
runtime_invisible_parameter_annotations,
|
runtime_invisible_parameter_annotations,
|
||||||
runtime_invisible_parameter_annotations_length,
|
runtime_invisible_parameter_annotations_length,
|
||||||
CHECK_(nullHandle));
|
runtime_visible_type_annotations,
|
||||||
*method_default_annotations = assemble_annotations(loader_data,
|
runtime_visible_type_annotations_length,
|
||||||
annotation_default,
|
runtime_invisible_type_annotations,
|
||||||
annotation_default_length,
|
runtime_invisible_type_annotations_length,
|
||||||
NULL,
|
annotation_default,
|
||||||
0,
|
annotation_default_length,
|
||||||
CHECK_(nullHandle));
|
CHECK_NULL);
|
||||||
*method_type_annotations = assemble_annotations(loader_data,
|
|
||||||
runtime_visible_type_annotations,
|
|
||||||
runtime_visible_type_annotations_length,
|
|
||||||
runtime_invisible_type_annotations,
|
|
||||||
runtime_invisible_type_annotations_length,
|
|
||||||
CHECK_(nullHandle));
|
|
||||||
|
|
||||||
if (name == vmSymbols::finalize_method_name() &&
|
if (name == vmSymbols::finalize_method_name() &&
|
||||||
signature == vmSymbols::void_method_signature()) {
|
signature == vmSymbols::void_method_signature()) {
|
||||||
@ -2463,6 +2551,7 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
|||||||
_has_vanilla_constructor = true;
|
_has_vanilla_constructor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NOT_PRODUCT(m->verify());
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2476,17 +2565,9 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
|||||||
bool is_interface,
|
bool is_interface,
|
||||||
AccessFlags* promoted_flags,
|
AccessFlags* promoted_flags,
|
||||||
bool* has_final_method,
|
bool* has_final_method,
|
||||||
Array<AnnotationArray*>** methods_annotations,
|
|
||||||
Array<AnnotationArray*>** methods_parameter_annotations,
|
|
||||||
Array<AnnotationArray*>** methods_default_annotations,
|
|
||||||
Array<AnnotationArray*>** methods_type_annotations,
|
|
||||||
bool* has_default_methods,
|
bool* has_default_methods,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
ClassFileStream* cfs = stream();
|
ClassFileStream* cfs = stream();
|
||||||
AnnotationArray* method_annotations = NULL;
|
|
||||||
AnnotationArray* method_parameter_annotations = NULL;
|
|
||||||
AnnotationArray* method_default_annotations = NULL;
|
|
||||||
AnnotationArray* method_type_annotations = NULL;
|
|
||||||
cfs->guarantee_more(2, CHECK_NULL); // length
|
cfs->guarantee_more(2, CHECK_NULL); // length
|
||||||
u2 length = cfs->get_u2_fast();
|
u2 length = cfs->get_u2_fast();
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
@ -2500,10 +2581,6 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
|||||||
methodHandle method = parse_method(loader_data,
|
methodHandle method = parse_method(loader_data,
|
||||||
cp, is_interface,
|
cp, is_interface,
|
||||||
promoted_flags,
|
promoted_flags,
|
||||||
&method_annotations,
|
|
||||||
&method_parameter_annotations,
|
|
||||||
&method_default_annotations,
|
|
||||||
&method_type_annotations,
|
|
||||||
CHECK_NULL);
|
CHECK_NULL);
|
||||||
|
|
||||||
if (method->is_final()) {
|
if (method->is_final()) {
|
||||||
@ -2514,38 +2591,6 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
|||||||
*has_default_methods = true;
|
*has_default_methods = true;
|
||||||
}
|
}
|
||||||
methods->at_put(index, method());
|
methods->at_put(index, method());
|
||||||
|
|
||||||
if (method_annotations != NULL) {
|
|
||||||
if (*methods_annotations == NULL) {
|
|
||||||
*methods_annotations =
|
|
||||||
MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL);
|
|
||||||
}
|
|
||||||
(*methods_annotations)->at_put(index, method_annotations);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method_parameter_annotations != NULL) {
|
|
||||||
if (*methods_parameter_annotations == NULL) {
|
|
||||||
*methods_parameter_annotations =
|
|
||||||
MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL);
|
|
||||||
}
|
|
||||||
(*methods_parameter_annotations)->at_put(index, method_parameter_annotations);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method_default_annotations != NULL) {
|
|
||||||
if (*methods_default_annotations == NULL) {
|
|
||||||
*methods_default_annotations =
|
|
||||||
MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL);
|
|
||||||
}
|
|
||||||
(*methods_default_annotations)->at_put(index, method_default_annotations);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (method_type_annotations != NULL) {
|
|
||||||
if (*methods_type_annotations == NULL) {
|
|
||||||
*methods_type_annotations =
|
|
||||||
MetadataFactory::new_array<AnnotationArray*>(loader_data, length, NULL, CHECK_NULL);
|
|
||||||
}
|
|
||||||
(*methods_type_annotations)->at_put(index, method_type_annotations);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_need_verify && length > 1) {
|
if (_need_verify && length > 1) {
|
||||||
@ -2578,11 +2623,7 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
|||||||
|
|
||||||
Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
|
Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
|
||||||
Array<Method*>* methods,
|
Array<Method*>* methods,
|
||||||
Array<AnnotationArray*>* methods_annotations,
|
TRAPS) {
|
||||||
Array<AnnotationArray*>* methods_parameter_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_default_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_type_annotations,
|
|
||||||
TRAPS) {
|
|
||||||
int length = methods->length();
|
int length = methods->length();
|
||||||
// If JVMTI original method ordering or sharing is enabled we have to
|
// If JVMTI original method ordering or sharing is enabled we have to
|
||||||
// remember the original class file ordering.
|
// remember the original class file ordering.
|
||||||
@ -2598,10 +2639,7 @@ Array<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data,
|
|||||||
}
|
}
|
||||||
// Sort method array by ascending method name (for faster lookups & vtable construction)
|
// Sort method array by ascending method name (for faster lookups & vtable construction)
|
||||||
// Note that the ordering is not alphabetical, see Symbol::fast_compare
|
// Note that the ordering is not alphabetical, see Symbol::fast_compare
|
||||||
Method::sort_methods(methods, methods_annotations,
|
Method::sort_methods(methods);
|
||||||
methods_parameter_annotations,
|
|
||||||
methods_default_annotations,
|
|
||||||
methods_type_annotations);
|
|
||||||
|
|
||||||
// If JVMTI original method ordering or sharing is enabled construct int
|
// If JVMTI original method ordering or sharing is enabled construct int
|
||||||
// array remembering the original ordering
|
// array remembering the original ordering
|
||||||
@ -3048,9 +3086,6 @@ void ClassFileParser::apply_parsed_class_attributes(instanceKlassHandle k) {
|
|||||||
k->set_source_debug_extension(_sde_buffer, _sde_length);
|
k->set_source_debug_extension(_sde_buffer, _sde_length);
|
||||||
}
|
}
|
||||||
k->set_inner_classes(_inner_classes);
|
k->set_inner_classes(_inner_classes);
|
||||||
if (_annotations != NULL) {
|
|
||||||
k->annotations()->set_class_annotations(_annotations);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AnnotationArray* ClassFileParser::assemble_annotations(ClassLoaderData* loader_data,
|
AnnotationArray* ClassFileParser::assemble_annotations(ClassLoaderData* loader_data,
|
||||||
@ -3361,19 +3396,10 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||||||
bool has_final_method = false;
|
bool has_final_method = false;
|
||||||
AccessFlags promoted_flags;
|
AccessFlags promoted_flags;
|
||||||
promoted_flags.set_flags(0);
|
promoted_flags.set_flags(0);
|
||||||
|
|
||||||
Array<AnnotationArray*>* methods_annotations = NULL;
|
|
||||||
Array<AnnotationArray*>* methods_parameter_annotations = NULL;
|
|
||||||
Array<AnnotationArray*>* methods_default_annotations = NULL;
|
|
||||||
Array<AnnotationArray*>* methods_type_annotations = NULL;
|
|
||||||
Array<Method*>* methods = parse_methods(loader_data,
|
Array<Method*>* methods = parse_methods(loader_data,
|
||||||
cp, access_flags.is_interface(),
|
cp, access_flags.is_interface(),
|
||||||
&promoted_flags,
|
&promoted_flags,
|
||||||
&has_final_method,
|
&has_final_method,
|
||||||
&methods_annotations,
|
|
||||||
&methods_parameter_annotations,
|
|
||||||
&methods_default_annotations,
|
|
||||||
&methods_type_annotations,
|
|
||||||
&has_default_methods,
|
&has_default_methods,
|
||||||
CHECK_(nullHandle));
|
CHECK_(nullHandle));
|
||||||
|
|
||||||
@ -3432,10 +3458,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||||||
// sort methods
|
// sort methods
|
||||||
Array<int>* method_ordering = sort_methods(loader_data,
|
Array<int>* method_ordering = sort_methods(loader_data,
|
||||||
methods,
|
methods,
|
||||||
methods_annotations,
|
|
||||||
methods_parameter_annotations,
|
|
||||||
methods_default_annotations,
|
|
||||||
methods_type_annotations,
|
|
||||||
CHECK_(nullHandle));
|
CHECK_(nullHandle));
|
||||||
|
|
||||||
// promote flags from parse_methods() to the klass' flags
|
// promote flags from parse_methods() to the klass' flags
|
||||||
@ -4035,7 +4057,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||||||
const unsigned int total_oop_map_count =
|
const unsigned int total_oop_map_count =
|
||||||
compute_oop_map_count(super_klass, nonstatic_oop_map_count,
|
compute_oop_map_count(super_klass, nonstatic_oop_map_count,
|
||||||
first_nonstatic_oop_offset);
|
first_nonstatic_oop_offset);
|
||||||
|
|
||||||
// Compute reference type
|
// Compute reference type
|
||||||
ReferenceType rt;
|
ReferenceType rt;
|
||||||
if (super_klass() == NULL) {
|
if (super_klass() == NULL) {
|
||||||
@ -4057,7 +4078,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||||||
access_flags,
|
access_flags,
|
||||||
name,
|
name,
|
||||||
super_klass(),
|
super_klass(),
|
||||||
host_klass,
|
!host_klass.is_null(),
|
||||||
CHECK_(nullHandle));
|
CHECK_(nullHandle));
|
||||||
|
|
||||||
// Add all classes to our internal class loader list here,
|
// Add all classes to our internal class loader list here,
|
||||||
@ -4103,31 +4124,15 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||||||
if (is_anonymous()) // I am well known to myself
|
if (is_anonymous()) // I am well known to myself
|
||||||
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
|
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
|
||||||
|
|
||||||
// Allocate an annotation type if needed.
|
// Assign allocations if needed
|
||||||
if (fields_annotations != NULL ||
|
if (_annotations != NULL || _type_annotations != NULL ||
|
||||||
methods_annotations != NULL ||
|
fields_annotations != NULL || fields_type_annotations != NULL) {
|
||||||
methods_parameter_annotations != NULL ||
|
Annotations* annotations = Annotations::allocate(loader_data, CHECK_NULL);
|
||||||
methods_default_annotations != NULL ||
|
annotations->set_class_annotations(_annotations);
|
||||||
fields_type_annotations != NULL ||
|
annotations->set_class_type_annotations(_type_annotations);
|
||||||
methods_type_annotations != NULL) {
|
annotations->set_fields_annotations(fields_annotations);
|
||||||
Annotations* anno = Annotations::allocate(loader_data,
|
annotations->set_fields_type_annotations(fields_type_annotations);
|
||||||
fields_annotations, methods_annotations,
|
this_klass->set_annotations(annotations);
|
||||||
methods_parameter_annotations,
|
|
||||||
methods_default_annotations, CHECK_(nullHandle));
|
|
||||||
this_klass->set_annotations(anno);
|
|
||||||
} else {
|
|
||||||
this_klass->set_annotations(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fields_type_annotations != NULL ||
|
|
||||||
methods_type_annotations != NULL) {
|
|
||||||
assert(this_klass->annotations() != NULL, "annotations should have been allocated");
|
|
||||||
Annotations* anno = Annotations::allocate(loader_data,
|
|
||||||
fields_type_annotations,
|
|
||||||
methods_type_annotations,
|
|
||||||
NULL,
|
|
||||||
NULL, CHECK_(nullHandle));
|
|
||||||
this_klass->annotations()->set_type_annotations(anno);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this_klass->set_minor_version(minor_version);
|
this_klass->set_minor_version(minor_version);
|
||||||
@ -4153,27 +4158,8 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
|||||||
// Fill in field values obtained by parse_classfile_attributes
|
// Fill in field values obtained by parse_classfile_attributes
|
||||||
if (parsed_annotations.has_any_annotations())
|
if (parsed_annotations.has_any_annotations())
|
||||||
parsed_annotations.apply_to(this_klass);
|
parsed_annotations.apply_to(this_klass);
|
||||||
|
|
||||||
// Create annotations
|
|
||||||
if (_annotations != NULL && this_klass->annotations() == NULL) {
|
|
||||||
Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
|
|
||||||
this_klass->set_annotations(anno);
|
|
||||||
}
|
|
||||||
apply_parsed_class_attributes(this_klass);
|
apply_parsed_class_attributes(this_klass);
|
||||||
|
|
||||||
// Create type annotations
|
|
||||||
if (_type_annotations != NULL) {
|
|
||||||
if (this_klass->annotations() == NULL) {
|
|
||||||
Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
|
|
||||||
this_klass->set_annotations(anno);
|
|
||||||
}
|
|
||||||
if (this_klass->annotations()->type_annotations() == NULL) {
|
|
||||||
Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
|
|
||||||
this_klass->annotations()->set_type_annotations(anno);
|
|
||||||
}
|
|
||||||
this_klass->annotations()->type_annotations()->set_class_annotations(_type_annotations);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Miranda methods
|
// Miranda methods
|
||||||
if ((num_miranda_methods > 0) ||
|
if ((num_miranda_methods > 0) ||
|
||||||
// if this class introduced new miranda methods or
|
// if this class introduced new miranda methods or
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -199,29 +199,17 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
constantPoolHandle cp,
|
constantPoolHandle cp,
|
||||||
bool is_interface,
|
bool is_interface,
|
||||||
AccessFlags* promoted_flags,
|
AccessFlags* promoted_flags,
|
||||||
AnnotationArray** method_annotations,
|
|
||||||
AnnotationArray** method_parameter_annotations,
|
|
||||||
AnnotationArray** method_default_annotations,
|
|
||||||
AnnotationArray** method_type_annotations,
|
|
||||||
TRAPS);
|
TRAPS);
|
||||||
Array<Method*>* parse_methods(ClassLoaderData* loader_data,
|
Array<Method*>* parse_methods(ClassLoaderData* loader_data,
|
||||||
constantPoolHandle cp,
|
constantPoolHandle cp,
|
||||||
bool is_interface,
|
bool is_interface,
|
||||||
AccessFlags* promoted_flags,
|
AccessFlags* promoted_flags,
|
||||||
bool* has_final_method,
|
bool* has_final_method,
|
||||||
Array<AnnotationArray*>** methods_annotations,
|
|
||||||
Array<AnnotationArray*>** methods_parameter_annotations,
|
|
||||||
Array<AnnotationArray*>** methods_default_annotations,
|
|
||||||
Array<AnnotationArray*>** methods_type_annotations,
|
|
||||||
bool* has_default_method,
|
bool* has_default_method,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
Array<int>* sort_methods(ClassLoaderData* loader_data,
|
Array<int>* sort_methods(ClassLoaderData* loader_data,
|
||||||
Array<Method*>* methods,
|
Array<Method*>* methods,
|
||||||
Array<AnnotationArray*>* methods_annotations,
|
TRAPS);
|
||||||
Array<AnnotationArray*>* methods_parameter_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_default_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_type_annotations,
|
|
||||||
TRAPS);
|
|
||||||
u2* parse_exception_table(ClassLoaderData* loader_data,
|
u2* parse_exception_table(ClassLoaderData* loader_data,
|
||||||
u4 code_length, u4 exception_table_length,
|
u4 code_length, u4 exception_table_length,
|
||||||
constantPoolHandle cp, TRAPS);
|
constantPoolHandle cp, TRAPS);
|
||||||
@ -377,6 +365,32 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
: cp->tag_at(index).is_klass_reference());
|
: cp->tag_at(index).is_klass_reference());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void copy_localvariable_table(ConstMethod* cm, int lvt_cnt,
|
||||||
|
u2* localvariable_table_length,
|
||||||
|
u2** localvariable_table_start,
|
||||||
|
int lvtt_cnt,
|
||||||
|
u2* localvariable_type_table_length,
|
||||||
|
u2** localvariable_type_table_start,
|
||||||
|
TRAPS);
|
||||||
|
|
||||||
|
void copy_method_annotations(ClassLoaderData* loader_data,
|
||||||
|
ConstMethod* cm,
|
||||||
|
u1* runtime_visible_annotations,
|
||||||
|
int runtime_visible_annotations_length,
|
||||||
|
u1* runtime_invisible_annotations,
|
||||||
|
int runtime_invisible_annotations_length,
|
||||||
|
u1* runtime_visible_parameter_annotations,
|
||||||
|
int runtime_visible_parameter_annotations_length,
|
||||||
|
u1* runtime_invisible_parameter_annotations,
|
||||||
|
int runtime_invisible_parameter_annotations_length,
|
||||||
|
u1* runtime_visible_type_annotations,
|
||||||
|
int runtime_visible_type_annotations_length,
|
||||||
|
u1* runtime_invisible_type_annotations,
|
||||||
|
int runtime_invisible_type_annotations_length,
|
||||||
|
u1* annotation_default,
|
||||||
|
int annotation_default_length,
|
||||||
|
TRAPS);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
ClassFileParser(ClassFileStream* st) { set_stream(st); }
|
ClassFileParser(ClassFileStream* st) { set_stream(st); }
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -1146,9 +1146,10 @@ static Method* new_method(
|
|||||||
|
|
||||||
address code_start = static_cast<address>(bytecodes->adr_at(0));
|
address code_start = static_cast<address>(bytecodes->adr_at(0));
|
||||||
int code_length = bytecodes->length();
|
int code_length = bytecodes->length();
|
||||||
|
InlineTableSizes sizes;
|
||||||
|
|
||||||
Method* m = Method::allocate(cp->pool_holder()->class_loader_data(),
|
Method* m = Method::allocate(cp->pool_holder()->class_loader_data(),
|
||||||
code_length, flags, 0, 0, 0, 0, 0, 0,
|
code_length, flags, &sizes,
|
||||||
mt, CHECK_NULL);
|
mt, CHECK_NULL);
|
||||||
|
|
||||||
m->set_constants(NULL); // This will get filled in later
|
m->set_constants(NULL); // This will get filled in later
|
||||||
@ -1285,33 +1286,15 @@ static void merge_in_new_methods(InstanceKlass* klass,
|
|||||||
|
|
||||||
enum { ANNOTATIONS, PARAMETERS, DEFAULTS, NUM_ARRAYS };
|
enum { ANNOTATIONS, PARAMETERS, DEFAULTS, NUM_ARRAYS };
|
||||||
|
|
||||||
Array<AnnotationArray*>* original_annots[NUM_ARRAYS] = { NULL };
|
|
||||||
|
|
||||||
Array<Method*>* original_methods = klass->methods();
|
Array<Method*>* original_methods = klass->methods();
|
||||||
Annotations* annots = klass->annotations();
|
|
||||||
if (annots != NULL) {
|
|
||||||
original_annots[ANNOTATIONS] = annots->methods_annotations();
|
|
||||||
original_annots[PARAMETERS] = annots->methods_parameter_annotations();
|
|
||||||
original_annots[DEFAULTS] = annots->methods_default_annotations();
|
|
||||||
}
|
|
||||||
|
|
||||||
Array<int>* original_ordering = klass->method_ordering();
|
Array<int>* original_ordering = klass->method_ordering();
|
||||||
Array<int>* merged_ordering = Universe::the_empty_int_array();
|
Array<int>* merged_ordering = Universe::the_empty_int_array();
|
||||||
|
|
||||||
int new_size = klass->methods()->length() + new_methods->length();
|
int new_size = klass->methods()->length() + new_methods->length();
|
||||||
|
|
||||||
Array<AnnotationArray*>* merged_annots[NUM_ARRAYS];
|
|
||||||
|
|
||||||
Array<Method*>* merged_methods = MetadataFactory::new_array<Method*>(
|
Array<Method*>* merged_methods = MetadataFactory::new_array<Method*>(
|
||||||
klass->class_loader_data(), new_size, NULL, CHECK);
|
klass->class_loader_data(), new_size, NULL, CHECK);
|
||||||
for (int i = 0; i < NUM_ARRAYS; ++i) {
|
|
||||||
if (original_annots[i] != NULL) {
|
|
||||||
merged_annots[i] = MetadataFactory::new_array<AnnotationArray*>(
|
|
||||||
klass->class_loader_data(), new_size, CHECK);
|
|
||||||
} else {
|
|
||||||
merged_annots[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (original_ordering != NULL && original_ordering->length() > 0) {
|
if (original_ordering != NULL && original_ordering->length() > 0) {
|
||||||
merged_ordering = MetadataFactory::new_array<int>(
|
merged_ordering = MetadataFactory::new_array<int>(
|
||||||
klass->class_loader_data(), new_size, CHECK);
|
klass->class_loader_data(), new_size, CHECK);
|
||||||
@ -1338,12 +1321,6 @@ static void merge_in_new_methods(InstanceKlass* klass,
|
|||||||
(new_method == NULL || orig_method->name() < new_method->name())) {
|
(new_method == NULL || orig_method->name() < new_method->name())) {
|
||||||
merged_methods->at_put(i, orig_method);
|
merged_methods->at_put(i, orig_method);
|
||||||
original_methods->at_put(orig_idx, NULL);
|
original_methods->at_put(orig_idx, NULL);
|
||||||
for (int j = 0; j < NUM_ARRAYS; ++j) {
|
|
||||||
if (merged_annots[j] != NULL) {
|
|
||||||
merged_annots[j]->at_put(i, original_annots[j]->at(orig_idx));
|
|
||||||
original_annots[j]->at_put(orig_idx, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (merged_ordering->length() > 0) {
|
if (merged_ordering->length() > 0) {
|
||||||
merged_ordering->at_put(i, original_ordering->at(orig_idx));
|
merged_ordering->at_put(i, original_ordering->at(orig_idx));
|
||||||
}
|
}
|
||||||
@ -1372,21 +1349,9 @@ static void merge_in_new_methods(InstanceKlass* klass,
|
|||||||
|
|
||||||
// Replace klass methods with new merged lists
|
// Replace klass methods with new merged lists
|
||||||
klass->set_methods(merged_methods);
|
klass->set_methods(merged_methods);
|
||||||
if (annots != NULL) {
|
|
||||||
annots->set_methods_annotations(merged_annots[ANNOTATIONS]);
|
|
||||||
annots->set_methods_parameter_annotations(merged_annots[PARAMETERS]);
|
|
||||||
annots->set_methods_default_annotations(merged_annots[DEFAULTS]);
|
|
||||||
} else {
|
|
||||||
assert(merged_annots[ANNOTATIONS] == NULL, "Must be");
|
|
||||||
assert(merged_annots[PARAMETERS] == NULL, "Must be");
|
|
||||||
assert(merged_annots[DEFAULTS] == NULL, "Must be");
|
|
||||||
}
|
|
||||||
|
|
||||||
ClassLoaderData* cld = klass->class_loader_data();
|
ClassLoaderData* cld = klass->class_loader_data();
|
||||||
MetadataFactory::free_array(cld, original_methods);
|
MetadataFactory::free_array(cld, original_methods);
|
||||||
for (int i = 0; i < NUM_ARRAYS; ++i) {
|
|
||||||
MetadataFactory::free_array(cld, original_annots[i]);
|
|
||||||
}
|
|
||||||
if (original_ordering->length() > 0) {
|
if (original_ordering->length() > 0) {
|
||||||
klass->set_method_ordering(merged_ordering);
|
klass->set_method_ordering(merged_ordering);
|
||||||
MetadataFactory::free_array(cld, original_ordering);
|
MetadataFactory::free_array(cld, original_ordering);
|
||||||
|
@ -274,8 +274,8 @@ ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration(
|
|||||||
// end of a collection, we let CMSTriggerRatio of the (purported) free
|
// end of a collection, we let CMSTriggerRatio of the (purported) free
|
||||||
// space be allocated before initiating a new collection cycle.
|
// space be allocated before initiating a new collection cycle.
|
||||||
//
|
//
|
||||||
void ConcurrentMarkSweepGeneration::init_initiating_occupancy(intx io, intx tr) {
|
void ConcurrentMarkSweepGeneration::init_initiating_occupancy(intx io, uintx tr) {
|
||||||
assert(io <= 100 && tr >= 0 && tr <= 100, "Check the arguments");
|
assert(io <= 100 && tr <= 100, "Check the arguments");
|
||||||
if (io >= 0) {
|
if (io >= 0) {
|
||||||
_initiating_occupancy = (double)io / 100.0;
|
_initiating_occupancy = (double)io / 100.0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -1093,7 +1093,7 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
|
|||||||
|
|
||||||
// getter and initializer for _initiating_occupancy field.
|
// getter and initializer for _initiating_occupancy field.
|
||||||
double initiating_occupancy() const { return _initiating_occupancy; }
|
double initiating_occupancy() const { return _initiating_occupancy; }
|
||||||
void init_initiating_occupancy(intx io, intx tr);
|
void init_initiating_occupancy(intx io, uintx tr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
|
ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
|
||||||
|
@ -4062,15 +4062,36 @@ void CMTask::do_marking_step(double time_target_ms,
|
|||||||
if (_cm->verbose_low()) {
|
if (_cm->verbose_low()) {
|
||||||
gclog_or_tty->print_cr("[%u] we're scanning part "
|
gclog_or_tty->print_cr("[%u] we're scanning part "
|
||||||
"["PTR_FORMAT", "PTR_FORMAT") "
|
"["PTR_FORMAT", "PTR_FORMAT") "
|
||||||
"of region "PTR_FORMAT,
|
"of region "HR_FORMAT,
|
||||||
_worker_id, _finger, _region_limit, _curr_region);
|
_worker_id, _finger, _region_limit,
|
||||||
|
HR_FORMAT_PARAMS(_curr_region));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's iterate over the bitmap of the part of the
|
assert(!_curr_region->isHumongous() || mr.start() == _curr_region->bottom(),
|
||||||
// region that is left.
|
"humongous regions should go around loop once only");
|
||||||
if (mr.is_empty() || _nextMarkBitMap->iterate(&bitmap_closure, mr)) {
|
|
||||||
// We successfully completed iterating over the region. Now,
|
// Some special cases:
|
||||||
// let's give up the region.
|
// If the memory region is empty, we can just give up the region.
|
||||||
|
// If the current region is humongous then we only need to check
|
||||||
|
// the bitmap for the bit associated with the start of the object,
|
||||||
|
// scan the object if it's live, and give up the region.
|
||||||
|
// Otherwise, let's iterate over the bitmap of the part of the region
|
||||||
|
// that is left.
|
||||||
|
// If the iteration is successful, give up the region.
|
||||||
|
if (mr.is_empty()) {
|
||||||
|
giveup_current_region();
|
||||||
|
regular_clock_call();
|
||||||
|
} else if (_curr_region->isHumongous() && mr.start() == _curr_region->bottom()) {
|
||||||
|
if (_nextMarkBitMap->isMarked(mr.start())) {
|
||||||
|
// The object is marked - apply the closure
|
||||||
|
BitMap::idx_t offset = _nextMarkBitMap->heapWordToOffset(mr.start());
|
||||||
|
bitmap_closure.do_bit(offset);
|
||||||
|
}
|
||||||
|
// Even if this task aborted while scanning the humongous object
|
||||||
|
// we can (and should) give up the current region.
|
||||||
|
giveup_current_region();
|
||||||
|
regular_clock_call();
|
||||||
|
} else if (_nextMarkBitMap->iterate(&bitmap_closure, mr)) {
|
||||||
giveup_current_region();
|
giveup_current_region();
|
||||||
regular_clock_call();
|
regular_clock_call();
|
||||||
} else {
|
} else {
|
||||||
|
@ -1893,7 +1893,6 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) :
|
|||||||
_ref_processor_stw(NULL),
|
_ref_processor_stw(NULL),
|
||||||
_process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)),
|
_process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)),
|
||||||
_bot_shared(NULL),
|
_bot_shared(NULL),
|
||||||
_objs_with_preserved_marks(NULL), _preserved_marks_of_objs(NULL),
|
|
||||||
_evac_failure_scan_stack(NULL) ,
|
_evac_failure_scan_stack(NULL) ,
|
||||||
_mark_in_progress(false),
|
_mark_in_progress(false),
|
||||||
_cg1r(NULL), _summary_bytes_used(0),
|
_cg1r(NULL), _summary_bytes_used(0),
|
||||||
@ -4215,22 +4214,15 @@ void G1CollectedHeap::remove_self_forwarding_pointers() {
|
|||||||
assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
|
assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity");
|
||||||
|
|
||||||
// Now restore saved marks, if any.
|
// Now restore saved marks, if any.
|
||||||
if (_objs_with_preserved_marks != NULL) {
|
assert(_objs_with_preserved_marks.size() ==
|
||||||
assert(_preserved_marks_of_objs != NULL, "Both or none.");
|
_preserved_marks_of_objs.size(), "Both or none.");
|
||||||
guarantee(_objs_with_preserved_marks->length() ==
|
while (!_objs_with_preserved_marks.is_empty()) {
|
||||||
_preserved_marks_of_objs->length(), "Both or none.");
|
oop obj = _objs_with_preserved_marks.pop();
|
||||||
for (int i = 0; i < _objs_with_preserved_marks->length(); i++) {
|
markOop m = _preserved_marks_of_objs.pop();
|
||||||
oop obj = _objs_with_preserved_marks->at(i);
|
obj->set_mark(m);
|
||||||
markOop m = _preserved_marks_of_objs->at(i);
|
|
||||||
obj->set_mark(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete the preserved marks growable arrays (allocated on the C heap).
|
|
||||||
delete _objs_with_preserved_marks;
|
|
||||||
delete _preserved_marks_of_objs;
|
|
||||||
_objs_with_preserved_marks = NULL;
|
|
||||||
_preserved_marks_of_objs = NULL;
|
|
||||||
}
|
}
|
||||||
|
_objs_with_preserved_marks.clear(true);
|
||||||
|
_preserved_marks_of_objs.clear(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectedHeap::push_on_evac_failure_scan_stack(oop obj) {
|
void G1CollectedHeap::push_on_evac_failure_scan_stack(oop obj) {
|
||||||
@ -4313,15 +4305,8 @@ void G1CollectedHeap::preserve_mark_if_necessary(oop obj, markOop m) {
|
|||||||
// We want to call the "for_promotion_failure" version only in the
|
// We want to call the "for_promotion_failure" version only in the
|
||||||
// case of a promotion failure.
|
// case of a promotion failure.
|
||||||
if (m->must_be_preserved_for_promotion_failure(obj)) {
|
if (m->must_be_preserved_for_promotion_failure(obj)) {
|
||||||
if (_objs_with_preserved_marks == NULL) {
|
_objs_with_preserved_marks.push(obj);
|
||||||
assert(_preserved_marks_of_objs == NULL, "Both or none.");
|
_preserved_marks_of_objs.push(m);
|
||||||
_objs_with_preserved_marks =
|
|
||||||
new (ResourceObj::C_HEAP, mtGC) GrowableArray<oop>(40, true);
|
|
||||||
_preserved_marks_of_objs =
|
|
||||||
new (ResourceObj::C_HEAP, mtGC) GrowableArray<markOop>(40, true);
|
|
||||||
}
|
|
||||||
_objs_with_preserved_marks->push(obj);
|
|
||||||
_preserved_marks_of_objs->push(m);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "memory/barrierSet.hpp"
|
#include "memory/barrierSet.hpp"
|
||||||
#include "memory/memRegion.hpp"
|
#include "memory/memRegion.hpp"
|
||||||
#include "memory/sharedHeap.hpp"
|
#include "memory/sharedHeap.hpp"
|
||||||
|
#include "utilities/stack.hpp"
|
||||||
|
|
||||||
// A "G1CollectedHeap" is an implementation of a java heap for HotSpot.
|
// A "G1CollectedHeap" is an implementation of a java heap for HotSpot.
|
||||||
// It uses the "Garbage First" heap organization and algorithm, which
|
// It uses the "Garbage First" heap organization and algorithm, which
|
||||||
@ -877,10 +878,9 @@ protected:
|
|||||||
// forwarding pointers to themselves. Reset them.
|
// forwarding pointers to themselves. Reset them.
|
||||||
void remove_self_forwarding_pointers();
|
void remove_self_forwarding_pointers();
|
||||||
|
|
||||||
// When one is non-null, so is the other. Together, they each pair is
|
// Together, these store an object with a preserved mark, and its mark value.
|
||||||
// an object with a preserved mark, and its mark value.
|
Stack<oop, mtGC> _objs_with_preserved_marks;
|
||||||
GrowableArray<oop>* _objs_with_preserved_marks;
|
Stack<markOop, mtGC> _preserved_marks_of_objs;
|
||||||
GrowableArray<markOop>* _preserved_marks_of_objs;
|
|
||||||
|
|
||||||
// Preserve the mark of "obj", if necessary, in preparation for its mark
|
// Preserve the mark of "obj", if necessary, in preparation for its mark
|
||||||
// word being overwritten with a self-forwarding-pointer.
|
// word being overwritten with a self-forwarding-pointer.
|
||||||
|
@ -101,9 +101,6 @@
|
|||||||
"to-space, we will allow regions whose survival rate is up to " \
|
"to-space, we will allow regions whose survival rate is up to " \
|
||||||
"S + (1 - S)*X, where X is this parameter (as a fraction.)") \
|
"S + (1 - S)*X, where X is this parameter (as a fraction.)") \
|
||||||
\
|
\
|
||||||
develop(intx, G1InitYoungSurvRatio, 50, \
|
|
||||||
"Expected Survival Rate for newly allocated bytes") \
|
|
||||||
\
|
|
||||||
develop(bool, G1SATBPrintStubs, false, \
|
develop(bool, G1SATBPrintStubs, false, \
|
||||||
"If true, print generated stubs for the SATB barrier") \
|
"If true, print generated stubs for the SATB barrier") \
|
||||||
\
|
\
|
||||||
|
@ -85,16 +85,20 @@
|
|||||||
"Number of bytes used by the InstanceKlass::singers() array") \
|
"Number of bytes used by the InstanceKlass::singers() array") \
|
||||||
f(class_annotations_bytes, class_annotations, \
|
f(class_annotations_bytes, class_annotations, \
|
||||||
"Size of class annotations") \
|
"Size of class annotations") \
|
||||||
|
f(class_type_annotations_bytes, class_type_annotations, \
|
||||||
|
"Size of class type annotations") \
|
||||||
f(fields_annotations_bytes, fields_annotations, \
|
f(fields_annotations_bytes, fields_annotations, \
|
||||||
"Size of field annotations") \
|
"Size of field annotations") \
|
||||||
|
f(fields_type_annotations_bytes, fields_type_annotations, \
|
||||||
|
"Size of field type annotations") \
|
||||||
f(methods_annotations_bytes, methods_annotations, \
|
f(methods_annotations_bytes, methods_annotations, \
|
||||||
"Size of method annotations") \
|
"Size of method annotations") \
|
||||||
f(methods_parameter_annotations_bytes, methods_parameter_annotations, \
|
f(methods_parameter_annotations_bytes, methods_parameter_annotations, \
|
||||||
"Size of method parameter annotations") \
|
"Size of method parameter annotations") \
|
||||||
|
f(methods_type_annotations_bytes, methods_type_annotations, \
|
||||||
|
"Size of methods type annotations") \
|
||||||
f(methods_default_annotations_bytes, methods_default_annotations, \
|
f(methods_default_annotations_bytes, methods_default_annotations, \
|
||||||
"Size of methods default annotations") \
|
"Size of methods default annotations") \
|
||||||
f(type_annotations_bytes, type_annotations, \
|
|
||||||
"Size of type annotations") \
|
|
||||||
f(annotations_bytes, annotations, \
|
f(annotations_bytes, annotations, \
|
||||||
"Size of all annotations") \
|
"Size of all annotations") \
|
||||||
f(cp_bytes, Cp, \
|
f(cp_bytes, Cp, \
|
||||||
|
@ -1064,11 +1064,11 @@ bool VirtualSpaceList::contains(const void *ptr) {
|
|||||||
//
|
//
|
||||||
// After the GC the compute_new_size() for MetaspaceGC is called to
|
// After the GC the compute_new_size() for MetaspaceGC is called to
|
||||||
// resize the capacity of the metaspaces. The current implementation
|
// resize the capacity of the metaspaces. The current implementation
|
||||||
// is based on the flags MinHeapFreeRatio and MaxHeapFreeRatio used
|
// is based on the flags MinMetaspaceFreeRatio and MaxHeapFreeRatio used
|
||||||
// to resize the Java heap by some GC's. New flags can be implemented
|
// to resize the Java heap by some GC's. New flags can be implemented
|
||||||
// if really needed. MinHeapFreeRatio is used to calculate how much
|
// if really needed. MinHeapFreeRatio is used to calculate how much
|
||||||
// free space is desirable in the metaspace capacity to decide how much
|
// free space is desirable in the metaspace capacity to decide how much
|
||||||
// to increase the HWM. MaxHeapFreeRatio is used to decide how much
|
// to increase the HWM. MaxMetaspaceFreeRatio is used to decide how much
|
||||||
// free space is desirable in the metaspace capacity before decreasing
|
// free space is desirable in the metaspace capacity before decreasing
|
||||||
// the HWM.
|
// the HWM.
|
||||||
|
|
||||||
@ -1166,7 +1166,7 @@ void MetaspaceGC::compute_new_size() {
|
|||||||
size_t capacity_until_GC = vsl->capacity_bytes_sum();
|
size_t capacity_until_GC = vsl->capacity_bytes_sum();
|
||||||
size_t free_after_gc = capacity_until_GC - used_after_gc;
|
size_t free_after_gc = capacity_until_GC - used_after_gc;
|
||||||
|
|
||||||
const double minimum_free_percentage = MinHeapFreeRatio / 100.0;
|
const double minimum_free_percentage = MinMetaspaceFreeRatio / 100.0;
|
||||||
const double maximum_used_percentage = 1.0 - minimum_free_percentage;
|
const double maximum_used_percentage = 1.0 - minimum_free_percentage;
|
||||||
|
|
||||||
const double min_tmp = used_after_gc / maximum_used_percentage;
|
const double min_tmp = used_after_gc / maximum_used_percentage;
|
||||||
@ -1232,8 +1232,8 @@ void MetaspaceGC::compute_new_size() {
|
|||||||
max_shrink_words));
|
max_shrink_words));
|
||||||
|
|
||||||
// Should shrinking be considered?
|
// Should shrinking be considered?
|
||||||
if (MaxHeapFreeRatio < 100) {
|
if (MaxMetaspaceFreeRatio < 100) {
|
||||||
const double maximum_free_percentage = MaxHeapFreeRatio / 100.0;
|
const double maximum_free_percentage = MaxMetaspaceFreeRatio / 100.0;
|
||||||
const double minimum_used_percentage = 1.0 - maximum_free_percentage;
|
const double minimum_used_percentage = 1.0 - maximum_free_percentage;
|
||||||
const double max_tmp = used_after_gc / minimum_used_percentage;
|
const double max_tmp = used_after_gc / minimum_used_percentage;
|
||||||
size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx));
|
size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx));
|
||||||
|
@ -36,16 +36,8 @@ Annotations* Annotations::allocate(ClassLoaderData* loader_data, TRAPS) {
|
|||||||
return new (loader_data, size(), true, THREAD) Annotations();
|
return new (loader_data, size(), true, THREAD) Annotations();
|
||||||
}
|
}
|
||||||
|
|
||||||
Annotations* Annotations::allocate(ClassLoaderData* loader_data,
|
|
||||||
Array<AnnotationArray*>* fa,
|
|
||||||
Array<AnnotationArray*>* ma,
|
|
||||||
Array<AnnotationArray*>* mpa,
|
|
||||||
Array<AnnotationArray*>* mda, TRAPS) {
|
|
||||||
return new (loader_data, size(), true, THREAD) Annotations(fa, ma, mpa, mda);
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper
|
// helper
|
||||||
static void free_contents(ClassLoaderData* loader_data, Array<AnnotationArray*>* p) {
|
void Annotations::free_contents(ClassLoaderData* loader_data, Array<AnnotationArray*>* p) {
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
for (int i = 0; i < p->length(); i++) {
|
for (int i = 0; i < p->length(); i++) {
|
||||||
MetadataFactory::free_array<u1>(loader_data, p->at(i));
|
MetadataFactory::free_array<u1>(loader_data, p->at(i));
|
||||||
@ -59,44 +51,16 @@ void Annotations::deallocate_contents(ClassLoaderData* loader_data) {
|
|||||||
MetadataFactory::free_array<u1>(loader_data, class_annotations());
|
MetadataFactory::free_array<u1>(loader_data, class_annotations());
|
||||||
}
|
}
|
||||||
free_contents(loader_data, fields_annotations());
|
free_contents(loader_data, fields_annotations());
|
||||||
free_contents(loader_data, methods_annotations());
|
|
||||||
free_contents(loader_data, methods_parameter_annotations());
|
|
||||||
free_contents(loader_data, methods_default_annotations());
|
|
||||||
|
|
||||||
// Recursively deallocate optional Annotations linked through this one
|
if (class_type_annotations() != NULL) {
|
||||||
MetadataFactory::free_metadata(loader_data, type_annotations());
|
MetadataFactory::free_array<u1>(loader_data, class_type_annotations());
|
||||||
|
}
|
||||||
|
free_contents(loader_data, fields_type_annotations());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the annotation at 'idnum' to 'anno'.
|
|
||||||
// We don't want to create or extend the array if 'anno' is NULL, since that is the
|
|
||||||
// default value. However, if the array exists and is long enough, we must set NULL values.
|
|
||||||
void Annotations::set_methods_annotations_of(instanceKlassHandle ik,
|
|
||||||
int idnum, AnnotationArray* anno,
|
|
||||||
Array<AnnotationArray*>** md_p,
|
|
||||||
TRAPS) {
|
|
||||||
Array<AnnotationArray*>* md = *md_p;
|
|
||||||
if (md != NULL && md->length() > idnum) {
|
|
||||||
md->at_put(idnum, anno);
|
|
||||||
} else if (anno != NULL) {
|
|
||||||
// create the array
|
|
||||||
int length = MAX2(idnum+1, (int)ik->idnum_allocated_count());
|
|
||||||
md = MetadataFactory::new_array<AnnotationArray*>(ik->class_loader_data(), length, CHECK);
|
|
||||||
if (*md_p != NULL) {
|
|
||||||
// copy the existing entries
|
|
||||||
for (int index = 0; index < (*md_p)->length(); index++) {
|
|
||||||
md->at_put(index, (*md_p)->at(index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set_annotations(md, md_p);
|
|
||||||
md->at_put(idnum, anno);
|
|
||||||
} // if no array and idnum isn't included there is nothing to do
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep created annotations in a global growable array (should be hashtable)
|
|
||||||
// need to add, search, delete when class is unloaded.
|
|
||||||
// Does it need a lock? yes. This sucks.
|
|
||||||
|
|
||||||
// Copy annotations to JVM call or reflection to the java heap.
|
// Copy annotations to JVM call or reflection to the java heap.
|
||||||
|
// The alternative to creating this array and adding to Java heap pressure
|
||||||
|
// is to have a hashtable of the already created typeArrayOops
|
||||||
typeArrayOop Annotations::make_java_array(AnnotationArray* annotations, TRAPS) {
|
typeArrayOop Annotations::make_java_array(AnnotationArray* annotations, TRAPS) {
|
||||||
if (annotations != NULL) {
|
if (annotations != NULL) {
|
||||||
int length = annotations->length();
|
int length = annotations->length();
|
||||||
@ -132,28 +96,15 @@ julong Annotations::count_bytes(Array<AnnotationArray*>* p) {
|
|||||||
void Annotations::collect_statistics(KlassSizeStats *sz) const {
|
void Annotations::collect_statistics(KlassSizeStats *sz) const {
|
||||||
sz->_annotations_bytes = sz->count(this);
|
sz->_annotations_bytes = sz->count(this);
|
||||||
sz->_class_annotations_bytes = sz->count(class_annotations());
|
sz->_class_annotations_bytes = sz->count(class_annotations());
|
||||||
|
sz->_class_type_annotations_bytes = sz->count(class_type_annotations());
|
||||||
sz->_fields_annotations_bytes = count_bytes(fields_annotations());
|
sz->_fields_annotations_bytes = count_bytes(fields_annotations());
|
||||||
sz->_methods_annotations_bytes = count_bytes(methods_annotations());
|
sz->_fields_type_annotations_bytes = count_bytes(fields_type_annotations());
|
||||||
sz->_methods_parameter_annotations_bytes =
|
|
||||||
count_bytes(methods_parameter_annotations());
|
|
||||||
sz->_methods_default_annotations_bytes =
|
|
||||||
count_bytes(methods_default_annotations());
|
|
||||||
|
|
||||||
const Annotations* type_anno = type_annotations();
|
|
||||||
if (type_anno != NULL) {
|
|
||||||
sz->_type_annotations_bytes = sz->count(type_anno);
|
|
||||||
sz->_type_annotations_bytes += sz->count(type_anno->class_annotations());
|
|
||||||
sz->_type_annotations_bytes += count_bytes(type_anno->fields_annotations());
|
|
||||||
sz->_type_annotations_bytes += count_bytes(type_anno->methods_annotations());
|
|
||||||
}
|
|
||||||
|
|
||||||
sz->_annotations_bytes +=
|
sz->_annotations_bytes +=
|
||||||
sz->_class_annotations_bytes +
|
sz->_class_annotations_bytes +
|
||||||
|
sz->_class_type_annotations_bytes +
|
||||||
sz->_fields_annotations_bytes +
|
sz->_fields_annotations_bytes +
|
||||||
sz->_methods_annotations_bytes +
|
sz->_fields_type_annotations_bytes;
|
||||||
sz->_methods_parameter_annotations_bytes +
|
|
||||||
sz->_methods_default_annotations_bytes +
|
|
||||||
sz->_type_annotations_bytes;
|
|
||||||
|
|
||||||
sz->_ro_bytes += sz->_annotations_bytes;
|
sz->_ro_bytes += sz->_annotations_bytes;
|
||||||
}
|
}
|
||||||
@ -165,8 +116,7 @@ void Annotations::collect_statistics(KlassSizeStats *sz) const {
|
|||||||
void Annotations::print_on(outputStream* st) const {
|
void Annotations::print_on(outputStream* st) const {
|
||||||
st->print(BULLET"class_annotations "); class_annotations()->print_value_on(st);
|
st->print(BULLET"class_annotations "); class_annotations()->print_value_on(st);
|
||||||
st->print(BULLET"fields_annotations "); fields_annotations()->print_value_on(st);
|
st->print(BULLET"fields_annotations "); fields_annotations()->print_value_on(st);
|
||||||
st->print(BULLET"methods_annotations "); methods_annotations()->print_value_on(st);
|
st->print(BULLET"class_type_annotations "); class_type_annotations()->print_value_on(st);
|
||||||
st->print(BULLET"methods_parameter_annotations"); methods_parameter_annotations()->print_value_on(st);
|
st->print(BULLET"fields_type_annotations "); fields_type_annotations()->print_value_on(st);
|
||||||
st->print(BULLET"methods_default_annotations "); methods_default_annotations()->print_value_on(st);
|
|
||||||
}
|
}
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
@ -49,38 +49,15 @@ class Annotations: public MetaspaceObj {
|
|||||||
// Annotation objects (byte arrays) for fields, or null if no annotations.
|
// Annotation objects (byte arrays) for fields, or null if no annotations.
|
||||||
// Indices correspond to entries (not indices) in fields array.
|
// Indices correspond to entries (not indices) in fields array.
|
||||||
Array<AnnotationArray*>* _fields_annotations;
|
Array<AnnotationArray*>* _fields_annotations;
|
||||||
// Annotation objects (byte arrays) for methods, or null if no annotations.
|
|
||||||
// Index is the idnum, which is initially the same as the methods array index.
|
|
||||||
Array<AnnotationArray*>* _methods_annotations;
|
|
||||||
// Annotation objects (byte arrays) for methods' parameters, or null if no
|
|
||||||
// such annotations.
|
|
||||||
// Index is the idnum, which is initially the same as the methods array index.
|
|
||||||
Array<AnnotationArray*>* _methods_parameter_annotations;
|
|
||||||
// Annotation objects (byte arrays) for methods' default values, or null if no
|
|
||||||
// such annotations.
|
|
||||||
// Index is the idnum, which is initially the same as the methods array index.
|
|
||||||
Array<AnnotationArray*>* _methods_default_annotations;
|
|
||||||
// Type annotations for this class, or null if none.
|
// Type annotations for this class, or null if none.
|
||||||
Annotations* _type_annotations;
|
AnnotationArray* _class_type_annotations;
|
||||||
|
Array<AnnotationArray*>* _fields_type_annotations;
|
||||||
// Constructor where some some values are known to not be null
|
|
||||||
Annotations(Array<AnnotationArray*>* fa, Array<AnnotationArray*>* ma,
|
|
||||||
Array<AnnotationArray*>* mpa, Array<AnnotationArray*>* mda) :
|
|
||||||
_class_annotations(NULL),
|
|
||||||
_fields_annotations(fa),
|
|
||||||
_methods_annotations(ma),
|
|
||||||
_methods_parameter_annotations(mpa),
|
|
||||||
_methods_default_annotations(mda),
|
|
||||||
_type_annotations(NULL) {}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Allocate instance of this class
|
// Allocate instance of this class
|
||||||
static Annotations* allocate(ClassLoaderData* loader_data, TRAPS);
|
static Annotations* allocate(ClassLoaderData* loader_data, TRAPS);
|
||||||
static Annotations* allocate(ClassLoaderData* loader_data,
|
|
||||||
Array<AnnotationArray*>* fa,
|
static void free_contents(ClassLoaderData* loader_data, Array<AnnotationArray*>* p);
|
||||||
Array<AnnotationArray*>* ma,
|
|
||||||
Array<AnnotationArray*>* mpa,
|
|
||||||
Array<AnnotationArray*>* mda, TRAPS);
|
|
||||||
void deallocate_contents(ClassLoaderData* loader_data);
|
void deallocate_contents(ClassLoaderData* loader_data);
|
||||||
DEBUG_ONLY(bool on_stack() { return false; }) // for template
|
DEBUG_ONLY(bool on_stack() { return false; }) // for template
|
||||||
|
|
||||||
@ -93,61 +70,24 @@ class Annotations: public MetaspaceObj {
|
|||||||
// Constructor to initialize to null
|
// Constructor to initialize to null
|
||||||
Annotations() : _class_annotations(NULL),
|
Annotations() : _class_annotations(NULL),
|
||||||
_fields_annotations(NULL),
|
_fields_annotations(NULL),
|
||||||
_methods_annotations(NULL),
|
_class_type_annotations(NULL),
|
||||||
_methods_parameter_annotations(NULL),
|
_fields_type_annotations(NULL) {}
|
||||||
_methods_default_annotations(NULL),
|
|
||||||
_type_annotations(NULL) {}
|
|
||||||
|
|
||||||
AnnotationArray* class_annotations() const { return _class_annotations; }
|
AnnotationArray* class_annotations() const { return _class_annotations; }
|
||||||
Array<AnnotationArray*>* fields_annotations() const { return _fields_annotations; }
|
Array<AnnotationArray*>* fields_annotations() const { return _fields_annotations; }
|
||||||
Array<AnnotationArray*>* methods_annotations() const { return _methods_annotations; }
|
AnnotationArray* class_type_annotations() const { return _class_type_annotations; }
|
||||||
Array<AnnotationArray*>* methods_parameter_annotations() const { return _methods_parameter_annotations; }
|
Array<AnnotationArray*>* fields_type_annotations() const { return _fields_type_annotations; }
|
||||||
Array<AnnotationArray*>* methods_default_annotations() const { return _methods_default_annotations; }
|
|
||||||
Annotations* type_annotations() const { return _type_annotations; }
|
|
||||||
|
|
||||||
void set_class_annotations(AnnotationArray* md) { _class_annotations = md; }
|
void set_class_annotations(AnnotationArray* md) { _class_annotations = md; }
|
||||||
void set_fields_annotations(Array<AnnotationArray*>* md) { _fields_annotations = md; }
|
void set_fields_annotations(Array<AnnotationArray*>* md) { _fields_annotations = md; }
|
||||||
void set_methods_annotations(Array<AnnotationArray*>* md) { _methods_annotations = md; }
|
void set_class_type_annotations(AnnotationArray* cta) { _class_type_annotations = cta; }
|
||||||
void set_methods_parameter_annotations(Array<AnnotationArray*>* md) { _methods_parameter_annotations = md; }
|
void set_fields_type_annotations(Array<AnnotationArray*>* fta) { _fields_type_annotations = fta; }
|
||||||
void set_methods_default_annotations(Array<AnnotationArray*>* md) { _methods_default_annotations = md; }
|
|
||||||
void set_type_annotations(Annotations* annos) { _type_annotations = annos; }
|
|
||||||
|
|
||||||
// Redefine classes support
|
|
||||||
AnnotationArray* get_method_annotations_of(int idnum)
|
|
||||||
{ return get_method_annotations_from(idnum, _methods_annotations); }
|
|
||||||
|
|
||||||
AnnotationArray* get_method_parameter_annotations_of(int idnum)
|
|
||||||
{ return get_method_annotations_from(idnum, _methods_parameter_annotations); }
|
|
||||||
AnnotationArray* get_method_default_annotations_of(int idnum)
|
|
||||||
{ return get_method_annotations_from(idnum, _methods_default_annotations); }
|
|
||||||
|
|
||||||
|
|
||||||
void set_method_annotations_of(instanceKlassHandle ik,
|
|
||||||
int idnum, AnnotationArray* anno, TRAPS) {
|
|
||||||
set_methods_annotations_of(ik, idnum, anno, &_methods_annotations, THREAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_method_parameter_annotations_of(instanceKlassHandle ik,
|
|
||||||
int idnum, AnnotationArray* anno, TRAPS) {
|
|
||||||
set_methods_annotations_of(ik, idnum, anno, &_methods_parameter_annotations, THREAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_method_default_annotations_of(instanceKlassHandle ik,
|
|
||||||
int idnum, AnnotationArray* anno, TRAPS) {
|
|
||||||
set_methods_annotations_of(ik, idnum, anno, &_methods_default_annotations, THREAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turn metadata annotations into a Java heap object (oop)
|
// Turn metadata annotations into a Java heap object (oop)
|
||||||
static typeArrayOop make_java_array(AnnotationArray* annotations, TRAPS);
|
static typeArrayOop make_java_array(AnnotationArray* annotations, TRAPS);
|
||||||
|
|
||||||
inline AnnotationArray* get_method_annotations_from(int idnum, Array<AnnotationArray*>* annos);
|
|
||||||
void set_annotations(Array<AnnotationArray*>* md, Array<AnnotationArray*>** md_p) { *md_p = md; }
|
|
||||||
|
|
||||||
bool is_klass() const { return false; }
|
bool is_klass() const { return false; }
|
||||||
private:
|
private:
|
||||||
void set_methods_annotations_of(instanceKlassHandle ik,
|
|
||||||
int idnum, AnnotationArray* anno,
|
|
||||||
Array<AnnotationArray*>** md_p, TRAPS);
|
|
||||||
static julong count_bytes(Array<AnnotationArray*>* p);
|
static julong count_bytes(Array<AnnotationArray*>* p);
|
||||||
public:
|
public:
|
||||||
const char* internal_name() const { return "{constant pool}"; }
|
const char* internal_name() const { return "{constant pool}"; }
|
||||||
@ -156,13 +96,4 @@ class Annotations: public MetaspaceObj {
|
|||||||
#endif
|
#endif
|
||||||
void print_value_on(outputStream* st) const;
|
void print_value_on(outputStream* st) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// For method with idnum get the method's Annotations
|
|
||||||
inline AnnotationArray* Annotations::get_method_annotations_from(int idnum, Array<AnnotationArray*>* annos) {
|
|
||||||
if (annos == NULL || annos->length() <= idnum) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return annos->at(idnum);
|
|
||||||
}
|
|
||||||
#endif // SHARE_VM_OOPS_ANNOTATIONS_HPP
|
#endif // SHARE_VM_OOPS_ANNOTATIONS_HPP
|
||||||
|
@ -36,51 +36,26 @@ const u2 ConstMethod::UNSET_IDNUM = 0xFFFF;
|
|||||||
|
|
||||||
ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data,
|
ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data,
|
||||||
int byte_code_size,
|
int byte_code_size,
|
||||||
int compressed_line_number_size,
|
InlineTableSizes* sizes,
|
||||||
int localvariable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index,
|
|
||||||
MethodType method_type,
|
MethodType method_type,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
int size = ConstMethod::size(byte_code_size,
|
int size = ConstMethod::size(byte_code_size, sizes);
|
||||||
compressed_line_number_size,
|
|
||||||
localvariable_table_length,
|
|
||||||
exception_table_length,
|
|
||||||
checked_exceptions_length,
|
|
||||||
method_parameters_length,
|
|
||||||
generic_signature_index);
|
|
||||||
return new (loader_data, size, true, THREAD) ConstMethod(
|
return new (loader_data, size, true, THREAD) ConstMethod(
|
||||||
byte_code_size, compressed_line_number_size, localvariable_table_length,
|
byte_code_size, sizes, method_type, size);
|
||||||
exception_table_length, checked_exceptions_length,
|
|
||||||
method_parameters_length, generic_signature_index,
|
|
||||||
method_type, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstMethod::ConstMethod(int byte_code_size,
|
ConstMethod::ConstMethod(int byte_code_size,
|
||||||
int compressed_line_number_size,
|
InlineTableSizes* sizes,
|
||||||
int localvariable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index,
|
|
||||||
MethodType method_type,
|
MethodType method_type,
|
||||||
int size) {
|
int size) {
|
||||||
|
|
||||||
No_Safepoint_Verifier no_safepoint;
|
No_Safepoint_Verifier no_safepoint;
|
||||||
set_interpreter_kind(Interpreter::invalid);
|
|
||||||
init_fingerprint();
|
init_fingerprint();
|
||||||
set_constants(NULL);
|
set_constants(NULL);
|
||||||
set_stackmap_data(NULL);
|
set_stackmap_data(NULL);
|
||||||
set_code_size(byte_code_size);
|
set_code_size(byte_code_size);
|
||||||
set_constMethod_size(size);
|
set_constMethod_size(size);
|
||||||
set_inlined_tables_length(generic_signature_index,
|
set_inlined_tables_length(sizes);
|
||||||
checked_exceptions_length,
|
|
||||||
compressed_line_number_size,
|
|
||||||
localvariable_table_length,
|
|
||||||
exception_table_length,
|
|
||||||
method_parameters_length);
|
|
||||||
set_method_type(method_type);
|
set_method_type(method_type);
|
||||||
assert(this->size() == size, "wrong size for object");
|
assert(this->size() == size, "wrong size for object");
|
||||||
}
|
}
|
||||||
@ -88,47 +63,70 @@ ConstMethod::ConstMethod(int byte_code_size,
|
|||||||
|
|
||||||
// Deallocate metadata fields associated with ConstMethod*
|
// Deallocate metadata fields associated with ConstMethod*
|
||||||
void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) {
|
void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) {
|
||||||
set_interpreter_kind(Interpreter::invalid);
|
|
||||||
if (stackmap_data() != NULL) {
|
if (stackmap_data() != NULL) {
|
||||||
MetadataFactory::free_array<u1>(loader_data, stackmap_data());
|
MetadataFactory::free_array<u1>(loader_data, stackmap_data());
|
||||||
}
|
}
|
||||||
set_stackmap_data(NULL);
|
set_stackmap_data(NULL);
|
||||||
|
|
||||||
|
// deallocate annotation arrays
|
||||||
|
if (has_method_annotations())
|
||||||
|
MetadataFactory::free_array<u1>(loader_data, method_annotations());
|
||||||
|
if (has_parameter_annotations())
|
||||||
|
MetadataFactory::free_array<u1>(loader_data, parameter_annotations());
|
||||||
|
if (has_type_annotations())
|
||||||
|
MetadataFactory::free_array<u1>(loader_data, type_annotations());
|
||||||
|
if (has_default_annotations())
|
||||||
|
MetadataFactory::free_array<u1>(loader_data, default_annotations());
|
||||||
}
|
}
|
||||||
|
|
||||||
// How big must this constMethodObject be?
|
// How big must this constMethodObject be?
|
||||||
|
|
||||||
int ConstMethod::size(int code_size,
|
int ConstMethod::size(int code_size,
|
||||||
int compressed_line_number_size,
|
InlineTableSizes* sizes) {
|
||||||
int local_variable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index) {
|
|
||||||
int extra_bytes = code_size;
|
int extra_bytes = code_size;
|
||||||
if (compressed_line_number_size > 0) {
|
if (sizes->compressed_linenumber_size() > 0) {
|
||||||
extra_bytes += compressed_line_number_size;
|
extra_bytes += sizes->compressed_linenumber_size();
|
||||||
}
|
}
|
||||||
if (checked_exceptions_length > 0) {
|
if (sizes->checked_exceptions_length() > 0) {
|
||||||
extra_bytes += sizeof(u2);
|
extra_bytes += sizeof(u2);
|
||||||
extra_bytes += checked_exceptions_length * sizeof(CheckedExceptionElement);
|
extra_bytes += sizes->checked_exceptions_length() * sizeof(CheckedExceptionElement);
|
||||||
}
|
}
|
||||||
if (local_variable_table_length > 0) {
|
if (sizes->localvariable_table_length() > 0) {
|
||||||
extra_bytes += sizeof(u2);
|
extra_bytes += sizeof(u2);
|
||||||
extra_bytes +=
|
extra_bytes +=
|
||||||
local_variable_table_length * sizeof(LocalVariableTableElement);
|
sizes->localvariable_table_length() * sizeof(LocalVariableTableElement);
|
||||||
}
|
}
|
||||||
if (exception_table_length > 0) {
|
if (sizes->exception_table_length() > 0) {
|
||||||
extra_bytes += sizeof(u2);
|
extra_bytes += sizeof(u2);
|
||||||
extra_bytes += exception_table_length * sizeof(ExceptionTableElement);
|
extra_bytes += sizes->exception_table_length() * sizeof(ExceptionTableElement);
|
||||||
}
|
}
|
||||||
if (generic_signature_index != 0) {
|
if (sizes->generic_signature_index() != 0) {
|
||||||
extra_bytes += sizeof(u2);
|
extra_bytes += sizeof(u2);
|
||||||
}
|
}
|
||||||
if (method_parameters_length > 0) {
|
if (sizes->method_parameters_length() > 0) {
|
||||||
extra_bytes += sizeof(u2);
|
extra_bytes += sizeof(u2);
|
||||||
extra_bytes += method_parameters_length * sizeof(MethodParametersElement);
|
extra_bytes += sizes->method_parameters_length() * sizeof(MethodParametersElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Align sizes up to a word.
|
||||||
|
extra_bytes = align_size_up(extra_bytes, BytesPerWord);
|
||||||
|
|
||||||
|
// One pointer per annotation array
|
||||||
|
if (sizes->method_annotations_length() > 0) {
|
||||||
|
extra_bytes += sizeof(AnnotationArray*);
|
||||||
|
}
|
||||||
|
if (sizes->parameter_annotations_length() > 0) {
|
||||||
|
extra_bytes += sizeof(AnnotationArray*);
|
||||||
|
}
|
||||||
|
if (sizes->type_annotations_length() > 0) {
|
||||||
|
extra_bytes += sizeof(AnnotationArray*);
|
||||||
|
}
|
||||||
|
if (sizes->default_annotations_length() > 0) {
|
||||||
|
extra_bytes += sizeof(AnnotationArray*);
|
||||||
|
}
|
||||||
|
|
||||||
int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord;
|
int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord;
|
||||||
|
assert(extra_words == extra_bytes/BytesPerWord, "should already be aligned");
|
||||||
return align_object_size(header_size() + extra_words);
|
return align_object_size(header_size() + extra_words);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,12 +143,28 @@ u_char* ConstMethod::compressed_linenumber_table() const {
|
|||||||
return code_end();
|
return code_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Last short in ConstMethod* before annotations
|
||||||
|
u2* ConstMethod::last_u2_element() const {
|
||||||
|
int offset = 0;
|
||||||
|
if (has_method_annotations()) offset++;
|
||||||
|
if (has_parameter_annotations()) offset++;
|
||||||
|
if (has_type_annotations()) offset++;
|
||||||
|
if (has_default_annotations()) offset++;
|
||||||
|
return (u2*)((AnnotationArray**)constMethod_end() - offset) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
u2* ConstMethod::generic_signature_index_addr() const {
|
u2* ConstMethod::generic_signature_index_addr() const {
|
||||||
// Located at the end of the constMethod.
|
// Located at the end of the constMethod.
|
||||||
assert(has_generic_signature(), "called only if generic signature exists");
|
assert(has_generic_signature(), "called only if generic signature exists");
|
||||||
return last_u2_element();
|
return last_u2_element();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u2* ConstMethod::method_parameters_length_addr() const {
|
||||||
|
assert(has_method_parameters(), "called only if table is present");
|
||||||
|
return has_generic_signature() ? (last_u2_element() - 1) :
|
||||||
|
last_u2_element();
|
||||||
|
}
|
||||||
|
|
||||||
u2* ConstMethod::checked_exceptions_length_addr() const {
|
u2* ConstMethod::checked_exceptions_length_addr() const {
|
||||||
// Located immediately before the generic signature index.
|
// Located immediately before the generic signature index.
|
||||||
assert(has_checked_exceptions(), "called only if table is present");
|
assert(has_checked_exceptions(), "called only if table is present");
|
||||||
@ -164,12 +178,6 @@ u2* ConstMethod::checked_exceptions_length_addr() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u2* ConstMethod::method_parameters_length_addr() const {
|
|
||||||
assert(has_method_parameters(), "called only if table is present");
|
|
||||||
return has_generic_signature() ? (last_u2_element() - 1) :
|
|
||||||
last_u2_element();
|
|
||||||
}
|
|
||||||
|
|
||||||
u2* ConstMethod::exception_table_length_addr() const {
|
u2* ConstMethod::exception_table_length_addr() const {
|
||||||
assert(has_exception_handler(), "called only if table is present");
|
assert(has_exception_handler(), "called only if table is present");
|
||||||
if (has_checked_exceptions()) {
|
if (has_checked_exceptions()) {
|
||||||
@ -181,9 +189,9 @@ u2* ConstMethod::exception_table_length_addr() const {
|
|||||||
return (u2*)method_parameters_start() - 1;
|
return (u2*)method_parameters_start() - 1;
|
||||||
} else {
|
} else {
|
||||||
// Else, the exception table is at the end of the constMethod.
|
// Else, the exception table is at the end of the constMethod.
|
||||||
return has_generic_signature() ? (last_u2_element() - 1) :
|
return has_generic_signature() ? (last_u2_element() - 1) :
|
||||||
last_u2_element();
|
last_u2_element();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,32 +212,38 @@ u2* ConstMethod::localvariable_table_length_addr() const {
|
|||||||
// Else, the exception table is at the end of the constMethod.
|
// Else, the exception table is at the end of the constMethod.
|
||||||
return has_generic_signature() ? (last_u2_element() - 1) :
|
return has_generic_signature() ? (last_u2_element() - 1) :
|
||||||
last_u2_element();
|
last_u2_element();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the flags to indicate the presence of these optional fields.
|
// Update the flags to indicate the presence of these optional fields.
|
||||||
void ConstMethod::set_inlined_tables_length(u2 generic_signature_index,
|
void ConstMethod::set_inlined_tables_length(InlineTableSizes* sizes) {
|
||||||
int checked_exceptions_len,
|
_flags = 0;
|
||||||
int compressed_line_number_size,
|
if (sizes->compressed_linenumber_size() > 0)
|
||||||
int localvariable_table_len,
|
|
||||||
int exception_table_len,
|
|
||||||
int method_parameters_len) {
|
|
||||||
assert(_flags == 0, "Error");
|
|
||||||
if (compressed_line_number_size > 0)
|
|
||||||
_flags |= _has_linenumber_table;
|
_flags |= _has_linenumber_table;
|
||||||
if (generic_signature_index != 0)
|
if (sizes->generic_signature_index() != 0)
|
||||||
_flags |= _has_generic_signature;
|
_flags |= _has_generic_signature;
|
||||||
if (method_parameters_len > 0)
|
if (sizes->method_parameters_length() > 0)
|
||||||
_flags |= _has_method_parameters;
|
_flags |= _has_method_parameters;
|
||||||
if (checked_exceptions_len > 0)
|
if (sizes->checked_exceptions_length() > 0)
|
||||||
_flags |= _has_checked_exceptions;
|
_flags |= _has_checked_exceptions;
|
||||||
if (exception_table_len > 0)
|
if (sizes->exception_table_length() > 0)
|
||||||
_flags |= _has_exception_table;
|
_flags |= _has_exception_table;
|
||||||
if (localvariable_table_len > 0)
|
if (sizes->localvariable_table_length() > 0)
|
||||||
_flags |= _has_localvariable_table;
|
_flags |= _has_localvariable_table;
|
||||||
|
|
||||||
|
// annotations, they are all pointer sized embedded objects so don't have
|
||||||
|
// a length embedded also.
|
||||||
|
if (sizes->method_annotations_length() > 0)
|
||||||
|
_flags |= _has_method_annotations;
|
||||||
|
if (sizes->parameter_annotations_length() > 0)
|
||||||
|
_flags |= _has_parameter_annotations;
|
||||||
|
if (sizes->type_annotations_length() > 0)
|
||||||
|
_flags |= _has_type_annotations;
|
||||||
|
if (sizes->default_annotations_length() > 0)
|
||||||
|
_flags |= _has_default_annotations;
|
||||||
|
|
||||||
// This code is extremely brittle and should possibly be revised.
|
// This code is extremely brittle and should possibly be revised.
|
||||||
// The *_length_addr functions walk backwards through the
|
// The *_length_addr functions walk backwards through the
|
||||||
// constMethod data, using each of the length indexes ahead of them,
|
// constMethod data, using each of the length indexes ahead of them,
|
||||||
@ -242,17 +256,17 @@ void ConstMethod::set_inlined_tables_length(u2 generic_signature_index,
|
|||||||
// Also, the servicability agent needs to be informed anytime
|
// Also, the servicability agent needs to be informed anytime
|
||||||
// anything is added here. It might be advisable to have some sort
|
// anything is added here. It might be advisable to have some sort
|
||||||
// of indication of this inline.
|
// of indication of this inline.
|
||||||
if (generic_signature_index != 0)
|
if (sizes->generic_signature_index() != 0)
|
||||||
*(generic_signature_index_addr()) = generic_signature_index;
|
*(generic_signature_index_addr()) = sizes->generic_signature_index();
|
||||||
// New data should probably go here.
|
// New data should probably go here.
|
||||||
if (method_parameters_len > 0)
|
if (sizes->method_parameters_length() > 0)
|
||||||
*(method_parameters_length_addr()) = method_parameters_len;
|
*(method_parameters_length_addr()) = sizes->method_parameters_length();
|
||||||
if (checked_exceptions_len > 0)
|
if (sizes->checked_exceptions_length() > 0)
|
||||||
*(checked_exceptions_length_addr()) = checked_exceptions_len;
|
*(checked_exceptions_length_addr()) = sizes->checked_exceptions_length();
|
||||||
if (exception_table_len > 0)
|
if (sizes->exception_table_length() > 0)
|
||||||
*(exception_table_length_addr()) = exception_table_len;
|
*(exception_table_length_addr()) = sizes->exception_table_length();
|
||||||
if (localvariable_table_len > 0)
|
if (sizes->localvariable_table_length() > 0)
|
||||||
*(localvariable_table_length_addr()) = localvariable_table_len;
|
*(localvariable_table_length_addr()) = sizes->localvariable_table_length();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConstMethod::method_parameters_length() const {
|
int ConstMethod::method_parameters_length() const {
|
||||||
@ -307,6 +321,34 @@ ExceptionTableElement* ConstMethod::exception_table_start() const {
|
|||||||
return (ExceptionTableElement*)addr;
|
return (ExceptionTableElement*)addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnnotationArray** ConstMethod::method_annotations_addr() const {
|
||||||
|
assert(has_method_annotations(), "should only be called if method annotations are present");
|
||||||
|
return (AnnotationArray**)constMethod_end() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationArray** ConstMethod::parameter_annotations_addr() const {
|
||||||
|
assert(has_parameter_annotations(), "should only be called if method parameter annotations are present");
|
||||||
|
int offset = 1;
|
||||||
|
if (has_method_annotations()) offset++;
|
||||||
|
return (AnnotationArray**)constMethod_end() - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationArray** ConstMethod::type_annotations_addr() const {
|
||||||
|
assert(has_type_annotations(), "should only be called if method type annotations are present");
|
||||||
|
int offset = 1;
|
||||||
|
if (has_method_annotations()) offset++;
|
||||||
|
if (has_parameter_annotations()) offset++;
|
||||||
|
return (AnnotationArray**)constMethod_end() - offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationArray** ConstMethod::default_annotations_addr() const {
|
||||||
|
assert(has_default_annotations(), "should only be called if method default annotations are present");
|
||||||
|
int offset = 1;
|
||||||
|
if (has_method_annotations()) offset++;
|
||||||
|
if (has_parameter_annotations()) offset++;
|
||||||
|
if (has_type_annotations()) offset++;
|
||||||
|
return (AnnotationArray**)constMethod_end() - offset;
|
||||||
|
}
|
||||||
|
|
||||||
// Printing
|
// Printing
|
||||||
|
|
||||||
@ -339,8 +381,25 @@ void ConstMethod::collect_statistics(KlassSizeStats *sz) const {
|
|||||||
sz->_bytecode_bytes += (n2 = code_size());
|
sz->_bytecode_bytes += (n2 = code_size());
|
||||||
sz->_stackmap_bytes += (n3 = sz->count_array(stackmap_data()));
|
sz->_stackmap_bytes += (n3 = sz->count_array(stackmap_data()));
|
||||||
|
|
||||||
sz->_method_all_bytes += n1 + n3; // note: n2 is part of n3
|
// Count method annotations
|
||||||
sz->_ro_bytes += n1 + n3;
|
int a1 = 0, a2 = 0, a3 = 0, a4 = 0;
|
||||||
|
if (has_method_annotations()) {
|
||||||
|
sz->_methods_annotations_bytes += (a1 = sz->count_array(method_annotations()));
|
||||||
|
}
|
||||||
|
if (has_parameter_annotations()) {
|
||||||
|
sz->_methods_parameter_annotations_bytes += (a2 = sz->count_array(parameter_annotations()));
|
||||||
|
}
|
||||||
|
if (has_type_annotations()) {
|
||||||
|
sz->_methods_type_annotations_bytes += (a3 = sz->count_array(type_annotations()));
|
||||||
|
}
|
||||||
|
if (has_default_annotations()) {
|
||||||
|
sz->_methods_default_annotations_bytes += (a4 = sz->count_array(default_annotations()));
|
||||||
|
}
|
||||||
|
|
||||||
|
int size_annotations = a1 + a2 + a3 + a4;
|
||||||
|
|
||||||
|
sz->_method_all_bytes += n1 + n3 + size_annotations; // note: n2 is part of n3
|
||||||
|
sz->_ro_bytes += n1 + n3 + size_annotations;
|
||||||
}
|
}
|
||||||
#endif // INCLUDE_SERVICES
|
#endif // INCLUDE_SERVICES
|
||||||
|
|
||||||
@ -352,10 +411,9 @@ void ConstMethod::verify_on(outputStream* st) {
|
|||||||
|
|
||||||
// Verification can occur during oop construction before the method or
|
// Verification can occur during oop construction before the method or
|
||||||
// other fields have been initialized.
|
// other fields have been initialized.
|
||||||
guarantee(is_metadata(), err_msg("Should be metadata " PTR_FORMAT, this));
|
|
||||||
guarantee(method()->is_method(), "should be method");
|
guarantee(method()->is_method(), "should be method");
|
||||||
|
|
||||||
address m_end = (address)((oop*) this + size());
|
address m_end = (address)((intptr_t) this + size());
|
||||||
address compressed_table_start = code_end();
|
address compressed_table_start = code_end();
|
||||||
guarantee(compressed_table_start <= m_end, "invalid method layout");
|
guarantee(compressed_table_start <= m_end, "invalid method layout");
|
||||||
address compressed_table_end = compressed_table_start;
|
address compressed_table_end = compressed_table_start;
|
||||||
|
@ -86,19 +86,22 @@
|
|||||||
// | generic signature index (u2) |
|
// | generic signature index (u2) |
|
||||||
// | (indexed from start of constMethodOop) |
|
// | (indexed from start of constMethodOop) |
|
||||||
// |------------------------------------------------------|
|
// |------------------------------------------------------|
|
||||||
|
// | annotations arrays - method, parameter, type, default|
|
||||||
|
// | pointer to Array<u1> if annotation is present |
|
||||||
|
// |------------------------------------------------------|
|
||||||
//
|
//
|
||||||
// IMPORTANT: If anything gets added here, there need to be changes to
|
// IMPORTANT: If anything gets added here, there need to be changes to
|
||||||
// ensure that ServicabilityAgent doesn't get broken as a result!
|
// ensure that ServicabilityAgent doesn't get broken as a result!
|
||||||
|
|
||||||
|
|
||||||
// Utitily class decribing elements in checked exceptions table inlined in Method*.
|
// Utility class describing elements in checked exceptions table inlined in Method*.
|
||||||
class CheckedExceptionElement VALUE_OBJ_CLASS_SPEC {
|
class CheckedExceptionElement VALUE_OBJ_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
u2 class_cp_index;
|
u2 class_cp_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Utitily class decribing elements in local variable table inlined in Method*.
|
// Utility class describing elements in local variable table inlined in Method*.
|
||||||
class LocalVariableTableElement VALUE_OBJ_CLASS_SPEC {
|
class LocalVariableTableElement VALUE_OBJ_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
u2 start_bci;
|
u2 start_bci;
|
||||||
@ -109,7 +112,7 @@ class LocalVariableTableElement VALUE_OBJ_CLASS_SPEC {
|
|||||||
u2 slot;
|
u2 slot;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Utitily class describing elements in exception table
|
// Utility class describing elements in exception table
|
||||||
class ExceptionTableElement VALUE_OBJ_CLASS_SPEC {
|
class ExceptionTableElement VALUE_OBJ_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
u2 start_pc;
|
u2 start_pc;
|
||||||
@ -127,6 +130,51 @@ class MethodParametersElement VALUE_OBJ_CLASS_SPEC {
|
|||||||
|
|
||||||
class KlassSizeStats;
|
class KlassSizeStats;
|
||||||
|
|
||||||
|
// Class to collect the sizes of ConstMethod inline tables
|
||||||
|
#define INLINE_TABLES_DO(do_element) \
|
||||||
|
do_element(localvariable_table_length) \
|
||||||
|
do_element(compressed_linenumber_size) \
|
||||||
|
do_element(exception_table_length) \
|
||||||
|
do_element(checked_exceptions_length) \
|
||||||
|
do_element(method_parameters_length) \
|
||||||
|
do_element(generic_signature_index) \
|
||||||
|
do_element(method_annotations_length) \
|
||||||
|
do_element(parameter_annotations_length) \
|
||||||
|
do_element(type_annotations_length) \
|
||||||
|
do_element(default_annotations_length)
|
||||||
|
|
||||||
|
#define INLINE_TABLE_DECLARE(sym) int _##sym;
|
||||||
|
#define INLINE_TABLE_PARAM(sym) int sym,
|
||||||
|
#define INLINE_TABLE_INIT(sym) _##sym(sym),
|
||||||
|
#define INLINE_TABLE_NULL(sym) _##sym(0),
|
||||||
|
#define INLINE_TABLE_ACCESSOR(sym) int sym() const { return _##sym; }
|
||||||
|
|
||||||
|
class InlineTableSizes : StackObj {
|
||||||
|
// declarations
|
||||||
|
INLINE_TABLES_DO(INLINE_TABLE_DECLARE)
|
||||||
|
int _end;
|
||||||
|
public:
|
||||||
|
InlineTableSizes(
|
||||||
|
INLINE_TABLES_DO(INLINE_TABLE_PARAM)
|
||||||
|
int end) :
|
||||||
|
INLINE_TABLES_DO(INLINE_TABLE_INIT)
|
||||||
|
_end(end) {}
|
||||||
|
|
||||||
|
// Default constructor for no inlined tables
|
||||||
|
InlineTableSizes() :
|
||||||
|
INLINE_TABLES_DO(INLINE_TABLE_NULL)
|
||||||
|
_end(0) {}
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
INLINE_TABLES_DO(INLINE_TABLE_ACCESSOR)
|
||||||
|
};
|
||||||
|
#undef INLINE_TABLE_ACCESSOR
|
||||||
|
#undef INLINE_TABLE_NULL
|
||||||
|
#undef INLINE_TABLE_INIT
|
||||||
|
#undef INLINE_TABLE_PARAM
|
||||||
|
#undef INLINE_TABLE_DECLARE
|
||||||
|
|
||||||
|
|
||||||
class ConstMethod : public MetaspaceObj {
|
class ConstMethod : public MetaspaceObj {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
|
|
||||||
@ -135,13 +183,17 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
_has_linenumber_table = 1,
|
_has_linenumber_table = 0x0001,
|
||||||
_has_checked_exceptions = 2,
|
_has_checked_exceptions = 0x0002,
|
||||||
_has_localvariable_table = 4,
|
_has_localvariable_table = 0x0004,
|
||||||
_has_exception_table = 8,
|
_has_exception_table = 0x0008,
|
||||||
_has_generic_signature = 16,
|
_has_generic_signature = 0x0010,
|
||||||
_has_method_parameters = 32,
|
_has_method_parameters = 0x0020,
|
||||||
_is_overpass = 64
|
_is_overpass = 0x0040,
|
||||||
|
_has_method_annotations = 0x0080,
|
||||||
|
_has_parameter_annotations = 0x0100,
|
||||||
|
_has_type_annotations = 0x0200,
|
||||||
|
_has_default_annotations = 0x0400
|
||||||
};
|
};
|
||||||
|
|
||||||
// Bit vector of signature
|
// Bit vector of signature
|
||||||
@ -158,8 +210,7 @@ private:
|
|||||||
Array<u1>* _stackmap_data;
|
Array<u1>* _stackmap_data;
|
||||||
|
|
||||||
int _constMethod_size;
|
int _constMethod_size;
|
||||||
jbyte _interpreter_kind;
|
u2 _flags;
|
||||||
jbyte _flags;
|
|
||||||
|
|
||||||
// Size of Java bytecodes allocated immediately after Method*.
|
// Size of Java bytecodes allocated immediately after Method*.
|
||||||
u2 _code_size;
|
u2 _code_size;
|
||||||
@ -174,36 +225,21 @@ private:
|
|||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
ConstMethod(int byte_code_size,
|
ConstMethod(int byte_code_size,
|
||||||
int compressed_line_number_size,
|
InlineTableSizes* sizes,
|
||||||
int localvariable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index,
|
|
||||||
MethodType is_overpass,
|
MethodType is_overpass,
|
||||||
int size);
|
int size);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static ConstMethod* allocate(ClassLoaderData* loader_data,
|
static ConstMethod* allocate(ClassLoaderData* loader_data,
|
||||||
int byte_code_size,
|
int byte_code_size,
|
||||||
int compressed_line_number_size,
|
InlineTableSizes* sizes,
|
||||||
int localvariable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index,
|
|
||||||
MethodType mt,
|
MethodType mt,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
|
||||||
bool is_constMethod() const { return true; }
|
bool is_constMethod() const { return true; }
|
||||||
|
|
||||||
// Inlined tables
|
// Inlined tables
|
||||||
void set_inlined_tables_length(u2 generic_signature_index,
|
void set_inlined_tables_length(InlineTableSizes* sizes);
|
||||||
int checked_exceptions_len,
|
|
||||||
int compressed_line_number_size,
|
|
||||||
int localvariable_table_len,
|
|
||||||
int exception_table_len,
|
|
||||||
int method_parameters_length);
|
|
||||||
|
|
||||||
bool has_generic_signature() const
|
bool has_generic_signature() const
|
||||||
{ return (_flags & _has_generic_signature) != 0; }
|
{ return (_flags & _has_generic_signature) != 0; }
|
||||||
@ -235,10 +271,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void set_interpreter_kind(int kind) { _interpreter_kind = kind; }
|
|
||||||
int interpreter_kind(void) const { return _interpreter_kind; }
|
|
||||||
|
|
||||||
// constant pool
|
// constant pool
|
||||||
ConstantPool* constants() const { return _constants; }
|
ConstantPool* constants() const { return _constants; }
|
||||||
void set_constants(ConstantPool* c) { _constants = c; }
|
void set_constants(ConstantPool* c) { _constants = c; }
|
||||||
@ -307,12 +339,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Size needed
|
// Size needed
|
||||||
static int size(int code_size, int compressed_line_number_size,
|
static int size(int code_size, InlineTableSizes* sizes);
|
||||||
int local_variable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index);
|
|
||||||
|
|
||||||
int size() const { return _constMethod_size;}
|
int size() const { return _constMethod_size;}
|
||||||
void set_constMethod_size(int size) { _constMethod_size = size; }
|
void set_constMethod_size(int size) { _constMethod_size = size; }
|
||||||
@ -354,6 +381,65 @@ public:
|
|||||||
int method_parameters_length() const;
|
int method_parameters_length() const;
|
||||||
MethodParametersElement* method_parameters_start() const;
|
MethodParametersElement* method_parameters_start() const;
|
||||||
|
|
||||||
|
// method annotations
|
||||||
|
bool has_method_annotations() const
|
||||||
|
{ return (_flags & _has_method_annotations) != 0; }
|
||||||
|
|
||||||
|
bool has_parameter_annotations() const
|
||||||
|
{ return (_flags & _has_parameter_annotations) != 0; }
|
||||||
|
|
||||||
|
bool has_type_annotations() const
|
||||||
|
{ return (_flags & _has_type_annotations) != 0; }
|
||||||
|
|
||||||
|
bool has_default_annotations() const
|
||||||
|
{ return (_flags & _has_default_annotations) != 0; }
|
||||||
|
|
||||||
|
|
||||||
|
AnnotationArray** method_annotations_addr() const;
|
||||||
|
AnnotationArray* method_annotations() const {
|
||||||
|
return has_method_annotations() ? *(method_annotations_addr()) : NULL;
|
||||||
|
}
|
||||||
|
void set_method_annotations(AnnotationArray* anno) {
|
||||||
|
*(method_annotations_addr()) = anno;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationArray** parameter_annotations_addr() const;
|
||||||
|
AnnotationArray* parameter_annotations() const {
|
||||||
|
return has_parameter_annotations() ? *(parameter_annotations_addr()) : NULL;
|
||||||
|
}
|
||||||
|
void set_parameter_annotations(AnnotationArray* anno) {
|
||||||
|
*(parameter_annotations_addr()) = anno;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationArray** type_annotations_addr() const;
|
||||||
|
AnnotationArray* type_annotations() const {
|
||||||
|
return has_type_annotations() ? *(type_annotations_addr()) : NULL;
|
||||||
|
}
|
||||||
|
void set_type_annotations(AnnotationArray* anno) {
|
||||||
|
*(type_annotations_addr()) = anno;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationArray** default_annotations_addr() const;
|
||||||
|
AnnotationArray* default_annotations() const {
|
||||||
|
return has_default_annotations() ? *(default_annotations_addr()) : NULL;
|
||||||
|
}
|
||||||
|
void set_default_annotations(AnnotationArray* anno) {
|
||||||
|
*(default_annotations_addr()) = anno;
|
||||||
|
}
|
||||||
|
|
||||||
|
int method_annotations_length() const {
|
||||||
|
return has_method_annotations() ? method_annotations()->length() : 0;
|
||||||
|
}
|
||||||
|
int parameter_annotations_length() const {
|
||||||
|
return has_parameter_annotations() ? parameter_annotations()->length() : 0;
|
||||||
|
}
|
||||||
|
int type_annotations_length() const {
|
||||||
|
return has_type_annotations() ? type_annotations()->length() : 0;
|
||||||
|
}
|
||||||
|
int default_annotations_length() const {
|
||||||
|
return has_default_annotations() ? default_annotations()->length() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
// byte codes
|
// byte codes
|
||||||
void set_code(address code) {
|
void set_code(address code) {
|
||||||
if (code_size() > 0) {
|
if (code_size() > 0) {
|
||||||
@ -409,11 +495,10 @@ private:
|
|||||||
|
|
||||||
// First byte after ConstMethod*
|
// First byte after ConstMethod*
|
||||||
address constMethod_end() const
|
address constMethod_end() const
|
||||||
{ return (address)((oop*)this + _constMethod_size); }
|
{ return (address)((intptr_t*)this + _constMethod_size); }
|
||||||
|
|
||||||
// Last short in ConstMethod*
|
// Last short in ConstMethod*
|
||||||
u2* last_u2_element() const
|
u2* last_u2_element() const;
|
||||||
{ return (u2*)constMethod_end() - 1; }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Printing
|
// Printing
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -402,8 +402,9 @@ oop ConstantPoolCacheEntry::method_type_if_resolved(constantPoolHandle cpool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if INCLUDE_JVMTI
|
||||||
// RedefineClasses() API support:
|
// RedefineClasses() API support:
|
||||||
// If this constantPoolCacheEntry refers to old_method then update it
|
// If this ConstantPoolCacheEntry refers to old_method then update it
|
||||||
// to refer to new_method.
|
// to refer to new_method.
|
||||||
bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
|
bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
|
||||||
Method* new_method, bool * trace_name_printed) {
|
Method* new_method, bool * trace_name_printed) {
|
||||||
@ -461,16 +462,24 @@ bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
// a constant pool cache entry should never contain old or obsolete methods
|
||||||
bool ConstantPoolCacheEntry::check_no_old_entries() {
|
bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() {
|
||||||
if (is_vfinal()) {
|
if (is_vfinal()) {
|
||||||
|
// virtual and final so _f2 contains method ptr instead of vtable index
|
||||||
Metadata* f2 = (Metadata*)_f2;
|
Metadata* f2 = (Metadata*)_f2;
|
||||||
return (f2->is_valid() && f2->is_method() && !((Method*)f2)->is_old());
|
// Return false if _f2 refers to an old or an obsolete method.
|
||||||
} else {
|
// _f2 == NULL || !_f2->is_method() are just as unexpected here.
|
||||||
return (_f1 == NULL || (_f1->is_valid() && _f1->is_method() && !((Method*)_f1)->is_old()));
|
return (f2 != NULL NOT_PRODUCT(&& f2->is_valid()) && f2->is_method() &&
|
||||||
|
!((Method*)f2)->is_old() && !((Method*)f2)->is_obsolete());
|
||||||
|
} else if (_f1 == NULL ||
|
||||||
|
(NOT_PRODUCT(_f1->is_valid() &&) !_f1->is_method())) {
|
||||||
|
// _f1 == NULL || !_f1->is_method() are OK here
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
// return false if _f1 refers to an old or an obsolete method
|
||||||
|
return (NOT_PRODUCT(_f1->is_valid() &&) _f1->is_method() &&
|
||||||
|
!((Method*)_f1)->is_old() && !((Method*)_f1)->is_obsolete());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
bool ConstantPoolCacheEntry::is_interesting_method_entry(Klass* k) {
|
bool ConstantPoolCacheEntry::is_interesting_method_entry(Klass* k) {
|
||||||
if (!is_method_entry()) {
|
if (!is_method_entry()) {
|
||||||
@ -503,13 +512,15 @@ bool ConstantPoolCacheEntry::is_interesting_method_entry(Klass* k) {
|
|||||||
// the method is in the interesting class so the entry is interesting
|
// the method is in the interesting class so the entry is interesting
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif // INCLUDE_JVMTI
|
||||||
|
|
||||||
void ConstantPoolCacheEntry::print(outputStream* st, int index) const {
|
void ConstantPoolCacheEntry::print(outputStream* st, int index) const {
|
||||||
// print separator
|
// print separator
|
||||||
if (index == 0) st->print_cr(" -------------");
|
if (index == 0) st->print_cr(" -------------");
|
||||||
// print entry
|
// print entry
|
||||||
st->print("%3d ("PTR_FORMAT") ", index, (intptr_t)this);
|
st->print("%3d ("PTR_FORMAT") ", index, (intptr_t)this);
|
||||||
st->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index());
|
st->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(),
|
||||||
|
constant_pool_index());
|
||||||
st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f1);
|
st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f1);
|
||||||
st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f2);
|
st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f2);
|
||||||
st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_flags);
|
st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_flags);
|
||||||
@ -553,8 +564,9 @@ void ConstantPoolCache::initialize(intArray& inverse_index_map, intArray& invoke
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_JVMTI
|
||||||
// RedefineClasses() API support:
|
// RedefineClasses() API support:
|
||||||
// If any entry of this constantPoolCache points to any of
|
// If any entry of this ConstantPoolCache points to any of
|
||||||
// old_methods, replace it with the corresponding new_method.
|
// old_methods, replace it with the corresponding new_method.
|
||||||
void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new_methods,
|
void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new_methods,
|
||||||
int methods_length, bool * trace_name_printed) {
|
int methods_length, bool * trace_name_printed) {
|
||||||
@ -573,7 +585,7 @@ void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The constantPoolCache contains entries for several different
|
// The ConstantPoolCache contains entries for several different
|
||||||
// things, but we only care about methods. In fact, we only care
|
// things, but we only care about methods. In fact, we only care
|
||||||
// about methods in the same class as the one that contains the
|
// about methods in the same class as the one that contains the
|
||||||
// old_methods. At this point, we have an interesting entry.
|
// old_methods. At this point, we have an interesting entry.
|
||||||
@ -592,17 +604,25 @@ void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
// the constant pool cache should never contain old or obsolete methods
|
||||||
bool ConstantPoolCache::check_no_old_entries() {
|
bool ConstantPoolCache::check_no_old_or_obsolete_entries() {
|
||||||
for (int i = 1; i < length(); i++) {
|
for (int i = 1; i < length(); i++) {
|
||||||
if (entry_at(i)->is_interesting_method_entry(NULL) &&
|
if (entry_at(i)->is_interesting_method_entry(NULL) &&
|
||||||
!entry_at(i)->check_no_old_entries()) {
|
!entry_at(i)->check_no_old_or_obsolete_entries()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // PRODUCT
|
|
||||||
|
void ConstantPoolCache::dump_cache() {
|
||||||
|
for (int i = 1; i < length(); i++) {
|
||||||
|
if (entry_at(i)->is_interesting_method_entry(NULL)) {
|
||||||
|
entry_at(i)->print(tty, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // INCLUDE_JVMTI
|
||||||
|
|
||||||
|
|
||||||
// Printing
|
// Printing
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -337,16 +337,18 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
|||||||
static ByteSize f2_offset() { return byte_offset_of(ConstantPoolCacheEntry, _f2); }
|
static ByteSize f2_offset() { return byte_offset_of(ConstantPoolCacheEntry, _f2); }
|
||||||
static ByteSize flags_offset() { return byte_offset_of(ConstantPoolCacheEntry, _flags); }
|
static ByteSize flags_offset() { return byte_offset_of(ConstantPoolCacheEntry, _flags); }
|
||||||
|
|
||||||
|
#if INCLUDE_JVMTI
|
||||||
// RedefineClasses() API support:
|
// RedefineClasses() API support:
|
||||||
// If this constantPoolCacheEntry refers to old_method then update it
|
// If this ConstantPoolCacheEntry refers to old_method then update it
|
||||||
// to refer to new_method.
|
// to refer to new_method.
|
||||||
// trace_name_printed is set to true if the current call has
|
// trace_name_printed is set to true if the current call has
|
||||||
// printed the klass name so that other routines in the adjust_*
|
// printed the klass name so that other routines in the adjust_*
|
||||||
// group don't print the klass name.
|
// group don't print the klass name.
|
||||||
bool adjust_method_entry(Method* old_method, Method* new_method,
|
bool adjust_method_entry(Method* old_method, Method* new_method,
|
||||||
bool * trace_name_printed);
|
bool * trace_name_printed);
|
||||||
NOT_PRODUCT(bool check_no_old_entries();)
|
bool check_no_old_or_obsolete_entries();
|
||||||
bool is_interesting_method_entry(Klass* k);
|
bool is_interesting_method_entry(Klass* k);
|
||||||
|
#endif // INCLUDE_JVMTI
|
||||||
|
|
||||||
// Debugging & Printing
|
// Debugging & Printing
|
||||||
void print (outputStream* st, int index) const;
|
void print (outputStream* st, int index) const;
|
||||||
@ -423,15 +425,18 @@ class ConstantPoolCache: public MetaspaceObj {
|
|||||||
return (base_offset() + ConstantPoolCacheEntry::size_in_bytes() * index);
|
return (base_offset() + ConstantPoolCacheEntry::size_in_bytes() * index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_JVMTI
|
||||||
// RedefineClasses() API support:
|
// RedefineClasses() API support:
|
||||||
// If any entry of this constantPoolCache points to any of
|
// If any entry of this ConstantPoolCache points to any of
|
||||||
// old_methods, replace it with the corresponding new_method.
|
// old_methods, replace it with the corresponding new_method.
|
||||||
// trace_name_printed is set to true if the current call has
|
// trace_name_printed is set to true if the current call has
|
||||||
// printed the klass name so that other routines in the adjust_*
|
// printed the klass name so that other routines in the adjust_*
|
||||||
// group don't print the klass name.
|
// group don't print the klass name.
|
||||||
void adjust_method_entries(Method** old_methods, Method** new_methods,
|
void adjust_method_entries(Method** old_methods, Method** new_methods,
|
||||||
int methods_length, bool * trace_name_printed);
|
int methods_length, bool * trace_name_printed);
|
||||||
NOT_PRODUCT(bool check_no_old_entries();)
|
bool check_no_old_or_obsolete_entries();
|
||||||
|
void dump_cache();
|
||||||
|
#endif // INCLUDE_JVMTI
|
||||||
|
|
||||||
// Deallocate - no fields to deallocate
|
// Deallocate - no fields to deallocate
|
||||||
DEBUG_ONLY(bool on_stack() { return false; })
|
DEBUG_ONLY(bool on_stack() { return false; })
|
||||||
|
@ -166,20 +166,19 @@ HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end,
|
|||||||
volatile int InstanceKlass::_total_instanceKlass_count = 0;
|
volatile int InstanceKlass::_total_instanceKlass_count = 0;
|
||||||
|
|
||||||
Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
|
Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
|
||||||
int vtable_len,
|
int vtable_len,
|
||||||
int itable_len,
|
int itable_len,
|
||||||
int static_field_size,
|
int static_field_size,
|
||||||
int nonstatic_oop_map_size,
|
int nonstatic_oop_map_size,
|
||||||
ReferenceType rt,
|
ReferenceType rt,
|
||||||
AccessFlags access_flags,
|
AccessFlags access_flags,
|
||||||
Symbol* name,
|
Symbol* name,
|
||||||
Klass* super_klass,
|
Klass* super_klass,
|
||||||
KlassHandle host_klass,
|
bool is_anonymous,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
|
|
||||||
int size = InstanceKlass::size(vtable_len, itable_len, nonstatic_oop_map_size,
|
int size = InstanceKlass::size(vtable_len, itable_len, nonstatic_oop_map_size,
|
||||||
access_flags.is_interface(),
|
access_flags.is_interface(), is_anonymous);
|
||||||
!host_klass.is_null());
|
|
||||||
|
|
||||||
// Allocation
|
// Allocation
|
||||||
InstanceKlass* ik;
|
InstanceKlass* ik;
|
||||||
@ -187,25 +186,25 @@ Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
|
|||||||
if (name == vmSymbols::java_lang_Class()) {
|
if (name == vmSymbols::java_lang_Class()) {
|
||||||
ik = new (loader_data, size, THREAD) InstanceMirrorKlass(
|
ik = new (loader_data, size, THREAD) InstanceMirrorKlass(
|
||||||
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
||||||
access_flags, !host_klass.is_null());
|
access_flags, is_anonymous);
|
||||||
} else if (name == vmSymbols::java_lang_ClassLoader() ||
|
} else if (name == vmSymbols::java_lang_ClassLoader() ||
|
||||||
(SystemDictionary::ClassLoader_klass_loaded() &&
|
(SystemDictionary::ClassLoader_klass_loaded() &&
|
||||||
super_klass != NULL &&
|
super_klass != NULL &&
|
||||||
super_klass->is_subtype_of(SystemDictionary::ClassLoader_klass()))) {
|
super_klass->is_subtype_of(SystemDictionary::ClassLoader_klass()))) {
|
||||||
ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(
|
ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(
|
||||||
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
||||||
access_flags, !host_klass.is_null());
|
access_flags, is_anonymous);
|
||||||
} else {
|
} else {
|
||||||
// normal class
|
// normal class
|
||||||
ik = new (loader_data, size, THREAD) InstanceKlass(
|
ik = new (loader_data, size, THREAD) InstanceKlass(
|
||||||
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
||||||
access_flags, !host_klass.is_null());
|
access_flags, is_anonymous);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// reference klass
|
// reference klass
|
||||||
ik = new (loader_data, size, THREAD) InstanceRefKlass(
|
ik = new (loader_data, size, THREAD) InstanceRefKlass(
|
||||||
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
|
||||||
access_flags, !host_klass.is_null());
|
access_flags, is_anonymous);
|
||||||
}
|
}
|
||||||
|
|
||||||
Atomic::inc(&_total_instanceKlass_count);
|
Atomic::inc(&_total_instanceKlass_count);
|
||||||
@ -2793,7 +2792,10 @@ void InstanceKlass::print_on(outputStream* st) const {
|
|||||||
st->print("%s", source_debug_extension());
|
st->print("%s", source_debug_extension());
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
st->print(BULLET"annotations: "); annotations()->print_value_on(st); st->cr();
|
st->print(BULLET"class annotations: "); class_annotations()->print_value_on(st); st->cr();
|
||||||
|
st->print(BULLET"class type annotations: "); class_type_annotations()->print_value_on(st); st->cr();
|
||||||
|
st->print(BULLET"field annotations: "); fields_annotations()->print_value_on(st); st->cr();
|
||||||
|
st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr();
|
||||||
{
|
{
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
// PreviousVersionInfo objects returned via PreviousVersionWalker
|
// PreviousVersionInfo objects returned via PreviousVersionWalker
|
||||||
|
@ -155,8 +155,8 @@ class InstanceKlass: public Klass {
|
|||||||
ReferenceType rt,
|
ReferenceType rt,
|
||||||
AccessFlags access_flags,
|
AccessFlags access_flags,
|
||||||
Symbol* name,
|
Symbol* name,
|
||||||
Klass* super_klass,
|
Klass* super_klass,
|
||||||
KlassHandle host_klass,
|
bool is_anonymous,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
|
||||||
InstanceKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
|
InstanceKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
|
||||||
@ -679,19 +679,19 @@ class InstanceKlass: public Klass {
|
|||||||
// annotations support
|
// annotations support
|
||||||
Annotations* annotations() const { return _annotations; }
|
Annotations* annotations() const { return _annotations; }
|
||||||
void set_annotations(Annotations* anno) { _annotations = anno; }
|
void set_annotations(Annotations* anno) { _annotations = anno; }
|
||||||
|
|
||||||
AnnotationArray* class_annotations() const {
|
AnnotationArray* class_annotations() const {
|
||||||
if (annotations() == NULL) return NULL;
|
return (_annotations != NULL) ? _annotations->class_annotations() : NULL;
|
||||||
return annotations()->class_annotations();
|
|
||||||
}
|
}
|
||||||
Array<AnnotationArray*>* fields_annotations() const {
|
Array<AnnotationArray*>* fields_annotations() const {
|
||||||
if (annotations() == NULL) return NULL;
|
return (_annotations != NULL) ? _annotations->fields_annotations() : NULL;
|
||||||
return annotations()->fields_annotations();
|
|
||||||
}
|
}
|
||||||
Annotations* type_annotations() const {
|
AnnotationArray* class_type_annotations() const {
|
||||||
if (annotations() == NULL) return NULL;
|
return (_annotations != NULL) ? _annotations->class_type_annotations() : NULL;
|
||||||
return annotations()->type_annotations();
|
}
|
||||||
|
Array<AnnotationArray*>* fields_type_annotations() const {
|
||||||
|
return (_annotations != NULL) ? _annotations->fields_type_annotations() : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocation
|
// allocation
|
||||||
instanceOop allocate_instance(TRAPS);
|
instanceOop allocate_instance(TRAPS);
|
||||||
|
|
||||||
@ -810,6 +810,7 @@ class InstanceKlass: public Klass {
|
|||||||
|
|
||||||
// Sizing (in words)
|
// Sizing (in words)
|
||||||
static int header_size() { return align_object_offset(sizeof(InstanceKlass)/HeapWordSize); }
|
static int header_size() { return align_object_offset(sizeof(InstanceKlass)/HeapWordSize); }
|
||||||
|
|
||||||
static int size(int vtable_length, int itable_length,
|
static int size(int vtable_length, int itable_length,
|
||||||
int nonstatic_oop_map_size,
|
int nonstatic_oop_map_size,
|
||||||
bool is_interface, bool is_anonymous) {
|
bool is_interface, bool is_anonymous) {
|
||||||
@ -847,10 +848,14 @@ class InstanceKlass: public Klass {
|
|||||||
return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length()));
|
return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Klass** end_of_nonstatic_oop_maps() const {
|
||||||
|
return (Klass**)(start_of_nonstatic_oop_maps() +
|
||||||
|
nonstatic_oop_map_count());
|
||||||
|
}
|
||||||
|
|
||||||
Klass** adr_implementor() const {
|
Klass** adr_implementor() const {
|
||||||
if (is_interface()) {
|
if (is_interface()) {
|
||||||
return (Klass**)(start_of_nonstatic_oop_maps() +
|
return (Klass**)end_of_nonstatic_oop_maps();
|
||||||
nonstatic_oop_map_count());
|
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -862,8 +867,7 @@ class InstanceKlass: public Klass {
|
|||||||
if (adr_impl != NULL) {
|
if (adr_impl != NULL) {
|
||||||
return adr_impl + 1;
|
return adr_impl + 1;
|
||||||
} else {
|
} else {
|
||||||
return (Klass**)(start_of_nonstatic_oop_maps() +
|
return end_of_nonstatic_oop_maps();
|
||||||
nonstatic_oop_map_count());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -610,6 +610,7 @@ void klassVtable::copy_vtable_to(vtableEntry* start) {
|
|||||||
Copy::disjoint_words((HeapWord*)table(), (HeapWord*)start, _length * vtableEntry::size());
|
Copy::disjoint_words((HeapWord*)table(), (HeapWord*)start, _length * vtableEntry::size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_JVMTI
|
||||||
void klassVtable::adjust_method_entries(Method** old_methods, Method** new_methods,
|
void klassVtable::adjust_method_entries(Method** old_methods, Method** new_methods,
|
||||||
int methods_length, bool * trace_name_printed) {
|
int methods_length, bool * trace_name_printed) {
|
||||||
// search the vtable for uses of either obsolete or EMCP methods
|
// search the vtable for uses of either obsolete or EMCP methods
|
||||||
@ -638,11 +639,39 @@ void klassVtable::adjust_method_entries(Method** old_methods, Method** new_metho
|
|||||||
new_method->name()->as_C_string(),
|
new_method->name()->as_C_string(),
|
||||||
new_method->signature()->as_C_string()));
|
new_method->signature()->as_C_string()));
|
||||||
}
|
}
|
||||||
|
// cannot 'break' here; see for-loop comment above.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a vtable should never contain old or obsolete methods
|
||||||
|
bool klassVtable::check_no_old_or_obsolete_entries() {
|
||||||
|
for (int i = 0; i < length(); i++) {
|
||||||
|
Method* m = unchecked_method_at(i);
|
||||||
|
if (m != NULL &&
|
||||||
|
(NOT_PRODUCT(!m->is_valid() ||) m->is_old() || m->is_obsolete())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void klassVtable::dump_vtable() {
|
||||||
|
tty->print_cr("vtable dump --");
|
||||||
|
for (int i = 0; i < length(); i++) {
|
||||||
|
Method* m = unchecked_method_at(i);
|
||||||
|
if (m != NULL) {
|
||||||
|
tty->print(" (%5d) ", i);
|
||||||
|
m->access_flags().print_on(tty);
|
||||||
|
tty->print(" -- ");
|
||||||
|
m->print_name(tty);
|
||||||
|
tty->cr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // INCLUDE_JVMTI
|
||||||
|
|
||||||
// CDS/RedefineClasses support - clear vtables so they can be reinitialized
|
// CDS/RedefineClasses support - clear vtables so they can be reinitialized
|
||||||
void klassVtable::clear_vtable() {
|
void klassVtable::clear_vtable() {
|
||||||
for (int i = 0; i < _length; i++) table()[i].clear();
|
for (int i = 0; i < _length; i++) table()[i].clear();
|
||||||
@ -805,6 +834,7 @@ void klassItable::initialize_with_method(Method* m) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_JVMTI
|
||||||
void klassItable::adjust_method_entries(Method** old_methods, Method** new_methods,
|
void klassItable::adjust_method_entries(Method** old_methods, Method** new_methods,
|
||||||
int methods_length, bool * trace_name_printed) {
|
int methods_length, bool * trace_name_printed) {
|
||||||
// search the itable for uses of either obsolete or EMCP methods
|
// search the itable for uses of either obsolete or EMCP methods
|
||||||
@ -833,13 +863,44 @@ void klassItable::adjust_method_entries(Method** old_methods, Method** new_metho
|
|||||||
new_method->name()->as_C_string(),
|
new_method->name()->as_C_string(),
|
||||||
new_method->signature()->as_C_string()));
|
new_method->signature()->as_C_string()));
|
||||||
}
|
}
|
||||||
// Cannot break because there might be another entry for this method
|
// cannot 'break' here; see for-loop comment above.
|
||||||
}
|
}
|
||||||
ime++;
|
ime++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// an itable should never contain old or obsolete methods
|
||||||
|
bool klassItable::check_no_old_or_obsolete_entries() {
|
||||||
|
itableMethodEntry* ime = method_entry(0);
|
||||||
|
for (int i = 0; i < _size_method_table; i++) {
|
||||||
|
Method* m = ime->method();
|
||||||
|
if (m != NULL &&
|
||||||
|
(NOT_PRODUCT(!m->is_valid() ||) m->is_old() || m->is_obsolete())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ime++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void klassItable::dump_itable() {
|
||||||
|
itableMethodEntry* ime = method_entry(0);
|
||||||
|
tty->print_cr("itable dump --");
|
||||||
|
for (int i = 0; i < _size_method_table; i++) {
|
||||||
|
Method* m = ime->method();
|
||||||
|
if (m != NULL) {
|
||||||
|
tty->print(" (%5d) ", i);
|
||||||
|
m->access_flags().print_on(tty);
|
||||||
|
tty->print(" -- ");
|
||||||
|
m->print_name(tty);
|
||||||
|
tty->cr();
|
||||||
|
}
|
||||||
|
ime++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // INCLUDE_JVMTI
|
||||||
|
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
class InterfaceVisiterClosure : public StackObj {
|
class InterfaceVisiterClosure : public StackObj {
|
||||||
@ -1126,43 +1187,6 @@ void klassVtable::print_statistics() {
|
|||||||
tty->print_cr("%6d bytes total", total);
|
tty->print_cr("%6d bytes total", total);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool klassVtable::check_no_old_entries() {
|
|
||||||
// Check that there really is no entry
|
|
||||||
for (int i = 0; i < length(); i++) {
|
|
||||||
Method* m = unchecked_method_at(i);
|
|
||||||
if (m != NULL) {
|
|
||||||
if (!m->is_valid() || m->is_old()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void klassVtable::dump_vtable() {
|
|
||||||
tty->print_cr("vtable dump --");
|
|
||||||
for (int i = 0; i < length(); i++) {
|
|
||||||
Method* m = unchecked_method_at(i);
|
|
||||||
if (m != NULL) {
|
|
||||||
tty->print(" (%5d) ", i);
|
|
||||||
m->access_flags().print_on(tty);
|
|
||||||
tty->print(" -- ");
|
|
||||||
m->print_name(tty);
|
|
||||||
tty->cr();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool klassItable::check_no_old_entries() {
|
|
||||||
itableMethodEntry* ime = method_entry(0);
|
|
||||||
for(int i = 0; i < _size_method_table; i++) {
|
|
||||||
Method* m = ime->method();
|
|
||||||
if (m != NULL && (!m->is_valid() || m->is_old())) return false;
|
|
||||||
ime++;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int klassItable::_total_classes; // Total no. of classes with itables
|
int klassItable::_total_classes; // Total no. of classes with itables
|
||||||
long klassItable::_total_size; // Total no. of bytes used for itables
|
long klassItable::_total_size; // Total no. of bytes used for itables
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -90,6 +90,7 @@ class klassVtable : public ResourceObj {
|
|||||||
Array<Method*>* methods, AccessFlags class_flags, Handle classloader,
|
Array<Method*>* methods, AccessFlags class_flags, Handle classloader,
|
||||||
Symbol* classname, Array<Klass*>* local_interfaces, TRAPS);
|
Symbol* classname, Array<Klass*>* local_interfaces, TRAPS);
|
||||||
|
|
||||||
|
#if INCLUDE_JVMTI
|
||||||
// RedefineClasses() API support:
|
// RedefineClasses() API support:
|
||||||
// If any entry of this vtable points to any of old_methods,
|
// If any entry of this vtable points to any of old_methods,
|
||||||
// replace it with the corresponding new_method.
|
// replace it with the corresponding new_method.
|
||||||
@ -98,17 +99,15 @@ class klassVtable : public ResourceObj {
|
|||||||
// group don't print the klass name.
|
// group don't print the klass name.
|
||||||
void adjust_method_entries(Method** old_methods, Method** new_methods,
|
void adjust_method_entries(Method** old_methods, Method** new_methods,
|
||||||
int methods_length, bool * trace_name_printed);
|
int methods_length, bool * trace_name_printed);
|
||||||
|
bool check_no_old_or_obsolete_entries();
|
||||||
|
void dump_vtable();
|
||||||
|
#endif // INCLUDE_JVMTI
|
||||||
|
|
||||||
// Debugging code
|
// Debugging code
|
||||||
void print() PRODUCT_RETURN;
|
void print() PRODUCT_RETURN;
|
||||||
void verify(outputStream* st, bool force = false);
|
void verify(outputStream* st, bool force = false);
|
||||||
static void print_statistics() PRODUCT_RETURN;
|
static void print_statistics() PRODUCT_RETURN;
|
||||||
|
|
||||||
#ifndef PRODUCT
|
|
||||||
bool check_no_old_entries();
|
|
||||||
void dump_vtable();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class vtableEntry;
|
friend class vtableEntry;
|
||||||
private:
|
private:
|
||||||
@ -275,6 +274,7 @@ class klassItable : public ResourceObj {
|
|||||||
// Updates
|
// Updates
|
||||||
void initialize_with_method(Method* m);
|
void initialize_with_method(Method* m);
|
||||||
|
|
||||||
|
#if INCLUDE_JVMTI
|
||||||
// RedefineClasses() API support:
|
// RedefineClasses() API support:
|
||||||
// if any entry of this itable points to any of old_methods,
|
// if any entry of this itable points to any of old_methods,
|
||||||
// replace it with the corresponding new_method.
|
// replace it with the corresponding new_method.
|
||||||
@ -283,6 +283,9 @@ class klassItable : public ResourceObj {
|
|||||||
// group don't print the klass name.
|
// group don't print the klass name.
|
||||||
void adjust_method_entries(Method** old_methods, Method** new_methods,
|
void adjust_method_entries(Method** old_methods, Method** new_methods,
|
||||||
int methods_length, bool * trace_name_printed);
|
int methods_length, bool * trace_name_printed);
|
||||||
|
bool check_no_old_or_obsolete_entries();
|
||||||
|
void dump_itable();
|
||||||
|
#endif // INCLUDE_JVMTI
|
||||||
|
|
||||||
// Setup of itable
|
// Setup of itable
|
||||||
static int compute_itable_size(Array<Klass*>* transitive_interfaces);
|
static int compute_itable_size(Array<Klass*>* transitive_interfaces);
|
||||||
@ -307,11 +310,6 @@ class klassItable : public ResourceObj {
|
|||||||
NOT_PRODUCT(static long _total_size;) // Total no. of bytes used for itables
|
NOT_PRODUCT(static long _total_size;) // Total no. of bytes used for itables
|
||||||
|
|
||||||
static void update_stats(int size) PRODUCT_RETURN NOT_PRODUCT({ _total_classes++; _total_size += size; })
|
static void update_stats(int size) PRODUCT_RETURN NOT_PRODUCT({ _total_classes++; _total_size += size; })
|
||||||
|
|
||||||
public:
|
|
||||||
#ifndef PRODUCT
|
|
||||||
bool check_no_old_entries();
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_VM_OOPS_KLASSVTABLE_HPP
|
#endif // SHARE_VM_OOPS_KLASSVTABLE_HPP
|
||||||
|
@ -61,24 +61,14 @@
|
|||||||
Method* Method::allocate(ClassLoaderData* loader_data,
|
Method* Method::allocate(ClassLoaderData* loader_data,
|
||||||
int byte_code_size,
|
int byte_code_size,
|
||||||
AccessFlags access_flags,
|
AccessFlags access_flags,
|
||||||
int compressed_line_number_size,
|
InlineTableSizes* sizes,
|
||||||
int localvariable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index,
|
|
||||||
ConstMethod::MethodType method_type,
|
ConstMethod::MethodType method_type,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
assert(!access_flags.is_native() || byte_code_size == 0,
|
assert(!access_flags.is_native() || byte_code_size == 0,
|
||||||
"native methods should not contain byte codes");
|
"native methods should not contain byte codes");
|
||||||
ConstMethod* cm = ConstMethod::allocate(loader_data,
|
ConstMethod* cm = ConstMethod::allocate(loader_data,
|
||||||
byte_code_size,
|
byte_code_size,
|
||||||
compressed_line_number_size,
|
sizes,
|
||||||
localvariable_table_length,
|
|
||||||
exception_table_length,
|
|
||||||
checked_exceptions_length,
|
|
||||||
method_parameters_length,
|
|
||||||
generic_signature_index,
|
|
||||||
method_type,
|
method_type,
|
||||||
CHECK_NULL);
|
CHECK_NULL);
|
||||||
|
|
||||||
@ -317,14 +307,6 @@ Symbol* Method::klass_name() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Method::set_interpreter_kind() {
|
|
||||||
int kind = Interpreter::method_kind(this);
|
|
||||||
assert(kind != Interpreter::invalid,
|
|
||||||
"interpreter entry must be valid");
|
|
||||||
set_interpreter_kind(kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Attempt to return method oop to original state. Clear any pointers
|
// Attempt to return method oop to original state. Clear any pointers
|
||||||
// (to objects outside the shared spaces). We won't be able to predict
|
// (to objects outside the shared spaces). We won't be able to predict
|
||||||
// where they should point in a new JVM. Further initialize some
|
// where they should point in a new JVM. Further initialize some
|
||||||
@ -332,7 +314,6 @@ void Method::set_interpreter_kind() {
|
|||||||
|
|
||||||
void Method::remove_unshareable_info() {
|
void Method::remove_unshareable_info() {
|
||||||
unlink_method();
|
unlink_method();
|
||||||
set_interpreter_kind();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1045,9 +1026,9 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid,
|
|||||||
|
|
||||||
methodHandle m;
|
methodHandle m;
|
||||||
{
|
{
|
||||||
|
InlineTableSizes sizes;
|
||||||
Method* m_oop = Method::allocate(loader_data, 0,
|
Method* m_oop = Method::allocate(loader_data, 0,
|
||||||
accessFlags_from(flags_bits),
|
accessFlags_from(flags_bits), &sizes,
|
||||||
0, 0, 0, 0, 0, 0,
|
|
||||||
ConstMethod::NORMAL, CHECK_(empty));
|
ConstMethod::NORMAL, CHECK_(empty));
|
||||||
m = methodHandle(THREAD, m_oop);
|
m = methodHandle(THREAD, m_oop);
|
||||||
}
|
}
|
||||||
@ -1096,22 +1077,35 @@ methodHandle Method::clone_with_new_data(methodHandle m, u_char* new_code, int n
|
|||||||
assert(!m->is_native(), "cannot rewrite native methods");
|
assert(!m->is_native(), "cannot rewrite native methods");
|
||||||
// Allocate new Method*
|
// Allocate new Method*
|
||||||
AccessFlags flags = m->access_flags();
|
AccessFlags flags = m->access_flags();
|
||||||
u2 generic_signature_index = m->generic_signature_index();
|
|
||||||
int checked_exceptions_len = m->checked_exceptions_length();
|
ConstMethod* cm = m->constMethod();
|
||||||
int localvariable_len = m->localvariable_table_length();
|
int checked_exceptions_len = cm->checked_exceptions_length();
|
||||||
int exception_table_len = m->exception_table_length();
|
int localvariable_len = cm->localvariable_table_length();
|
||||||
int method_parameters_len = m->method_parameters_length();
|
int exception_table_len = cm->exception_table_length();
|
||||||
|
int method_parameters_len = cm->method_parameters_length();
|
||||||
|
int method_annotations_len = cm->method_annotations_length();
|
||||||
|
int parameter_annotations_len = cm->parameter_annotations_length();
|
||||||
|
int type_annotations_len = cm->type_annotations_length();
|
||||||
|
int default_annotations_len = cm->default_annotations_length();
|
||||||
|
|
||||||
|
InlineTableSizes sizes(
|
||||||
|
localvariable_len,
|
||||||
|
new_compressed_linenumber_size,
|
||||||
|
exception_table_len,
|
||||||
|
checked_exceptions_len,
|
||||||
|
method_parameters_len,
|
||||||
|
cm->generic_signature_index(),
|
||||||
|
method_annotations_len,
|
||||||
|
parameter_annotations_len,
|
||||||
|
type_annotations_len,
|
||||||
|
default_annotations_len,
|
||||||
|
0);
|
||||||
|
|
||||||
ClassLoaderData* loader_data = m->method_holder()->class_loader_data();
|
ClassLoaderData* loader_data = m->method_holder()->class_loader_data();
|
||||||
Method* newm_oop = Method::allocate(loader_data,
|
Method* newm_oop = Method::allocate(loader_data,
|
||||||
new_code_length,
|
new_code_length,
|
||||||
flags,
|
flags,
|
||||||
new_compressed_linenumber_size,
|
&sizes,
|
||||||
localvariable_len,
|
|
||||||
exception_table_len,
|
|
||||||
checked_exceptions_len,
|
|
||||||
method_parameters_len,
|
|
||||||
generic_signature_index,
|
|
||||||
m->method_type(),
|
m->method_type(),
|
||||||
CHECK_(methodHandle()));
|
CHECK_(methodHandle()));
|
||||||
methodHandle newm (THREAD, newm_oop);
|
methodHandle newm (THREAD, newm_oop);
|
||||||
@ -1311,29 +1305,6 @@ void Method::print_short_name(outputStream* st) {
|
|||||||
MethodHandles::print_as_basic_type_signature_on(st, signature(), true);
|
MethodHandles::print_as_basic_type_signature_on(st, signature(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
|
|
||||||
static void reorder_based_on_method_index(Array<Method*>* methods,
|
|
||||||
Array<AnnotationArray*>* annotations,
|
|
||||||
GrowableArray<AnnotationArray*>* temp_array) {
|
|
||||||
if (annotations == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int length = methods->length();
|
|
||||||
int i;
|
|
||||||
// Copy to temp array
|
|
||||||
temp_array->clear();
|
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
temp_array->append(annotations->at(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy back using old method indices
|
|
||||||
for (i = 0; i < length; i++) {
|
|
||||||
Method* m = methods->at(i);
|
|
||||||
annotations->at_put(i, temp_array->at(m->method_idnum()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comparer for sorting an object array containing
|
// Comparer for sorting an object array containing
|
||||||
// Method*s.
|
// Method*s.
|
||||||
static int method_comparator(Method* a, Method* b) {
|
static int method_comparator(Method* a, Method* b) {
|
||||||
@ -1341,48 +1312,13 @@ static int method_comparator(Method* a, Method* b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
|
// This is only done during class loading, so it is OK to assume method_idnum matches the methods() array
|
||||||
void Method::sort_methods(Array<Method*>* methods,
|
void Method::sort_methods(Array<Method*>* methods, bool idempotent) {
|
||||||
Array<AnnotationArray*>* methods_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_parameter_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_default_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_type_annotations,
|
|
||||||
bool idempotent) {
|
|
||||||
int length = methods->length();
|
int length = methods->length();
|
||||||
if (length > 1) {
|
if (length > 1) {
|
||||||
bool do_annotations = false;
|
|
||||||
if (methods_annotations != NULL ||
|
|
||||||
methods_parameter_annotations != NULL ||
|
|
||||||
methods_default_annotations != NULL ||
|
|
||||||
methods_type_annotations != NULL) {
|
|
||||||
do_annotations = true;
|
|
||||||
}
|
|
||||||
if (do_annotations) {
|
|
||||||
// Remember current method ordering so we can reorder annotations
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
Method* m = methods->at(i);
|
|
||||||
m->set_method_idnum(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
No_Safepoint_Verifier nsv;
|
No_Safepoint_Verifier nsv;
|
||||||
QuickSort::sort<Method*>(methods->data(), length, method_comparator, idempotent);
|
QuickSort::sort<Method*>(methods->data(), length, method_comparator, idempotent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort annotations if necessary
|
|
||||||
assert(methods_annotations == NULL || methods_annotations->length() == methods->length(), "");
|
|
||||||
assert(methods_parameter_annotations == NULL || methods_parameter_annotations->length() == methods->length(), "");
|
|
||||||
assert(methods_default_annotations == NULL || methods_default_annotations->length() == methods->length(), "");
|
|
||||||
assert(methods_type_annotations == NULL || methods_type_annotations->length() == methods->length(), "");
|
|
||||||
if (do_annotations) {
|
|
||||||
ResourceMark rm;
|
|
||||||
// Allocate temporary storage
|
|
||||||
GrowableArray<AnnotationArray*>* temp_array = new GrowableArray<AnnotationArray*>(length);
|
|
||||||
reorder_based_on_method_index(methods, methods_annotations, temp_array);
|
|
||||||
reorder_based_on_method_index(methods, methods_parameter_annotations, temp_array);
|
|
||||||
reorder_based_on_method_index(methods, methods_default_annotations, temp_array);
|
|
||||||
reorder_based_on_method_index(methods, methods_type_annotations, temp_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset method ordering
|
// Reset method ordering
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
Method* m = methods->at(i);
|
Method* m = methods->at(i);
|
||||||
@ -1393,9 +1329,9 @@ void Method::sort_methods(Array<Method*>* methods,
|
|||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
// Non-product code
|
// Non-product code unless JVM/TI needs it
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#if !defined(PRODUCT) || INCLUDE_JVMTI
|
||||||
class SignatureTypePrinter : public SignatureTypeNames {
|
class SignatureTypePrinter : public SignatureTypeNames {
|
||||||
private:
|
private:
|
||||||
outputStream* _st;
|
outputStream* _st;
|
||||||
@ -1430,8 +1366,13 @@ void Method::print_name(outputStream* st) {
|
|||||||
sig.print_parameters();
|
sig.print_parameters();
|
||||||
st->print(")");
|
st->print(")");
|
||||||
}
|
}
|
||||||
|
#endif // !PRODUCT || INCLUDE_JVMTI
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
// Non-product code
|
||||||
|
|
||||||
|
#ifndef PRODUCT
|
||||||
void Method::print_codes_on(outputStream* st) const {
|
void Method::print_codes_on(outputStream* st) const {
|
||||||
print_codes_on(0, code_size(), st);
|
print_codes_on(0, code_size(), st);
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,7 @@ class LocalVariableTableElement;
|
|||||||
class AdapterHandlerEntry;
|
class AdapterHandlerEntry;
|
||||||
class MethodData;
|
class MethodData;
|
||||||
class ConstMethod;
|
class ConstMethod;
|
||||||
|
class InlineTableSizes;
|
||||||
class KlassSizeStats;
|
class KlassSizeStats;
|
||||||
|
|
||||||
class Method : public Metadata {
|
class Method : public Metadata {
|
||||||
@ -157,12 +158,7 @@ class Method : public Metadata {
|
|||||||
static Method* allocate(ClassLoaderData* loader_data,
|
static Method* allocate(ClassLoaderData* loader_data,
|
||||||
int byte_code_size,
|
int byte_code_size,
|
||||||
AccessFlags access_flags,
|
AccessFlags access_flags,
|
||||||
int compressed_line_number_size,
|
InlineTableSizes* sizes,
|
||||||
int localvariable_table_length,
|
|
||||||
int exception_table_length,
|
|
||||||
int checked_exceptions_length,
|
|
||||||
int method_parameters_length,
|
|
||||||
u2 generic_signature_index,
|
|
||||||
ConstMethod::MethodType method_type,
|
ConstMethod::MethodType method_type,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
|
||||||
@ -207,33 +203,17 @@ class Method : public Metadata {
|
|||||||
|
|
||||||
// annotations support
|
// annotations support
|
||||||
AnnotationArray* annotations() const {
|
AnnotationArray* annotations() const {
|
||||||
InstanceKlass* ik = method_holder();
|
return constMethod()->method_annotations();
|
||||||
if (ik->annotations() == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return ik->annotations()->get_method_annotations_of(method_idnum());
|
|
||||||
}
|
}
|
||||||
AnnotationArray* parameter_annotations() const {
|
AnnotationArray* parameter_annotations() const {
|
||||||
InstanceKlass* ik = method_holder();
|
return constMethod()->parameter_annotations();
|
||||||
if (ik->annotations() == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return ik->annotations()->get_method_parameter_annotations_of(method_idnum());
|
|
||||||
}
|
}
|
||||||
AnnotationArray* annotation_default() const {
|
AnnotationArray* annotation_default() const {
|
||||||
InstanceKlass* ik = method_holder();
|
return constMethod()->default_annotations();
|
||||||
if (ik->annotations() == NULL) {
|
}
|
||||||
return NULL;
|
AnnotationArray* type_annotations() const {
|
||||||
}
|
return constMethod()->type_annotations();
|
||||||
return ik->annotations()->get_method_default_annotations_of(method_idnum());
|
|
||||||
}
|
}
|
||||||
AnnotationArray* type_annotations() const {
|
|
||||||
InstanceKlass* ik = method_holder();
|
|
||||||
Annotations* type_annos = ik->type_annotations();
|
|
||||||
if (type_annos == NULL)
|
|
||||||
return NULL;
|
|
||||||
return type_annos->get_method_annotations_of(method_idnum());
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CC_INTERP
|
#ifdef CC_INTERP
|
||||||
void set_result_index(BasicType type);
|
void set_result_index(BasicType type);
|
||||||
@ -439,13 +419,6 @@ class Method : public Metadata {
|
|||||||
address interpreter_entry() const { return _i2i_entry; }
|
address interpreter_entry() const { return _i2i_entry; }
|
||||||
// Only used when first initialize so we can set _i2i_entry and _from_interpreted_entry
|
// Only used when first initialize so we can set _i2i_entry and _from_interpreted_entry
|
||||||
void set_interpreter_entry(address entry) { _i2i_entry = entry; _from_interpreted_entry = entry; }
|
void set_interpreter_entry(address entry) { _i2i_entry = entry; _from_interpreted_entry = entry; }
|
||||||
int interpreter_kind(void) {
|
|
||||||
return constMethod()->interpreter_kind();
|
|
||||||
}
|
|
||||||
void set_interpreter_kind();
|
|
||||||
void set_interpreter_kind(int kind) {
|
|
||||||
constMethod()->set_interpreter_kind(kind);
|
|
||||||
}
|
|
||||||
|
|
||||||
// native function (used for native methods only)
|
// native function (used for native methods only)
|
||||||
enum {
|
enum {
|
||||||
@ -800,16 +773,15 @@ class Method : public Metadata {
|
|||||||
static bool has_unloaded_classes_in_signature(methodHandle m, TRAPS);
|
static bool has_unloaded_classes_in_signature(methodHandle m, TRAPS);
|
||||||
|
|
||||||
// Printing
|
// Printing
|
||||||
void print_short_name(outputStream* st = tty) /*PRODUCT_RETURN*/; // prints as klassname::methodname; Exposed so field engineers can debug VM
|
void print_short_name(outputStream* st = tty); // prints as klassname::methodname; Exposed so field engineers can debug VM
|
||||||
|
#if INCLUDE_JVMTI
|
||||||
|
void print_name(outputStream* st = tty); // prints as "virtual void foo(int)"; exposed for TraceRedefineClasses
|
||||||
|
#else
|
||||||
void print_name(outputStream* st = tty) PRODUCT_RETURN; // prints as "virtual void foo(int)"
|
void print_name(outputStream* st = tty) PRODUCT_RETURN; // prints as "virtual void foo(int)"
|
||||||
|
#endif
|
||||||
|
|
||||||
// Helper routine used for method sorting
|
// Helper routine used for method sorting
|
||||||
static void sort_methods(Array<Method*>* methods,
|
static void sort_methods(Array<Method*>* methods, bool idempotent = false);
|
||||||
Array<AnnotationArray*>* methods_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_parameter_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_default_annotations,
|
|
||||||
Array<AnnotationArray*>* methods_type_annotations,
|
|
||||||
bool idempotent = false);
|
|
||||||
|
|
||||||
// Deallocation function for redefine classes or if an error occurs
|
// Deallocation function for redefine classes or if an error occurs
|
||||||
void deallocate_contents(ClassLoaderData* loader_data);
|
void deallocate_contents(ClassLoaderData* loader_data);
|
||||||
|
@ -618,6 +618,9 @@
|
|||||||
\
|
\
|
||||||
product(intx, LiveNodeCountInliningCutoff, 20000, \
|
product(intx, LiveNodeCountInliningCutoff, 20000, \
|
||||||
"max number of live nodes in a method") \
|
"max number of live nodes in a method") \
|
||||||
|
\
|
||||||
|
diagnostic(bool, OptimizeExpensiveOps, true, \
|
||||||
|
"Find best control for expensive operations") \
|
||||||
|
|
||||||
|
|
||||||
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)
|
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)
|
||||||
|
@ -409,6 +409,13 @@ void Compile::remove_useless_nodes(Unique_Node_List &useful) {
|
|||||||
remove_macro_node(n);
|
remove_macro_node(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Remove useless expensive node
|
||||||
|
for (int i = C->expensive_count()-1; i >= 0; i--) {
|
||||||
|
Node* n = C->expensive_node(i);
|
||||||
|
if (!useful.member(n)) {
|
||||||
|
remove_expensive_node(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
// clean up the late inline lists
|
// clean up the late inline lists
|
||||||
remove_useless_late_inlines(&_string_late_inlines, useful);
|
remove_useless_late_inlines(&_string_late_inlines, useful);
|
||||||
remove_useless_late_inlines(&_late_inlines, useful);
|
remove_useless_late_inlines(&_late_inlines, useful);
|
||||||
@ -1061,6 +1068,7 @@ void Compile::Init(int aliaslevel) {
|
|||||||
_intrinsics = NULL;
|
_intrinsics = NULL;
|
||||||
_macro_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL);
|
_macro_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL);
|
||||||
_predicate_opaqs = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL);
|
_predicate_opaqs = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL);
|
||||||
|
_expensive_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL);
|
||||||
register_library_intrinsics();
|
register_library_intrinsics();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1927,6 +1935,10 @@ void Compile::Optimize() {
|
|||||||
|
|
||||||
if (failing()) return;
|
if (failing()) return;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
// Perform escape analysis
|
// Perform escape analysis
|
||||||
if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) {
|
if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) {
|
||||||
if (has_loops()) {
|
if (has_loops()) {
|
||||||
@ -3010,6 +3022,15 @@ bool Compile::final_graph_reshaping() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expensive nodes have their control input set to prevent the GVN
|
||||||
|
// from freely commoning them. There's no GVN beyond this point so
|
||||||
|
// no need to keep the control input. We want the expensive nodes to
|
||||||
|
// be freely moved to the least frequent code path by gcm.
|
||||||
|
assert(OptimizeExpensiveOps || expensive_count() == 0, "optimization off but list non empty?");
|
||||||
|
for (int i = 0; i < expensive_count(); i++) {
|
||||||
|
_expensive_nodes->at(i)->set_req(0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
Final_Reshape_Counts frc;
|
Final_Reshape_Counts frc;
|
||||||
|
|
||||||
// Visit everybody reachable!
|
// Visit everybody reachable!
|
||||||
@ -3525,3 +3546,126 @@ void Compile::dump_inlining() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Compile::cmp_expensive_nodes(Node* n1, Node* n2) {
|
||||||
|
if (n1->Opcode() < n2->Opcode()) return -1;
|
||||||
|
else if (n1->Opcode() > n2->Opcode()) return 1;
|
||||||
|
|
||||||
|
assert(n1->req() == n2->req(), err_msg_res("can't compare %s nodes: n1->req() = %d, n2->req() = %d", NodeClassNames[n1->Opcode()], n1->req(), n2->req()));
|
||||||
|
for (uint i = 1; i < n1->req(); i++) {
|
||||||
|
if (n1->in(i) < n2->in(i)) return -1;
|
||||||
|
else if (n1->in(i) > n2->in(i)) return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Compile::cmp_expensive_nodes(Node** n1p, Node** n2p) {
|
||||||
|
Node* n1 = *n1p;
|
||||||
|
Node* n2 = *n2p;
|
||||||
|
|
||||||
|
return cmp_expensive_nodes(n1, n2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compile::sort_expensive_nodes() {
|
||||||
|
if (!expensive_nodes_sorted()) {
|
||||||
|
_expensive_nodes->sort(cmp_expensive_nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Compile::expensive_nodes_sorted() const {
|
||||||
|
for (int i = 1; i < _expensive_nodes->length(); i++) {
|
||||||
|
if (cmp_expensive_nodes(_expensive_nodes->adr_at(i), _expensive_nodes->adr_at(i-1)) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Compile::should_optimize_expensive_nodes(PhaseIterGVN &igvn) {
|
||||||
|
if (_expensive_nodes->length() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(OptimizeExpensiveOps, "optimization off?");
|
||||||
|
|
||||||
|
// Take this opportunity to remove dead nodes from the list
|
||||||
|
int j = 0;
|
||||||
|
for (int i = 0; i < _expensive_nodes->length(); i++) {
|
||||||
|
Node* n = _expensive_nodes->at(i);
|
||||||
|
if (!n->is_unreachable(igvn)) {
|
||||||
|
assert(n->is_expensive(), "should be expensive");
|
||||||
|
_expensive_nodes->at_put(j, n);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_expensive_nodes->trunc_to(j);
|
||||||
|
|
||||||
|
// Then sort the list so that similar nodes are next to each other
|
||||||
|
// and check for at least two nodes of identical kind with same data
|
||||||
|
// inputs.
|
||||||
|
sort_expensive_nodes();
|
||||||
|
|
||||||
|
for (int i = 0; i < _expensive_nodes->length()-1; i++) {
|
||||||
|
if (cmp_expensive_nodes(_expensive_nodes->adr_at(i), _expensive_nodes->adr_at(i+1)) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compile::cleanup_expensive_nodes(PhaseIterGVN &igvn) {
|
||||||
|
if (_expensive_nodes->length() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(OptimizeExpensiveOps, "optimization off?");
|
||||||
|
|
||||||
|
// Sort to bring similar nodes next to each other and clear the
|
||||||
|
// control input of nodes for which there's only a single copy.
|
||||||
|
sort_expensive_nodes();
|
||||||
|
|
||||||
|
int j = 0;
|
||||||
|
int identical = 0;
|
||||||
|
int i = 0;
|
||||||
|
for (; i < _expensive_nodes->length()-1; i++) {
|
||||||
|
assert(j <= i, "can't write beyond current index");
|
||||||
|
if (_expensive_nodes->at(i)->Opcode() == _expensive_nodes->at(i+1)->Opcode()) {
|
||||||
|
identical++;
|
||||||
|
_expensive_nodes->at_put(j++, _expensive_nodes->at(i));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (identical > 0) {
|
||||||
|
_expensive_nodes->at_put(j++, _expensive_nodes->at(i));
|
||||||
|
identical = 0;
|
||||||
|
} else {
|
||||||
|
Node* n = _expensive_nodes->at(i);
|
||||||
|
igvn.hash_delete(n);
|
||||||
|
n->set_req(0, NULL);
|
||||||
|
igvn.hash_insert(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (identical > 0) {
|
||||||
|
_expensive_nodes->at_put(j++, _expensive_nodes->at(i));
|
||||||
|
} else if (_expensive_nodes->length() >= 1) {
|
||||||
|
Node* n = _expensive_nodes->at(i);
|
||||||
|
igvn.hash_delete(n);
|
||||||
|
n->set_req(0, NULL);
|
||||||
|
igvn.hash_insert(n);
|
||||||
|
}
|
||||||
|
_expensive_nodes->trunc_to(j);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Compile::add_expensive_node(Node * n) {
|
||||||
|
assert(!_expensive_nodes->contains(n), "duplicate entry in expensive list");
|
||||||
|
assert(n->is_expensive(), "expensive nodes with non-null control here only");
|
||||||
|
assert(!n->is_CFG() && !n->is_Mem(), "no cfg or memory nodes here");
|
||||||
|
if (OptimizeExpensiveOps) {
|
||||||
|
_expensive_nodes->append(n);
|
||||||
|
} else {
|
||||||
|
// Clear control input and let IGVN optimize expensive nodes if
|
||||||
|
// OptimizeExpensiveOps is off.
|
||||||
|
n->set_req(0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -314,6 +314,7 @@ class Compile : public Phase {
|
|||||||
GrowableArray<CallGenerator*>* _intrinsics; // List of intrinsics.
|
GrowableArray<CallGenerator*>* _intrinsics; // List of intrinsics.
|
||||||
GrowableArray<Node*>* _macro_nodes; // List of nodes which need to be expanded before matching.
|
GrowableArray<Node*>* _macro_nodes; // List of nodes which need to be expanded before matching.
|
||||||
GrowableArray<Node*>* _predicate_opaqs; // List of Opaque1 nodes for the loop predicates.
|
GrowableArray<Node*>* _predicate_opaqs; // List of Opaque1 nodes for the loop predicates.
|
||||||
|
GrowableArray<Node*>* _expensive_nodes; // List of nodes that are expensive to compute and that we'd better not let the GVN freely common
|
||||||
ConnectionGraph* _congraph;
|
ConnectionGraph* _congraph;
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
IdealGraphPrinter* _printer;
|
IdealGraphPrinter* _printer;
|
||||||
@ -398,6 +399,13 @@ class Compile : public Phase {
|
|||||||
GrowableArray<PrintInliningBuffer>* _print_inlining_list;
|
GrowableArray<PrintInliningBuffer>* _print_inlining_list;
|
||||||
int _print_inlining;
|
int _print_inlining;
|
||||||
|
|
||||||
|
// Only keep nodes in the expensive node list that need to be optimized
|
||||||
|
void cleanup_expensive_nodes(PhaseIterGVN &igvn);
|
||||||
|
// Use for sorting expensive nodes to bring similar nodes together
|
||||||
|
static int cmp_expensive_nodes(Node** n1, Node** n2);
|
||||||
|
// Expensive nodes list already sorted?
|
||||||
|
bool expensive_nodes_sorted() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
outputStream* print_inlining_stream() const {
|
outputStream* print_inlining_stream() const {
|
||||||
@ -573,8 +581,10 @@ class Compile : public Phase {
|
|||||||
|
|
||||||
int macro_count() { return _macro_nodes->length(); }
|
int macro_count() { return _macro_nodes->length(); }
|
||||||
int predicate_count() { return _predicate_opaqs->length();}
|
int predicate_count() { return _predicate_opaqs->length();}
|
||||||
|
int expensive_count() { return _expensive_nodes->length(); }
|
||||||
Node* macro_node(int idx) { return _macro_nodes->at(idx); }
|
Node* macro_node(int idx) { return _macro_nodes->at(idx); }
|
||||||
Node* predicate_opaque1_node(int idx) { return _predicate_opaqs->at(idx);}
|
Node* predicate_opaque1_node(int idx) { return _predicate_opaqs->at(idx);}
|
||||||
|
Node* expensive_node(int idx) { return _expensive_nodes->at(idx); }
|
||||||
ConnectionGraph* congraph() { return _congraph;}
|
ConnectionGraph* congraph() { return _congraph;}
|
||||||
void set_congraph(ConnectionGraph* congraph) { _congraph = congraph;}
|
void set_congraph(ConnectionGraph* congraph) { _congraph = congraph;}
|
||||||
void add_macro_node(Node * n) {
|
void add_macro_node(Node * n) {
|
||||||
@ -592,6 +602,12 @@ class Compile : public Phase {
|
|||||||
_predicate_opaqs->remove(n);
|
_predicate_opaqs->remove(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void add_expensive_node(Node * n);
|
||||||
|
void remove_expensive_node(Node * n) {
|
||||||
|
if (_expensive_nodes->contains(n)) {
|
||||||
|
_expensive_nodes->remove(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
void add_predicate_opaq(Node * n) {
|
void add_predicate_opaq(Node * n) {
|
||||||
assert(!_predicate_opaqs->contains(n), " duplicate entry in predicate opaque1");
|
assert(!_predicate_opaqs->contains(n), " duplicate entry in predicate opaque1");
|
||||||
assert(_macro_nodes->contains(n), "should have already been in macro list");
|
assert(_macro_nodes->contains(n), "should have already been in macro list");
|
||||||
@ -604,6 +620,13 @@ class Compile : public Phase {
|
|||||||
return _predicate_opaqs->contains(n);
|
return _predicate_opaqs->contains(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Are there candidate expensive nodes for optimization?
|
||||||
|
bool should_optimize_expensive_nodes(PhaseIterGVN &igvn);
|
||||||
|
// Check whether n1 and n2 are similar
|
||||||
|
static int cmp_expensive_nodes(Node* n1, Node* n2);
|
||||||
|
// Sort expensive nodes to locate similar expensive nodes
|
||||||
|
void sort_expensive_nodes();
|
||||||
|
|
||||||
// Compilation environment.
|
// Compilation environment.
|
||||||
Arena* comp_arena() { return &_comp_arena; }
|
Arena* comp_arena() { return &_comp_arena; }
|
||||||
ciEnv* env() const { return _env; }
|
ciEnv* env() const { return _env; }
|
||||||
|
@ -1653,7 +1653,7 @@ void LibraryCallKit::finish_pow_exp(Node* result, Node* x, Node* y, const TypeFu
|
|||||||
// really odd corner cases (+/- Infinity). Just uncommon-trap them.
|
// really odd corner cases (+/- Infinity). Just uncommon-trap them.
|
||||||
bool LibraryCallKit::inline_exp() {
|
bool LibraryCallKit::inline_exp() {
|
||||||
Node* arg = round_double_node(argument(0));
|
Node* arg = round_double_node(argument(0));
|
||||||
Node* n = _gvn.transform(new (C) ExpDNode(0, arg));
|
Node* n = _gvn.transform(new (C) ExpDNode(C, control(), arg));
|
||||||
|
|
||||||
finish_pow_exp(n, arg, NULL, OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dexp), "EXP");
|
finish_pow_exp(n, arg, NULL, OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dexp), "EXP");
|
||||||
|
|
||||||
@ -1688,7 +1688,7 @@ bool LibraryCallKit::inline_pow() {
|
|||||||
|
|
||||||
if (!too_many_traps(Deoptimization::Reason_intrinsic)) {
|
if (!too_many_traps(Deoptimization::Reason_intrinsic)) {
|
||||||
// Short form: skip the fancy tests and just check for NaN result.
|
// Short form: skip the fancy tests and just check for NaN result.
|
||||||
result = _gvn.transform(new (C) PowDNode(0, x, y));
|
result = _gvn.transform(new (C) PowDNode(C, control(), x, y));
|
||||||
} else {
|
} else {
|
||||||
// If this inlining ever returned NaN in the past, include all
|
// If this inlining ever returned NaN in the past, include all
|
||||||
// checks + call to the runtime.
|
// checks + call to the runtime.
|
||||||
@ -1715,7 +1715,7 @@ bool LibraryCallKit::inline_pow() {
|
|||||||
Node *complex_path = _gvn.transform( new (C) IfTrueNode(if1) );
|
Node *complex_path = _gvn.transform( new (C) IfTrueNode(if1) );
|
||||||
|
|
||||||
// Set fast path result
|
// Set fast path result
|
||||||
Node *fast_result = _gvn.transform( new (C) PowDNode(0, x, y) );
|
Node *fast_result = _gvn.transform( new (C) PowDNode(C, control(), x, y) );
|
||||||
phi->init_req(3, fast_result);
|
phi->init_req(3, fast_result);
|
||||||
|
|
||||||
// Complex path
|
// Complex path
|
||||||
@ -1775,7 +1775,7 @@ bool LibraryCallKit::inline_pow() {
|
|||||||
// abs(x)
|
// abs(x)
|
||||||
Node *absx=_gvn.transform( new (C) AbsDNode(x));
|
Node *absx=_gvn.transform( new (C) AbsDNode(x));
|
||||||
// abs(x)^y
|
// abs(x)^y
|
||||||
Node *absxpowy = _gvn.transform( new (C) PowDNode(0, absx, y) );
|
Node *absxpowy = _gvn.transform( new (C) PowDNode(C, control(), absx, y) );
|
||||||
// -abs(x)^y
|
// -abs(x)^y
|
||||||
Node *negabsxpowy = _gvn.transform(new (C) NegDNode (absxpowy));
|
Node *negabsxpowy = _gvn.transform(new (C) NegDNode (absxpowy));
|
||||||
// (1&(long)y)==1?-DPow(abs(x), y):DPow(abs(x), y)
|
// (1&(long)y)==1?-DPow(abs(x), y):DPow(abs(x), y)
|
||||||
|
@ -88,9 +88,9 @@ Node *PhaseIdealLoop::get_early_ctrl( Node *n ) {
|
|||||||
assert( !n->is_Phi() && !n->is_CFG(), "this code only handles data nodes" );
|
assert( !n->is_Phi() && !n->is_CFG(), "this code only handles data nodes" );
|
||||||
uint i;
|
uint i;
|
||||||
Node *early;
|
Node *early;
|
||||||
if( n->in(0) ) {
|
if (n->in(0) && !n->is_expensive()) {
|
||||||
early = n->in(0);
|
early = n->in(0);
|
||||||
if( !early->is_CFG() ) // Might be a non-CFG multi-def
|
if (!early->is_CFG()) // Might be a non-CFG multi-def
|
||||||
early = get_ctrl(early); // So treat input as a straight data input
|
early = get_ctrl(early); // So treat input as a straight data input
|
||||||
i = 1;
|
i = 1;
|
||||||
} else {
|
} else {
|
||||||
@ -99,28 +99,28 @@ Node *PhaseIdealLoop::get_early_ctrl( Node *n ) {
|
|||||||
}
|
}
|
||||||
uint e_d = dom_depth(early);
|
uint e_d = dom_depth(early);
|
||||||
assert( early, "" );
|
assert( early, "" );
|
||||||
for( ; i < n->req(); i++ ) {
|
for (; i < n->req(); i++) {
|
||||||
Node *cin = get_ctrl(n->in(i));
|
Node *cin = get_ctrl(n->in(i));
|
||||||
assert( cin, "" );
|
assert( cin, "" );
|
||||||
// Keep deepest dominator depth
|
// Keep deepest dominator depth
|
||||||
uint c_d = dom_depth(cin);
|
uint c_d = dom_depth(cin);
|
||||||
if( c_d > e_d ) { // Deeper guy?
|
if (c_d > e_d) { // Deeper guy?
|
||||||
early = cin; // Keep deepest found so far
|
early = cin; // Keep deepest found so far
|
||||||
e_d = c_d;
|
e_d = c_d;
|
||||||
} else if( c_d == e_d && // Same depth?
|
} else if (c_d == e_d && // Same depth?
|
||||||
early != cin ) { // If not equal, must use slower algorithm
|
early != cin) { // If not equal, must use slower algorithm
|
||||||
// If same depth but not equal, one _must_ dominate the other
|
// If same depth but not equal, one _must_ dominate the other
|
||||||
// and we want the deeper (i.e., dominated) guy.
|
// and we want the deeper (i.e., dominated) guy.
|
||||||
Node *n1 = early;
|
Node *n1 = early;
|
||||||
Node *n2 = cin;
|
Node *n2 = cin;
|
||||||
while( 1 ) {
|
while (1) {
|
||||||
n1 = idom(n1); // Walk up until break cycle
|
n1 = idom(n1); // Walk up until break cycle
|
||||||
n2 = idom(n2);
|
n2 = idom(n2);
|
||||||
if( n1 == cin || // Walked early up to cin
|
if (n1 == cin || // Walked early up to cin
|
||||||
dom_depth(n2) < c_d )
|
dom_depth(n2) < c_d)
|
||||||
break; // early is deeper; keep him
|
break; // early is deeper; keep him
|
||||||
if( n2 == early || // Walked cin up to early
|
if (n2 == early || // Walked cin up to early
|
||||||
dom_depth(n1) < c_d ) {
|
dom_depth(n1) < c_d) {
|
||||||
early = cin; // cin is deeper; keep him
|
early = cin; // cin is deeper; keep him
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -132,9 +132,108 @@ Node *PhaseIdealLoop::get_early_ctrl( Node *n ) {
|
|||||||
// Return earliest legal location
|
// Return earliest legal location
|
||||||
assert(early == find_non_split_ctrl(early), "unexpected early control");
|
assert(early == find_non_split_ctrl(early), "unexpected early control");
|
||||||
|
|
||||||
|
if (n->is_expensive()) {
|
||||||
|
assert(n->in(0), "should have control input");
|
||||||
|
early = get_early_ctrl_for_expensive(n, early);
|
||||||
|
}
|
||||||
|
|
||||||
return early;
|
return early;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------get_early_ctrl_for_expensive---------------------------------
|
||||||
|
// Move node up the dominator tree as high as legal while still beneficial
|
||||||
|
Node *PhaseIdealLoop::get_early_ctrl_for_expensive(Node *n, Node* earliest) {
|
||||||
|
assert(n->in(0) && n->is_expensive(), "expensive node with control input here");
|
||||||
|
assert(OptimizeExpensiveOps, "optimization off?");
|
||||||
|
|
||||||
|
Node* ctl = n->in(0);
|
||||||
|
assert(ctl->is_CFG(), "expensive input 0 must be cfg");
|
||||||
|
uint min_dom_depth = dom_depth(earliest);
|
||||||
|
#ifdef ASSERT
|
||||||
|
if (!is_dominator(ctl, earliest) && !is_dominator(earliest, ctl)) {
|
||||||
|
dump_bad_graph("Bad graph detected in get_early_ctrl_for_expensive", n, earliest, ctl);
|
||||||
|
assert(false, "Bad graph detected in get_early_ctrl_for_expensive");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (dom_depth(ctl) < min_dom_depth) {
|
||||||
|
return earliest;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
Node *next = ctl;
|
||||||
|
// Moving the node out of a loop on the projection of a If
|
||||||
|
// confuses loop predication. So once we hit a Loop in a If branch
|
||||||
|
// that doesn't branch to an UNC, we stop. The code that process
|
||||||
|
// 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)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next = idom(ctl->in(1)->in(0));
|
||||||
|
} else if (ctl->is_Proj()) {
|
||||||
|
// We only move it up along a projection if the projection is
|
||||||
|
// the single control projection for its parent: same code path,
|
||||||
|
// if it's a If with UNC or fallthrough of a call.
|
||||||
|
Node* parent_ctl = ctl->in(0);
|
||||||
|
if (parent_ctl == NULL) {
|
||||||
|
break;
|
||||||
|
} 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)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert(idom(ctl) == parent_ctl, "strange");
|
||||||
|
next = idom(parent_ctl);
|
||||||
|
} else if (ctl->is_CatchProj()) {
|
||||||
|
if (ctl->as_Proj()->_con != CatchProjNode::fall_through_index) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert(parent_ctl->in(0)->in(0)->is_Call(), "strange graph");
|
||||||
|
next = parent_ctl->in(0)->in(0)->in(0);
|
||||||
|
} else {
|
||||||
|
// Check if parent control has a single projection (this
|
||||||
|
// control is the only possible successor of the parent
|
||||||
|
// control). If so, we can try to move the node above the
|
||||||
|
// parent control.
|
||||||
|
int nb_ctl_proj = 0;
|
||||||
|
for (DUIterator_Fast imax, i = parent_ctl->fast_outs(imax); i < imax; i++) {
|
||||||
|
Node *p = parent_ctl->fast_out(i);
|
||||||
|
if (p->is_Proj() && p->is_CFG()) {
|
||||||
|
nb_ctl_proj++;
|
||||||
|
if (nb_ctl_proj > 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nb_ctl_proj > 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert(parent_ctl->is_Start() || parent_ctl->is_MemBar() || parent_ctl->is_Call(), "unexpected node");
|
||||||
|
assert(idom(ctl) == parent_ctl, "strange");
|
||||||
|
next = idom(parent_ctl);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
next = idom(ctl);
|
||||||
|
}
|
||||||
|
if (next->is_Root() || next->is_Start() || dom_depth(next) < min_dom_depth) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ctl = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctl != n->in(0)) {
|
||||||
|
_igvn.hash_delete(n);
|
||||||
|
n->set_req(0, ctl);
|
||||||
|
_igvn.hash_insert(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------set_early_ctrl---------------------------------
|
//------------------------------set_early_ctrl---------------------------------
|
||||||
// Set earliest legal control
|
// Set earliest legal control
|
||||||
void PhaseIdealLoop::set_early_ctrl( Node *n ) {
|
void PhaseIdealLoop::set_early_ctrl( Node *n ) {
|
||||||
@ -1892,6 +1991,98 @@ void PhaseIdealLoop::eliminate_useless_predicates() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------process_expensive_nodes-----------------------------
|
||||||
|
// Expensive nodes have their control input set to prevent the GVN
|
||||||
|
// from commoning them and as a result forcing the resulting node to
|
||||||
|
// be in a more frequent path. Use CFG information here, to change the
|
||||||
|
// control inputs so that some expensive nodes can be commoned while
|
||||||
|
// not executed more frequently.
|
||||||
|
bool PhaseIdealLoop::process_expensive_nodes() {
|
||||||
|
assert(OptimizeExpensiveOps, "optimization off?");
|
||||||
|
|
||||||
|
// Sort nodes to bring similar nodes together
|
||||||
|
C->sort_expensive_nodes();
|
||||||
|
|
||||||
|
bool progress = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < C->expensive_count(); ) {
|
||||||
|
Node* n = C->expensive_node(i);
|
||||||
|
int start = i;
|
||||||
|
// Find nodes similar to n
|
||||||
|
i++;
|
||||||
|
for (; i < C->expensive_count() && Compile::cmp_expensive_nodes(n, C->expensive_node(i)) == 0; i++);
|
||||||
|
int end = i;
|
||||||
|
// And compare them two by two
|
||||||
|
for (int j = start; j < end; j++) {
|
||||||
|
Node* n1 = C->expensive_node(j);
|
||||||
|
if (is_node_unreachable(n1)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int k = j+1; k < end; k++) {
|
||||||
|
Node* n2 = C->expensive_node(k);
|
||||||
|
if (is_node_unreachable(n2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(n1 != n2, "should be pair of nodes");
|
||||||
|
|
||||||
|
Node* c1 = n1->in(0);
|
||||||
|
Node* c2 = n2->in(0);
|
||||||
|
|
||||||
|
Node* parent_c1 = c1;
|
||||||
|
Node* parent_c2 = c2;
|
||||||
|
|
||||||
|
// The call to get_early_ctrl_for_expensive() moves the
|
||||||
|
// expensive nodes up but stops at loops that are in a if
|
||||||
|
// branch. See whether we can exit the loop and move above the
|
||||||
|
// If.
|
||||||
|
if (c1->is_Loop()) {
|
||||||
|
parent_c1 = c1->in(1);
|
||||||
|
}
|
||||||
|
if (c2->is_Loop()) {
|
||||||
|
parent_c2 = c2->in(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent_c1 == parent_c2) {
|
||||||
|
_igvn._worklist.push(n1);
|
||||||
|
_igvn._worklist.push(n2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for identical expensive node up the dominator chain.
|
||||||
|
if (is_dominator(c1, c2)) {
|
||||||
|
c2 = c1;
|
||||||
|
} else if (is_dominator(c2, c1)) {
|
||||||
|
c1 = c2;
|
||||||
|
} else if (parent_c1->is_Proj() && parent_c1->in(0)->is_If() &&
|
||||||
|
parent_c2->is_Proj() && parent_c1->in(0) == parent_c2->in(0)) {
|
||||||
|
// Both branches have the same expensive node so move it up
|
||||||
|
// before the if.
|
||||||
|
c1 = c2 = idom(parent_c1->in(0));
|
||||||
|
}
|
||||||
|
// Do the actual moves
|
||||||
|
if (n1->in(0) != c1) {
|
||||||
|
_igvn.hash_delete(n1);
|
||||||
|
n1->set_req(0, c1);
|
||||||
|
_igvn.hash_insert(n1);
|
||||||
|
_igvn._worklist.push(n1);
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
if (n2->in(0) != c2) {
|
||||||
|
_igvn.hash_delete(n2);
|
||||||
|
n2->set_req(0, c2);
|
||||||
|
_igvn.hash_insert(n2);
|
||||||
|
_igvn._worklist.push(n2);
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//----------------------------build_and_optimize-------------------------------
|
//----------------------------build_and_optimize-------------------------------
|
||||||
// Create a PhaseLoop. Build the ideal Loop tree. Map each Ideal Node to
|
// Create a PhaseLoop. Build the ideal Loop tree. Map each Ideal Node to
|
||||||
@ -1960,7 +2151,9 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Nothing to do, so get out
|
// Nothing to do, so get out
|
||||||
if( !C->has_loops() && !skip_loop_opts && !do_split_ifs && !_verify_me && !_verify_only ) {
|
bool stop_early = !C->has_loops() && !skip_loop_opts && !do_split_ifs && !_verify_me && !_verify_only;
|
||||||
|
bool do_expensive_nodes = C->should_optimize_expensive_nodes(_igvn);
|
||||||
|
if (stop_early && !do_expensive_nodes) {
|
||||||
_igvn.optimize(); // Cleanup NeverBranches
|
_igvn.optimize(); // Cleanup NeverBranches
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2058,6 +2251,21 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stop_early) {
|
||||||
|
assert(do_expensive_nodes, "why are we here?");
|
||||||
|
if (process_expensive_nodes()) {
|
||||||
|
// If we made some progress when processing expensive nodes then
|
||||||
|
// the IGVN may modify the graph in a way that will allow us to
|
||||||
|
// make some more progress: we need to try processing expensive
|
||||||
|
// nodes again.
|
||||||
|
C->set_major_progress();
|
||||||
|
}
|
||||||
|
|
||||||
|
_igvn.optimize();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Some parser-inserted loop predicates could never be used by loop
|
// Some parser-inserted loop predicates could never be used by loop
|
||||||
// predication or they were moved away from loop during some optimizations.
|
// predication or they were moved away from loop during some optimizations.
|
||||||
// For example, peeling. Eliminate them before next loop optimizations.
|
// For example, peeling. Eliminate them before next loop optimizations.
|
||||||
@ -2120,6 +2328,10 @@ void PhaseIdealLoop::build_and_optimize(bool do_split_ifs, bool skip_loop_opts)
|
|||||||
NOT_PRODUCT( if( VerifyLoopOptimizations ) verify(); );
|
NOT_PRODUCT( if( VerifyLoopOptimizations ) verify(); );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!C->major_progress() && do_expensive_nodes && process_expensive_nodes()) {
|
||||||
|
C->set_major_progress();
|
||||||
|
}
|
||||||
|
|
||||||
// Perform loop predication before iteration splitting
|
// Perform loop predication before iteration splitting
|
||||||
if (C->has_loops() && !C->major_progress() && (C->predicate_count() > 0)) {
|
if (C->has_loops() && !C->major_progress() && (C->predicate_count() > 0)) {
|
||||||
_ltree_root->_child->loop_predication(this);
|
_ltree_root->_child->loop_predication(this);
|
||||||
@ -3299,7 +3511,7 @@ void PhaseIdealLoop::build_loop_late_post( Node *n ) {
|
|||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
if (legal->is_Start() && !early->is_Root()) {
|
if (legal->is_Start() && !early->is_Root()) {
|
||||||
// Bad graph. Print idom path and fail.
|
// Bad graph. Print idom path and fail.
|
||||||
dump_bad_graph(n, early, LCA);
|
dump_bad_graph("Bad graph detected in build_loop_late", n, early, LCA);
|
||||||
assert(false, "Bad graph detected in build_loop_late");
|
assert(false, "Bad graph detected in build_loop_late");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -3350,8 +3562,8 @@ void PhaseIdealLoop::build_loop_late_post( Node *n ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
void PhaseIdealLoop::dump_bad_graph(Node* n, Node* early, Node* LCA) {
|
void PhaseIdealLoop::dump_bad_graph(const char* msg, Node* n, Node* early, Node* LCA) {
|
||||||
tty->print_cr( "Bad graph detected in build_loop_late");
|
tty->print_cr(msg);
|
||||||
tty->print("n: "); n->dump();
|
tty->print("n: "); n->dump();
|
||||||
tty->print("early(n): "); early->dump();
|
tty->print("early(n): "); early->dump();
|
||||||
if (n->in(0) != NULL && !n->in(0)->is_top() &&
|
if (n->in(0) != NULL && !n->in(0)->is_top() &&
|
||||||
|
@ -263,9 +263,18 @@ public:
|
|||||||
bool stride_is_con() const { Node *tmp = stride (); return (tmp != NULL && tmp->is_Con()); }
|
bool stride_is_con() const { Node *tmp = stride (); return (tmp != NULL && tmp->is_Con()); }
|
||||||
BoolTest::mask test_trip() const { return in(TestValue)->as_Bool()->_test._test; }
|
BoolTest::mask test_trip() const { return in(TestValue)->as_Bool()->_test._test; }
|
||||||
CountedLoopNode *loopnode() const {
|
CountedLoopNode *loopnode() const {
|
||||||
|
// The CountedLoopNode that goes with this CountedLoopEndNode may
|
||||||
|
// have been optimized out by the IGVN so be cautious with the
|
||||||
|
// pattern matching on the graph
|
||||||
|
if (phi() == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
Node *ln = phi()->in(0);
|
Node *ln = phi()->in(0);
|
||||||
assert( ln->Opcode() == Op_CountedLoop, "malformed loop" );
|
if (ln->is_CountedLoop() && ln->as_CountedLoop()->loopexit() == this) {
|
||||||
return (CountedLoopNode*)ln; }
|
return (CountedLoopNode*)ln;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
virtual void dump_spec(outputStream *st) const;
|
virtual void dump_spec(outputStream *st) const;
|
||||||
@ -598,6 +607,7 @@ public:
|
|||||||
// check if transform created new nodes that need _ctrl recorded
|
// check if transform created new nodes that need _ctrl recorded
|
||||||
Node *get_late_ctrl( Node *n, Node *early );
|
Node *get_late_ctrl( Node *n, Node *early );
|
||||||
Node *get_early_ctrl( Node *n );
|
Node *get_early_ctrl( Node *n );
|
||||||
|
Node *get_early_ctrl_for_expensive(Node *n, Node* earliest);
|
||||||
void set_early_ctrl( Node *n );
|
void set_early_ctrl( Node *n );
|
||||||
void set_subtree_ctrl( Node *root );
|
void set_subtree_ctrl( Node *root );
|
||||||
void set_ctrl( Node *n, Node *ctrl ) {
|
void set_ctrl( Node *n, Node *ctrl ) {
|
||||||
@ -905,6 +915,16 @@ public:
|
|||||||
void collect_potentially_useful_predicates(IdealLoopTree *loop, Unique_Node_List &predicate_opaque1);
|
void collect_potentially_useful_predicates(IdealLoopTree *loop, Unique_Node_List &predicate_opaque1);
|
||||||
void eliminate_useless_predicates();
|
void eliminate_useless_predicates();
|
||||||
|
|
||||||
|
// Change the control input of expensive nodes to allow commoning by
|
||||||
|
// IGVN when it is guaranteed to not result in a more frequent
|
||||||
|
// execution of the expensive node. Return true if progress.
|
||||||
|
bool process_expensive_nodes();
|
||||||
|
|
||||||
|
// Check whether node has become unreachable
|
||||||
|
bool is_node_unreachable(Node *n) const {
|
||||||
|
return !has_node(n) || n->is_unreachable(_igvn);
|
||||||
|
}
|
||||||
|
|
||||||
// Eliminate range-checks and other trip-counter vs loop-invariant tests.
|
// Eliminate range-checks and other trip-counter vs loop-invariant tests.
|
||||||
void do_range_check( IdealLoopTree *loop, Node_List &old_new );
|
void do_range_check( IdealLoopTree *loop, Node_List &old_new );
|
||||||
|
|
||||||
@ -1043,7 +1063,7 @@ public:
|
|||||||
void register_new_node( Node *n, Node *blk );
|
void register_new_node( Node *n, Node *blk );
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
void dump_bad_graph(Node* n, Node* early, Node* LCA);
|
void dump_bad_graph(const char* msg, Node* n, Node* early, Node* LCA);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -493,6 +493,8 @@ Node *Node::clone() const {
|
|||||||
}
|
}
|
||||||
if (is_macro())
|
if (is_macro())
|
||||||
compile->add_macro_node(n);
|
compile->add_macro_node(n);
|
||||||
|
if (is_expensive())
|
||||||
|
compile->add_expensive_node(n);
|
||||||
|
|
||||||
n->set_idx(compile->next_unique()); // Get new unique index as well
|
n->set_idx(compile->next_unique()); // Get new unique index as well
|
||||||
debug_only( n->verify_construction() );
|
debug_only( n->verify_construction() );
|
||||||
@ -616,6 +618,9 @@ void Node::destruct() {
|
|||||||
if (is_macro()) {
|
if (is_macro()) {
|
||||||
compile->remove_macro_node(this);
|
compile->remove_macro_node(this);
|
||||||
}
|
}
|
||||||
|
if (is_expensive()) {
|
||||||
|
compile->remove_expensive_node(this);
|
||||||
|
}
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
// We will not actually delete the storage, but we'll make the node unusable.
|
// We will not actually delete the storage, but we'll make the node unusable.
|
||||||
*(address*)this = badAddress; // smash the C++ vtbl, probably
|
*(address*)this = badAddress; // smash the C++ vtbl, probably
|
||||||
@ -689,6 +694,13 @@ bool Node::is_dead() const {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------is_unreachable---------------------------------
|
||||||
|
bool Node::is_unreachable(PhaseIterGVN &igvn) const {
|
||||||
|
assert(!is_Mach(), "doesn't work with MachNodes");
|
||||||
|
return outcnt() == 0 || igvn.type(this) == Type::TOP || in(0)->is_top();
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------add_req----------------------------------------
|
//------------------------------add_req----------------------------------------
|
||||||
// Add a new required input at the end
|
// Add a new required input at the end
|
||||||
void Node::add_req( Node *n ) {
|
void Node::add_req( Node *n ) {
|
||||||
@ -1246,6 +1258,9 @@ static void kill_dead_code( Node *dead, PhaseIterGVN *igvn ) {
|
|||||||
if (dead->is_macro()) {
|
if (dead->is_macro()) {
|
||||||
igvn->C->remove_macro_node(dead);
|
igvn->C->remove_macro_node(dead);
|
||||||
}
|
}
|
||||||
|
if (dead->is_expensive()) {
|
||||||
|
igvn->C->remove_expensive_node(dead);
|
||||||
|
}
|
||||||
// Kill all inputs to the dead guy
|
// Kill all inputs to the dead guy
|
||||||
for (uint i=0; i < dead->req(); i++) {
|
for (uint i=0; i < dead->req(); i++) {
|
||||||
Node *n = dead->in(i); // Get input to dead guy
|
Node *n = dead->in(i); // Get input to dead guy
|
||||||
|
@ -378,6 +378,8 @@ protected:
|
|||||||
bool is_dead() const;
|
bool is_dead() const;
|
||||||
#define is_not_dead(n) ((n) == NULL || !VerifyIterativeGVN || !((n)->is_dead()))
|
#define is_not_dead(n) ((n) == NULL || !VerifyIterativeGVN || !((n)->is_dead()))
|
||||||
#endif
|
#endif
|
||||||
|
// Check whether node has become unreachable
|
||||||
|
bool is_unreachable(PhaseIterGVN &igvn) const;
|
||||||
|
|
||||||
// Set a required input edge, also updates corresponding output edge
|
// Set a required input edge, also updates corresponding output edge
|
||||||
void add_req( Node *n ); // Append a NEW required input
|
void add_req( Node *n ); // Append a NEW required input
|
||||||
@ -646,7 +648,8 @@ public:
|
|||||||
Flag_may_be_short_branch = Flag_is_dead_loop_safe << 1,
|
Flag_may_be_short_branch = Flag_is_dead_loop_safe << 1,
|
||||||
Flag_avoid_back_to_back = Flag_may_be_short_branch << 1,
|
Flag_avoid_back_to_back = Flag_may_be_short_branch << 1,
|
||||||
Flag_has_call = Flag_avoid_back_to_back << 1,
|
Flag_has_call = Flag_avoid_back_to_back << 1,
|
||||||
_max_flags = (Flag_has_call << 1) - 1 // allow flags combination
|
Flag_is_expensive = Flag_has_call << 1,
|
||||||
|
_max_flags = (Flag_is_expensive << 1) - 1 // allow flags combination
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -819,6 +822,8 @@ public:
|
|||||||
|
|
||||||
// The node is a "macro" node which needs to be expanded before matching
|
// The node is a "macro" node which needs to be expanded before matching
|
||||||
bool is_macro() const { return (_flags & Flag_is_macro) != 0; }
|
bool is_macro() const { return (_flags & Flag_is_macro) != 0; }
|
||||||
|
// The node is expensive: the best control is set during loop opts
|
||||||
|
bool is_expensive() const { return (_flags & Flag_is_expensive) != 0 && in(0) != NULL; }
|
||||||
|
|
||||||
//----------------- Optimization
|
//----------------- Optimization
|
||||||
|
|
||||||
|
@ -1203,6 +1203,9 @@ void PhaseIterGVN::remove_globally_dead_node( Node *dead ) {
|
|||||||
if (dead->is_macro()) {
|
if (dead->is_macro()) {
|
||||||
C->remove_macro_node(dead);
|
C->remove_macro_node(dead);
|
||||||
}
|
}
|
||||||
|
if (dead->is_expensive()) {
|
||||||
|
C->remove_expensive_node(dead);
|
||||||
|
}
|
||||||
|
|
||||||
if (recurse) {
|
if (recurse) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -241,7 +241,8 @@ int RegMask::is_bound_pair() const {
|
|||||||
} else { // Else its a split-pair case
|
} else { // Else its a split-pair case
|
||||||
if( bit != _A[i] ) return false; // Found many bits, so fail
|
if( bit != _A[i] ) return false; // Found many bits, so fail
|
||||||
i++; // Skip iteration forward
|
i++; // Skip iteration forward
|
||||||
if( _A[i] != 1 ) return false; // Require 1 lo bit in next word
|
if( i >= RM_SIZE || _A[i] != 1 )
|
||||||
|
return false; // Require 1 lo bit in next word
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,7 +255,7 @@ static int low_bits[3] = { 0x55555555, 0x11111111, 0x01010101 };
|
|||||||
// Find the lowest-numbered register set in the mask. Return the
|
// Find the lowest-numbered register set in the mask. Return the
|
||||||
// HIGHEST register number in the set, or BAD if no sets.
|
// HIGHEST register number in the set, or BAD if no sets.
|
||||||
// Works also for size 1.
|
// Works also for size 1.
|
||||||
OptoReg::Name RegMask::find_first_set(int size) const {
|
OptoReg::Name RegMask::find_first_set(const int size) const {
|
||||||
verify_sets(size);
|
verify_sets(size);
|
||||||
for (int i = 0; i < RM_SIZE; i++) {
|
for (int i = 0; i < RM_SIZE; i++) {
|
||||||
if (_A[i]) { // Found some bits
|
if (_A[i]) { // Found some bits
|
||||||
@ -268,7 +269,7 @@ OptoReg::Name RegMask::find_first_set(int size) const {
|
|||||||
|
|
||||||
//------------------------------clear_to_sets----------------------------------
|
//------------------------------clear_to_sets----------------------------------
|
||||||
// Clear out partial bits; leave only aligned adjacent bit pairs
|
// Clear out partial bits; leave only aligned adjacent bit pairs
|
||||||
void RegMask::clear_to_sets(int size) {
|
void RegMask::clear_to_sets(const int size) {
|
||||||
if (size == 1) return;
|
if (size == 1) return;
|
||||||
assert(2 <= size && size <= 8, "update low bits table");
|
assert(2 <= size && size <= 8, "update low bits table");
|
||||||
assert(is_power_of_2(size), "sanity");
|
assert(is_power_of_2(size), "sanity");
|
||||||
@ -293,7 +294,7 @@ void RegMask::clear_to_sets(int size) {
|
|||||||
|
|
||||||
//------------------------------smear_to_sets----------------------------------
|
//------------------------------smear_to_sets----------------------------------
|
||||||
// Smear out partial bits to aligned adjacent bit sets
|
// Smear out partial bits to aligned adjacent bit sets
|
||||||
void RegMask::smear_to_sets(int size) {
|
void RegMask::smear_to_sets(const int size) {
|
||||||
if (size == 1) return;
|
if (size == 1) return;
|
||||||
assert(2 <= size && size <= 8, "update low bits table");
|
assert(2 <= size && size <= 8, "update low bits table");
|
||||||
assert(is_power_of_2(size), "sanity");
|
assert(is_power_of_2(size), "sanity");
|
||||||
@ -318,7 +319,7 @@ void RegMask::smear_to_sets(int size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------is_aligned_set--------------------------------
|
//------------------------------is_aligned_set--------------------------------
|
||||||
bool RegMask::is_aligned_sets(int size) const {
|
bool RegMask::is_aligned_sets(const int size) const {
|
||||||
if (size == 1) return true;
|
if (size == 1) return true;
|
||||||
assert(2 <= size && size <= 8, "update low bits table");
|
assert(2 <= size && size <= 8, "update low bits table");
|
||||||
assert(is_power_of_2(size), "sanity");
|
assert(is_power_of_2(size), "sanity");
|
||||||
@ -344,7 +345,7 @@ bool RegMask::is_aligned_sets(int size) const {
|
|||||||
//------------------------------is_bound_set-----------------------------------
|
//------------------------------is_bound_set-----------------------------------
|
||||||
// Return TRUE if the mask contains one adjacent set of bits and no other bits.
|
// Return TRUE if the mask contains one adjacent set of bits and no other bits.
|
||||||
// Works also for size 1.
|
// Works also for size 1.
|
||||||
int RegMask::is_bound_set(int size) const {
|
int RegMask::is_bound_set(const int size) const {
|
||||||
if( is_AllStack() ) return false;
|
if( is_AllStack() ) return false;
|
||||||
assert(1 <= size && size <= 8, "update low bits table");
|
assert(1 <= size && size <= 8, "update low bits table");
|
||||||
int bit = -1; // Set to hold the one bit allowed
|
int bit = -1; // Set to hold the one bit allowed
|
||||||
@ -352,7 +353,7 @@ int RegMask::is_bound_set(int size) const {
|
|||||||
if (_A[i] ) { // Found some bits
|
if (_A[i] ) { // Found some bits
|
||||||
if (bit != -1)
|
if (bit != -1)
|
||||||
return false; // Already had bits, so fail
|
return false; // Already had bits, so fail
|
||||||
bit = _A[i] & -_A[i]; // Extract 1 bit from mask
|
bit = _A[i] & -_A[i]; // Extract low bit from mask
|
||||||
int hi_bit = bit << (size-1); // high bit
|
int hi_bit = bit << (size-1); // high bit
|
||||||
if (hi_bit != 0) { // Bit set stays in same word?
|
if (hi_bit != 0) { // Bit set stays in same word?
|
||||||
int set = hi_bit + ((hi_bit-1) & ~(bit-1));
|
int set = hi_bit + ((hi_bit-1) & ~(bit-1));
|
||||||
@ -362,12 +363,12 @@ int RegMask::is_bound_set(int size) const {
|
|||||||
if (((-1) & ~(bit-1)) != _A[i])
|
if (((-1) & ~(bit-1)) != _A[i])
|
||||||
return false; // Found many bits, so fail
|
return false; // Found many bits, so fail
|
||||||
i++; // Skip iteration forward and check high part
|
i++; // Skip iteration forward and check high part
|
||||||
assert(size <= 8, "update next code");
|
|
||||||
// The lower 24 bits should be 0 since it is split case and size <= 8.
|
// The lower 24 bits should be 0 since it is split case and size <= 8.
|
||||||
int set = bit>>24;
|
int set = bit>>24;
|
||||||
set = set & -set; // Remove sign extension.
|
set = set & -set; // Remove sign extension.
|
||||||
set = (((set << size) - 1) >> 8);
|
set = (((set << size) - 1) >> 8);
|
||||||
if (_A[i] != set) return false; // Require 1 lo bit in next word
|
if (i >= RM_SIZE || _A[i] != set)
|
||||||
|
return false; // Require expected low bits in next word
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -225,22 +225,22 @@ public:
|
|||||||
// Find the lowest-numbered register set in the mask. Return the
|
// Find the lowest-numbered register set in the mask. Return the
|
||||||
// HIGHEST register number in the set, or BAD if no sets.
|
// HIGHEST register number in the set, or BAD if no sets.
|
||||||
// Assert that the mask contains only bit sets.
|
// Assert that the mask contains only bit sets.
|
||||||
OptoReg::Name find_first_set(int size) const;
|
OptoReg::Name find_first_set(const int size) const;
|
||||||
|
|
||||||
// Clear out partial bits; leave only aligned adjacent bit sets of size.
|
// Clear out partial bits; leave only aligned adjacent bit sets of size.
|
||||||
void clear_to_sets(int size);
|
void clear_to_sets(const int size);
|
||||||
// Smear out partial bits to aligned adjacent bit sets.
|
// Smear out partial bits to aligned adjacent bit sets.
|
||||||
void smear_to_sets(int size);
|
void smear_to_sets(const int size);
|
||||||
// Verify that the mask contains only aligned adjacent bit sets
|
// Verify that the mask contains only aligned adjacent bit sets
|
||||||
void verify_sets(int size) const { assert(is_aligned_sets(size), "mask is not aligned, adjacent sets"); }
|
void verify_sets(int size) const { assert(is_aligned_sets(size), "mask is not aligned, adjacent sets"); }
|
||||||
// Test that the mask contains only aligned adjacent bit sets
|
// Test that the mask contains only aligned adjacent bit sets
|
||||||
bool is_aligned_sets(int size) const;
|
bool is_aligned_sets(const int size) const;
|
||||||
|
|
||||||
// mask is a set of misaligned registers
|
// mask is a set of misaligned registers
|
||||||
bool is_misaligned_set(int size) const { return (int)Size()==size && !is_aligned_sets(size);}
|
bool is_misaligned_set(int size) const { return (int)Size()==size && !is_aligned_sets(size);}
|
||||||
|
|
||||||
// Test for a single adjacent set
|
// Test for a single adjacent set
|
||||||
int is_bound_set(int size) const;
|
int is_bound_set(const int size) const;
|
||||||
|
|
||||||
static bool is_vector(uint ireg);
|
static bool is_vector(uint ireg);
|
||||||
static int num_registers(uint ireg);
|
static int num_registers(uint ireg);
|
||||||
|
@ -456,7 +456,10 @@ public:
|
|||||||
// Exponentiate a double
|
// Exponentiate a double
|
||||||
class ExpDNode : public Node {
|
class ExpDNode : public Node {
|
||||||
public:
|
public:
|
||||||
ExpDNode( Node *c, Node *in1 ) : Node(c, in1) {}
|
ExpDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) {
|
||||||
|
init_flags(Flag_is_expensive);
|
||||||
|
C->add_expensive_node(this);
|
||||||
|
}
|
||||||
virtual int Opcode() const;
|
virtual int Opcode() const;
|
||||||
const Type *bottom_type() const { return Type::DOUBLE; }
|
const Type *bottom_type() const { return Type::DOUBLE; }
|
||||||
virtual uint ideal_reg() const { return Op_RegD; }
|
virtual uint ideal_reg() const { return Op_RegD; }
|
||||||
@ -489,7 +492,10 @@ public:
|
|||||||
// Raise a double to a double power
|
// Raise a double to a double power
|
||||||
class PowDNode : public Node {
|
class PowDNode : public Node {
|
||||||
public:
|
public:
|
||||||
PowDNode(Node *c, Node *in1, Node *in2 ) : Node(c, in1, in2) {}
|
PowDNode(Compile* C, Node *c, Node *in1, Node *in2 ) : Node(c, in1, in2) {
|
||||||
|
init_flags(Flag_is_expensive);
|
||||||
|
C->add_expensive_node(this);
|
||||||
|
}
|
||||||
virtual int Opcode() const;
|
virtual int Opcode() const;
|
||||||
const Type *bottom_type() const { return Type::DOUBLE; }
|
const Type *bottom_type() const { return Type::DOUBLE; }
|
||||||
virtual uint ideal_reg() const { return Op_RegD; }
|
virtual uint ideal_reg() const { return Op_RegD; }
|
||||||
|
@ -1573,9 +1573,9 @@ JVM_ENTRY(jbyteArray, JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls))
|
|||||||
if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
|
if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
|
||||||
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls));
|
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls));
|
||||||
if (k->oop_is_instance()) {
|
if (k->oop_is_instance()) {
|
||||||
Annotations* type_annotations = InstanceKlass::cast(k)->type_annotations();
|
AnnotationArray* type_annotations = InstanceKlass::cast(k)->class_type_annotations();
|
||||||
if (type_annotations != NULL) {
|
if (type_annotations != NULL) {
|
||||||
typeArrayOop a = Annotations::make_java_array(type_annotations->class_annotations(), CHECK_NULL);
|
typeArrayOop a = Annotations::make_java_array(type_annotations, CHECK_NULL);
|
||||||
return (jbyteArray) JNIHandles::make_local(env, a);
|
return (jbyteArray) JNIHandles::make_local(env, a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4528,6 +4528,5 @@ JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t i
|
|||||||
// consider to expose this new capability in the sun.rt.jvmCapabilities jvmstat
|
// consider to expose this new capability in the sun.rt.jvmCapabilities jvmstat
|
||||||
// counter defined in runtimeService.cpp.
|
// counter defined in runtimeService.cpp.
|
||||||
info->is_attachable = AttachListener::is_attach_supported();
|
info->is_attachable = AttachListener::is_attach_supported();
|
||||||
info->is_kernel_jvm = 0; // false;
|
|
||||||
}
|
}
|
||||||
JVM_END
|
JVM_END
|
||||||
|
@ -1559,8 +1559,7 @@ typedef struct {
|
|||||||
* the new bit is also added in the main/baseline.
|
* the new bit is also added in the main/baseline.
|
||||||
*/
|
*/
|
||||||
unsigned int is_attachable : 1;
|
unsigned int is_attachable : 1;
|
||||||
unsigned int is_kernel_jvm : 1;
|
unsigned int : 31;
|
||||||
unsigned int : 30;
|
|
||||||
unsigned int : 32;
|
unsigned int : 32;
|
||||||
unsigned int : 32;
|
unsigned int : 32;
|
||||||
} jvm_version_info;
|
} jvm_version_info;
|
||||||
|
@ -154,8 +154,15 @@ void VM_RedefineClasses::doit() {
|
|||||||
// See jvmtiExport.hpp for detailed explanation.
|
// See jvmtiExport.hpp for detailed explanation.
|
||||||
JvmtiExport::set_has_redefined_a_class();
|
JvmtiExport::set_has_redefined_a_class();
|
||||||
|
|
||||||
#ifdef ASSERT
|
// check_class() is optionally called for product bits, but is
|
||||||
SystemDictionary::classes_do(check_class, thread);
|
// always called for non-product bits.
|
||||||
|
#ifdef PRODUCT
|
||||||
|
if (RC_TRACE_ENABLED(0x00004000)) {
|
||||||
|
#endif
|
||||||
|
RC_TRACE_WITH_THREAD(0x00004000, thread, ("calling check_class"));
|
||||||
|
SystemDictionary::classes_do(check_class, thread);
|
||||||
|
#ifdef PRODUCT
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,26 +492,6 @@ int VM_RedefineClasses::find_or_append_indirect_entry(constantPoolHandle scratch
|
|||||||
} // end find_or_append_indirect_entry()
|
} // end find_or_append_indirect_entry()
|
||||||
|
|
||||||
|
|
||||||
void VM_RedefineClasses::swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class, TRAPS) {
|
|
||||||
AnnotationArray* save;
|
|
||||||
|
|
||||||
Annotations* sca = scratch_class->annotations();
|
|
||||||
if (sca == NULL) return;
|
|
||||||
|
|
||||||
save = sca->get_method_annotations_of(i);
|
|
||||||
sca->set_method_annotations_of(scratch_class, i, sca->get_method_annotations_of(j), CHECK);
|
|
||||||
sca->set_method_annotations_of(scratch_class, j, save, CHECK);
|
|
||||||
|
|
||||||
save = sca->get_method_parameter_annotations_of(i);
|
|
||||||
sca->set_method_parameter_annotations_of(scratch_class, i, sca->get_method_parameter_annotations_of(j), CHECK);
|
|
||||||
sca->set_method_parameter_annotations_of(scratch_class, j, save, CHECK);
|
|
||||||
|
|
||||||
save = sca->get_method_default_annotations_of(i);
|
|
||||||
sca->set_method_default_annotations_of(scratch_class, i, sca->get_method_default_annotations_of(j), CHECK);
|
|
||||||
sca->set_method_default_annotations_of(scratch_class, j, save, CHECK);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
||||||
instanceKlassHandle the_class,
|
instanceKlassHandle the_class,
|
||||||
instanceKlassHandle scratch_class) {
|
instanceKlassHandle scratch_class) {
|
||||||
@ -686,10 +673,9 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
|||||||
idnum_owner->set_method_idnum(new_num);
|
idnum_owner->set_method_idnum(new_num);
|
||||||
}
|
}
|
||||||
k_new_method->set_method_idnum(old_num);
|
k_new_method->set_method_idnum(old_num);
|
||||||
swap_all_method_annotations(old_num, new_num, scratch_class, thread);
|
if (thread->has_pending_exception()) {
|
||||||
if (thread->has_pending_exception()) {
|
return JVMTI_ERROR_OUT_OF_MEMORY;
|
||||||
return JVMTI_ERROR_OUT_OF_MEMORY;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RC_TRACE(0x00008000, ("Method matched: new: %s [%d] == old: %s [%d]",
|
RC_TRACE(0x00008000, ("Method matched: new: %s [%d] == old: %s [%d]",
|
||||||
@ -722,7 +708,6 @@ jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
|
|||||||
idnum_owner->set_method_idnum(new_num);
|
idnum_owner->set_method_idnum(new_num);
|
||||||
}
|
}
|
||||||
k_new_method->set_method_idnum(num);
|
k_new_method->set_method_idnum(num);
|
||||||
swap_all_method_annotations(new_num, num, scratch_class, thread);
|
|
||||||
if (thread->has_pending_exception()) {
|
if (thread->has_pending_exception()) {
|
||||||
return JVMTI_ERROR_OUT_OF_MEMORY;
|
return JVMTI_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
@ -1564,9 +1549,9 @@ void VM_RedefineClasses::rewrite_cp_refs_in_method(methodHandle method,
|
|||||||
bcp, cp_index, new_index));
|
bcp, cp_index, new_index));
|
||||||
// Rewriter::rewrite_method() uses put_native_u2() in this
|
// Rewriter::rewrite_method() uses put_native_u2() in this
|
||||||
// situation because it is reusing the constant pool index
|
// situation because it is reusing the constant pool index
|
||||||
// location for a native index into the constantPoolCache.
|
// location for a native index into the ConstantPoolCache.
|
||||||
// Since we are updating the constant pool index prior to
|
// Since we are updating the constant pool index prior to
|
||||||
// verification and constantPoolCache initialization, we
|
// verification and ConstantPoolCache initialization, we
|
||||||
// need to keep the new index in Java byte order.
|
// need to keep the new index in Java byte order.
|
||||||
Bytes::put_Java_u2(p, new_index);
|
Bytes::put_Java_u2(p, new_index);
|
||||||
}
|
}
|
||||||
@ -1888,10 +1873,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_element_value(
|
|||||||
bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations(
|
bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations(
|
||||||
instanceKlassHandle scratch_class, TRAPS) {
|
instanceKlassHandle scratch_class, TRAPS) {
|
||||||
|
|
||||||
Annotations* sca = scratch_class->annotations();
|
Array<AnnotationArray*>* fields_annotations = scratch_class->fields_annotations();
|
||||||
if (sca == NULL) return true;
|
|
||||||
|
|
||||||
Array<AnnotationArray*>* fields_annotations = sca->fields_annotations();
|
|
||||||
|
|
||||||
if (fields_annotations == NULL || fields_annotations->length() == 0) {
|
if (fields_annotations == NULL || fields_annotations->length() == 0) {
|
||||||
// no fields_annotations so nothing to do
|
// no fields_annotations so nothing to do
|
||||||
@ -1926,21 +1908,10 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations(
|
|||||||
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations(
|
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations(
|
||||||
instanceKlassHandle scratch_class, TRAPS) {
|
instanceKlassHandle scratch_class, TRAPS) {
|
||||||
|
|
||||||
Annotations* sca = scratch_class->annotations();
|
for (int i = 0; i < scratch_class->methods()->length(); i++) {
|
||||||
if (sca == NULL) return true;
|
Method* m = scratch_class->methods()->at(i);
|
||||||
|
AnnotationArray* method_annotations = m->constMethod()->method_annotations();
|
||||||
|
|
||||||
Array<AnnotationArray*>* methods_annotations = sca->methods_annotations();
|
|
||||||
|
|
||||||
if (methods_annotations == NULL || methods_annotations->length() == 0) {
|
|
||||||
// no methods_annotations so nothing to do
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
RC_TRACE_WITH_THREAD(0x02000000, THREAD,
|
|
||||||
("methods_annotations length=%d", methods_annotations->length()));
|
|
||||||
|
|
||||||
for (int i = 0; i < methods_annotations->length(); i++) {
|
|
||||||
AnnotationArray* method_annotations = methods_annotations->at(i);
|
|
||||||
if (method_annotations == NULL || method_annotations->length() == 0) {
|
if (method_annotations == NULL || method_annotations->length() == 0) {
|
||||||
// this method does not have any annotations so skip it
|
// this method does not have any annotations so skip it
|
||||||
continue;
|
continue;
|
||||||
@ -1976,24 +1947,9 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations(
|
|||||||
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations(
|
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations(
|
||||||
instanceKlassHandle scratch_class, TRAPS) {
|
instanceKlassHandle scratch_class, TRAPS) {
|
||||||
|
|
||||||
Annotations* sca = scratch_class->annotations();
|
for (int i = 0; i < scratch_class->methods()->length(); i++) {
|
||||||
if (sca == NULL) return true;
|
Method* m = scratch_class->methods()->at(i);
|
||||||
|
AnnotationArray* method_parameter_annotations = m->constMethod()->parameter_annotations();
|
||||||
Array<AnnotationArray*>* methods_parameter_annotations =
|
|
||||||
sca->methods_parameter_annotations();
|
|
||||||
|
|
||||||
if (methods_parameter_annotations == NULL
|
|
||||||
|| methods_parameter_annotations->length() == 0) {
|
|
||||||
// no methods_parameter_annotations so nothing to do
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
RC_TRACE_WITH_THREAD(0x02000000, THREAD,
|
|
||||||
("methods_parameter_annotations length=%d",
|
|
||||||
methods_parameter_annotations->length()));
|
|
||||||
|
|
||||||
for (int i = 0; i < methods_parameter_annotations->length(); i++) {
|
|
||||||
AnnotationArray* method_parameter_annotations = methods_parameter_annotations->at(i);
|
|
||||||
if (method_parameter_annotations == NULL
|
if (method_parameter_annotations == NULL
|
||||||
|| method_parameter_annotations->length() == 0) {
|
|| method_parameter_annotations->length() == 0) {
|
||||||
// this method does not have any parameter annotations so skip it
|
// this method does not have any parameter annotations so skip it
|
||||||
@ -2043,24 +1999,9 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations(
|
|||||||
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_default_annotations(
|
bool VM_RedefineClasses::rewrite_cp_refs_in_methods_default_annotations(
|
||||||
instanceKlassHandle scratch_class, TRAPS) {
|
instanceKlassHandle scratch_class, TRAPS) {
|
||||||
|
|
||||||
Annotations* sca = scratch_class->annotations();
|
for (int i = 0; i < scratch_class->methods()->length(); i++) {
|
||||||
if (sca == NULL) return true;
|
Method* m = scratch_class->methods()->at(i);
|
||||||
|
AnnotationArray* method_default_annotations = m->constMethod()->default_annotations();
|
||||||
Array<AnnotationArray*>* methods_default_annotations =
|
|
||||||
sca->methods_default_annotations();
|
|
||||||
|
|
||||||
if (methods_default_annotations == NULL
|
|
||||||
|| methods_default_annotations->length() == 0) {
|
|
||||||
// no methods_default_annotations so nothing to do
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
RC_TRACE_WITH_THREAD(0x02000000, THREAD,
|
|
||||||
("methods_default_annotations length=%d",
|
|
||||||
methods_default_annotations->length()));
|
|
||||||
|
|
||||||
for (int i = 0; i < methods_default_annotations->length(); i++) {
|
|
||||||
AnnotationArray* method_default_annotations = methods_default_annotations->at(i);
|
|
||||||
if (method_default_annotations == NULL
|
if (method_default_annotations == NULL
|
||||||
|| method_default_annotations->length() == 0) {
|
|| method_default_annotations->length() == 0) {
|
||||||
// this method does not have any default annotations so skip it
|
// this method does not have any default annotations so skip it
|
||||||
@ -3065,6 +3006,31 @@ void VM_RedefineClasses::compute_added_deleted_matching_methods() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VM_RedefineClasses::swap_annotations(instanceKlassHandle the_class,
|
||||||
|
instanceKlassHandle scratch_class) {
|
||||||
|
// Since there is currently no rewriting of type annotations indexes
|
||||||
|
// into the CP, we null out type annotations on scratch_class before
|
||||||
|
// we swap annotations with the_class rather than facing the
|
||||||
|
// possibility of shipping annotations with broken indexes to
|
||||||
|
// Java-land.
|
||||||
|
ClassLoaderData* loader_data = scratch_class->class_loader_data();
|
||||||
|
AnnotationArray* new_class_type_annotations = scratch_class->class_type_annotations();
|
||||||
|
if (new_class_type_annotations != NULL) {
|
||||||
|
MetadataFactory::free_array<u1>(loader_data, new_class_type_annotations);
|
||||||
|
scratch_class->annotations()->set_class_type_annotations(NULL);
|
||||||
|
}
|
||||||
|
Array<AnnotationArray*>* new_field_type_annotations = scratch_class->fields_type_annotations();
|
||||||
|
if (new_field_type_annotations != NULL) {
|
||||||
|
Annotations::free_contents(loader_data, new_field_type_annotations);
|
||||||
|
scratch_class->annotations()->set_fields_type_annotations(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap annotation fields values
|
||||||
|
Annotations* old_annotations = the_class->annotations();
|
||||||
|
the_class->set_annotations(scratch_class->annotations());
|
||||||
|
scratch_class->set_annotations(old_annotations);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Install the redefinition of a class:
|
// Install the redefinition of a class:
|
||||||
// - house keeping (flushing breakpoints and caches, deoptimizing
|
// - house keeping (flushing breakpoints and caches, deoptimizing
|
||||||
@ -3275,23 +3241,7 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
|
|||||||
the_class->set_access_flags(flags);
|
the_class->set_access_flags(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since there is currently no rewriting of type annotations indexes
|
swap_annotations(the_class, scratch_class);
|
||||||
// into the CP, we null out type annotations on scratch_class before
|
|
||||||
// we swap annotations with the_class rather than facing the
|
|
||||||
// possibility of shipping annotations with broken indexes to
|
|
||||||
// Java-land.
|
|
||||||
Annotations* new_annotations = scratch_class->annotations();
|
|
||||||
if (new_annotations != NULL) {
|
|
||||||
Annotations* new_type_annotations = new_annotations->type_annotations();
|
|
||||||
if (new_type_annotations != NULL) {
|
|
||||||
MetadataFactory::free_metadata(scratch_class->class_loader_data(), new_type_annotations);
|
|
||||||
new_annotations->set_type_annotations(NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Swap annotation fields values
|
|
||||||
Annotations* old_annotations = the_class->annotations();
|
|
||||||
the_class->set_annotations(scratch_class->annotations());
|
|
||||||
scratch_class->set_annotations(old_annotations);
|
|
||||||
|
|
||||||
// Replace minor version number of class file
|
// Replace minor version number of class file
|
||||||
u2 old_minor_version = the_class->minor_version();
|
u2 old_minor_version = the_class->minor_version();
|
||||||
@ -3371,7 +3321,6 @@ void VM_RedefineClasses::increment_class_counter(InstanceKlass *ik, TRAPS) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
|
||||||
void VM_RedefineClasses::check_class(Klass* k_oop,
|
void VM_RedefineClasses::check_class(Klass* k_oop,
|
||||||
ClassLoaderData* initiating_loader,
|
ClassLoaderData* initiating_loader,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
@ -3379,82 +3328,110 @@ void VM_RedefineClasses::check_class(Klass* k_oop,
|
|||||||
if (k->oop_is_instance()) {
|
if (k->oop_is_instance()) {
|
||||||
HandleMark hm(THREAD);
|
HandleMark hm(THREAD);
|
||||||
InstanceKlass *ik = (InstanceKlass *) k;
|
InstanceKlass *ik = (InstanceKlass *) k;
|
||||||
|
bool no_old_methods = true; // be optimistic
|
||||||
|
ResourceMark rm(THREAD);
|
||||||
|
|
||||||
if (ik->vtable_length() > 0) {
|
// a vtable should never contain old or obsolete methods
|
||||||
ResourceMark rm(THREAD);
|
if (ik->vtable_length() > 0 &&
|
||||||
if (!ik->vtable()->check_no_old_entries()) {
|
!ik->vtable()->check_no_old_or_obsolete_entries()) {
|
||||||
tty->print_cr("klassVtable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name());
|
if (RC_TRACE_ENABLED(0x00004000)) {
|
||||||
|
RC_TRACE_WITH_THREAD(0x00004000, THREAD,
|
||||||
|
("klassVtable::check_no_old_or_obsolete_entries failure"
|
||||||
|
" -- OLD or OBSOLETE method found -- class: %s",
|
||||||
|
ik->signature_name()));
|
||||||
ik->vtable()->dump_vtable();
|
ik->vtable()->dump_vtable();
|
||||||
assert(false, "OLD method found");
|
|
||||||
}
|
}
|
||||||
|
no_old_methods = false;
|
||||||
}
|
}
|
||||||
if (ik->itable_length() > 0) {
|
|
||||||
ResourceMark rm(THREAD);
|
// an itable should never contain old or obsolete methods
|
||||||
if (!ik->itable()->check_no_old_entries()) {
|
if (ik->itable_length() > 0 &&
|
||||||
tty->print_cr("klassItable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name());
|
!ik->itable()->check_no_old_or_obsolete_entries()) {
|
||||||
assert(false, "OLD method found");
|
if (RC_TRACE_ENABLED(0x00004000)) {
|
||||||
|
RC_TRACE_WITH_THREAD(0x00004000, THREAD,
|
||||||
|
("klassItable::check_no_old_or_obsolete_entries failure"
|
||||||
|
" -- OLD or OBSOLETE method found -- class: %s",
|
||||||
|
ik->signature_name()));
|
||||||
|
ik->itable()->dump_itable();
|
||||||
}
|
}
|
||||||
|
no_old_methods = false;
|
||||||
}
|
}
|
||||||
// Check that the constant pool cache has no deleted entries.
|
|
||||||
|
// the constant pool cache should never contain old or obsolete methods
|
||||||
if (ik->constants() != NULL &&
|
if (ik->constants() != NULL &&
|
||||||
ik->constants()->cache() != NULL &&
|
ik->constants()->cache() != NULL &&
|
||||||
!ik->constants()->cache()->check_no_old_entries()) {
|
!ik->constants()->cache()->check_no_old_or_obsolete_entries()) {
|
||||||
tty->print_cr("klassVtable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name());
|
if (RC_TRACE_ENABLED(0x00004000)) {
|
||||||
assert(false, "OLD method found");
|
RC_TRACE_WITH_THREAD(0x00004000, THREAD,
|
||||||
|
("cp-cache::check_no_old_or_obsolete_entries failure"
|
||||||
|
" -- OLD or OBSOLETE method found -- class: %s",
|
||||||
|
ik->signature_name()));
|
||||||
|
ik->constants()->cache()->dump_cache();
|
||||||
|
}
|
||||||
|
no_old_methods = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!no_old_methods) {
|
||||||
|
if (RC_TRACE_ENABLED(0x00004000)) {
|
||||||
|
dump_methods();
|
||||||
|
} else {
|
||||||
|
tty->print_cr("INFO: use the '-XX:TraceRedefineClasses=16384' option "
|
||||||
|
"to see more info about the following guarantee() failure.");
|
||||||
|
}
|
||||||
|
guarantee(false, "OLD and/or OBSOLETE method(s) found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM_RedefineClasses::dump_methods() {
|
void VM_RedefineClasses::dump_methods() {
|
||||||
int j;
|
int j;
|
||||||
tty->print_cr("_old_methods --");
|
RC_TRACE(0x00004000, ("_old_methods --"));
|
||||||
for (j = 0; j < _old_methods->length(); ++j) {
|
for (j = 0; j < _old_methods->length(); ++j) {
|
||||||
Method* m = _old_methods->at(j);
|
Method* m = _old_methods->at(j);
|
||||||
tty->print("%4d (%5d) ", j, m->vtable_index());
|
RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index()));
|
||||||
m->access_flags().print_on(tty);
|
m->access_flags().print_on(tty);
|
||||||
tty->print(" -- ");
|
tty->print(" -- ");
|
||||||
m->print_name(tty);
|
m->print_name(tty);
|
||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
tty->print_cr("_new_methods --");
|
RC_TRACE(0x00004000, ("_new_methods --"));
|
||||||
for (j = 0; j < _new_methods->length(); ++j) {
|
for (j = 0; j < _new_methods->length(); ++j) {
|
||||||
Method* m = _new_methods->at(j);
|
Method* m = _new_methods->at(j);
|
||||||
tty->print("%4d (%5d) ", j, m->vtable_index());
|
RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index()));
|
||||||
m->access_flags().print_on(tty);
|
m->access_flags().print_on(tty);
|
||||||
tty->print(" -- ");
|
tty->print(" -- ");
|
||||||
m->print_name(tty);
|
m->print_name(tty);
|
||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
tty->print_cr("_matching_(old/new)_methods --");
|
RC_TRACE(0x00004000, ("_matching_(old/new)_methods --"));
|
||||||
for (j = 0; j < _matching_methods_length; ++j) {
|
for (j = 0; j < _matching_methods_length; ++j) {
|
||||||
Method* m = _matching_old_methods[j];
|
Method* m = _matching_old_methods[j];
|
||||||
tty->print("%4d (%5d) ", j, m->vtable_index());
|
RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index()));
|
||||||
m->access_flags().print_on(tty);
|
m->access_flags().print_on(tty);
|
||||||
tty->print(" -- ");
|
tty->print(" -- ");
|
||||||
m->print_name(tty);
|
m->print_name(tty);
|
||||||
tty->cr();
|
tty->cr();
|
||||||
m = _matching_new_methods[j];
|
m = _matching_new_methods[j];
|
||||||
tty->print(" (%5d) ", m->vtable_index());
|
RC_TRACE_NO_CR(0x00004000, (" (%5d) ", m->vtable_index()));
|
||||||
m->access_flags().print_on(tty);
|
m->access_flags().print_on(tty);
|
||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
tty->print_cr("_deleted_methods --");
|
RC_TRACE(0x00004000, ("_deleted_methods --"));
|
||||||
for (j = 0; j < _deleted_methods_length; ++j) {
|
for (j = 0; j < _deleted_methods_length; ++j) {
|
||||||
Method* m = _deleted_methods[j];
|
Method* m = _deleted_methods[j];
|
||||||
tty->print("%4d (%5d) ", j, m->vtable_index());
|
RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index()));
|
||||||
m->access_flags().print_on(tty);
|
m->access_flags().print_on(tty);
|
||||||
tty->print(" -- ");
|
tty->print(" -- ");
|
||||||
m->print_name(tty);
|
m->print_name(tty);
|
||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
tty->print_cr("_added_methods --");
|
RC_TRACE(0x00004000, ("_added_methods --"));
|
||||||
for (j = 0; j < _added_methods_length; ++j) {
|
for (j = 0; j < _added_methods_length; ++j) {
|
||||||
Method* m = _added_methods[j];
|
Method* m = _added_methods[j];
|
||||||
tty->print("%4d (%5d) ", j, m->vtable_index());
|
RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index()));
|
||||||
m->access_flags().print_on(tty);
|
m->access_flags().print_on(tty);
|
||||||
tty->print(" -- ");
|
tty->print(" -- ");
|
||||||
m->print_name(tty);
|
m->print_name(tty);
|
||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
@ -384,11 +384,6 @@ class VM_RedefineClasses: public VM_Operation {
|
|||||||
jvmtiError compare_and_normalize_class_versions(
|
jvmtiError compare_and_normalize_class_versions(
|
||||||
instanceKlassHandle the_class, instanceKlassHandle scratch_class);
|
instanceKlassHandle the_class, instanceKlassHandle scratch_class);
|
||||||
|
|
||||||
// Swap annotations[i] with annotations[j]
|
|
||||||
// Used by compare_and_normalize_class_versions() when normalizing
|
|
||||||
// overloaded methods or changing idnum as when adding or deleting methods.
|
|
||||||
void swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class, TRAPS);
|
|
||||||
|
|
||||||
// Figure out which new methods match old methods in name and signature,
|
// Figure out which new methods match old methods in name and signature,
|
||||||
// which methods have been added, and which are no longer present
|
// which methods have been added, and which are no longer present
|
||||||
void compute_added_deleted_matching_methods();
|
void compute_added_deleted_matching_methods();
|
||||||
@ -417,6 +412,9 @@ class VM_RedefineClasses: public VM_Operation {
|
|||||||
void redefine_single_class(jclass the_jclass,
|
void redefine_single_class(jclass the_jclass,
|
||||||
Klass* scratch_class_oop, TRAPS);
|
Klass* scratch_class_oop, TRAPS);
|
||||||
|
|
||||||
|
void swap_annotations(instanceKlassHandle new_class,
|
||||||
|
instanceKlassHandle scratch_class);
|
||||||
|
|
||||||
// Increment the classRedefinedCount field in the specific InstanceKlass
|
// Increment the classRedefinedCount field in the specific InstanceKlass
|
||||||
// and in all direct and indirect subclasses.
|
// and in all direct and indirect subclasses.
|
||||||
void increment_class_counter(InstanceKlass *ik, TRAPS);
|
void increment_class_counter(InstanceKlass *ik, TRAPS);
|
||||||
@ -468,9 +466,9 @@ class VM_RedefineClasses: public VM_Operation {
|
|||||||
|
|
||||||
void flush_dependent_code(instanceKlassHandle k_h, TRAPS);
|
void flush_dependent_code(instanceKlassHandle k_h, TRAPS);
|
||||||
|
|
||||||
static void check_class(Klass* k_oop, ClassLoaderData* initiating_loader, TRAPS) PRODUCT_RETURN;
|
static void check_class(Klass* k_oop, ClassLoaderData* initiating_loader,
|
||||||
|
TRAPS);
|
||||||
static void dump_methods() PRODUCT_RETURN;
|
static void dump_methods();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VM_RedefineClasses(jint class_count,
|
VM_RedefineClasses(jint class_count,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -54,7 +54,7 @@
|
|||||||
// 0x00000800 | 2048 - previous class breakpoint mgmt
|
// 0x00000800 | 2048 - previous class breakpoint mgmt
|
||||||
// 0x00001000 | 4096 - detect calls to obsolete methods
|
// 0x00001000 | 4096 - detect calls to obsolete methods
|
||||||
// 0x00002000 | 8192 - fail a guarantee() in addition to detection
|
// 0x00002000 | 8192 - fail a guarantee() in addition to detection
|
||||||
// 0x00004000 | 16384 - unused
|
// 0x00004000 | 16384 - detect old/obsolete methods in metadata
|
||||||
// 0x00008000 | 32768 - old/new method matching/add/delete
|
// 0x00008000 | 32768 - old/new method matching/add/delete
|
||||||
// 0x00010000 | 65536 - impl details: CP size info
|
// 0x00010000 | 65536 - impl details: CP size info
|
||||||
// 0x00020000 | 131072 - impl details: CP merge pass info
|
// 0x00020000 | 131072 - impl details: CP merge pass info
|
||||||
@ -82,6 +82,13 @@
|
|||||||
tty->print_cr args; \
|
tty->print_cr args; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define RC_TRACE_NO_CR(level, args) \
|
||||||
|
if ((TraceRedefineClasses & level) != 0) { \
|
||||||
|
ResourceMark rm; \
|
||||||
|
tty->print("RedefineClasses-0x%x: ", level); \
|
||||||
|
tty->print args; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define RC_TRACE_WITH_THREAD(level, thread, args) \
|
#define RC_TRACE_WITH_THREAD(level, thread, args) \
|
||||||
if ((TraceRedefineClasses & level) != 0) { \
|
if ((TraceRedefineClasses & level) != 0) { \
|
||||||
ResourceMark rm(thread); \
|
ResourceMark rm(thread); \
|
||||||
|
@ -27,6 +27,6 @@
|
|||||||
#include "prims/jni.h"
|
#include "prims/jni.h"
|
||||||
#include "prims/whitebox.hpp"
|
#include "prims/whitebox.hpp"
|
||||||
|
|
||||||
WB_METHOD_DECLARE WB_ParseCommandLine(JNIEnv* env, jobject o, jstring args, jobjectArray arguments);
|
WB_METHOD_DECLARE(jobjectArray) WB_ParseCommandLine(JNIEnv* env, jobject o, jstring args, jobjectArray arguments);
|
||||||
|
|
||||||
#endif //SHARE_VM_PRIMS_WBTESTMETHODS_PARSERTESTS_H
|
#endif //SHARE_VM_PRIMS_WBTESTMETHODS_PARSERTESTS_H
|
||||||
|
@ -48,6 +48,8 @@
|
|||||||
#include "services/memTracker.hpp"
|
#include "services/memTracker.hpp"
|
||||||
#endif // INCLUDE_NMT
|
#endif // INCLUDE_NMT
|
||||||
|
|
||||||
|
#include "compiler/compileBroker.hpp"
|
||||||
|
|
||||||
bool WhiteBox::_used = false;
|
bool WhiteBox::_used = false;
|
||||||
|
|
||||||
WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
|
WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
|
||||||
@ -169,6 +171,89 @@ WB_END
|
|||||||
|
|
||||||
#endif // INCLUDE_NMT
|
#endif // INCLUDE_NMT
|
||||||
|
|
||||||
|
static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
|
||||||
|
assert(method != NULL, "method should not be null");
|
||||||
|
ThreadToNativeFromVM ttn(thread);
|
||||||
|
return env->FromReflectedMethod(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o))
|
||||||
|
MutexLockerEx mu(Compile_lock);
|
||||||
|
CodeCache::mark_all_nmethods_for_deoptimization();
|
||||||
|
VM_Deoptimize op;
|
||||||
|
VMThread::execute(&op);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method))
|
||||||
|
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
|
||||||
|
MutexLockerEx mu(Compile_lock);
|
||||||
|
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
|
||||||
|
int result = 0;
|
||||||
|
nmethod* code = mh->code();
|
||||||
|
if (code != NULL) {
|
||||||
|
code->mark_for_deoptimization();
|
||||||
|
++result;
|
||||||
|
}
|
||||||
|
result += CodeCache::mark_for_deoptimization(mh());
|
||||||
|
if (result > 0) {
|
||||||
|
VM_Deoptimize op;
|
||||||
|
VMThread::execute(&op);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method))
|
||||||
|
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
|
||||||
|
MutexLockerEx mu(Compile_lock);
|
||||||
|
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
|
||||||
|
nmethod* code = mh->code();
|
||||||
|
if (code == NULL) {
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
return (code->is_alive() && !code->is_marked_for_deoptimization());
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method))
|
||||||
|
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
|
||||||
|
MutexLockerEx mu(Compile_lock);
|
||||||
|
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
|
||||||
|
return !mh->is_not_compilable();
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
|
||||||
|
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
|
||||||
|
MutexLockerEx mu(Compile_lock);
|
||||||
|
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
|
||||||
|
return mh->queued_for_compilation();
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method))
|
||||||
|
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
|
||||||
|
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
|
||||||
|
nmethod* code = mh->code();
|
||||||
|
return (code != NULL ? code->comp_level() : CompLevel_none);
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method))
|
||||||
|
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
|
||||||
|
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
|
||||||
|
mh->set_not_compilable();
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jboolean, WB_SetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
|
||||||
|
jmethodID jmid = reflected_method_to_jmid(thread, env, method);
|
||||||
|
methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
|
||||||
|
bool result = mh->dont_inline();
|
||||||
|
mh->set_dont_inline(value == JNI_TRUE);
|
||||||
|
return result;
|
||||||
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jint, WB_GetCompileQueuesSize(JNIEnv* env, jobject o))
|
||||||
|
return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ +
|
||||||
|
CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
|
||||||
|
WB_END
|
||||||
|
|
||||||
//Some convenience methods to deal with objects from java
|
//Some convenience methods to deal with objects from java
|
||||||
int WhiteBox::offset_for_field(const char* field_name, oop object,
|
int WhiteBox::offset_for_field(const char* field_name, oop object,
|
||||||
Symbol* signature_symbol) {
|
Symbol* signature_symbol) {
|
||||||
@ -225,9 +310,9 @@ bool WhiteBox::lookup_bool(const char* field_name, oop object) {
|
|||||||
static JNINativeMethod methods[] = {
|
static JNINativeMethod methods[] = {
|
||||||
{CC"getObjectAddress", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress },
|
{CC"getObjectAddress", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress },
|
||||||
{CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize },
|
{CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize },
|
||||||
{CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive },
|
{CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive },
|
||||||
{CC "parseCommandLine",
|
{CC"parseCommandLine",
|
||||||
CC "(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
|
CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
|
||||||
(void*) &WB_ParseCommandLine
|
(void*) &WB_ParseCommandLine
|
||||||
},
|
},
|
||||||
#if INCLUDE_ALL_GCS
|
#if INCLUDE_ALL_GCS
|
||||||
@ -241,6 +326,23 @@ static JNINativeMethod methods[] = {
|
|||||||
{CC"NMTFreeTestMemory", CC"()Z", (void*)&WB_NMTFreeTestMemory },
|
{CC"NMTFreeTestMemory", CC"()Z", (void*)&WB_NMTFreeTestMemory },
|
||||||
{CC"NMTWaitForDataMerge",CC"()Z", (void*)&WB_NMTWaitForDataMerge},
|
{CC"NMTWaitForDataMerge",CC"()Z", (void*)&WB_NMTWaitForDataMerge},
|
||||||
#endif // INCLUDE_NMT
|
#endif // INCLUDE_NMT
|
||||||
|
{CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll },
|
||||||
|
{CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Method;)I",
|
||||||
|
(void*)&WB_DeoptimizeMethod },
|
||||||
|
{CC"isMethodCompiled", CC"(Ljava/lang/reflect/Method;)Z",
|
||||||
|
(void*)&WB_IsMethodCompiled },
|
||||||
|
{CC"isMethodCompilable", CC"(Ljava/lang/reflect/Method;)Z",
|
||||||
|
(void*)&WB_IsMethodCompilable},
|
||||||
|
{CC"isMethodQueuedForCompilation",
|
||||||
|
CC"(Ljava/lang/reflect/Method;)Z", (void*)&WB_IsMethodQueuedForCompilation},
|
||||||
|
{CC"makeMethodNotCompilable",
|
||||||
|
CC"(Ljava/lang/reflect/Method;)V", (void*)&WB_MakeMethodNotCompilable},
|
||||||
|
{CC"setDontInlineMethod",
|
||||||
|
CC"(Ljava/lang/reflect/Method;Z)Z", (void*)&WB_SetDontInlineMethod},
|
||||||
|
{CC"getMethodCompilationLevel",
|
||||||
|
CC"(Ljava/lang/reflect/Method;)I", (void*)&WB_GetMethodCompilationLevel},
|
||||||
|
{CC"getCompileQueuesSize",
|
||||||
|
CC"()I", (void*)&WB_GetCompileQueuesSize},
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef CC
|
#undef CC
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
#define WB_ENTRY(result_type, header) JNI_ENTRY(result_type, header)
|
#define WB_ENTRY(result_type, header) JNI_ENTRY(result_type, header)
|
||||||
#define WB_END JNI_END
|
#define WB_END JNI_END
|
||||||
#define WB_METHOD_DECLARE extern "C" jobjectArray JNICALL
|
#define WB_METHOD_DECLARE(result_type) extern "C" result_type JNICALL
|
||||||
|
|
||||||
class WhiteBox : public AllStatic {
|
class WhiteBox : public AllStatic {
|
||||||
private:
|
private:
|
||||||
|
@ -1086,7 +1086,7 @@ void Arguments::set_tiered_flags() {
|
|||||||
}
|
}
|
||||||
// Increase the code cache size - tiered compiles a lot more.
|
// Increase the code cache size - tiered compiles a lot more.
|
||||||
if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
|
if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
|
||||||
FLAG_SET_DEFAULT(ReservedCodeCacheSize, ReservedCodeCacheSize * 2);
|
FLAG_SET_DEFAULT(ReservedCodeCacheSize, ReservedCodeCacheSize * 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1257,7 +1257,7 @@ void Arguments::set_cms_and_parnew_gc_flags() {
|
|||||||
// prefer minuscule survivor spaces so as not to waste
|
// prefer minuscule survivor spaces so as not to waste
|
||||||
// space for (non-existent) survivors
|
// space for (non-existent) survivors
|
||||||
if (FLAG_IS_DEFAULT(SurvivorRatio) && MaxTenuringThreshold == 0) {
|
if (FLAG_IS_DEFAULT(SurvivorRatio) && MaxTenuringThreshold == 0) {
|
||||||
FLAG_SET_ERGO(intx, SurvivorRatio, MAX2((intx)1024, SurvivorRatio));
|
FLAG_SET_ERGO(uintx, SurvivorRatio, MAX2((uintx)1024, SurvivorRatio));
|
||||||
}
|
}
|
||||||
// If OldPLABSize is set and CMSParPromoteBlocksToClaim is not,
|
// If OldPLABSize is set and CMSParPromoteBlocksToClaim is not,
|
||||||
// set CMSParPromoteBlocksToClaim equal to OldPLABSize.
|
// set CMSParPromoteBlocksToClaim equal to OldPLABSize.
|
||||||
@ -1897,6 +1897,24 @@ bool Arguments::check_vm_args_consistency() {
|
|||||||
// Keeping the heap 100% free is hard ;-) so limit it to 99%.
|
// Keeping the heap 100% free is hard ;-) so limit it to 99%.
|
||||||
MinHeapFreeRatio = MIN2(MinHeapFreeRatio, (uintx) 99);
|
MinHeapFreeRatio = MIN2(MinHeapFreeRatio, (uintx) 99);
|
||||||
|
|
||||||
|
// Min/MaxMetaspaceFreeRatio
|
||||||
|
status = status && verify_percentage(MinMetaspaceFreeRatio, "MinMetaspaceFreeRatio");
|
||||||
|
status = status && verify_percentage(MaxMetaspaceFreeRatio, "MaxMetaspaceFreeRatio");
|
||||||
|
|
||||||
|
if (MinMetaspaceFreeRatio > MaxMetaspaceFreeRatio) {
|
||||||
|
jio_fprintf(defaultStream::error_stream(),
|
||||||
|
"MinMetaspaceFreeRatio (%s" UINTX_FORMAT ") must be less than or "
|
||||||
|
"equal to MaxMetaspaceFreeRatio (%s" UINTX_FORMAT ")\n",
|
||||||
|
FLAG_IS_DEFAULT(MinMetaspaceFreeRatio) ? "Default: " : "",
|
||||||
|
MinMetaspaceFreeRatio,
|
||||||
|
FLAG_IS_DEFAULT(MaxMetaspaceFreeRatio) ? "Default: " : "",
|
||||||
|
MaxMetaspaceFreeRatio);
|
||||||
|
status = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trying to keep 100% free is not practical
|
||||||
|
MinMetaspaceFreeRatio = MIN2(MinMetaspaceFreeRatio, (uintx) 99);
|
||||||
|
|
||||||
if (FullGCALot && FLAG_IS_DEFAULT(MarkSweepAlwaysCompactCount)) {
|
if (FullGCALot && FLAG_IS_DEFAULT(MarkSweepAlwaysCompactCount)) {
|
||||||
MarkSweepAlwaysCompactCount = 1; // Move objects every gc.
|
MarkSweepAlwaysCompactCount = 1; // Move objects every gc.
|
||||||
}
|
}
|
||||||
@ -1904,7 +1922,7 @@ bool Arguments::check_vm_args_consistency() {
|
|||||||
if (UseParallelOldGC && ParallelOldGCSplitALot) {
|
if (UseParallelOldGC && ParallelOldGCSplitALot) {
|
||||||
// Settings to encourage splitting.
|
// Settings to encourage splitting.
|
||||||
if (!FLAG_IS_CMDLINE(NewRatio)) {
|
if (!FLAG_IS_CMDLINE(NewRatio)) {
|
||||||
FLAG_SET_CMDLINE(intx, NewRatio, 2);
|
FLAG_SET_CMDLINE(uintx, NewRatio, 2);
|
||||||
}
|
}
|
||||||
if (!FLAG_IS_CMDLINE(ScavengeBeforeFullGC)) {
|
if (!FLAG_IS_CMDLINE(ScavengeBeforeFullGC)) {
|
||||||
FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
|
FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -67,13 +67,10 @@ AnnotationArray* fieldDescriptor::annotations() const {
|
|||||||
|
|
||||||
AnnotationArray* fieldDescriptor::type_annotations() const {
|
AnnotationArray* fieldDescriptor::type_annotations() const {
|
||||||
InstanceKlass* ik = field_holder();
|
InstanceKlass* ik = field_holder();
|
||||||
Annotations* type_annos = ik->type_annotations();
|
Array<AnnotationArray*>* type_annos = ik->fields_type_annotations();
|
||||||
if (type_annos == NULL)
|
if (type_annos == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
Array<AnnotationArray*>* md = type_annos->fields_annotations();
|
return type_annos->at(index());
|
||||||
if (md == NULL)
|
|
||||||
return NULL;
|
|
||||||
return md->at(index());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constantTag fieldDescriptor::initial_value_tag() const {
|
constantTag fieldDescriptor::initial_value_tag() const {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -69,7 +69,10 @@ bool Flag::is_unlocker() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Flag::is_unlocked() const {
|
bool Flag::is_unlocked() const {
|
||||||
if (strcmp(kind, "{diagnostic}") == 0) {
|
if (strcmp(kind, "{diagnostic}") == 0 ||
|
||||||
|
strcmp(kind, "{C2 diagnostic}") == 0 ||
|
||||||
|
strcmp(kind, "{ARCH diagnostic}") == 0 ||
|
||||||
|
strcmp(kind, "{Shark diagnostic}") == 0) {
|
||||||
if (strcmp(name, "EnableInvokeDynamic") == 0 && UnlockExperimentalVMOptions && !UnlockDiagnosticVMOptions) {
|
if (strcmp(name, "EnableInvokeDynamic") == 0 && UnlockExperimentalVMOptions && !UnlockDiagnosticVMOptions) {
|
||||||
// transitional logic to allow tests to run until they are changed
|
// transitional logic to allow tests to run until they are changed
|
||||||
static int warned;
|
static int warned;
|
||||||
@ -78,7 +81,9 @@ bool Flag::is_unlocked() const {
|
|||||||
}
|
}
|
||||||
return UnlockDiagnosticVMOptions;
|
return UnlockDiagnosticVMOptions;
|
||||||
} else if (strcmp(kind, "{experimental}") == 0 ||
|
} else if (strcmp(kind, "{experimental}") == 0 ||
|
||||||
strcmp(kind, "{C2 experimental}") == 0) {
|
strcmp(kind, "{C2 experimental}") == 0 ||
|
||||||
|
strcmp(kind, "{ARCH experimental}") == 0 ||
|
||||||
|
strcmp(kind, "{Shark experimental}") == 0) {
|
||||||
return UnlockExperimentalVMOptions;
|
return UnlockExperimentalVMOptions;
|
||||||
} else {
|
} else {
|
||||||
return is_unlocked_ext();
|
return is_unlocked_ext();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -1802,7 +1802,7 @@ class CommandLineFlags {
|
|||||||
product(bool, ParallelRefProcBalancingEnabled, true, \
|
product(bool, ParallelRefProcBalancingEnabled, true, \
|
||||||
"Enable balancing of reference processing queues") \
|
"Enable balancing of reference processing queues") \
|
||||||
\
|
\
|
||||||
product(intx, CMSTriggerRatio, 80, \
|
product(uintx, CMSTriggerRatio, 80, \
|
||||||
"Percentage of MinHeapFreeRatio in CMS generation that is " \
|
"Percentage of MinHeapFreeRatio in CMS generation that is " \
|
||||||
"allocated before a CMS collection cycle commences") \
|
"allocated before a CMS collection cycle commences") \
|
||||||
\
|
\
|
||||||
@ -1816,7 +1816,7 @@ class CommandLineFlags {
|
|||||||
\
|
\
|
||||||
product(uintx, InitiatingHeapOccupancyPercent, 45, \
|
product(uintx, InitiatingHeapOccupancyPercent, 45, \
|
||||||
"Percentage of the (entire) heap occupancy to start a " \
|
"Percentage of the (entire) heap occupancy to start a " \
|
||||||
"concurrent GC cycle. It us used by GCs that trigger a " \
|
"concurrent GC cycle. It is used by GCs that trigger a " \
|
||||||
"concurrent GC cycle based on the occupancy of the entire heap, " \
|
"concurrent GC cycle based on the occupancy of the entire heap, " \
|
||||||
"not just one of the generations (e.g., G1). A value of 0 " \
|
"not just one of the generations (e.g., G1). A value of 0 " \
|
||||||
"denotes 'do constant GC cycles'.") \
|
"denotes 'do constant GC cycles'.") \
|
||||||
@ -2977,10 +2977,10 @@ class CommandLineFlags {
|
|||||||
product(uintx, TLABWasteIncrement, 4, \
|
product(uintx, TLABWasteIncrement, 4, \
|
||||||
"Increment allowed waste at slow allocation") \
|
"Increment allowed waste at slow allocation") \
|
||||||
\
|
\
|
||||||
product(intx, SurvivorRatio, 8, \
|
product(uintx, SurvivorRatio, 8, \
|
||||||
"Ratio of eden/survivor space size") \
|
"Ratio of eden/survivor space size") \
|
||||||
\
|
\
|
||||||
product(intx, NewRatio, 2, \
|
product(uintx, NewRatio, 2, \
|
||||||
"Ratio of new/old generation sizes") \
|
"Ratio of new/old generation sizes") \
|
||||||
\
|
\
|
||||||
product_pd(uintx, NewSizeThreadIncrease, \
|
product_pd(uintx, NewSizeThreadIncrease, \
|
||||||
@ -3010,10 +3010,16 @@ class CommandLineFlags {
|
|||||||
"Min change in heap space due to GC (in bytes)") \
|
"Min change in heap space due to GC (in bytes)") \
|
||||||
\
|
\
|
||||||
product(uintx, MinMetaspaceExpansion, ScaleForWordSize(256*K), \
|
product(uintx, MinMetaspaceExpansion, ScaleForWordSize(256*K), \
|
||||||
"Min expansion of permanent heap (in bytes)") \
|
"Min expansion of Metaspace (in bytes)") \
|
||||||
|
\
|
||||||
|
product(uintx, MinMetaspaceFreeRatio, 40, \
|
||||||
|
"Min percentage of Metaspace free after GC to avoid expansion") \
|
||||||
|
\
|
||||||
|
product(uintx, MaxMetaspaceFreeRatio, 70, \
|
||||||
|
"Max percentage of Metaspace free after GC to avoid shrinking") \
|
||||||
\
|
\
|
||||||
product(uintx, MaxMetaspaceExpansion, ScaleForWordSize(4*M), \
|
product(uintx, MaxMetaspaceExpansion, ScaleForWordSize(4*M), \
|
||||||
"Max expansion of permanent heap without full GC (in bytes)") \
|
"Max expansion of Metaspace without full GC (in bytes)") \
|
||||||
\
|
\
|
||||||
product(intx, QueuedAllocationWarningCount, 0, \
|
product(intx, QueuedAllocationWarningCount, 0, \
|
||||||
"Number of times an allocation that queues behind a GC " \
|
"Number of times an allocation that queues behind a GC " \
|
||||||
@ -3031,7 +3037,7 @@ class CommandLineFlags {
|
|||||||
product(uintx, InitialTenuringThreshold, 7, \
|
product(uintx, InitialTenuringThreshold, 7, \
|
||||||
"Initial value for tenuring threshold") \
|
"Initial value for tenuring threshold") \
|
||||||
\
|
\
|
||||||
product(intx, TargetSurvivorRatio, 50, \
|
product(uintx, TargetSurvivorRatio, 50, \
|
||||||
"Desired percentage of survivor space used after scavenge") \
|
"Desired percentage of survivor space used after scavenge") \
|
||||||
\
|
\
|
||||||
product(uintx, MarkSweepDeadRatio, 5, \
|
product(uintx, MarkSweepDeadRatio, 5, \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -366,11 +366,10 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
|
|||||||
volatile_nonstatic_field(Method, _from_compiled_entry, address) \
|
volatile_nonstatic_field(Method, _from_compiled_entry, address) \
|
||||||
volatile_nonstatic_field(Method, _from_interpreted_entry, address) \
|
volatile_nonstatic_field(Method, _from_interpreted_entry, address) \
|
||||||
volatile_nonstatic_field(ConstMethod, _fingerprint, uint64_t) \
|
volatile_nonstatic_field(ConstMethod, _fingerprint, uint64_t) \
|
||||||
nonstatic_field(ConstMethod, _constants, ConstantPool*) \
|
nonstatic_field(ConstMethod, _constants, ConstantPool*) \
|
||||||
nonstatic_field(ConstMethod, _stackmap_data, Array<u1>*) \
|
nonstatic_field(ConstMethod, _stackmap_data, Array<u1>*) \
|
||||||
nonstatic_field(ConstMethod, _constMethod_size, int) \
|
nonstatic_field(ConstMethod, _constMethod_size, int) \
|
||||||
nonstatic_field(ConstMethod, _interpreter_kind, jbyte) \
|
nonstatic_field(ConstMethod, _flags, u2) \
|
||||||
nonstatic_field(ConstMethod, _flags, jbyte) \
|
|
||||||
nonstatic_field(ConstMethod, _code_size, u2) \
|
nonstatic_field(ConstMethod, _code_size, u2) \
|
||||||
nonstatic_field(ConstMethod, _name_index, u2) \
|
nonstatic_field(ConstMethod, _name_index, u2) \
|
||||||
nonstatic_field(ConstMethod, _signature_index, u2) \
|
nonstatic_field(ConstMethod, _signature_index, u2) \
|
||||||
@ -2261,14 +2260,18 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
|
|||||||
declare_constant(Klass::_lh_array_tag_obj_value) \
|
declare_constant(Klass::_lh_array_tag_obj_value) \
|
||||||
\
|
\
|
||||||
/********************************/ \
|
/********************************/ \
|
||||||
/* ConstMethod anon-enum */ \
|
/* ConstMethod anon-enum */ \
|
||||||
/********************************/ \
|
/********************************/ \
|
||||||
\
|
\
|
||||||
declare_constant(ConstMethod::_has_linenumber_table) \
|
declare_constant(ConstMethod::_has_linenumber_table) \
|
||||||
declare_constant(ConstMethod::_has_checked_exceptions) \
|
declare_constant(ConstMethod::_has_checked_exceptions) \
|
||||||
declare_constant(ConstMethod::_has_localvariable_table) \
|
declare_constant(ConstMethod::_has_localvariable_table) \
|
||||||
declare_constant(ConstMethod::_has_exception_table) \
|
declare_constant(ConstMethod::_has_exception_table) \
|
||||||
declare_constant(ConstMethod::_has_generic_signature) \
|
declare_constant(ConstMethod::_has_generic_signature) \
|
||||||
|
declare_constant(ConstMethod::_has_method_annotations) \
|
||||||
|
declare_constant(ConstMethod::_has_parameter_annotations) \
|
||||||
|
declare_constant(ConstMethod::_has_default_annotations) \
|
||||||
|
declare_constant(ConstMethod::_has_type_annotations) \
|
||||||
\
|
\
|
||||||
/*************************************/ \
|
/*************************************/ \
|
||||||
/* InstanceKlass enum */ \
|
/* InstanceKlass enum */ \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -59,7 +59,7 @@ void AccessFlags::atomic_clear_bits(jint bits) {
|
|||||||
} while(f != old_flags);
|
} while(f != old_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#if !defined(PRODUCT) || INCLUDE_JVMTI
|
||||||
|
|
||||||
void AccessFlags::print_on(outputStream* st) const {
|
void AccessFlags::print_on(outputStream* st) const {
|
||||||
if (is_public ()) st->print("public " );
|
if (is_public ()) st->print("public " );
|
||||||
@ -80,7 +80,7 @@ void AccessFlags::print_on(outputStream* st) const {
|
|||||||
if (on_stack ()) st->print("{on_stack} " );
|
if (on_stack ()) st->print("{on_stack} " );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif // !PRODUCT || INCLUDE_JVMTI
|
||||||
|
|
||||||
void accessFlags_init() {
|
void accessFlags_init() {
|
||||||
assert(sizeof(AccessFlags) == sizeof(jint), "just checking size of flags");
|
assert(sizeof(AccessFlags) == sizeof(jint), "just checking size of flags");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2012, 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -239,7 +239,11 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
|
|||||||
inline friend AccessFlags accessFlags_from(jint flags);
|
inline friend AccessFlags accessFlags_from(jint flags);
|
||||||
|
|
||||||
// Printing/debugging
|
// Printing/debugging
|
||||||
|
#if INCLUDE_JVMTI
|
||||||
|
void print_on(outputStream* st) const;
|
||||||
|
#else
|
||||||
void print_on(outputStream* st) const PRODUCT_RETURN;
|
void print_on(outputStream* st) const PRODUCT_RETURN;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
inline AccessFlags accessFlags_from(jint flags) {
|
inline AccessFlags accessFlags_from(jint flags) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -27,13 +27,13 @@
|
|||||||
* @bug 7009359
|
* @bug 7009359
|
||||||
* @summary HS with -XX:+AggressiveOpts optimize new StringBuffer(null) so it does not throw NPE as expected
|
* @summary HS with -XX:+AggressiveOpts optimize new StringBuffer(null) so it does not throw NPE as expected
|
||||||
*
|
*
|
||||||
* @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+OptimizeStringConcat -XX:CompileCommand=exclude,Test7009359,main Test7009359
|
* @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+OptimizeStringConcat -XX:CompileCommand=dontinline,Test7009359,stringmakerBUG Test7009359
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Test7009359 {
|
public class Test7009359 {
|
||||||
public static void main (String[] args) {
|
public static void main (String[] args) {
|
||||||
for(int i = 0; i < 1000000; i++) {
|
for(int i = 0; i < 100000; i++) {
|
||||||
if(!stringmakerBUG(null).equals("NPE")) {
|
if(!stringmakerBUG(null).equals("NPE")) {
|
||||||
System.out.println("StringBuffer(null) does not throw NPE");
|
System.out.println("StringBuffer(null) does not throw NPE");
|
||||||
System.exit(97);
|
System.exit(97);
|
||||||
|
142
hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java
Normal file
142
hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* 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 sun.hotspot.WhiteBox;
|
||||||
|
import sun.management.ManagementFactoryHelper;
|
||||||
|
import com.sun.management.HotSpotDiagnosticMXBean;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @author igor.ignatyev@oracle.com
|
||||||
|
*/
|
||||||
|
public abstract class CompilerWhiteBoxTest {
|
||||||
|
protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
|
||||||
|
protected static final Method METHOD = getMethod("method");
|
||||||
|
protected static final int COMPILE_THRESHOLD
|
||||||
|
= Integer.parseInt(getVMOption("CompileThreshold", "10000"));
|
||||||
|
|
||||||
|
protected static Method getMethod(String name) {
|
||||||
|
try {
|
||||||
|
return CompilerWhiteBoxTest.class.getDeclaredMethod(name);
|
||||||
|
} catch (NoSuchMethodException | SecurityException e) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"exception on getting method " + name, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String getVMOption(String name, String defaultValue) {
|
||||||
|
String result;
|
||||||
|
HotSpotDiagnosticMXBean diagnostic
|
||||||
|
= ManagementFactoryHelper.getDiagnosticMXBean();
|
||||||
|
result = diagnostic.getVMOption(name).getValue();
|
||||||
|
return result == null ? defaultValue : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void runTest() throws RuntimeException {
|
||||||
|
if (ManagementFactoryHelper.getCompilationMXBean() == null) {
|
||||||
|
System.err.println(
|
||||||
|
"Warning: test is not applicable in interpreted mode");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
System.out.println("at test's start:");
|
||||||
|
printInfo(METHOD);
|
||||||
|
try {
|
||||||
|
test();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.printf("on exception '%s':", e.getMessage());
|
||||||
|
printInfo(METHOD);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
System.out.println("at test's end:");
|
||||||
|
printInfo(METHOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void checkNotCompiled(Method method) {
|
||||||
|
if (WHITE_BOX.isMethodCompiled(method)) {
|
||||||
|
throw new RuntimeException(method + " must be not compiled");
|
||||||
|
}
|
||||||
|
if (WHITE_BOX.getMethodCompilationLevel(method) != 0) {
|
||||||
|
throw new RuntimeException(method + " comp_level must be == 0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void checkCompiled(Method method)
|
||||||
|
throws InterruptedException {
|
||||||
|
final long start = System.currentTimeMillis();
|
||||||
|
waitBackgroundCompilation(method);
|
||||||
|
if (WHITE_BOX.isMethodQueuedForCompilation(method)) {
|
||||||
|
System.err.printf("Warning: %s is still in queue after %dms%n",
|
||||||
|
method, System.currentTimeMillis() - start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!WHITE_BOX.isMethodCompiled(method)) {
|
||||||
|
throw new RuntimeException(method + " must be compiled");
|
||||||
|
}
|
||||||
|
if (WHITE_BOX.getMethodCompilationLevel(method) == 0) {
|
||||||
|
throw new RuntimeException(method + " comp_level must be != 0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void waitBackgroundCompilation(Method method)
|
||||||
|
throws InterruptedException {
|
||||||
|
final Object obj = new Object();
|
||||||
|
synchronized (obj) {
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
if (!WHITE_BOX.isMethodQueuedForCompilation(method)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
obj.wait(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void printInfo(Method method) {
|
||||||
|
System.out.printf("%n%s:%n", method);
|
||||||
|
System.out.printf("\tcompilable:\t%b%n",
|
||||||
|
WHITE_BOX.isMethodCompilable(method));
|
||||||
|
System.out.printf("\tcompiled:\t%b%n",
|
||||||
|
WHITE_BOX.isMethodCompiled(method));
|
||||||
|
System.out.printf("\tcomp_level:\t%d%n",
|
||||||
|
WHITE_BOX.getMethodCompilationLevel(method));
|
||||||
|
System.out.printf("\tin_queue:\t%b%n",
|
||||||
|
WHITE_BOX.isMethodQueuedForCompilation(method));
|
||||||
|
System.out.printf("compile_queues_size:\t%d%n%n",
|
||||||
|
WHITE_BOX.getCompileQueuesSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void test() throws Exception;
|
||||||
|
|
||||||
|
protected final int compile() {
|
||||||
|
int result = 0;
|
||||||
|
for (int i = 0; i < COMPILE_THRESHOLD; ++i) {
|
||||||
|
result += method();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected int method() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
}
|
45
hotspot/test/compiler/whitebox/DeoptimizeAllTest.java
Normal file
45
hotspot/test/compiler/whitebox/DeoptimizeAllTest.java
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* 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 DeoptimizeAllTest
|
||||||
|
* @compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI CompilerWhiteBoxTest.java
|
||||||
|
* @compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI DeoptimizeAllTest.java
|
||||||
|
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI DeoptimizeAllTest
|
||||||
|
* @author igor.ignatyev@oracle.com
|
||||||
|
*/
|
||||||
|
public class DeoptimizeAllTest extends CompilerWhiteBoxTest {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
new DeoptimizeAllTest().runTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void test() throws Exception {
|
||||||
|
// to prevent inlining #method into #compile()
|
||||||
|
WHITE_BOX.setDontInlineMethod(METHOD, true);
|
||||||
|
compile();
|
||||||
|
checkCompiled(METHOD);
|
||||||
|
WHITE_BOX.deoptimizeAll();
|
||||||
|
checkNotCompiled(METHOD);
|
||||||
|
}
|
||||||
|
}
|
45
hotspot/test/compiler/whitebox/DeoptimizeMethodTest.java
Normal file
45
hotspot/test/compiler/whitebox/DeoptimizeMethodTest.java
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* 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 DeoptimizeMethodTest
|
||||||
|
* @compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI CompilerWhiteBoxTest.java
|
||||||
|
* @compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI DeoptimizeMethodTest.java
|
||||||
|
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI DeoptimizeMethodTest
|
||||||
|
* @author igor.ignatyev@oracle.com
|
||||||
|
*/
|
||||||
|
public class DeoptimizeMethodTest extends CompilerWhiteBoxTest {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
new DeoptimizeMethodTest().runTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void test() throws Exception {
|
||||||
|
// to prevent inlining #method into #compile()
|
||||||
|
WHITE_BOX.setDontInlineMethod(METHOD, true);
|
||||||
|
compile();
|
||||||
|
checkCompiled(METHOD);
|
||||||
|
WHITE_BOX.deoptimizeMethod(METHOD);
|
||||||
|
checkNotCompiled(METHOD);
|
||||||
|
}
|
||||||
|
}
|
84
hotspot/test/compiler/whitebox/IsMethodCompilableTest.java
Normal file
84
hotspot/test/compiler/whitebox/IsMethodCompilableTest.java
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* 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 IsMethodCompilableTest
|
||||||
|
* @bug 8007270
|
||||||
|
* @compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI CompilerWhiteBoxTest.java
|
||||||
|
* @compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI IsMethodCompilableTest.java
|
||||||
|
* @run main/othervm/timeout=600 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI IsMethodCompilableTest
|
||||||
|
* @author igor.ignatyev@oracle.com
|
||||||
|
*/
|
||||||
|
public class IsMethodCompilableTest extends CompilerWhiteBoxTest {
|
||||||
|
protected static final long PER_METHOD_RECOMPILATION_CUTOFF;
|
||||||
|
|
||||||
|
static {
|
||||||
|
long tmp = Long.parseLong(
|
||||||
|
getVMOption("PerMethodRecompilationCutoff", "400"));
|
||||||
|
if (tmp == -1) {
|
||||||
|
PER_METHOD_RECOMPILATION_CUTOFF = -1 /* Inf */;
|
||||||
|
} else {
|
||||||
|
PER_METHOD_RECOMPILATION_CUTOFF = 1 + (0xFFFFFFFFL & tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
new IsMethodCompilableTest().runTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void test() throws Exception {
|
||||||
|
if (!WHITE_BOX.isMethodCompilable(METHOD)) {
|
||||||
|
throw new RuntimeException(METHOD + " must be compilable");
|
||||||
|
}
|
||||||
|
System.out.println("PerMethodRecompilationCutoff = "
|
||||||
|
+ PER_METHOD_RECOMPILATION_CUTOFF);
|
||||||
|
if (PER_METHOD_RECOMPILATION_CUTOFF == -1) {
|
||||||
|
System.err.println(
|
||||||
|
"Warning: test is not applicable if PerMethodRecompilationCutoff == Inf");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// to prevent inlining #method into #compile()
|
||||||
|
WHITE_BOX.setDontInlineMethod(METHOD, true);
|
||||||
|
boolean madeNotCompilable = false;
|
||||||
|
|
||||||
|
for (long i = 0; i < PER_METHOD_RECOMPILATION_CUTOFF; ++i) {
|
||||||
|
compile();
|
||||||
|
waitBackgroundCompilation(METHOD);
|
||||||
|
WHITE_BOX.deoptimizeMethod(METHOD);
|
||||||
|
if (!WHITE_BOX.isMethodCompilable(METHOD)) {
|
||||||
|
madeNotCompilable = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!madeNotCompilable) {
|
||||||
|
throw new RuntimeException(METHOD + " is still compilable after "
|
||||||
|
+ PER_METHOD_RECOMPILATION_CUTOFF + " iterations");
|
||||||
|
}
|
||||||
|
compile();
|
||||||
|
if (WHITE_BOX.isMethodCompiled(METHOD)) {
|
||||||
|
printInfo(METHOD);
|
||||||
|
throw new RuntimeException(
|
||||||
|
METHOD + " is not compilable but compiled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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 MakeMethodNotCompilableTest
|
||||||
|
* @compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI CompilerWhiteBoxTest.java
|
||||||
|
* @compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI MakeMethodNotCompilableTest.java
|
||||||
|
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI MakeMethodNotCompilableTest
|
||||||
|
* @author igor.ignatyev@oracle.com
|
||||||
|
*/
|
||||||
|
public class MakeMethodNotCompilableTest extends CompilerWhiteBoxTest {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
new MakeMethodNotCompilableTest().runTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void test() throws Exception {
|
||||||
|
if (!WHITE_BOX.isMethodCompilable(METHOD)) {
|
||||||
|
throw new RuntimeException(METHOD + " must be compilable");
|
||||||
|
}
|
||||||
|
WHITE_BOX.makeMethodNotCompilable(METHOD);
|
||||||
|
if (WHITE_BOX.isMethodCompilable(METHOD)) {
|
||||||
|
throw new RuntimeException(METHOD + " must be not compilable");
|
||||||
|
}
|
||||||
|
compile();
|
||||||
|
if (WHITE_BOX.isMethodQueuedForCompilation(METHOD)) {
|
||||||
|
throw new RuntimeException(METHOD + " must not be in queue");
|
||||||
|
}
|
||||||
|
checkNotCompiled(METHOD);
|
||||||
|
if (WHITE_BOX.isMethodCompilable(METHOD)) {
|
||||||
|
throw new RuntimeException(METHOD + " must be not compilable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
59
hotspot/test/compiler/whitebox/SetDontInlineMethodTest.java
Normal file
59
hotspot/test/compiler/whitebox/SetDontInlineMethodTest.java
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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 SetDontInlineMethodTest
|
||||||
|
* @compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI CompilerWhiteBoxTest.java
|
||||||
|
* @compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI SetDontInlineMethodTest.java
|
||||||
|
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SetDontInlineMethodTest
|
||||||
|
* @author igor.ignatyev@oracle.com
|
||||||
|
*/
|
||||||
|
public class SetDontInlineMethodTest extends CompilerWhiteBoxTest {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
new SetDontInlineMethodTest().runTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void test() throws Exception {
|
||||||
|
if (WHITE_BOX.setDontInlineMethod(METHOD, true)) {
|
||||||
|
throw new RuntimeException("on start " + METHOD
|
||||||
|
+ " must be inlineable");
|
||||||
|
}
|
||||||
|
if (!WHITE_BOX.setDontInlineMethod(METHOD, true)) {
|
||||||
|
throw new RuntimeException("after first change to true " + METHOD
|
||||||
|
+ " must be not inlineable");
|
||||||
|
}
|
||||||
|
if (!WHITE_BOX.setDontInlineMethod(METHOD, false)) {
|
||||||
|
throw new RuntimeException("after second change to true " + METHOD
|
||||||
|
+ " must be still not inlineable");
|
||||||
|
}
|
||||||
|
if (WHITE_BOX.setDontInlineMethod(METHOD, false)) {
|
||||||
|
throw new RuntimeException("after first change to false" + METHOD
|
||||||
|
+ " must be inlineable");
|
||||||
|
}
|
||||||
|
if (WHITE_BOX.setDontInlineMethod(METHOD, false)) {
|
||||||
|
throw new RuntimeException("after second change to false " + METHOD
|
||||||
|
+ " must be inlineable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
148
hotspot/test/runtime/8007320/ConstMethodTest.java
Normal file
148
hotspot/test/runtime/8007320/ConstMethodTest.java
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* 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 8007320
|
||||||
|
* @summary Test all optional fields in ConstMethod
|
||||||
|
* @compile -g -parameters ConstMethodTest.java
|
||||||
|
* @run main ConstMethodTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@interface MyAnnotation {
|
||||||
|
public String name();
|
||||||
|
public String value();
|
||||||
|
public String date() default "today";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE_USE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@interface TypeAnno {
|
||||||
|
String value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.TYPE_USE)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@interface TypeAnno2 {
|
||||||
|
String value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.PARAMETER)
|
||||||
|
@interface Named {
|
||||||
|
String value();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@interface ScalarTypesWithDefault {
|
||||||
|
byte b() default 11;
|
||||||
|
short s() default 12;
|
||||||
|
int i() default 13;
|
||||||
|
long l() default 14;
|
||||||
|
char c() default 'V';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some exception class
|
||||||
|
class OkException extends RuntimeException {};
|
||||||
|
|
||||||
|
|
||||||
|
@MyAnnotation(name="someName", value = "Hello World")
|
||||||
|
public class ConstMethodTest {
|
||||||
|
|
||||||
|
private static void check(boolean b) {
|
||||||
|
if (!b)
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
private static void fail(String msg) {
|
||||||
|
System.err.println(msg);
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
private static void equal(Object x, Object y) {
|
||||||
|
if (x == null ? y == null : x.equals(y)) {
|
||||||
|
} else {
|
||||||
|
fail(x + " not equal to " + y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static final String[] parameter_names = {
|
||||||
|
"parameter", "parameter2", "x"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Declare a function with everything in it.
|
||||||
|
@MyAnnotation(name="someName", value="Hello World")
|
||||||
|
static <T> void kitchenSinkFunc(@Named(value="aName") String parameter,
|
||||||
|
@Named("bName") String parameter2,
|
||||||
|
@ScalarTypesWithDefault T x)
|
||||||
|
throws @TypeAnno("RE") @TypeAnno2("RE2") RuntimeException,
|
||||||
|
NullPointerException,
|
||||||
|
@TypeAnno("AIOOBE") ArrayIndexOutOfBoundsException {
|
||||||
|
int i, j, k;
|
||||||
|
try {
|
||||||
|
System.out.println("calling kitchenSinkFunc " + parameter);
|
||||||
|
throw new OkException(); // to see stack trace with line numbers
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void test1() throws Throwable {
|
||||||
|
for (Method m : ConstMethodTest.class.getDeclaredMethods()) {
|
||||||
|
if (m.getName().equals("kitchenSinkFunc")) {
|
||||||
|
Annotation[][] ann = m.getParameterAnnotations();
|
||||||
|
equal(ann.length, 3);
|
||||||
|
Annotation foo = ann[0][0];
|
||||||
|
Annotation bar = ann[1][0];
|
||||||
|
equal(foo.toString(), "@Named(value=aName)");
|
||||||
|
equal(bar.toString(), "@Named(value=bName)");
|
||||||
|
check(foo.equals(foo));
|
||||||
|
check(bar.equals(bar));
|
||||||
|
check(! foo.equals(bar));
|
||||||
|
// method annotations
|
||||||
|
Annotation[] ann2 = m.getAnnotations();
|
||||||
|
equal(ann2.length, 1);
|
||||||
|
Annotation mann = ann2[0];
|
||||||
|
equal(mann.toString(), "@MyAnnotation(date=today, name=someName, value=Hello World)");
|
||||||
|
// Test Method parameter names
|
||||||
|
Parameter[] parameters = m.getParameters();
|
||||||
|
if(parameters == null)
|
||||||
|
throw new Exception("getParameters should never be null");
|
||||||
|
for(int i = 0; i < parameters.length; i++) {
|
||||||
|
Parameter p = parameters[i];
|
||||||
|
equal(parameters[i].getName(), parameter_names[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(java.lang.String[] unused) throws Throwable {
|
||||||
|
// pass 5 so kitchenSinkFunc is instantiated with an int
|
||||||
|
kitchenSinkFunc("parameter", "param2", 5);
|
||||||
|
test1();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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 8006298
|
||||||
|
* @summary Setting an invalid value for a bool argument should result in a useful error message
|
||||||
|
* @library /testlibrary
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.*;
|
||||||
|
|
||||||
|
public class BooleanFlagWithInvalidValue {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||||
|
"-XX:+UseLargePages=8", "-version");
|
||||||
|
|
||||||
|
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||||
|
output.shouldContain("Improperly specified VM option 'UseLargePages=8'");
|
||||||
|
output.shouldHaveExitValue(1);
|
||||||
|
|
||||||
|
pb = ProcessTools.createJavaProcessBuilder(
|
||||||
|
"-XX:-UseLargePages=8", "-version");
|
||||||
|
|
||||||
|
output = new OutputAnalyzer(pb.start());
|
||||||
|
output.shouldContain("Improperly specified VM option 'UseLargePages=8'");
|
||||||
|
output.shouldHaveExitValue(1);
|
||||||
|
}
|
||||||
|
}
|
42
hotspot/test/runtime/CommandLine/FlagWithInvalidValue.java
Normal file
42
hotspot/test/runtime/CommandLine/FlagWithInvalidValue.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* 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 8006298
|
||||||
|
* @summary Setting a flag to an invalid value should print a useful error message
|
||||||
|
* @library /testlibrary
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.*;
|
||||||
|
|
||||||
|
public class FlagWithInvalidValue {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||||
|
"-XX:ObjectAlignmentInBytes=v", "-version");
|
||||||
|
|
||||||
|
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||||
|
output.shouldContain("Improperly specified VM option 'ObjectAlignmentInBytes=v'");
|
||||||
|
output.shouldHaveExitValue(1);
|
||||||
|
}
|
||||||
|
}
|
@ -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 8006298
|
||||||
|
* @summary Using a bool (+/-) prefix on non-bool flag should result in a useful error message
|
||||||
|
* @library /testlibrary
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.*;
|
||||||
|
|
||||||
|
public class NonBooleanFlagWithInvalidBooleanPrefix {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||||
|
"-XX:-ObjectAlignmentInBytes=16", "-version");
|
||||||
|
|
||||||
|
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||||
|
output.shouldContain("Unexpected +/- setting in VM option 'ObjectAlignmentInBytes=16'");
|
||||||
|
output.shouldHaveExitValue(1);
|
||||||
|
|
||||||
|
pb = ProcessTools.createJavaProcessBuilder(
|
||||||
|
"-XX:+ObjectAlignmentInBytes=16", "-version");
|
||||||
|
|
||||||
|
output = new OutputAnalyzer(pb.start());
|
||||||
|
output.shouldContain("Unexpected +/- setting in VM option 'ObjectAlignmentInBytes=16'");
|
||||||
|
output.shouldHaveExitValue(1);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
42
hotspot/test/runtime/CommandLine/UnrecognizedVMOption.java
Normal file
42
hotspot/test/runtime/CommandLine/UnrecognizedVMOption.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* 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 8006298
|
||||||
|
* @summary Using an unrecognized VM option should print the name of the option
|
||||||
|
* @library /testlibrary
|
||||||
|
*/
|
||||||
|
|
||||||
|
import com.oracle.java.testlibrary.*;
|
||||||
|
|
||||||
|
public class UnrecognizedVMOption {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||||
|
"-XX:bogus_option", "-version");
|
||||||
|
|
||||||
|
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||||
|
output.shouldContain("Unrecognized VM option 'bogus_option'");
|
||||||
|
output.shouldHaveExitValue(1);
|
||||||
|
}
|
||||||
|
}
|
@ -198,3 +198,4 @@ bdf2af722a6b54fca47d8c51d17a1b8f41dd7a3e jdk8-b72
|
|||||||
2087e24a4357eceb6432e94918e75fdc706a27d6 jdk8-b74
|
2087e24a4357eceb6432e94918e75fdc706a27d6 jdk8-b74
|
||||||
ff0b73a6b3f6cea644d37d56d746a37743419fa7 jdk8-b75
|
ff0b73a6b3f6cea644d37d56d746a37743419fa7 jdk8-b75
|
||||||
0c08593944d0cd30645f6e1e4946c51ff2b10c8c jdk8-b76
|
0c08593944d0cd30645f6e1e4946c51ff2b10c8c jdk8-b76
|
||||||
|
573e789c187a69a3ae00bffd26eb35c0f4a60636 jdk8-b77
|
||||||
|
@ -198,3 +198,4 @@ c606f644a5d9118c14b5822738bf23c300f14f24 jdk8-b73
|
|||||||
12db3c5a3393b03eeb09ff26f418c4420c21aaab jdk8-b74
|
12db3c5a3393b03eeb09ff26f418c4420c21aaab jdk8-b74
|
||||||
966bf9f3c41a59ff5d86ff4275291c52f329f984 jdk8-b75
|
966bf9f3c41a59ff5d86ff4275291c52f329f984 jdk8-b75
|
||||||
c4853f3f0e89ac60aa5b517f5f224f0f60e08577 jdk8-b76
|
c4853f3f0e89ac60aa5b517f5f224f0f60e08577 jdk8-b76
|
||||||
|
64dfba1bad16433f609f17a42c3c5990367c5c0b jdk8-b77
|
||||||
|
@ -199,3 +199,4 @@ a996b57e554198f4592a5f3c30f2f9f4075e545d jdk8-b70
|
|||||||
4a67fdb752b7d6329d9be9c28d3f9d6cf7eb9a3c jdk8-b75
|
4a67fdb752b7d6329d9be9c28d3f9d6cf7eb9a3c jdk8-b75
|
||||||
3a263052866137b645ab86498a43693ff5c19e69 jdk8-b76
|
3a263052866137b645ab86498a43693ff5c19e69 jdk8-b76
|
||||||
b2fc8e31cecc35b76188e821d4c5dc0e0b74ac24 jdk8-b77
|
b2fc8e31cecc35b76188e821d4c5dc0e0b74ac24 jdk8-b77
|
||||||
|
00b7535d743f83eda763c10b3c9ea19ba4b67f55 jdk8-b78
|
||||||
|
@ -405,3 +405,11 @@ ifdef CROSS_COMPILE_ARCH
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
LIB_LOCATION ?= $(LIBDIR)
|
LIB_LOCATION ?= $(LIBDIR)
|
||||||
|
|
||||||
|
# Adding these macros will make it an error to link to mac APIs newer than OS version 10.7
|
||||||
|
ifeq ($(MACOSX_REQUIRED_VERSION),)
|
||||||
|
MACOSX_REQUIRED_VERSION:=1070
|
||||||
|
endif
|
||||||
|
MACOSX_OS_VERSION_CFLAGS := -DMAC_OS_X_VERSION_MAX_ALLOWED=$(MACOSX_REQUIRED_VERSION) -DMAC_OS_X_VERSION_MIN_REQUIRED=$(MACOSX_REQUIRED_VERSION)
|
||||||
|
OTHER_CFLAGS += $(MACOSX_OS_VERSION_CFLAGS)
|
||||||
|
OTHER_CXXFLAGS += $(MACOSX_OS_VERSION_CFLAGS)
|
||||||
|
@ -1056,6 +1056,7 @@ initial-image-jdk:: initial-image-jdk-setup \
|
|||||||
-processor com.sun.tools.javac.sym.CreateSymbols \
|
-processor com.sun.tools.javac.sym.CreateSymbols \
|
||||||
-Acom.sun.tools.javac.sym.Jar=$(RT_JAR) \
|
-Acom.sun.tools.javac.sym.Jar=$(RT_JAR) \
|
||||||
-Acom.sun.tools.javac.sym.Dest=$(OUTPUTDIR)/symbols/META-INF/sym/rt.jar \
|
-Acom.sun.tools.javac.sym.Dest=$(OUTPUTDIR)/symbols/META-INF/sym/rt.jar \
|
||||||
|
-Acom.sun.tools.javac.sym.Profiles=$(JDK_TOPDIR)/makefiles/profile-rtjar-includes.txt \
|
||||||
$(CORE_PKGS) $(NON_CORE_PKGS) $(EXCLUDE_PROPWARN_PKGS) $(EXPORTED_PRIVATE_PKGS)
|
$(CORE_PKGS) $(NON_CORE_PKGS) $(EXCLUDE_PROPWARN_PKGS) $(EXPORTED_PRIVATE_PKGS)
|
||||||
$(BOOT_JAR_CMD) $(CREATE_JAR_OPTS_NOMANIFEST) $(LIBDIR)/ct.sym \
|
$(BOOT_JAR_CMD) $(CREATE_JAR_OPTS_NOMANIFEST) $(LIBDIR)/ct.sym \
|
||||||
-C $(OUTPUTDIR)/symbols META-INF $(BOOT_JAR_JFLAGS)
|
-C $(OUTPUTDIR)/symbols META-INF $(BOOT_JAR_JFLAGS)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 1997, 2012, 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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
@ -208,6 +208,7 @@ COMMON_JAVADOCFLAGS = \
|
|||||||
-use \
|
-use \
|
||||||
-keywords \
|
-keywords \
|
||||||
-Xdoclint:none \
|
-Xdoclint:none \
|
||||||
|
-Xprofilespath $(JDK_TOPDIR)/makefiles/profile-rtjar-includes.txt \
|
||||||
$(ADDITIONAL_JAVADOCFLAGS)
|
$(ADDITIONAL_JAVADOCFLAGS)
|
||||||
|
|
||||||
ifdef OPENJDK
|
ifdef OPENJDK
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
|
# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
@ -40,6 +40,7 @@ $(GENSRCDIR)/sun/misc/Version.java: \
|
|||||||
-e 's/@@java_version@@/$(RELEASE)/g' \
|
-e 's/@@java_version@@/$(RELEASE)/g' \
|
||||||
-e 's/@@java_runtime_version@@/$(FULL_VERSION)/g' \
|
-e 's/@@java_runtime_version@@/$(FULL_VERSION)/g' \
|
||||||
-e 's/@@java_runtime_name@@/$(RUNTIME_NAME)/g' \
|
-e 's/@@java_runtime_name@@/$(RUNTIME_NAME)/g' \
|
||||||
|
-e 's/@@java_profile_name@@//g' \
|
||||||
$< > $@.temp
|
$< > $@.temp
|
||||||
@$(MV) $@.temp $@
|
@$(MV) $@.temp $@
|
||||||
|
|
||||||
|
115
jdk/make/tools/src/build/tools/classfile/RemoveMethods.java
Normal file
115
jdk/make/tools/src/build/tools/classfile/RemoveMethods.java
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package build.tools.classfile;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import com.sun.tools.classfile.AccessFlags;
|
||||||
|
import com.sun.tools.classfile.Attributes;
|
||||||
|
import com.sun.tools.classfile.ClassFile;
|
||||||
|
import com.sun.tools.classfile.ClassWriter;
|
||||||
|
import com.sun.tools.classfile.ConstantPool;
|
||||||
|
import com.sun.tools.classfile.Field;
|
||||||
|
import com.sun.tools.classfile.Method;
|
||||||
|
|
||||||
|
public class RemoveMethods {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
if (args.length < 2) {
|
||||||
|
System.err.println("Usage: java RemoveMethods classfile output [method...]");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// class file to read
|
||||||
|
Path input = Paths.get(args[0]);
|
||||||
|
|
||||||
|
// class file to write, if directory then use the name of the input
|
||||||
|
Path output = Paths.get(args[1]);
|
||||||
|
if (Files.isDirectory(output))
|
||||||
|
output = output.resolve(input.getFileName());
|
||||||
|
|
||||||
|
// the methods to remove
|
||||||
|
Set<String> methodsToRemove = new HashSet<>();
|
||||||
|
int i = 2;
|
||||||
|
while (i < args.length)
|
||||||
|
methodsToRemove.add(args[i++]);
|
||||||
|
|
||||||
|
// read class file
|
||||||
|
ClassFile cf;
|
||||||
|
try (InputStream in = Files.newInputStream(input)) {
|
||||||
|
cf = ClassFile.read(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int magic = cf.magic;
|
||||||
|
final int major_version = cf.major_version;
|
||||||
|
final int minor_version = cf.minor_version;
|
||||||
|
final ConstantPool cp = cf.constant_pool;
|
||||||
|
final AccessFlags access_flags = cf.access_flags;
|
||||||
|
final int this_class = cf.this_class;
|
||||||
|
final int super_class = cf.super_class;
|
||||||
|
final int[] interfaces = cf.interfaces;
|
||||||
|
final Field[] fields = cf.fields;
|
||||||
|
final Attributes class_attrs = cf.attributes;
|
||||||
|
|
||||||
|
// remove the requested methods, no signature check at this time
|
||||||
|
Method[] methods = cf.methods;
|
||||||
|
i = 0;
|
||||||
|
while (i < methods.length) {
|
||||||
|
Method m = methods[i];
|
||||||
|
String name = m.getName(cp);
|
||||||
|
if (methodsToRemove.contains(name)) {
|
||||||
|
int len = methods.length;
|
||||||
|
Method[] newMethods = new Method[len-1];
|
||||||
|
if (i > 0)
|
||||||
|
System.arraycopy(methods, 0, newMethods, 0, i);
|
||||||
|
int after = methods.length - i - 1;
|
||||||
|
if (after > 0)
|
||||||
|
System.arraycopy(methods, i+1, newMethods, i, after);
|
||||||
|
methods = newMethods;
|
||||||
|
String paramTypes = m.descriptor.getParameterTypes(cp);
|
||||||
|
System.out.format("Removed method %s%s from %s%n",
|
||||||
|
name, paramTypes, cf.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TBD, prune constant pool of entries that are no longer referenced
|
||||||
|
|
||||||
|
// re-write class file
|
||||||
|
cf = new ClassFile(magic, minor_version, major_version, cp, access_flags,
|
||||||
|
this_class, super_class, interfaces, fields, methods, class_attrs);
|
||||||
|
try (OutputStream out = Files.newOutputStream(output)) {
|
||||||
|
new ClassWriter().write(cf, out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user